Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit9394d62

Browse files
committed
I have been working with user defined types and user defined c
functions. One problem that I have encountered with the functionmanager is that it does not allow the user to define type conversionfunctions that convert between user types. For instance if mytype1,mytype2, and mytype3 are three Postgresql user types, and if I wish todefine Postgresql conversion functions likeI run into problems, because the Postgresql dynamic loader would lookfor a single link symbol, mytype3, for both pieces of object code. IfI just change the name of one of the Postgresql functions (to make thesymbols distinct), the automatic type conversion that Postgresql uses,for example, when matching operators to arguments no longer finds thetype conversion function.The solution that I propose, and have implemented in the attatchedpatch extends the CREATE FUNCTION syntax as follows. In the first caseabove I use the link symbol mytype2_to_mytype3 for the link objectthat implements the first conversion function, and define thePostgresql operator with the following syntaxThe patch includes changes to the parser to include the alteredsyntax, changes to the ProcedureStmt node in nodes/parsenodes.h,changes to commands/define.c to handle the extra information in the ASclause, and changes to utils/fmgr/dfmgr.c that alter the way that thedynamic loader figures out what link symbol to use. I store thestring for the link symbol in the prosrc text attribute of the pg_proctable which is currently unused in rows that reference dynamicallyloadedfunctions.Bernie Frankpitt
1 parent63a8508 commit9394d62

File tree

9 files changed

+223
-83
lines changed

9 files changed

+223
-83
lines changed

‎doc/src/sgml/ref/create_function.sgml

Lines changed: 70 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!--
2-
$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_function.sgml,v 1.9 1999/07/22 15:09:07 thomas Exp $
2+
$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_function.sgml,v 1.10 1999/09/28 04:34:39 momjian Exp $
33
Postgres documentation
44
-->
55

@@ -25,8 +25,14 @@ Postgres documentation
2525
<synopsis>
2626
CREATE FUNCTION <replaceable class="parameter">name</replaceable> ( [ <replaceable class="parameter">ftype</replaceable> [, ...] ] )
2727
RETURNS <replaceable class="parameter">rtype</replaceable>
28-
AS <replaceable class="parameter">definition</replaceable>
28+
AS <replaceable class="parameter">definition</replaceable>
2929
LANGUAGE '<replaceable class="parameter">langname</replaceable>'
30+
31+
32+
CREATE FUNCTION <replaceable class="parameter">name</replaceable> ( [ <replaceable class="parameter">ftype</replaceable> [, ...] ] )
33+
RETURNS <replaceable class="parameter">rtype</replaceable>
34+
AS <replaceable class="parameter">obj_file</replaceable> , <replaceable class="parameter">link_symbol</replaceable>
35+
LANGUAGE 'c'
3036
</synopsis>
3137

3238
<refsect2 id="R2-SQL-CREATEFUNCTION-1">
@@ -83,6 +89,22 @@ CREATE FUNCTION <replaceable class="parameter">name</replaceable> ( [ <replaceab
8389
</para>
8490
</listitem>
8591
</varlistentry>
92+
<varlistentry>
93+
<term><replaceable class="parameter">obj_file</replaceable> , <replaceable class="parameter">link_symbol</replaceable></term>
94+
<listitem>
95+
<para>
96+
This form of the <command>AS</command> clause is used for
97+
dynamically-linked, C language functions when the function name in
98+
the C language source code is not the same as the name of the SQL
99+
function. The string <replaceable
100+
class="parameter">obj_file</replaceable> is the name of the file
101+
containing the dynamically loadable object, and <replaceable
102+
class="parameter">link_symbol</replaceable>, is the object's link
103+
symbol which is the same as the name of the function in the C
104+
language source code.
105+
</para>
106+
</listitem>
107+
</varlistentry>
86108
<varlistentry>
87109
<term><replaceable class="parameter">langname</replaceable></term>
88110
<listitem>
@@ -165,10 +187,10 @@ CREATE
165187
<para>
166188
<productname>Postgres</productname> allows function "overloading";
167189
that is, the same name can be used for several different functions
168-
so long as they have distinct argument types. This facility must be
169-
used with caution for <literal>internal</literal>
170-
andC-language functions, however.
171-
</para>
190+
so long as they have distinct argument types. This facility must
191+
beused with caution for <literal>internal</literal> and
192+
C-language functions, however.
193+
</para>
172194

173195
<para>
174196
Two <literal>internal</literal>
@@ -181,18 +203,15 @@ CREATE
181203
</para>
182204

183205
<para>
184-
For dynamically-loaded C functions, the SQL name of the function must
185-
be the same as the C function name, because the AS clause is used to
186-
give the path name of the object file containing the C code. In this
187-
situation it is best not to try to overload SQL function names. It
188-
might work to load a C function that has the same C name as an internal
189-
function or another dynamically-loaded function --- or it might not.
190-
On some platforms the dynamic loader may botch the load in interesting
191-
ways if there is a conflict of C function names. So, even if it works
192-
for you today, you might regret overloading names later when you try
193-
to run the code somewhere else.
206+
When overloading SQL functions with C-language functions, give
207+
each C-language instance of the function a distinct name, and use
208+
the alternative form of the <command>AS</command> clause in the
209+
<command>CREATE FUNCTION</command> syntax to ensure that
210+
overloaded SQL functions names are resolved to the correct
211+
dynamically linked objects.
194212
</para>
195213

214+
196215
<para>
197216
A C function cannot return a set of values.
198217
</para>
@@ -227,7 +246,6 @@ SELECT one() AS answer;
227246
is correct. It is intended for use in a CHECK contraint.
228247
</para>
229248
<programlisting>
230-
<userinput>
231249
CREATE FUNCTION ean_checkdigit(bpchar, bpchar) RETURNS bool
232250
AS '/usr1/proj/bray/sql/funcs.so' LANGUAGE 'c';
233251

@@ -238,8 +256,41 @@ CREATE TABLE product (
238256
eancode char(6) CHECK (eancode ~ '[0-9]{6}'),
239257
CONSTRAINT ean CHECK (ean_checkdigit(eanprefix, eancode))
240258
);
241-
</userinput>
242259
</programlisting>
260+
261+
262+
<para>
263+
This example creates a function that does type conversion between the
264+
user defined type complex, and the internal type point. The
265+
function is implemented by a dynamically loaded object that was
266+
compiled from C source. For <productname>Postgres</productname> to
267+
find a type conversion function automatically, the sql function has
268+
to have the same name as the return type, and overloading is
269+
unavoidable. The function name is overloaded by using the second
270+
form of the <command>AS</command> clause in the SQL definition
271+
</para>
272+
<programlisting>
273+
CREATE FUNCTION point(complex) RETURNS point
274+
AS '/home/bernie/pgsql/lib/complex.so', 'complex_to_point'
275+
LANGUAGE 'c';
276+
</programlisting>
277+
<para>
278+
The C decalaration of the function is:
279+
</para>
280+
<programlisting>
281+
Point * complex_to_point (Complex *z)
282+
{
283+
Point *p;
284+
285+
p = (Point *) palloc(sizeof(Point));
286+
p->x = z->x;
287+
p->y = z->y;
288+
289+
return p;
290+
}
291+
</programlisting>
292+
293+
243294
</refsect1>
244295

245296
<refsect1 id="R1-SQL-CREATEFUNCTION-4">
@@ -283,8 +334,7 @@ CREATE TABLE product (
283334
SQL/PSM <command>CREATE FUNCTION</command> has the following syntax:
284335
<synopsis>
285336
CREATE FUNCTION <replaceable class="parameter">name</replaceable>
286-
( [ [ IN | OUT | INOUT ] <replaceable class="parameter">eter</replaceable>eable>eable> <replaceable
287-
class="parameter">type</replaceable> [, ...] ] )
337+
( [ [ IN | OUT | INOUT ] <replaceable class="parameter">type</replaceable> [, ...] ] )
288338
RETURNS <replaceable class="parameter">rtype</replaceable>
289339
LANGUAGE '<replaceable class="parameter">langname</replaceable>'
290340
ESPECIFIC <replaceable class="parameter">routine</replaceable>

‎doc/src/sgml/xfunc.sgml

Lines changed: 41 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -357,25 +357,43 @@ WARN::function declared to return type EMP does not retrieve (EMP.*)
357357
<title>Compiled (C) Language Functions</title>
358358

359359
<para>
360-
Functions written in C can be defined to Postgres, which will dynamically
361-
load them into its address space. The AS
362-
clause gives the full path name of the object file that contains the
363-
function. This file is loaded either using
364-
load(l)
365-
or automatically the first time the function is necessary for
366-
execution. Repeated execution of a function will cause negligible
367-
additional overhead, as the function will remain in a main memory
368-
cache.
360+
Functions written in C can be compiled into dynamically loadable
361+
objects, and used to implement user-defined SQL functions. The
362+
first time the user defined function is called inside the backend,
363+
the dynamic loader loads the function's object code into memory,
364+
and links the function with the running
365+
<productname>Postgres</productname> executable. The SQL syntax
366+
for the <xref linkend="sql-createfunction-title"
367+
endterm="sql-createfunction-title"> command links the SQL function
368+
to the C source function in one of two ways. If the SQL function
369+
has the same name as the C source function the first form of the
370+
statement is used. The string argument in the AS clause is the
371+
full pathname of the file that contains the dynamically loadable
372+
compiled object. If the name of C function is different from the
373+
name of the SQL function, then the second form is used. In this
374+
form the AS clause takes two string arguments, the first is the
375+
full pathname of the dynamically loadable object file, and the
376+
second is the link symbol that the dynamic loader should search
377+
for. This link symbol is just the function name in the C source
378+
code.
379+
380+
After it is used for the first time, a dynamically loaded, user
381+
function is retained in memory, and future calls to the function
382+
only incur the small overhead of a symbol table lookup.
369383
</para>
370384

371385
<para>
372-
The string which specifies the object file (the string in the AS clause)
373-
should be the <emphasis>full path</emphasis>
374-
of the object code file for the function, bracketed by quotation
375-
marks. (<productname>Postgres</productname> will not compile a
376-
function automatically; it must
377-
be compiled before it is used in a CREATE FUNCTION
378-
command. See below for additional information.)
386+
The string which specifies the object file (the string in the AS
387+
clause) should be the <emphasis>full path</emphasis> of the object
388+
code file for the function, bracketed by quotation marks. If a
389+
link symbol is used in the AS clause, the link symbol should also be
390+
bracketed by single quotation marks, and should be exactly the
391+
same as the name of function in the C source code. On UNIX systems
392+
the command <command>nm</command> will print all of the link
393+
symbols in a dynamically loadable object.
394+
(<productname>Postgres</productname> will not compile a function
395+
automatically; it must be compiled before it is used in a CREATE
396+
FUNCTION command. See below for additional information.)
379397
</para>
380398

381399
<sect2>
@@ -960,10 +978,13 @@ memmove(destination-&gt;data, buffer, 40);
960978
<title>Name Space Conflicts</title>
961979

962980
<para>
963-
As of <productname>Postgres</productname> v6.5,
964-
<command>CREATE FUNCTION</command> can decouple a C language
965-
function name from the name of the entry point. This is now the
966-
preferred technique to accomplish function overloading.
981+
As of <productname>Postgres</productname> v6.6, the alternative
982+
form of the AS clause for the SQL <command>CREATE
983+
FUNCTION</command> command described in <xref
984+
linkend="sql-createfunction-title" endterm="sql-createfunction-title">
985+
decouples the SQL function name from the function name in the C
986+
source code. This is now the preferred technique to accomplish
987+
function overloading.
967988
</para>
968989

969990
<sect3>

‎src/backend/commands/define.c

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*
1010
*
1111
* IDENTIFICATION
12-
* $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.34 1999/07/17 20:16:52 momjian Exp $
12+
* $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.35 1999/09/28 04:34:40 momjian Exp $
1313
*
1414
* DESCRIPTION
1515
* The "DefineFoo" routines take the parse tree and pick out the
@@ -178,23 +178,45 @@ compute_full_attributes(const List *parameters, int32 *byte_pct_p,
178178
}
179179

180180

181+
/*
182+
* For a dynamically linked C language object, the form of the clause is
183+
*
184+
* AS <object file name> [, <link symbol name> ]
185+
*
186+
* In all other cases
187+
*
188+
* AS <object reference, or sql code>
189+
*
190+
*/
181191

182192
staticvoid
183-
interpret_AS_clause(constchar*languageName,constchar*as,
193+
interpret_AS_clause(constchar*languageName,constList*as,
184194
char**prosrc_str_p,char**probin_str_p)
185195
{
196+
Assert(as!=NIL);
186197

187198
if (strcmp(languageName,"C")==0)
188199
{
189-
/* For "C" language, store the given string in probin */
190-
*prosrc_str_p="-";
191-
*probin_str_p= (char*)as;
200+
201+
/*
202+
* For "C" language, store the file name in probin and, when
203+
* given, the link symbol name in prosrc.
204+
*/
205+
*probin_str_p=strVal(lfirst(as));
206+
if (lnext(as)==NULL)
207+
*prosrc_str_p="-";
208+
else
209+
*prosrc_str_p=strVal(lsecond(as));
192210
}
193211
else
194212
{
195-
/* Everything else wants the given string in prosrc */
196-
*prosrc_str_p=(char*)as;
213+
/* Everything else wants the given string in prosrc. */
214+
*prosrc_str_p=strVal(lfirst(as));
197215
*probin_str_p="-";
216+
217+
if (lnext(as)!=NULL)
218+
elog(ERROR,"CREATE FUNCTION: parse error in 'AS %s, %s'.",
219+
strVal(lfirst(as)),strVal(lsecond(as)));
198220
}
199221
}
200222

‎src/backend/parser/gram.y

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
*
1111
*
1212
* IDENTIFICATION
13-
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.99 1999/09/23 17:02:46 momjian Exp $
13+
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.100 1999/09/28 04:34:44 momjian Exp $
1414
*
1515
* HISTORY
1616
* AUTHORDATEMAJOR EVENT
@@ -163,7 +163,7 @@ Oidparam_type(int t); /* used in parse_expr.c */
163163
%type <list>stmtblock, stmtmulti,
164164
result, relation_name_list, OptTableElementList,
165165
OptInherit, definition,
166-
opt_with, func_args, func_args_list,
166+
opt_with, func_args, func_args_list, func_as,
167167
oper_argtypes, RuleActionList, RuleActionBlock, RuleActionMulti,
168168
opt_column_list, columnList, opt_va_list, va_list,
169169
sort_clause, sortby_list, index_params, index_list, name_list,
@@ -1923,7 +1923,7 @@ RecipeStmt: EXECUTE RECIPE recipe_name
19231923
*****************************************************************************/
19241924

19251925
ProcedureStmt:CREATE FUNCTION func_name func_args
1926-
RETURNS func_return opt_with ASSconst LANGUAGE Sconst
1926+
RETURNS func_return opt_with ASfunc_as LANGUAGE Sconst
19271927
{
19281928
ProcedureStmt *n = makeNode(ProcedureStmt);
19291929
n->funcname = $3;
@@ -1949,6 +1949,12 @@ func_args_list: TypeId
19491949
{$$ = lappend($1,makeString($3)); }
19501950
;
19511951

1952+
func_as: Sconst
1953+
{ $$ = lcons(makeString($1),NIL); }
1954+
| Sconst ',' Sconst
1955+
{ $$ = lappend(lcons(makeString($1),NIL), makeString($3)); }
1956+
;
1957+
19521958
func_return: set_opt TypeId
19531959
{
19541960
TypeName *n = makeNode(TypeName);

‎src/backend/utils/fmgr/dfmgr.c

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/utils/fmgr/dfmgr.c,v 1.32 1999/09/18 19:08:01 tgl Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/utils/fmgr/dfmgr.c,v 1.33 1999/09/28 04:34:46 momjian Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -42,8 +42,11 @@ fmgr_dynamic(Oid procedureId, int *pronargs)
4242
HeapTupleprocedureTuple;
4343
Form_pg_procprocedureStruct;
4444
char*proname,
45-
*probinstring;
45+
*probinstring,
46+
*prosrcstring,
47+
*linksymbol;
4648
Datumprobinattr;
49+
Datumprosrcattr;
4750
func_ptruser_fn;
4851
Relationrel;
4952
boolisnull;
@@ -90,7 +93,32 @@ fmgr_dynamic(Oid procedureId, int *pronargs)
9093

9194
heap_close(rel,AccessShareLock);
9295

93-
user_fn=handle_load(probinstring,proname);
96+
prosrcattr=heap_getattr(procedureTuple,
97+
Anum_pg_proc_prosrc,
98+
RelationGetDescr(rel),&isnull);
99+
100+
if (isnull)
101+
{/* Use the proname for the link symbol */
102+
linksymbol=proname;
103+
}
104+
elseif (!PointerIsValid(prosrcattr))
105+
{/* pg_proc must be messed up! */
106+
heap_close(rel);
107+
elog(ERROR,"fmgr: Could not extract prosrc for %u from %s",
108+
procedureId,ProcedureRelationName);
109+
return (func_ptr)NULL;
110+
}
111+
else
112+
{/* The text in prosrcattr is either "-" or
113+
* a link symbol */
114+
prosrcstring=textout((structvarlena*)prosrcattr);
115+
if (strcmp(prosrcstring,"-")==0)
116+
linksymbol=proname;
117+
else
118+
linksymbol=prosrcstring;
119+
}
120+
121+
user_fn=handle_load(probinstring,linksymbol);
94122

95123
pfree(probinstring);
96124

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp