mirror of
https://github.com/postgres/postgres.git
synced 2025-09-02 04:21:28 +03:00
Enhancement of SPI to get access to portals
- New functions to create a portal using a prepared/saved SPI plan or lookup an existing portal by name. - Functions to fetch/move from/in portals. Results are placed in the usual SPI_processed and SPI_tuptable, so the entire set of utility functions can be used to gain attribute access. - Prepared/saved SPI plans now use their own memory context and SPI_freeplan(plan) can remove them. - Tuple result sets (SPI_tuptable) now uses it's own memory context and can be free'd by SPI_freetuptable(tuptab). Enhancement of PL/pgSQL - Uses generic named portals internally in FOR ... SELECT loops to avoid running out of memory on huge result sets. - Support for CURSOR and REFCURSOR syntax using the new SPI functionality. Cursors used internally only need no explicit transaction block. Refcursor variables can be used inside of explicit transaction block to pass cursors between main application and functions. Jan
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
* procedural language
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/gram.y,v 1.18 2001/05/18 21:16:59 wieck Exp $
|
||||
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/gram.y,v 1.19 2001/05/21 14:22:18 wieck Exp $
|
||||
*
|
||||
* This software is copyrighted by Jan Wieck - Hamburg.
|
||||
*
|
||||
@@ -47,6 +47,7 @@
|
||||
|
||||
static PLpgSQL_expr *read_sqlstmt(int until, char *s, char *sqlstart);
|
||||
static PLpgSQL_stmt *make_select_stmt(void);
|
||||
static PLpgSQL_stmt *make_fetch_stmt(void);
|
||||
static PLpgSQL_expr *make_tupret_expr(PLpgSQL_row *row);
|
||||
|
||||
%}
|
||||
@@ -99,17 +100,17 @@ static PLpgSQL_expr *make_tupret_expr(PLpgSQL_row *row);
|
||||
%type <varname> decl_varname
|
||||
%type <str> decl_renname
|
||||
%type <ival> decl_const, decl_notnull, decl_atttypmod, decl_atttypmodval
|
||||
%type <expr> decl_defval
|
||||
%type <expr> decl_defval, decl_cursor_query
|
||||
%type <dtype> decl_datatype, decl_dtypename
|
||||
%type <row> decl_rowtype
|
||||
%type <row> decl_rowtype, decl_cursor_args, decl_cursor_arglist
|
||||
%type <nsitem> decl_aliasitem
|
||||
%type <str> decl_stmts, decl_stmt
|
||||
|
||||
%type <expr> expr_until_semi, expr_until_then, expr_until_loop
|
||||
%type <expr> opt_exitcond
|
||||
|
||||
%type <ival> assign_var
|
||||
%type <var> fori_var
|
||||
%type <ival> assign_var, cursor_variable
|
||||
%type <var> fori_var, cursor_varptr, decl_cursor_arg
|
||||
%type <varname> fori_varname
|
||||
%type <forilow> fori_lower
|
||||
%type <rec> fors_target
|
||||
@@ -124,6 +125,7 @@ static PLpgSQL_expr *make_tupret_expr(PLpgSQL_row *row);
|
||||
%type <stmt> stmt_return, stmt_raise, stmt_execsql, stmt_fori
|
||||
%type <stmt> stmt_fors, stmt_select, stmt_perform
|
||||
%type <stmt> stmt_dynexecute, stmt_dynfors, stmt_getdiag
|
||||
%type <stmt> stmt_open, stmt_fetch, stmt_close
|
||||
|
||||
%type <intlist> raise_params
|
||||
%type <ival> raise_level, raise_param
|
||||
@@ -140,7 +142,9 @@ static PLpgSQL_expr *make_tupret_expr(PLpgSQL_row *row);
|
||||
%token K_ALIAS
|
||||
%token K_ASSIGN
|
||||
%token K_BEGIN
|
||||
%token K_CLOSE
|
||||
%token K_CONSTANT
|
||||
%token K_CURSOR
|
||||
%token K_DEBUG
|
||||
%token K_DECLARE
|
||||
%token K_DEFAULT
|
||||
@@ -153,15 +157,18 @@ static PLpgSQL_expr *make_tupret_expr(PLpgSQL_row *row);
|
||||
%token K_EXECUTE
|
||||
%token K_EXIT
|
||||
%token K_FOR
|
||||
%token K_FETCH
|
||||
%token K_FROM
|
||||
%token K_GET
|
||||
%token K_IF
|
||||
%token K_IN
|
||||
%token K_INTO
|
||||
%token K_IS
|
||||
%token K_LOOP
|
||||
%token K_NOT
|
||||
%token K_NOTICE
|
||||
%token K_NULL
|
||||
%token K_OPEN
|
||||
%token K_PERFORM
|
||||
%token K_ROW_COUNT
|
||||
%token K_RAISE
|
||||
@@ -300,6 +307,7 @@ decl_statement : decl_varname decl_const decl_datatype decl_notnull decl_defval
|
||||
PLpgSQL_var *new;
|
||||
|
||||
new = malloc(sizeof(PLpgSQL_var));
|
||||
memset(new, 0, sizeof(PLpgSQL_var));
|
||||
|
||||
new->dtype = PLPGSQL_DTYPE_VAR;
|
||||
new->refname = $1.name;
|
||||
@@ -347,8 +355,152 @@ decl_statement : decl_varname decl_const decl_datatype decl_notnull decl_defval
|
||||
{
|
||||
plpgsql_ns_rename($2, $4);
|
||||
}
|
||||
| decl_varname K_CURSOR decl_cursor_args K_IS K_SELECT decl_cursor_query
|
||||
{
|
||||
PLpgSQL_var *new;
|
||||
PLpgSQL_expr *curname_def;
|
||||
char buf[1024];
|
||||
char *cp1;
|
||||
char *cp2;
|
||||
|
||||
plpgsql_ns_pop();
|
||||
|
||||
new = malloc(sizeof(PLpgSQL_var));
|
||||
memset(new, 0, sizeof(PLpgSQL_var));
|
||||
|
||||
curname_def = malloc(sizeof(PLpgSQL_var));
|
||||
memset(curname_def, 0, sizeof(PLpgSQL_var));
|
||||
|
||||
new->dtype = PLPGSQL_DTYPE_VAR;
|
||||
new->refname = $1.name;
|
||||
new->lineno = $1.lineno;
|
||||
|
||||
curname_def->dtype = PLPGSQL_DTYPE_EXPR;
|
||||
strcpy(buf, "SELECT '");
|
||||
cp1 = new->refname;
|
||||
cp2 = buf + strlen(buf);
|
||||
while (*cp1 != '\0')
|
||||
{
|
||||
if (*cp1 == '\\' || *cp1 == '\'')
|
||||
*cp2++ = '\\';
|
||||
*cp2++ = *cp1++;
|
||||
}
|
||||
strcat(buf, "'");
|
||||
curname_def->query = strdup(buf);
|
||||
new->default_val = curname_def;
|
||||
|
||||
plpgsql_parse_word("refcursor");
|
||||
new->datatype = yylval.dtype;
|
||||
|
||||
new->cursor_explicit_expr = $6;
|
||||
if ($3 == NULL)
|
||||
new->cursor_explicit_argrow = -1;
|
||||
else
|
||||
new->cursor_explicit_argrow = $3->rowno;
|
||||
|
||||
plpgsql_adddatum((PLpgSQL_datum *)new);
|
||||
plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, new->varno,
|
||||
$1.name);
|
||||
}
|
||||
;
|
||||
|
||||
decl_cursor_query :
|
||||
{
|
||||
PLpgSQL_expr *query;
|
||||
|
||||
plpgsql_ns_setlocal(false);
|
||||
query = plpgsql_read_expression(';', ";");
|
||||
plpgsql_ns_setlocal(true);
|
||||
|
||||
$$ = query;
|
||||
}
|
||||
;
|
||||
|
||||
decl_cursor_args :
|
||||
{
|
||||
$$ = NULL;
|
||||
}
|
||||
| decl_cursor_openparen decl_cursor_arglist ')'
|
||||
{
|
||||
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));
|
||||
|
||||
pfree((char *)($2->fieldnames));
|
||||
pfree((char *)($2->varnos));
|
||||
|
||||
$2->fieldnames = ftmp;
|
||||
$2->varnos = vtmp;
|
||||
|
||||
plpgsql_adddatum((PLpgSQL_datum *)$2);
|
||||
|
||||
$$ = $2;
|
||||
}
|
||||
;
|
||||
|
||||
decl_cursor_arglist : decl_cursor_arg
|
||||
{
|
||||
PLpgSQL_row *new;
|
||||
|
||||
new = malloc(sizeof(PLpgSQL_row));
|
||||
memset(new, 0, sizeof(PLpgSQL_row));
|
||||
|
||||
new->dtype = PLPGSQL_DTYPE_ROW;
|
||||
new->refname = strdup("*internal*");
|
||||
new->lineno = yylineno;
|
||||
new->rowtypeclass = InvalidOid;
|
||||
new->fieldnames = palloc(1024 * sizeof(char *));
|
||||
new->varnos = palloc(1024 * sizeof(int));
|
||||
new->nfields = 1;
|
||||
|
||||
new->fieldnames[0] = $1->refname;
|
||||
new->varnos[0] = $1->varno;
|
||||
|
||||
$$ = new;
|
||||
}
|
||||
| decl_cursor_arglist ',' decl_cursor_arg
|
||||
{
|
||||
int i = $1->nfields++;
|
||||
|
||||
$1->fieldnames[i] = $3->refname;
|
||||
$1->varnos[i] = $3->varno;
|
||||
}
|
||||
;
|
||||
|
||||
decl_cursor_arg : decl_varname decl_datatype
|
||||
{
|
||||
PLpgSQL_var *new;
|
||||
|
||||
new = malloc(sizeof(PLpgSQL_var));
|
||||
memset(new, 0, sizeof(PLpgSQL_var));
|
||||
|
||||
new->dtype = PLPGSQL_DTYPE_VAR;
|
||||
new->refname = $1.name;
|
||||
new->lineno = $1.lineno;
|
||||
|
||||
new->datatype = $2;
|
||||
new->isconst = false;
|
||||
new->notnull = false;
|
||||
|
||||
plpgsql_adddatum((PLpgSQL_datum *)new);
|
||||
plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, new->varno,
|
||||
$1.name);
|
||||
|
||||
$$ = new;
|
||||
}
|
||||
;
|
||||
|
||||
decl_cursor_openparen : '('
|
||||
{
|
||||
plpgsql_ns_push(NULL);
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
decl_aliasitem : T_WORD
|
||||
{
|
||||
PLpgSQL_nsitem *nsi;
|
||||
@@ -581,6 +733,12 @@ proc_stmt : pl_block
|
||||
{ $$ = $1; }
|
||||
| stmt_getdiag
|
||||
{ $$ = $1; }
|
||||
| stmt_open
|
||||
{ $$ = $1; }
|
||||
| stmt_fetch
|
||||
{ $$ = $1; }
|
||||
| stmt_close
|
||||
{ $$ = $1; }
|
||||
;
|
||||
|
||||
stmt_perform : K_PERFORM lno expr_until_semi
|
||||
@@ -836,6 +994,7 @@ fori_var : fori_varname
|
||||
PLpgSQL_var *new;
|
||||
|
||||
new = malloc(sizeof(PLpgSQL_var));
|
||||
memset(new, 0, sizeof(PLpgSQL_var));
|
||||
|
||||
new->dtype = PLPGSQL_DTYPE_VAR;
|
||||
new->refname = $1.name;
|
||||
@@ -1189,15 +1348,137 @@ stmt_execsql : execsql_start lno
|
||||
|
||||
stmt_dynexecute : K_EXECUTE lno expr_until_semi
|
||||
{
|
||||
PLpgSQL_stmt_dynexecute *new;
|
||||
PLpgSQL_stmt_dynexecute *new;
|
||||
|
||||
new = malloc(sizeof(PLpgSQL_stmt_dynexecute));
|
||||
new->cmd_type = PLPGSQL_STMT_DYNEXECUTE;
|
||||
new->lineno = $2;
|
||||
new->query = $3;
|
||||
new = malloc(sizeof(PLpgSQL_stmt_dynexecute));
|
||||
new->cmd_type = PLPGSQL_STMT_DYNEXECUTE;
|
||||
new->lineno = $2;
|
||||
new->query = $3;
|
||||
|
||||
$$ = (PLpgSQL_stmt *)new;
|
||||
}
|
||||
;
|
||||
|
||||
stmt_open : K_OPEN lno cursor_varptr
|
||||
{
|
||||
PLpgSQL_stmt_open *new;
|
||||
int tok;
|
||||
|
||||
new = malloc(sizeof(PLpgSQL_stmt_open));
|
||||
memset(new, 0, sizeof(PLpgSQL_stmt_open));
|
||||
|
||||
new->cmd_type = PLPGSQL_STMT_OPEN;
|
||||
new->lineno = $2;
|
||||
new->curvar = $3->varno;
|
||||
|
||||
if ($3->cursor_explicit_expr == NULL)
|
||||
{
|
||||
tok = yylex();
|
||||
|
||||
if (tok != K_FOR)
|
||||
{
|
||||
plpgsql_comperrinfo();
|
||||
elog(ERROR, "syntax error at \"%s\" - expected FOR to open a reference cursor", yytext);
|
||||
}
|
||||
|
||||
tok = yylex();
|
||||
switch (tok)
|
||||
{
|
||||
case K_SELECT:
|
||||
new->query = plpgsql_read_expression(';', ";");
|
||||
break;
|
||||
|
||||
case K_EXECUTE:
|
||||
new->dynquery = plpgsql_read_expression(';', ";");
|
||||
break;
|
||||
|
||||
default:
|
||||
plpgsql_comperrinfo();
|
||||
elog(ERROR, "syntax error at \"%s\"", yytext);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($3->cursor_explicit_argrow >= 0)
|
||||
{
|
||||
tok = yylex();
|
||||
|
||||
if (tok != '(')
|
||||
{
|
||||
plpgsql_comperrinfo();
|
||||
elog(ERROR, "cursor %s has arguments", $3->refname);
|
||||
}
|
||||
|
||||
new->argquery = read_sqlstmt(';', ";", "SELECT (");
|
||||
}
|
||||
else
|
||||
{
|
||||
tok = yylex();
|
||||
|
||||
if (tok == '(')
|
||||
{
|
||||
plpgsql_comperrinfo();
|
||||
elog(ERROR, "cursor %s has no arguments", $3->refname);
|
||||
}
|
||||
|
||||
if (tok != ';')
|
||||
{
|
||||
plpgsql_comperrinfo();
|
||||
elog(ERROR, "syntax error at \"%s\"", yytext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$$ = (PLpgSQL_stmt *)new;
|
||||
}
|
||||
;
|
||||
|
||||
stmt_fetch : K_FETCH lno cursor_variable K_INTO
|
||||
{
|
||||
PLpgSQL_stmt_fetch *new;
|
||||
|
||||
new = (PLpgSQL_stmt_fetch *)make_fetch_stmt();
|
||||
new->curvar = $3;
|
||||
|
||||
$$ = (PLpgSQL_stmt *)new;
|
||||
$$->lineno = $2;
|
||||
}
|
||||
;
|
||||
|
||||
stmt_close : K_CLOSE lno cursor_variable ';'
|
||||
{
|
||||
PLpgSQL_stmt_close *new;
|
||||
|
||||
new = malloc(sizeof(PLpgSQL_stmt_close));
|
||||
new->cmd_type = PLPGSQL_STMT_CLOSE;
|
||||
new->lineno = $2;
|
||||
new->curvar = $3;
|
||||
|
||||
$$ = (PLpgSQL_stmt *)new;
|
||||
}
|
||||
;
|
||||
|
||||
cursor_varptr : T_VARIABLE
|
||||
{
|
||||
if (yylval.var->datatype->typoid != REFCURSOROID)
|
||||
{
|
||||
plpgsql_comperrinfo();
|
||||
elog(ERROR, "%s must be of type cursor or refcursor", yylval.var->refname);
|
||||
}
|
||||
$$ = yylval.var;
|
||||
}
|
||||
;
|
||||
|
||||
cursor_variable : T_VARIABLE
|
||||
{
|
||||
if (yylval.var->datatype->typoid != REFCURSOROID)
|
||||
{
|
||||
plpgsql_comperrinfo();
|
||||
elog(ERROR, "%s must be of type refcursor", yylval.var->refname);
|
||||
}
|
||||
$$ = yylval.var->varno;
|
||||
}
|
||||
;
|
||||
|
||||
execsql_start : T_WORD
|
||||
@@ -1615,6 +1896,113 @@ make_select_stmt()
|
||||
}
|
||||
|
||||
|
||||
static PLpgSQL_stmt *
|
||||
make_fetch_stmt()
|
||||
{
|
||||
int tok;
|
||||
PLpgSQL_row *row = NULL;
|
||||
PLpgSQL_rec *rec = NULL;
|
||||
PLpgSQL_stmt_fetch *fetch;
|
||||
int have_nexttok = 0;
|
||||
|
||||
tok = yylex();
|
||||
switch (tok)
|
||||
{
|
||||
case T_ROW:
|
||||
row = yylval.row;
|
||||
break;
|
||||
|
||||
case T_RECORD:
|
||||
rec = yylval.rec;
|
||||
break;
|
||||
|
||||
case T_VARIABLE:
|
||||
case T_RECFIELD:
|
||||
{
|
||||
PLpgSQL_var *var;
|
||||
PLpgSQL_recfield *recfield;
|
||||
int nfields = 1;
|
||||
char *fieldnames[1024];
|
||||
int varnos[1024];
|
||||
|
||||
switch (tok)
|
||||
{
|
||||
case T_VARIABLE:
|
||||
var = yylval.var;
|
||||
fieldnames[0] = strdup(yytext);
|
||||
varnos[0] = var->varno;
|
||||
break;
|
||||
|
||||
case T_RECFIELD:
|
||||
recfield = yylval.recfield;
|
||||
fieldnames[0] = strdup(yytext);
|
||||
varnos[0] = recfield->rfno;
|
||||
break;
|
||||
}
|
||||
|
||||
while ((tok = yylex()) == ',')
|
||||
{
|
||||
tok = yylex();
|
||||
switch(tok)
|
||||
{
|
||||
case T_VARIABLE:
|
||||
var = yylval.var;
|
||||
fieldnames[nfields] = strdup(yytext);
|
||||
varnos[nfields++] = var->varno;
|
||||
break;
|
||||
|
||||
case T_RECFIELD:
|
||||
recfield = yylval.recfield;
|
||||
fieldnames[0] = strdup(yytext);
|
||||
varnos[0] = recfield->rfno;
|
||||
break;
|
||||
|
||||
default:
|
||||
elog(ERROR, "plpgsql: %s is not a variable or record field", yytext);
|
||||
}
|
||||
}
|
||||
row = malloc(sizeof(PLpgSQL_row));
|
||||
row->dtype = PLPGSQL_DTYPE_ROW;
|
||||
row->refname = strdup("*internal*");
|
||||
row->lineno = yylineno;
|
||||
row->rowtypeclass = InvalidOid;
|
||||
row->nfields = nfields;
|
||||
row->fieldnames = malloc(sizeof(char *) * nfields);
|
||||
row->varnos = malloc(sizeof(int) * nfields);
|
||||
while (--nfields >= 0)
|
||||
{
|
||||
row->fieldnames[nfields] = fieldnames[nfields];
|
||||
row->varnos[nfields] = varnos[nfields];
|
||||
}
|
||||
|
||||
plpgsql_adddatum((PLpgSQL_datum *)row);
|
||||
|
||||
have_nexttok = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
elog(ERROR, "syntax error at '%s'", yytext);
|
||||
}
|
||||
}
|
||||
|
||||
if (!have_nexttok)
|
||||
tok = yylex();
|
||||
|
||||
if (tok != ';')
|
||||
elog(ERROR, "syntax error at '%s'", yytext);
|
||||
|
||||
fetch = malloc(sizeof(PLpgSQL_stmt_select));
|
||||
memset(fetch, 0, sizeof(PLpgSQL_stmt_fetch));
|
||||
fetch->cmd_type = PLPGSQL_STMT_FETCH;
|
||||
fetch->rec = rec;
|
||||
fetch->row = row;
|
||||
|
||||
return (PLpgSQL_stmt *)fetch;
|
||||
}
|
||||
|
||||
|
||||
static PLpgSQL_expr *
|
||||
make_tupret_expr(PLpgSQL_row *row)
|
||||
{
|
||||
|
@@ -3,7 +3,7 @@
|
||||
* procedural language
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.30 2001/04/18 20:42:56 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.31 2001/05/21 14:22:18 wieck Exp $
|
||||
*
|
||||
* This software is copyrighted by Jan Wieck - Hamburg.
|
||||
*
|
||||
@@ -282,6 +282,7 @@ plpgsql_compile(Oid fn_oid, int functype)
|
||||
perm_fmgr_info(typeStruct->typinput, &(var->datatype->typinput));
|
||||
var->datatype->typelem = typeStruct->typelem;
|
||||
var->datatype->typbyval = typeStruct->typbyval;
|
||||
var->datatype->typlen = typeStruct->typlen;
|
||||
var->datatype->atttypmod = -1;
|
||||
var->isconst = true;
|
||||
var->notnull = false;
|
||||
@@ -313,6 +314,9 @@ plpgsql_compile(Oid fn_oid, int functype)
|
||||
memset(rec, 0, sizeof(PLpgSQL_rec));
|
||||
rec->dtype = PLPGSQL_DTYPE_REC;
|
||||
rec->refname = strdup("new");
|
||||
rec->tup = NULL;
|
||||
rec->tupdesc = NULL;
|
||||
rec->freetup = false;
|
||||
plpgsql_adddatum((PLpgSQL_datum *) rec);
|
||||
plpgsql_ns_additem(PLPGSQL_NSTYPE_REC, rec->recno, rec->refname);
|
||||
function->new_varno = rec->recno;
|
||||
@@ -324,6 +328,9 @@ plpgsql_compile(Oid fn_oid, int functype)
|
||||
memset(rec, 0, sizeof(PLpgSQL_rec));
|
||||
rec->dtype = PLPGSQL_DTYPE_REC;
|
||||
rec->refname = strdup("old");
|
||||
rec->tup = NULL;
|
||||
rec->tupdesc = NULL;
|
||||
rec->freetup = false;
|
||||
plpgsql_adddatum((PLpgSQL_datum *) rec);
|
||||
plpgsql_ns_additem(PLPGSQL_NSTYPE_REC, rec->recno, rec->refname);
|
||||
function->old_varno = rec->recno;
|
||||
@@ -632,6 +639,7 @@ plpgsql_parse_word(char *word)
|
||||
perm_fmgr_info(typeStruct->typinput, &(typ->typinput));
|
||||
typ->typelem = typeStruct->typelem;
|
||||
typ->typbyval = typeStruct->typbyval;
|
||||
typ->typlen = typeStruct->typlen;
|
||||
typ->atttypmod = -1;
|
||||
|
||||
plpgsql_yylval.dtype = typ;
|
||||
@@ -948,6 +956,7 @@ plpgsql_parse_wordtype(char *word)
|
||||
perm_fmgr_info(typeStruct->typinput, &(typ->typinput));
|
||||
typ->typelem = typeStruct->typelem;
|
||||
typ->typbyval = typeStruct->typbyval;
|
||||
typ->typlen = typeStruct->typlen;
|
||||
typ->atttypmod = -1;
|
||||
|
||||
plpgsql_yylval.dtype = typ;
|
||||
@@ -1091,6 +1100,7 @@ plpgsql_parse_dblwordtype(char *string)
|
||||
perm_fmgr_info(typeStruct->typinput, &(typ->typinput));
|
||||
typ->typelem = typeStruct->typelem;
|
||||
typ->typbyval = typeStruct->typbyval;
|
||||
typ->typlen = typeStruct->typlen;
|
||||
typ->atttypmod = attrStruct->atttypmod;
|
||||
|
||||
plpgsql_yylval.dtype = typ;
|
||||
@@ -1230,13 +1240,14 @@ plpgsql_parse_wordrowtype(char *string)
|
||||
perm_fmgr_info(typeStruct->typinput, &(var->datatype->typinput));
|
||||
var->datatype->typelem = typeStruct->typelem;
|
||||
var->datatype->typbyval = typeStruct->typbyval;
|
||||
var->datatype->typlen = typeStruct->typlen;
|
||||
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;
|
||||
var->freeval = false;
|
||||
|
||||
ReleaseSysCache(typetup);
|
||||
ReleaseSysCache(attrtup);
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -3,7 +3,7 @@
|
||||
* procedural language
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_funcs.c,v 1.12 2001/03/22 06:16:21 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_funcs.c,v 1.13 2001/05/21 14:22:19 wieck Exp $
|
||||
*
|
||||
* This software is copyrighted by Jan Wieck - Hamburg.
|
||||
*
|
||||
@@ -387,6 +387,9 @@ static void dump_execsql(PLpgSQL_stmt_execsql * stmt);
|
||||
static void dump_dynexecute(PLpgSQL_stmt_dynexecute * stmt);
|
||||
static void dump_dynfors(PLpgSQL_stmt_dynfors * stmt);
|
||||
static void dump_getdiag(PLpgSQL_stmt_getdiag * stmt);
|
||||
static void dump_open(PLpgSQL_stmt_open * stmt);
|
||||
static void dump_fetch(PLpgSQL_stmt_fetch * stmt);
|
||||
static void dump_close(PLpgSQL_stmt_close * stmt);
|
||||
static void dump_expr(PLpgSQL_expr * expr);
|
||||
|
||||
|
||||
@@ -450,6 +453,15 @@ dump_stmt(PLpgSQL_stmt * stmt)
|
||||
case PLPGSQL_STMT_GETDIAG:
|
||||
dump_getdiag((PLpgSQL_stmt_getdiag *) stmt);
|
||||
break;
|
||||
case PLPGSQL_STMT_OPEN:
|
||||
dump_open((PLpgSQL_stmt_open *) stmt);
|
||||
break;
|
||||
case PLPGSQL_STMT_FETCH:
|
||||
dump_fetch((PLpgSQL_stmt_fetch *) stmt);
|
||||
break;
|
||||
case PLPGSQL_STMT_CLOSE:
|
||||
dump_close((PLpgSQL_stmt_close *) stmt);
|
||||
break;
|
||||
default:
|
||||
elog(ERROR, "plpgsql_dump: unknown cmd_type %d\n", stmt->cmd_type);
|
||||
break;
|
||||
@@ -619,6 +631,66 @@ dump_select(PLpgSQL_stmt_select * stmt)
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
dump_open(PLpgSQL_stmt_open * stmt)
|
||||
{
|
||||
dump_ind();
|
||||
printf("OPEN curvar=%d\n", stmt->curvar);
|
||||
|
||||
dump_indent += 2;
|
||||
if (stmt->argquery != NULL)
|
||||
{
|
||||
dump_ind();
|
||||
printf(" arguments = '");
|
||||
dump_expr(stmt->argquery);
|
||||
printf("'\n");
|
||||
}
|
||||
if (stmt->query != NULL)
|
||||
{
|
||||
dump_ind();
|
||||
printf(" query = '");
|
||||
dump_expr(stmt->query);
|
||||
printf("'\n");
|
||||
}
|
||||
if (stmt->dynquery != NULL)
|
||||
{
|
||||
dump_ind();
|
||||
printf(" execute = '");
|
||||
dump_expr(stmt->dynquery);
|
||||
printf("'\n");
|
||||
}
|
||||
dump_indent -= 2;
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
dump_fetch(PLpgSQL_stmt_fetch * stmt)
|
||||
{
|
||||
dump_ind();
|
||||
printf("FETCH curvar=%d\n", stmt->curvar);
|
||||
|
||||
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_close(PLpgSQL_stmt_close * stmt)
|
||||
{
|
||||
dump_ind();
|
||||
printf("CLOSE curvar=%d\n", stmt->curvar);
|
||||
}
|
||||
|
||||
static void
|
||||
dump_exit(PLpgSQL_stmt_exit * stmt)
|
||||
{
|
||||
@@ -777,6 +849,25 @@ plpgsql_dumptree(PLpgSQL_function * func)
|
||||
var->refname, var->datatype->typname,
|
||||
var->datatype->typoid,
|
||||
var->datatype->atttypmod);
|
||||
if (var->isconst)
|
||||
printf(" CONSTANT\n");
|
||||
if (var->notnull)
|
||||
printf(" NOT NULL\n");
|
||||
if (var->default_val != NULL)
|
||||
{
|
||||
printf(" DEFAULT ");
|
||||
dump_expr(var->default_val);
|
||||
printf("\n");
|
||||
}
|
||||
if (var->cursor_explicit_expr != NULL)
|
||||
{
|
||||
if (var->cursor_explicit_argrow >= 0)
|
||||
printf(" CURSOR argument row %d\n", var->cursor_explicit_argrow);
|
||||
|
||||
printf(" CURSOR IS ");
|
||||
dump_expr(var->cursor_explicit_expr);
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PLPGSQL_DTYPE_ROW:
|
||||
|
@@ -3,7 +3,7 @@
|
||||
* procedural language
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.13 2001/03/22 04:01:42 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.14 2001/05/21 14:22:19 wieck Exp $
|
||||
*
|
||||
* This software is copyrighted by Jan Wieck - Hamburg.
|
||||
*
|
||||
@@ -94,7 +94,10 @@ enum
|
||||
PLPGSQL_STMT_EXECSQL,
|
||||
PLPGSQL_STMT_DYNEXECUTE,
|
||||
PLPGSQL_STMT_DYNFORS,
|
||||
PLPGSQL_STMT_GETDIAG
|
||||
PLPGSQL_STMT_GETDIAG,
|
||||
PLPGSQL_STMT_OPEN,
|
||||
PLPGSQL_STMT_FETCH,
|
||||
PLPGSQL_STMT_CLOSE
|
||||
};
|
||||
|
||||
|
||||
@@ -139,6 +142,7 @@ typedef struct
|
||||
Oid typoid;
|
||||
FmgrInfo typinput;
|
||||
Oid typelem;
|
||||
int16 typlen;
|
||||
bool typbyval;
|
||||
int32 atttypmod;
|
||||
} PLpgSQL_type;
|
||||
@@ -176,10 +180,12 @@ typedef struct
|
||||
int isconst;
|
||||
int notnull;
|
||||
PLpgSQL_expr *default_val;
|
||||
PLpgSQL_expr *cursor_explicit_expr;
|
||||
int cursor_explicit_argrow;
|
||||
|
||||
Datum value;
|
||||
bool isnull;
|
||||
int shouldfree;
|
||||
bool freeval;
|
||||
} PLpgSQL_var;
|
||||
|
||||
|
||||
@@ -206,6 +212,8 @@ typedef struct
|
||||
|
||||
HeapTuple tup;
|
||||
TupleDesc tupdesc;
|
||||
bool freetup;
|
||||
bool freetupdesc;
|
||||
} PLpgSQL_rec;
|
||||
|
||||
|
||||
@@ -369,6 +377,36 @@ typedef struct
|
||||
} PLpgSQL_stmt_select;
|
||||
|
||||
|
||||
typedef struct
|
||||
{ /* OPEN a curvar */
|
||||
int cmd_type;
|
||||
int lineno;
|
||||
int curvar;
|
||||
PLpgSQL_row *returntype;
|
||||
PLpgSQL_expr *argquery;
|
||||
PLpgSQL_expr *query;
|
||||
PLpgSQL_expr *dynquery;
|
||||
} PLpgSQL_stmt_open;
|
||||
|
||||
|
||||
typedef struct
|
||||
{ /* FETCH curvar INTO statement */
|
||||
int cmd_type;
|
||||
int lineno;
|
||||
PLpgSQL_rec *rec;
|
||||
PLpgSQL_row *row;
|
||||
int curvar;
|
||||
} PLpgSQL_stmt_fetch;
|
||||
|
||||
|
||||
typedef struct
|
||||
{ /* CLOSE curvar */
|
||||
int cmd_type;
|
||||
int lineno;
|
||||
int curvar;
|
||||
} PLpgSQL_stmt_close;
|
||||
|
||||
|
||||
typedef struct
|
||||
{ /* EXIT statement */
|
||||
int cmd_type;
|
||||
|
@@ -4,7 +4,7 @@
|
||||
* procedural language
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/Attic/scan.l,v 1.11 2001/05/18 21:16:59 wieck Exp $
|
||||
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/Attic/scan.l,v 1.12 2001/05/21 14:22:19 wieck Exp $
|
||||
*
|
||||
* This software is copyrighted by Jan Wieck - Hamburg.
|
||||
*
|
||||
@@ -93,7 +93,9 @@ alias { return K_ALIAS; }
|
||||
begin { return K_BEGIN; }
|
||||
bpchar { return T_BPCHAR; }
|
||||
char { return T_CHAR; }
|
||||
close { return K_CLOSE; }
|
||||
constant { return K_CONSTANT; }
|
||||
cursor { return K_CURSOR; }
|
||||
debug { return K_DEBUG; }
|
||||
declare { return K_DECLARE; }
|
||||
default { return K_DEFAULT; }
|
||||
@@ -104,16 +106,19 @@ end { return K_END; }
|
||||
exception { return K_EXCEPTION; }
|
||||
execute { return K_EXECUTE; }
|
||||
exit { return K_EXIT; }
|
||||
fetch { return K_FETCH; }
|
||||
for { return K_FOR; }
|
||||
from { return K_FROM; }
|
||||
get { return K_GET; }
|
||||
if { return K_IF; }
|
||||
in { return K_IN; }
|
||||
into { return K_INTO; }
|
||||
is { return K_IS; }
|
||||
loop { return K_LOOP; }
|
||||
not { return K_NOT; }
|
||||
notice { return K_NOTICE; }
|
||||
null { return K_NULL; }
|
||||
open { return K_OPEN; }
|
||||
perform { return K_PERFORM; }
|
||||
raise { return K_RAISE; }
|
||||
record { return K_RECORD; }
|
||||
|
Reference in New Issue
Block a user