summaryrefslogtreecommitdiff
path: root/src/pl
diff options
context:
space:
mode:
authorBruce Momjian1998-09-01 04:40:42 +0000
committerBruce Momjian1998-09-01 04:40:42 +0000
commitfa1a8d6a97068295fe30ac646aec7493a6305bc2 (patch)
tree645f7cef3c78fbab4d6d7bbc7c9a61ad2893d273 /src/pl
parentaf74855a608da4cd7ef88ceb2241ec1c75537f39 (diff)
OK, folks, here is the pgindent output.
Diffstat (limited to 'src/pl')
-rw-r--r--src/pl/plpgsql/src/pl_comp.c2200
-rw-r--r--src/pl/plpgsql/src/pl_exec.c3657
-rw-r--r--src/pl/plpgsql/src/pl_funcs.c949
-rw-r--r--src/pl/plpgsql/src/pl_handler.c239
-rw-r--r--src/pl/plpgsql/src/plpgsql.h637
-rw-r--r--src/pl/tcl/pltcl.c45
6 files changed, 3960 insertions, 3767 deletions
diff --git a/src/pl/plpgsql/src/pl_comp.c b/src/pl/plpgsql/src/pl_comp.c
index 96c11294126..f982471fd09 100644
--- a/src/pl/plpgsql/src/pl_comp.c
+++ b/src/pl/plpgsql/src/pl_comp.c
@@ -3,35 +3,35 @@
* procedural language
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.2 1998/09/01 03:29:03 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.3 1998/09/01 04:40:20 momjian Exp $
*
- * This software is copyrighted by Jan Wieck - Hamburg.
+ * This software is copyrighted by Jan Wieck - Hamburg.
*
- * The author hereby grants permission to use, copy, modify,
- * distribute, and license this software and its documentation
- * for any purpose, provided that existing copyright notices are
- * retained in all copies and that this notice is included
- * verbatim in any distributions. No written agreement, license,
- * or royalty fee is required for any of the authorized uses.
- * Modifications to this software may be copyrighted by their
- * author and need not follow the licensing terms described
- * here, provided that the new terms are clearly indicated on
- * the first page of each file where they apply.
+ * The author hereby grants permission to use, copy, modify,
+ * distribute, and license this software and its documentation
+ * for any purpose, provided that existing copyright notices are
+ * retained in all copies and that this notice is included
+ * verbatim in any distributions. No written agreement, license,
+ * or royalty fee is required for any of the authorized uses.
+ * Modifications to this software may be copyrighted by their
+ * author and need not follow the licensing terms described
+ * here, provided that the new terms are clearly indicated on
+ * the first page of each file where they apply.
*
- * IN NO EVENT SHALL THE AUTHOR OR DISTRIBUTORS BE LIABLE TO ANY
- * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR
- * CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS
- * SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN
- * IF THE AUTHOR HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
+ * IN NO EVENT SHALL THE AUTHOR OR DISTRIBUTORS BE LIABLE TO ANY
+ * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR
+ * CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS
+ * SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN
+ * IF THE AUTHOR HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
*
- * THE AUTHOR AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
- * PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON
- * AN "AS IS" BASIS, AND THE AUTHOR AND DISTRIBUTORS HAVE NO
- * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
- * ENHANCEMENTS, OR MODIFICATIONS.
+ * THE AUTHOR AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON
+ * AN "AS IS" BASIS, AND THE AUTHOR AND DISTRIBUTORS HAVE NO
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
+ * ENHANCEMENTS, OR MODIFICATIONS.
*
**********************************************************************/
@@ -67,24 +67,24 @@
* Variables in the parser that shouldn't go into plpgsql.h
* ----------
*/
-extern PLPGSQL_YYSTYPE plpgsql_yylval;
-extern int plpgsql_yylineno;
-extern char plpgsql_yytext[];
+extern PLPGSQL_YYSTYPE plpgsql_yylval;
+extern int plpgsql_yylineno;
+extern char plpgsql_yytext[];
-void plpgsql_yyerror(const char *s);
+void plpgsql_yyerror(const char *s);
/* ----------
* Our own local and global variables
* ----------
*/
static int datums_alloc;
-int plpgsql_nDatums;
-PLpgSQL_datum **plpgsql_Datums;
+int plpgsql_nDatums;
+PLpgSQL_datum **plpgsql_Datums;
static int datums_last = 0;
-int plpgsql_error_lineno;
-char *plpgsql_error_funcname;
-int plpgsql_DumpExecTree = 0;
+int plpgsql_error_lineno;
+char *plpgsql_error_funcname;
+int plpgsql_DumpExecTree = 0;
PLpgSQL_function *plpgsql_curr_compile;
@@ -101,413 +101,420 @@ static char *xlateSqlType(char *name);
* an execution tree for it.
* ----------
*/
-PLpgSQL_function *plpgsql_compile(Oid fn_oid, int functype)
+PLpgSQL_function *
+plpgsql_compile(Oid fn_oid, int functype)
{
- int parse_rc;
- HeapTuple procTup;
- Form_pg_proc procStruct;
- HeapTuple typeTup;
- Form_pg_type typeStruct;
- char *proc_source;
- PLpgSQL_function *function;
- PLpgSQL_var *var;
- PLpgSQL_row *row;
- PLpgSQL_rec *rec;
- int i;
- int arg_varnos[MAXFMGRARGS];
-
- /* ----------
- * Initialize the compiler
- * ----------
- */
- plpgsql_ns_init();
- plpgsql_ns_push(NULL);
- plpgsql_DumpExecTree = 0;
-
- datums_alloc = 128;
- plpgsql_nDatums = 0;
- plpgsql_Datums = palloc(sizeof(PLpgSQL_datum *) * datums_alloc);
- datums_last = 0;
-
- /* ----------
- * Lookup the pg_proc tuple by Oid
- * ----------
- */
- procTup = SearchSysCacheTuple(PROOID,
- ObjectIdGetDatum(fn_oid),
- 0, 0, 0);
- if (!HeapTupleIsValid(procTup)) {
- elog(ERROR, "plpgsql: cache lookup from pg_proc failed");
- }
-
- /* ----------
- * Setup the scanner input and error info
- * ----------
- */
- procStruct = (Form_pg_proc) GETSTRUCT(procTup);
- proc_source = textout(&(procStruct->prosrc));
- plpgsql_setinput(proc_source, functype);
- plpgsql_error_funcname = nameout(&(procStruct->proname));
- plpgsql_error_lineno = 0;
-
- /* ----------
- * Create the new function node
- * ----------
- */
- function = malloc(sizeof(PLpgSQL_function));
- memset(function, 0, sizeof(PLpgSQL_function));
- plpgsql_curr_compile = function;
-
- function->fn_functype = functype;
- function->fn_oid = fn_oid;
- function->fn_name = strdup(nameout(&(procStruct->proname)));
-
- switch (functype) {
- case T_FUNCTION:
- /* ----------
- * Normal function has a defined returntype
- * ----------
- */
- function->fn_rettype = procStruct->prorettype;
- function->fn_retset = procStruct->proretset;
-
- /* ----------
- * Lookup the functions return type
- * ----------
- */
- typeTup = SearchSysCacheTuple(TYPOID,
- ObjectIdGetDatum(procStruct->prorettype), 0, 0, 0);
-
- if (!HeapTupleIsValid(typeTup)) {
+ int parse_rc;
+ HeapTuple procTup;
+ Form_pg_proc procStruct;
+ HeapTuple typeTup;
+ Form_pg_type typeStruct;
+ char *proc_source;
+ PLpgSQL_function *function;
+ PLpgSQL_var *var;
+ PLpgSQL_row *row;
+ PLpgSQL_rec *rec;
+ int i;
+ int arg_varnos[MAXFMGRARGS];
+
+ /* ----------
+ * Initialize the compiler
+ * ----------
+ */
+ plpgsql_ns_init();
+ plpgsql_ns_push(NULL);
+ plpgsql_DumpExecTree = 0;
+
+ datums_alloc = 128;
+ plpgsql_nDatums = 0;
+ plpgsql_Datums = palloc(sizeof(PLpgSQL_datum *) * datums_alloc);
+ datums_last = 0;
+
+ /* ----------
+ * Lookup the pg_proc tuple by Oid
+ * ----------
+ */
+ procTup = SearchSysCacheTuple(PROOID,
+ ObjectIdGetDatum(fn_oid),
+ 0, 0, 0);
+ if (!HeapTupleIsValid(procTup))
+ elog(ERROR, "plpgsql: cache lookup from pg_proc failed");
+
+ /* ----------
+ * Setup the scanner input and error info
+ * ----------
+ */
+ procStruct = (Form_pg_proc) GETSTRUCT(procTup);
+ proc_source = textout(&(procStruct->prosrc));
+ plpgsql_setinput(proc_source, functype);
+ plpgsql_error_funcname = nameout(&(procStruct->proname));
+ plpgsql_error_lineno = 0;
+
+ /* ----------
+ * Create the new function node
+ * ----------
+ */
+ function = malloc(sizeof(PLpgSQL_function));
+ memset(function, 0, sizeof(PLpgSQL_function));
+ plpgsql_curr_compile = function;
+
+ function->fn_functype = functype;
+ function->fn_oid = fn_oid;
+ function->fn_name = strdup(nameout(&(procStruct->proname)));
+
+ switch (functype)
+ {
+ case T_FUNCTION:
+ /* ----------
+ * Normal function has a defined returntype
+ * ----------
+ */
+ function->fn_rettype = procStruct->prorettype;
+ function->fn_retset = procStruct->proretset;
+
+ /* ----------
+ * Lookup the functions return type
+ * ----------
+ */
+ typeTup = SearchSysCacheTuple(TYPOID,
+ ObjectIdGetDatum(procStruct->prorettype), 0, 0, 0);
+
+ if (!HeapTupleIsValid(typeTup))
+ {
+ plpgsql_comperrinfo();
+ elog(ERROR, "cache lookup for return type %d failed",
+ procStruct->prorettype);
+ }
+ typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
+ if (typeStruct->typrelid != InvalidOid)
+ function->fn_retistuple = true;
+ else
+ {
+ function->fn_retbyval = typeStruct->typbyval;
+ function->fn_rettyplen = typeStruct->typlen;
+ fmgr_info(typeStruct->typinput, &(function->fn_retinput));
+ }
+
+ /* ----------
+ * Create the variables for the procedures parameters
+ * ----------
+ */
+ for (i = 0; i < procStruct->pronargs; i++)
+ {
+ char buf[256];
+
+ /* ----------
+ * Get the parameters type
+ * ----------
+ */
+ typeTup = SearchSysCacheTuple(TYPOID,
+ ObjectIdGetDatum(procStruct->proargtypes[i]), 0, 0, 0);
+
+ if (!HeapTupleIsValid(typeTup))
+ {
+ plpgsql_comperrinfo();
+ elog(ERROR, "cache lookup for argument type %d failed",
+ procStruct->proargtypes[i]);
+ }
+ typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
+
+ if (typeStruct->typrelid != InvalidOid)
+ {
+ /* ----------
+ * For tuple type parameters, we set up a record
+ * of that type
+ * ----------
+ */
+ sprintf(buf, "%s%%rowtype", nameout(&(typeStruct->typname)));
+ if (plpgsql_parse_wordrowtype(buf) != T_ROW)
+ {
+ plpgsql_comperrinfo();
+ elog(ERROR, "cannot get tuple struct of argument %d", i + 1);
+ }
+
+ row = plpgsql_yylval.row;
+ sprintf(buf, "$%d", i + 1);
+
+ row->refname = strdup(buf);
+
+ plpgsql_adddatum((PLpgSQL_datum *) row);
+ plpgsql_ns_additem(PLPGSQL_NSTYPE_ROW, row->rowno, buf);
+
+ arg_varnos[i] = row->rowno;
+ }
+ else
+ {
+ /* ----------
+ * Normal parameters get a var node
+ * ----------
+ */
+ var = malloc(sizeof(PLpgSQL_var));
+ memset(var, 0, sizeof(PLpgSQL_var));
+ var->datatype = malloc(sizeof(PLpgSQL_type));
+ memset(var->datatype, 0, sizeof(PLpgSQL_type));
+
+ sprintf(buf, "$%d", i + 1);
+ var->dtype = PLPGSQL_DTYPE_VAR;
+ var->refname = strdup(buf);
+ var->lineno = 0;
+ var->datatype->typname = strdup(nameout(&(typeStruct->typname)));
+ var->datatype->typoid = procStruct->proargtypes[i];
+ fmgr_info(typeStruct->typinput, &(var->datatype->typinput));
+ var->datatype->typbyval = typeStruct->typbyval;
+ var->datatype->atttypmod = -1;
+ var->isconst = true;
+ var->notnull = false;
+ var->default_val = NULL;
+
+ plpgsql_adddatum((PLpgSQL_datum *) var);
+ plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, var->varno, buf);
+
+ arg_varnos[i] = var->varno;
+ }
+ }
+ break;
+
+ case T_TRIGGER:
+ /* ----------
+ * Trigger procedures return type is unknown yet
+ * ----------
+ */
+ function->fn_rettype = InvalidOid;
+ function->fn_retbyval = false;
+ function->fn_retistuple = true;
+ function->fn_retset = false;
+
+ /* ----------
+ * Add the record for referencing NEW
+ * ----------
+ */
+ rec = malloc(sizeof(PLpgSQL_rec));
+ memset(rec, 0, sizeof(PLpgSQL_rec));
+ rec->dtype = PLPGSQL_DTYPE_REC;
+ rec->refname = strdup("new");
+ plpgsql_adddatum((PLpgSQL_datum *) rec);
+ plpgsql_ns_additem(PLPGSQL_NSTYPE_REC, rec->recno, rec->refname);
+ function->new_varno = rec->recno;
+
+ /* ----------
+ * Add the record for referencing OLD
+ * ----------
+ */
+ rec = malloc(sizeof(PLpgSQL_rec));
+ memset(rec, 0, sizeof(PLpgSQL_rec));
+ rec->dtype = PLPGSQL_DTYPE_REC;
+ rec->refname = strdup("old");
+ plpgsql_adddatum((PLpgSQL_datum *) rec);
+ plpgsql_ns_additem(PLPGSQL_NSTYPE_REC, rec->recno, rec->refname);
+ function->old_varno = rec->recno;
+
+ /* ----------
+ * Add the variable tg_name
+ * ----------
+ */
+ var = malloc(sizeof(PLpgSQL_var));
+ memset(var, 0, sizeof(PLpgSQL_var));
+
+ var->dtype = PLPGSQL_DTYPE_VAR;
+ var->refname = strdup("tg_name");
+ var->lineno = 0;
+ plpgsql_parse_word("name");
+ var->datatype = plpgsql_yylval.dtype;
+ var->isconst = false;
+ var->notnull = false;
+ var->default_val = NULL;
+
+ plpgsql_adddatum((PLpgSQL_datum *) var);
+ plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, var->varno, var->refname);
+ function->tg_name_varno = var->varno;
+
+ /* ----------
+ * Add the variable tg_when
+ * ----------
+ */
+ var = malloc(sizeof(PLpgSQL_var));
+ memset(var, 0, sizeof(PLpgSQL_var));
+
+ var->dtype = PLPGSQL_DTYPE_VAR;
+ var->refname = strdup("tg_when");
+ var->lineno = 0;
+ plpgsql_parse_word("text");
+ var->datatype = plpgsql_yylval.dtype;
+ var->isconst = false;
+ var->notnull = false;
+ var->default_val = NULL;
+
+ plpgsql_adddatum((PLpgSQL_datum *) var);
+ plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, var->varno, var->refname);
+ function->tg_when_varno = var->varno;
+
+ /* ----------
+ * Add the variable tg_level
+ * ----------
+ */
+ var = malloc(sizeof(PLpgSQL_var));
+ memset(var, 0, sizeof(PLpgSQL_var));
+
+ var->dtype = PLPGSQL_DTYPE_VAR;
+ var->refname = strdup("tg_level");
+ var->lineno = 0;
+ plpgsql_parse_word("text");
+ var->datatype = plpgsql_yylval.dtype;
+ var->isconst = false;
+ var->notnull = false;
+ var->default_val = NULL;
+
+ plpgsql_adddatum((PLpgSQL_datum *) var);
+ plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, var->varno, var->refname);
+ function->tg_level_varno = var->varno;
+
+ /* ----------
+ * Add the variable tg_op
+ * ----------
+ */
+ var = malloc(sizeof(PLpgSQL_var));
+ memset(var, 0, sizeof(PLpgSQL_var));
+
+ var->dtype = PLPGSQL_DTYPE_VAR;
+ var->refname = strdup("tg_op");
+ var->lineno = 0;
+ plpgsql_parse_word("text");
+ var->datatype = plpgsql_yylval.dtype;
+ var->isconst = false;
+ var->notnull = false;
+ var->default_val = NULL;
+
+ plpgsql_adddatum((PLpgSQL_datum *) var);
+ plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, var->varno, var->refname);
+ function->tg_op_varno = var->varno;
+
+ /* ----------
+ * Add the variable tg_relid
+ * ----------
+ */
+ var = malloc(sizeof(PLpgSQL_var));
+ memset(var, 0, sizeof(PLpgSQL_var));
+
+ var->dtype = PLPGSQL_DTYPE_VAR;
+ var->refname = strdup("tg_relid");
+ var->lineno = 0;
+ plpgsql_parse_word("oid");
+ var->datatype = plpgsql_yylval.dtype;
+ var->isconst = false;
+ var->notnull = false;
+ var->default_val = NULL;
+
+ plpgsql_adddatum((PLpgSQL_datum *) var);
+ plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, var->varno, var->refname);
+ function->tg_relid_varno = var->varno;
+
+ /* ----------
+ * Add the variable tg_relname
+ * ----------
+ */
+ var = malloc(sizeof(PLpgSQL_var));
+ memset(var, 0, sizeof(PLpgSQL_var));
+
+ var->dtype = PLPGSQL_DTYPE_VAR;
+ var->refname = strdup("tg_relname");
+ var->lineno = 0;
+ plpgsql_parse_word("name");
+ var->datatype = plpgsql_yylval.dtype;
+ var->isconst = false;
+ var->notnull = false;
+ var->default_val = NULL;
+
+ plpgsql_adddatum((PLpgSQL_datum *) var);
+ plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, var->varno, var->refname);
+ function->tg_relname_varno = var->varno;
+
+ /* ----------
+ * Add the variable tg_nargs
+ * ----------
+ */
+ var = malloc(sizeof(PLpgSQL_var));
+ memset(var, 0, sizeof(PLpgSQL_var));
+
+ var->dtype = PLPGSQL_DTYPE_VAR;
+ var->refname = strdup("tg_nargs");
+ var->lineno = 0;
+ plpgsql_parse_word("int4");
+ var->datatype = plpgsql_yylval.dtype;
+ var->isconst = false;
+ var->notnull = false;
+ var->default_val = NULL;
+
+ plpgsql_adddatum((PLpgSQL_datum *) var);
+ plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, var->varno, var->refname);
+ function->tg_nargs_varno = var->varno;
+
+ break;
+
+ default:
+ elog(ERROR, "unknown function type %d in plpgsql_compile()",
+ functype);
+ break;
+ }
+
+ /* ----------
+ * Create the magic found variable indicating if the
+ * last FOR or SELECT statement returned data
+ * ----------
+ */
+ var = malloc(sizeof(PLpgSQL_var));
+ memset(var, 0, sizeof(PLpgSQL_var));
+
+ var->dtype = PLPGSQL_DTYPE_VAR;
+ var->refname = strdup("found");
+ var->lineno = 0;
+ plpgsql_parse_word("bool");
+ var->datatype = plpgsql_yylval.dtype;
+ var->isconst = false;
+ var->notnull = false;
+ var->default_val = NULL;
+
+ plpgsql_adddatum((PLpgSQL_datum *) var);
+ plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, var->varno, strdup("found"));
+ function->found_varno = var->varno;
+
+ /* ----------
+ * Forget about the above created variables
+ * ----------
+ */
+ plpgsql_add_initdatums(NULL);
+
+ /* ----------
+ * Now parse the functions text
+ * ----------
+ */
+ parse_rc = plpgsql_yyparse();
+ if (parse_rc != 0)
+ {
plpgsql_comperrinfo();
- elog(ERROR, "cache lookup for return type %d failed",
- procStruct->prorettype);
- }
- typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
- if (typeStruct->typrelid != InvalidOid) {
- function->fn_retistuple = true;
- } else {
- function->fn_retbyval = typeStruct->typbyval;
- function->fn_rettyplen = typeStruct->typlen;
- fmgr_info(typeStruct->typinput, &(function->fn_retinput));
- }
-
- /* ----------
- * Create the variables for the procedures parameters
- * ----------
- */
- for (i = 0; i < procStruct->pronargs; i++) {
- char buf[256];
+ elog(ERROR, "plpgsql: parser returned %d ???", parse_rc);
+ }
- /* ----------
- * Get the parameters type
- * ----------
- */
- typeTup = SearchSysCacheTuple(TYPOID,
- ObjectIdGetDatum(procStruct->proargtypes[i]), 0, 0, 0);
+ /* ----------
+ * If that was successful, complete the functions info.
+ * ----------
+ */
+ function->fn_nargs = procStruct->pronargs;
+ for (i = 0; i < function->fn_nargs; i++)
+ function->fn_argvarnos[i] = arg_varnos[i];
+ function->ndatums = plpgsql_nDatums;
+ function->datums = malloc(sizeof(PLpgSQL_datum *) * plpgsql_nDatums);
+ for (i = 0; i < plpgsql_nDatums; i++)
+ function->datums[i] = plpgsql_Datums[i];
+ function->action = plpgsql_yylval.program;
- if (!HeapTupleIsValid(typeTup)) {
- plpgsql_comperrinfo();
- elog(ERROR, "cache lookup for argument type %d failed",
- procStruct->proargtypes[i]);
- }
- typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
- if (typeStruct->typrelid != InvalidOid) {
- /* ----------
- * For tuple type parameters, we set up a record
- * of that type
- * ----------
- */
- sprintf(buf, "%s%%rowtype", nameout(&(typeStruct->typname)));
- if (plpgsql_parse_wordrowtype(buf) != T_ROW) {
- plpgsql_comperrinfo();
- elog(ERROR, "cannot get tuple struct of argument %d", i + 1);
- }
-
- row = plpgsql_yylval.row;
- sprintf(buf, "$%d", i + 1);
-
- row->refname = strdup(buf);
-
- plpgsql_adddatum((PLpgSQL_datum *)row);
- plpgsql_ns_additem(PLPGSQL_NSTYPE_ROW, row->rowno, buf);
-
- arg_varnos[i] = row->rowno;
- } else {
- /* ----------
- * Normal parameters get a var node
- * ----------
- */
- var = malloc(sizeof(PLpgSQL_var));
- memset(var, 0, sizeof(PLpgSQL_var));
- var->datatype = malloc(sizeof(PLpgSQL_type));
- memset(var->datatype, 0, sizeof(PLpgSQL_type));
-
- sprintf(buf, "$%d", i + 1);
- var->dtype = PLPGSQL_DTYPE_VAR;
- var->refname = strdup(buf);
- var->lineno = 0;
- var->datatype->typname = strdup(nameout(&(typeStruct->typname)));
- var->datatype->typoid = procStruct->proargtypes[i];
- fmgr_info(typeStruct->typinput, &(var->datatype->typinput));
- var->datatype->typbyval = typeStruct->typbyval;
- var->datatype->atttypmod = -1;
- var->isconst = true;
- var->notnull = false;
- var->default_val = NULL;
-
- plpgsql_adddatum((PLpgSQL_datum *)var);
- plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, var->varno, buf);
-
- arg_varnos[i] = var->varno;
- }
- }
- break;
-
- case T_TRIGGER:
- /* ----------
- * Trigger procedures return type is unknown yet
- * ----------
- */
- function->fn_rettype = InvalidOid;
- function->fn_retbyval = false;
- function->fn_retistuple = true;
- function->fn_retset = false;
-
- /* ----------
- * Add the record for referencing NEW
- * ----------
- */
- rec = malloc(sizeof(PLpgSQL_rec));
- memset(rec, 0, sizeof(PLpgSQL_rec));
- rec->dtype = PLPGSQL_DTYPE_REC;
- rec->refname = strdup("new");
- plpgsql_adddatum((PLpgSQL_datum *)rec);
- plpgsql_ns_additem(PLPGSQL_NSTYPE_REC, rec->recno, rec->refname);
- function->new_varno = rec->recno;
-
- /* ----------
- * Add the record for referencing OLD
- * ----------
- */
- rec = malloc(sizeof(PLpgSQL_rec));
- memset(rec, 0, sizeof(PLpgSQL_rec));
- rec->dtype = PLPGSQL_DTYPE_REC;
- rec->refname = strdup("old");
- plpgsql_adddatum((PLpgSQL_datum *)rec);
- plpgsql_ns_additem(PLPGSQL_NSTYPE_REC, rec->recno, rec->refname);
- function->old_varno = rec->recno;
-
- /* ----------
- * Add the variable tg_name
- * ----------
- */
- var = malloc(sizeof(PLpgSQL_var));
- memset(var, 0, sizeof(PLpgSQL_var));
-
- var->dtype = PLPGSQL_DTYPE_VAR;
- var->refname = strdup("tg_name");
- var->lineno = 0;
- plpgsql_parse_word("name");
- var->datatype = plpgsql_yylval.dtype;
- var->isconst = false;
- var->notnull = false;
- var->default_val = NULL;
-
- plpgsql_adddatum((PLpgSQL_datum *)var);
- plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, var->varno, var->refname);
- function->tg_name_varno = var->varno;
-
- /* ----------
- * Add the variable tg_when
- * ----------
- */
- var = malloc(sizeof(PLpgSQL_var));
- memset(var, 0, sizeof(PLpgSQL_var));
-
- var->dtype = PLPGSQL_DTYPE_VAR;
- var->refname = strdup("tg_when");
- var->lineno = 0;
- plpgsql_parse_word("text");
- var->datatype = plpgsql_yylval.dtype;
- var->isconst = false;
- var->notnull = false;
- var->default_val = NULL;
-
- plpgsql_adddatum((PLpgSQL_datum *)var);
- plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, var->varno, var->refname);
- function->tg_when_varno = var->varno;
-
- /* ----------
- * Add the variable tg_level
- * ----------
- */
- var = malloc(sizeof(PLpgSQL_var));
- memset(var, 0, sizeof(PLpgSQL_var));
-
- var->dtype = PLPGSQL_DTYPE_VAR;
- var->refname = strdup("tg_level");
- var->lineno = 0;
- plpgsql_parse_word("text");
- var->datatype = plpgsql_yylval.dtype;
- var->isconst = false;
- var->notnull = false;
- var->default_val = NULL;
-
- plpgsql_adddatum((PLpgSQL_datum *)var);
- plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, var->varno, var->refname);
- function->tg_level_varno = var->varno;
-
- /* ----------
- * Add the variable tg_op
- * ----------
- */
- var = malloc(sizeof(PLpgSQL_var));
- memset(var, 0, sizeof(PLpgSQL_var));
-
- var->dtype = PLPGSQL_DTYPE_VAR;
- var->refname = strdup("tg_op");
- var->lineno = 0;
- plpgsql_parse_word("text");
- var->datatype = plpgsql_yylval.dtype;
- var->isconst = false;
- var->notnull = false;
- var->default_val = NULL;
-
- plpgsql_adddatum((PLpgSQL_datum *)var);
- plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, var->varno, var->refname);
- function->tg_op_varno = var->varno;
-
- /* ----------
- * Add the variable tg_relid
- * ----------
- */
- var = malloc(sizeof(PLpgSQL_var));
- memset(var, 0, sizeof(PLpgSQL_var));
-
- var->dtype = PLPGSQL_DTYPE_VAR;
- var->refname = strdup("tg_relid");
- var->lineno = 0;
- plpgsql_parse_word("oid");
- var->datatype = plpgsql_yylval.dtype;
- var->isconst = false;
- var->notnull = false;
- var->default_val = NULL;
-
- plpgsql_adddatum((PLpgSQL_datum *)var);
- plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, var->varno, var->refname);
- function->tg_relid_varno = var->varno;
-
- /* ----------
- * Add the variable tg_relname
- * ----------
- */
- var = malloc(sizeof(PLpgSQL_var));
- memset(var, 0, sizeof(PLpgSQL_var));
-
- var->dtype = PLPGSQL_DTYPE_VAR;
- var->refname = strdup("tg_relname");
- var->lineno = 0;
- plpgsql_parse_word("name");
- var->datatype = plpgsql_yylval.dtype;
- var->isconst = false;
- var->notnull = false;
- var->default_val = NULL;
-
- plpgsql_adddatum((PLpgSQL_datum *)var);
- plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, var->varno, var->refname);
- function->tg_relname_varno = var->varno;
-
- /* ----------
- * Add the variable tg_nargs
- * ----------
- */
- var = malloc(sizeof(PLpgSQL_var));
- memset(var, 0, sizeof(PLpgSQL_var));
-
- var->dtype = PLPGSQL_DTYPE_VAR;
- var->refname = strdup("tg_nargs");
- var->lineno = 0;
- plpgsql_parse_word("int4");
- var->datatype = plpgsql_yylval.dtype;
- var->isconst = false;
- var->notnull = false;
- var->default_val = NULL;
-
- plpgsql_adddatum((PLpgSQL_datum *)var);
- plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, var->varno, var->refname);
- function->tg_nargs_varno = var->varno;
-
- break;
-
- default:
- elog(ERROR, "unknown function type %d in plpgsql_compile()",
- functype);
- break;
- }
-
- /* ----------
- * Create the magic found variable indicating if the
- * last FOR or SELECT statement returned data
- * ----------
- */
- var = malloc(sizeof(PLpgSQL_var));
- memset(var, 0, sizeof(PLpgSQL_var));
-
- var->dtype = PLPGSQL_DTYPE_VAR;
- var->refname = strdup("found");
- var->lineno = 0;
- plpgsql_parse_word("bool");
- var->datatype = plpgsql_yylval.dtype;
- var->isconst = false;
- var->notnull = false;
- var->default_val = NULL;
-
- plpgsql_adddatum((PLpgSQL_datum *)var);
- plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, var->varno, strdup("found"));
- function->found_varno = var->varno;
-
- /* ----------
- * Forget about the above created variables
- * ----------
- */
- plpgsql_add_initdatums(NULL);
-
- /* ----------
- * Now parse the functions text
- * ----------
- */
- parse_rc = plpgsql_yyparse();
- if (parse_rc != 0) {
- plpgsql_comperrinfo();
- elog(ERROR, "plpgsql: parser returned %d ???", parse_rc);
- }
-
- /* ----------
- * If that was successful, complete the functions info.
- * ----------
- */
- function->fn_nargs = procStruct->pronargs;
- for (i = 0; i < function->fn_nargs; i++) {
- function->fn_argvarnos[i] = arg_varnos[i];
- }
- function->ndatums = plpgsql_nDatums;
- function->datums = malloc(sizeof(PLpgSQL_datum *) * plpgsql_nDatums);
- for (i = 0; i < plpgsql_nDatums; i++) {
- function->datums[i] = plpgsql_Datums[i];
- }
- function->action = plpgsql_yylval.program;
-
-
- /* ----------
- * Finally return the compiled function
- * ----------
- */
- if (plpgsql_DumpExecTree) {
- plpgsql_dumptree(function);
- }
- return function;
+ /* ----------
+ * Finally return the compiled function
+ * ----------
+ */
+ if (plpgsql_DumpExecTree)
+ plpgsql_dumptree(function);
+ return function;
}
@@ -517,114 +524,120 @@ PLpgSQL_function *plpgsql_compile(Oid fn_oid, int functype)
* keyword rule.
* ----------
*/
-int plpgsql_parse_word(char *word)
+int
+plpgsql_parse_word(char *word)
{
- PLpgSQL_nsitem *nse;
- char *cp;
- HeapTuple typeTup;
- Form_pg_type typeStruct;
- char *typeXlated;
-
- /* ----------
- * We do our lookups case insensitive
- * ----------
- */
- cp = plpgsql_tolower(pstrdup(word));
-
- /* ----------
- * Special handling when compiling triggers
- * ----------
- */
- if (plpgsql_curr_compile->fn_functype == T_TRIGGER) {
- if (!strcmp(cp, "tg_argv")) {
- int save_spacescanned = plpgsql_SpaceScanned;
- PLpgSQL_trigarg *trigarg;
-
- trigarg = malloc(sizeof(PLpgSQL_trigarg));
- memset(trigarg, 0, sizeof(PLpgSQL_trigarg));
- trigarg->dtype = PLPGSQL_DTYPE_TRIGARG;
-
- if (plpgsql_yylex() != '[') {
- plpgsql_yyerror("expected [");
- }
-
- trigarg->argnum = plpgsql_read_expression(']', "]");
-
- plpgsql_adddatum((PLpgSQL_datum *)trigarg);
- plpgsql_yylval.trigarg = trigarg;
-
- plpgsql_SpaceScanned = save_spacescanned;
- return T_TGARGV;
- }
- }
-
- /* ----------
- * Do a lookup on the compilers namestack
- * ----------
- */
- nse = plpgsql_ns_lookup(cp, NULL);
- if (nse != NULL) {
- pfree(cp);
- switch (nse->itemtype) {
- case PLPGSQL_NSTYPE_LABEL:
- return T_LABEL;
+ PLpgSQL_nsitem *nse;
+ char *cp;
+ HeapTuple typeTup;
+ Form_pg_type typeStruct;
+ char *typeXlated;
- case PLPGSQL_NSTYPE_VAR:
- plpgsql_yylval.var = (PLpgSQL_var *)(plpgsql_Datums[nse->itemno]);
- return T_VARIABLE;
+ /* ----------
+ * We do our lookups case insensitive
+ * ----------
+ */
+ cp = plpgsql_tolower(pstrdup(word));
+
+ /* ----------
+ * Special handling when compiling triggers
+ * ----------
+ */
+ if (plpgsql_curr_compile->fn_functype == T_TRIGGER)
+ {
+ if (!strcmp(cp, "tg_argv"))
+ {
+ int save_spacescanned = plpgsql_SpaceScanned;
+ PLpgSQL_trigarg *trigarg;
+
+ trigarg = malloc(sizeof(PLpgSQL_trigarg));
+ memset(trigarg, 0, sizeof(PLpgSQL_trigarg));
+ trigarg->dtype = PLPGSQL_DTYPE_TRIGARG;
+
+ if (plpgsql_yylex() != '[')
+ plpgsql_yyerror("expected [");
- case PLPGSQL_NSTYPE_REC:
- plpgsql_yylval.rec = (PLpgSQL_rec *)(plpgsql_Datums[nse->itemno]);
- return T_RECORD;
+ trigarg->argnum = plpgsql_read_expression(']', "]");
- case PLPGSQL_NSTYPE_ROW:
- plpgsql_yylval.row = (PLpgSQL_row *)(plpgsql_Datums[nse->itemno]);
- return T_ROW;
+ plpgsql_adddatum((PLpgSQL_datum *) trigarg);
+ plpgsql_yylval.trigarg = trigarg;
- default:
- return T_ERROR;
+ plpgsql_SpaceScanned = save_spacescanned;
+ return T_TGARGV;
+ }
}
- }
-
- /* ----------
- * Try to find a data type with that name, but ignore
- * pg_type entries that are in fact class types.
- * ----------
- */
- typeXlated = xlateSqlType(cp);
- typeTup = SearchSysCacheTuple(TYPNAME,
- PointerGetDatum(typeXlated), 0, 0, 0);
- if (HeapTupleIsValid(typeTup)) {
- PLpgSQL_type *typ;
-
- typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
-
- if (typeStruct->typrelid != InvalidOid) {
- pfree(cp);
- return T_WORD;
+
+ /* ----------
+ * Do a lookup on the compilers namestack
+ * ----------
+ */
+ nse = plpgsql_ns_lookup(cp, NULL);
+ if (nse != NULL)
+ {
+ pfree(cp);
+ switch (nse->itemtype)
+ {
+ case PLPGSQL_NSTYPE_LABEL:
+ return T_LABEL;
+
+ case PLPGSQL_NSTYPE_VAR:
+ plpgsql_yylval.var = (PLpgSQL_var *) (plpgsql_Datums[nse->itemno]);
+ return T_VARIABLE;
+
+ case PLPGSQL_NSTYPE_REC:
+ plpgsql_yylval.rec = (PLpgSQL_rec *) (plpgsql_Datums[nse->itemno]);
+ return T_RECORD;
+
+ case PLPGSQL_NSTYPE_ROW:
+ plpgsql_yylval.row = (PLpgSQL_row *) (plpgsql_Datums[nse->itemno]);
+ return T_ROW;
+
+ default:
+ return T_ERROR;
+ }
}
- typ = (PLpgSQL_type *)malloc(sizeof(PLpgSQL_type));
+ /* ----------
+ * Try to find a data type with that name, but ignore
+ * pg_type entries that are in fact class types.
+ * ----------
+ */
+ typeXlated = xlateSqlType(cp);
+ typeTup = SearchSysCacheTuple(TYPNAME,
+ PointerGetDatum(typeXlated), 0, 0, 0);
+ if (HeapTupleIsValid(typeTup))
+ {
+ PLpgSQL_type *typ;
+
+ typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
- typ->typname = strdup(nameout(&(typeStruct->typname)));
- typ->typoid = typeTup->t_oid;
- fmgr_info(typeStruct->typinput, &(typ->typinput));
- typ->typbyval = typeStruct->typbyval;
- typ->atttypmod = -1;
+ if (typeStruct->typrelid != InvalidOid)
+ {
+ pfree(cp);
+ return T_WORD;
+ }
- plpgsql_yylval.dtype = typ;
+ typ = (PLpgSQL_type *) malloc(sizeof(PLpgSQL_type));
+
+ typ->typname = strdup(nameout(&(typeStruct->typname)));
+ typ->typoid = typeTup->t_oid;
+ fmgr_info(typeStruct->typinput, &(typ->typinput));
+ typ->typbyval = typeStruct->typbyval;
+ typ->atttypmod = -1;
+
+ plpgsql_yylval.dtype = typ;
+
+ pfree(cp);
+ return T_DTYPE;
+ }
+ /* ----------
+ * Nothing found - up to now it's a word without any
+ * special meaning for us.
+ * ----------
+ */
pfree(cp);
- return T_DTYPE;
- }
-
- /* ----------
- * Nothing found - up to now it's a word without any
- * special meaning for us.
- * ----------
- */
- pfree(cp);
- return T_WORD;
+ return T_WORD;
}
@@ -633,116 +646,123 @@ int plpgsql_parse_word(char *word)
* separated by a dot.
* ----------
*/
-int plpgsql_parse_dblword(char *string)
+int
+plpgsql_parse_dblword(char *string)
{
- char *word1;
- char *word2;
- PLpgSQL_nsitem *ns;
-
- /* ----------
- * Convert to lower case and separate the words
- * ----------
- */
- word1 = plpgsql_tolower(pstrdup(string));
- word2 = strchr(word1, '.');
- *word2++ = '\0';
-
- /* ----------
- * Lookup the first word
- * ----------
- */
- ns = plpgsql_ns_lookup(word1, NULL);
- if (ns == NULL) {
- pfree(word1);
- return T_ERROR;
- }
-
- switch (ns->itemtype) {
- case PLPGSQL_NSTYPE_LABEL:
- /* ----------
- * First word is a label, so second word could be
- * a variable, record or row in that bodies namestack.
- * Anything else could only be something in a query
- * given to the SPI manager and T_ERROR will get eaten
- * up by the collector routines.
- * ----------
- */
- ns = plpgsql_ns_lookup(word2, word1);
- if (ns == NULL) {
- pfree(word1);
- return T_ERROR;
- }
- switch (ns->itemtype) {
- case PLPGSQL_NSTYPE_VAR:
- plpgsql_yylval.var = (PLpgSQL_var *)(plpgsql_Datums[ns->itemno]);
- pfree(word1);
- return T_VARIABLE;
-
- case PLPGSQL_NSTYPE_REC:
- plpgsql_yylval.rec = (PLpgSQL_rec *)(plpgsql_Datums[ns->itemno]);
- pfree(word1);
- return T_RECORD;
-
- case PLPGSQL_NSTYPE_ROW:
- plpgsql_yylval.row = (PLpgSQL_row *)(plpgsql_Datums[ns->itemno]);
- pfree(word1);
- return T_ROW;
-
- default:
- pfree(word1);
- return T_ERROR;
- }
-
- case PLPGSQL_NSTYPE_REC:
- {
- /* ----------
- * First word is a record name, so second word
- * must be a field in this record.
- * ----------
- */
- PLpgSQL_recfield *new;
-
- new = malloc(sizeof(PLpgSQL_recfield));
- new->dtype = PLPGSQL_DTYPE_RECFIELD;
- new->fieldname = strdup(word2);
- new->recno = ns->itemno;
+ char *word1;
+ char *word2;
+ PLpgSQL_nsitem *ns;
- plpgsql_adddatum((PLpgSQL_datum *)new);
+ /* ----------
+ * Convert to lower case and separate the words
+ * ----------
+ */
+ word1 = plpgsql_tolower(pstrdup(string));
+ word2 = strchr(word1, '.');
+ *word2++ = '\0';
+ /* ----------
+ * Lookup the first word
+ * ----------
+ */
+ ns = plpgsql_ns_lookup(word1, NULL);
+ if (ns == NULL)
+ {
pfree(word1);
- plpgsql_yylval.recfield = new;
- return T_RECFIELD;
- }
+ return T_ERROR;
+ }
- case PLPGSQL_NSTYPE_ROW:
- {
- /* ----------
- * First word is a row name, so second word must
- * be a field in this row.
- * ----------
- */
- PLpgSQL_row *row;
- int i;
+ switch (ns->itemtype)
+ {
+ case PLPGSQL_NSTYPE_LABEL:
+ /* ----------
+ * First word is a label, so second word could be
+ * a variable, record or row in that bodies namestack.
+ * Anything else could only be something in a query
+ * given to the SPI manager and T_ERROR will get eaten
+ * up by the collector routines.
+ * ----------
+ */
+ ns = plpgsql_ns_lookup(word2, word1);
+ if (ns == NULL)
+ {
+ pfree(word1);
+ return T_ERROR;
+ }
+ switch (ns->itemtype)
+ {
+ case PLPGSQL_NSTYPE_VAR:
+ plpgsql_yylval.var = (PLpgSQL_var *) (plpgsql_Datums[ns->itemno]);
+ pfree(word1);
+ return T_VARIABLE;
+
+ case PLPGSQL_NSTYPE_REC:
+ plpgsql_yylval.rec = (PLpgSQL_rec *) (plpgsql_Datums[ns->itemno]);
+ pfree(word1);
+ return T_RECORD;
+
+ case PLPGSQL_NSTYPE_ROW:
+ plpgsql_yylval.row = (PLpgSQL_row *) (plpgsql_Datums[ns->itemno]);
+ pfree(word1);
+ return T_ROW;
+
+ default:
+ pfree(word1);
+ return T_ERROR;
+ }
+
+ case PLPGSQL_NSTYPE_REC:
+ {
+ /* ----------
+ * First word is a record name, so second word
+ * must be a field in this record.
+ * ----------
+ */
+ PLpgSQL_recfield *new;
+
+ new = malloc(sizeof(PLpgSQL_recfield));
+ new->dtype = PLPGSQL_DTYPE_RECFIELD;
+ new->fieldname = strdup(word2);
+ new->recno = ns->itemno;
+
+ plpgsql_adddatum((PLpgSQL_datum *) new);
+
+ pfree(word1);
+ plpgsql_yylval.recfield = new;
+ return T_RECFIELD;
+ }
+
+ case PLPGSQL_NSTYPE_ROW:
+ {
+ /* ----------
+ * First word is a row name, so second word must
+ * be a field in this row.
+ * ----------
+ */
+ PLpgSQL_row *row;
+ int i;
+
+ row = (PLpgSQL_row *) (plpgsql_Datums[ns->itemno]);
+ for (i = 0; i < row->nfields; i++)
+ {
+ if (!strcmp(row->fieldnames[i], word2))
+ {
+ plpgsql_yylval.var = (PLpgSQL_var *) (plpgsql_Datums[row->varnos[i]]);
+ pfree(word1);
+ return T_VARIABLE;
+ }
+ }
+ plpgsql_comperrinfo();
+ elog(ERROR, "row %s doesn't have a field %s",
+ word1, word2);
+ }
- row = (PLpgSQL_row *)(plpgsql_Datums[ns->itemno]);
- for (i = 0; i < row->nfields; i++) {
- if (!strcmp(row->fieldnames[i], word2)) {
- plpgsql_yylval.var = (PLpgSQL_var *)(plpgsql_Datums[row->varnos[i]]);
- pfree(word1);
- return T_VARIABLE;
- }
- }
- plpgsql_comperrinfo();
- elog(ERROR, "row %s doesn't have a field %s",
- word1, word2);
- }
-
- default:
- break;
- }
+ default:
+ break;
+ }
- pfree(word1);
- return T_ERROR;
+ pfree(word1);
+ return T_ERROR;
}
@@ -751,99 +771,106 @@ int plpgsql_parse_dblword(char *string)
* separated by dots.
* ----------
*/
-int plpgsql_parse_tripword(char *string)
+int
+plpgsql_parse_tripword(char *string)
{
- char *word1;
- char *word2;
- char *word3;
- PLpgSQL_nsitem *ns;
-
- /* ----------
- * Convert to lower case and separate the words
- * ----------
- */
- word1 = plpgsql_tolower(pstrdup(string));
- word2 = strchr(word1, '.');
- *word2++ = '\0';
- word3 = strchr(word2, '.');
- *word3++ = '\0';
-
- /* ----------
- * Lookup the first word - it must be a label
- * ----------
- */
- ns = plpgsql_ns_lookup(word1, NULL);
- if (ns == NULL) {
- pfree(word1);
- return T_ERROR;
- }
- if (ns->itemtype != PLPGSQL_NSTYPE_LABEL) {
- pfree(word1);
- return T_ERROR;
- }
-
- /* ----------
- * First word is a label, so second word could be
- * a record or row
- * ----------
- */
- ns = plpgsql_ns_lookup(word2, word1);
- if (ns == NULL) {
- pfree(word1);
- return T_ERROR;
- }
+ char *word1;
+ char *word2;
+ char *word3;
+ PLpgSQL_nsitem *ns;
- switch (ns->itemtype) {
- case PLPGSQL_NSTYPE_REC:
- {
- /* ----------
- * This word is a record name, so third word
- * must be a field in this record.
- * ----------
- */
- PLpgSQL_recfield *new;
-
- new = malloc(sizeof(PLpgSQL_recfield));
- new->dtype = PLPGSQL_DTYPE_RECFIELD;
- new->fieldname = strdup(word3);
- new->recno = ns->itemno;
-
- plpgsql_adddatum((PLpgSQL_datum *)new);
+ /* ----------
+ * Convert to lower case and separate the words
+ * ----------
+ */
+ word1 = plpgsql_tolower(pstrdup(string));
+ word2 = strchr(word1, '.');
+ *word2++ = '\0';
+ word3 = strchr(word2, '.');
+ *word3++ = '\0';
+ /* ----------
+ * Lookup the first word - it must be a label
+ * ----------
+ */
+ ns = plpgsql_ns_lookup(word1, NULL);
+ if (ns == NULL)
+ {
+ pfree(word1);
+ return T_ERROR;
+ }
+ if (ns->itemtype != PLPGSQL_NSTYPE_LABEL)
+ {
pfree(word1);
- plpgsql_yylval.recfield = new;
- return T_RECFIELD;
- }
+ return T_ERROR;
+ }
- case PLPGSQL_NSTYPE_ROW:
- {
- /* ----------
- * This word is a row name, so third word must
- * be a field in this row.
- * ----------
- */
- PLpgSQL_row *row;
- int i;
+ /* ----------
+ * First word is a label, so second word could be
+ * a record or row
+ * ----------
+ */
+ ns = plpgsql_ns_lookup(word2, word1);
+ if (ns == NULL)
+ {
+ pfree(word1);
+ return T_ERROR;
+ }
- row = (PLpgSQL_row *)(plpgsql_Datums[ns->itemno]);
- for (i = 0; i < row->nfields; i++) {
- if (!strcmp(row->fieldnames[i], word3)) {
- plpgsql_yylval.var = (PLpgSQL_var *)(plpgsql_Datums[row->varnos[i]]);
- pfree(word1);
- return T_VARIABLE;
- }
- }
- plpgsql_comperrinfo();
- elog(ERROR, "row %s.%s doesn't have a field %s",
- word1, word2, word3);
- }
+ switch (ns->itemtype)
+ {
+ case PLPGSQL_NSTYPE_REC:
+ {
+ /* ----------
+ * This word is a record name, so third word
+ * must be a field in this record.
+ * ----------
+ */
+ PLpgSQL_recfield *new;
+
+ new = malloc(sizeof(PLpgSQL_recfield));
+ new->dtype = PLPGSQL_DTYPE_RECFIELD;
+ new->fieldname = strdup(word3);
+ new->recno = ns->itemno;
+
+ plpgsql_adddatum((PLpgSQL_datum *) new);
+
+ pfree(word1);
+ plpgsql_yylval.recfield = new;
+ return T_RECFIELD;
+ }
+
+ case PLPGSQL_NSTYPE_ROW:
+ {
+ /* ----------
+ * This word is a row name, so third word must
+ * be a field in this row.
+ * ----------
+ */
+ PLpgSQL_row *row;
+ int i;
+
+ row = (PLpgSQL_row *) (plpgsql_Datums[ns->itemno]);
+ for (i = 0; i < row->nfields; i++)
+ {
+ if (!strcmp(row->fieldnames[i], word3))
+ {
+ plpgsql_yylval.var = (PLpgSQL_var *) (plpgsql_Datums[row->varnos[i]]);
+ pfree(word1);
+ return T_VARIABLE;
+ }
+ }
+ plpgsql_comperrinfo();
+ elog(ERROR, "row %s.%s doesn't have a field %s",
+ word1, word2, word3);
+ }
- default:
- break;
- }
+ default:
+ break;
+ }
- pfree(word1);
- return T_ERROR;
+ pfree(word1);
+ return T_ERROR;
}
@@ -852,83 +879,88 @@ int plpgsql_parse_tripword(char *string)
* a variable name or a basetype.
* ----------
*/
-int plpgsql_parse_wordtype(char *word)
+int
+plpgsql_parse_wordtype(char *word)
{
- PLpgSQL_nsitem *nse;
- char *cp;
- HeapTuple typeTup;
- Form_pg_type typeStruct;
- char *typeXlated;
- bool old_nsstate;
-
- /* ----------
- * We do our lookups case insensitive
- * ----------
- */
- cp = plpgsql_tolower(pstrdup(word));
- *(strchr(cp, '%')) = '\0';
-
- /* ----------
- * Do a lookup on the compilers namestack.
- * But ensure it moves up to the toplevel.
- * ----------
- */
- old_nsstate = plpgsql_ns_setlocal(false);
- nse = plpgsql_ns_lookup(cp, NULL);
- plpgsql_ns_setlocal(old_nsstate);
-
- if (nse != NULL) {
- pfree(cp);
- switch (nse->itemtype) {
- case PLPGSQL_NSTYPE_VAR:
- plpgsql_yylval.dtype = ((PLpgSQL_var *)(plpgsql_Datums[nse->itemno]))->datatype;
- return T_DTYPE;
+ PLpgSQL_nsitem *nse;
+ char *cp;
+ HeapTuple typeTup;
+ Form_pg_type typeStruct;
+ char *typeXlated;
+ bool old_nsstate;
- default:
- return T_ERROR;
- }
- }
-
- /* ----------
- * Word wasn't found on the namestack.
- * Try to find a data type with that name, but ignore
- * pg_type entries that are in fact class types.
- * ----------
- */
- typeXlated = xlateSqlType(cp);
- typeTup = SearchSysCacheTuple(TYPNAME,
- PointerGetDatum(typeXlated), 0, 0, 0);
- if (HeapTupleIsValid(typeTup)) {
- PLpgSQL_type *typ;
-
- typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
-
- if (typeStruct->typrelid != InvalidOid) {
- pfree(cp);
- return T_ERROR;
+ /* ----------
+ * We do our lookups case insensitive
+ * ----------
+ */
+ cp = plpgsql_tolower(pstrdup(word));
+ *(strchr(cp, '%')) = '\0';
+
+ /* ----------
+ * Do a lookup on the compilers namestack.
+ * But ensure it moves up to the toplevel.
+ * ----------
+ */
+ old_nsstate = plpgsql_ns_setlocal(false);
+ nse = plpgsql_ns_lookup(cp, NULL);
+ plpgsql_ns_setlocal(old_nsstate);
+
+ if (nse != NULL)
+ {
+ pfree(cp);
+ switch (nse->itemtype)
+ {
+ case PLPGSQL_NSTYPE_VAR:
+ plpgsql_yylval.dtype = ((PLpgSQL_var *) (plpgsql_Datums[nse->itemno]))->datatype;
+ return T_DTYPE;
+
+ default:
+ return T_ERROR;
+ }
}
- typ = (PLpgSQL_type *)malloc(sizeof(PLpgSQL_type));
+ /* ----------
+ * Word wasn't found on the namestack.
+ * Try to find a data type with that name, but ignore
+ * pg_type entries that are in fact class types.
+ * ----------
+ */
+ typeXlated = xlateSqlType(cp);
+ typeTup = SearchSysCacheTuple(TYPNAME,
+ PointerGetDatum(typeXlated), 0, 0, 0);
+ if (HeapTupleIsValid(typeTup))
+ {
+ PLpgSQL_type *typ;
- typ->typname = strdup(nameout(&(typeStruct->typname)));
- typ->typoid = typeTup->t_oid;
- fmgr_info(typeStruct->typinput, &(typ->typinput));
- typ->typbyval = typeStruct->typbyval;
- typ->atttypmod = -1;
+ typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
- plpgsql_yylval.dtype = typ;
+ if (typeStruct->typrelid != InvalidOid)
+ {
+ pfree(cp);
+ return T_ERROR;
+ }
+
+ typ = (PLpgSQL_type *) malloc(sizeof(PLpgSQL_type));
+
+ typ->typname = strdup(nameout(&(typeStruct->typname)));
+ typ->typoid = typeTup->t_oid;
+ fmgr_info(typeStruct->typinput, &(typ->typinput));
+ typ->typbyval = typeStruct->typbyval;
+ typ->atttypmod = -1;
+ plpgsql_yylval.dtype = typ;
+
+ pfree(cp);
+ return T_DTYPE;
+ }
+
+ /* ----------
+ * Nothing found - up to now it's a word without any
+ * special meaning for us.
+ * ----------
+ */
pfree(cp);
- return T_DTYPE;
- }
-
- /* ----------
- * Nothing found - up to now it's a word without any
- * special meaning for us.
- * ----------
- */
- pfree(cp);
- return T_ERROR;
+ return T_ERROR;
}
@@ -936,125 +968,134 @@ int plpgsql_parse_wordtype(char *word)
* plpgsql_parse_dblwordtype Same lookup for word.word%TYPE
* ----------
*/
-int plpgsql_parse_dblwordtype(char *string)
+int
+plpgsql_parse_dblwordtype(char *string)
{
- char *word1;
- char *word2;
- PLpgSQL_nsitem *nse;
- bool old_nsstate;
- HeapTuple classtup;
- Form_pg_class classStruct;
- HeapTuple attrtup;
- Form_pg_attribute attrStruct;
- HeapTuple typetup;
- Form_pg_type typeStruct;
- PLpgSQL_type *typ;
-
-
- /* ----------
- * Convert to lower case and separate the words
- * ----------
- */
- word1 = plpgsql_tolower(pstrdup(string));
- word2 = strchr(word1, '.');
- *word2++ = '\0';
- *(strchr(word2, '%')) = '\0';
-
- /* ----------
- * Lookup the first word
- * ----------
- */
- nse = plpgsql_ns_lookup(word1, NULL);
-
- /* ----------
- * If this is a label lookup the second word in that
- * labels namestack level
- * ----------
- */
- if (nse != NULL) {
- if (nse->itemtype == PLPGSQL_NSTYPE_LABEL) {
- old_nsstate = plpgsql_ns_setlocal(false);
- nse = plpgsql_ns_lookup(word2, word1);
- plpgsql_ns_setlocal(old_nsstate);
-
- pfree(word1);
-
- if (nse != NULL) {
- switch (nse->itemtype) {
- case PLPGSQL_NSTYPE_VAR:
- plpgsql_yylval.dtype = ((PLpgSQL_var *)(plpgsql_Datums[nse->itemno]))->datatype;
- return T_DTYPE;
-
- default:
+ char *word1;
+ char *word2;
+ PLpgSQL_nsitem *nse;
+ bool old_nsstate;
+ HeapTuple classtup;
+ Form_pg_class classStruct;
+ HeapTuple attrtup;
+ Form_pg_attribute attrStruct;
+ HeapTuple typetup;
+ Form_pg_type typeStruct;
+ PLpgSQL_type *typ;
+
+
+ /* ----------
+ * Convert to lower case and separate the words
+ * ----------
+ */
+ word1 = plpgsql_tolower(pstrdup(string));
+ word2 = strchr(word1, '.');
+ *word2++ = '\0';
+ *(strchr(word2, '%')) = '\0';
+
+ /* ----------
+ * Lookup the first word
+ * ----------
+ */
+ nse = plpgsql_ns_lookup(word1, NULL);
+
+ /* ----------
+ * If this is a label lookup the second word in that
+ * labels namestack level
+ * ----------
+ */
+ if (nse != NULL)
+ {
+ if (nse->itemtype == PLPGSQL_NSTYPE_LABEL)
+ {
+ old_nsstate = plpgsql_ns_setlocal(false);
+ nse = plpgsql_ns_lookup(word2, word1);
+ plpgsql_ns_setlocal(old_nsstate);
+
+ pfree(word1);
+
+ if (nse != NULL)
+ {
+ switch (nse->itemtype)
+ {
+ case PLPGSQL_NSTYPE_VAR:
+ plpgsql_yylval.dtype = ((PLpgSQL_var *) (plpgsql_Datums[nse->itemno]))->datatype;
+ return T_DTYPE;
+
+ default:
+ return T_ERROR;
+ }
+ }
return T_ERROR;
}
- }
- return T_ERROR;
+ pfree(word1);
+ return T_ERROR;
}
- pfree(word1);
- return T_ERROR;
- }
-
- /* ----------
- * First word could also be a table name
- * ----------
- */
- classtup = SearchSysCacheTuple(RELNAME,
- PointerGetDatum(word1), 0, 0, 0);
- if (!HeapTupleIsValid(classtup)) {
- pfree(word1);
- return T_ERROR;
- }
-
- /* ----------
- * It must be a (shared) relation class
- * ----------
- */
- classStruct = (Form_pg_class)GETSTRUCT(classtup);
- if (classStruct->relkind != 'r' && classStruct->relkind != 's') {
- pfree(word1);
- return T_ERROR;
- }
-
- /* ----------
- * Fetch the named table field and it's type
- * ----------
- */
- attrtup = SearchSysCacheTuple(ATTNAME,
- ObjectIdGetDatum(classtup->t_oid),
- PointerGetDatum(word2), 0, 0);
- if (!HeapTupleIsValid(attrtup)) {
- pfree(word1);
- return T_ERROR;
- }
- attrStruct = (Form_pg_attribute)GETSTRUCT(attrtup);
- typetup = SearchSysCacheTuple(TYPOID,
- ObjectIdGetDatum(attrStruct->atttypid), 0, 0, 0);
- if (!HeapTupleIsValid(typetup)) {
- plpgsql_comperrinfo();
- elog(ERROR, "cache lookup for type %d of %s.%s failed",
- attrStruct->atttypid, word1, word2);
- }
+ /* ----------
+ * First word could also be a table name
+ * ----------
+ */
+ classtup = SearchSysCacheTuple(RELNAME,
+ PointerGetDatum(word1), 0, 0, 0);
+ if (!HeapTupleIsValid(classtup))
+ {
+ pfree(word1);
+ return T_ERROR;
+ }
+
+ /* ----------
+ * It must be a (shared) relation class
+ * ----------
+ */
+ classStruct = (Form_pg_class) GETSTRUCT(classtup);
+ if (classStruct->relkind != 'r' && classStruct->relkind != 's')
+ {
+ pfree(word1);
+ return T_ERROR;
+ }
- /* ----------
- * Found that - build a compiler type struct and return it
- * ----------
- */
- typeStruct = (Form_pg_type)GETSTRUCT(typetup);
+ /* ----------
+ * Fetch the named table field and it's type
+ * ----------
+ */
+ attrtup = SearchSysCacheTuple(ATTNAME,
+ ObjectIdGetDatum(classtup->t_oid),
+ PointerGetDatum(word2), 0, 0);
+ if (!HeapTupleIsValid(attrtup))
+ {
+ pfree(word1);
+ return T_ERROR;
+ }
+ attrStruct = (Form_pg_attribute) GETSTRUCT(attrtup);
- typ = (PLpgSQL_type *)malloc(sizeof(PLpgSQL_type));
+ typetup = SearchSysCacheTuple(TYPOID,
+ ObjectIdGetDatum(attrStruct->atttypid), 0, 0, 0);
+ if (!HeapTupleIsValid(typetup))
+ {
+ plpgsql_comperrinfo();
+ elog(ERROR, "cache lookup for type %d of %s.%s failed",
+ attrStruct->atttypid, word1, word2);
+ }
- typ->typname = strdup(nameout(&(typeStruct->typname)));
- typ->typoid = typetup->t_oid;
- fmgr_info(typeStruct->typinput, &(typ->typinput));
- typ->typbyval = typeStruct->typbyval;
- typ->atttypmod = attrStruct->atttypmod;
+ /* ----------
+ * Found that - build a compiler type struct and return it
+ * ----------
+ */
+ typeStruct = (Form_pg_type) GETSTRUCT(typetup);
- plpgsql_yylval.dtype = typ;
+ typ = (PLpgSQL_type *) malloc(sizeof(PLpgSQL_type));
- pfree(word1);
- return T_DTYPE;
+ typ->typname = strdup(nameout(&(typeStruct->typname)));
+ typ->typoid = typetup->t_oid;
+ fmgr_info(typeStruct->typinput, &(typ->typinput));
+ typ->typbyval = typeStruct->typbyval;
+ typ->atttypmod = attrStruct->atttypmod;
+
+ plpgsql_yylval.dtype = typ;
+
+ pfree(word1);
+ return T_DTYPE;
}
@@ -1063,138 +1104,145 @@ int plpgsql_parse_dblwordtype(char *string)
* So word must be a table name.
* ----------
*/
-int plpgsql_parse_wordrowtype(char *string)
+int
+plpgsql_parse_wordrowtype(char *string)
{
- HeapTuple classtup;
- Form_pg_class classStruct;
- HeapTuple typetup;
- Form_pg_type typeStruct;
- HeapTuple attrtup;
- Form_pg_attribute attrStruct;
- char *word1;
- char *cp;
- int i;
- PLpgSQL_row *row;
- PLpgSQL_var *var;
-
- /* ----------
- * Get the word in lower case and fetch the pg_class tuple.
- * ----------
- */
- word1 = plpgsql_tolower(pstrdup(string));
- cp = strchr(word1, '%');
- *cp = '\0';
-
- classtup = SearchSysCacheTuple(RELNAME,
- PointerGetDatum(word1), 0, 0, 0);
- if (!HeapTupleIsValid(classtup)) {
- plpgsql_comperrinfo();
- elog(ERROR, "%s: no such class", word1);
- }
- classStruct = (Form_pg_class)GETSTRUCT(classtup);
- if (classStruct->relkind != 'r' && classStruct->relkind != 's') {
- plpgsql_comperrinfo();
- elog(ERROR, "%s isn't a table", word1);
- }
-
- /* ----------
- * Fetch the tables pg_type tuple too
- * ----------
- */
- typetup = SearchSysCacheTuple(TYPNAME,
- PointerGetDatum(word1), 0, 0, 0);
- if (!HeapTupleIsValid(typetup)) {
- plpgsql_comperrinfo();
- elog(ERROR, "cache lookup for %s in pg_type failed", word1);
- }
-
- /* ----------
- * Create a row datum entry and all the required variables
- * that it will point to.
- * ----------
- */
- row = malloc(sizeof(PLpgSQL_row));
- memset(row, 0, sizeof(PLpgSQL_row));
-
- row->dtype = PLPGSQL_DTYPE_ROW;
- row->nfields = classStruct->relnatts;
- row->rowtypeclass = typetup->t_oid;
- row->fieldnames = malloc(sizeof(char *) * row->nfields);
- row->varnos = malloc(sizeof(int) * row->nfields);
-
- for (i = 0; i < row->nfields; i++) {
+ HeapTuple classtup;
+ Form_pg_class classStruct;
+ HeapTuple typetup;
+ Form_pg_type typeStruct;
+ HeapTuple attrtup;
+ Form_pg_attribute attrStruct;
+ char *word1;
+ char *cp;
+ int i;
+ PLpgSQL_row *row;
+ PLpgSQL_var *var;
+
/* ----------
- * Get the attribute and it's type
+ * Get the word in lower case and fetch the pg_class tuple.
* ----------
*/
- attrtup = SearchSysCacheTuple(ATTNUM,
- ObjectIdGetDatum(classtup->t_oid),
- (Datum)(i + 1), 0, 0);
- if (!HeapTupleIsValid(attrtup)) {
- plpgsql_comperrinfo();
- elog(ERROR, "cache lookup for attribute %d of class %s failed",
- i + 1, word1);
+ word1 = plpgsql_tolower(pstrdup(string));
+ cp = strchr(word1, '%');
+ *cp = '\0';
+
+ classtup = SearchSysCacheTuple(RELNAME,
+ PointerGetDatum(word1), 0, 0, 0);
+ if (!HeapTupleIsValid(classtup))
+ {
+ plpgsql_comperrinfo();
+ elog(ERROR, "%s: no such class", word1);
}
- attrStruct = (Form_pg_attribute)GETSTRUCT(attrtup);
-
- typetup = SearchSysCacheTuple(TYPOID,
- ObjectIdGetDatum(attrStruct->atttypid), 0, 0, 0);
- if (!HeapTupleIsValid(typetup)) {
- plpgsql_comperrinfo();
- elog(ERROR, "cache lookup for type %d of %s.%s failed",
- attrStruct->atttypid, word1,
- nameout(&(attrStruct->attname)));
+ classStruct = (Form_pg_class) GETSTRUCT(classtup);
+ if (classStruct->relkind != 'r' && classStruct->relkind != 's')
+ {
+ plpgsql_comperrinfo();
+ elog(ERROR, "%s isn't a table", word1);
}
- typeStruct = (Form_pg_type)GETSTRUCT(typetup);
- cp = strdup(nameout(&(attrStruct->attname)));
+ /* ----------
+ * Fetch the tables pg_type tuple too
+ * ----------
+ */
+ typetup = SearchSysCacheTuple(TYPNAME,
+ PointerGetDatum(word1), 0, 0, 0);
+ if (!HeapTupleIsValid(typetup))
+ {
+ plpgsql_comperrinfo();
+ elog(ERROR, "cache lookup for %s in pg_type failed", word1);
+ }
/* ----------
- * Create the internal variable
- * We know if the table definitions contain a default value
- * or if the field is declared in the table as NOT NULL. But
- * it's possible to create a table field as NOT NULL without
- * a default value and that would lead to problems later when
- * initializing the variables due to entering a block at
- * execution time. Thus we ignore this information for now.
+ * Create a row datum entry and all the required variables
+ * that it will point to.
* ----------
*/
- var = malloc(sizeof(PLpgSQL_var));
- var->dtype = PLPGSQL_DTYPE_VAR;
- var->refname = malloc(strlen(word1) + strlen(cp) + 2);
- strcpy(var->refname, word1);
- strcat(var->refname, ".");
- strcat(var->refname, cp);
- var->datatype = malloc(sizeof(PLpgSQL_type));
- var->datatype->typname = strdup(nameout(&(typeStruct->typname)));
- var->datatype->typoid = typetup->t_oid;
- fmgr_info(typeStruct->typinput, &(var->datatype->typinput));
- var->datatype->typbyval = typeStruct->typbyval;
- var->datatype->atttypmod = attrStruct->atttypmod;
- var->isconst = false;
- var->notnull = false;
- var->default_val = NULL;
- var->value = (Datum)0;
- var->isnull = true;
- var->shouldfree = false;
+ row = malloc(sizeof(PLpgSQL_row));
+ memset(row, 0, sizeof(PLpgSQL_row));
+
+ row->dtype = PLPGSQL_DTYPE_ROW;
+ row->nfields = classStruct->relnatts;
+ row->rowtypeclass = typetup->t_oid;
+ row->fieldnames = malloc(sizeof(char *) * row->nfields);
+ row->varnos = malloc(sizeof(int) * row->nfields);
+
+ for (i = 0; i < row->nfields; i++)
+ {
+ /* ----------
+ * Get the attribute and it's type
+ * ----------
+ */
+ attrtup = SearchSysCacheTuple(ATTNUM,
+ ObjectIdGetDatum(classtup->t_oid),
+ (Datum) (i + 1), 0, 0);
+ if (!HeapTupleIsValid(attrtup))
+ {
+ plpgsql_comperrinfo();
+ elog(ERROR, "cache lookup for attribute %d of class %s failed",
+ i + 1, word1);
+ }
+ attrStruct = (Form_pg_attribute) GETSTRUCT(attrtup);
+
+ typetup = SearchSysCacheTuple(TYPOID,
+ ObjectIdGetDatum(attrStruct->atttypid), 0, 0, 0);
+ if (!HeapTupleIsValid(typetup))
+ {
+ plpgsql_comperrinfo();
+ elog(ERROR, "cache lookup for type %d of %s.%s failed",
+ attrStruct->atttypid, word1,
+ nameout(&(attrStruct->attname)));
+ }
+ typeStruct = (Form_pg_type) GETSTRUCT(typetup);
+
+ cp = strdup(nameout(&(attrStruct->attname)));
+
+ /* ----------
+ * Create the internal variable
+ * We know if the table definitions contain a default value
+ * or if the field is declared in the table as NOT NULL. But
+ * it's possible to create a table field as NOT NULL without
+ * a default value and that would lead to problems later when
+ * initializing the variables due to entering a block at
+ * execution time. Thus we ignore this information for now.
+ * ----------
+ */
+ var = malloc(sizeof(PLpgSQL_var));
+ var->dtype = PLPGSQL_DTYPE_VAR;
+ var->refname = malloc(strlen(word1) + strlen(cp) + 2);
+ strcpy(var->refname, word1);
+ strcat(var->refname, ".");
+ strcat(var->refname, cp);
+ var->datatype = malloc(sizeof(PLpgSQL_type));
+ var->datatype->typname = strdup(nameout(&(typeStruct->typname)));
+ var->datatype->typoid = typetup->t_oid;
+ fmgr_info(typeStruct->typinput, &(var->datatype->typinput));
+ var->datatype->typbyval = typeStruct->typbyval;
+ var->datatype->atttypmod = attrStruct->atttypmod;
+ var->isconst = false;
+ var->notnull = false;
+ var->default_val = NULL;
+ var->value = (Datum) 0;
+ var->isnull = true;
+ var->shouldfree = false;
+
+ plpgsql_adddatum((PLpgSQL_datum *) var);
- plpgsql_adddatum((PLpgSQL_datum *)var);
+ /* ----------
+ * Add the variable to the row.
+ * ----------
+ */
+ row->fieldnames[i] = cp;
+ row->varnos[i] = var->varno;
+ }
/* ----------
- * Add the variable to the row.
+ * Return the complete row definition
* ----------
*/
- row->fieldnames[i] = cp;
- row->varnos[i] = var->varno;
- }
+ plpgsql_yylval.row = row;
- /* ----------
- * Return the complete row definition
- * ----------
- */
- plpgsql_yylval.row = row;
-
- return T_ROW;
+ return T_ROW;
}
@@ -1203,15 +1251,17 @@ int plpgsql_parse_wordrowtype(char *string)
* to the compilers datum list.
* ----------
*/
-void plpgsql_adddatum(PLpgSQL_datum *new)
+void
+plpgsql_adddatum(PLpgSQL_datum * new)
{
- if (plpgsql_nDatums == datums_alloc) {
- datums_alloc *= 2;
- plpgsql_Datums = repalloc(plpgsql_Datums, sizeof(PLpgSQL_datum *) * datums_alloc);
- }
+ if (plpgsql_nDatums == datums_alloc)
+ {
+ datums_alloc *= 2;
+ plpgsql_Datums = repalloc(plpgsql_Datums, sizeof(PLpgSQL_datum *) * datums_alloc);
+ }
- new->dno = plpgsql_nDatums;
- plpgsql_Datums[plpgsql_nDatums++] = new;
+ new->dno = plpgsql_nDatums;
+ plpgsql_Datums[plpgsql_nDatums++] = new;
}
@@ -1223,39 +1273,45 @@ void plpgsql_adddatum(PLpgSQL_datum *new)
* reinitialize when entered.
* ----------
*/
-int plpgsql_add_initdatums(int **varnos)
+int
+plpgsql_add_initdatums(int **varnos)
{
- int i;
- int n = 0;
-
- for (i = datums_last; i < plpgsql_nDatums; i++) {
- switch (plpgsql_Datums[i]->dtype) {
- case PLPGSQL_DTYPE_VAR:
- n++;
- break;
-
- default:
- break;
+ int i;
+ int n = 0;
+
+ for (i = datums_last; i < plpgsql_nDatums; i++)
+ {
+ switch (plpgsql_Datums[i]->dtype)
+ {
+ case PLPGSQL_DTYPE_VAR:
+ n++;
+ break;
+
+ default:
+ break;
+ }
}
- }
-
- if (varnos != NULL) {
- *varnos = (int *)malloc(sizeof(int) * n);
- n = 0;
- for (i = datums_last; i < plpgsql_nDatums; i++) {
- switch (plpgsql_Datums[i]->dtype) {
- case PLPGSQL_DTYPE_VAR:
- (*varnos)[n++] = plpgsql_Datums[i]->dno;
-
- default:
- break;
- }
+ if (varnos != NULL)
+ {
+ *varnos = (int *) malloc(sizeof(int) * n);
+
+ n = 0;
+ for (i = datums_last; i < plpgsql_nDatums; i++)
+ {
+ switch (plpgsql_Datums[i]->dtype)
+ {
+ case PLPGSQL_DTYPE_VAR:
+ (*varnos)[n++] = plpgsql_Datums[i]->dno;
+
+ default:
+ break;
+ }
+ }
}
- }
- datums_last = plpgsql_nDatums;
- return n;
+ datums_last = plpgsql_nDatums;
+ return n;
}
@@ -1264,10 +1320,11 @@ int plpgsql_add_initdatums(int **varnos)
* during compile.
* ----------
*/
-void plpgsql_comperrinfo()
+void
+plpgsql_comperrinfo()
{
- elog(NOTICE, "plpgsql: ERROR during compile of %s near line %d",
- plpgsql_error_funcname, plpgsql_error_lineno);
+ elog(NOTICE, "plpgsql: ERROR during compile of %s near line %d",
+ plpgsql_error_funcname, plpgsql_error_lineno);
}
@@ -1276,11 +1333,12 @@ void plpgsql_comperrinfo()
* ---------
*/
-void plpgsql_yyerror(const char *s)
+void
+plpgsql_yyerror(const char *s)
{
- plpgsql_error_lineno = plpgsql_yylineno;
- plpgsql_comperrinfo();
- elog(ERROR, "%s at or near \"%s\"", s, plpgsql_yytext);
+ plpgsql_error_lineno = plpgsql_yylineno;
+ plpgsql_comperrinfo();
+ elog(ERROR, "%s at or near \"%s\"", s, plpgsql_yytext);
}
@@ -1294,20 +1352,18 @@ void plpgsql_yyerror(const char *s)
static char *
xlateSqlType(char *name)
{
- if (!strcasecmp(name,"int")
- || !strcasecmp(name,"integer"))
- return "int4";
- else if (!strcasecmp(name, "smallint"))
- return "int2";
- else if (!strcasecmp(name, "real")
- || !strcasecmp(name, "float"))
- return "float8";
- else if (!strcasecmp(name, "interval"))
- return "timespan";
- else if (!strcasecmp(name, "boolean"))
- return "bool";
- else
- return name;
-} /* xlateSqlType() */
-
-
+ if (!strcasecmp(name, "int")
+ || !strcasecmp(name, "integer"))
+ return "int4";
+ else if (!strcasecmp(name, "smallint"))
+ return "int2";
+ else if (!strcasecmp(name, "real")
+ || !strcasecmp(name, "float"))
+ return "float8";
+ else if (!strcasecmp(name, "interval"))
+ return "timespan";
+ else if (!strcasecmp(name, "boolean"))
+ return "bool";
+ else
+ return name;
+} /* xlateSqlType() */
diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c
index 9c43f90ef50..b414d15f943 100644
--- a/src/pl/plpgsql/src/pl_exec.c
+++ b/src/pl/plpgsql/src/pl_exec.c
@@ -3,35 +3,35 @@
* procedural language
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.2 1998/09/01 03:29:05 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.3 1998/09/01 04:40:22 momjian Exp $
*
- * This software is copyrighted by Jan Wieck - Hamburg.
+ * This software is copyrighted by Jan Wieck - Hamburg.
*
- * The author hereby grants permission to use, copy, modify,
- * distribute, and license this software and its documentation
- * for any purpose, provided that existing copyright notices are
- * retained in all copies and that this notice is included
- * verbatim in any distributions. No written agreement, license,
- * or royalty fee is required for any of the authorized uses.
- * Modifications to this software may be copyrighted by their
- * author and need not follow the licensing terms described
- * here, provided that the new terms are clearly indicated on
- * the first page of each file where they apply.
+ * The author hereby grants permission to use, copy, modify,
+ * distribute, and license this software and its documentation
+ * for any purpose, provided that existing copyright notices are
+ * retained in all copies and that this notice is included
+ * verbatim in any distributions. No written agreement, license,
+ * or royalty fee is required for any of the authorized uses.
+ * Modifications to this software may be copyrighted by their
+ * author and need not follow the licensing terms described
+ * here, provided that the new terms are clearly indicated on
+ * the first page of each file where they apply.
*
- * IN NO EVENT SHALL THE AUTHOR OR DISTRIBUTORS BE LIABLE TO ANY
- * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR
- * CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS
- * SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN
- * IF THE AUTHOR HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
+ * IN NO EVENT SHALL THE AUTHOR OR DISTRIBUTORS BE LIABLE TO ANY
+ * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR
+ * CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS
+ * SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN
+ * IF THE AUTHOR HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
*
- * THE AUTHOR AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
- * PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON
- * AN "AS IS" BASIS, AND THE AUTHOR AND DISTRIBUTORS HAVE NO
- * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
- * ENHANCEMENTS, OR MODIFICATIONS.
+ * THE AUTHOR AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON
+ * AN "AS IS" BASIS, AND THE AUTHOR AND DISTRIBUTORS HAVE NO
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
+ * ENHANCEMENTS, OR MODIFICATIONS.
*
**********************************************************************/
@@ -69,75 +69,75 @@
* It's ugly - Jan
************************************************************/
#if defined(nextstep)
-#define sigjmp_buf jmp_buf
-#define sigsetjmp(x,y) setjmp(x)
-#define siglongjmp longjmp
+#define sigjmp_buf jmp_buf
+#define sigsetjmp(x,y) setjmp(x)
+#define siglongjmp longjmp
#endif
extern sigjmp_buf Warn_restart; /* in tcop/postgres.c */
-static PLpgSQL_function *error_info_func = NULL;
-static PLpgSQL_stmt *error_info_stmt = NULL;
-static char *error_info_text = NULL;
+static PLpgSQL_function *error_info_func = NULL;
+static PLpgSQL_stmt *error_info_stmt = NULL;
+static char *error_info_text = NULL;
/************************************************************
* Local function forward declarations
************************************************************/
-static PLpgSQL_var *copy_var(PLpgSQL_var *var);
-static PLpgSQL_rec *copy_rec(PLpgSQL_rec *rec);
-
-static int exec_stmt_block(PLpgSQL_execstate *estate,
- PLpgSQL_stmt_block *block);
-static int exec_stmts(PLpgSQL_execstate *estate,
- PLpgSQL_stmts *stmts);
-static int exec_stmt(PLpgSQL_execstate *estate,
- PLpgSQL_stmt *stmt);
-static int exec_stmt_assign(PLpgSQL_execstate *estate,
- PLpgSQL_stmt_assign *stmt);
-static int exec_stmt_if(PLpgSQL_execstate *estate,
- PLpgSQL_stmt_if *stmt);
-static int exec_stmt_loop(PLpgSQL_execstate *estate,
- PLpgSQL_stmt_loop *stmt);
-static int exec_stmt_while(PLpgSQL_execstate *estate,
- PLpgSQL_stmt_while *stmt);
-static int exec_stmt_fori(PLpgSQL_execstate *estate,
- PLpgSQL_stmt_fori *stmt);
-static int exec_stmt_fors(PLpgSQL_execstate *estate,
- PLpgSQL_stmt_fors *stmt);
-static int exec_stmt_select(PLpgSQL_execstate *estate,
- PLpgSQL_stmt_select *stmt);
-static int exec_stmt_exit(PLpgSQL_execstate *estate,
- PLpgSQL_stmt_exit *stmt);
-static int exec_stmt_return(PLpgSQL_execstate *estate,
- PLpgSQL_stmt_return *stmt);
-static int exec_stmt_raise(PLpgSQL_execstate *estate,
- PLpgSQL_stmt_raise *stmt);
-static int exec_stmt_execsql(PLpgSQL_execstate *estate,
- PLpgSQL_stmt_execsql *stmt);
-
-static void exec_assign_expr(PLpgSQL_execstate *estate,
- PLpgSQL_datum *target,
- PLpgSQL_expr *expr);
-static void exec_assign_value(PLpgSQL_execstate *estate,
- PLpgSQL_datum *target,
- Datum value, Oid valtype, bool *isNull);
-static Datum exec_eval_expr(PLpgSQL_execstate *estate,
- PLpgSQL_expr *expr,
- bool *isNull,
- Oid *rettype);
-static int exec_run_select(PLpgSQL_execstate *estate,
- PLpgSQL_expr *expr, int maxtuples);
-static void exec_move_row(PLpgSQL_execstate *estate,
- PLpgSQL_rec *rec,
- PLpgSQL_row *row,
- HeapTuple tup, TupleDesc tupdesc);
-static Datum exec_cast_value(Datum value, Oid valtype,
- Oid reqtype,
+static PLpgSQL_var *copy_var(PLpgSQL_var * var);
+static PLpgSQL_rec *copy_rec(PLpgSQL_rec * rec);
+
+static int exec_stmt_block(PLpgSQL_execstate * estate,
+ PLpgSQL_stmt_block * block);
+static int exec_stmts(PLpgSQL_execstate * estate,
+ PLpgSQL_stmts * stmts);
+static int exec_stmt(PLpgSQL_execstate * estate,
+ PLpgSQL_stmt * stmt);
+static int exec_stmt_assign(PLpgSQL_execstate * estate,
+ PLpgSQL_stmt_assign * stmt);
+static int exec_stmt_if(PLpgSQL_execstate * estate,
+ PLpgSQL_stmt_if * stmt);
+static int exec_stmt_loop(PLpgSQL_execstate * estate,
+ PLpgSQL_stmt_loop * stmt);
+static int exec_stmt_while(PLpgSQL_execstate * estate,
+ PLpgSQL_stmt_while * stmt);
+static int exec_stmt_fori(PLpgSQL_execstate * estate,
+ PLpgSQL_stmt_fori * stmt);
+static int exec_stmt_fors(PLpgSQL_execstate * estate,
+ PLpgSQL_stmt_fors * stmt);
+static int exec_stmt_select(PLpgSQL_execstate * estate,
+ PLpgSQL_stmt_select * stmt);
+static int exec_stmt_exit(PLpgSQL_execstate * estate,
+ PLpgSQL_stmt_exit * stmt);
+static int exec_stmt_return(PLpgSQL_execstate * estate,
+ PLpgSQL_stmt_return * stmt);
+static int exec_stmt_raise(PLpgSQL_execstate * estate,
+ PLpgSQL_stmt_raise * stmt);
+static int exec_stmt_execsql(PLpgSQL_execstate * estate,
+ PLpgSQL_stmt_execsql * stmt);
+
+static void exec_assign_expr(PLpgSQL_execstate * estate,
+ PLpgSQL_datum * target,
+ PLpgSQL_expr * expr);
+static void exec_assign_value(PLpgSQL_execstate * estate,
+ PLpgSQL_datum * target,
+ Datum value, Oid valtype, bool *isNull);
+static Datum exec_eval_expr(PLpgSQL_execstate * estate,
+ PLpgSQL_expr * expr,
+ bool *isNull,
+ Oid *rettype);
+static int exec_run_select(PLpgSQL_execstate * estate,
+ PLpgSQL_expr * expr, int maxtuples);
+static void exec_move_row(PLpgSQL_execstate * estate,
+ PLpgSQL_rec * rec,
+ PLpgSQL_row * row,
+ HeapTuple tup, TupleDesc tupdesc);
+static Datum exec_cast_value(Datum value, Oid valtype,
+ Oid reqtype,
FmgrInfo *reqinput,
int16 reqtypmod,
bool *isnull);
-static void exec_set_found(PLpgSQL_execstate *estate, bool state);
+static void exec_set_found(PLpgSQL_execstate * estate, bool state);
/* ----------
@@ -145,275 +145,293 @@ static void exec_set_found(PLpgSQL_execstate *estate, bool state);
* function execution.
* ----------
*/
-Datum plpgsql_exec_function(PLpgSQL_function *func,
- FmgrValues *args, bool *isNull)
+Datum
+plpgsql_exec_function(PLpgSQL_function * func,
+ FmgrValues *args, bool *isNull)
{
- PLpgSQL_execstate estate;
- int i;
- sigjmp_buf save_restart;
- PLpgSQL_function *save_efunc;
- PLpgSQL_stmt *save_estmt;
- char *save_etext;
-
- /* ----------
- * Setup debug error info and catch elog()
- * ----------
- */
- save_efunc = error_info_func;
- save_estmt = error_info_stmt;
- save_etext = error_info_text;
-
- error_info_func = func;
- error_info_stmt = NULL;
- error_info_text = "while initialization of execution state";
-
- memcpy(&save_restart, &Warn_restart, sizeof(save_restart));
- if (sigsetjmp(Warn_restart, 1) != 0) {
- memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
+ PLpgSQL_execstate estate;
+ int i;
+ sigjmp_buf save_restart;
+ PLpgSQL_function *save_efunc;
+ PLpgSQL_stmt *save_estmt;
+ char *save_etext;
/* ----------
- * If we are the first of cascaded error catchings,
- * print where this happened
+ * Setup debug error info and catch elog()
* ----------
*/
- if (error_info_func != NULL) {
- elog(DEBUG, "Last error occured while executing PL/pgSQL function %s",
- error_info_func->fn_name);
- if (error_info_stmt != NULL) {
- char *stmttype;
- switch (error_info_stmt->cmd_type) {
- case PLPGSQL_STMT_BLOCK:
- stmttype = "blocks variable initialization";
- break;
- case PLPGSQL_STMT_ASSIGN:
- stmttype = "assignment";
- break;
- case PLPGSQL_STMT_IF:
- stmttype = "if";
- break;
- case PLPGSQL_STMT_LOOP:
- stmttype = "loop";
- break;
- case PLPGSQL_STMT_WHILE:
- stmttype = "while";
- break;
- case PLPGSQL_STMT_FORI:
- stmttype = "for with integer loopvar";
- break;
- case PLPGSQL_STMT_FORS:
- stmttype = "for over select rows";
- break;
- case PLPGSQL_STMT_SELECT:
- stmttype = "select into variables";
- break;
- case PLPGSQL_STMT_EXIT:
- stmttype = "exit";
- break;
- case PLPGSQL_STMT_RETURN:
- stmttype = "return";
- break;
- case PLPGSQL_STMT_RAISE:
- stmttype = "raise";
- break;
- case PLPGSQL_STMT_EXECSQL:
- stmttype = "SQL statement";
- break;
- default:
- stmttype = "unknown";
- break;
- }
- elog(DEBUG, "line %d at %s", error_info_stmt->lineno,
- stmttype);
- } else {
- if (error_info_text != NULL) {
- elog(DEBUG, "%s", error_info_text);
- } else {
- elog(DEBUG, "no more error information available");
- }
- }
+ save_efunc = error_info_func;
+ save_estmt = error_info_stmt;
+ save_etext = error_info_text;
- error_info_func = NULL;
- error_info_stmt = NULL;
- error_info_text = NULL;
- }
+ error_info_func = func;
+ error_info_stmt = NULL;
+ error_info_text = "while initialization of execution state";
- siglongjmp(Warn_restart, 1);
- }
-
-
- /* ----------
- * Setup the execution state
- * ----------
- */
- estate.retval = 0;
- estate.retisnull = false;
- estate.rettype = InvalidOid;
- estate.retistuple = func->fn_retistuple;
- estate.retisset = func->fn_retset;
- estate.exitlabel = NULL;
-
- estate.found_varno = func->found_varno;
- estate.ndatums = func->ndatums;
- estate.datums = palloc(sizeof(PLpgSQL_datum *) * estate.ndatums);
-
- /* ----------
- * Make local execution copies of all the datums
- * ----------
- */
- for (i = 0; i < func->ndatums; i++) {
- switch(func->datums[i]->dtype) {
- case PLPGSQL_DTYPE_VAR:
- estate.datums[i] = (PLpgSQL_datum *)
- copy_var((PLpgSQL_var *)(func->datums[i]));
- break;
-
- case PLPGSQL_DTYPE_REC:
- estate.datums[i] = (PLpgSQL_datum *)
- copy_rec((PLpgSQL_rec *)(func->datums[i]));
- break;
-
- case PLPGSQL_DTYPE_ROW:
- case PLPGSQL_DTYPE_RECFIELD:
- estate.datums[i] = func->datums[i];
- break;
-
- default:
- elog(ERROR, "unknown dtype %d in plpgsql_exec_function()",
- func->datums[i]->dtype);
- }
- }
-
- /* ----------
- * Put the actual call argument values into the variables
- * ----------
- */
- error_info_text = "while putting call arguments to local variables";
- for (i = 0; i < func->fn_nargs; i++) {
- int n = func->fn_argvarnos[i];
- switch(estate.datums[n]->dtype) {
- case PLPGSQL_DTYPE_VAR:
+ memcpy(&save_restart, &Warn_restart, sizeof(save_restart));
+ if (sigsetjmp(Warn_restart, 1) != 0)
+ {
+ memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
+
+ /* ----------
+ * If we are the first of cascaded error catchings,
+ * print where this happened
+ * ----------
+ */
+ if (error_info_func != NULL)
{
- PLpgSQL_var *var = (PLpgSQL_var *)estate.datums[n];
- var->value = (Datum)(args->data[i]);
- var->isnull = *isNull;
- var->shouldfree = false;
+ elog(DEBUG, "Last error occured while executing PL/pgSQL function %s",
+ error_info_func->fn_name);
+ if (error_info_stmt != NULL)
+ {
+ char *stmttype;
+
+ switch (error_info_stmt->cmd_type)
+ {
+ case PLPGSQL_STMT_BLOCK:
+ stmttype = "blocks variable initialization";
+ break;
+ case PLPGSQL_STMT_ASSIGN:
+ stmttype = "assignment";
+ break;
+ case PLPGSQL_STMT_IF:
+ stmttype = "if";
+ break;
+ case PLPGSQL_STMT_LOOP:
+ stmttype = "loop";
+ break;
+ case PLPGSQL_STMT_WHILE:
+ stmttype = "while";
+ break;
+ case PLPGSQL_STMT_FORI:
+ stmttype = "for with integer loopvar";
+ break;
+ case PLPGSQL_STMT_FORS:
+ stmttype = "for over select rows";
+ break;
+ case PLPGSQL_STMT_SELECT:
+ stmttype = "select into variables";
+ break;
+ case PLPGSQL_STMT_EXIT:
+ stmttype = "exit";
+ break;
+ case PLPGSQL_STMT_RETURN:
+ stmttype = "return";
+ break;
+ case PLPGSQL_STMT_RAISE:
+ stmttype = "raise";
+ break;
+ case PLPGSQL_STMT_EXECSQL:
+ stmttype = "SQL statement";
+ break;
+ default:
+ stmttype = "unknown";
+ break;
+ }
+ elog(DEBUG, "line %d at %s", error_info_stmt->lineno,
+ stmttype);
+ }
+ else
+ {
+ if (error_info_text != NULL)
+ elog(DEBUG, "%s", error_info_text);
+ else
+ elog(DEBUG, "no more error information available");
+ }
+
+ error_info_func = NULL;
+ error_info_stmt = NULL;
+ error_info_text = NULL;
}
- break;
- case PLPGSQL_DTYPE_ROW:
- {
- HeapTuple tup;
- TupleDesc tupdesc;
- PLpgSQL_row *row = (PLpgSQL_row *)estate.datums[n];
+ siglongjmp(Warn_restart, 1);
+ }
+
+
+ /* ----------
+ * Setup the execution state
+ * ----------
+ */
+ estate.retval = 0;
+ estate.retisnull = false;
+ estate.rettype = InvalidOid;
+ estate.retistuple = func->fn_retistuple;
+ estate.retisset = func->fn_retset;
+ estate.exitlabel = NULL;
- tup = ((TupleTableSlot *)(args->data[i]))->val;
- tupdesc = ((TupleTableSlot *)(args->data[i]))->ttc_tupleDescriptor;
+ estate.found_varno = func->found_varno;
+ estate.ndatums = func->ndatums;
+ estate.datums = palloc(sizeof(PLpgSQL_datum *) * estate.ndatums);
- exec_move_row(&estate, NULL, row, tup, tupdesc);
+ /* ----------
+ * Make local execution copies of all the datums
+ * ----------
+ */
+ for (i = 0; i < func->ndatums; i++)
+ {
+ switch (func->datums[i]->dtype)
+ {
+ case PLPGSQL_DTYPE_VAR:
+ estate.datums[i] = (PLpgSQL_datum *)
+ copy_var((PLpgSQL_var *) (func->datums[i]));
+ break;
+
+ case PLPGSQL_DTYPE_REC:
+ estate.datums[i] = (PLpgSQL_datum *)
+ copy_rec((PLpgSQL_rec *) (func->datums[i]));
+ break;
+
+ case PLPGSQL_DTYPE_ROW:
+ case PLPGSQL_DTYPE_RECFIELD:
+ estate.datums[i] = func->datums[i];
+ break;
+
+ default:
+ elog(ERROR, "unknown dtype %d in plpgsql_exec_function()",
+ func->datums[i]->dtype);
}
- break;
+ }
- default:
- elog(ERROR, "unknown dtype %d in plpgsql_exec_function()",
- func->datums[i]->dtype);
+ /* ----------
+ * Put the actual call argument values into the variables
+ * ----------
+ */
+ error_info_text = "while putting call arguments to local variables";
+ for (i = 0; i < func->fn_nargs; i++)
+ {
+ int n = func->fn_argvarnos[i];
+
+ switch (estate.datums[n]->dtype)
+ {
+ case PLPGSQL_DTYPE_VAR:
+ {
+ PLpgSQL_var *var = (PLpgSQL_var *) estate.datums[n];
+
+ var->value = (Datum) (args->data[i]);
+ var->isnull = *isNull;
+ var->shouldfree = false;
+ }
+ break;
+
+ case PLPGSQL_DTYPE_ROW:
+ {
+ HeapTuple tup;
+ TupleDesc tupdesc;
+ PLpgSQL_row *row = (PLpgSQL_row *) estate.datums[n];
+
+ tup = ((TupleTableSlot *) (args->data[i]))->val;
+ tupdesc = ((TupleTableSlot *) (args->data[i]))->ttc_tupleDescriptor;
+
+ exec_move_row(&estate, NULL, row, tup, tupdesc);
+ }
+ break;
+
+ default:
+ elog(ERROR, "unknown dtype %d in plpgsql_exec_function()",
+ func->datums[i]->dtype);
+ }
}
- }
-
- /* ----------
- * Initialize the other variables to NULL values for now.
- * The default values are set when the blocks are entered.
- * ----------
- */
- error_info_text = "while initializing local variables to NULL";
- for (i = estate.found_varno; i < estate.ndatums; i++) {
- switch(estate.datums[i]->dtype) {
- case PLPGSQL_DTYPE_VAR:
+
+ /* ----------
+ * Initialize the other variables to NULL values for now.
+ * The default values are set when the blocks are entered.
+ * ----------
+ */
+ error_info_text = "while initializing local variables to NULL";
+ for (i = estate.found_varno; i < estate.ndatums; i++)
+ {
+ switch (estate.datums[i]->dtype)
{
- PLpgSQL_var *var = (PLpgSQL_var *)estate.datums[i];
- var->value = 0;
- var->isnull = true;
- var->shouldfree = false;
+ case PLPGSQL_DTYPE_VAR:
+ {
+ PLpgSQL_var *var = (PLpgSQL_var *) estate.datums[i];
+
+ var->value = 0;
+ var->isnull = true;
+ var->shouldfree = false;
+ }
+ break;
+
+ case PLPGSQL_DTYPE_ROW:
+ case PLPGSQL_DTYPE_REC:
+ case PLPGSQL_DTYPE_RECFIELD:
+ break;
+
+ default:
+ elog(ERROR, "unknown dtype %d in plpgsql_exec_function()",
+ func->datums[i]->dtype);
}
- break;
-
- case PLPGSQL_DTYPE_ROW:
- case PLPGSQL_DTYPE_REC:
- case PLPGSQL_DTYPE_RECFIELD:
- break;
-
- default:
- elog(ERROR, "unknown dtype %d in plpgsql_exec_function()",
- func->datums[i]->dtype);
- }
- }
-
- /* ----------
- * Set the magic variable FOUND to false
- * ----------
- */
- exec_set_found(&estate, false);
-
- /* ----------
- * Now call the toplevel block of statements
- * ----------
- */
- error_info_text = NULL;
- error_info_stmt = (PLpgSQL_stmt *)(func->action);
- if (exec_stmt_block(&estate, func->action) != PLPGSQL_RC_RETURN) {
+ }
+
+ /* ----------
+ * Set the magic variable FOUND to false
+ * ----------
+ */
+ exec_set_found(&estate, false);
+
+ /* ----------
+ * Now call the toplevel block of statements
+ * ----------
+ */
+ error_info_text = NULL;
+ error_info_stmt = (PLpgSQL_stmt *) (func->action);
+ if (exec_stmt_block(&estate, func->action) != PLPGSQL_RC_RETURN)
+ {
+ error_info_stmt = NULL;
+ error_info_text = "at END of toplevel PL block";
+ elog(ERROR, "control reaches end of function without RETURN");
+ }
+
+ /* ----------
+ * We got a return value - process it
+ * ----------
+ */
error_info_stmt = NULL;
- error_info_text = "at END of toplevel PL block";
- elog(ERROR, "control reaches end of function without RETURN");
- }
+ error_info_text = "while casting return value to functions return type";
- /* ----------
- * We got a return value - process it
- * ----------
- */
- error_info_stmt = NULL;
- error_info_text = "while casting return value to functions return type";
+ *isNull = estate.retisnull;
- *isNull = estate.retisnull;
+ if (!estate.retistuple)
+ {
+ estate.retval = exec_cast_value(estate.retval, estate.rettype,
+ func->fn_rettype, &(func->fn_retinput), -1,
+ isNull);
+
+ /* ----------
+ * If the functions return type isn't by value,
+ * copy the value into upper executor memory context.
+ * ----------
+ */
+ if (!*isNull && !func->fn_retbyval)
+ {
+ int len;
+ Datum tmp;
- if (!estate.retistuple) {
- estate.retval = exec_cast_value(estate.retval, estate.rettype,
- func->fn_rettype, &(func->fn_retinput), -1,
- isNull);
+ if (func->fn_rettyplen < 0)
+ len = VARSIZE(estate.retval);
+ else
+ len = func->fn_rettyplen;
+
+ tmp = (Datum) SPI_palloc(len);
+ memcpy((void *) tmp, (void *) estate.retval, len);
+ estate.retval = tmp;
+ }
+ }
/* ----------
- * If the functions return type isn't by value,
- * copy the value into upper executor memory context.
+ * Restore the previous error info and elog() jump target
* ----------
*/
- if (!*isNull && !func->fn_retbyval) {
- int len;
- Datum tmp;
-
- if (func->fn_rettyplen < 0) {
- len = VARSIZE(estate.retval);
- } else {
- len = func->fn_rettyplen;
- }
-
- tmp = (Datum)SPI_palloc(len);
- memcpy((void *)tmp, (void *)estate.retval, len);
- estate.retval = tmp;
- }
- }
-
- /* ----------
- * Restore the previous error info and elog() jump target
- * ----------
- */
- error_info_func = save_efunc;
- error_info_stmt = save_estmt;
- error_info_text = save_etext;
- memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
-
- /* ----------
- * Return the functions result
- * ----------
- */
- return estate.retval;
+ error_info_func = save_efunc;
+ error_info_stmt = save_estmt;
+ error_info_text = save_etext;
+ memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
+
+ /* ----------
+ * Return the functions result
+ * ----------
+ */
+ return estate.retval;
}
@@ -422,333 +440,347 @@ Datum plpgsql_exec_function(PLpgSQL_function *func,
* trigger execution.
* ----------
*/
-HeapTuple plpgsql_exec_trigger(PLpgSQL_function *func,
- TriggerData *trigdata)
+HeapTuple
+plpgsql_exec_trigger(PLpgSQL_function * func,
+ TriggerData *trigdata)
{
- PLpgSQL_execstate estate;
- int i;
- sigjmp_buf save_restart;
- PLpgSQL_function *save_efunc;
- PLpgSQL_stmt *save_estmt;
- char *save_etext;
- PLpgSQL_rec *rec_new;
- PLpgSQL_rec *rec_old;
- PLpgSQL_var *var;
- HeapTuple rettup;
-
- /* ----------
- * Setup debug error info and catch elog()
- * ----------
- */
- save_efunc = error_info_func;
- save_estmt = error_info_stmt;
- save_etext = error_info_text;
-
- error_info_func = func;
- error_info_stmt = NULL;
- error_info_text = "while initialization of execution state";
-
- memcpy(&save_restart, &Warn_restart, sizeof(save_restart));
- if (sigsetjmp(Warn_restart, 1) != 0) {
- memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
+ PLpgSQL_execstate estate;
+ int i;
+ sigjmp_buf save_restart;
+ PLpgSQL_function *save_efunc;
+ PLpgSQL_stmt *save_estmt;
+ char *save_etext;
+ PLpgSQL_rec *rec_new;
+ PLpgSQL_rec *rec_old;
+ PLpgSQL_var *var;
+ HeapTuple rettup;
/* ----------
- * If we are the first of cascaded error catchings,
- * print where this happened
+ * Setup debug error info and catch elog()
* ----------
*/
- if (error_info_func != NULL) {
- elog(DEBUG, "Last error occured while executing PL/pgSQL function %s",
- error_info_func->fn_name);
- if (error_info_stmt != NULL) {
- char *stmttype;
- switch (error_info_stmt->cmd_type) {
- case PLPGSQL_STMT_BLOCK:
- stmttype = "blocks variable initialization";
- break;
- case PLPGSQL_STMT_ASSIGN:
- stmttype = "assignment";
- break;
- case PLPGSQL_STMT_IF:
- stmttype = "if";
- break;
- case PLPGSQL_STMT_LOOP:
- stmttype = "loop";
- break;
- case PLPGSQL_STMT_WHILE:
- stmttype = "while";
- break;
- case PLPGSQL_STMT_FORI:
- stmttype = "for with integer loopvar";
- break;
- case PLPGSQL_STMT_FORS:
- stmttype = "for over select rows";
- break;
- case PLPGSQL_STMT_SELECT:
- stmttype = "select into variables";
- break;
- case PLPGSQL_STMT_EXIT:
- stmttype = "exit";
- break;
- case PLPGSQL_STMT_RETURN:
- stmttype = "return";
- break;
- case PLPGSQL_STMT_RAISE:
- stmttype = "raise";
- break;
- case PLPGSQL_STMT_EXECSQL:
- stmttype = "SQL statement";
- break;
- default:
- stmttype = "unknown";
- break;
- }
- elog(DEBUG, "line %d at %s", error_info_stmt->lineno,
- stmttype);
- } else {
- if (error_info_text != NULL) {
- elog(DEBUG, "%s", error_info_text);
- } else {
- elog(DEBUG, "no more error information available");
+ save_efunc = error_info_func;
+ save_estmt = error_info_stmt;
+ save_etext = error_info_text;
+
+ error_info_func = func;
+ error_info_stmt = NULL;
+ error_info_text = "while initialization of execution state";
+
+ memcpy(&save_restart, &Warn_restart, sizeof(save_restart));
+ if (sigsetjmp(Warn_restart, 1) != 0)
+ {
+ memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
+
+ /* ----------
+ * If we are the first of cascaded error catchings,
+ * print where this happened
+ * ----------
+ */
+ if (error_info_func != NULL)
+ {
+ elog(DEBUG, "Last error occured while executing PL/pgSQL function %s",
+ error_info_func->fn_name);
+ if (error_info_stmt != NULL)
+ {
+ char *stmttype;
+
+ switch (error_info_stmt->cmd_type)
+ {
+ case PLPGSQL_STMT_BLOCK:
+ stmttype = "blocks variable initialization";
+ break;
+ case PLPGSQL_STMT_ASSIGN:
+ stmttype = "assignment";
+ break;
+ case PLPGSQL_STMT_IF:
+ stmttype = "if";
+ break;
+ case PLPGSQL_STMT_LOOP:
+ stmttype = "loop";
+ break;
+ case PLPGSQL_STMT_WHILE:
+ stmttype = "while";
+ break;
+ case PLPGSQL_STMT_FORI:
+ stmttype = "for with integer loopvar";
+ break;
+ case PLPGSQL_STMT_FORS:
+ stmttype = "for over select rows";
+ break;
+ case PLPGSQL_STMT_SELECT:
+ stmttype = "select into variables";
+ break;
+ case PLPGSQL_STMT_EXIT:
+ stmttype = "exit";
+ break;
+ case PLPGSQL_STMT_RETURN:
+ stmttype = "return";
+ break;
+ case PLPGSQL_STMT_RAISE:
+ stmttype = "raise";
+ break;
+ case PLPGSQL_STMT_EXECSQL:
+ stmttype = "SQL statement";
+ break;
+ default:
+ stmttype = "unknown";
+ break;
+ }
+ elog(DEBUG, "line %d at %s", error_info_stmt->lineno,
+ stmttype);
+ }
+ else
+ {
+ if (error_info_text != NULL)
+ elog(DEBUG, "%s", error_info_text);
+ else
+ elog(DEBUG, "no more error information available");
+ }
+
+ error_info_func = NULL;
+ error_info_stmt = NULL;
+ error_info_text = NULL;
}
- }
- error_info_func = NULL;
- error_info_stmt = NULL;
- error_info_text = NULL;
+ siglongjmp(Warn_restart, 1);
}
- siglongjmp(Warn_restart, 1);
- }
-
-
- /* ----------
- * Setup the execution state
- * ----------
- */
- estate.retval = 0;
- estate.retisnull = false;
- estate.rettype = InvalidOid;
- estate.retistuple = func->fn_retistuple;
- estate.retisset = func->fn_retset;
- estate.exitlabel = NULL;
-
- estate.found_varno = func->found_varno;
- estate.ndatums = func->ndatums;
- estate.datums = palloc(sizeof(PLpgSQL_datum *) * estate.ndatums);
-
- /* ----------
- * Make local execution copies of all the datums
- * ----------
- */
- for (i = 0; i < func->ndatums; i++) {
- switch(func->datums[i]->dtype) {
- case PLPGSQL_DTYPE_VAR:
- estate.datums[i] = (PLpgSQL_datum *)
- copy_var((PLpgSQL_var *)(func->datums[i]));
- break;
-
- case PLPGSQL_DTYPE_REC:
- estate.datums[i] = (PLpgSQL_datum *)
- copy_rec((PLpgSQL_rec *)(func->datums[i]));
- break;
-
- case PLPGSQL_DTYPE_ROW:
- case PLPGSQL_DTYPE_RECFIELD:
- case PLPGSQL_DTYPE_TRIGARG:
- estate.datums[i] = func->datums[i];
- break;
-
- default:
- elog(ERROR, "unknown dtype %d in plpgsql_exec_function()",
- func->datums[i]->dtype);
+
+ /* ----------
+ * Setup the execution state
+ * ----------
+ */
+ estate.retval = 0;
+ estate.retisnull = false;
+ estate.rettype = InvalidOid;
+ estate.retistuple = func->fn_retistuple;
+ estate.retisset = func->fn_retset;
+ estate.exitlabel = NULL;
+
+ estate.found_varno = func->found_varno;
+ estate.ndatums = func->ndatums;
+ estate.datums = palloc(sizeof(PLpgSQL_datum *) * estate.ndatums);
+
+ /* ----------
+ * Make local execution copies of all the datums
+ * ----------
+ */
+ for (i = 0; i < func->ndatums; i++)
+ {
+ switch (func->datums[i]->dtype)
+ {
+ case PLPGSQL_DTYPE_VAR:
+ estate.datums[i] = (PLpgSQL_datum *)
+ copy_var((PLpgSQL_var *) (func->datums[i]));
+ break;
+
+ case PLPGSQL_DTYPE_REC:
+ estate.datums[i] = (PLpgSQL_datum *)
+ copy_rec((PLpgSQL_rec *) (func->datums[i]));
+ break;
+
+ case PLPGSQL_DTYPE_ROW:
+ case PLPGSQL_DTYPE_RECFIELD:
+ case PLPGSQL_DTYPE_TRIGARG:
+ estate.datums[i] = func->datums[i];
+ break;
+
+ default:
+ elog(ERROR, "unknown dtype %d in plpgsql_exec_function()",
+ func->datums[i]->dtype);
+ }
+ }
+
+ /* ----------
+ * Put the trig and new tuples into the records
+ * and set the tg_op variable
+ * ----------
+ */
+ rec_new = (PLpgSQL_rec *) (estate.datums[func->new_varno]);
+ rec_old = (PLpgSQL_rec *) (estate.datums[func->old_varno]);
+ var = (PLpgSQL_var *) (estate.datums[func->tg_op_varno]);
+ var->isnull = false;
+
+ if (TRIGGER_FIRED_BY_INSERT(trigdata->tg_event))
+ {
+ rec_new->tup = trigdata->tg_trigtuple;
+ rec_new->tupdesc = trigdata->tg_relation->rd_att;
+ rec_old->tup = NULL;
+ rec_old->tupdesc = NULL;
+ var->value = (Datum) textin("INSERT");
}
- }
-
- /* ----------
- * Put the trig and new tuples into the records
- * and set the tg_op variable
- * ----------
- */
- rec_new = (PLpgSQL_rec *)(estate.datums[func->new_varno]);
- rec_old = (PLpgSQL_rec *)(estate.datums[func->old_varno]);
- var = (PLpgSQL_var *)(estate.datums[func->tg_op_varno]);
- var->isnull = false;
-
- if (TRIGGER_FIRED_BY_INSERT(trigdata->tg_event)) {
- rec_new->tup = trigdata->tg_trigtuple;
- rec_new->tupdesc = trigdata->tg_relation->rd_att;
- rec_old->tup = NULL;
- rec_old->tupdesc = NULL;
- var->value = (Datum)textin("INSERT");
- } else
- if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event)) {
- rec_new->tup = trigdata->tg_newtuple;
- rec_new->tupdesc = trigdata->tg_relation->rd_att;
- rec_old->tup = trigdata->tg_trigtuple;
- rec_old->tupdesc = trigdata->tg_relation->rd_att;
- var->value = (Datum)textin("UPDATE");
- } else
- if (TRIGGER_FIRED_BY_DELETE(trigdata->tg_event)) {
- rec_new->tup = NULL;
- rec_new->tupdesc = NULL;
- rec_old->tup = trigdata->tg_trigtuple;
- rec_old->tupdesc = trigdata->tg_relation->rd_att;
- var->value = (Datum)textin("DELETE");
- } else {
- rec_new->tup = NULL;
- rec_new->tupdesc = NULL;
- var->value = (Datum)textin("UNKNOWN");
- }
-
- /* ----------
- * Fill all the other special tg_ variables
- * ----------
- */
- var = (PLpgSQL_var *)(estate.datums[func->tg_name_varno]);
- var->isnull = false;
- var->value = (Datum)namein(trigdata->tg_trigger->tgname);
-
- var = (PLpgSQL_var *)(estate.datums[func->tg_when_varno]);
- var->isnull = false;
- if (TRIGGER_FIRED_BEFORE(trigdata->tg_event)) {
- var->value = (Datum)textin("BEFORE");
- } else
- if (TRIGGER_FIRED_AFTER(trigdata->tg_event)) {
- var->value = (Datum)textin("AFTER");
- } else {
- var->value = (Datum)textin("UNKNOWN");
- }
-
- var = (PLpgSQL_var *)(estate.datums[func->tg_level_varno]);
- var->isnull = false;
- if (TRIGGER_FIRED_FOR_ROW(trigdata->tg_event)) {
- var->value = (Datum)textin("ROW");
- } else
- if (TRIGGER_FIRED_FOR_STATEMENT(trigdata->tg_event)) {
- var->value = (Datum)textin("STATEMENT");
- } else {
- var->value = (Datum)textin("UNKNOWN");
- }
-
- var = (PLpgSQL_var *)(estate.datums[func->tg_relid_varno]);
- var->isnull = false;
- var->value = (Datum)(trigdata->tg_relation->rd_id);
-
- var = (PLpgSQL_var *)(estate.datums[func->tg_relname_varno]);
- var->isnull = false;
- var->value = (Datum)namein(nameout(&(trigdata->tg_relation->rd_rel->relname)));
-
- var = (PLpgSQL_var *)(estate.datums[func->tg_nargs_varno]);
- var->isnull = false;
- var->value = (Datum)(trigdata->tg_trigger->tgnargs);
-
- /* ----------
- * Put the actual call argument values into the special
- * execution state variables
- * ----------
- */
- error_info_text = "while putting call arguments to local variables";
- estate.trig_nargs = trigdata->tg_trigger->tgnargs;
- if (estate.trig_nargs == 0) {
- estate.trig_argv = NULL;
- } else {
- estate.trig_argv = palloc(sizeof(Datum) * estate.trig_nargs);
- for (i = 0; i < trigdata->tg_trigger->tgnargs; i++) {
- estate.trig_argv[i] = (Datum)textin(trigdata->tg_trigger->tgargs[i]);
+ else if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event))
+ {
+ rec_new->tup = trigdata->tg_newtuple;
+ rec_new->tupdesc = trigdata->tg_relation->rd_att;
+ rec_old->tup = trigdata->tg_trigtuple;
+ rec_old->tupdesc = trigdata->tg_relation->rd_att;
+ var->value = (Datum) textin("UPDATE");
}
- }
-
- /* ----------
- * Initialize the other variables to NULL values for now.
- * The default values are set when the blocks are entered.
- * ----------
- */
- error_info_text = "while initializing local variables to NULL";
- for (i = estate.found_varno; i < estate.ndatums; i++) {
- switch(estate.datums[i]->dtype) {
- case PLPGSQL_DTYPE_VAR:
+ else if (TRIGGER_FIRED_BY_DELETE(trigdata->tg_event))
+ {
+ rec_new->tup = NULL;
+ rec_new->tupdesc = NULL;
+ rec_old->tup = trigdata->tg_trigtuple;
+ rec_old->tupdesc = trigdata->tg_relation->rd_att;
+ var->value = (Datum) textin("DELETE");
+ }
+ else
+ {
+ rec_new->tup = NULL;
+ rec_new->tupdesc = NULL;
+ var->value = (Datum) textin("UNKNOWN");
+ }
+
+ /* ----------
+ * Fill all the other special tg_ variables
+ * ----------
+ */
+ var = (PLpgSQL_var *) (estate.datums[func->tg_name_varno]);
+ var->isnull = false;
+ var->value = (Datum) namein(trigdata->tg_trigger->tgname);
+
+ var = (PLpgSQL_var *) (estate.datums[func->tg_when_varno]);
+ var->isnull = false;
+ if (TRIGGER_FIRED_BEFORE(trigdata->tg_event))
+ var->value = (Datum) textin("BEFORE");
+ else if (TRIGGER_FIRED_AFTER(trigdata->tg_event))
+ var->value = (Datum) textin("AFTER");
+ else
+ var->value = (Datum) textin("UNKNOWN");
+
+ var = (PLpgSQL_var *) (estate.datums[func->tg_level_varno]);
+ var->isnull = false;
+ if (TRIGGER_FIRED_FOR_ROW(trigdata->tg_event))
+ var->value = (Datum) textin("ROW");
+ else if (TRIGGER_FIRED_FOR_STATEMENT(trigdata->tg_event))
+ var->value = (Datum) textin("STATEMENT");
+ else
+ var->value = (Datum) textin("UNKNOWN");
+
+ var = (PLpgSQL_var *) (estate.datums[func->tg_relid_varno]);
+ var->isnull = false;
+ var->value = (Datum) (trigdata->tg_relation->rd_id);
+
+ var = (PLpgSQL_var *) (estate.datums[func->tg_relname_varno]);
+ var->isnull = false;
+ var->value = (Datum) namein(nameout(&(trigdata->tg_relation->rd_rel->relname)));
+
+ var = (PLpgSQL_var *) (estate.datums[func->tg_nargs_varno]);
+ var->isnull = false;
+ var->value = (Datum) (trigdata->tg_trigger->tgnargs);
+
+ /* ----------
+ * Put the actual call argument values into the special
+ * execution state variables
+ * ----------
+ */
+ error_info_text = "while putting call arguments to local variables";
+ estate.trig_nargs = trigdata->tg_trigger->tgnargs;
+ if (estate.trig_nargs == 0)
+ estate.trig_argv = NULL;
+ else
+ {
+ estate.trig_argv = palloc(sizeof(Datum) * estate.trig_nargs);
+ for (i = 0; i < trigdata->tg_trigger->tgnargs; i++)
+ estate.trig_argv[i] = (Datum) textin(trigdata->tg_trigger->tgargs[i]);
+ }
+
+ /* ----------
+ * Initialize the other variables to NULL values for now.
+ * The default values are set when the blocks are entered.
+ * ----------
+ */
+ error_info_text = "while initializing local variables to NULL";
+ for (i = estate.found_varno; i < estate.ndatums; i++)
+ {
+ switch (estate.datums[i]->dtype)
{
- PLpgSQL_var *var = (PLpgSQL_var *)estate.datums[i];
- var->value = 0;
- var->isnull = true;
- var->shouldfree = false;
+ case PLPGSQL_DTYPE_VAR:
+ {
+ PLpgSQL_var *var = (PLpgSQL_var *) estate.datums[i];
+
+ var->value = 0;
+ var->isnull = true;
+ var->shouldfree = false;
+ }
+ break;
+
+ case PLPGSQL_DTYPE_ROW:
+ case PLPGSQL_DTYPE_REC:
+ case PLPGSQL_DTYPE_RECFIELD:
+ case PLPGSQL_DTYPE_TRIGARG:
+ break;
+
+ default:
+ elog(ERROR, "unknown dtype %d in plpgsql_exec_trigger()",
+ func->datums[i]->dtype);
}
- break;
-
- case PLPGSQL_DTYPE_ROW:
- case PLPGSQL_DTYPE_REC:
- case PLPGSQL_DTYPE_RECFIELD:
- case PLPGSQL_DTYPE_TRIGARG:
- break;
-
- default:
- elog(ERROR, "unknown dtype %d in plpgsql_exec_trigger()",
- func->datums[i]->dtype);
- }
- }
-
- /* ----------
- * Set the magic variable FOUND to false
- * ----------
- */
- exec_set_found(&estate, false);
-
- /* ----------
- * Now call the toplevel block of statements
- * ----------
- */
- error_info_text = NULL;
- error_info_stmt = (PLpgSQL_stmt *)(func->action);
- if (exec_stmt_block(&estate, func->action) != PLPGSQL_RC_RETURN) {
- error_info_stmt = NULL;
- error_info_text = "at END of toplevel PL block";
- elog(ERROR, "control reaches end of trigger procedure without RETURN");
- }
-
- /* ----------
- * Check that the returned tuple structure has the same attributes,
- * the relation that fired the trigger has.
- *
- * XXX This way it is possible, that the trigger returns a tuple
- * where attributes don't have the correct atttypmod's length.
- * It's up to the trigger's programmer to ensure that this
- * doesn't happen. Jan
- * ----------
- */
- if (estate.retisnull) {
- rettup = NULL;
- } else {
- TupleDesc td1 = trigdata->tg_relation->rd_att;
- TupleDesc td2 = estate.rettupdesc;
- int i;
-
- if (td1->natts != td2->natts) {
- elog(ERROR, "returned tuple structure doesn't match table of trigger event");
}
- for (i = 1; i <= td1->natts; i++) {
- if (SPI_gettypeid(td1, i) != SPI_gettypeid(td2, i)) {
- elog(ERROR, "returned tuple structure doesn't match table of trigger event");
- }
+
+ /* ----------
+ * Set the magic variable FOUND to false
+ * ----------
+ */
+ exec_set_found(&estate, false);
+
+ /* ----------
+ * Now call the toplevel block of statements
+ * ----------
+ */
+ error_info_text = NULL;
+ error_info_stmt = (PLpgSQL_stmt *) (func->action);
+ if (exec_stmt_block(&estate, func->action) != PLPGSQL_RC_RETURN)
+ {
+ error_info_stmt = NULL;
+ error_info_text = "at END of toplevel PL block";
+ elog(ERROR, "control reaches end of trigger procedure without RETURN");
+ }
+
+ /* ----------
+ * Check that the returned tuple structure has the same attributes,
+ * the relation that fired the trigger has.
+ *
+ * XXX This way it is possible, that the trigger returns a tuple
+ * where attributes don't have the correct atttypmod's length.
+ * It's up to the trigger's programmer to ensure that this
+ * doesn't happen. Jan
+ * ----------
+ */
+ if (estate.retisnull)
+ rettup = NULL;
+ else
+ {
+ TupleDesc td1 = trigdata->tg_relation->rd_att;
+ TupleDesc td2 = estate.rettupdesc;
+ int i;
+
+ if (td1->natts != td2->natts)
+ elog(ERROR, "returned tuple structure doesn't match table of trigger event");
+ for (i = 1; i <= td1->natts; i++)
+ {
+ if (SPI_gettypeid(td1, i) != SPI_gettypeid(td2, i))
+ elog(ERROR, "returned tuple structure doesn't match table of trigger event");
+ }
+
+ rettup = SPI_copytuple((HeapTuple) (estate.retval));
}
- rettup = SPI_copytuple((HeapTuple)(estate.retval));
- }
-
- /* ----------
- * Restore the previous error info and elog() jump target
- * ----------
- */
- error_info_func = save_efunc;
- error_info_stmt = save_estmt;
- error_info_text = save_etext;
- memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
-
- /* ----------
- * Return the triggers result
- * ----------
- */
- return rettup;
+ /* ----------
+ * Restore the previous error info and elog() jump target
+ * ----------
+ */
+ error_info_func = save_efunc;
+ error_info_stmt = save_estmt;
+ error_info_text = save_etext;
+ memcpy(&Warn_restart, &save_restart, sizeof(Warn_restart));
+
+ /* ----------
+ * Return the triggers result
+ * ----------
+ */
+ return rettup;
}
@@ -756,21 +788,25 @@ HeapTuple plpgsql_exec_trigger(PLpgSQL_function *func,
* Support functions for copying local execution variables
* ----------
*/
-static PLpgSQL_var *copy_var(PLpgSQL_var *var)
+static PLpgSQL_var *
+copy_var(PLpgSQL_var * var)
{
- PLpgSQL_var *new = palloc(sizeof(PLpgSQL_var));
- memcpy(new, var, sizeof(PLpgSQL_var));
+ PLpgSQL_var *new = palloc(sizeof(PLpgSQL_var));
+
+ memcpy(new, var, sizeof(PLpgSQL_var));
- return new;
+ return new;
}
-static PLpgSQL_rec *copy_rec(PLpgSQL_rec *rec)
+static PLpgSQL_rec *
+copy_rec(PLpgSQL_rec * rec)
{
- PLpgSQL_rec *new = palloc(sizeof(PLpgSQL_rec));
- memcpy(new, rec, sizeof(PLpgSQL_rec));
+ PLpgSQL_rec *new = palloc(sizeof(PLpgSQL_rec));
- return new;
+ memcpy(new, rec, sizeof(PLpgSQL_rec));
+
+ return new;
}
@@ -778,92 +814,96 @@ static PLpgSQL_rec *copy_rec(PLpgSQL_rec *rec)
* exec_stmt_block Execute a block of statements
* ----------
*/
-static int exec_stmt_block(PLpgSQL_execstate *estate, PLpgSQL_stmt_block *block)
+static int
+exec_stmt_block(PLpgSQL_execstate * estate, PLpgSQL_stmt_block * block)
{
- int rc;
- int i;
- int n;
-
- /* ----------
- * First initialize all variables declared in this block
- * ----------
- */
- for (i = 0; i < block->n_initvars; i++) {
- n = block->initvarnos[i];
-
- switch (estate->datums[n]->dtype) {
- case PLPGSQL_DTYPE_VAR:
- {
- PLpgSQL_var *var = (PLpgSQL_var *)(estate->datums[n]);
-
- if (!var->isconst || var->isnull) {
- if (var->default_val == NULL) {
- var->value = (Datum)0;
- var->isnull = true;
- if (var->notnull) {
- elog(ERROR, "variable '%s' declared NOT NULL cannot default to NULL", var->refname);
- }
- } else {
- exec_assign_expr(estate, (PLpgSQL_datum *)var,
- var->default_val);
- }
- }
- }
- break;
+ int rc;
+ int i;
+ int n;
- case PLPGSQL_DTYPE_REC:
- {
- PLpgSQL_rec *rec = (PLpgSQL_rec *)(estate->datums[n]);
+ /* ----------
+ * First initialize all variables declared in this block
+ * ----------
+ */
+ for (i = 0; i < block->n_initvars; i++)
+ {
+ n = block->initvarnos[i];
- rec->tup = NULL;
- rec->tupdesc = NULL;
+ switch (estate->datums[n]->dtype)
+ {
+ case PLPGSQL_DTYPE_VAR:
+ {
+ PLpgSQL_var *var = (PLpgSQL_var *) (estate->datums[n]);
+
+ if (!var->isconst || var->isnull)
+ {
+ if (var->default_val == NULL)
+ {
+ var->value = (Datum) 0;
+ var->isnull = true;
+ if (var->notnull)
+ elog(ERROR, "variable '%s' declared NOT NULL cannot default to NULL", var->refname);
+ }
+ else
+ {
+ exec_assign_expr(estate, (PLpgSQL_datum *) var,
+ var->default_val);
+ }
+ }
+ }
+ break;
+
+ case PLPGSQL_DTYPE_REC:
+ {
+ PLpgSQL_rec *rec = (PLpgSQL_rec *) (estate->datums[n]);
+
+ rec->tup = NULL;
+ rec->tupdesc = NULL;
+ }
+ break;
+
+ case PLPGSQL_DTYPE_RECFIELD:
+ break;
+
+ default:
+ elog(ERROR, "unknown dtype %d in exec_stmt_block()", estate->datums[n]->dtype);
}
- break;
-
- case PLPGSQL_DTYPE_RECFIELD:
- break;
- default:
- elog(ERROR, "unknown dtype %d in exec_stmt_block()", estate->datums[n]->dtype);
}
- }
+ /* ----------
+ * Execute the statements in the block's body
+ * ----------
+ */
+ rc = exec_stmts(estate, block->body);
- /* ----------
- * Execute the statements in the block's body
- * ----------
- */
- rc = exec_stmts(estate, block->body);
+ /* ----------
+ * Handle the return code.
+ * ----------
+ */
+ switch (rc)
+ {
+ case PLPGSQL_RC_OK:
+ return PLPGSQL_RC_OK;
+
+ case PLPGSQL_RC_EXIT:
+ if (estate->exitlabel == NULL)
+ return PLPGSQL_RC_OK;
+ if (block->label == NULL)
+ return PLPGSQL_RC_EXIT;
+ if (strcmp(block->label, estate->exitlabel))
+ return PLPGSQL_RC_EXIT;
+ estate->exitlabel = NULL;
+ return PLPGSQL_RC_OK;
+
+ case PLPGSQL_RC_RETURN:
+ return PLPGSQL_RC_RETURN;
- /* ----------
- * Handle the return code.
- * ----------
- */
- switch(rc) {
- case PLPGSQL_RC_OK:
- return PLPGSQL_RC_OK;
+ default:
+ elog(ERROR, "unknown rc %d from exec_stmt()", rc);
+ }
- case PLPGSQL_RC_EXIT:
- if (estate->exitlabel == NULL) {
- return PLPGSQL_RC_OK;
- }
- if (block->label == NULL) {
- return PLPGSQL_RC_EXIT;
- }
- if (strcmp(block->label, estate->exitlabel)) {
- return PLPGSQL_RC_EXIT;
- }
- estate->exitlabel = NULL;
- return PLPGSQL_RC_OK;
-
- case PLPGSQL_RC_RETURN:
- return PLPGSQL_RC_RETURN;
-
- default:
- elog(ERROR, "unknown rc %d from exec_stmt()", rc);
- }
-
- return PLPGSQL_RC_OK;
+ return PLPGSQL_RC_OK;
}
@@ -872,19 +912,20 @@ static int exec_stmt_block(PLpgSQL_execstate *estate, PLpgSQL_stmt_block *block)
* as long as their return code is OK
* ----------
*/
-static int exec_stmts(PLpgSQL_execstate *estate, PLpgSQL_stmts *stmts)
+static int
+exec_stmts(PLpgSQL_execstate * estate, PLpgSQL_stmts * stmts)
{
- int rc;
- int i;
-
- for (i = 0; i < stmts->stmts_used; i++) {
- rc = exec_stmt(estate, (PLpgSQL_stmt *)(stmts->stmts[i]));
- if (rc != PLPGSQL_RC_OK) {
- return rc;
+ int rc;
+ int i;
+
+ for (i = 0; i < stmts->stmts_used; i++)
+ {
+ rc = exec_stmt(estate, (PLpgSQL_stmt *) (stmts->stmts[i]));
+ if (rc != PLPGSQL_RC_OK)
+ return rc;
}
- }
- return PLPGSQL_RC_OK;
+ return PLPGSQL_RC_OK;
}
@@ -893,72 +934,74 @@ static int exec_stmts(PLpgSQL_execstate *estate, PLpgSQL_stmts *stmts)
* type specific execution function.
* ----------
*/
-static int exec_stmt(PLpgSQL_execstate *estate, PLpgSQL_stmt *stmt)
+static int
+exec_stmt(PLpgSQL_execstate * estate, PLpgSQL_stmt * stmt)
{
- PLpgSQL_stmt *save_estmt;
- int rc = -1;
+ PLpgSQL_stmt *save_estmt;
+ int rc = -1;
- save_estmt = error_info_stmt;
- error_info_stmt = stmt;
+ save_estmt = error_info_stmt;
+ error_info_stmt = stmt;
- switch (stmt->cmd_type) {
- case PLPGSQL_STMT_BLOCK:
- rc = exec_stmt_block(estate, (PLpgSQL_stmt_block *)stmt);
- break;
+ switch (stmt->cmd_type)
+ {
+ case PLPGSQL_STMT_BLOCK:
+ rc = exec_stmt_block(estate, (PLpgSQL_stmt_block *) stmt);
+ break;
- case PLPGSQL_STMT_ASSIGN:
- rc = exec_stmt_assign(estate, (PLpgSQL_stmt_assign *)stmt);
- break;
+ case PLPGSQL_STMT_ASSIGN:
+ rc = exec_stmt_assign(estate, (PLpgSQL_stmt_assign *) stmt);
+ break;
- case PLPGSQL_STMT_IF:
- rc = exec_stmt_if(estate, (PLpgSQL_stmt_if *)stmt);
- break;
+ case PLPGSQL_STMT_IF:
+ rc = exec_stmt_if(estate, (PLpgSQL_stmt_if *) stmt);
+ break;
- case PLPGSQL_STMT_LOOP:
- rc = exec_stmt_loop(estate, (PLpgSQL_stmt_loop *)stmt);
- break;
+ case PLPGSQL_STMT_LOOP:
+ rc = exec_stmt_loop(estate, (PLpgSQL_stmt_loop *) stmt);
+ break;
- case PLPGSQL_STMT_WHILE:
- rc = exec_stmt_while(estate, (PLpgSQL_stmt_while *)stmt);
- break;
+ case PLPGSQL_STMT_WHILE:
+ rc = exec_stmt_while(estate, (PLpgSQL_stmt_while *) stmt);
+ break;
- case PLPGSQL_STMT_FORI:
- rc = exec_stmt_fori(estate, (PLpgSQL_stmt_fori *)stmt);
- break;
+ case PLPGSQL_STMT_FORI:
+ rc = exec_stmt_fori(estate, (PLpgSQL_stmt_fori *) stmt);
+ break;
- case PLPGSQL_STMT_FORS:
- rc = exec_stmt_fors(estate, (PLpgSQL_stmt_fors *)stmt);
- break;
+ case PLPGSQL_STMT_FORS:
+ rc = exec_stmt_fors(estate, (PLpgSQL_stmt_fors *) stmt);
+ break;
- case PLPGSQL_STMT_SELECT:
- rc = exec_stmt_select(estate, (PLpgSQL_stmt_select *)stmt);
- break;
+ case PLPGSQL_STMT_SELECT:
+ rc = exec_stmt_select(estate, (PLpgSQL_stmt_select *) stmt);
+ break;
- case PLPGSQL_STMT_EXIT:
- rc = exec_stmt_exit(estate, (PLpgSQL_stmt_exit *)stmt);
- break;
+ case PLPGSQL_STMT_EXIT:
+ rc = exec_stmt_exit(estate, (PLpgSQL_stmt_exit *) stmt);
+ break;
- case PLPGSQL_STMT_RETURN:
- rc = exec_stmt_return(estate, (PLpgSQL_stmt_return *)stmt);
- break;
+ case PLPGSQL_STMT_RETURN:
+ rc = exec_stmt_return(estate, (PLpgSQL_stmt_return *) stmt);
+ break;
- case PLPGSQL_STMT_RAISE:
- rc = exec_stmt_raise(estate, (PLpgSQL_stmt_raise *)stmt);
- break;
+ case PLPGSQL_STMT_RAISE:
+ rc = exec_stmt_raise(estate, (PLpgSQL_stmt_raise *) stmt);
+ break;
- case PLPGSQL_STMT_EXECSQL:
- rc = exec_stmt_execsql(estate, (PLpgSQL_stmt_execsql *)stmt);
- break;
+ case PLPGSQL_STMT_EXECSQL:
+ rc = exec_stmt_execsql(estate, (PLpgSQL_stmt_execsql *) stmt);
+ break;
- default:
- error_info_stmt = save_estmt;
- elog(ERROR, "unknown cmdtype %d in exec_stmt",
- stmt->cmd_type);
- }
+ default:
+ error_info_stmt = save_estmt;
+ elog(ERROR, "unknown cmdtype %d in exec_stmt",
+ stmt->cmd_type);
+ }
- error_info_stmt = save_estmt;
+ error_info_stmt = save_estmt;
- return rc;
+ return rc;
}
@@ -967,15 +1010,15 @@ static int exec_stmt(PLpgSQL_execstate *estate, PLpgSQL_stmt *stmt)
* put the result into a variable.
* ----------
*/
-static int exec_stmt_assign(PLpgSQL_execstate *estate, PLpgSQL_stmt_assign *stmt)
+static int
+exec_stmt_assign(PLpgSQL_execstate * estate, PLpgSQL_stmt_assign * stmt)
{
- if (stmt->varno < 0) {
- exec_assign_expr(estate, NULL, stmt->expr);
- } else {
- exec_assign_expr(estate, estate->datums[stmt->varno], stmt->expr);
- }
+ if (stmt->varno < 0)
+ exec_assign_expr(estate, NULL, stmt->expr);
+ else
+ exec_assign_expr(estate, estate->datums[stmt->varno], stmt->expr);
- return PLPGSQL_RC_OK;
+ return PLPGSQL_RC_OK;
}
@@ -985,25 +1028,27 @@ static int exec_stmt_assign(PLpgSQL_execstate *estate, PLpgSQL_stmt_assign *stmt
* conditionally.
* ----------
*/
-static int exec_stmt_if(PLpgSQL_execstate *estate, PLpgSQL_stmt_if *stmt)
+static int
+exec_stmt_if(PLpgSQL_execstate * estate, PLpgSQL_stmt_if * stmt)
{
- Datum value;
- Oid valtype;
- bool isnull = false;
+ Datum value;
+ Oid valtype;
+ bool isnull = false;
- value = exec_eval_expr(estate, stmt->cond, &isnull, &valtype);
+ value = exec_eval_expr(estate, stmt->cond, &isnull, &valtype);
- if (value) {
- if (stmt->true_body != NULL) {
- return exec_stmts(estate, stmt->true_body);
+ if (value)
+ {
+ if (stmt->true_body != NULL)
+ return exec_stmts(estate, stmt->true_body);
}
- } else {
- if (stmt->false_body != NULL) {
- return exec_stmts(estate, stmt->false_body);
+ else
+ {
+ if (stmt->false_body != NULL)
+ return exec_stmts(estate, stmt->false_body);
}
- }
- return PLPGSQL_RC_OK;
+ return PLPGSQL_RC_OK;
}
@@ -1012,39 +1057,39 @@ static int exec_stmt_if(PLpgSQL_execstate *estate, PLpgSQL_stmt_if *stmt)
* an exit occurs.
* ----------
*/
-static int exec_stmt_loop(PLpgSQL_execstate *estate, PLpgSQL_stmt_loop *stmt)
+static int
+exec_stmt_loop(PLpgSQL_execstate * estate, PLpgSQL_stmt_loop * stmt)
{
- int rc;
+ int rc;
- for (;;) {
- rc = exec_stmts(estate, stmt->body);
+ for (;;)
+ {
+ rc = exec_stmts(estate, stmt->body);
- switch (rc) {
- case PLPGSQL_RC_OK:
- break;
-
- case PLPGSQL_RC_EXIT:
- if (estate->exitlabel == NULL) {
- return PLPGSQL_RC_OK;
- }
- if (stmt->label == NULL) {
- return PLPGSQL_RC_EXIT;
- }
- if (strcmp(stmt->label, estate->exitlabel)) {
- return PLPGSQL_RC_EXIT;
+ switch (rc)
+ {
+ case PLPGSQL_RC_OK:
+ break;
+
+ case PLPGSQL_RC_EXIT:
+ if (estate->exitlabel == NULL)
+ return PLPGSQL_RC_OK;
+ if (stmt->label == NULL)
+ return PLPGSQL_RC_EXIT;
+ if (strcmp(stmt->label, estate->exitlabel))
+ return PLPGSQL_RC_EXIT;
+ estate->exitlabel = NULL;
+ return PLPGSQL_RC_OK;
+
+ case PLPGSQL_RC_RETURN:
+ return PLPGSQL_RC_RETURN;
+
+ default:
+ elog(ERROR, "unknown rc %d from exec_stmts()", rc);
}
- estate->exitlabel = NULL;
- return PLPGSQL_RC_OK;
-
- case PLPGSQL_RC_RETURN:
- return PLPGSQL_RC_RETURN;
-
- default:
- elog(ERROR, "unknown rc %d from exec_stmts()", rc);
}
- }
- return PLPGSQL_RC_OK;
+ return PLPGSQL_RC_OK;
}
@@ -1054,47 +1099,46 @@ static int exec_stmt_loop(PLpgSQL_execstate *estate, PLpgSQL_stmt_loop *stmt)
* true or an exit occurs.
* ----------
*/
-static int exec_stmt_while(PLpgSQL_execstate *estate, PLpgSQL_stmt_while *stmt)
+static int
+exec_stmt_while(PLpgSQL_execstate * estate, PLpgSQL_stmt_while * stmt)
{
- Datum value;
- Oid valtype;
- bool isnull = false;
- int rc;
-
- for (;;) {
- value = exec_eval_expr(estate, stmt->cond, &isnull, &valtype);
- if (!value) {
- break;
- }
-
- rc = exec_stmts(estate, stmt->body);
+ Datum value;
+ Oid valtype;
+ bool isnull = false;
+ int rc;
+
+ for (;;)
+ {
+ value = exec_eval_expr(estate, stmt->cond, &isnull, &valtype);
+ if (!value)
+ break;
- switch (rc) {
- case PLPGSQL_RC_OK:
- break;
+ rc = exec_stmts(estate, stmt->body);
- case PLPGSQL_RC_EXIT:
- if (estate->exitlabel == NULL) {
- return PLPGSQL_RC_OK;
- }
- if (stmt->label == NULL) {
- return PLPGSQL_RC_EXIT;
- }
- if (strcmp(stmt->label, estate->exitlabel)) {
- return PLPGSQL_RC_EXIT;
+ switch (rc)
+ {
+ case PLPGSQL_RC_OK:
+ break;
+
+ case PLPGSQL_RC_EXIT:
+ if (estate->exitlabel == NULL)
+ return PLPGSQL_RC_OK;
+ if (stmt->label == NULL)
+ return PLPGSQL_RC_EXIT;
+ if (strcmp(stmt->label, estate->exitlabel))
+ return PLPGSQL_RC_EXIT;
+ estate->exitlabel = NULL;
+ return PLPGSQL_RC_OK;
+
+ case PLPGSQL_RC_RETURN:
+ return PLPGSQL_RC_RETURN;
+
+ default:
+ elog(ERROR, "unknown rc %d from exec_stmts()", rc);
}
- estate->exitlabel = NULL;
- return PLPGSQL_RC_OK;
-
- case PLPGSQL_RC_RETURN:
- return PLPGSQL_RC_RETURN;
-
- default:
- elog(ERROR, "unknown rc %d from exec_stmts()", rc);
}
- }
- return PLPGSQL_RC_OK;
+ return PLPGSQL_RC_OK;
}
@@ -1104,109 +1148,107 @@ static int exec_stmt_while(PLpgSQL_execstate *estate, PLpgSQL_stmt_while *stmt)
* Loop can be left with exit.
* ----------
*/
-static int exec_stmt_fori(PLpgSQL_execstate *estate, PLpgSQL_stmt_fori *stmt)
+static int
+exec_stmt_fori(PLpgSQL_execstate * estate, PLpgSQL_stmt_fori * stmt)
{
- PLpgSQL_var *var;
- Datum value;
- Oid valtype;
- bool isnull = false;
- int rc;
-
- /* ----------
- * Get the value of the lower bound into the loop var
- * ----------
- */
- value = exec_eval_expr(estate, stmt->lower, &isnull, &valtype);
- var = (PLpgSQL_var *)(estate->datums[stmt->var->varno]);
-
- value = exec_cast_value(value, valtype, var->datatype->typoid,
- &(var->datatype->typinput),
- var->datatype->atttypmod, &isnull);
- if (isnull) {
- elog(ERROR, "lower bound of FOR loop cannot be NULL");
- }
- var->value = value;
- var->isnull = false;
-
- /* ----------
- * Get the value of the upper bound
- * ----------
- */
- value = exec_eval_expr(estate, stmt->upper, &isnull, &valtype);
- value = exec_cast_value(value, valtype, var->datatype->typoid,
- &(var->datatype->typinput),
- var->datatype->atttypmod, &isnull);
- if (isnull) {
- elog(ERROR, "upper bound of FOR loop cannot be NULL");
- }
-
- /* ----------
- * Now do the loop
- * ----------
- */
- exec_set_found(estate, false);
- for (;;) {
+ PLpgSQL_var *var;
+ Datum value;
+ Oid valtype;
+ bool isnull = false;
+ int rc;
+
/* ----------
- * Check bounds
+ * Get the value of the lower bound into the loop var
* ----------
*/
- if (stmt->reverse) {
- if ((int4)(var->value) < (int4)value) {
- break;
- }
- } else {
- if ((int4)(var->value) > (int4)value) {
- break;
- }
- }
- exec_set_found(estate, true);
+ value = exec_eval_expr(estate, stmt->lower, &isnull, &valtype);
+ var = (PLpgSQL_var *) (estate->datums[stmt->var->varno]);
+
+ value = exec_cast_value(value, valtype, var->datatype->typoid,
+ &(var->datatype->typinput),
+ var->datatype->atttypmod, &isnull);
+ if (isnull)
+ elog(ERROR, "lower bound of FOR loop cannot be NULL");
+ var->value = value;
+ var->isnull = false;
/* ----------
- * Execute the statements
+ * Get the value of the upper bound
* ----------
*/
- rc = exec_stmts(estate, stmt->body);
+ value = exec_eval_expr(estate, stmt->upper, &isnull, &valtype);
+ value = exec_cast_value(value, valtype, var->datatype->typoid,
+ &(var->datatype->typinput),
+ var->datatype->atttypmod, &isnull);
+ if (isnull)
+ elog(ERROR, "upper bound of FOR loop cannot be NULL");
/* ----------
- * Check returncode
+ * Now do the loop
* ----------
*/
- switch (rc) {
- case PLPGSQL_RC_OK:
- break;
-
- case PLPGSQL_RC_EXIT:
- if (estate->exitlabel == NULL) {
- return PLPGSQL_RC_OK;
- }
- if (stmt->label == NULL) {
- return PLPGSQL_RC_EXIT;
+ exec_set_found(estate, false);
+ for (;;)
+ {
+ /* ----------
+ * Check bounds
+ * ----------
+ */
+ if (stmt->reverse)
+ {
+ if ((int4) (var->value) < (int4) value)
+ break;
}
- if (strcmp(stmt->label, estate->exitlabel)) {
- return PLPGSQL_RC_EXIT;
+ else
+ {
+ if ((int4) (var->value) > (int4) value)
+ break;
}
- estate->exitlabel = NULL;
- return PLPGSQL_RC_OK;
+ exec_set_found(estate, true);
- case PLPGSQL_RC_RETURN:
- return PLPGSQL_RC_RETURN;
+ /* ----------
+ * Execute the statements
+ * ----------
+ */
+ rc = exec_stmts(estate, stmt->body);
- default:
- elog(ERROR, "unknown rc %d from exec_stmts()", rc);
- }
+ /* ----------
+ * Check returncode
+ * ----------
+ */
+ switch (rc)
+ {
+ case PLPGSQL_RC_OK:
+ break;
+
+ case PLPGSQL_RC_EXIT:
+ if (estate->exitlabel == NULL)
+ return PLPGSQL_RC_OK;
+ if (stmt->label == NULL)
+ return PLPGSQL_RC_EXIT;
+ if (strcmp(stmt->label, estate->exitlabel))
+ return PLPGSQL_RC_EXIT;
+ estate->exitlabel = NULL;
+ return PLPGSQL_RC_OK;
+
+ case PLPGSQL_RC_RETURN:
+ return PLPGSQL_RC_RETURN;
+
+ default:
+ elog(ERROR, "unknown rc %d from exec_stmts()", rc);
+ }
- /* ----------
- * Increase/decrease loop var
- * ----------
- */
- if (stmt->reverse) {
- ((int4)(var->value))--;
- } else {
- ((int4)(var->value))++;
+ /* ----------
+ * Increase/decrease loop var
+ * ----------
+ */
+ if (stmt->reverse)
+ ((int4) (var->value))--;
+ else
+ ((int4) (var->value))++;
}
- }
- return PLPGSQL_RC_OK;
+ return PLPGSQL_RC_OK;
}
@@ -1217,108 +1259,109 @@ static int exec_stmt_fori(PLpgSQL_execstate *estate, PLpgSQL_stmt_fori *stmt)
* for it.
* ----------
*/
-static int exec_stmt_fors(PLpgSQL_execstate *estate, PLpgSQL_stmt_fors *stmt)
+static int
+exec_stmt_fors(PLpgSQL_execstate * estate, PLpgSQL_stmt_fors * stmt)
{
- PLpgSQL_rec *rec = NULL;
- PLpgSQL_row *row = NULL;
- SPITupleTable *tuptab;
- int rc;
- int i;
- int n;
-
- /* ----------
- * Initialize the global found variable to false
- * ----------
- */
- exec_set_found(estate, false);
-
- /* ----------
- * Determine if we assign to a record or a row
- * ----------
- */
- if (stmt->rec != NULL) {
- rec = (PLpgSQL_rec *)(estate->datums[stmt->rec->recno]);
- } else {
- if (stmt->row != NULL) {
- row = (PLpgSQL_row *)(estate->datums[stmt->row->rowno]);
- } else {
- elog(ERROR, "unsupported target in exec_stmt_fors()");
- }
- }
-
- /* ----------
- * Run the query
- * ----------
- */
- exec_run_select(estate, stmt->query, 0);
- n = SPI_processed;
-
- /* ----------
- * If the query didn't return any row, set the target
- * to NULL and return.
- * ----------
- */
- if (n == 0) {
- exec_move_row(estate, rec, row, NULL, NULL);
- return PLPGSQL_RC_OK;
- }
-
- /* ----------
- * There are tuples, so set found to true
- * ----------
- */
- exec_set_found(estate, true);
-
- /* ----------
- * Now do the loop
- * ----------
- */
- tuptab = SPI_tuptable;
- SPI_tuptable = NULL;
-
- for (i = 0; i < n; i++) {
+ PLpgSQL_rec *rec = NULL;
+ PLpgSQL_row *row = NULL;
+ SPITupleTable *tuptab;
+ int rc;
+ int i;
+ int n;
+
/* ----------
- * Assign the tuple to the target
+ * Initialize the global found variable to false
* ----------
*/
- exec_move_row(estate, rec, row, tuptab->vals[i], tuptab->tupdesc);
+ exec_set_found(estate, false);
/* ----------
- * Execute the statements
+ * Determine if we assign to a record or a row
* ----------
*/
- rc = exec_stmts(estate, stmt->body);
+ if (stmt->rec != NULL)
+ rec = (PLpgSQL_rec *) (estate->datums[stmt->rec->recno]);
+ else
+ {
+ if (stmt->row != NULL)
+ row = (PLpgSQL_row *) (estate->datums[stmt->row->rowno]);
+ else
+ elog(ERROR, "unsupported target in exec_stmt_fors()");
+ }
/* ----------
- * Check returncode
+ * Run the query
* ----------
*/
- switch (rc) {
- case PLPGSQL_RC_OK:
- break;
+ exec_run_select(estate, stmt->query, 0);
+ n = SPI_processed;
- case PLPGSQL_RC_EXIT:
- if (estate->exitlabel == NULL) {
- return PLPGSQL_RC_OK;
- }
- if (stmt->label == NULL) {
- return PLPGSQL_RC_EXIT;
- }
- if (strcmp(stmt->label, estate->exitlabel)) {
- return PLPGSQL_RC_EXIT;
- }
- estate->exitlabel = NULL;
+ /* ----------
+ * If the query didn't return any row, set the target
+ * to NULL and return.
+ * ----------
+ */
+ if (n == 0)
+ {
+ exec_move_row(estate, rec, row, NULL, NULL);
return PLPGSQL_RC_OK;
+ }
- case PLPGSQL_RC_RETURN:
- return PLPGSQL_RC_RETURN;
+ /* ----------
+ * There are tuples, so set found to true
+ * ----------
+ */
+ exec_set_found(estate, true);
+
+ /* ----------
+ * Now do the loop
+ * ----------
+ */
+ tuptab = SPI_tuptable;
+ SPI_tuptable = NULL;
+
+ for (i = 0; i < n; i++)
+ {
+ /* ----------
+ * Assign the tuple to the target
+ * ----------
+ */
+ exec_move_row(estate, rec, row, tuptab->vals[i], tuptab->tupdesc);
+
+ /* ----------
+ * Execute the statements
+ * ----------
+ */
+ rc = exec_stmts(estate, stmt->body);
- default:
- elog(ERROR, "unknown rc %d from exec_stmts()", rc);
+ /* ----------
+ * Check returncode
+ * ----------
+ */
+ switch (rc)
+ {
+ case PLPGSQL_RC_OK:
+ break;
+
+ case PLPGSQL_RC_EXIT:
+ if (estate->exitlabel == NULL)
+ return PLPGSQL_RC_OK;
+ if (stmt->label == NULL)
+ return PLPGSQL_RC_EXIT;
+ if (strcmp(stmt->label, estate->exitlabel))
+ return PLPGSQL_RC_EXIT;
+ estate->exitlabel = NULL;
+ return PLPGSQL_RC_OK;
+
+ case PLPGSQL_RC_RETURN:
+ return PLPGSQL_RC_RETURN;
+
+ default:
+ elog(ERROR, "unknown rc %d from exec_stmts()", rc);
+ }
}
- }
- return PLPGSQL_RC_OK;
+ return PLPGSQL_RC_OK;
}
@@ -1327,62 +1370,64 @@ static int exec_stmt_fors(PLpgSQL_execstate *estate, PLpgSQL_stmt_fors *stmt)
* row to a record or rowtype.
* ----------
*/
-static int exec_stmt_select(PLpgSQL_execstate *estate, PLpgSQL_stmt_select *stmt)
+static int
+exec_stmt_select(PLpgSQL_execstate * estate, PLpgSQL_stmt_select * stmt)
{
- PLpgSQL_rec *rec = NULL;
- PLpgSQL_row *row = NULL;
- SPITupleTable *tuptab;
- int n;
-
- /* ----------
- * Initialize the global found variable to false
- * ----------
- */
- exec_set_found(estate, false);
-
- /* ----------
- * Determine if we assign to a record or a row
- * ----------
- */
- if (stmt->rec != NULL) {
- rec = (PLpgSQL_rec *)(estate->datums[stmt->rec->recno]);
- } else {
- if (stmt->row != NULL) {
- row = (PLpgSQL_row *)(estate->datums[stmt->row->rowno]);
- } else {
- elog(ERROR, "unsupported target in exec_stmt_select()");
+ PLpgSQL_rec *rec = NULL;
+ PLpgSQL_row *row = NULL;
+ SPITupleTable *tuptab;
+ int n;
+
+ /* ----------
+ * Initialize the global found variable to false
+ * ----------
+ */
+ exec_set_found(estate, false);
+
+ /* ----------
+ * Determine if we assign to a record or a row
+ * ----------
+ */
+ if (stmt->rec != NULL)
+ rec = (PLpgSQL_rec *) (estate->datums[stmt->rec->recno]);
+ else
+ {
+ if (stmt->row != NULL)
+ row = (PLpgSQL_row *) (estate->datums[stmt->row->rowno]);
+ else
+ elog(ERROR, "unsupported target in exec_stmt_select()");
}
- }
-
- /* ----------
- * Run the query
- * ----------
- */
- exec_run_select(estate, stmt->query, 1);
- n = SPI_processed;
-
- /* ----------
- * If the query didn't return any row, set the target
- * to NULL and return.
- * ----------
- */
- if (n == 0) {
- exec_move_row(estate, rec, row, NULL, NULL);
- return PLPGSQL_RC_OK;
- }
- /* ----------
- * Put the result into the target and set found to true
- * ----------
- */
- tuptab = SPI_tuptable;
- SPI_tuptable = NULL;
+ /* ----------
+ * Run the query
+ * ----------
+ */
+ exec_run_select(estate, stmt->query, 1);
+ n = SPI_processed;
- exec_move_row(estate, rec, row, tuptab->vals[0], tuptab->tupdesc);
+ /* ----------
+ * If the query didn't return any row, set the target
+ * to NULL and return.
+ * ----------
+ */
+ if (n == 0)
+ {
+ exec_move_row(estate, rec, row, NULL, NULL);
+ return PLPGSQL_RC_OK;
+ }
- exec_set_found(estate, true);
+ /* ----------
+ * Put the result into the target and set found to true
+ * ----------
+ */
+ tuptab = SPI_tuptable;
+ SPI_tuptable = NULL;
+
+ exec_move_row(estate, rec, row, tuptab->vals[0], tuptab->tupdesc);
- return PLPGSQL_RC_OK;
+ exec_set_found(estate, true);
+
+ return PLPGSQL_RC_OK;
}
@@ -1390,25 +1435,26 @@ static int exec_stmt_select(PLpgSQL_execstate *estate, PLpgSQL_stmt_select *stmt
* exec_stmt_exit Start exiting loop(s) or blocks
* ----------
*/
-static int exec_stmt_exit(PLpgSQL_execstate *estate, PLpgSQL_stmt_exit *stmt)
+static int
+exec_stmt_exit(PLpgSQL_execstate * estate, PLpgSQL_stmt_exit * stmt)
{
- Datum value;
- Oid valtype;
- bool isnull = false;
-
- /* ----------
- * If the exit has a condition, check that it's true
- * ----------
- */
- if (stmt->cond != NULL) {
- value = exec_eval_expr(estate, stmt->cond, &isnull, &valtype);
- if (!value) {
- return PLPGSQL_RC_OK;
+ Datum value;
+ Oid valtype;
+ bool isnull = false;
+
+ /* ----------
+ * If the exit has a condition, check that it's true
+ * ----------
+ */
+ if (stmt->cond != NULL)
+ {
+ value = exec_eval_expr(estate, stmt->cond, &isnull, &valtype);
+ if (!value)
+ return PLPGSQL_RC_OK;
}
- }
- estate->exitlabel = stmt->label;
- return PLPGSQL_RC_EXIT;
+ estate->exitlabel = stmt->label;
+ return PLPGSQL_RC_EXIT;
}
@@ -1417,37 +1463,43 @@ static int exec_stmt_exit(PLpgSQL_execstate *estate, PLpgSQL_stmt_exit *stmt)
* returning from the function.
* ----------
*/
-static int exec_stmt_return(PLpgSQL_execstate *estate, PLpgSQL_stmt_return *stmt)
+static int
+exec_stmt_return(PLpgSQL_execstate * estate, PLpgSQL_stmt_return * stmt)
{
- if (estate->retistuple) {
- if (stmt->retrecno >= 0) {
- PLpgSQL_rec *rec = (PLpgSQL_rec *)(estate->datums[stmt->retrecno]);
+ if (estate->retistuple)
+ {
+ if (stmt->retrecno >= 0)
+ {
+ PLpgSQL_rec *rec = (PLpgSQL_rec *) (estate->datums[stmt->retrecno]);
- estate->retval = (Datum)(rec->tup);
- estate->rettupdesc = rec->tupdesc;
- estate->retisnull = !HeapTupleIsValid(rec->tup);
+ estate->retval = (Datum) (rec->tup);
+ estate->rettupdesc = rec->tupdesc;
+ estate->retisnull = !HeapTupleIsValid(rec->tup);
- return PLPGSQL_RC_RETURN;
- }
+ return PLPGSQL_RC_RETURN;
+ }
- if (stmt->expr == NULL) {
- estate->retval = (Datum)0;
- estate->rettupdesc = NULL;
- estate->retisnull = true;
- } else {
- exec_run_select(estate, stmt->expr, 1);
- estate->retval = (Datum) SPI_copytuple(SPI_tuptable->vals[0]);
- estate->rettupdesc = SPI_tuptable->tupdesc;
- estate->retisnull = false;
+ if (stmt->expr == NULL)
+ {
+ estate->retval = (Datum) 0;
+ estate->rettupdesc = NULL;
+ estate->retisnull = true;
+ }
+ else
+ {
+ exec_run_select(estate, stmt->expr, 1);
+ estate->retval = (Datum) SPI_copytuple(SPI_tuptable->vals[0]);
+ estate->rettupdesc = SPI_tuptable->tupdesc;
+ estate->retisnull = false;
+ }
+ return PLPGSQL_RC_RETURN;
}
- return PLPGSQL_RC_RETURN;
- }
- estate->retval = exec_eval_expr(estate, stmt->expr,
- &(estate->retisnull),
- &(estate->rettype));
+ estate->retval = exec_eval_expr(estate, stmt->expr,
+ &(estate->retisnull),
+ &(estate->rettype));
- return PLPGSQL_RC_RETURN;
+ return PLPGSQL_RC_RETURN;
}
@@ -1456,143 +1508,150 @@ static int exec_stmt_return(PLpgSQL_execstate *estate, PLpgSQL_stmt_return *stmt
* elog()
* ----------
*/
-static int exec_stmt_raise(PLpgSQL_execstate *estate, PLpgSQL_stmt_raise *stmt)
+static int
+exec_stmt_raise(PLpgSQL_execstate * estate, PLpgSQL_stmt_raise * stmt)
{
- HeapTuple typetup;
- Form_pg_type typeStruct;
- FmgrInfo finfo_output;
- char *extval;
- int pidx = 0;
- char c[2] = {0, 0};
- char *cp;
- PLpgSQL_dstring ds;
- PLpgSQL_var *var;
- PLpgSQL_rec *rec;
- PLpgSQL_recfield *recfield;
- int fno;
-
- plpgsql_dstring_init(&ds);
-
- for (cp = stmt->message; *cp; cp++) {
- /* ----------
- * Occurences of a single % are replaced by the next
- * arguments external representation. Double %'s are
- * left as is so elog() will also don't touch them.
- * ----------
- */
- if ((c[0] = *cp) == '%') {
- cp++;
- if (*cp == '%') {
- plpgsql_dstring_append(&ds, c);
- plpgsql_dstring_append(&ds, c);
- continue;
- }
- cp--;
- if (pidx >= stmt->nparams) {
- plpgsql_dstring_append(&ds, c);
- plpgsql_dstring_append(&ds, c);
- continue;
- }
- switch(estate->datums[stmt->params[pidx]]->dtype) {
- case PLPGSQL_DTYPE_VAR:
- var = (PLpgSQL_var *)
- (estate->datums[stmt->params[pidx]]);
- if (var->isnull) {
- extval = "<NULL>";
- } else {
- typetup = SearchSysCacheTuple(TYPOID,
- ObjectIdGetDatum(var->datatype->typoid), 0, 0, 0);
- if (!HeapTupleIsValid(typetup)) {
- elog(ERROR, "cache lookup for type %d failed (1)", var->datatype->typoid);
+ HeapTuple typetup;
+ Form_pg_type typeStruct;
+ FmgrInfo finfo_output;
+ char *extval;
+ int pidx = 0;
+ char c[2] = {0, 0};
+ char *cp;
+ PLpgSQL_dstring ds;
+ PLpgSQL_var *var;
+ PLpgSQL_rec *rec;
+ PLpgSQL_recfield *recfield;
+ int fno;
+
+ plpgsql_dstring_init(&ds);
+
+ for (cp = stmt->message; *cp; cp++)
+ {
+ /* ----------
+ * Occurences of a single % are replaced by the next
+ * arguments external representation. Double %'s are
+ * left as is so elog() will also don't touch them.
+ * ----------
+ */
+ if ((c[0] = *cp) == '%')
+ {
+ cp++;
+ if (*cp == '%')
+ {
+ plpgsql_dstring_append(&ds, c);
+ plpgsql_dstring_append(&ds, c);
+ continue;
}
- typeStruct = (Form_pg_type) GETSTRUCT(typetup);
-
- fmgr_info(typeStruct->typoutput, &finfo_output);
- extval = (char *)(*fmgr_faddr(&finfo_output))(var->value, &(var->isnull), var->datatype->atttypmod);
- }
- plpgsql_dstring_append(&ds, extval);
- break;
-
- case PLPGSQL_DTYPE_RECFIELD:
- recfield = (PLpgSQL_recfield *)
- (estate->datums[stmt->params[pidx]]);
- rec = (PLpgSQL_rec *)
- (estate->datums[recfield->recno]);
- if (!HeapTupleIsValid(rec->tup)) {
- extval = "<NULL>";
- } else {
- fno = SPI_fnumber(rec->tupdesc, recfield->fieldname);
- if (fno == SPI_ERROR_NOATTRIBUTE) {
- elog(ERROR, "record %s has no field %s", rec->refname, recfield->fieldname);
+ cp--;
+ if (pidx >= stmt->nparams)
+ {
+ plpgsql_dstring_append(&ds, c);
+ plpgsql_dstring_append(&ds, c);
+ continue;
}
- extval = SPI_getvalue(rec->tup, rec->tupdesc, fno);
- }
- plpgsql_dstring_append(&ds, extval);
- break;
-
- case PLPGSQL_DTYPE_TRIGARG:
- {
- PLpgSQL_trigarg *trigarg;
- int value;
- Oid valtype;
- bool valisnull = false;
-
- trigarg = (PLpgSQL_trigarg *)
- (estate->datums[stmt->params[pidx]]);
- value = (int)exec_eval_expr(estate, trigarg->argnum,
- &valisnull, &valtype);
- if (valisnull) {
- extval = "<INDEX_IS_NULL>";
- } else {
- if (value < 0 || value >= estate->trig_nargs) {
- extval = "<OUT_OF_RANGE>";
- } else {
- extval = textout((text *)(estate->trig_argv[value]));
- }
+ switch (estate->datums[stmt->params[pidx]]->dtype)
+ {
+ case PLPGSQL_DTYPE_VAR:
+ var = (PLpgSQL_var *)
+ (estate->datums[stmt->params[pidx]]);
+ if (var->isnull)
+ extval = "<NULL>";
+ else
+ {
+ typetup = SearchSysCacheTuple(TYPOID,
+ ObjectIdGetDatum(var->datatype->typoid), 0, 0, 0);
+ if (!HeapTupleIsValid(typetup))
+ elog(ERROR, "cache lookup for type %d failed (1)", var->datatype->typoid);
+ typeStruct = (Form_pg_type) GETSTRUCT(typetup);
+
+ fmgr_info(typeStruct->typoutput, &finfo_output);
+ extval = (char *) (*fmgr_faddr(&finfo_output)) (var->value, &(var->isnull), var->datatype->atttypmod);
+ }
+ plpgsql_dstring_append(&ds, extval);
+ break;
+
+ case PLPGSQL_DTYPE_RECFIELD:
+ recfield = (PLpgSQL_recfield *)
+ (estate->datums[stmt->params[pidx]]);
+ rec = (PLpgSQL_rec *)
+ (estate->datums[recfield->recno]);
+ if (!HeapTupleIsValid(rec->tup))
+ extval = "<NULL>";
+ else
+ {
+ fno = SPI_fnumber(rec->tupdesc, recfield->fieldname);
+ if (fno == SPI_ERROR_NOATTRIBUTE)
+ elog(ERROR, "record %s has no field %s", rec->refname, recfield->fieldname);
+ extval = SPI_getvalue(rec->tup, rec->tupdesc, fno);
+ }
+ plpgsql_dstring_append(&ds, extval);
+ break;
+
+ case PLPGSQL_DTYPE_TRIGARG:
+ {
+ PLpgSQL_trigarg *trigarg;
+ int value;
+ Oid valtype;
+ bool valisnull = false;
+
+ trigarg = (PLpgSQL_trigarg *)
+ (estate->datums[stmt->params[pidx]]);
+ value = (int) exec_eval_expr(estate, trigarg->argnum,
+ &valisnull, &valtype);
+ if (valisnull)
+ extval = "<INDEX_IS_NULL>";
+ else
+ {
+ if (value < 0 || value >= estate->trig_nargs)
+ extval = "<OUT_OF_RANGE>";
+ else
+ extval = textout((text *) (estate->trig_argv[value]));
+ }
+ plpgsql_dstring_append(&ds, extval);
+ }
+ break;
+
+ default:
+ c[0] = '?';
+ plpgsql_dstring_append(&ds, c);
+ break;
}
- plpgsql_dstring_append(&ds, extval);
- }
- break;
+ pidx++;
+ continue;
+ }
- default:
- c[0] = '?';
- plpgsql_dstring_append(&ds, c);
- break;
- }
- pidx++;
- continue;
+ /* ----------
+ * Occurences of single ' are removed. double ' are reduced
+ * to single ones.
+ * ----------
+ */
+ if (*cp == '\'')
+ {
+ cp++;
+ if (*cp == '\'')
+ plpgsql_dstring_append(&ds, c);
+ else
+ cp--;
+ continue;
+ }
+ plpgsql_dstring_append(&ds, c);
}
/* ----------
- * Occurences of single ' are removed. double ' are reduced
- * to single ones.
+ * Now suppress debug info and throw the elog()
* ----------
*/
- if (*cp == '\'') {
- cp++;
- if (*cp == '\'') {
- plpgsql_dstring_append(&ds, c);
- } else {
- cp--;
- }
- continue;
+ if (stmt->elog_level == ERROR)
+ {
+ error_info_func = NULL;
+ error_info_stmt = NULL;
+ error_info_text = NULL;
}
- plpgsql_dstring_append(&ds, c);
- }
-
- /* ----------
- * Now suppress debug info and throw the elog()
- * ----------
- */
- if (stmt->elog_level == ERROR) {
- error_info_func = NULL;
- error_info_stmt = NULL;
- error_info_text = NULL;
- }
- elog(stmt->elog_level, "%s", plpgsql_dstring_get(&ds));
- plpgsql_dstring_free(&ds);
+ elog(stmt->elog_level, "%s", plpgsql_dstring_get(&ds));
+ plpgsql_dstring_free(&ds);
- return PLPGSQL_RC_OK;
+ return PLPGSQL_RC_OK;
}
@@ -1601,157 +1660,159 @@ static int exec_stmt_raise(PLpgSQL_execstate *estate, PLpgSQL_stmt_raise *stmt)
* returning any data.
* ----------
*/
-static int exec_stmt_execsql(PLpgSQL_execstate *estate,
- PLpgSQL_stmt_execsql *stmt)
+static int
+exec_stmt_execsql(PLpgSQL_execstate * estate,
+ PLpgSQL_stmt_execsql * stmt)
{
- PLpgSQL_var *var;
- PLpgSQL_rec *rec;
- PLpgSQL_recfield *recfield;
- PLpgSQL_trigarg *trigarg;
- int tgargno;
- Oid tgargoid;
- int fno;
- int i;
- Datum *values;
- char *nulls;
- int rc;
- PLpgSQL_expr *expr = stmt->sqlstmt;
- bool isnull;
-
- /* ----------
- * On the first call for this expression generate the plan
- * ----------
- */
- if (expr->plan == NULL) {
- void *plan;
- Oid *argtypes;
-
- argtypes = malloc(sizeof(Oid *) * (expr->nparams + 1));
-
- for (i = 0; i < expr->nparams; i++) {
- switch (estate->datums[expr->params[i]]->dtype) {
- case PLPGSQL_DTYPE_VAR:
- var = (PLpgSQL_var *)(estate->datums[expr->params[i]]);
- argtypes[i] = var->datatype->typoid;
- break;
+ PLpgSQL_var *var;
+ PLpgSQL_rec *rec;
+ PLpgSQL_recfield *recfield;
+ PLpgSQL_trigarg *trigarg;
+ int tgargno;
+ Oid tgargoid;
+ int fno;
+ int i;
+ Datum *values;
+ char *nulls;
+ int rc;
+ PLpgSQL_expr *expr = stmt->sqlstmt;
+ bool isnull;
- case PLPGSQL_DTYPE_RECFIELD:
- recfield = (PLpgSQL_recfield *)(estate->datums[expr->params[i]]);
- rec = (PLpgSQL_rec *)(estate->datums[recfield->recno]);
-
- if (!HeapTupleIsValid(rec->tup)) {
- elog(ERROR, "record %s is unassigned yet", rec->refname);
- }
- fno = SPI_fnumber(rec->tupdesc, recfield->fieldname);
- if (fno == SPI_ERROR_NOATTRIBUTE) {
- elog(ERROR, "record %s has no field %s", rec->refname, recfield->fieldname);
- }
- argtypes[i] = SPI_gettypeid(rec->tupdesc, fno);
- break;
-
- case PLPGSQL_DTYPE_TRIGARG:
- argtypes[i] = (Oid)TEXTOID;
- break;
-
- default:
- elog(ERROR, "unknown parameter dtype %d in exec_stmt_execsql()", estate->datums[expr->params[i]]->dtype);
- }
+ /* ----------
+ * On the first call for this expression generate the plan
+ * ----------
+ */
+ if (expr->plan == NULL)
+ {
+ void *plan;
+ Oid *argtypes;
+
+ argtypes = malloc(sizeof(Oid *) * (expr->nparams + 1));
+
+ for (i = 0; i < expr->nparams; i++)
+ {
+ switch (estate->datums[expr->params[i]]->dtype)
+ {
+ case PLPGSQL_DTYPE_VAR:
+ var = (PLpgSQL_var *) (estate->datums[expr->params[i]]);
+ argtypes[i] = var->datatype->typoid;
+ break;
+
+ case PLPGSQL_DTYPE_RECFIELD:
+ recfield = (PLpgSQL_recfield *) (estate->datums[expr->params[i]]);
+ rec = (PLpgSQL_rec *) (estate->datums[recfield->recno]);
+
+ if (!HeapTupleIsValid(rec->tup))
+ elog(ERROR, "record %s is unassigned yet", rec->refname);
+ fno = SPI_fnumber(rec->tupdesc, recfield->fieldname);
+ if (fno == SPI_ERROR_NOATTRIBUTE)
+ elog(ERROR, "record %s has no field %s", rec->refname, recfield->fieldname);
+ argtypes[i] = SPI_gettypeid(rec->tupdesc, fno);
+ break;
+
+ case PLPGSQL_DTYPE_TRIGARG:
+ argtypes[i] = (Oid) TEXTOID;
+ break;
+
+ default:
+ elog(ERROR, "unknown parameter dtype %d in exec_stmt_execsql()", estate->datums[expr->params[i]]->dtype);
+ }
+ }
+
+ plan = SPI_prepare(expr->query, expr->nparams, argtypes);
+ if (plan == NULL)
+ elog(ERROR, "SPI_prepare() failed on \"%s\"", expr->query);
+ expr->plan = SPI_saveplan(plan);
+ expr->plan_argtypes = argtypes;
}
- plan = SPI_prepare(expr->query, expr->nparams, argtypes);
- if (plan == NULL) {
- elog(ERROR, "SPI_prepare() failed on \"%s\"", expr->query);
+ /* ----------
+ * Now build up the values and nulls arguments for SPI_execp()
+ * ----------
+ */
+ values = palloc(sizeof(Datum) * (expr->nparams + 1));
+ nulls = palloc(expr->nparams + 1);
+
+ for (i = 0; i < expr->nparams; i++)
+ {
+ switch (estate->datums[expr->params[i]]->dtype)
+ {
+ case PLPGSQL_DTYPE_VAR:
+ var = (PLpgSQL_var *) (estate->datums[expr->params[i]]);
+ values[i] = var->value;
+ if (var->isnull)
+ nulls[i] = 'n';
+ else
+ nulls[i] = ' ';
+ break;
+
+ case PLPGSQL_DTYPE_RECFIELD:
+ recfield = (PLpgSQL_recfield *) (estate->datums[expr->params[i]]);
+ rec = (PLpgSQL_rec *) (estate->datums[recfield->recno]);
+
+ if (!HeapTupleIsValid(rec->tup))
+ elog(ERROR, "record %s is unassigned yet", rec->refname);
+ fno = SPI_fnumber(rec->tupdesc, recfield->fieldname);
+ if (fno == SPI_ERROR_NOATTRIBUTE)
+ elog(ERROR, "record %s has no field %s", rec->refname, recfield->fieldname);
+
+ if (expr->plan_argtypes[i] != SPI_gettypeid(rec->tupdesc, fno))
+ elog(ERROR, "type of %s.%s doesn't match that when preparing the plan", rec->refname, recfield->fieldname);
+
+ values[i] = SPI_getbinval(rec->tup, rec->tupdesc, fno, &isnull);
+ if (isnull)
+ nulls[i] = 'n';
+ else
+ nulls[i] = ' ';
+ break;
+
+ case PLPGSQL_DTYPE_TRIGARG:
+ trigarg = (PLpgSQL_trigarg *) (estate->datums[expr->params[i]]);
+ tgargno = (int) exec_eval_expr(estate, trigarg->argnum,
+ &isnull, &tgargoid);
+ if (isnull || tgargno < 0 || tgargno >= estate->trig_nargs)
+ {
+ values[i] = 0;
+ nulls[i] = 'n';
+ }
+ else
+ {
+ values[i] = estate->trig_argv[tgargno];
+ nulls[i] = ' ';
+ }
+ break;
+
+ default:
+ elog(ERROR, "unknown parameter dtype %d in exec_stmt_execsql()", estate->datums[expr->params[i]]->dtype);
+ }
}
- expr->plan = SPI_saveplan(plan);
- expr->plan_argtypes = argtypes;
- }
-
- /* ----------
- * Now build up the values and nulls arguments for SPI_execp()
- * ----------
- */
- values = palloc(sizeof(Datum) * (expr->nparams + 1));
- nulls = palloc(expr->nparams + 1);
-
- for (i = 0; i < expr->nparams; i++) {
- switch (estate->datums[expr->params[i]]->dtype) {
- case PLPGSQL_DTYPE_VAR:
- var = (PLpgSQL_var *)(estate->datums[expr->params[i]]);
- values[i] = var->value;
- if (var->isnull) {
- nulls[i] = 'n';
- } else {
- nulls[i] = ' ';
- }
- break;
+ nulls[i] = '\0';
- case PLPGSQL_DTYPE_RECFIELD:
- recfield = (PLpgSQL_recfield *)(estate->datums[expr->params[i]]);
- rec = (PLpgSQL_rec *)(estate->datums[recfield->recno]);
-
- if (!HeapTupleIsValid(rec->tup)) {
- elog(ERROR, "record %s is unassigned yet", rec->refname);
- }
- fno = SPI_fnumber(rec->tupdesc, recfield->fieldname);
- if (fno == SPI_ERROR_NOATTRIBUTE) {
- elog(ERROR, "record %s has no field %s", rec->refname, recfield->fieldname);
- }
-
- if (expr->plan_argtypes[i] != SPI_gettypeid(rec->tupdesc, fno)) {
- elog(ERROR, "type of %s.%s doesn't match that when preparing the plan", rec->refname, recfield->fieldname);
- }
-
- values[i] = SPI_getbinval(rec->tup, rec->tupdesc, fno, &isnull);
- if (isnull) {
- nulls[i] = 'n';
- } else {
- nulls[i] = ' ';
- }
- break;
-
- case PLPGSQL_DTYPE_TRIGARG:
- trigarg = (PLpgSQL_trigarg *)(estate->datums[expr->params[i]]);
- tgargno = (int)exec_eval_expr(estate, trigarg->argnum,
- &isnull, &tgargoid);
- if (isnull || tgargno < 0 || tgargno >= estate->trig_nargs) {
- values[i] = 0;
- nulls[i] = 'n';
- } else {
- values[i] = estate->trig_argv[tgargno];
- nulls[i] = ' ';
- }
- break;
-
- default:
- elog(ERROR, "unknown parameter dtype %d in exec_stmt_execsql()", estate->datums[expr->params[i]]->dtype);
- }
- }
- nulls[i] = '\0';
-
- /* ----------
- * Execute the plan
- * ----------
- */
- rc = SPI_execp(expr->plan, values, nulls, 0);
- switch(rc) {
- case SPI_OK_UTILITY:
- case SPI_OK_SELINTO:
- case SPI_OK_INSERT:
- case SPI_OK_DELETE:
- case SPI_OK_UPDATE:
- break;
-
- case SPI_OK_SELECT:
- elog(ERROR, "unexpected SELECT query in exec_stmt_execsql()");
-
- default:
- elog(ERROR, "error executing query \"%s\"",
- expr->query);
- }
- pfree(values);
- pfree(nulls);
-
- return PLPGSQL_RC_OK;
+ /* ----------
+ * Execute the plan
+ * ----------
+ */
+ rc = SPI_execp(expr->plan, values, nulls, 0);
+ switch (rc)
+ {
+ case SPI_OK_UTILITY:
+ case SPI_OK_SELINTO:
+ case SPI_OK_INSERT:
+ case SPI_OK_DELETE:
+ case SPI_OK_UPDATE:
+ break;
+
+ case SPI_OK_SELECT:
+ elog(ERROR, "unexpected SELECT query in exec_stmt_execsql()");
+
+ default:
+ elog(ERROR, "error executing query \"%s\"",
+ expr->query);
+ }
+ pfree(values);
+ pfree(nulls);
+
+ return PLPGSQL_RC_OK;
}
@@ -1760,17 +1821,17 @@ static int exec_stmt_execsql(PLpgSQL_execstate *estate,
* a variable.
* ----------
*/
-static void exec_assign_expr(PLpgSQL_execstate *estate, PLpgSQL_datum *target,
- PLpgSQL_expr *expr)
+static void
+exec_assign_expr(PLpgSQL_execstate * estate, PLpgSQL_datum * target,
+ PLpgSQL_expr * expr)
{
- Datum value;
- Oid valtype;
- bool isnull = false;
-
- value = exec_eval_expr(estate, expr, &isnull, &valtype);
- if (target != NULL) {
- exec_assign_value(estate, target, value, valtype, &isnull);
- }
+ Datum value;
+ Oid valtype;
+ bool isnull = false;
+
+ value = exec_eval_expr(estate, expr, &isnull, &valtype);
+ if (target != NULL)
+ exec_assign_value(estate, target, value, valtype, &isnull);
}
@@ -1778,140 +1839,138 @@ static void exec_assign_expr(PLpgSQL_execstate *estate, PLpgSQL_datum *target,
* exec_assign_value Put a value into a target field
* ----------
*/
-static void exec_assign_value(PLpgSQL_execstate *estate,
- PLpgSQL_datum *target,
- Datum value, Oid valtype, bool *isNull)
+static void
+exec_assign_value(PLpgSQL_execstate * estate,
+ PLpgSQL_datum * target,
+ Datum value, Oid valtype, bool *isNull)
{
- PLpgSQL_var *var;
- PLpgSQL_rec *rec;
- PLpgSQL_recfield *recfield;
- int fno;
- int i;
- int natts;
- Datum *values;
- char *nulls;
- bool attisnull;
- Oid atttype;
- int4 atttypmod;
- HeapTuple typetup;
- Form_pg_type typeStruct;
- FmgrInfo finfo_input;
-
- switch (target->dtype) {
- case PLPGSQL_DTYPE_VAR:
- /* ----------
- * Target field is a variable - that's easy
- * ----------
- */
- var = (PLpgSQL_var *)target;
- var->value = exec_cast_value(value, valtype, var->datatype->typoid,
- &(var->datatype->typinput),
- var->datatype->atttypmod, isNull);
-
- if (isNull && var->notnull) {
- elog(ERROR, "NULL assignment to variable '%s' declared NOT NULL", var->refname);
- }
-
- var->isnull = *isNull;
- break;
-
- case PLPGSQL_DTYPE_RECFIELD:
- /* ----------
- * Target field is a record
- * ----------
- */
- recfield = (PLpgSQL_recfield *)target;
- rec = (PLpgSQL_rec *)(estate->datums[recfield->recno]);
-
- /* ----------
- * Check that there is already a tuple in the record.
- * We need that because records don't have any predefined
- * field structure.
- * ----------
- */
- if (!HeapTupleIsValid(rec->tup)) {
- elog(ERROR, "record %s is unassigned yet - don't know it's tuple structure", rec->refname);
- }
-
- /* ----------
- * Get the number of the records field to change and the
- * number of attributes in the tuple.
- * ----------
- */
- fno = SPI_fnumber(rec->tupdesc, recfield->fieldname);
- if (fno == SPI_ERROR_NOATTRIBUTE) {
- elog(ERROR, "record %s has no field %s", rec->refname, recfield->fieldname);
- }
- fno--;
- natts = rec->tupdesc->natts;
-
- /* ----------
- * We loop over the attributes of the rec's current tuple
- * and collect the values in a Datum array along with the
- * nulls information.
- * ----------
- */
- values = palloc(sizeof(Datum) * natts);
- nulls = palloc(natts + 1);
-
- for (i = 0; i < natts; i++) {
- /* ----------
- * If this isn't the field we assign to, just use the
- * value that's already in the tuple.
- * ----------
- */
- if (i != fno) {
- values[i] = SPI_getbinval(rec->tup, rec->tupdesc,
- i + 1, &attisnull);
- if (attisnull) {
- nulls[i] = 'n';
- } else {
- nulls[i] = ' ';
- }
- continue;
- }
+ PLpgSQL_var *var;
+ PLpgSQL_rec *rec;
+ PLpgSQL_recfield *recfield;
+ int fno;
+ int i;
+ int natts;
+ Datum *values;
+ char *nulls;
+ bool attisnull;
+ Oid atttype;
+ int4 atttypmod;
+ HeapTuple typetup;
+ Form_pg_type typeStruct;
+ FmgrInfo finfo_input;
+
+ switch (target->dtype)
+ {
+ case PLPGSQL_DTYPE_VAR:
+ /* ----------
+ * Target field is a variable - that's easy
+ * ----------
+ */
+ var = (PLpgSQL_var *) target;
+ var->value = exec_cast_value(value, valtype, var->datatype->typoid,
+ &(var->datatype->typinput),
+ var->datatype->atttypmod, isNull);
+
+ if (isNull && var->notnull)
+ elog(ERROR, "NULL assignment to variable '%s' declared NOT NULL", var->refname);
+
+ var->isnull = *isNull;
+ break;
- /* ----------
- * This is the field to change. Get it's type
- * and cast the value we insert to that type.
- * ----------
- */
- atttype = SPI_gettypeid(rec->tupdesc, i + 1);
- atttypmod = rec->tupdesc->attrs[i]->atttypmod;
- typetup = SearchSysCacheTuple(TYPOID,
- ObjectIdGetDatum(atttype), 0, 0, 0);
- if (!HeapTupleIsValid(typetup)) {
- elog(ERROR, "cache lookup for type %d failed", atttype);
- }
- typeStruct = (Form_pg_type) GETSTRUCT(typetup);
- fmgr_info(typeStruct->typinput, &finfo_input);
-
- attisnull = *isNull;
- values[i] = exec_cast_value(value, valtype,
- atttype, &finfo_input, atttypmod, &attisnull);
- if (attisnull) {
- nulls[i] = 'n';
- } else {
- nulls[i] = ' ';
- }
- }
-
- /* ----------
- * Now call heap_formtuple() to create a new tuple
- * that replaces the old one in the record.
- * ----------
- */
- nulls[i] = '\0';
- rec->tup = heap_formtuple(rec->tupdesc, values, nulls);
- pfree(values);
- pfree(nulls);
-
- break;
-
- default:
- elog(ERROR, "unknown dtype %d in exec_assign_value()",
- target->dtype);
- }
+ case PLPGSQL_DTYPE_RECFIELD:
+ /* ----------
+ * Target field is a record
+ * ----------
+ */
+ recfield = (PLpgSQL_recfield *) target;
+ rec = (PLpgSQL_rec *) (estate->datums[recfield->recno]);
+
+ /* ----------
+ * Check that there is already a tuple in the record.
+ * We need that because records don't have any predefined
+ * field structure.
+ * ----------
+ */
+ if (!HeapTupleIsValid(rec->tup))
+ elog(ERROR, "record %s is unassigned yet - don't know it's tuple structure", rec->refname);
+
+ /* ----------
+ * Get the number of the records field to change and the
+ * number of attributes in the tuple.
+ * ----------
+ */
+ fno = SPI_fnumber(rec->tupdesc, recfield->fieldname);
+ if (fno == SPI_ERROR_NOATTRIBUTE)
+ elog(ERROR, "record %s has no field %s", rec->refname, recfield->fieldname);
+ fno--;
+ natts = rec->tupdesc->natts;
+
+ /* ----------
+ * We loop over the attributes of the rec's current tuple
+ * and collect the values in a Datum array along with the
+ * nulls information.
+ * ----------
+ */
+ values = palloc(sizeof(Datum) * natts);
+ nulls = palloc(natts + 1);
+
+ for (i = 0; i < natts; i++)
+ {
+ /* ----------
+ * If this isn't the field we assign to, just use the
+ * value that's already in the tuple.
+ * ----------
+ */
+ if (i != fno)
+ {
+ values[i] = SPI_getbinval(rec->tup, rec->tupdesc,
+ i + 1, &attisnull);
+ if (attisnull)
+ nulls[i] = 'n';
+ else
+ nulls[i] = ' ';
+ continue;
+ }
+
+ /* ----------
+ * This is the field to change. Get it's type
+ * and cast the value we insert to that type.
+ * ----------
+ */
+ atttype = SPI_gettypeid(rec->tupdesc, i + 1);
+ atttypmod = rec->tupdesc->attrs[i]->atttypmod;
+ typetup = SearchSysCacheTuple(TYPOID,
+ ObjectIdGetDatum(atttype), 0, 0, 0);
+ if (!HeapTupleIsValid(typetup))
+ elog(ERROR, "cache lookup for type %d failed", atttype);
+ typeStruct = (Form_pg_type) GETSTRUCT(typetup);
+ fmgr_info(typeStruct->typinput, &finfo_input);
+
+ attisnull = *isNull;
+ values[i] = exec_cast_value(value, valtype,
+ atttype, &finfo_input, atttypmod, &attisnull);
+ if (attisnull)
+ nulls[i] = 'n';
+ else
+ nulls[i] = ' ';
+ }
+
+ /* ----------
+ * Now call heap_formtuple() to create a new tuple
+ * that replaces the old one in the record.
+ * ----------
+ */
+ nulls[i] = '\0';
+ rec->tup = heap_formtuple(rec->tupdesc, values, nulls);
+ pfree(values);
+ pfree(nulls);
+
+ break;
+
+ default:
+ elog(ERROR, "unknown dtype %d in exec_assign_value()",
+ target->dtype);
+ }
}
@@ -1920,44 +1979,43 @@ static void exec_assign_value(PLpgSQL_execstate *estate,
* the result Datum.
* ----------
*/
-static Datum exec_eval_expr(PLpgSQL_execstate *estate,
- PLpgSQL_expr *expr,
- bool *isNull,
- Oid *rettype)
+static Datum
+exec_eval_expr(PLpgSQL_execstate * estate,
+ PLpgSQL_expr * expr,
+ bool *isNull,
+ Oid *rettype)
{
- int rc;
-
- rc = exec_run_select(estate, expr, 2);
- if (rc != SPI_OK_SELECT) {
- elog(ERROR, "query \"%s\" didn't return data", expr->query);
- }
-
- /* ----------
- * If there are no rows selected, the result is NULL.
- * ----------
- */
- if (SPI_processed == 0) {
- *isNull = true;
- return (Datum)0;
- }
-
- /* ----------
- * Check that the expression returned one single Datum
- * ----------
- */
- if (SPI_processed > 1) {
- elog(ERROR, "query \"%s\" didn't return a single value", expr->query);
- }
- if (SPI_tuptable->tupdesc->natts != 1) {
- elog(ERROR, "query \"%s\" didn't return a single value", expr->query);
- }
-
- /* ----------
- * Return the result and it's type
- * ----------
- */
- *rettype = SPI_gettypeid(SPI_tuptable->tupdesc, 1);
- return SPI_getbinval(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1, isNull);
+ int rc;
+
+ rc = exec_run_select(estate, expr, 2);
+ if (rc != SPI_OK_SELECT)
+ elog(ERROR, "query \"%s\" didn't return data", expr->query);
+
+ /* ----------
+ * If there are no rows selected, the result is NULL.
+ * ----------
+ */
+ if (SPI_processed == 0)
+ {
+ *isNull = true;
+ return (Datum) 0;
+ }
+
+ /* ----------
+ * Check that the expression returned one single Datum
+ * ----------
+ */
+ if (SPI_processed > 1)
+ elog(ERROR, "query \"%s\" didn't return a single value", expr->query);
+ if (SPI_tuptable->tupdesc->natts != 1)
+ elog(ERROR, "query \"%s\" didn't return a single value", expr->query);
+
+ /* ----------
+ * Return the result and it's type
+ * ----------
+ */
+ *rettype = SPI_gettypeid(SPI_tuptable->tupdesc, 1);
+ return SPI_getbinval(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1, isNull);
}
@@ -1965,152 +2023,152 @@ static Datum exec_eval_expr(PLpgSQL_execstate *estate,
* exec_run_select Execute a select query
* ----------
*/
-static int exec_run_select(PLpgSQL_execstate *estate,
- PLpgSQL_expr *expr, int maxtuples)
+static int
+exec_run_select(PLpgSQL_execstate * estate,
+ PLpgSQL_expr * expr, int maxtuples)
{
- PLpgSQL_var *var;
- PLpgSQL_rec *rec;
- PLpgSQL_recfield *recfield;
- PLpgSQL_trigarg *trigarg;
- int tgargno;
- Oid tgargoid;
- int i;
- Datum *values;
- char *nulls;
- int rc;
- int fno;
- bool isnull;
-
- /* ----------
- * On the first call for this expression generate the plan
- * ----------
- */
- if (expr->plan == NULL) {
- void *plan;
- Oid *argtypes;
+ PLpgSQL_var *var;
+ PLpgSQL_rec *rec;
+ PLpgSQL_recfield *recfield;
+ PLpgSQL_trigarg *trigarg;
+ int tgargno;
+ Oid tgargoid;
+ int i;
+ Datum *values;
+ char *nulls;
+ int rc;
+ int fno;
+ bool isnull;
/* ----------
- * Setup the argtypes array
+ * On the first call for this expression generate the plan
* ----------
*/
- argtypes = malloc(sizeof(Oid *) * (expr->nparams + 1));
+ if (expr->plan == NULL)
+ {
+ void *plan;
+ Oid *argtypes;
+
+ /* ----------
+ * Setup the argtypes array
+ * ----------
+ */
+ argtypes = malloc(sizeof(Oid *) * (expr->nparams + 1));
- for (i = 0; i < expr->nparams; i++) {
- switch (estate->datums[expr->params[i]]->dtype) {
- case PLPGSQL_DTYPE_VAR:
- var = (PLpgSQL_var *)(estate->datums[expr->params[i]]);
- argtypes[i] = var->datatype->typoid;
- break;
+ for (i = 0; i < expr->nparams; i++)
+ {
+ switch (estate->datums[expr->params[i]]->dtype)
+ {
+ case PLPGSQL_DTYPE_VAR:
+ var = (PLpgSQL_var *) (estate->datums[expr->params[i]]);
+ argtypes[i] = var->datatype->typoid;
+ break;
+
+ case PLPGSQL_DTYPE_RECFIELD:
+ recfield = (PLpgSQL_recfield *) (estate->datums[expr->params[i]]);
+ rec = (PLpgSQL_rec *) (estate->datums[recfield->recno]);
+
+ if (!HeapTupleIsValid(rec->tup))
+ elog(ERROR, "record %s is unassigned yet", rec->refname);
+ fno = SPI_fnumber(rec->tupdesc, recfield->fieldname);
+ if (fno == SPI_ERROR_NOATTRIBUTE)
+ elog(ERROR, "record %s has no field %s", rec->refname, recfield->fieldname);
+ argtypes[i] = SPI_gettypeid(rec->tupdesc, fno);
+ break;
+
+ case PLPGSQL_DTYPE_TRIGARG:
+ argtypes[i] = (Oid) TEXTOID;
+ break;
+
+ default:
+ elog(ERROR, "unknown parameter dtype %d in exec_run_select()", estate->datums[expr->params[i]]);
+ }
+ }
- case PLPGSQL_DTYPE_RECFIELD:
- recfield = (PLpgSQL_recfield *)(estate->datums[expr->params[i]]);
- rec = (PLpgSQL_rec *)(estate->datums[recfield->recno]);
-
- if (!HeapTupleIsValid(rec->tup)) {
- elog(ERROR, "record %s is unassigned yet", rec->refname);
- }
- fno = SPI_fnumber(rec->tupdesc, recfield->fieldname);
- if (fno == SPI_ERROR_NOATTRIBUTE) {
- elog(ERROR, "record %s has no field %s", rec->refname, recfield->fieldname);
- }
- argtypes[i] = SPI_gettypeid(rec->tupdesc, fno);
- break;
-
- case PLPGSQL_DTYPE_TRIGARG:
- argtypes[i] = (Oid)TEXTOID;
- break;
-
- default:
- elog(ERROR, "unknown parameter dtype %d in exec_run_select()", estate->datums[expr->params[i]]);
- }
+ /* ----------
+ * Generate and save the plan
+ * ----------
+ */
+ plan = SPI_prepare(expr->query, expr->nparams, argtypes);
+ if (plan == NULL)
+ elog(ERROR, "SPI_prepare() failed on \"%s\"", expr->query);
+ expr->plan = SPI_saveplan(plan);
+ expr->plan_argtypes = argtypes;
}
/* ----------
- * Generate and save the plan
+ * Now build up the values and nulls arguments for SPI_execp()
* ----------
*/
- plan = SPI_prepare(expr->query, expr->nparams, argtypes);
- if (plan == NULL) {
- elog(ERROR, "SPI_prepare() failed on \"%s\"", expr->query);
+ values = palloc(sizeof(Datum) * (expr->nparams + 1));
+ nulls = palloc(expr->nparams + 1);
+
+ for (i = 0; i < expr->nparams; i++)
+ {
+ switch (estate->datums[expr->params[i]]->dtype)
+ {
+ case PLPGSQL_DTYPE_VAR:
+ var = (PLpgSQL_var *) (estate->datums[expr->params[i]]);
+ values[i] = var->value;
+ if (var->isnull)
+ nulls[i] = 'n';
+ else
+ nulls[i] = ' ';
+ break;
+
+ case PLPGSQL_DTYPE_RECFIELD:
+ recfield = (PLpgSQL_recfield *) (estate->datums[expr->params[i]]);
+ rec = (PLpgSQL_rec *) (estate->datums[recfield->recno]);
+
+ if (!HeapTupleIsValid(rec->tup))
+ elog(ERROR, "record %s is unassigned yet", rec->refname);
+ fno = SPI_fnumber(rec->tupdesc, recfield->fieldname);
+ if (fno == SPI_ERROR_NOATTRIBUTE)
+ elog(ERROR, "record %s has no field %s", rec->refname, recfield->fieldname);
+
+ if (expr->plan_argtypes[i] != SPI_gettypeid(rec->tupdesc, fno))
+ elog(ERROR, "type of %s.%s doesn't match that when preparing the plan", rec->refname, recfield->fieldname);
+
+ values[i] = SPI_getbinval(rec->tup, rec->tupdesc, fno, &isnull);
+ if (isnull)
+ nulls[i] = 'n';
+ else
+ nulls[i] = ' ';
+ break;
+
+ case PLPGSQL_DTYPE_TRIGARG:
+ trigarg = (PLpgSQL_trigarg *) (estate->datums[expr->params[i]]);
+ tgargno = (int) exec_eval_expr(estate, trigarg->argnum,
+ &isnull, &tgargoid);
+ if (isnull || tgargno < 0 || tgargno >= estate->trig_nargs)
+ {
+ values[i] = 0;
+ nulls[i] = 'n';
+ }
+ else
+ {
+ values[i] = estate->trig_argv[tgargno];
+ nulls[i] = ' ';
+ }
+ break;
+
+ default:
+ elog(ERROR, "unknown parameter dtype %d in exec_eval_expr()", estate->datums[expr->params[i]]);
+ }
}
- expr->plan = SPI_saveplan(plan);
- expr->plan_argtypes = argtypes;
- }
-
- /* ----------
- * Now build up the values and nulls arguments for SPI_execp()
- * ----------
- */
- values = palloc(sizeof(Datum) * (expr->nparams + 1));
- nulls = palloc(expr->nparams + 1);
-
- for (i = 0; i < expr->nparams; i++) {
- switch (estate->datums[expr->params[i]]->dtype) {
- case PLPGSQL_DTYPE_VAR:
- var = (PLpgSQL_var *)(estate->datums[expr->params[i]]);
- values[i] = var->value;
- if (var->isnull) {
- nulls[i] = 'n';
- } else {
- nulls[i] = ' ';
- }
- break;
+ nulls[i] = '\0';
- case PLPGSQL_DTYPE_RECFIELD:
- recfield = (PLpgSQL_recfield *)(estate->datums[expr->params[i]]);
- rec = (PLpgSQL_rec *)(estate->datums[recfield->recno]);
-
- if (!HeapTupleIsValid(rec->tup)) {
- elog(ERROR, "record %s is unassigned yet", rec->refname);
- }
- fno = SPI_fnumber(rec->tupdesc, recfield->fieldname);
- if (fno == SPI_ERROR_NOATTRIBUTE) {
- elog(ERROR, "record %s has no field %s", rec->refname, recfield->fieldname);
- }
-
- if (expr->plan_argtypes[i] != SPI_gettypeid(rec->tupdesc, fno)) {
- elog(ERROR, "type of %s.%s doesn't match that when preparing the plan", rec->refname, recfield->fieldname);
- }
-
- values[i] = SPI_getbinval(rec->tup, rec->tupdesc, fno, &isnull);
- if (isnull) {
- nulls[i] = 'n';
- } else {
- nulls[i] = ' ';
- }
- break;
-
- case PLPGSQL_DTYPE_TRIGARG:
- trigarg = (PLpgSQL_trigarg *)(estate->datums[expr->params[i]]);
- tgargno = (int)exec_eval_expr(estate, trigarg->argnum,
- &isnull, &tgargoid);
- if (isnull || tgargno < 0 || tgargno >= estate->trig_nargs) {
- values[i] = 0;
- nulls[i] = 'n';
- } else {
- values[i] = estate->trig_argv[tgargno];
- nulls[i] = ' ';
- }
- break;
-
- default:
- elog(ERROR, "unknown parameter dtype %d in exec_eval_expr()", estate->datums[expr->params[i]]);
- }
- }
- nulls[i] = '\0';
-
- /* ----------
- * Execute the query
- * ----------
- */
- rc = SPI_execp(expr->plan, values, nulls, maxtuples);
- if (rc != SPI_OK_SELECT) {
- elog(ERROR, "query \"%s\" isn't a SELECT", expr->query);
- }
- pfree(values);
- pfree(nulls);
-
- return rc;
+ /* ----------
+ * Execute the query
+ * ----------
+ */
+ rc = SPI_execp(expr->plan, values, nulls, maxtuples);
+ if (rc != SPI_OK_SELECT)
+ elog(ERROR, "query \"%s\" isn't a SELECT", expr->query);
+ pfree(values);
+ pfree(nulls);
+
+ return rc;
}
@@ -2119,69 +2177,81 @@ static int exec_run_select(PLpgSQL_execstate *estate,
* record or row
* ----------
*/
-static void exec_move_row(PLpgSQL_execstate *estate,
- PLpgSQL_rec *rec,
- PLpgSQL_row *row,
- HeapTuple tup, TupleDesc tupdesc)
+static void
+exec_move_row(PLpgSQL_execstate * estate,
+ PLpgSQL_rec * rec,
+ PLpgSQL_row * row,
+ HeapTuple tup, TupleDesc tupdesc)
{
- PLpgSQL_var *var;
- int i;
- Datum value;
- Oid valtype;
- bool isnull;
-
- /* ----------
- * Record is simple - just put the tuple and it's descriptor
- * into the record
- * ----------
- */
- if (rec != NULL) {
- if (HeapTupleIsValid(tup)) {
- rec->tup = tup;
- rec->tupdesc = tupdesc;
- } else {
- rec->tup = NULL;
- rec->tupdesc = NULL;
- }
+ PLpgSQL_var *var;
+ int i;
+ Datum value;
+ Oid valtype;
+ bool isnull;
- return;
- }
-
-
- /* ----------
- * Row is a bit more complicated in that we assign the single
- * attributes of the query to the variables the row points to.
- * ----------
- */
- if (row != NULL) {
- if (HeapTupleIsValid(tup)) {
- if (row->nfields != tupdesc->natts) {
- elog(ERROR, "query didn't return correct # of attributes for %s",
- row->refname);
- }
-
- for (i = 0; i < row->nfields; i++) {
- var = (PLpgSQL_var *)(estate->datums[row->varnos[i]]);
-
- valtype = SPI_gettypeid(tupdesc, i + 1);
- value = SPI_getbinval(tup, tupdesc, i + 1, &isnull);
- exec_assign_value(estate, estate->datums[row->varnos[i]],
- value, valtype, &isnull);
-
- }
- } else {
- for (i = 0; i < row->nfields; i++) {
- bool nullval = true;
-
- exec_assign_value(estate, estate->datums[row->varnos[i]],
- (Datum) 0, 0, &nullval);
- }
+ /* ----------
+ * Record is simple - just put the tuple and it's descriptor
+ * into the record
+ * ----------
+ */
+ if (rec != NULL)
+ {
+ if (HeapTupleIsValid(tup))
+ {
+ rec->tup = tup;
+ rec->tupdesc = tupdesc;
+ }
+ else
+ {
+ rec->tup = NULL;
+ rec->tupdesc = NULL;
+ }
+
+ return;
}
- return;
- }
- elog(ERROR, "unsupported target in exec_move_row()");
+ /* ----------
+ * Row is a bit more complicated in that we assign the single
+ * attributes of the query to the variables the row points to.
+ * ----------
+ */
+ if (row != NULL)
+ {
+ if (HeapTupleIsValid(tup))
+ {
+ if (row->nfields != tupdesc->natts)
+ {
+ elog(ERROR, "query didn't return correct # of attributes for %s",
+ row->refname);
+ }
+
+ for (i = 0; i < row->nfields; i++)
+ {
+ var = (PLpgSQL_var *) (estate->datums[row->varnos[i]]);
+
+ valtype = SPI_gettypeid(tupdesc, i + 1);
+ value = SPI_getbinval(tup, tupdesc, i + 1, &isnull);
+ exec_assign_value(estate, estate->datums[row->varnos[i]],
+ value, valtype, &isnull);
+
+ }
+ }
+ else
+ {
+ for (i = 0; i < row->nfields; i++)
+ {
+ bool nullval = true;
+
+ exec_assign_value(estate, estate->datums[row->varnos[i]],
+ (Datum) 0, 0, &nullval);
+ }
+ }
+
+ return;
+ }
+
+ elog(ERROR, "unsupported target in exec_move_row()");
}
@@ -2189,38 +2259,40 @@ static void exec_move_row(PLpgSQL_execstate *estate,
* exec_cast_value Cast a value if required
* ----------
*/
-static Datum exec_cast_value(Datum value, Oid valtype,
- Oid reqtype,
+static Datum
+exec_cast_value(Datum value, Oid valtype,
+ Oid reqtype,
FmgrInfo *reqinput,
int16 reqtypmod,
bool *isnull)
{
- if (!*isnull) {
- /* ----------
- * If the type of the queries return value isn't
- * that of the variable, convert it.
- * ----------
- */
- if (valtype != reqtype || reqtypmod > 0) {
- HeapTuple typetup;
- Form_pg_type typeStruct;
- FmgrInfo finfo_output;
- char *extval;
-
- typetup = SearchSysCacheTuple(TYPOID,
- ObjectIdGetDatum(valtype), 0, 0, 0);
- if (!HeapTupleIsValid(typetup)) {
- elog(ERROR, "cache lookup for type %d failed", valtype);
- }
- typeStruct = (Form_pg_type) GETSTRUCT(typetup);
-
- fmgr_info(typeStruct->typoutput, &finfo_output);
- extval = (char *)(*fmgr_faddr(&finfo_output))(value, &isnull, -1);
- value = (Datum)(*fmgr_faddr(reqinput))(extval, &isnull, reqtypmod);
+ if (!*isnull)
+ {
+ /* ----------
+ * If the type of the queries return value isn't
+ * that of the variable, convert it.
+ * ----------
+ */
+ if (valtype != reqtype || reqtypmod > 0)
+ {
+ HeapTuple typetup;
+ Form_pg_type typeStruct;
+ FmgrInfo finfo_output;
+ char *extval;
+
+ typetup = SearchSysCacheTuple(TYPOID,
+ ObjectIdGetDatum(valtype), 0, 0, 0);
+ if (!HeapTupleIsValid(typetup))
+ elog(ERROR, "cache lookup for type %d failed", valtype);
+ typeStruct = (Form_pg_type) GETSTRUCT(typetup);
+
+ fmgr_info(typeStruct->typoutput, &finfo_output);
+ extval = (char *) (*fmgr_faddr(&finfo_output)) (value, &isnull, -1);
+ value = (Datum) (*fmgr_faddr(reqinput)) (extval, &isnull, reqtypmod);
+ }
}
- }
- return value;
+ return value;
}
@@ -2229,13 +2301,12 @@ static Datum exec_cast_value(Datum value, Oid valtype,
* to true/false
* ----------
*/
-static void exec_set_found(PLpgSQL_execstate *estate, bool state)
+static void
+exec_set_found(PLpgSQL_execstate * estate, bool state)
{
- PLpgSQL_var *var;
-
- var = (PLpgSQL_var *)(estate->datums[estate->found_varno]);
- var->value = (Datum) state;
- var->isnull = false;
-}
-
+ PLpgSQL_var *var;
+ var = (PLpgSQL_var *) (estate->datums[estate->found_varno]);
+ var->value = (Datum) state;
+ var->isnull = false;
+}
diff --git a/src/pl/plpgsql/src/pl_funcs.c b/src/pl/plpgsql/src/pl_funcs.c
index e7f9fe722c7..5cb2b7002bb 100644
--- a/src/pl/plpgsql/src/pl_funcs.c
+++ b/src/pl/plpgsql/src/pl_funcs.c
@@ -3,35 +3,35 @@
* procedural language
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_funcs.c,v 1.1 1998/08/24 19:14:48 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_funcs.c,v 1.2 1998/09/01 04:40:24 momjian Exp $
*
- * This software is copyrighted by Jan Wieck - Hamburg.
+ * This software is copyrighted by Jan Wieck - Hamburg.
*
- * The author hereby grants permission to use, copy, modify,
- * distribute, and license this software and its documentation
- * for any purpose, provided that existing copyright notices are
- * retained in all copies and that this notice is included
- * verbatim in any distributions. No written agreement, license,
- * or royalty fee is required for any of the authorized uses.
- * Modifications to this software may be copyrighted by their
- * author and need not follow the licensing terms described
- * here, provided that the new terms are clearly indicated on
- * the first page of each file where they apply.
+ * The author hereby grants permission to use, copy, modify,
+ * distribute, and license this software and its documentation
+ * for any purpose, provided that existing copyright notices are
+ * retained in all copies and that this notice is included
+ * verbatim in any distributions. No written agreement, license,
+ * or royalty fee is required for any of the authorized uses.
+ * Modifications to this software may be copyrighted by their
+ * author and need not follow the licensing terms described
+ * here, provided that the new terms are clearly indicated on
+ * the first page of each file where they apply.
*
- * IN NO EVENT SHALL THE AUTHOR OR DISTRIBUTORS BE LIABLE TO ANY
- * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR
- * CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS
- * SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN
- * IF THE AUTHOR HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
+ * IN NO EVENT SHALL THE AUTHOR OR DISTRIBUTORS BE LIABLE TO ANY
+ * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR
+ * CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS
+ * SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN
+ * IF THE AUTHOR HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
*
- * THE AUTHOR AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
- * PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON
- * AN "AS IS" BASIS, AND THE AUTHOR AND DISTRIBUTORS HAVE NO
- * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
- * ENHANCEMENTS, OR MODIFICATIONS.
+ * THE AUTHOR AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON
+ * AN "AS IS" BASIS, AND THE AUTHOR AND DISTRIBUTORS HAVE NO
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
+ * ENHANCEMENTS, OR MODIFICATIONS.
*
**********************************************************************/
@@ -51,18 +51,19 @@
* Local variables for the namestack handling
* ----------
*/
-static PLpgSQL_ns *ns_current = NULL;
-static bool ns_localmode = false;
+static PLpgSQL_ns *ns_current = NULL;
+static bool ns_localmode = false;
/* ----------
* plpgsql_dstring_init Dynamic string initialization
* ----------
*/
-void plpgsql_dstring_init(PLpgSQL_dstring *ds)
+void
+plpgsql_dstring_init(PLpgSQL_dstring * ds)
{
- ds->value = palloc(ds->alloc = 512);
- ds->used = 0;
+ ds->value = palloc(ds->alloc = 512);
+ ds->used = 0;
}
@@ -70,9 +71,10 @@ void plpgsql_dstring_init(PLpgSQL_dstring *ds)
* plpgsql_dstring_free Dynamic string destruction
* ----------
*/
-void plpgsql_dstring_free(PLpgSQL_dstring *ds)
+void
+plpgsql_dstring_free(PLpgSQL_dstring * ds)
{
- pfree(ds->value);
+ pfree(ds->value);
}
@@ -80,17 +82,19 @@ void plpgsql_dstring_free(PLpgSQL_dstring *ds)
* plpgsql_dstring_append Dynamic string extending
* ----------
*/
-void plpgsql_dstring_append(PLpgSQL_dstring *ds, char *str)
+void
+plpgsql_dstring_append(PLpgSQL_dstring * ds, char *str)
{
- int len = strlen(str);
+ int len = strlen(str);
- if (ds->used + len + 1 > ds->alloc) {
- ds->alloc *= 2;
- ds->value = repalloc(ds->value, ds->alloc);
- }
+ if (ds->used + len + 1 > ds->alloc)
+ {
+ ds->alloc *= 2;
+ ds->value = repalloc(ds->value, ds->alloc);
+ }
- strcpy(&(ds->value[ds->used]), str);
- ds->used += len;
+ strcpy(&(ds->value[ds->used]), str);
+ ds->used += len;
}
@@ -98,9 +102,10 @@ void plpgsql_dstring_append(PLpgSQL_dstring *ds, char *str)
* plpgsql_dstring_get Dynamic string get value
* ----------
*/
-char *plpgsql_dstring_get(PLpgSQL_dstring *ds)
+char *
+plpgsql_dstring_get(PLpgSQL_dstring * ds)
{
- return ds->value;
+ return ds->value;
}
@@ -108,10 +113,11 @@ char *plpgsql_dstring_get(PLpgSQL_dstring *ds)
* plpgsql_ns_init Initialize the namestack
* ----------
*/
-void plpgsql_ns_init(void)
+void
+plpgsql_ns_init(void)
{
- ns_current = NULL;
- ns_localmode = false;
+ ns_current = NULL;
+ ns_localmode = false;
}
@@ -121,13 +127,14 @@ void plpgsql_ns_init(void)
* only.
* ----------
*/
-bool plpgsql_ns_setlocal(bool flag)
+bool
+plpgsql_ns_setlocal(bool flag)
{
- bool oldstate;
+ bool oldstate;
- oldstate = ns_localmode;
- ns_localmode = flag;
- return oldstate;
+ oldstate = ns_localmode;
+ ns_localmode = flag;
+ return oldstate;
}
@@ -135,16 +142,17 @@ bool plpgsql_ns_setlocal(bool flag)
* plpgsql_ns_push Enter a new namestack level
* ----------
*/
-void plpgsql_ns_push(char *label)
+void
+plpgsql_ns_push(char *label)
{
- PLpgSQL_ns *new;
+ PLpgSQL_ns *new;
- new = palloc(sizeof(PLpgSQL_ns));
- memset(new, 0, sizeof(PLpgSQL_ns));
- new->upper = ns_current;
- ns_current = new;
+ new = palloc(sizeof(PLpgSQL_ns));
+ memset(new, 0, sizeof(PLpgSQL_ns));
+ new->upper = ns_current;
+ ns_current = new;
- plpgsql_ns_additem(PLPGSQL_NSTYPE_LABEL, 0, label);
+ plpgsql_ns_additem(PLPGSQL_NSTYPE_LABEL, 0, label);
}
@@ -152,19 +160,19 @@ void plpgsql_ns_push(char *label)
* plpgsql_ns_pop Return to the previous level
* ----------
*/
-void plpgsql_ns_pop()
+void
+plpgsql_ns_pop()
{
- int i;
- PLpgSQL_ns *old;
+ int i;
+ PLpgSQL_ns *old;
- old = ns_current;
- ns_current = old->upper;
+ old = ns_current;
+ ns_current = old->upper;
- for (i = 0; i < old->items_used; i++) {
- pfree(old->items[i]);
- }
- pfree(old->items);
- pfree(old);
+ for (i = 0; i < old->items_used; i++)
+ pfree(old->items[i]);
+ pfree(old->items);
+ pfree(old);
}
@@ -173,30 +181,35 @@ void plpgsql_ns_pop()
* namestack level
* ----------
*/
-void plpgsql_ns_additem(int itemtype, int itemno, char *name)
+void
+plpgsql_ns_additem(int itemtype, int itemno, char *name)
{
- PLpgSQL_ns *ns = ns_current;
- PLpgSQL_nsitem *nse;
-
- if (name == NULL)
- name = "";
-
- if (ns->items_used == ns->items_alloc) {
- if (ns->items_alloc == 0) {
- ns->items_alloc = 32;
- ns->items = palloc(sizeof(PLpgSQL_nsitem *) * ns->items_alloc);
- } else {
- ns->items_alloc *= 2;
- ns->items = repalloc(ns->items,
- sizeof(PLpgSQL_nsitem *) * ns->items_alloc);
+ PLpgSQL_ns *ns = ns_current;
+ PLpgSQL_nsitem *nse;
+
+ if (name == NULL)
+ name = "";
+
+ if (ns->items_used == ns->items_alloc)
+ {
+ if (ns->items_alloc == 0)
+ {
+ ns->items_alloc = 32;
+ ns->items = palloc(sizeof(PLpgSQL_nsitem *) * ns->items_alloc);
+ }
+ else
+ {
+ ns->items_alloc *= 2;
+ ns->items = repalloc(ns->items,
+ sizeof(PLpgSQL_nsitem *) * ns->items_alloc);
+ }
}
- }
- nse = palloc(sizeof(PLpgSQL_nsitem) + strlen(name));
- nse->itemtype = itemtype;
- nse->itemno = itemno;
- strcpy(nse->name, name);
- ns->items[ns->items_used++] = nse;
+ nse = palloc(sizeof(PLpgSQL_nsitem) + strlen(name));
+ nse->itemtype = itemtype;
+ nse->itemno = itemno;
+ strcpy(nse->name, name);
+ ns->items[ns->items_used++] = nse;
}
@@ -204,54 +217,61 @@ void plpgsql_ns_additem(int itemtype, int itemno, char *name)
* plpgsql_ns_lookup Lookup for a word in the namestack
* ----------
*/
-PLpgSQL_nsitem *plpgsql_ns_lookup(char *name, char *label)
+PLpgSQL_nsitem *
+plpgsql_ns_lookup(char *name, char *label)
{
- PLpgSQL_ns *ns;
- int i;
-
- /* ----------
- * If a label is specified, lookup only in that
- * ----------
- */
- if (label != NULL) {
- for (ns = ns_current; ns != NULL; ns = ns->upper) {
- if (!strcmp(ns->items[0]->name, label)) {
- for (i = 1; i < ns->items_used; i++) {
- if (!strcmp(ns->items[i]->name, name)) {
- return ns->items[i];
- }
+ PLpgSQL_ns *ns;
+ int i;
+
+ /* ----------
+ * If a label is specified, lookup only in that
+ * ----------
+ */
+ if (label != NULL)
+ {
+ for (ns = ns_current; ns != NULL; ns = ns->upper)
+ {
+ if (!strcmp(ns->items[0]->name, label))
+ {
+ for (i = 1; i < ns->items_used; i++)
+ {
+ if (!strcmp(ns->items[i]->name, name))
+ return ns->items[i];
+ }
+ return NULL; /* name not found in specified label */
+ }
}
- return NULL; /* name not found in specified label */
- }
+ return NULL; /* label not found */
}
- return NULL; /* label not found */
- }
-
- /* ----------
- * No label given, lookup for visible labels ignoring localmode
- * ----------
- */
- for (ns = ns_current; ns != NULL; ns = ns->upper) {
- if (!strcmp(ns->items[0]->name, name)) {
- return ns->items[0];
- }
- }
-
- /* ----------
- * Finally lookup name in the namestack
- * ----------
- */
- for (ns = ns_current; ns != NULL; ns = ns->upper) {
- for (i = 1; i < ns->items_used; i++) {
- if (!strcmp(ns->items[i]->name, name))
- return ns->items[i];
+
+ /* ----------
+ * No label given, lookup for visible labels ignoring localmode
+ * ----------
+ */
+ for (ns = ns_current; ns != NULL; ns = ns->upper)
+ {
+ if (!strcmp(ns->items[0]->name, name))
+ return ns->items[0];
}
- if (ns_localmode) {
- return NULL; /* name not found in current namespace */
+
+ /* ----------
+ * Finally lookup name in the namestack
+ * ----------
+ */
+ for (ns = ns_current; ns != NULL; ns = ns->upper)
+ {
+ for (i = 1; i < ns->items_used; i++)
+ {
+ if (!strcmp(ns->items[i]->name, name))
+ return ns->items[i];
+ }
+ if (ns_localmode)
+ {
+ return NULL; /* name not found in current namespace */
+ }
}
- }
- return NULL;
+ return NULL;
}
@@ -259,39 +279,43 @@ PLpgSQL_nsitem *plpgsql_ns_lookup(char *name, char *label)
* plpgsql_ns_rename Rename a namespace entry
* ----------
*/
-void plpgsql_ns_rename(char *oldname, char *newname)
+void
+plpgsql_ns_rename(char *oldname, char *newname)
{
- PLpgSQL_ns *ns;
- PLpgSQL_nsitem *newitem;
- int i;
-
- /* ----------
- * Lookup in the current namespace only
- * ----------
- */
- /* ----------
- * Lookup name in the namestack
- * ----------
- */
- for (ns = ns_current; ns != NULL; ns = ns->upper) {
- for (i = 1; i < ns->items_used; i++) {
- if (!strcmp(ns->items[i]->name, oldname)) {
- newitem = palloc(sizeof(PLpgSQL_nsitem) + strlen(newname));
- newitem->itemtype = ns->items[i]->itemtype;
- newitem->itemno = ns->items[i]->itemno;
- strcpy(newitem->name, newname);
-
- pfree(oldname);
- pfree(newname);
-
- pfree(ns->items[i]);
- ns->items[i] = newitem;
- return;
- }
+ PLpgSQL_ns *ns;
+ PLpgSQL_nsitem *newitem;
+ int i;
+
+ /* ----------
+ * Lookup in the current namespace only
+ * ----------
+ */
+ /* ----------
+ * Lookup name in the namestack
+ * ----------
+ */
+ for (ns = ns_current; ns != NULL; ns = ns->upper)
+ {
+ for (i = 1; i < ns->items_used; i++)
+ {
+ if (!strcmp(ns->items[i]->name, oldname))
+ {
+ newitem = palloc(sizeof(PLpgSQL_nsitem) + strlen(newname));
+ newitem->itemtype = ns->items[i]->itemtype;
+ newitem->itemno = ns->items[i]->itemno;
+ strcpy(newitem->name, newname);
+
+ pfree(oldname);
+ pfree(newname);
+
+ pfree(ns->items[i]);
+ ns->items[i] = newitem;
+ return;
+ }
+ }
}
- }
- elog(ERROR, "there is no variable '%s' in the current block", oldname);
+ elog(ERROR, "there is no variable '%s' in the current block", oldname);
}
@@ -300,15 +324,18 @@ void plpgsql_ns_rename(char *oldname, char *newname)
* lower case
* ----------
*/
-char *plpgsql_tolower(char *s)
+char *
+plpgsql_tolower(char *s)
{
- char *cp;
+ char *cp;
- for (cp = s; *cp; cp++) {
- if (isupper(*cp)) *cp = tolower(*cp);
- }
+ for (cp = s; *cp; cp++)
+ {
+ if (isupper(*cp))
+ *cp = tolower(*cp);
+ }
- return s;
+ return s;
}
@@ -321,355 +348,373 @@ char *plpgsql_tolower(char *s)
static int dump_indent;
static void dump_ind();
-static void dump_stmt(PLpgSQL_stmt *stmt);
-static void dump_block(PLpgSQL_stmt_block *block);
-static void dump_assign(PLpgSQL_stmt_assign *stmt);
-static void dump_if(PLpgSQL_stmt_if *stmt);
-static void dump_loop(PLpgSQL_stmt_loop *stmt);
-static void dump_while(PLpgSQL_stmt_while *stmt);
-static void dump_fori(PLpgSQL_stmt_fori *stmt);
-static void dump_fors(PLpgSQL_stmt_fors *stmt);
-static void dump_select(PLpgSQL_stmt_select *stmt);
-static void dump_exit(PLpgSQL_stmt_exit *stmt);
-static void dump_return(PLpgSQL_stmt_return *stmt);
-static void dump_raise(PLpgSQL_stmt_raise *stmt);
-static void dump_execsql(PLpgSQL_stmt_execsql *stmt);
-static void dump_expr(PLpgSQL_expr *expr);
-
-
-static void dump_ind()
+static void dump_stmt(PLpgSQL_stmt * stmt);
+static void dump_block(PLpgSQL_stmt_block * block);
+static void dump_assign(PLpgSQL_stmt_assign * stmt);
+static void dump_if(PLpgSQL_stmt_if * stmt);
+static void dump_loop(PLpgSQL_stmt_loop * stmt);
+static void dump_while(PLpgSQL_stmt_while * stmt);
+static void dump_fori(PLpgSQL_stmt_fori * stmt);
+static void dump_fors(PLpgSQL_stmt_fors * stmt);
+static void dump_select(PLpgSQL_stmt_select * stmt);
+static void dump_exit(PLpgSQL_stmt_exit * stmt);
+static void dump_return(PLpgSQL_stmt_return * stmt);
+static void dump_raise(PLpgSQL_stmt_raise * stmt);
+static void dump_execsql(PLpgSQL_stmt_execsql * stmt);
+static void dump_expr(PLpgSQL_expr * expr);
+
+
+static void
+dump_ind()
{
- int i;
- for (i = 0; i < dump_indent; i++) {
- printf(" ");
- }
-}
+ int i;
-static void dump_stmt(PLpgSQL_stmt *stmt)
-{
- printf("%3d:", stmt->lineno);
- switch (stmt->cmd_type) {
- case PLPGSQL_STMT_BLOCK:
- dump_block((PLpgSQL_stmt_block *)stmt);
- break;
- case PLPGSQL_STMT_ASSIGN:
- dump_assign((PLpgSQL_stmt_assign *)stmt);
- break;
- case PLPGSQL_STMT_IF:
- dump_if((PLpgSQL_stmt_if *)stmt);
- break;
- case PLPGSQL_STMT_LOOP:
- dump_loop((PLpgSQL_stmt_loop *)stmt);
- break;
- case PLPGSQL_STMT_WHILE:
- dump_while((PLpgSQL_stmt_while *)stmt);
- break;
- case PLPGSQL_STMT_FORI:
- dump_fori((PLpgSQL_stmt_fori *)stmt);
- break;
- case PLPGSQL_STMT_FORS:
- dump_fors((PLpgSQL_stmt_fors *)stmt);
- break;
- case PLPGSQL_STMT_SELECT:
- dump_select((PLpgSQL_stmt_select *)stmt);
- break;
- case PLPGSQL_STMT_EXIT:
- dump_exit((PLpgSQL_stmt_exit *)stmt);
- break;
- case PLPGSQL_STMT_RETURN:
- dump_return((PLpgSQL_stmt_return *)stmt);
- break;
- case PLPGSQL_STMT_RAISE:
- dump_raise((PLpgSQL_stmt_raise *)stmt);
- break;
- case PLPGSQL_STMT_EXECSQL:
- dump_execsql((PLpgSQL_stmt_execsql *)stmt);
- break;
- default:
- elog(ERROR, "plpgsql_dump: unknown cmd_type %d\n", stmt->cmd_type);
- break;
- }
+ for (i = 0; i < dump_indent; i++)
+ printf(" ");
}
-static void dump_block(PLpgSQL_stmt_block *block)
+static void
+dump_stmt(PLpgSQL_stmt * stmt)
{
- int i;
- char *name;
-
- if (block->label == NULL) {
- name = "*unnamed*";
- } else {
- name = block->label;
- }
-
- dump_ind();
- printf("BLOCK <<%s>>\n", name);
-
- dump_indent += 2;
- for (i = 0; i < block->body->stmts_used; i++) {
- dump_stmt((PLpgSQL_stmt *)(block->body->stmts[i]));
- }
- dump_indent -= 2;
-
- dump_ind();
- printf(" END -- %s\n", name);
+ printf("%3d:", stmt->lineno);
+ switch (stmt->cmd_type)
+ {
+ case PLPGSQL_STMT_BLOCK:
+ dump_block((PLpgSQL_stmt_block *) stmt);
+ break;
+ case PLPGSQL_STMT_ASSIGN:
+ dump_assign((PLpgSQL_stmt_assign *) stmt);
+ break;
+ case PLPGSQL_STMT_IF:
+ dump_if((PLpgSQL_stmt_if *) stmt);
+ break;
+ case PLPGSQL_STMT_LOOP:
+ dump_loop((PLpgSQL_stmt_loop *) stmt);
+ break;
+ case PLPGSQL_STMT_WHILE:
+ dump_while((PLpgSQL_stmt_while *) stmt);
+ break;
+ case PLPGSQL_STMT_FORI:
+ dump_fori((PLpgSQL_stmt_fori *) stmt);
+ break;
+ case PLPGSQL_STMT_FORS:
+ dump_fors((PLpgSQL_stmt_fors *) stmt);
+ break;
+ case PLPGSQL_STMT_SELECT:
+ dump_select((PLpgSQL_stmt_select *) stmt);
+ break;
+ case PLPGSQL_STMT_EXIT:
+ dump_exit((PLpgSQL_stmt_exit *) stmt);
+ break;
+ case PLPGSQL_STMT_RETURN:
+ dump_return((PLpgSQL_stmt_return *) stmt);
+ break;
+ case PLPGSQL_STMT_RAISE:
+ dump_raise((PLpgSQL_stmt_raise *) stmt);
+ break;
+ case PLPGSQL_STMT_EXECSQL:
+ dump_execsql((PLpgSQL_stmt_execsql *) stmt);
+ break;
+ default:
+ elog(ERROR, "plpgsql_dump: unknown cmd_type %d\n", stmt->cmd_type);
+ break;
+ }
}
-static void dump_assign(PLpgSQL_stmt_assign *stmt)
+static void
+dump_block(PLpgSQL_stmt_block * block)
{
- dump_ind();
- printf("ASSIGN var %d := ", stmt->varno);
- dump_expr(stmt->expr);
- printf("\n");
+ int i;
+ char *name;
+
+ if (block->label == NULL)
+ name = "*unnamed*";
+ else
+ name = block->label;
+
+ dump_ind();
+ printf("BLOCK <<%s>>\n", name);
+
+ dump_indent += 2;
+ for (i = 0; i < block->body->stmts_used; i++)
+ dump_stmt((PLpgSQL_stmt *) (block->body->stmts[i]));
+ dump_indent -= 2;
+
+ dump_ind();
+ printf(" END -- %s\n", name);
}
-static void dump_if(PLpgSQL_stmt_if *stmt)
+static void
+dump_assign(PLpgSQL_stmt_assign * stmt)
{
- int i;
-
- dump_ind();
- printf("IF ");
- dump_expr(stmt->cond);
- printf(" THEN\n");
-
- dump_indent += 2;
- for (i = 0; i < stmt->true_body->stmts_used; i++) {
- dump_stmt((PLpgSQL_stmt *)(stmt->true_body->stmts[i]));
- }
- dump_indent -= 2;
-
- dump_ind();
- printf(" ELSE\n");
-
- dump_indent += 2;
- for (i = 0; i < stmt->false_body->stmts_used; i++) {
- dump_stmt((PLpgSQL_stmt *)(stmt->false_body->stmts[i]));
- }
- dump_indent -= 2;
-
- dump_ind();
- printf(" ENDIF\n");
+ dump_ind();
+ printf("ASSIGN var %d := ", stmt->varno);
+ dump_expr(stmt->expr);
+ printf("\n");
}
-static void dump_loop(PLpgSQL_stmt_loop *stmt)
+static void
+dump_if(PLpgSQL_stmt_if * stmt)
{
- int i;
+ int i;
+
+ dump_ind();
+ printf("IF ");
+ dump_expr(stmt->cond);
+ printf(" THEN\n");
- dump_ind();
- printf("LOOP\n");
+ dump_indent += 2;
+ for (i = 0; i < stmt->true_body->stmts_used; i++)
+ dump_stmt((PLpgSQL_stmt *) (stmt->true_body->stmts[i]));
+ dump_indent -= 2;
- dump_indent += 2;
- for (i = 0; i < stmt->body->stmts_used; i++) {
- dump_stmt((PLpgSQL_stmt *)(stmt->body->stmts[i]));
- }
- dump_indent -= 2;
+ dump_ind();
+ printf(" ELSE\n");
+
+ dump_indent += 2;
+ for (i = 0; i < stmt->false_body->stmts_used; i++)
+ dump_stmt((PLpgSQL_stmt *) (stmt->false_body->stmts[i]));
+ dump_indent -= 2;
- dump_ind();
- printf(" ENDLOOP\n");
+ dump_ind();
+ printf(" ENDIF\n");
}
-static void dump_while(PLpgSQL_stmt_while *stmt)
+static void
+dump_loop(PLpgSQL_stmt_loop * stmt)
{
- int i;
+ int i;
- dump_ind();
- printf("WHILE ");
- dump_expr(stmt->cond);
- printf("\n");
+ dump_ind();
+ printf("LOOP\n");
- dump_indent += 2;
- for (i = 0; i < stmt->body->stmts_used; i++) {
- dump_stmt((PLpgSQL_stmt *)(stmt->body->stmts[i]));
- }
- dump_indent -= 2;
+ dump_indent += 2;
+ for (i = 0; i < stmt->body->stmts_used; i++)
+ dump_stmt((PLpgSQL_stmt *) (stmt->body->stmts[i]));
+ dump_indent -= 2;
- dump_ind();
- printf(" ENDWHILE\n");
+ dump_ind();
+ printf(" ENDLOOP\n");
}
-static void dump_fori(PLpgSQL_stmt_fori *stmt)
+static void
+dump_while(PLpgSQL_stmt_while * stmt)
{
- int i;
-
- dump_ind();
- printf("FORI %s %s\n", stmt->var->refname, (stmt->reverse) ? "REVERSE" : "NORMAL");
-
- dump_indent += 2;
- dump_ind();
- printf(" lower = ");
- dump_expr(stmt->lower);
- printf("\n");
- dump_ind();
- printf(" upper = ");
- dump_expr(stmt->upper);
- printf("\n");
-
- for (i = 0; i < stmt->body->stmts_used; i++) {
- dump_stmt((PLpgSQL_stmt *)(stmt->body->stmts[i]));
- }
- dump_indent -= 2;
-
- dump_ind();
- printf(" ENDFORI\n");
+ int i;
+
+ dump_ind();
+ printf("WHILE ");
+ dump_expr(stmt->cond);
+ printf("\n");
+
+ dump_indent += 2;
+ for (i = 0; i < stmt->body->stmts_used; i++)
+ dump_stmt((PLpgSQL_stmt *) (stmt->body->stmts[i]));
+ dump_indent -= 2;
+
+ dump_ind();
+ printf(" ENDWHILE\n");
}
-static void dump_fors(PLpgSQL_stmt_fors *stmt)
+static void
+dump_fori(PLpgSQL_stmt_fori * stmt)
{
- int i;
+ int i;
- dump_ind();
- printf("FORS %s ", (stmt->rec != NULL) ? stmt->rec->refname : stmt->row->refname);
- dump_expr(stmt->query);
- printf("\n");
+ dump_ind();
+ printf("FORI %s %s\n", stmt->var->refname, (stmt->reverse) ? "REVERSE" : "NORMAL");
- dump_indent += 2;
- for (i = 0; i < stmt->body->stmts_used; i++) {
- dump_stmt((PLpgSQL_stmt *)(stmt->body->stmts[i]));
- }
- dump_indent -= 2;
+ dump_indent += 2;
+ dump_ind();
+ printf(" lower = ");
+ dump_expr(stmt->lower);
+ printf("\n");
+ dump_ind();
+ printf(" upper = ");
+ dump_expr(stmt->upper);
+ printf("\n");
+
+ for (i = 0; i < stmt->body->stmts_used; i++)
+ dump_stmt((PLpgSQL_stmt *) (stmt->body->stmts[i]));
+ dump_indent -= 2;
- dump_ind();
- printf(" ENDFORS\n");
+ dump_ind();
+ printf(" ENDFORI\n");
}
-static void dump_select(PLpgSQL_stmt_select *stmt)
+static void
+dump_fors(PLpgSQL_stmt_fors * stmt)
{
- dump_ind();
- printf("SELECT ");
- dump_expr(stmt->query);
- printf("\n");
+ int i;
+
+ dump_ind();
+ printf("FORS %s ", (stmt->rec != NULL) ? stmt->rec->refname : stmt->row->refname);
+ dump_expr(stmt->query);
+ printf("\n");
+
+ dump_indent += 2;
+ for (i = 0; i < stmt->body->stmts_used; i++)
+ dump_stmt((PLpgSQL_stmt *) (stmt->body->stmts[i]));
+ dump_indent -= 2;
- dump_indent += 2;
- if (stmt->rec != NULL) {
dump_ind();
- printf(" target = %d %s\n", stmt->rec->recno, stmt->rec->refname);
- }
- if (stmt->row != NULL) {
+ printf(" ENDFORS\n");
+}
+
+static void
+dump_select(PLpgSQL_stmt_select * stmt)
+{
dump_ind();
- printf(" target = %d %s\n", stmt->row->rowno, stmt->row->refname);
- }
- dump_indent -= 2;
+ printf("SELECT ");
+ dump_expr(stmt->query);
+ printf("\n");
+
+ dump_indent += 2;
+ if (stmt->rec != NULL)
+ {
+ dump_ind();
+ printf(" target = %d %s\n", stmt->rec->recno, stmt->rec->refname);
+ }
+ if (stmt->row != NULL)
+ {
+ dump_ind();
+ printf(" target = %d %s\n", stmt->row->rowno, stmt->row->refname);
+ }
+ dump_indent -= 2;
}
-static void dump_exit(PLpgSQL_stmt_exit *stmt)
+static void
+dump_exit(PLpgSQL_stmt_exit * stmt)
{
- dump_ind();
- printf("EXIT lbl='%s'", stmt->label);
- if (stmt->cond != NULL) {
- printf(" WHEN ");
- dump_expr(stmt->cond);
- }
- printf("\n");
+ dump_ind();
+ printf("EXIT lbl='%s'", stmt->label);
+ if (stmt->cond != NULL)
+ {
+ printf(" WHEN ");
+ dump_expr(stmt->cond);
+ }
+ printf("\n");
}
-static void dump_return(PLpgSQL_stmt_return *stmt)
+static void
+dump_return(PLpgSQL_stmt_return * stmt)
{
- dump_ind();
- printf("RETURN ");
- if (stmt->retrecno >= 0) {
- printf("record %d", stmt->retrecno);
- } else {
- if (stmt->expr == NULL) {
- printf("NULL");
- } else {
- dump_expr(stmt->expr);
+ dump_ind();
+ printf("RETURN ");
+ if (stmt->retrecno >= 0)
+ printf("record %d", stmt->retrecno);
+ else
+ {
+ if (stmt->expr == NULL)
+ printf("NULL");
+ else
+ dump_expr(stmt->expr);
}
- }
- printf("\n");
+ printf("\n");
}
-static void dump_raise(PLpgSQL_stmt_raise *stmt)
+static void
+dump_raise(PLpgSQL_stmt_raise * stmt)
{
- int i;
-
- dump_ind();
- printf("RAISE '%s'", stmt->message);
- for (i = 0; i < stmt->nparams; i++) {
- printf(" %d", stmt->params[i]);
- }
- printf("\n");
+ int i;
+
+ dump_ind();
+ printf("RAISE '%s'", stmt->message);
+ for (i = 0; i < stmt->nparams; i++)
+ printf(" %d", stmt->params[i]);
+ printf("\n");
}
-static void dump_execsql(PLpgSQL_stmt_execsql *stmt)
+static void
+dump_execsql(PLpgSQL_stmt_execsql * stmt)
{
- dump_ind();
- printf("EXECSQL ");
- dump_expr(stmt->sqlstmt);
- printf("\n");
+ dump_ind();
+ printf("EXECSQL ");
+ dump_expr(stmt->sqlstmt);
+ printf("\n");
}
-static void dump_expr(PLpgSQL_expr *expr)
+static void
+dump_expr(PLpgSQL_expr * expr)
{
- int i;
- printf("'%s", expr->query);
- if (expr->nparams > 0) {
- printf(" {");
- for(i = 0; i < expr->nparams; i++) {
- if (i > 0) printf(", ");
- printf("$%d=%d", i+1, expr->params[i]);
+ int i;
+
+ printf("'%s", expr->query);
+ if (expr->nparams > 0)
+ {
+ printf(" {");
+ for (i = 0; i < expr->nparams; i++)
+ {
+ if (i > 0)
+ printf(", ");
+ printf("$%d=%d", i + 1, expr->params[i]);
+ }
+ printf("}");
}
- printf("}");
- }
- printf("'");
+ printf("'");
}
-void plpgsql_dumptree(PLpgSQL_function *func)
+void
+plpgsql_dumptree(PLpgSQL_function * func)
{
- int i;
- PLpgSQL_datum *d;
+ int i;
+ PLpgSQL_datum *d;
- printf("\nExecution tree of successfully compiled PL/pgSQL function %s:\n",
- func->fn_name);
+ printf("\nExecution tree of successfully compiled PL/pgSQL function %s:\n",
+ func->fn_name);
- printf("\nFunctions data area:\n");
- for (i = 0; i < func->ndatums; i++) {
- d = func->datums[i];
+ printf("\nFunctions data area:\n");
+ for (i = 0; i < func->ndatums; i++)
+ {
+ d = func->datums[i];
- printf(" entry %d: ", i);
- switch (d->dtype) {
- case PLPGSQL_DTYPE_VAR:
+ printf(" entry %d: ", i);
+ switch (d->dtype)
{
- PLpgSQL_var *var = (PLpgSQL_var *)d;
- printf("VAR %-16s type %s (typoid %d) atttypmod %d\n",
- var->refname, var->datatype->typname,
- var->datatype->typoid,
- var->datatype->atttypmod);
+ case PLPGSQL_DTYPE_VAR:
+ {
+ PLpgSQL_var *var = (PLpgSQL_var *) d;
+
+ printf("VAR %-16s type %s (typoid %d) atttypmod %d\n",
+ var->refname, var->datatype->typname,
+ var->datatype->typoid,
+ var->datatype->atttypmod);
+ }
+ break;
+ case PLPGSQL_DTYPE_ROW:
+ {
+ PLpgSQL_row *row = (PLpgSQL_row *) d;
+ int i;
+
+ printf("ROW %-16s fields", row->refname);
+ for (i = 0; i < row->nfields; i++)
+ {
+ printf(" %s=var %d", row->fieldnames[i],
+ row->varnos[i]);
+ }
+ printf("\n");
+ }
+ break;
+ case PLPGSQL_DTYPE_REC:
+ printf("REC %s\n", ((PLpgSQL_rec *) d)->refname);
+ break;
+ case PLPGSQL_DTYPE_RECFIELD:
+ printf("RECFIELD %-16s of REC %d\n", ((PLpgSQL_recfield *) d)->fieldname, ((PLpgSQL_recfield *) d)->recno);
+ break;
+ case PLPGSQL_DTYPE_TRIGARG:
+ printf("TRIGARG ");
+ dump_expr(((PLpgSQL_trigarg *) d)->argnum);
+ printf("\n");
+ break;
+ default:
+ printf("??? unknown data type %d\n", d->dtype);
}
- break;
- case PLPGSQL_DTYPE_ROW:
- {
- PLpgSQL_row *row = (PLpgSQL_row *)d;
- int i;
- printf("ROW %-16s fields", row->refname);
- for (i = 0; i < row->nfields; i++) {
- printf(" %s=var %d", row->fieldnames[i],
- row->varnos[i]);
- }
- printf("\n");
- }
- break;
- case PLPGSQL_DTYPE_REC:
- printf("REC %s\n", ((PLpgSQL_rec *)d)->refname);
- break;
- case PLPGSQL_DTYPE_RECFIELD:
- printf("RECFIELD %-16s of REC %d\n", ((PLpgSQL_recfield *)d)->fieldname, ((PLpgSQL_recfield *)d)->recno);
- break;
- case PLPGSQL_DTYPE_TRIGARG:
- printf("TRIGARG ");
- dump_expr(((PLpgSQL_trigarg *)d)->argnum);
- printf("\n");
- break;
- default:
- printf("??? unknown data type %d\n", d->dtype);
}
- }
- printf("\nFunctions statements:\n");
-
- dump_indent = 0;
- printf("%3d:", func->action->lineno);
- dump_block(func->action);
- printf("\nEnd of execution tree of function %s\n\n", func->fn_name);
-}
-
+ printf("\nFunctions statements:\n");
+ dump_indent = 0;
+ printf("%3d:", func->action->lineno);
+ dump_block(func->action);
+ printf("\nEnd of execution tree of function %s\n\n", func->fn_name);
+}
diff --git a/src/pl/plpgsql/src/pl_handler.c b/src/pl/plpgsql/src/pl_handler.c
index 285fac81aff..8b2a0c8cba5 100644
--- a/src/pl/plpgsql/src/pl_handler.c
+++ b/src/pl/plpgsql/src/pl_handler.c
@@ -3,35 +3,35 @@
* procedural language
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_handler.c,v 1.1 1998/08/24 19:14:49 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_handler.c,v 1.2 1998/09/01 04:40:25 momjian Exp $
*
- * This software is copyrighted by Jan Wieck - Hamburg.
+ * This software is copyrighted by Jan Wieck - Hamburg.
*
- * The author hereby grants permission to use, copy, modify,
- * distribute, and license this software and its documentation
- * for any purpose, provided that existing copyright notices are
- * retained in all copies and that this notice is included
- * verbatim in any distributions. No written agreement, license,
- * or royalty fee is required for any of the authorized uses.
- * Modifications to this software may be copyrighted by their
- * author and need not follow the licensing terms described
- * here, provided that the new terms are clearly indicated on
- * the first page of each file where they apply.
+ * The author hereby grants permission to use, copy, modify,
+ * distribute, and license this software and its documentation
+ * for any purpose, provided that existing copyright notices are
+ * retained in all copies and that this notice is included
+ * verbatim in any distributions. No written agreement, license,
+ * or royalty fee is required for any of the authorized uses.
+ * Modifications to this software may be copyrighted by their
+ * author and need not follow the licensing terms described
+ * here, provided that the new terms are clearly indicated on
+ * the first page of each file where they apply.
*
- * IN NO EVENT SHALL THE AUTHOR OR DISTRIBUTORS BE LIABLE TO ANY
- * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR
- * CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS
- * SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN
- * IF THE AUTHOR HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
+ * IN NO EVENT SHALL THE AUTHOR OR DISTRIBUTORS BE LIABLE TO ANY
+ * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR
+ * CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS
+ * SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN
+ * IF THE AUTHOR HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
*
- * THE AUTHOR AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
- * PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON
- * AN "AS IS" BASIS, AND THE AUTHOR AND DISTRIBUTORS HAVE NO
- * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
- * ENHANCEMENTS, OR MODIFICATIONS.
+ * THE AUTHOR AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON
+ * AN "AS IS" BASIS, AND THE AUTHOR AND DISTRIBUTORS HAVE NO
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
+ * ENHANCEMENTS, OR MODIFICATIONS.
*
**********************************************************************/
@@ -57,14 +57,14 @@
#include "catalog/pg_type.h"
-static PLpgSQL_function *compiled_functions = NULL;
+static PLpgSQL_function *compiled_functions = NULL;
Datum plpgsql_call_handler(FmgrInfo *proinfo,
- FmgrValues *proargs, bool *isNull);
+ FmgrValues *proargs, bool *isNull);
static Datum plpgsql_func_handler(FmgrInfo *proinfo,
- FmgrValues *proargs, bool *isNull);
+ FmgrValues *proargs, bool *isNull);
static HeapTuple plpgsql_trigger_handler(FmgrInfo *proinfo);
@@ -78,40 +78,37 @@ static HeapTuple plpgsql_trigger_handler(FmgrInfo *proinfo);
* ----------
*/
Datum
-plpgsql_call_handler(FmgrInfo *proinfo,
- FmgrValues *proargs,
- bool *isNull)
+plpgsql_call_handler(FmgrInfo *proinfo,
+ FmgrValues *proargs,
+ bool *isNull)
{
- Datum retval;
-
- /* ----------
- * Connect to SPI manager
- * ----------
- */
- if (SPI_connect() != SPI_OK_CONNECT) {
- elog(ERROR, "plpgsql: cannot connect to SPI manager");
- }
-
- /* ----------
- * Determine if called as function or trigger and
- * call appropriate subhandler
- * ----------
- */
- if (CurrentTriggerData == NULL) {
- retval = plpgsql_func_handler(proinfo, proargs, isNull);
- } else {
- retval = (Datum)plpgsql_trigger_handler(proinfo);
- }
-
- /* ----------
- * Disconnect from SPI manager
- * ----------
- */
- if (SPI_finish() != SPI_OK_FINISH) {
- elog(ERROR, "plpgsql: SPI_finish() failed");
- }
-
- return retval;
+ Datum retval;
+
+ /* ----------
+ * Connect to SPI manager
+ * ----------
+ */
+ if (SPI_connect() != SPI_OK_CONNECT)
+ elog(ERROR, "plpgsql: cannot connect to SPI manager");
+
+ /* ----------
+ * Determine if called as function or trigger and
+ * call appropriate subhandler
+ * ----------
+ */
+ if (CurrentTriggerData == NULL)
+ retval = plpgsql_func_handler(proinfo, proargs, isNull);
+ else
+ retval = (Datum) plpgsql_trigger_handler(proinfo);
+
+ /* ----------
+ * Disconnect from SPI manager
+ * ----------
+ */
+ if (SPI_finish() != SPI_OK_FINISH)
+ elog(ERROR, "plpgsql: SPI_finish() failed");
+
+ return retval;
}
@@ -120,33 +117,35 @@ plpgsql_call_handler(FmgrInfo *proinfo,
* ----------
*/
static Datum
-plpgsql_func_handler(FmgrInfo *proinfo,
- FmgrValues *proargs,
- bool *isNull)
+plpgsql_func_handler(FmgrInfo *proinfo,
+ FmgrValues *proargs,
+ bool *isNull)
{
- PLpgSQL_function *func;
-
- /* ----------
- * Check if we already compiled this function
- * ----------
- */
- for (func = compiled_functions; func != NULL; func = func->next) {
- if (proinfo->fn_oid == func->fn_oid)
- break;
- }
-
- /* ----------
- * If not, do so and add it to the compiled ones
- * ----------
- */
- if (func == NULL) {
- func = plpgsql_compile(proinfo->fn_oid, T_FUNCTION);
-
- func->next = compiled_functions;
- compiled_functions = func;
- }
-
- return plpgsql_exec_function(func, proargs, isNull);
+ PLpgSQL_function *func;
+
+ /* ----------
+ * Check if we already compiled this function
+ * ----------
+ */
+ for (func = compiled_functions; func != NULL; func = func->next)
+ {
+ if (proinfo->fn_oid == func->fn_oid)
+ break;
+ }
+
+ /* ----------
+ * If not, do so and add it to the compiled ones
+ * ----------
+ */
+ if (func == NULL)
+ {
+ func = plpgsql_compile(proinfo->fn_oid, T_FUNCTION);
+
+ func->next = compiled_functions;
+ compiled_functions = func;
+ }
+
+ return plpgsql_exec_function(func, proargs, isNull);
}
@@ -157,37 +156,37 @@ plpgsql_func_handler(FmgrInfo *proinfo,
static HeapTuple
plpgsql_trigger_handler(FmgrInfo *proinfo)
{
- TriggerData *trigdata;
- PLpgSQL_function *func;
-
- /* ----------
- * Save the current trigger data local
- * ----------
- */
- trigdata = CurrentTriggerData;
- CurrentTriggerData = NULL;
-
- /* ----------
- * Check if we already compiled this trigger procedure
- * ----------
- */
- for (func = compiled_functions; func != NULL; func = func->next) {
- if (proinfo->fn_oid == func->fn_oid)
- break;
- }
-
- /* ----------
- * If not, do so and add it to the compiled ones
- * ----------
- */
- if (func == NULL) {
- func = plpgsql_compile(proinfo->fn_oid, T_TRIGGER);
-
- func->next = compiled_functions;
- compiled_functions = func;
- }
-
- return plpgsql_exec_trigger(func, trigdata);
+ TriggerData *trigdata;
+ PLpgSQL_function *func;
+
+ /* ----------
+ * Save the current trigger data local
+ * ----------
+ */
+ trigdata = CurrentTriggerData;
+ CurrentTriggerData = NULL;
+
+ /* ----------
+ * Check if we already compiled this trigger procedure
+ * ----------
+ */
+ for (func = compiled_functions; func != NULL; func = func->next)
+ {
+ if (proinfo->fn_oid == func->fn_oid)
+ break;
+ }
+
+ /* ----------
+ * If not, do so and add it to the compiled ones
+ * ----------
+ */
+ if (func == NULL)
+ {
+ func = plpgsql_compile(proinfo->fn_oid, T_TRIGGER);
+
+ func->next = compiled_functions;
+ compiled_functions = func;
+ }
+
+ return plpgsql_exec_trigger(func, trigdata);
}
-
-
diff --git a/src/pl/plpgsql/src/plpgsql.h b/src/pl/plpgsql/src/plpgsql.h
index 1c56ba814c3..281cdc64a1c 100644
--- a/src/pl/plpgsql/src/plpgsql.h
+++ b/src/pl/plpgsql/src/plpgsql.h
@@ -3,35 +3,35 @@
* procedural language
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.1 1998/08/24 19:14:49 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.2 1998/09/01 04:40:27 momjian Exp $
*
- * This software is copyrighted by Jan Wieck - Hamburg.
+ * This software is copyrighted by Jan Wieck - Hamburg.
*
- * The author hereby grants permission to use, copy, modify,
- * distribute, and license this software and its documentation
- * for any purpose, provided that existing copyright notices are
- * retained in all copies and that this notice is included
- * verbatim in any distributions. No written agreement, license,
- * or royalty fee is required for any of the authorized uses.
- * Modifications to this software may be copyrighted by their
- * author and need not follow the licensing terms described
- * here, provided that the new terms are clearly indicated on
- * the first page of each file where they apply.
+ * The author hereby grants permission to use, copy, modify,
+ * distribute, and license this software and its documentation
+ * for any purpose, provided that existing copyright notices are
+ * retained in all copies and that this notice is included
+ * verbatim in any distributions. No written agreement, license,
+ * or royalty fee is required for any of the authorized uses.
+ * Modifications to this software may be copyrighted by their
+ * author and need not follow the licensing terms described
+ * here, provided that the new terms are clearly indicated on
+ * the first page of each file where they apply.
*
- * IN NO EVENT SHALL THE AUTHOR OR DISTRIBUTORS BE LIABLE TO ANY
- * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR
- * CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS
- * SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN
- * IF THE AUTHOR HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
+ * IN NO EVENT SHALL THE AUTHOR OR DISTRIBUTORS BE LIABLE TO ANY
+ * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR
+ * CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS
+ * SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN
+ * IF THE AUTHOR HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
*
- * THE AUTHOR AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
- * PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON
- * AN "AS IS" BASIS, AND THE AUTHOR AND DISTRIBUTORS HAVE NO
- * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
- * ENHANCEMENTS, OR MODIFICATIONS.
+ * THE AUTHOR AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON
+ * AN "AS IS" BASIS, AND THE AUTHOR AND DISTRIBUTORS HAVE NO
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
+ * ENHANCEMENTS, OR MODIFICATIONS.
*
**********************************************************************/
#ifndef PLPGSQL_H
@@ -52,44 +52,47 @@
* Compilers namestack item types
* ----------
*/
-enum {
- PLPGSQL_NSTYPE_LABEL,
- PLPGSQL_NSTYPE_VAR,
- PLPGSQL_NSTYPE_ROW,
- PLPGSQL_NSTYPE_REC,
- PLPGSQL_NSTYPE_RECFIELD
+enum
+{
+ PLPGSQL_NSTYPE_LABEL,
+ PLPGSQL_NSTYPE_VAR,
+ PLPGSQL_NSTYPE_ROW,
+ PLPGSQL_NSTYPE_REC,
+ PLPGSQL_NSTYPE_RECFIELD
};
/* ----------
* Datum array node types
* ----------
*/
-enum {
- PLPGSQL_DTYPE_VAR,
- PLPGSQL_DTYPE_ROW,
- PLPGSQL_DTYPE_REC,
- PLPGSQL_DTYPE_RECFIELD,
- PLPGSQL_DTYPE_EXPR,
- PLPGSQL_DTYPE_TRIGARG
+enum
+{
+ PLPGSQL_DTYPE_VAR,
+ PLPGSQL_DTYPE_ROW,
+ PLPGSQL_DTYPE_REC,
+ PLPGSQL_DTYPE_RECFIELD,
+ PLPGSQL_DTYPE_EXPR,
+ PLPGSQL_DTYPE_TRIGARG
};
/* ----------
* Execution tree node types
* ----------
*/
-enum {
- PLPGSQL_STMT_BLOCK,
- PLPGSQL_STMT_ASSIGN,
- PLPGSQL_STMT_IF,
- PLPGSQL_STMT_LOOP,
- PLPGSQL_STMT_WHILE,
- PLPGSQL_STMT_FORI,
- PLPGSQL_STMT_FORS,
- PLPGSQL_STMT_SELECT,
- PLPGSQL_STMT_EXIT,
- PLPGSQL_STMT_RETURN,
- PLPGSQL_STMT_RAISE,
- PLPGSQL_STMT_EXECSQL
+enum
+{
+ PLPGSQL_STMT_BLOCK,
+ PLPGSQL_STMT_ASSIGN,
+ PLPGSQL_STMT_IF,
+ PLPGSQL_STMT_LOOP,
+ PLPGSQL_STMT_WHILE,
+ PLPGSQL_STMT_FORI,
+ PLPGSQL_STMT_FORS,
+ PLPGSQL_STMT_SELECT,
+ PLPGSQL_STMT_EXIT,
+ PLPGSQL_STMT_RETURN,
+ PLPGSQL_STMT_RAISE,
+ PLPGSQL_STMT_EXECSQL
};
@@ -97,10 +100,11 @@ enum {
* Execution node return codes
* ----------
*/
-enum {
- PLPGSQL_RC_OK,
- PLPGSQL_RC_EXIT,
- PLPGSQL_RC_RETURN
+enum
+{
+ PLPGSQL_RC_OK,
+ PLPGSQL_RC_EXIT,
+ PLPGSQL_RC_RETURN
};
/**********************************************************************
@@ -108,243 +112,269 @@ enum {
**********************************************************************/
-typedef struct { /* Dynamic string control structure */
- int alloc;
- int used;
- char *value;
-} PLpgSQL_dstring;
+typedef struct
+{ /* Dynamic string control structure */
+ int alloc;
+ int used;
+ char *value;
+} PLpgSQL_dstring;
-typedef struct { /* Postgres base data type */
- char *typname;
- Oid typoid;
+typedef struct
+{ /* Postgres base data type */
+ char *typname;
+ Oid typoid;
FmgrInfo typinput;
bool typbyval;
int16 atttypmod;
-} PLpgSQL_type;
+} PLpgSQL_type;
-typedef struct { /* Generic datum array item */
- int dtype;
- int dno;
-} PLpgSQL_datum;
+typedef struct
+{ /* Generic datum array item */
+ int dtype;
+ int dno;
+} PLpgSQL_datum;
-typedef struct { /* SQL Query to plan and execute */
- int dtype;
- int exprno;
- char *query;
- void *plan;
- Oid *plan_argtypes;
- int nparams;
- int params[1];
-} PLpgSQL_expr;
+typedef struct
+{ /* SQL Query to plan and execute */
+ int dtype;
+ int exprno;
+ char *query;
+ void *plan;
+ Oid *plan_argtypes;
+ int nparams;
+ int params[1];
+} PLpgSQL_expr;
-typedef struct { /* Local variable */
- int dtype;
- int varno;
- char *refname;
- int lineno;
+typedef struct
+{ /* Local variable */
+ int dtype;
+ int varno;
+ char *refname;
+ int lineno;
- PLpgSQL_type *datatype;
- int isconst;
- int notnull;
- PLpgSQL_expr *default_val;
+ PLpgSQL_type *datatype;
+ int isconst;
+ int notnull;
+ PLpgSQL_expr *default_val;
Datum value;
bool isnull;
- int shouldfree;
-} PLpgSQL_var;
+ int shouldfree;
+} PLpgSQL_var;
-typedef struct { /* Rowtype */
- int dtype;
- int rowno;
- char *refname;
- int lineno;
- Oid rowtypeclass;
+typedef struct
+{ /* Rowtype */
+ int dtype;
+ int rowno;
+ char *refname;
+ int lineno;
+ Oid rowtypeclass;
- int nfields;
- char **fieldnames;
- int *varnos;
-} PLpgSQL_row;
+ int nfields;
+ char **fieldnames;
+ int *varnos;
+} PLpgSQL_row;
-typedef struct { /* Record of undefined structure */
- int dtype;
- int recno;
- char *refname;
- int lineno;
+typedef struct
+{ /* Record of undefined structure */
+ int dtype;
+ int recno;
+ char *refname;
+ int lineno;
HeapTuple tup;
TupleDesc tupdesc;
-} PLpgSQL_rec;
+} PLpgSQL_rec;
-typedef struct { /* Field in record */
- int dtype;
- int rfno;
- char *fieldname;
- int recno;
-} PLpgSQL_recfield;
+typedef struct
+{ /* Field in record */
+ int dtype;
+ int rfno;
+ char *fieldname;
+ int recno;
+} PLpgSQL_recfield;
-typedef struct { /* Positional argument to trigger */
- int dtype;
- int dno;
- PLpgSQL_expr *argnum;
-} PLpgSQL_trigarg;
+typedef struct
+{ /* Positional argument to trigger */
+ int dtype;
+ int dno;
+ PLpgSQL_expr *argnum;
+} PLpgSQL_trigarg;
-typedef struct { /* Item in the compilers namestack */
- int itemtype;
- int itemno;
+typedef struct
+{ /* Item in the compilers namestack */
+ int itemtype;
+ int itemno;
char name[1];
-} PLpgSQL_nsitem;
+} PLpgSQL_nsitem;
-typedef struct PLpgSQL_ns { /* Compiler namestack level */
- int items_alloc;
- int items_used;
- PLpgSQL_nsitem **items;
+typedef struct PLpgSQL_ns
+{ /* Compiler namestack level */
+ int items_alloc;
+ int items_used;
+ PLpgSQL_nsitem **items;
struct PLpgSQL_ns *upper;
-} PLpgSQL_ns;
-
-
-typedef struct { /* List of execution nodes */
- int stmts_alloc;
- int stmts_used;
- struct PLpgSQL_stmt **stmts;
-} PLpgSQL_stmts;
-
-
-typedef struct { /* Generic execution node */
- int cmd_type;
- int lineno;
-} PLpgSQL_stmt;
-
-
-typedef struct { /* Block of statements */
- int cmd_type;
- int lineno;
- char *label;
- PLpgSQL_stmts *body;
- int n_initvars;
- int *initvarnos;
-} PLpgSQL_stmt_block;
-
-
-typedef struct { /* Assign statement */
- int cmd_type;
- int lineno;
- int varno;
- PLpgSQL_expr *expr;
-} PLpgSQL_stmt_assign;
-
-
-typedef struct { /* IF statement */
- int cmd_type;
- int lineno;
- PLpgSQL_expr *cond;
- PLpgSQL_stmts *true_body;
- PLpgSQL_stmts *false_body;
-} PLpgSQL_stmt_if;
-
-
-typedef struct { /* Unconditional LOOP statement */
- int cmd_type;
- int lineno;
- char *label;
- PLpgSQL_stmts *body;
-} PLpgSQL_stmt_loop;
-
-
-typedef struct { /* WHILE cond LOOP statement */
- int cmd_type;
- int lineno;
- char *label;
- PLpgSQL_expr *cond;
- PLpgSQL_stmts *body;
-} PLpgSQL_stmt_while;
-
-
-typedef struct { /* FOR statement with integer loopvar */
- int cmd_type;
- int lineno;
- char *label;
- PLpgSQL_var *var;
- PLpgSQL_expr *lower;
- PLpgSQL_expr *upper;
- int reverse;
- PLpgSQL_stmts *body;
-} PLpgSQL_stmt_fori;
-
-
-typedef struct { /* FOR statement running over SELECT */
- int cmd_type;
- int lineno;
- char *label;
- PLpgSQL_rec *rec;
- PLpgSQL_row *row;
- PLpgSQL_expr *query;
- PLpgSQL_stmts *body;
-} PLpgSQL_stmt_fors;
-
-
-typedef struct { /* SELECT ... INTO statement */
- int cmd_type;
- int lineno;
- PLpgSQL_rec *rec;
- PLpgSQL_row *row;
- PLpgSQL_expr *query;
-} PLpgSQL_stmt_select;
-
-
-typedef struct { /* EXIT statement */
- int cmd_type;
- int lineno;
- char *label;
- PLpgSQL_expr *cond;
-} PLpgSQL_stmt_exit;
-
-
-typedef struct { /* RETURN statement */
- int cmd_type;
- int lineno;
+} PLpgSQL_ns;
+
+
+typedef struct
+{ /* List of execution nodes */
+ int stmts_alloc;
+ int stmts_used;
+ struct PLpgSQL_stmt **stmts;
+} PLpgSQL_stmts;
+
+
+typedef struct
+{ /* Generic execution node */
+ int cmd_type;
+ int lineno;
+} PLpgSQL_stmt;
+
+
+typedef struct
+{ /* Block of statements */
+ int cmd_type;
+ int lineno;
+ char *label;
+ PLpgSQL_stmts *body;
+ int n_initvars;
+ int *initvarnos;
+} PLpgSQL_stmt_block;
+
+
+typedef struct
+{ /* Assign statement */
+ int cmd_type;
+ int lineno;
+ int varno;
+ PLpgSQL_expr *expr;
+} PLpgSQL_stmt_assign;
+
+
+typedef struct
+{ /* IF statement */
+ int cmd_type;
+ int lineno;
+ PLpgSQL_expr *cond;
+ PLpgSQL_stmts *true_body;
+ PLpgSQL_stmts *false_body;
+} PLpgSQL_stmt_if;
+
+
+typedef struct
+{ /* Unconditional LOOP statement */
+ int cmd_type;
+ int lineno;
+ char *label;
+ PLpgSQL_stmts *body;
+} PLpgSQL_stmt_loop;
+
+
+typedef struct
+{ /* WHILE cond LOOP statement */
+ int cmd_type;
+ int lineno;
+ char *label;
+ PLpgSQL_expr *cond;
+ PLpgSQL_stmts *body;
+} PLpgSQL_stmt_while;
+
+
+typedef struct
+{ /* FOR statement with integer loopvar */
+ int cmd_type;
+ int lineno;
+ char *label;
+ PLpgSQL_var *var;
+ PLpgSQL_expr *lower;
+ PLpgSQL_expr *upper;
+ int reverse;
+ PLpgSQL_stmts *body;
+} PLpgSQL_stmt_fori;
+
+
+typedef struct
+{ /* FOR statement running over SELECT */
+ int cmd_type;
+ int lineno;
+ char *label;
+ PLpgSQL_rec *rec;
+ PLpgSQL_row *row;
+ PLpgSQL_expr *query;
+ PLpgSQL_stmts *body;
+} PLpgSQL_stmt_fors;
+
+
+typedef struct
+{ /* SELECT ... INTO statement */
+ int cmd_type;
+ int lineno;
+ PLpgSQL_rec *rec;
+ PLpgSQL_row *row;
+ PLpgSQL_expr *query;
+} PLpgSQL_stmt_select;
+
+
+typedef struct
+{ /* EXIT statement */
+ int cmd_type;
+ int lineno;
+ char *label;
+ PLpgSQL_expr *cond;
+} PLpgSQL_stmt_exit;
+
+
+typedef struct
+{ /* RETURN statement */
+ int cmd_type;
+ int lineno;
bool retistuple;
- PLpgSQL_expr *expr;
- int retrecno;
-} PLpgSQL_stmt_return;
+ PLpgSQL_expr *expr;
+ int retrecno;
+} PLpgSQL_stmt_return;
-typedef struct { /* RAISE statement */
- int cmd_type;
- int lineno;
- int elog_level;
- char *message;
- int nparams;
- int *params;
-} PLpgSQL_stmt_raise;
+typedef struct
+{ /* RAISE statement */
+ int cmd_type;
+ int lineno;
+ int elog_level;
+ char *message;
+ int nparams;
+ int *params;
+} PLpgSQL_stmt_raise;
-typedef struct { /* Generic SQL statement to execute */
- int cmd_type;
- int lineno;
- PLpgSQL_expr *sqlstmt;
-} PLpgSQL_stmt_execsql;
+typedef struct
+{ /* Generic SQL statement to execute */
+ int cmd_type;
+ int lineno;
+ PLpgSQL_expr *sqlstmt;
+} PLpgSQL_stmt_execsql;
-typedef struct PLpgSQL_function { /* Complete compiled function */
+typedef struct PLpgSQL_function
+{ /* Complete compiled function */
Oid fn_oid;
- char *fn_name;
+ char *fn_name;
int fn_functype;
Oid fn_rettype;
int fn_rettyplen;
- bool fn_retbyval;
- FmgrInfo fn_retinput;
- bool fn_retistuple;
- bool fn_retset;
+ bool fn_retbyval;
+ FmgrInfo fn_retinput;
+ bool fn_retistuple;
+ bool fn_retset;
int fn_nargs;
int fn_argvarnos[MAXFMGRARGS];
@@ -360,43 +390,44 @@ typedef struct PLpgSQL_function { /* Complete compiled function */
int tg_nargs_varno;
int ndatums;
- PLpgSQL_datum **datums;
- PLpgSQL_stmt_block *action;
- struct PLpgSQL_function *next;
-} PLpgSQL_function;
+ PLpgSQL_datum **datums;
+ PLpgSQL_stmt_block *action;
+ struct PLpgSQL_function *next;
+} PLpgSQL_function;
-typedef struct { /* Runtime execution data */
- Datum retval;
- bool retisnull;
+typedef struct
+{ /* Runtime execution data */
+ Datum retval;
+ bool retisnull;
Oid rettype;
- bool retistuple;
- TupleDesc rettupdesc;
- bool retisset;
- char *exitlabel;
+ bool retistuple;
+ TupleDesc rettupdesc;
+ bool retisset;
+ char *exitlabel;
int trig_nargs;
- Datum *trig_argv;
+ Datum *trig_argv;
int found_varno;
int ndatums;
- PLpgSQL_datum **datums;
-} PLpgSQL_execstate;
+ PLpgSQL_datum **datums;
+} PLpgSQL_execstate;
/**********************************************************************
* Global variable declarations
**********************************************************************/
-extern int plpgsql_DumpExecTree;
-extern int plpgsql_SpaceScanned;
-extern int plpgsql_nDatums;
-extern PLpgSQL_datum **plpgsql_Datums;
+extern int plpgsql_DumpExecTree;
+extern int plpgsql_SpaceScanned;
+extern int plpgsql_nDatums;
+extern PLpgSQL_datum **plpgsql_Datums;
-extern int plpgsql_error_lineno;
-extern char *plpgsql_error_funcname;
+extern int plpgsql_error_lineno;
+extern char *plpgsql_error_funcname;
-extern PLpgSQL_function *plpgsql_curr_compile;
+extern PLpgSQL_function *plpgsql_curr_compile;
/**********************************************************************
@@ -404,72 +435,72 @@ extern PLpgSQL_function *plpgsql_curr_compile;
**********************************************************************/
-extern char *pstrdup(char *s);
+extern char *pstrdup(char *s);
/* ----------
* Functions in pl_comp.c
* ----------
*/
-extern PLpgSQL_function *plpgsql_compile(Oid fn_oid, int functype);
-extern int plpgsql_parse_word(char *word);
-extern int plpgsql_parse_dblword(char *string);
-extern int plpgsql_parse_tripword(char *string);
-extern int plpgsql_parse_wordtype(char *string);
-extern int plpgsql_parse_dblwordtype(char *string);
-extern int plpgsql_parse_wordrowtype(char *string);
-extern void plpgsql_adddatum(PLpgSQL_datum *new);
-extern int plpgsql_add_initdatums(int **varnos);
-extern void plpgsql_comperrinfo(void);
+extern PLpgSQL_function *plpgsql_compile(Oid fn_oid, int functype);
+extern int plpgsql_parse_word(char *word);
+extern int plpgsql_parse_dblword(char *string);
+extern int plpgsql_parse_tripword(char *string);
+extern int plpgsql_parse_wordtype(char *string);
+extern int plpgsql_parse_dblwordtype(char *string);
+extern int plpgsql_parse_wordrowtype(char *string);
+extern void plpgsql_adddatum(PLpgSQL_datum * new);
+extern int plpgsql_add_initdatums(int **varnos);
+extern void plpgsql_comperrinfo(void);
/* ----------
* Functions in pl_exec.c
* ----------
*/
-extern Datum plpgsql_exec_function(PLpgSQL_function *func,
- FmgrValues *args, bool *isNull);
-extern HeapTuple plpgsql_exec_trigger(PLpgSQL_function *func,
- TriggerData *trigdata);
+extern Datum plpgsql_exec_function(PLpgSQL_function * func,
+ FmgrValues *args, bool *isNull);
+extern HeapTuple plpgsql_exec_trigger(PLpgSQL_function * func,
+ TriggerData *trigdata);
/* ----------
* Functions for the dynamic string handling in pl_funcs.c
* ----------
*/
-extern void plpgsql_dstring_init(PLpgSQL_dstring *ds);
-extern void plpgsql_dstring_free(PLpgSQL_dstring *ds);
-extern void plpgsql_dstring_append(PLpgSQL_dstring *ds, char *str);
-extern char *plpgsql_dstring_get(PLpgSQL_dstring *ds);
+extern void plpgsql_dstring_init(PLpgSQL_dstring * ds);
+extern void plpgsql_dstring_free(PLpgSQL_dstring * ds);
+extern void plpgsql_dstring_append(PLpgSQL_dstring * ds, char *str);
+extern char *plpgsql_dstring_get(PLpgSQL_dstring * ds);
/* ----------
* Functions for the namestack handling in pl_funcs.c
* ----------
*/
-extern void plpgsql_ns_init(void);
-extern bool plpgsql_ns_setlocal(bool flag);
-extern void plpgsql_ns_push(char *label);
-extern void plpgsql_ns_pop(void);
-extern void plpgsql_ns_additem(int itemtype, int itemno, char *name);
-extern PLpgSQL_nsitem *plpgsql_ns_lookup(char *name, char *nsname);
-extern void plpgsql_ns_rename(char *oldname, char *newname);
+extern void plpgsql_ns_init(void);
+extern bool plpgsql_ns_setlocal(bool flag);
+extern void plpgsql_ns_push(char *label);
+extern void plpgsql_ns_pop(void);
+extern void plpgsql_ns_additem(int itemtype, int itemno, char *name);
+extern PLpgSQL_nsitem *plpgsql_ns_lookup(char *name, char *nsname);
+extern void plpgsql_ns_rename(char *oldname, char *newname);
/* ----------
* Other functions in pl_funcs.c
* ----------
*/
-extern void plpgsql_dumptree(PLpgSQL_function *func);
-extern char *plpgsql_tolower(char *s);
+extern void plpgsql_dumptree(PLpgSQL_function * func);
+extern char *plpgsql_tolower(char *s);
/* ----------
* Externs in gram.y and scan.l
* ----------
*/
-extern PLpgSQL_expr *plpgsql_read_expression(int until, char *s);
-extern void plpgsql_yyrestart(FILE *fp);
-extern int plpgsql_yylex();
-extern void plpgsql_setinput(char *s, int functype);
-extern int plpgsql_yyparse();
+extern PLpgSQL_expr *plpgsql_read_expression(int until, char *s);
+extern void plpgsql_yyrestart(FILE *fp);
+extern int plpgsql_yylex();
+extern void plpgsql_setinput(char *s, int functype);
+extern int plpgsql_yyparse();
-#endif /* PLPGSQL_H */
+#endif /* PLPGSQL_H */
diff --git a/src/pl/tcl/pltcl.c b/src/pl/tcl/pltcl.c
index 6202816afe8..c6f418d3315 100644
--- a/src/pl/tcl/pltcl.c
+++ b/src/pl/tcl/pltcl.c
@@ -3,7 +3,7 @@
* procedural language (PL)
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/pl/tcl/pltcl.c,v 1.5 1998/09/01 03:29:08 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/pl/tcl/pltcl.c,v 1.6 1998/09/01 04:40:28 momjian Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
@@ -127,40 +127,31 @@ static void pltcl_init_safe_interp(void);
#ifdef PLTCL_UNKNOWN_SUPPORT
static void pltcl_init_load_unknown(void);
-#endif /* PLTCL_UNKNOWN_SUPPORT */
+#endif /* PLTCL_UNKNOWN_SUPPORT */
-Datum
-pltcl_call_handler(FmgrInfo *proinfo,
+Datum pltcl_call_handler(FmgrInfo *proinfo,
FmgrValues *proargs, bool *isNull);
-static Datum
-pltcl_func_handler(FmgrInfo *proinfo,
+static Datum pltcl_func_handler(FmgrInfo *proinfo,
FmgrValues *proargs, bool *isNull);
static HeapTuple pltcl_trigger_handler(FmgrInfo *proinfo);
-static int
-pltcl_elog(ClientData cdata, Tcl_Interp * interp,
+static int pltcl_elog(ClientData cdata, Tcl_Interp * interp,
int argc, char *argv[]);
-static int
-pltcl_quote(ClientData cdata, Tcl_Interp * interp,
+static int pltcl_quote(ClientData cdata, Tcl_Interp * interp,
int argc, char *argv[]);
-static int
-pltcl_SPI_exec(ClientData cdata, Tcl_Interp * interp,
+static int pltcl_SPI_exec(ClientData cdata, Tcl_Interp * interp,
int argc, char *argv[]);
-static int
-pltcl_SPI_prepare(ClientData cdata, Tcl_Interp * interp,
+static int pltcl_SPI_prepare(ClientData cdata, Tcl_Interp * interp,
int argc, char *argv[]);
-static int
-pltcl_SPI_execp(ClientData cdata, Tcl_Interp * interp,
+static int pltcl_SPI_execp(ClientData cdata, Tcl_Interp * interp,
int argc, char *argv[]);
-static void
-pltcl_set_tuple_values(Tcl_Interp * interp, char *arrayname,
+static void pltcl_set_tuple_values(Tcl_Interp * interp, char *arrayname,
int tupno, HeapTuple tuple, TupleDesc tupdesc);
-static void
-pltcl_build_tuple_argument(HeapTuple tuple, TupleDesc tupdesc,
+static void pltcl_build_tuple_argument(HeapTuple tuple, TupleDesc tupdesc,
Tcl_DString * retval);
/**********************************************************************
@@ -306,7 +297,7 @@ pltcl_init_safe_interp(void)
pltcl_init_load_unknown();
if (SPI_finish() != SPI_OK_FINISH)
elog(ERROR, "pltcl_init_safe_interp(): SPI_finish failed");
-#endif /* PLTCL_UNKNOWN_SUPPORT */
+#endif /* PLTCL_UNKNOWN_SUPPORT */
}
@@ -382,7 +373,7 @@ pltcl_init_load_unknown(void)
Tcl_DStringFree(&unknown_src);
}
-#endif /* PLTCL_UNKNOWN_SUPPORT */
+#endif /* PLTCL_UNKNOWN_SUPPORT */
/**********************************************************************
@@ -514,7 +505,7 @@ pltcl_func_handler(FmgrInfo *proinfo,
* return value.
************************************************************/
typeTup = SearchSysCacheTuple(TYPOID,
- ObjectIdGetDatum(procStruct->prorettype),
+ ObjectIdGetDatum(procStruct->prorettype),
0, 0, 0);
if (!HeapTupleIsValid(typeTup))
{
@@ -544,7 +535,7 @@ pltcl_func_handler(FmgrInfo *proinfo,
for (i = 0; i < proinfo->fn_nargs; i++)
{
typeTup = SearchSysCacheTuple(TYPOID,
- ObjectIdGetDatum(procStruct->proargtypes[i]),
+ ObjectIdGetDatum(procStruct->proargtypes[i]),
0, 0, 0);
if (!HeapTupleIsValid(typeTup))
{
@@ -1139,7 +1130,7 @@ pltcl_trigger_handler(FmgrInfo *proinfo)
* for the input function
************************************************************/
typeTup = SearchSysCacheTuple(TYPOID,
- ObjectIdGetDatum(tupdesc->attrs[attnum - 1]->atttypid),
+ ObjectIdGetDatum(tupdesc->attrs[attnum - 1]->atttypid),
0, 0, 0);
if (!HeapTupleIsValid(typeTup))
{
@@ -2156,7 +2147,7 @@ pltcl_set_tuple_values(Tcl_Interp * interp, char *arrayname,
* for the output function
************************************************************/
typeTup = SearchSysCacheTuple(TYPOID,
- ObjectIdGetDatum(tupdesc->attrs[i]->atttypid),
+ ObjectIdGetDatum(tupdesc->attrs[i]->atttypid),
0, 0, 0);
if (!HeapTupleIsValid(typeTup))
{
@@ -2229,7 +2220,7 @@ pltcl_build_tuple_argument(HeapTuple tuple, TupleDesc tupdesc,
* for the output function
************************************************************/
typeTup = SearchSysCacheTuple(TYPOID,
- ObjectIdGetDatum(tupdesc->attrs[i]->atttypid),
+ ObjectIdGetDatum(tupdesc->attrs[i]->atttypid),
0, 0, 0);
if (!HeapTupleIsValid(typeTup))
{