diff options
Diffstat (limited to 'src/backend/catalog/pg_proc.c')
-rw-r--r-- | src/backend/catalog/pg_proc.c | 200 |
1 files changed, 133 insertions, 67 deletions
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); +} |