diff options
Diffstat (limited to 'src/backend')
-rw-r--r-- | src/backend/catalog/pg_aggregate.c | 3 | ||||
-rw-r--r-- | src/backend/catalog/pg_proc.c | 200 | ||||
-rw-r--r-- | src/backend/commands/functioncmds.c | 28 | ||||
-rw-r--r-- | src/backend/commands/proclang.c | 20 | ||||
-rw-r--r-- | src/backend/nodes/copyfuncs.c | 3 | ||||
-rw-r--r-- | src/backend/nodes/equalfuncs.c | 4 | ||||
-rw-r--r-- | src/backend/parser/gram.y | 16 | ||||
-rw-r--r-- | src/backend/parser/keywords.c | 3 | ||||
-rw-r--r-- | src/backend/utils/adt/sets.c | 3 |
9 files changed, 199 insertions, 81 deletions
diff --git a/src/backend/catalog/pg_aggregate.c b/src/backend/catalog/pg_aggregate.c index 1853acda73c..3a3d749e19d 100644 --- a/src/backend/catalog/pg_aggregate.c +++ b/src/backend/catalog/pg_aggregate.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/pg_aggregate.c,v 1.47 2002/05/21 22:05:54 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/pg_aggregate.c,v 1.48 2002/05/22 17:20:58 petere Exp $ * *------------------------------------------------------------------------- */ @@ -136,6 +136,7 @@ AggregateCreate(const char *aggName, false, /* doesn't return a set */ finaltype, /* returnType */ INTERNALlanguageId, /* languageObjectId */ + 0, "aggregate_dummy", /* placeholder proc */ "-", /* probin */ true, /* isAgg */ diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c index 4d656d98ba2..e7421ef2077 100644 --- a/src/backend/catalog/pg_proc.c +++ b/src/backend/catalog/pg_proc.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.73 2002/05/21 22:05:54 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.74 2002/05/22 17:20:58 petere Exp $ * *------------------------------------------------------------------------- */ @@ -20,6 +20,7 @@ #include "catalog/pg_language.h" #include "catalog/pg_proc.h" #include "executor/executor.h" +#include "fmgr.h" #include "miscadmin.h" #include "parser/parse_coerce.h" #include "parser/parse_expr.h" @@ -32,6 +33,9 @@ static void checkretval(Oid rettype, List *queryTreeList); +Datum fmgr_internal_validator(PG_FUNCTION_ARGS); +Datum fmgr_c_validator(PG_FUNCTION_ARGS); +Datum fmgr_sql_validator(PG_FUNCTION_ARGS); /* ---------------------------------------------------------------- @@ -45,6 +49,7 @@ ProcedureCreate(const char *procedureName, bool returnsSet, Oid returnType, Oid languageObjectId, + Oid languageValidator, const char *prosrc, const char *probin, bool isAgg, @@ -66,7 +71,6 @@ ProcedureCreate(const char *procedureName, char nulls[Natts_pg_proc]; Datum values[Natts_pg_proc]; char replaces[Natts_pg_proc]; - List *querytree_list; Oid typev[FUNC_MAX_ARGS]; Oid relid; NameData procname; @@ -126,12 +130,6 @@ ProcedureCreate(const char *procedureName, } } - if (!OidIsValid(returnType)) - { - if (languageObjectId == SQLlanguageId) - elog(ERROR, "SQL functions cannot return type \"opaque\""); - } - /* * don't allow functions of complex types that have the same name as * existing attributes of the type @@ -142,65 +140,6 @@ ProcedureCreate(const char *procedureName, elog(ERROR, "method %s already an attribute of type %s", procedureName, format_type_be(typev[0])); - /* - * If this is a postquel procedure, we parse it here in order to be - * sure that it contains no syntax errors. We should store the plan - * in an Inversion file for use later, but for now, we just store the - * procedure's text in the prosrc attribute. - */ - - if (languageObjectId == SQLlanguageId) - { - querytree_list = pg_parse_and_rewrite((char *) prosrc, - typev, - parameterCount); - /* typecheck return value */ - checkretval(returnType, querytree_list); - } - - /* - * If this is an internal procedure, check that the given internal - * function name (the 'prosrc' value) is a known builtin function. - * - * NOTE: in Postgres versions before 6.5, the SQL name of the created - * function could not be different from the internal name, and - * 'prosrc' wasn't used. So there is code out there that does CREATE - * FUNCTION xyz AS '' LANGUAGE 'internal'. To preserve some modicum - * of backwards compatibility, accept an empty 'prosrc' value as - * meaning the supplied SQL function name. - */ - if (languageObjectId == INTERNALlanguageId) - { - if (strlen(prosrc) == 0) - prosrc = procedureName; - if (fmgr_internal_function((char *) prosrc) == InvalidOid) - elog(ERROR, - "there is no built-in function named \"%s\"", - prosrc); - } - - /* - * If this is a dynamically loadable procedure, make sure that the - * library file exists, is loadable, and contains the specified link - * symbol. Also check for a valid function information record. - * - * We used to perform these checks only when the function was first - * called, but it seems friendlier to verify the library's validity at - * CREATE FUNCTION time. - */ - if (languageObjectId == ClanguageId) - { - void *libraryhandle; - - /* If link symbol is specified as "-", substitute procedure name */ - if (strcmp(prosrc, "-") == 0) - prosrc = procedureName; - (void) load_external_function((char *) probin, - (char *) prosrc, - true, - &libraryhandle); - (void) fetch_finfo_record(libraryhandle, (char *) prosrc); - } /* * All seems OK; prepare the data to be inserted into pg_proc. @@ -316,6 +255,14 @@ ProcedureCreate(const char *procedureName, heap_close(rel, RowExclusiveLock); + /* Verify function body */ + if (OidIsValid(languageValidator)) + { + /* Advance command counter so recursive functions can be defined */ + CommandCounterIncrement(); + OidFunctionCall1(languageValidator, retval); + } + return retval; } @@ -454,3 +401,122 @@ checkretval(Oid rettype, List *queryTreeList) heap_close(reln, AccessShareLock); } + + + +/* + * Validator for internal functions + * + * Check that the given internal function name (the "prosrc" value) is + * a known builtin function. + */ +Datum +fmgr_internal_validator(PG_FUNCTION_ARGS) +{ + Oid funcoid = PG_GETARG_OID(0); + HeapTuple tuple; + Form_pg_proc proc; + bool isnull; + Datum tmp; + char *prosrc; + + tuple = SearchSysCache(PROCOID, funcoid, 0, 0, 0); + if (!HeapTupleIsValid(tuple)) + elog(ERROR, "cache lookup of function %u failed", funcoid); + proc = (Form_pg_proc) GETSTRUCT(tuple); + + tmp = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_prosrc, &isnull); + if (isnull) + elog(ERROR, "null prosrc"); + prosrc = DatumGetCString(DirectFunctionCall1(textout, tmp)); + + if (fmgr_internal_function(prosrc) == InvalidOid) + elog(ERROR, "there is no built-in function named \"%s\"", prosrc); + + ReleaseSysCache(tuple); + PG_RETURN_BOOL(true); +} + + + +/* + * Validator for C language functions + * + * Make sure that the library file exists, is loadable, and contains + * the specified link symbol. Also check for a valid function + * information record. + */ +Datum +fmgr_c_validator(PG_FUNCTION_ARGS) +{ + Oid funcoid = PG_GETARG_OID(0); + void *libraryhandle; + HeapTuple tuple; + Form_pg_proc proc; + bool isnull; + Datum tmp; + char *prosrc; + char *probin; + + tuple = SearchSysCache(PROCOID, funcoid, 0, 0, 0); + if (!HeapTupleIsValid(tuple)) + elog(ERROR, "cache lookup of function %u failed", funcoid); + proc = (Form_pg_proc) GETSTRUCT(tuple); + + tmp = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_prosrc, &isnull); + if (isnull) + elog(ERROR, "null prosrc"); + prosrc = DatumGetCString(DirectFunctionCall1(textout, tmp)); + + tmp = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_probin, &isnull); + if (isnull) + elog(ERROR, "null probin"); + probin = DatumGetCString(DirectFunctionCall1(textout, tmp)); + + (void) load_external_function(probin, prosrc, true, &libraryhandle); + (void) fetch_finfo_record(libraryhandle, prosrc); + + ReleaseSysCache(tuple); + PG_RETURN_BOOL(true); +} + + + +/* + * Validator for SQL language functions + * + * Parse it here in order to be sure that it contains no syntax + * errors. + */ +Datum +fmgr_sql_validator(PG_FUNCTION_ARGS) +{ + Oid funcoid = PG_GETARG_OID(0); + HeapTuple tuple; + Form_pg_proc proc; + List *querytree_list; + bool isnull; + Datum tmp; + char *prosrc; + + tuple = SearchSysCache(PROCOID, funcoid, 0, 0, 0); + if (!HeapTupleIsValid(tuple)) + elog(ERROR, "cache lookup of function %u failed", funcoid); + + proc = (Form_pg_proc) GETSTRUCT(tuple); + + if (!OidIsValid(proc->prorettype)) + elog(ERROR, "SQL functions cannot return type \"opaque\""); + + tmp = SysCacheGetAttr(PROCOID, tuple, Anum_pg_proc_prosrc, &isnull); + if (isnull) + elog(ERROR, "null prosrc"); + + prosrc = DatumGetCString(DirectFunctionCall1(textout, tmp)); + + querytree_list = pg_parse_and_rewrite(prosrc, proc->proargtypes, proc->pronargs); + checkretval(proc->prorettype, querytree_list); + + ReleaseSysCache(tuple); + PG_RETURN_BOOL(true); +} diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c index 06870b0d3d2..a619a71b435 100644 --- a/src/backend/commands/functioncmds.c +++ b/src/backend/commands/functioncmds.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/functioncmds.c,v 1.5 2002/05/18 13:47:59 petere Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/functioncmds.c,v 1.6 2002/05/22 17:20:58 petere Exp $ * * DESCRIPTION * These routines take the parse tree and pick out the @@ -388,6 +388,7 @@ CreateFunction(CreateFunctionStmt *stmt) char *language; char languageName[NAMEDATALEN]; Oid languageOid; + Oid languageValidator; char *funcname; Oid namespaceId; AclResult aclresult; @@ -457,6 +458,8 @@ CreateFunction(CreateFunctionStmt *stmt) aclcheck_error(ACLCHECK_NO_PRIV, NameStr(languageStruct->lanname)); } + languageValidator = languageStruct->lanvalidator; + ReleaseSysCache(languageTuple); /* @@ -477,6 +480,28 @@ CreateFunction(CreateFunctionStmt *stmt) interpret_AS_clause(languageOid, languageName, as_clause, &prosrc_str, &probin_str); + if (languageOid == INTERNALlanguageId) + { + /* + * In PostgreSQL versions before 6.5, the SQL name of the + * created function could not be different from the internal + * name, and "prosrc" wasn't used. So there is code out there + * that does CREATE FUNCTION xyz AS '' LANGUAGE 'internal'. + * To preserve some modicum of backwards compatibility, accept + * an empty "prosrc" value as meaning the supplied SQL + * function name. + */ + if (strlen(prosrc_str) == 0) + prosrc_str = funcname; + } + + if (languageOid == ClanguageId) + { + /* If link symbol is specified as "-", substitute procedure name */ + if (strcmp(prosrc_str, "-") == 0) + prosrc_str = funcname; + } + /* * And now that we have all the parameters, and know we're permitted * to do so, go ahead and create the function. @@ -487,6 +512,7 @@ CreateFunction(CreateFunctionStmt *stmt) returnsSet, prorettype, languageOid, + languageValidator, prosrc_str, /* converted to text later */ probin_str, /* converted to text later */ false, /* not an aggregate */ diff --git a/src/backend/commands/proclang.c b/src/backend/commands/proclang.c index 6cabbf0ec13..626c05f59cd 100644 --- a/src/backend/commands/proclang.c +++ b/src/backend/commands/proclang.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/proclang.c,v 1.32 2002/05/21 22:05:54 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/proclang.c,v 1.33 2002/05/22 17:20:58 petere Exp $ * *------------------------------------------------------------------------- */ @@ -21,6 +21,7 @@ #include "catalog/namespace.h" #include "catalog/pg_language.h" #include "catalog/pg_proc.h" +#include "catalog/pg_type.h" #include "commands/proclang.h" #include "commands/defrem.h" #include "fmgr.h" @@ -39,7 +40,7 @@ void CreateProceduralLanguage(CreatePLangStmt *stmt) { char languageName[NAMEDATALEN]; - Oid procOid; + Oid procOid, valProcOid; Oid typev[FUNC_MAX_ARGS]; char nulls[Natts_pg_language]; Datum values[Natts_pg_language]; @@ -76,9 +77,21 @@ CreateProceduralLanguage(CreatePLangStmt *stmt) elog(ERROR, "PL handler function %s() doesn't exist", NameListToString(stmt->plhandler)); if (get_func_rettype(procOid) != InvalidOid) - elog(ERROR, "PL handler function %s() isn't of return type Opaque", + elog(ERROR, "PL handler function %s() does not return type \"opaque\"", NameListToString(stmt->plhandler)); + /* validate the validator function */ + if (stmt->plvalidator) + { + typev[0] = OIDOID; + valProcOid = LookupFuncName(stmt->plvalidator, 1, typev); + if (!OidIsValid(valProcOid)) + elog(ERROR, "PL validator function %s(oid) doesn't exist", + NameListToString(stmt->plvalidator)); + } + else + valProcOid = 0; + /* * Insert the new language into pg_language */ @@ -93,6 +106,7 @@ CreateProceduralLanguage(CreatePLangStmt *stmt) values[i++] = BoolGetDatum(true); /* lanispl */ values[i++] = BoolGetDatum(stmt->pltrusted); values[i++] = ObjectIdGetDatum(procOid); + values[i++] = ObjectIdGetDatum(valProcOid); values[i++] = DirectFunctionCall1(textin, CStringGetDatum(stmt->plcompiler)); nulls[i] = 'n'; /* lanacl */ diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index 1f0cc11934f..5bc16dc9b82 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -15,7 +15,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.187 2002/05/17 18:32:52 petere Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.188 2002/05/22 17:20:58 petere Exp $ * *------------------------------------------------------------------------- */ @@ -2418,6 +2418,7 @@ _copyCreatePLangStmt(CreatePLangStmt *from) if (from->plname) newnode->plname = pstrdup(from->plname); Node_Copy(from, newnode, plhandler); + Node_Copy(from, newnode, plvalidator); if (from->plcompiler) newnode->plcompiler = pstrdup(from->plcompiler); newnode->pltrusted = from->pltrusted; diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index f48d6d033f4..b4f576fc881 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -20,7 +20,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.134 2002/05/17 18:32:52 petere Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.135 2002/05/22 17:20:59 petere Exp $ * *------------------------------------------------------------------------- */ @@ -1252,6 +1252,8 @@ _equalCreatePLangStmt(CreatePLangStmt *a, CreatePLangStmt *b) return false; if (!equal(a->plhandler, b->plhandler)) return false; + if (!equal(a->plvalidator, b->plvalidator)) + return false; if (!equalstr(a->plcompiler, b->plcompiler)) return false; if (a->pltrusted != b->pltrusted) diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 999910161d0..d1109b58a7e 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.318 2002/05/19 15:16:55 petere Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.319 2002/05/22 17:20:59 petere Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -182,7 +182,7 @@ static void doNegateFloat(Value *v); index_name, name, function_name, file_name %type <list> func_name, handler_name, qual_Op, qual_all_Op, OptUseOp, - opt_class + opt_class, opt_validator %type <range> qualified_name, OptConstrFromTable @@ -375,7 +375,7 @@ static void doNegateFloat(Value *v); UNENCRYPTED, UNION, UNIQUE, UNKNOWN, UNLISTEN, UNTIL, UPDATE, USAGE, USER, USING, - VACUUM, VALID, VALUES, VARCHAR, VARYING, VERBOSE, VERSION, VIEW, VOLATILE, + VACUUM, VALID, VALIDATOR, VALUES, VARCHAR, VARYING, VERBOSE, VERSION, VIEW, VOLATILE, WHEN, WHERE, WITH, WITHOUT, WORK, YEAR_P, ZONE @@ -1835,12 +1835,13 @@ IntegerOnly: Iconst *****************************************************************************/ CreatePLangStmt: CREATE opt_trusted opt_procedural LANGUAGE ColId_or_Sconst - HANDLER handler_name opt_lancompiler + HANDLER handler_name opt_validator opt_lancompiler { CreatePLangStmt *n = makeNode(CreatePLangStmt); n->plname = $5; n->plhandler = $7; - n->plcompiler = $8; + n->plvalidator = $8; + n->plcompiler = $9; n->pltrusted = $2; $$ = (Node *)n; } @@ -1864,6 +1865,10 @@ opt_lancompiler: LANCOMPILER Sconst { $$ = $2; } | /*EMPTY*/ { $$ = ""; } ; +opt_validator: VALIDATOR handler_name { $$ = $2; } + | /*EMPTY*/ { $$ = NULL; } + ; + DropPLangStmt: DROP opt_procedural LANGUAGE ColId_or_Sconst { DropPLangStmt *n = makeNode(DropPLangStmt); @@ -6357,6 +6362,7 @@ unreserved_keyword: | USAGE | VACUUM | VALID + | VALIDATOR | VALUES | VARYING | VERSION diff --git a/src/backend/parser/keywords.c b/src/backend/parser/keywords.c index 36900127ea8..2cf91572a00 100644 --- a/src/backend/parser/keywords.c +++ b/src/backend/parser/keywords.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.110 2002/05/17 18:32:52 petere Exp $ + * $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.111 2002/05/22 17:20:59 petere Exp $ * *------------------------------------------------------------------------- */ @@ -292,6 +292,7 @@ static const ScanKeyword ScanKeywords[] = { {"using", USING}, {"vacuum", VACUUM}, {"valid", VALID}, + {"validator", VALIDATOR}, {"values", VALUES}, {"varchar", VARCHAR}, {"varying", VARYING}, diff --git a/src/backend/utils/adt/sets.c b/src/backend/utils/adt/sets.c index 298bdbdec82..e93ed50ff0a 100644 --- a/src/backend/utils/adt/sets.c +++ b/src/backend/utils/adt/sets.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/sets.c,v 1.44 2002/05/18 13:47:59 petere Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/sets.c,v 1.45 2002/05/22 17:21:00 petere Exp $ * *------------------------------------------------------------------------- */ @@ -58,6 +58,7 @@ SetDefine(char *querystr, Oid elemType) true, /* returnsSet */ elemType, /* returnType */ SQLlanguageId, /* language */ + SQLvalidatorId, querystr, /* prosrc */ fileName, /* probin */ false, /* not aggregate */ |