aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands
diff options
context:
space:
mode:
authorPeter Eisentraut <peter_e@gmx.net>2002-05-22 17:21:02 +0000
committerPeter Eisentraut <peter_e@gmx.net>2002-05-22 17:21:02 +0000
commitd60f10b0e74173653d17c09750a791afe6f56404 (patch)
tree9803f14bc9ce71e3a056a447b6999847bb2a8dd6 /src/backend/commands
parentdf9c8e1a39dc0502c62e164aa94e7e810bcd2009 (diff)
downloadpostgresql-d60f10b0e74173653d17c09750a791afe6f56404.tar.gz
postgresql-d60f10b0e74173653d17c09750a791afe6f56404.zip
Add optional "validator" function to languages that can validate the
function body (and other properties) as a function in the language is created. This generalizes ad hoc code that already existed for the built-in languages. The validation now happens after the pg_proc tuple of the new function is created, so it is possible to define recursive SQL functions. Add some regression test cases that cover bogus function definition attempts.
Diffstat (limited to 'src/backend/commands')
-rw-r--r--src/backend/commands/functioncmds.c28
-rw-r--r--src/backend/commands/proclang.c20
2 files changed, 44 insertions, 4 deletions
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 */