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

Commitd60f10b

Browse files
committed
Add optional "validator" function to languages that can validate the
function body (and other properties) as a function in the languageis created. This generalizes ad hoc code that already existed forthe built-in languages.The validation now happens after the pg_proc tuple of the new functionis created, so it is possible to define recursive SQL functions.Add some regression test cases that cover bogus function definitionattempts.
1 parentdf9c8e1 commitd60f10b

File tree

18 files changed

+339
-102
lines changed

18 files changed

+339
-102
lines changed

‎doc/src/sgml/ref/create_language.sgml

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!--
2-
$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_language.sgml,v 1.23 2002/05/18 15:44:47 petere Exp $
2+
$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_language.sgml,v 1.24 2002/05/22 17:20:58 petere Exp $
33
PostgreSQL documentation
44
-->
55

@@ -17,7 +17,7 @@ PostgreSQL documentation
1717
<refsynopsisdiv>
1818
<synopsis>
1919
CREATE [ TRUSTED ] [ PROCEDURAL ] LANGUAGE <replaceable class="parameter">langname</replaceable>
20-
HANDLER <replaceable class="parameter">call_handler</replaceable>
20+
HANDLER <replaceable class="parameter">call_handler</replaceable> [ VALIDATOR <replaceable>valfunction</replaceable> ]
2121
</synopsis>
2222
</refsynopsisdiv>
2323

@@ -113,6 +113,32 @@ CREATE [ TRUSTED ] [ PROCEDURAL ] LANGUAGE <replaceable class="parameter">langna
113113
</para>
114114
</listitem>
115115
</varlistentry>
116+
117+
<varlistentry>
118+
<term><literal>VALIDATOR</literal> <replaceable class="parameter">valfunction</replaceable></term>
119+
120+
<listitem>
121+
<para>
122+
<replaceable class="parameter">valfunction</replaceable> is the
123+
name of a previously registered function that will be called
124+
when a new function in the language is created, to validate the
125+
new function. The validator function must take one argument of
126+
type <type>oid</type>, which will be the OID of the
127+
to-be-created function, and can have any return type. If no
128+
validator function is specified, then a new function will not
129+
be checked when it is created.
130+
</para>
131+
132+
<para>
133+
A validator function would typically inspect the function body
134+
for syntactical correctness, but it can also look at other
135+
properties of the function, for example if the language cannot
136+
handle certain argument types. To signal an error, the
137+
validator function should use the <function>elog()</function>
138+
function. The return value of the function is ignored.
139+
</para>
140+
</listitem>
141+
</varlistentry>
116142
</variablelist>
117143
</refsect1>
118144

‎doc/src/sgml/release.sgml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!--
2-
$Header: /cvsroot/pgsql/doc/src/sgml/release.sgml,v 1.137 2002/05/18 13:47:59 petere Exp $
2+
$Header: /cvsroot/pgsql/doc/src/sgml/release.sgml,v 1.138 2002/05/22 17:20:58 petere Exp $
33
-->
44

55
<appendix id="release">
@@ -24,6 +24,8 @@ CDATA means the content is "SGML-free", so you can write without
2424
worries about funny characters.
2525
-->
2626
<literallayout><![CDATA[
27+
Recursive SQL functions can be defined
28+
User-defined procedural languages can register a validator function to check new functions as they are created
2729
Functions can be executed with the privileges of the owner
2830
Syntax of CREATE FUNCTION has been extended to resemble SQL99
2931
Effects of SET within a transaction block now roll back if transaction aborts
@@ -72,7 +74,7 @@ Database and user-specific session defaults for run-time configuration variables
7274
<title>Changes</title>
7375

7476
<para>
75-
<programlisting>
77+
<literallayout>
7678
Ensure that sequence counters do not go backwards after a crash (Tom)
7779
Fix pgaccess kanji-coversion key binding (Tatsuo)
7880
Optimizer improvements (Tom)
@@ -90,7 +92,7 @@ contrib/tsearch dictionary improvements, see README.tsearch for
9092
an additional installation step (Thomas T. Thai, Teodor Sigaev)
9193
Fix for array subscripts handling (Tom)
9294
Allow EXECUTE of "CREATE TABLE AS ... SELECT" in PL/PgSQL (Tom)
93-
</programlisting>
95+
</literallayout>
9496
</para>
9597
</sect2>
9698
</sect1>

‎src/backend/catalog/pg_aggregate.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_aggregate.c,v 1.47 2002/05/21 22:05:54 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_aggregate.c,v 1.48 2002/05/22 17:20:58 petere Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -136,6 +136,7 @@ AggregateCreate(const char *aggName,
136136
false,/* doesn't return a set */
137137
finaltype,/* returnType */
138138
INTERNALlanguageId,/* languageObjectId */
139+
0,
139140
"aggregate_dummy",/* placeholder proc */
140141
"-",/* probin */
141142
true,/* isAgg */

‎src/backend/catalog/pg_proc.c

Lines changed: 133 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.73 2002/05/21 22:05:54 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.74 2002/05/22 17:20:58 petere Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -20,6 +20,7 @@
2020
#include"catalog/pg_language.h"
2121
#include"catalog/pg_proc.h"
2222
#include"executor/executor.h"
23+
#include"fmgr.h"
2324
#include"miscadmin.h"
2425
#include"parser/parse_coerce.h"
2526
#include"parser/parse_expr.h"
@@ -32,6 +33,9 @@
3233

3334

3435
staticvoidcheckretval(Oidrettype,List*queryTreeList);
36+
Datumfmgr_internal_validator(PG_FUNCTION_ARGS);
37+
Datumfmgr_c_validator(PG_FUNCTION_ARGS);
38+
Datumfmgr_sql_validator(PG_FUNCTION_ARGS);
3539

3640

3741
/* ----------------------------------------------------------------
@@ -45,6 +49,7 @@ ProcedureCreate(const char *procedureName,
4549
boolreturnsSet,
4650
OidreturnType,
4751
OidlanguageObjectId,
52+
OidlanguageValidator,
4853
constchar*prosrc,
4954
constchar*probin,
5055
boolisAgg,
@@ -66,7 +71,6 @@ ProcedureCreate(const char *procedureName,
6671
charnulls[Natts_pg_proc];
6772
Datumvalues[Natts_pg_proc];
6873
charreplaces[Natts_pg_proc];
69-
List*querytree_list;
7074
Oidtypev[FUNC_MAX_ARGS];
7175
Oidrelid;
7276
NameDataprocname;
@@ -126,12 +130,6 @@ ProcedureCreate(const char *procedureName,
126130
}
127131
}
128132

129-
if (!OidIsValid(returnType))
130-
{
131-
if (languageObjectId==SQLlanguageId)
132-
elog(ERROR,"SQL functions cannot return type \"opaque\"");
133-
}
134-
135133
/*
136134
* don't allow functions of complex types that have the same name as
137135
* existing attributes of the type
@@ -142,65 +140,6 @@ ProcedureCreate(const char *procedureName,
142140
elog(ERROR,"method %s already an attribute of type %s",
143141
procedureName,format_type_be(typev[0]));
144142

145-
/*
146-
* If this is a postquel procedure, we parse it here in order to be
147-
* sure that it contains no syntax errors.We should store the plan
148-
* in an Inversion file for use later, but for now, we just store the
149-
* procedure's text in the prosrc attribute.
150-
*/
151-
152-
if (languageObjectId==SQLlanguageId)
153-
{
154-
querytree_list=pg_parse_and_rewrite((char*)prosrc,
155-
typev,
156-
parameterCount);
157-
/* typecheck return value */
158-
checkretval(returnType,querytree_list);
159-
}
160-
161-
/*
162-
* If this is an internal procedure, check that the given internal
163-
* function name (the 'prosrc' value) is a known builtin function.
164-
*
165-
* NOTE: in Postgres versions before 6.5, the SQL name of the created
166-
* function could not be different from the internal name, and
167-
* 'prosrc' wasn't used. So there is code out there that does CREATE
168-
* FUNCTION xyz AS '' LANGUAGE 'internal'.To preserve some modicum
169-
* of backwards compatibility, accept an empty 'prosrc' value as
170-
* meaning the supplied SQL function name.
171-
*/
172-
if (languageObjectId==INTERNALlanguageId)
173-
{
174-
if (strlen(prosrc)==0)
175-
prosrc=procedureName;
176-
if (fmgr_internal_function((char*)prosrc)==InvalidOid)
177-
elog(ERROR,
178-
"there is no built-in function named \"%s\"",
179-
prosrc);
180-
}
181-
182-
/*
183-
* If this is a dynamically loadable procedure, make sure that the
184-
* library file exists, is loadable, and contains the specified link
185-
* symbol.Also check for a valid function information record.
186-
*
187-
* We used to perform these checks only when the function was first
188-
* called, but it seems friendlier to verify the library's validity at
189-
* CREATE FUNCTION time.
190-
*/
191-
if (languageObjectId==ClanguageId)
192-
{
193-
void*libraryhandle;
194-
195-
/* If link symbol is specified as "-", substitute procedure name */
196-
if (strcmp(prosrc,"-")==0)
197-
prosrc=procedureName;
198-
(void)load_external_function((char*)probin,
199-
(char*)prosrc,
200-
true,
201-
&libraryhandle);
202-
(void)fetch_finfo_record(libraryhandle, (char*)prosrc);
203-
}
204143

205144
/*
206145
* All seems OK; prepare the data to be inserted into pg_proc.
@@ -316,6 +255,14 @@ ProcedureCreate(const char *procedureName,
316255

317256
heap_close(rel,RowExclusiveLock);
318257

258+
/* Verify function body */
259+
if (OidIsValid(languageValidator))
260+
{
261+
/* Advance command counter so recursive functions can be defined */
262+
CommandCounterIncrement();
263+
OidFunctionCall1(languageValidator,retval);
264+
}
265+
319266
returnretval;
320267
}
321268

@@ -454,3 +401,122 @@ checkretval(Oid rettype, List *queryTreeList)
454401

455402
heap_close(reln,AccessShareLock);
456403
}
404+
405+
406+
407+
/*
408+
* Validator for internal functions
409+
*
410+
* Check that the given internal function name (the "prosrc" value) is
411+
* a known builtin function.
412+
*/
413+
Datum
414+
fmgr_internal_validator(PG_FUNCTION_ARGS)
415+
{
416+
Oidfuncoid=PG_GETARG_OID(0);
417+
HeapTupletuple;
418+
Form_pg_procproc;
419+
boolisnull;
420+
Datumtmp;
421+
char*prosrc;
422+
423+
tuple=SearchSysCache(PROCOID,funcoid,0,0,0);
424+
if (!HeapTupleIsValid(tuple))
425+
elog(ERROR,"cache lookup of function %u failed",funcoid);
426+
proc= (Form_pg_proc)GETSTRUCT(tuple);
427+
428+
tmp=SysCacheGetAttr(PROCOID,tuple,Anum_pg_proc_prosrc,&isnull);
429+
if (isnull)
430+
elog(ERROR,"null prosrc");
431+
prosrc=DatumGetCString(DirectFunctionCall1(textout,tmp));
432+
433+
if (fmgr_internal_function(prosrc)==InvalidOid)
434+
elog(ERROR,"there is no built-in function named \"%s\"",prosrc);
435+
436+
ReleaseSysCache(tuple);
437+
PG_RETURN_BOOL(true);
438+
}
439+
440+
441+
442+
/*
443+
* Validator for C language functions
444+
*
445+
* Make sure that the library file exists, is loadable, and contains
446+
* the specified link symbol. Also check for a valid function
447+
* information record.
448+
*/
449+
Datum
450+
fmgr_c_validator(PG_FUNCTION_ARGS)
451+
{
452+
Oidfuncoid=PG_GETARG_OID(0);
453+
void*libraryhandle;
454+
HeapTupletuple;
455+
Form_pg_procproc;
456+
boolisnull;
457+
Datumtmp;
458+
char*prosrc;
459+
char*probin;
460+
461+
tuple=SearchSysCache(PROCOID,funcoid,0,0,0);
462+
if (!HeapTupleIsValid(tuple))
463+
elog(ERROR,"cache lookup of function %u failed",funcoid);
464+
proc= (Form_pg_proc)GETSTRUCT(tuple);
465+
466+
tmp=SysCacheGetAttr(PROCOID,tuple,Anum_pg_proc_prosrc,&isnull);
467+
if (isnull)
468+
elog(ERROR,"null prosrc");
469+
prosrc=DatumGetCString(DirectFunctionCall1(textout,tmp));
470+
471+
tmp=SysCacheGetAttr(PROCOID,tuple,Anum_pg_proc_probin,&isnull);
472+
if (isnull)
473+
elog(ERROR,"null probin");
474+
probin=DatumGetCString(DirectFunctionCall1(textout,tmp));
475+
476+
(void)load_external_function(probin,prosrc, true,&libraryhandle);
477+
(void)fetch_finfo_record(libraryhandle,prosrc);
478+
479+
ReleaseSysCache(tuple);
480+
PG_RETURN_BOOL(true);
481+
}
482+
483+
484+
485+
/*
486+
* Validator for SQL language functions
487+
*
488+
* Parse it here in order to be sure that it contains no syntax
489+
* errors.
490+
*/
491+
Datum
492+
fmgr_sql_validator(PG_FUNCTION_ARGS)
493+
{
494+
Oidfuncoid=PG_GETARG_OID(0);
495+
HeapTupletuple;
496+
Form_pg_procproc;
497+
List*querytree_list;
498+
boolisnull;
499+
Datumtmp;
500+
char*prosrc;
501+
502+
tuple=SearchSysCache(PROCOID,funcoid,0,0,0);
503+
if (!HeapTupleIsValid(tuple))
504+
elog(ERROR,"cache lookup of function %u failed",funcoid);
505+
506+
proc= (Form_pg_proc)GETSTRUCT(tuple);
507+
508+
if (!OidIsValid(proc->prorettype))
509+
elog(ERROR,"SQL functions cannot return type \"opaque\"");
510+
511+
tmp=SysCacheGetAttr(PROCOID,tuple,Anum_pg_proc_prosrc,&isnull);
512+
if (isnull)
513+
elog(ERROR,"null prosrc");
514+
515+
prosrc=DatumGetCString(DirectFunctionCall1(textout,tmp));
516+
517+
querytree_list=pg_parse_and_rewrite(prosrc,proc->proargtypes,proc->pronargs);
518+
checkretval(proc->prorettype,querytree_list);
519+
520+
ReleaseSysCache(tuple);
521+
PG_RETURN_BOOL(true);
522+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp