* procedural language
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/gram.y,v 1.27 2001/10/09 15:59:56 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/gram.y,v 1.28 2001/11/15 23:31:09 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
{
plpgsql_ns_rename($2, $4);
}
- | decl_varname K_CURSOR decl_cursor_args decl_is_from K_SELECT decl_cursor_query
+ | decl_varname K_CURSOR
+ { plpgsql_ns_push(NULL); }
+ decl_cursor_args decl_is_from K_SELECT decl_cursor_query
{
PLpgSQL_var *new;
PLpgSQL_expr *curname_def;
char *cp1;
char *cp2;
+ /* pop local namespace for cursor args */
plpgsql_ns_pop();
new = malloc(sizeof(PLpgSQL_var));
*cp2++ = '\\';
*cp2++ = *cp1++;
}
- *cp2++ = '\'';
- *cp2 = '\0';
+ strcpy(cp2, "'::refcursor");
curname_def->query = strdup(buf);
new->default_val = curname_def;
new->datatype = plpgsql_parse_datatype("refcursor");
- new->cursor_explicit_expr = $6;
- if ($3 == NULL)
+ new->cursor_explicit_expr = $7;
+ if ($4 == NULL)
new->cursor_explicit_argrow = -1;
else
- new->cursor_explicit_argrow = $3->rowno;
+ new->cursor_explicit_argrow = $4->rowno;
plpgsql_adddatum((PLpgSQL_datum *)new);
plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, new->varno,
- $1.name);
+ $1.name);
}
;
{
$$ = NULL;
}
- | decl_cursor_openparen decl_cursor_arglist ')'
+ | '(' decl_cursor_arglist ')'
{
+ /* Copy the temp arrays to malloc'd storage */
+ int nfields = $2->nfields;
char **ftmp;
int *vtmp;
- ftmp = malloc($2->nfields * sizeof(char *));
- vtmp = malloc($2->nfields * sizeof(int));
- memcpy(ftmp, $2->fieldnames, $2->nfields * sizeof(char *));
- memcpy(vtmp, $2->varnos, $2->nfields * sizeof(int));
+ ftmp = malloc(nfields * sizeof(char *));
+ vtmp = malloc(nfields * sizeof(int));
+ memcpy(ftmp, $2->fieldnames, nfields * sizeof(char *));
+ memcpy(vtmp, $2->varnos, nfields * sizeof(int));
pfree((char *)($2->fieldnames));
pfree((char *)($2->varnos));
new->refname = strdup("*internal*");
new->lineno = yylineno;
new->rowtypeclass = InvalidOid;
+ /*
+ * We make temporary fieldnames/varnos arrays that
+ * are much bigger than necessary. We will resize
+ * them to just the needed size in the
+ * decl_cursor_args production.
+ */
new->fieldnames = palloc(1024 * sizeof(char *));
new->varnos = palloc(1024 * sizeof(int));
new->nfields = 1;
$1->fieldnames[i] = $3->refname;
$1->varnos[i] = $3->varno;
+
+ $$ = $1;
}
;
plpgsql_adddatum((PLpgSQL_datum *)new);
plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, new->varno,
- $1.name);
+ $1.name);
$$ = new;
}
;
-decl_cursor_openparen : '('
- {
- plpgsql_ns_push(NULL);
- }
- ;
-
decl_is_from : K_IS | /* Oracle */
K_FOR; /* ANSI */
* procedural language
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.51 2001/11/13 02:05:27 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.52 2001/11/15 23:31:09 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
elog(NOTICE, "Error occurred 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_GETDIAG:
- stmttype = "get diagnostics";
- 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;
- case PLPGSQL_STMT_DYNEXECUTE:
- stmttype = "execute statement";
- break;
- case PLPGSQL_STMT_DYNFORS:
- stmttype = "for over execute statement";
- break;
- case PLPGSQL_STMT_FETCH:
- stmttype = "fetch";
- break;
- case PLPGSQL_STMT_CLOSE:
- stmttype = "close";
- break;
- default:
- stmttype = "unknown";
- break;
- }
elog(NOTICE, "line %d at %s", error_info_stmt->lineno,
- stmttype);
- }
+ plpgsql_stmt_typename(error_info_stmt));
+ else if (error_info_text != NULL)
+ elog(NOTICE, "%s", error_info_text);
else
- {
- if (error_info_text != NULL)
- elog(NOTICE, "%s", error_info_text);
- else
- elog(NOTICE, "no more error information available");
- }
+ elog(NOTICE, "no more error information available");
error_info_func = NULL;
error_info_stmt = NULL;
elog(NOTICE, "Error occurred 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_GETDIAG:
- stmttype = "get diagnostics";
- 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;
- case PLPGSQL_STMT_DYNEXECUTE:
- stmttype = "execute statement";
- break;
- case PLPGSQL_STMT_DYNFORS:
- stmttype = "for over execute statement";
- break;
- default:
- stmttype = "unknown";
- break;
- }
elog(NOTICE, "line %d at %s", error_info_stmt->lineno,
- stmttype);
- }
+ plpgsql_stmt_typename(error_info_stmt));
+ else if (error_info_text != NULL)
+ elog(NOTICE, "%s", error_info_text);
else
- {
- if (error_info_text != NULL)
- elog(NOTICE, "%s", error_info_text);
- else
- elog(NOTICE, "no more error information available");
- }
+ elog(NOTICE, "no more error information available");
error_info_func = NULL;
error_info_stmt = NULL;
HeapTuple typetup;
Form_pg_type typeStruct;
FmgrInfo finfo_output;
- void *curplan = NULL;
+ void *curplan;
/* ----------
* We evaluate the string expression after the
{
/* ----------
* This is an OPEN cursor
+ *
+ * Note: parser should already have checked that statement supplies
+ * args iff cursor needs them, but we check again to be safe.
* ----------
*/
if (stmt->argquery != NULL)
*/
PLpgSQL_stmt_select set_args;
+ if (curvar->cursor_explicit_argrow < 0)
+ elog(ERROR, "arguments given for cursor without arguments");
+
memset(&set_args, 0, sizeof(set_args));
set_args.cmd_type = PLPGSQL_STMT_SELECT;
set_args.lineno = stmt->lineno;
if (exec_stmt_select(estate, &set_args) != PLPGSQL_RC_OK)
elog(ERROR, "open cursor failed during argument processing");
}
+ else
+ {
+ if (curvar->cursor_explicit_argrow >= 0)
+ elog(ERROR, "arguments required for cursor");
+ }
query = curvar->cursor_explicit_expr;
if (query->plan == NULL)
* procedural language
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_funcs.c,v 1.16 2001/10/09 15:59:56 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_funcs.c,v 1.17 2001/11/15 23:31:09 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
}
+/*
+ * Statement type as a string, for use in error messages etc.
+ */
+const char *
+plpgsql_stmt_typename(PLpgSQL_stmt * stmt)
+{
+ switch (stmt->cmd_type)
+ {
+ case PLPGSQL_STMT_BLOCK:
+ return "block variables initialization";
+ case PLPGSQL_STMT_ASSIGN:
+ return "assignment";
+ case PLPGSQL_STMT_IF:
+ return "if";
+ case PLPGSQL_STMT_LOOP:
+ return "loop";
+ case PLPGSQL_STMT_WHILE:
+ return "while";
+ case PLPGSQL_STMT_FORI:
+ return "for with integer loopvar";
+ case PLPGSQL_STMT_FORS:
+ return "for over select rows";
+ case PLPGSQL_STMT_SELECT:
+ return "select into variables";
+ case PLPGSQL_STMT_EXIT:
+ return "exit";
+ case PLPGSQL_STMT_RETURN:
+ return "return";
+ case PLPGSQL_STMT_RAISE:
+ return "raise";
+ case PLPGSQL_STMT_EXECSQL:
+ return "SQL statement";
+ case PLPGSQL_STMT_DYNEXECUTE:
+ return "execute statement";
+ case PLPGSQL_STMT_DYNFORS:
+ return "for over execute statement";
+ case PLPGSQL_STMT_GETDIAG:
+ return "get diagnostics";
+ case PLPGSQL_STMT_OPEN:
+ return "open";
+ case PLPGSQL_STMT_FETCH:
+ return "fetch";
+ case PLPGSQL_STMT_CLOSE:
+ return "close";
+ }
+ return "unknown";
+}
/**********************************************************************