worries about funny characters.
-->
+Recursive SQL functions can be defined
+User-defined procedural languages can register a validator function to check new functions as they are created
Functions can be executed with the privileges of the owner
Syntax of CREATE FUNCTION has been extended to resemble SQL99
Effects of SET within a transaction block now roll back if transaction aborts
Changes
+>
Ensure that sequence counters do not go backwards after a crash (Tom)
Fix pgaccess kanji-coversion key binding (Tatsuo)
Optimizer improvements (Tom)
an additional installation step (Thomas T. Thai, Teodor Sigaev)
Fix for array subscripts handling (Tom)
Allow EXECUTE of "CREATE TABLE AS ... SELECT" in PL/PgSQL (Tom)
- >
+>
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
false, /* doesn't return a set */
finaltype, /* returnType */
INTERNALlanguageId, /* languageObjectId */
+ 0,
"aggregate_dummy", /* placeholder proc */
"-", /* probin */
true, /* isAgg */
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
#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"
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);
/* ----------------------------------------------------------------
bool returnsSet,
Oid returnType,
Oid languageObjectId,
+ Oid languageValidator,
const char *prosrc,
const char *probin,
bool isAgg,
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;
}
}
- 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
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.
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;
}
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);
+}
*
*
* 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
char *language;
char languageName[NAMEDATALEN];
Oid languageOid;
+ Oid languageValidator;
char *funcname;
Oid namespaceId;
AclResult aclresult;
aclcheck_error(ACLCHECK_NO_PRIV, NameStr(languageStruct->lanname));
}
+ languageValidator = languageStruct->lanvalidator;
+
ReleaseSysCache(languageTuple);
/*
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.
returnsSet,
prorettype,
languageOid,
+ languageValidator,
prosrc_str, /* converted to text later */
probin_str, /* converted to text later */
false, /* not an aggregate */
* 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 $
*
*-------------------------------------------------------------------------
*/
#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"
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];
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
*/
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 */
* 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 $
*
*-------------------------------------------------------------------------
*/
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;
* 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 $
*
*-------------------------------------------------------------------------
*/
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)
*
*
* 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
index_name, name, function_name, file_name
%type func_name, handler_name, qual_Op, qual_all_Op, OptUseOp,
- opt_class
+ opt_class, opt_validator
%type qualified_name, OptConstrFromTable
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
*****************************************************************************/
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;
}
| /*EMPTY*/ { $$ = ""; }
;
+opt_validator: VALIDATOR handler_name { $$ = $2; }
+ | /*EMPTY*/ { $$ = NULL; }
+ ;
+
DropPLangStmt: DROP opt_procedural LANGUAGE ColId_or_Sconst
{
DropPLangStmt *n = makeNode(DropPLangStmt);
| USAGE
| VACUUM
| VALID
+ | VALIDATOR
| VALUES
| VARYING
| VERSION
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
{"using", USING},
{"vacuum", VACUUM},
{"valid", VALID},
+ {"validator", VALIDATOR},
{"values", VALUES},
{"varchar", VARCHAR},
{"varying", VARYING},
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
true, /* returnsSet */
elemType, /* returnType */
SQLlanguageId, /* language */
+ SQLvalidatorId,
querystr, /* prosrc */
fileName, /* probin */
false, /* not aggregate */
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.263 2002/05/19 10:08:25 petere Exp $
+ * $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.264 2002/05/22 17:21:00 petere Exp $
*
*-------------------------------------------------------------------------
*/
int i_lanname;
int i_lanpltrusted;
int i_lanplcallfoid;
+ int i_lanvalidator = -1;
int i_lancompiler;
int i_lanacl = -1;
char *lanoid;
char *lancompiler;
char *lanacl;
const char *lanplcallfoid;
+ const char *lanvalidator;
const char *((*deps)[]);
int depIdx;
int i,
- fidx;
+ fidx,
+ vidx = -1;
/* Make sure we are in proper schema */
selectSourceSchema("pg_catalog");
i_lancompiler = PQfnumber(res, "lancompiler");
i_oid = PQfnumber(res, "oid");
if (fout->remoteVersion >= 70300)
+ {
+ i_lanvalidator = PQfnumber(res, "lanvalidator");
i_lanacl = PQfnumber(res, "lanacl");
+ }
for (i = 0; i < ntups; i++)
{
lanname = PQgetvalue(res, i, i_lanname);
lancompiler = PQgetvalue(res, i, i_lancompiler);
if (fout->remoteVersion >= 70300)
+ {
+ lanvalidator = PQgetvalue(res, i, i_lanvalidator);
lanacl = PQgetvalue(res, i, i_lanacl);
+ }
else
- lanacl = "{=U}";
+ {
+ lanvalidator = "0";
+ lanacl = "{=U}";
+ }
fidx = findFuncByOid(finfo, numFuncs, lanplcallfoid);
if (fidx < 0)
exit_nicely();
}
+ if (strcmp(lanvalidator, "0") != 0)
+ {
+ vidx = findFuncByOid(finfo, numFuncs, lanvalidator);
+ if (vidx < 0)
+ {
+ write_msg(NULL, "validator procedure for procedural language %s not found\n",
+ lanname);
+ exit_nicely();
+ }
+ }
+
/*
* Current theory is to dump PLs iff their underlying functions
* will be dumped (are in a dumpable namespace, or have a non-system
resetPQExpBuffer(delqry);
/* Make a dependency to ensure function is dumped first */
- deps = malloc(sizeof(char *) * 2);
+ deps = malloc(sizeof(char *) * (2 + (strcmp(lanvalidator, "0")!=0) ? 1 : 0));
depIdx = 0;
(*deps)[depIdx++] = strdup(lanplcallfoid);
(PQgetvalue(res, i, i_lanpltrusted)[0] == 't') ?
"TRUSTED " : "",
fmtId(lanname, force_quotes));
- appendPQExpBuffer(defqry, " HANDLER %s;\n",
+ appendPQExpBuffer(defqry, " HANDLER %s",
fmtId(finfo[fidx].proname, force_quotes));
+ if (strcmp(lanvalidator, "0")!=0)
+ {
+ appendPQExpBuffer(defqry, " VALIDATOR %s",
+ fmtId(finfo[vidx].proname, force_quotes));
+ (*deps)[depIdx++] = strdup(lanvalidator);
+ }
+ appendPQExpBuffer(defqry, ";\n");
(*deps)[depIdx++] = NULL; /* End of List */
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: catversion.h,v 1.132 2002/05/18 13:48:00 petere Exp $
+ * $Id: catversion.h,v 1.133 2002/05/22 17:21:01 petere Exp $
*
*-------------------------------------------------------------------------
*/
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 200205181
+#define CATALOG_VERSION_NO 200205221
#endif
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: pg_language.h,v 1.16 2002/02/18 23:11:35 petere Exp $
+ * $Id: pg_language.h,v 1.17 2002/05/22 17:21:01 petere Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
bool lanispl; /* Is a procedural language */
bool lanpltrusted; /* PL is trusted */
Oid lanplcallfoid; /* Call handler for PL */
+ Oid lanvalidator; /* optional validation function */
text lancompiler; /* VARIABLE LENGTH FIELD */
aclitem lanacl[1]; /* Access privileges */
} FormData_pg_language;
* compiler constants for pg_language
* ----------------
*/
-#define Natts_pg_language 6
+#define Natts_pg_language 7
#define Anum_pg_language_lanname 1
#define Anum_pg_language_lanispl 2
#define Anum_pg_language_lanpltrusted 3
#define Anum_pg_language_lanplcallfoid 4
-#define Anum_pg_language_lancompiler 5
-#define Anum_pg_language_lanacl 6
+#define Anum_pg_language_lanvalidator 5
+#define Anum_pg_language_lancompiler 6
+#define Anum_pg_language_lanacl 7
/* ----------------
* initial contents of pg_language
* ----------------
*/
-DATA(insert OID = 12 ( "internal" f f 0 "n/a" _null_ ));
+DATA(insert OID = 12 ( "internal" f f 0 2246 "n/a" _null_ ));
DESCR("Built-in functions");
#define INTERNALlanguageId 12
-DATA(insert OID = 13 ( "c" f f 0 "/bin/cc" _null_ ));
+DATA(insert OID = 13 ( "c" f f 0 2247 "/bin/cc" _null_ ));
DESCR("Dynamically-loaded C functions");
#define ClanguageId 13
-DATA(insert OID = 14 ( "sql" f t 0 "postgres" _null_ ));
+DATA(insert OID = 14 ( "sql" f t 0 2248 "postgres" _null_ ));
DESCR("SQL-language functions");
#define SQLlanguageId 14
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: pg_proc.h,v 1.238 2002/05/20 23:51:43 tgl Exp $
+ * $Id: pg_proc.h,v 1.239 2002/05/22 17:21:01 petere Exp $
*
* NOTES
* The script catalog/genbki.sh reads this file and generates .bki
DATA(insert OID = 2221 ( regtypeout PGNSP PGUID 12 f f f t f s 1 23 "0" 100 0 0 100 regtypeout - _null_ ));
DESCR("(internal)");
+DATA(insert OID = 2246 ( fmgr_internal_validator PGNSP PGUID 12 f f f t f s 1 26 "23" 100 0 0 100 fmgr_internal_validator - _null_ ));
+DESCR("(internal)");
+DATA(insert OID = 2247 ( fmgr_c_validator PGNSP PGUID 12 f f f t f s 1 26 "23" 100 0 0 100 fmgr_c_validator - _null_ ));
+DESCR("(internal)");
+DATA(insert OID = 2248 ( fmgr_sql_validator PGNSP PGUID 12 f f f t f s 1 26 "23" 100 0 0 100 fmgr_sql_validator - _null_ ));
+DESCR("(internal)");
+#define SQLvalidatorId 2248
/*
* Symbolic values for provolatile column: these indicate whether the result
bool returnsSet,
Oid returnType,
Oid languageObjectId,
+ Oid languageValidator,
const char *prosrc,
const char *probin,
bool isAgg,
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: parsenodes.h,v 1.178 2002/05/17 18:32:52 petere Exp $
+ * $Id: parsenodes.h,v 1.179 2002/05/22 17:21:01 petere Exp $
*
*-------------------------------------------------------------------------
*/
NodeTag type;
char *plname; /* PL name */
List *plhandler; /* PL call handler function (qual. name) */
+ List *plvalidator; /* optional validator function (qual. name) */
char *plcompiler; /* lancompiler text */
bool pltrusted; /* PL is trusted */
} CreatePLangStmt;
AS '@abs_builddir@/regress@DLSUFFIX@'
LANGUAGE 'C';
+-- Things that shouldn't work:
+
+CREATE FUNCTION test1 (int) RETURNS int LANGUAGE sql
+ AS 'SELECT ''not an integer'';';
+
+CREATE FUNCTION test1 (int) RETURNS int LANGUAGE sql
+ AS 'not even SQL';
+
+CREATE FUNCTION test1 (int) RETURNS int LANGUAGE sql
+ AS 'SELECT 1, 2, 3;';
+
+CREATE FUNCTION test1 (int) RETURNS int LANGUAGE sql
+ AS 'SELECT $2;';
+
+CREATE FUNCTION test1 (int) RETURNS int LANGUAGE sql
+ AS 'a', 'b';
+
+CREATE FUNCTION test1 (int) RETURNS int LANGUAGE c
+ AS 'nosuchfile';
+
+CREATE FUNCTION test1 (int) RETURNS int LANGUAGE c
+ AS '@abs_builddir@/regress@DLSUFFIX@', 'nosuchsymbol';
+
+CREATE FUNCTION test1 (int) RETURNS int LANGUAGE internal
+ AS 'nosuch';
RETURNS int4
AS '@abs_builddir@/regress@DLSUFFIX@'
LANGUAGE 'C';
+-- Things that shouldn't work:
+CREATE FUNCTION test1 (int) RETURNS int LANGUAGE sql
+ AS 'SELECT ''not an integer'';';
+ERROR: return type mismatch in function: declared to return integer, returns "unknown"
+CREATE FUNCTION test1 (int) RETURNS int LANGUAGE sql
+ AS 'not even SQL';
+ERROR: parser: parse error at or near "not"
+CREATE FUNCTION test1 (int) RETURNS int LANGUAGE sql
+ AS 'SELECT 1, 2, 3;';
+ERROR: function declared to return integer returns multiple columns in final SELECT
+CREATE FUNCTION test1 (int) RETURNS int LANGUAGE sql
+ AS 'SELECT $2;';
+ERROR: Parameter '$2' is out of range
+CREATE FUNCTION test1 (int) RETURNS int LANGUAGE sql
+ AS 'a', 'b';
+ERROR: CREATE FUNCTION: only one AS item needed for sql language
+CREATE FUNCTION test1 (int) RETURNS int LANGUAGE c
+ AS 'nosuchfile';
+ERROR: stat failed on file 'nosuchfile': No such file or directory
+CREATE FUNCTION test1 (int) RETURNS int LANGUAGE c
+ AS '@abs_builddir@/regress@DLSUFFIX@', 'nosuchsymbol';
+ERROR: Can't find function nosuchsymbol in file @abs_builddir@/regress@DLSUFFIX@
+CREATE FUNCTION test1 (int) RETURNS int LANGUAGE internal
+ AS 'nosuch';
+ERROR: there is no built-in function named "nosuch"