mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-12-15 08:20:16 +08:00
Fix some problems in new plpgsql cursor operations, found while trying
to reverse-engineer documentation for them.
This commit is contained in:
parent
d4337f6a7c
commit
4be20187ab
@ -4,7 +4,7 @@
|
||||
* 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.
|
||||
*
|
||||
@ -351,7 +351,9 @@ decl_statement : decl_varname decl_const decl_datatype decl_notnull decl_defval
|
||||
{
|
||||
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;
|
||||
@ -359,6 +361,7 @@ decl_statement : decl_varname decl_const decl_datatype decl_notnull decl_defval
|
||||
char *cp1;
|
||||
char *cp2;
|
||||
|
||||
/* pop local namespace for cursor args */
|
||||
plpgsql_ns_pop();
|
||||
|
||||
new = malloc(sizeof(PLpgSQL_var));
|
||||
@ -381,22 +384,21 @@ decl_statement : decl_varname decl_const decl_datatype decl_notnull decl_defval
|
||||
*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);
|
||||
}
|
||||
;
|
||||
|
||||
@ -416,15 +418,17 @@ decl_cursor_args :
|
||||
{
|
||||
$$ = 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));
|
||||
@ -449,6 +453,12 @@ decl_cursor_arglist : decl_cursor_arg
|
||||
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;
|
||||
@ -464,6 +474,8 @@ decl_cursor_arglist : decl_cursor_arg
|
||||
|
||||
$1->fieldnames[i] = $3->refname;
|
||||
$1->varnos[i] = $3->varno;
|
||||
|
||||
$$ = $1;
|
||||
}
|
||||
;
|
||||
|
||||
@ -484,18 +496,12 @@ decl_cursor_arg : decl_varname decl_datatype
|
||||
|
||||
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 */
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
* 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.
|
||||
*
|
||||
@ -192,76 +192,12 @@ plpgsql_exec_function(PLpgSQL_function * func, FunctionCallInfo fcinfo)
|
||||
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;
|
||||
@ -504,70 +440,12 @@ plpgsql_exec_trigger(PLpgSQL_function * func,
|
||||
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;
|
||||
@ -2412,7 +2290,7 @@ exec_stmt_open(PLpgSQL_execstate * estate, PLpgSQL_stmt_open * stmt)
|
||||
HeapTuple typetup;
|
||||
Form_pg_type typeStruct;
|
||||
FmgrInfo finfo_output;
|
||||
void *curplan = NULL;
|
||||
void *curplan;
|
||||
|
||||
/* ----------
|
||||
* We evaluate the string expression after the
|
||||
@ -2471,6 +2349,9 @@ exec_stmt_open(PLpgSQL_execstate * estate, PLpgSQL_stmt_open * stmt)
|
||||
{
|
||||
/* ----------
|
||||
* 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)
|
||||
@ -2483,6 +2364,9 @@ exec_stmt_open(PLpgSQL_execstate * estate, PLpgSQL_stmt_open * stmt)
|
||||
*/
|
||||
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;
|
||||
@ -2493,6 +2377,11 @@ exec_stmt_open(PLpgSQL_execstate * estate, PLpgSQL_stmt_open * stmt)
|
||||
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)
|
||||
|
@ -3,7 +3,7 @@
|
||||
* 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.
|
||||
*
|
||||
@ -360,7 +360,54 @@ plpgsql_tolower(char *s)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 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";
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
|
@ -3,7 +3,7 @@
|
||||
* procedural language
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.22 2001/11/05 17:46:39 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.23 2001/11/15 23:31:09 tgl Exp $
|
||||
*
|
||||
* This software is copyrighted by Jan Wieck - Hamburg.
|
||||
*
|
||||
@ -598,8 +598,9 @@ 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 const char *plpgsql_stmt_typename(PLpgSQL_stmt * stmt);
|
||||
extern void plpgsql_dumptree(PLpgSQL_function * func);
|
||||
|
||||
/* ----------
|
||||
* Externs in gram.y and scan.l
|
||||
|
Loading…
Reference in New Issue
Block a user