mirror of
https://github.com/postgres/postgres.git
synced 2025-05-11 05:41:32 +03:00
Restructure plpgsql's parsing of datatype declarations to unify the
scalar and composite (rowtype) cases a little better. This commit is just a code-beautification operation and shouldn't make any real difference in behavior, but it's an important preliminary step for trying to improve plgsql's handling of rowtypes.
This commit is contained in:
parent
2a22750c96
commit
724c706400
@ -4,7 +4,7 @@
|
||||
* procedural language
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.53 2004/04/15 13:01:45 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.54 2004/06/03 22:56:43 tgl Exp $
|
||||
*
|
||||
* This software is copyrighted by Jan Wieck - Hamburg.
|
||||
*
|
||||
@ -83,7 +83,8 @@ static void check_assignable(PLpgSQL_datum *datum);
|
||||
int *initvarnos;
|
||||
} declhdr;
|
||||
PLpgSQL_type *dtype;
|
||||
PLpgSQL_datum *variable; /* a VAR, RECFIELD, or TRIGARG */
|
||||
PLpgSQL_datum *scalar; /* a VAR, RECFIELD, or TRIGARG */
|
||||
PLpgSQL_variable *variable; /* a VAR, REC, or ROW */
|
||||
PLpgSQL_var *var;
|
||||
PLpgSQL_row *row;
|
||||
PLpgSQL_rec *rec;
|
||||
@ -100,7 +101,7 @@ static void check_assignable(PLpgSQL_datum *datum);
|
||||
%type <ival> decl_const decl_notnull
|
||||
%type <expr> decl_defval decl_cursor_query
|
||||
%type <dtype> decl_datatype
|
||||
%type <row> decl_rowtype decl_cursor_args decl_cursor_arglist
|
||||
%type <row> decl_cursor_args decl_cursor_arglist
|
||||
%type <nsitem> decl_aliasitem
|
||||
%type <str> decl_stmts decl_stmt
|
||||
|
||||
@ -109,7 +110,8 @@ static void check_assignable(PLpgSQL_datum *datum);
|
||||
%type <expr> opt_exitcond
|
||||
|
||||
%type <ival> assign_var cursor_variable
|
||||
%type <var> fori_var cursor_varptr decl_cursor_arg
|
||||
%type <var> fori_var cursor_varptr
|
||||
%type <variable> decl_cursor_arg
|
||||
%type <varname> fori_varname
|
||||
%type <forilow> fori_lower
|
||||
%type <rec> fors_target
|
||||
@ -174,7 +176,6 @@ static void check_assignable(PLpgSQL_datum *datum);
|
||||
%token K_PERFORM
|
||||
%token K_ROW_COUNT
|
||||
%token K_RAISE
|
||||
%token K_RECORD
|
||||
%token K_RENAME
|
||||
%token K_RESULT_OID
|
||||
%token K_RETURN
|
||||
@ -195,7 +196,7 @@ static void check_assignable(PLpgSQL_datum *datum);
|
||||
%token T_TRIGGER
|
||||
%token T_STRING
|
||||
%token T_NUMBER
|
||||
%token T_VARIABLE /* a VAR, RECFIELD, or TRIGARG */
|
||||
%token T_SCALAR /* a VAR, RECFIELD, or TRIGARG */
|
||||
%token T_ROW
|
||||
%token T_RECORD
|
||||
%token T_DTYPE
|
||||
@ -306,86 +307,42 @@ decl_stmt : '<' '<' opt_lblname '>' '>'
|
||||
|
||||
decl_statement : decl_varname decl_const decl_datatype decl_notnull decl_defval
|
||||
{
|
||||
if (!OidIsValid($3->typrelid))
|
||||
PLpgSQL_variable *var;
|
||||
|
||||
var = plpgsql_build_variable($1.name, $1.lineno,
|
||||
$3, true);
|
||||
if ($2)
|
||||
{
|
||||
/* Ordinary scalar datatype */
|
||||
PLpgSQL_var *var;
|
||||
|
||||
var = malloc(sizeof(PLpgSQL_var));
|
||||
memset(var, 0, sizeof(PLpgSQL_var));
|
||||
|
||||
var->dtype = PLPGSQL_DTYPE_VAR;
|
||||
var->refname = $1.name;
|
||||
var->lineno = $1.lineno;
|
||||
|
||||
var->datatype = $3;
|
||||
var->isconst = $2;
|
||||
var->notnull = $4;
|
||||
var->default_val = $5;
|
||||
|
||||
plpgsql_adddatum((PLpgSQL_datum *)var);
|
||||
plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR,
|
||||
var->varno,
|
||||
$1.name);
|
||||
if (var->dtype == PLPGSQL_DTYPE_VAR)
|
||||
((PLpgSQL_var *) var)->isconst = $2;
|
||||
else
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("row or record variable cannot be CONSTANT")));
|
||||
}
|
||||
else
|
||||
if ($4)
|
||||
{
|
||||
/* Composite type --- treat as rowtype */
|
||||
PLpgSQL_row *row;
|
||||
|
||||
row = plpgsql_build_rowtype($3->typrelid);
|
||||
row->dtype = PLPGSQL_DTYPE_ROW;
|
||||
row->refname = $1.name;
|
||||
row->lineno = $1.lineno;
|
||||
|
||||
if ($2)
|
||||
if (var->dtype == PLPGSQL_DTYPE_VAR)
|
||||
((PLpgSQL_var *) var)->notnull = $4;
|
||||
else
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("rowtype variable cannot be CONSTANT")));
|
||||
if ($4)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("rowtype variable cannot be NOT NULL")));
|
||||
if ($5 != NULL)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("default value for rowtype variable is not supported")));
|
||||
|
||||
plpgsql_adddatum((PLpgSQL_datum *)row);
|
||||
plpgsql_ns_additem(PLPGSQL_NSTYPE_ROW,
|
||||
row->rowno,
|
||||
$1.name);
|
||||
|
||||
errmsg("row or record variable cannot be NOT NULL")));
|
||||
}
|
||||
if ($5 != NULL)
|
||||
{
|
||||
if (var->dtype == PLPGSQL_DTYPE_VAR)
|
||||
((PLpgSQL_var *) var)->default_val = $5;
|
||||
else
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("default value for row or record variable is not supported")));
|
||||
}
|
||||
}
|
||||
| decl_varname K_RECORD ';'
|
||||
{
|
||||
PLpgSQL_rec *var;
|
||||
|
||||
var = malloc(sizeof(PLpgSQL_rec));
|
||||
|
||||
var->dtype = PLPGSQL_DTYPE_REC;
|
||||
var->refname = $1.name;
|
||||
var->lineno = $1.lineno;
|
||||
|
||||
plpgsql_adddatum((PLpgSQL_datum *)var);
|
||||
plpgsql_ns_additem(PLPGSQL_NSTYPE_REC, var->recno,
|
||||
$1.name);
|
||||
}
|
||||
| decl_varname decl_rowtype ';'
|
||||
{
|
||||
$2->dtype = PLPGSQL_DTYPE_ROW;
|
||||
$2->refname = $1.name;
|
||||
$2->lineno = $1.lineno;
|
||||
|
||||
plpgsql_adddatum((PLpgSQL_datum *)$2);
|
||||
plpgsql_ns_additem(PLPGSQL_NSTYPE_ROW, $2->rowno,
|
||||
$1.name);
|
||||
}
|
||||
| decl_varname K_ALIAS K_FOR decl_aliasitem ';'
|
||||
{
|
||||
plpgsql_ns_additem($4->itemtype,
|
||||
$4->itemno, $1.name);
|
||||
$4->itemno, $1.name);
|
||||
}
|
||||
| K_RENAME decl_renname K_TO decl_renname ';'
|
||||
{
|
||||
@ -404,16 +361,15 @@ decl_statement : decl_varname decl_const decl_datatype decl_notnull decl_defval
|
||||
/* pop local namespace for cursor args */
|
||||
plpgsql_ns_pop();
|
||||
|
||||
new = malloc(sizeof(PLpgSQL_var));
|
||||
memset(new, 0, sizeof(PLpgSQL_var));
|
||||
new = (PLpgSQL_var *)
|
||||
plpgsql_build_variable($1.name, $1.lineno,
|
||||
plpgsql_build_datatype(REFCURSOROID,
|
||||
-1),
|
||||
true);
|
||||
|
||||
curname_def = malloc(sizeof(PLpgSQL_expr));
|
||||
memset(curname_def, 0, sizeof(PLpgSQL_expr));
|
||||
|
||||
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;
|
||||
@ -428,17 +384,11 @@ decl_statement : decl_varname decl_const decl_datatype decl_notnull decl_defval
|
||||
curname_def->query = strdup(buf);
|
||||
new->default_val = curname_def;
|
||||
|
||||
new->datatype = plpgsql_parse_datatype("refcursor");
|
||||
|
||||
new->cursor_explicit_expr = $6;
|
||||
if ($4 == NULL)
|
||||
new->cursor_explicit_argrow = -1;
|
||||
else
|
||||
new->cursor_explicit_argrow = $4->rowno;
|
||||
|
||||
plpgsql_adddatum((PLpgSQL_datum *)new);
|
||||
plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, new->varno,
|
||||
$1.name);
|
||||
}
|
||||
;
|
||||
|
||||
@ -504,7 +454,7 @@ decl_cursor_arglist : decl_cursor_arg
|
||||
new->nfields = 1;
|
||||
|
||||
new->fieldnames[0] = $1->refname;
|
||||
new->varnos[0] = $1->varno;
|
||||
new->varnos[0] = $1->dno;
|
||||
|
||||
$$ = new;
|
||||
}
|
||||
@ -513,7 +463,7 @@ decl_cursor_arglist : decl_cursor_arg
|
||||
int i = $1->nfields++;
|
||||
|
||||
$1->fieldnames[i] = $3->refname;
|
||||
$1->varnos[i] = $3->varno;
|
||||
$1->varnos[i] = $3->dno;
|
||||
|
||||
$$ = $1;
|
||||
}
|
||||
@ -521,24 +471,8 @@ decl_cursor_arglist : decl_cursor_arg
|
||||
|
||||
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;
|
||||
$$ = plpgsql_build_variable($1.name, $1.lineno,
|
||||
$2, true);
|
||||
}
|
||||
;
|
||||
|
||||
@ -573,12 +507,6 @@ decl_aliasitem : T_WORD
|
||||
}
|
||||
;
|
||||
|
||||
decl_rowtype : T_ROW
|
||||
{
|
||||
$$ = yylval.row;
|
||||
}
|
||||
;
|
||||
|
||||
decl_varname : T_WORD
|
||||
{
|
||||
char *name;
|
||||
@ -803,18 +731,18 @@ getdiag_item : K_ROW_COUNT
|
||||
}
|
||||
;
|
||||
|
||||
getdiag_target : T_VARIABLE
|
||||
getdiag_target : T_SCALAR
|
||||
{
|
||||
check_assignable(yylval.variable);
|
||||
$$ = yylval.variable->dno;
|
||||
check_assignable(yylval.scalar);
|
||||
$$ = yylval.scalar->dno;
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
assign_var : T_VARIABLE
|
||||
assign_var : T_SCALAR
|
||||
{
|
||||
check_assignable(yylval.variable);
|
||||
$$ = yylval.variable->dno;
|
||||
check_assignable(yylval.scalar);
|
||||
$$ = yylval.scalar->dno;
|
||||
}
|
||||
| assign_var '[' expr_until_rightbracket
|
||||
{
|
||||
@ -970,21 +898,11 @@ 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;
|
||||
new->lineno = $1.lineno;
|
||||
|
||||
new->datatype = plpgsql_parse_datatype("integer");
|
||||
new->isconst = false;
|
||||
new->notnull = false;
|
||||
new->default_val = NULL;
|
||||
|
||||
plpgsql_adddatum((PLpgSQL_datum *)new);
|
||||
plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, new->varno,
|
||||
$1.name);
|
||||
new = (PLpgSQL_var *)
|
||||
plpgsql_build_variable($1.name, $1.lineno,
|
||||
plpgsql_build_datatype(INT4OID,
|
||||
-1),
|
||||
true);
|
||||
|
||||
plpgsql_add_initdatums(NULL);
|
||||
|
||||
@ -992,7 +910,7 @@ fori_var : fori_varname
|
||||
}
|
||||
;
|
||||
|
||||
fori_varname : T_VARIABLE
|
||||
fori_varname : T_SCALAR
|
||||
{
|
||||
char *name;
|
||||
|
||||
@ -1297,9 +1215,9 @@ raise_params : raise_params raise_param
|
||||
}
|
||||
;
|
||||
|
||||
raise_param : ',' T_VARIABLE
|
||||
raise_param : ',' T_SCALAR
|
||||
{
|
||||
$$ = yylval.variable->dno;
|
||||
$$ = yylval.scalar->dno;
|
||||
}
|
||||
;
|
||||
|
||||
@ -1491,37 +1409,37 @@ stmt_close : K_CLOSE lno cursor_variable ';'
|
||||
}
|
||||
;
|
||||
|
||||
cursor_varptr : T_VARIABLE
|
||||
cursor_varptr : T_SCALAR
|
||||
{
|
||||
if (yylval.variable->dtype != PLPGSQL_DTYPE_VAR)
|
||||
if (yylval.scalar->dtype != PLPGSQL_DTYPE_VAR)
|
||||
yyerror("cursor variable must be a simple variable");
|
||||
|
||||
if (((PLpgSQL_var *) yylval.variable)->datatype->typoid != REFCURSOROID)
|
||||
if (((PLpgSQL_var *) yylval.scalar)->datatype->typoid != REFCURSOROID)
|
||||
{
|
||||
plpgsql_error_lineno = plpgsql_scanner_lineno();
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
||||
errmsg("\"%s\" must be of type cursor or refcursor",
|
||||
((PLpgSQL_var *) yylval.variable)->refname)));
|
||||
((PLpgSQL_var *) yylval.scalar)->refname)));
|
||||
}
|
||||
$$ = (PLpgSQL_var *) yylval.variable;
|
||||
$$ = (PLpgSQL_var *) yylval.scalar;
|
||||
}
|
||||
;
|
||||
|
||||
cursor_variable : T_VARIABLE
|
||||
cursor_variable : T_SCALAR
|
||||
{
|
||||
if (yylval.variable->dtype != PLPGSQL_DTYPE_VAR)
|
||||
if (yylval.scalar->dtype != PLPGSQL_DTYPE_VAR)
|
||||
yyerror("cursor variable must be a simple variable");
|
||||
|
||||
if (((PLpgSQL_var *) yylval.variable)->datatype->typoid != REFCURSOROID)
|
||||
if (((PLpgSQL_var *) yylval.scalar)->datatype->typoid != REFCURSOROID)
|
||||
{
|
||||
plpgsql_error_lineno = plpgsql_scanner_lineno();
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
||||
errmsg("\"%s\" must be of type refcursor",
|
||||
((PLpgSQL_var *) yylval.variable)->refname)));
|
||||
((PLpgSQL_var *) yylval.scalar)->refname)));
|
||||
}
|
||||
$$ = yylval.variable->dno;
|
||||
$$ = yylval.scalar->dno;
|
||||
}
|
||||
;
|
||||
|
||||
@ -1664,8 +1582,8 @@ read_sql_construct(int until,
|
||||
plpgsql_dstring_append(&ds, " ");
|
||||
switch (tok)
|
||||
{
|
||||
case T_VARIABLE:
|
||||
params[nparams] = yylval.variable->dno;
|
||||
case T_SCALAR:
|
||||
params[nparams] = yylval.scalar->dno;
|
||||
snprintf(buf, sizeof(buf), " $%d ", ++nparams);
|
||||
plpgsql_dstring_append(&ds, buf);
|
||||
break;
|
||||
@ -1821,25 +1739,25 @@ make_select_stmt(void)
|
||||
have_into = 1;
|
||||
break;
|
||||
|
||||
case T_VARIABLE:
|
||||
case T_SCALAR:
|
||||
{
|
||||
int nfields = 1;
|
||||
char *fieldnames[1024];
|
||||
int varnos[1024];
|
||||
|
||||
check_assignable(yylval.variable);
|
||||
check_assignable(yylval.scalar);
|
||||
fieldnames[0] = strdup(yytext);
|
||||
varnos[0] = yylval.variable->dno;
|
||||
varnos[0] = yylval.scalar->dno;
|
||||
|
||||
while ((tok = yylex()) == ',')
|
||||
{
|
||||
tok = yylex();
|
||||
switch(tok)
|
||||
{
|
||||
case T_VARIABLE:
|
||||
check_assignable(yylval.variable);
|
||||
case T_SCALAR:
|
||||
check_assignable(yylval.scalar);
|
||||
fieldnames[nfields] = strdup(yytext);
|
||||
varnos[nfields++] = yylval.variable->dno;
|
||||
varnos[nfields++] = yylval.scalar->dno;
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -1885,8 +1803,8 @@ make_select_stmt(void)
|
||||
plpgsql_dstring_append(&ds, " ");
|
||||
switch (tok)
|
||||
{
|
||||
case T_VARIABLE:
|
||||
params[nparams] = yylval.variable->dno;
|
||||
case T_SCALAR:
|
||||
params[nparams] = yylval.scalar->dno;
|
||||
snprintf(buf, sizeof(buf), " $%d ", ++nparams);
|
||||
plpgsql_dstring_append(&ds, buf);
|
||||
break;
|
||||
@ -1968,25 +1886,25 @@ make_fetch_stmt(void)
|
||||
rec = yylval.rec;
|
||||
break;
|
||||
|
||||
case T_VARIABLE:
|
||||
case T_SCALAR:
|
||||
{
|
||||
int nfields = 1;
|
||||
char *fieldnames[1024];
|
||||
int varnos[1024];
|
||||
|
||||
check_assignable(yylval.variable);
|
||||
check_assignable(yylval.scalar);
|
||||
fieldnames[0] = strdup(yytext);
|
||||
varnos[0] = yylval.variable->dno;
|
||||
varnos[0] = yylval.scalar->dno;
|
||||
|
||||
while ((tok = yylex()) == ',')
|
||||
{
|
||||
tok = yylex();
|
||||
switch(tok)
|
||||
{
|
||||
case T_VARIABLE:
|
||||
check_assignable(yylval.variable);
|
||||
case T_SCALAR:
|
||||
check_assignable(yylval.scalar);
|
||||
fieldnames[nfields] = strdup(yytext);
|
||||
varnos[nfields++] = yylval.variable->dno;
|
||||
varnos[nfields++] = yylval.scalar->dno;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -3,7 +3,7 @@
|
||||
* procedural language
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.75 2004/03/21 22:29:11 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.76 2004/06/03 22:56:43 tgl Exp $
|
||||
*
|
||||
* This software is copyrighted by Jan Wieck - Hamburg.
|
||||
*
|
||||
@ -56,6 +56,7 @@
|
||||
#include "tcop/tcopprot.h"
|
||||
#include "utils/array.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/lsyscache.h"
|
||||
#include "utils/syscache.h"
|
||||
|
||||
|
||||
@ -105,6 +106,7 @@ static PLpgSQL_function *do_compile(FunctionCallInfo fcinfo,
|
||||
bool forValidator);
|
||||
static void plpgsql_compile_error_callback(void *arg);
|
||||
static char **fetchArgNames(HeapTuple procTup, int nargs);
|
||||
static PLpgSQL_row *build_row_var(Oid classOid);
|
||||
static PLpgSQL_type *build_datatype(HeapTuple typeTup, int32 typmod);
|
||||
static void compute_function_hashkey(FunctionCallInfo fcinfo,
|
||||
Form_pg_proc procStruct,
|
||||
@ -249,8 +251,7 @@ do_compile(FunctionCallInfo fcinfo,
|
||||
char *proc_source;
|
||||
HeapTuple typeTup;
|
||||
Form_pg_type typeStruct;
|
||||
PLpgSQL_var *var;
|
||||
PLpgSQL_row *row;
|
||||
PLpgSQL_variable *var;
|
||||
PLpgSQL_rec *rec;
|
||||
int i;
|
||||
int arg_varnos[FUNC_MAX_ARGS];
|
||||
@ -392,33 +393,9 @@ do_compile(FunctionCallInfo fcinfo,
|
||||
if (procStruct->prorettype == ANYARRAYOID ||
|
||||
procStruct->prorettype == ANYELEMENTOID)
|
||||
{
|
||||
char buf[32];
|
||||
|
||||
/* name for variable */
|
||||
snprintf(buf, sizeof(buf), "$%d", 0);
|
||||
|
||||
/*
|
||||
* Normal return values get a var node
|
||||
*/
|
||||
var = malloc(sizeof(PLpgSQL_var));
|
||||
memset(var, 0, sizeof(PLpgSQL_var));
|
||||
|
||||
var->dtype = PLPGSQL_DTYPE_VAR;
|
||||
var->refname = strdup(buf);
|
||||
var->lineno = 0;
|
||||
var->datatype = build_datatype(typeTup, -1);
|
||||
var->isconst = false;
|
||||
var->notnull = false;
|
||||
var->default_val = NULL;
|
||||
|
||||
/* preset to NULL */
|
||||
var->value = 0;
|
||||
var->isnull = true;
|
||||
var->freeval = false;
|
||||
|
||||
plpgsql_adddatum((PLpgSQL_datum *) var);
|
||||
plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, var->varno,
|
||||
var->refname);
|
||||
(void) plpgsql_build_variable(strdup("$0"), 0,
|
||||
build_datatype(typeTup, -1),
|
||||
true);
|
||||
}
|
||||
}
|
||||
ReleaseSysCache(typeTup);
|
||||
@ -432,7 +409,8 @@ do_compile(FunctionCallInfo fcinfo,
|
||||
{
|
||||
char buf[32];
|
||||
Oid argtypeid;
|
||||
PLpgSQL_datum *argdatum;
|
||||
PLpgSQL_type *argdtype;
|
||||
PLpgSQL_variable *argvariable;
|
||||
int argitemtype;
|
||||
|
||||
/* Create $n name for variable */
|
||||
@ -444,70 +422,44 @@ do_compile(FunctionCallInfo fcinfo,
|
||||
* the hashkey, we can just use those results.
|
||||
*/
|
||||
argtypeid = hashkey->argtypes[i];
|
||||
|
||||
/*
|
||||
* Get the parameter type
|
||||
*/
|
||||
typeTup = SearchSysCache(TYPEOID,
|
||||
ObjectIdGetDatum(argtypeid),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(typeTup))
|
||||
elog(ERROR, "cache lookup failed for type %u", argtypeid);
|
||||
typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
|
||||
argdtype = plpgsql_build_datatype(argtypeid, -1);
|
||||
|
||||
/* Disallow pseudotype argument */
|
||||
/* (note we already replaced ANYARRAY/ANYELEMENT) */
|
||||
if (typeStruct->typtype == 'p')
|
||||
/* (build_variable would do this, but wrong message) */
|
||||
if (argdtype->ttype != PLPGSQL_TTYPE_SCALAR &&
|
||||
argdtype->ttype != PLPGSQL_TTYPE_ROW)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("plpgsql functions cannot take type %s",
|
||||
format_type_be(argtypeid))));
|
||||
errmsg("plpgsql functions cannot take type %s",
|
||||
format_type_be(argtypeid))));
|
||||
|
||||
if (typeStruct->typrelid != InvalidOid)
|
||||
/* Build variable and add to datum list */
|
||||
argvariable = plpgsql_build_variable(strdup(buf), 0,
|
||||
argdtype, false);
|
||||
|
||||
if (argvariable->dtype == PLPGSQL_DTYPE_VAR)
|
||||
{
|
||||
/*
|
||||
* For tuple type parameters, we set up a record of
|
||||
* that type
|
||||
*/
|
||||
row = plpgsql_build_rowtype(typeStruct->typrelid);
|
||||
row->refname = strdup(buf);
|
||||
|
||||
argdatum = (PLpgSQL_datum *) row;
|
||||
argitemtype = PLPGSQL_NSTYPE_ROW;
|
||||
/* argument vars are forced to be CONSTANT (why?) */
|
||||
((PLpgSQL_var *) argvariable)->isconst = true;
|
||||
argitemtype = PLPGSQL_NSTYPE_VAR;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Normal parameters get a var node
|
||||
*/
|
||||
var = malloc(sizeof(PLpgSQL_var));
|
||||
memset(var, 0, sizeof(PLpgSQL_var));
|
||||
|
||||
var->dtype = PLPGSQL_DTYPE_VAR;
|
||||
var->refname = strdup(buf);
|
||||
var->lineno = 0;
|
||||
var->datatype = build_datatype(typeTup, -1);
|
||||
var->isconst = true;
|
||||
var->notnull = false;
|
||||
var->default_val = NULL;
|
||||
|
||||
argdatum = (PLpgSQL_datum *) var;
|
||||
argitemtype = PLPGSQL_NSTYPE_VAR;
|
||||
Assert(argvariable->dtype == PLPGSQL_DTYPE_ROW);
|
||||
argitemtype = PLPGSQL_NSTYPE_ROW;
|
||||
}
|
||||
|
||||
/* Add it to datum list, and remember datum number */
|
||||
plpgsql_adddatum(argdatum);
|
||||
arg_varnos[i] = argdatum->dno;
|
||||
/* Remember datum number */
|
||||
arg_varnos[i] = argvariable->dno;
|
||||
|
||||
/* Add to namespace under the $n name */
|
||||
plpgsql_ns_additem(argitemtype, argdatum->dno, buf);
|
||||
plpgsql_ns_additem(argitemtype, argvariable->dno, buf);
|
||||
|
||||
/* If there's a name for the argument, make an alias */
|
||||
if (argnames && argnames[i] && argnames[i][0])
|
||||
plpgsql_ns_additem(argitemtype, argdatum->dno,
|
||||
plpgsql_ns_additem(argitemtype, argvariable->dno,
|
||||
argnames[i]);
|
||||
|
||||
ReleaseSysCache(typeTup);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -552,128 +504,58 @@ do_compile(FunctionCallInfo fcinfo,
|
||||
/*
|
||||
* 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;
|
||||
var->datatype = plpgsql_parse_datatype("name");
|
||||
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;
|
||||
var = plpgsql_build_variable(strdup("tg_name"), 0,
|
||||
plpgsql_build_datatype(NAMEOID, -1),
|
||||
true);
|
||||
function->tg_name_varno = var->dno;
|
||||
|
||||
/*
|
||||
* 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;
|
||||
var->datatype = plpgsql_parse_datatype("text");
|
||||
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;
|
||||
var = plpgsql_build_variable(strdup("tg_when"), 0,
|
||||
plpgsql_build_datatype(TEXTOID, -1),
|
||||
true);
|
||||
function->tg_when_varno = var->dno;
|
||||
|
||||
/*
|
||||
* 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;
|
||||
var->datatype = plpgsql_parse_datatype("text");
|
||||
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;
|
||||
var = plpgsql_build_variable(strdup("tg_level"), 0,
|
||||
plpgsql_build_datatype(TEXTOID, -1),
|
||||
true);
|
||||
function->tg_level_varno = var->dno;
|
||||
|
||||
/*
|
||||
* 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;
|
||||
var->datatype = plpgsql_parse_datatype("text");
|
||||
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;
|
||||
var = plpgsql_build_variable(strdup("tg_op"), 0,
|
||||
plpgsql_build_datatype(TEXTOID, -1),
|
||||
true);
|
||||
function->tg_op_varno = var->dno;
|
||||
|
||||
/*
|
||||
* 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;
|
||||
var->datatype = plpgsql_parse_datatype("oid");
|
||||
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;
|
||||
var = plpgsql_build_variable(strdup("tg_relid"), 0,
|
||||
plpgsql_build_datatype(OIDOID, -1),
|
||||
true);
|
||||
function->tg_relid_varno = var->dno;
|
||||
|
||||
/*
|
||||
* 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;
|
||||
var->datatype = plpgsql_parse_datatype("name");
|
||||
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;
|
||||
var = plpgsql_build_variable(strdup("tg_relname"), 0,
|
||||
plpgsql_build_datatype(NAMEOID, -1),
|
||||
true);
|
||||
function->tg_relname_varno = var->dno;
|
||||
|
||||
/*
|
||||
* 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;
|
||||
var->datatype = plpgsql_parse_datatype("int4");
|
||||
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;
|
||||
var = plpgsql_build_variable(strdup("tg_nargs"), 0,
|
||||
plpgsql_build_datatype(INT4OID, -1),
|
||||
true);
|
||||
function->tg_nargs_varno = var->dno;
|
||||
|
||||
break;
|
||||
|
||||
@ -685,20 +567,10 @@ do_compile(FunctionCallInfo fcinfo,
|
||||
/*
|
||||
* Create the magic FOUND variable.
|
||||
*/
|
||||
var = malloc(sizeof(PLpgSQL_var));
|
||||
memset(var, 0, sizeof(PLpgSQL_var));
|
||||
|
||||
var->dtype = PLPGSQL_DTYPE_VAR;
|
||||
var->refname = strdup("found");
|
||||
var->lineno = 0;
|
||||
var->datatype = plpgsql_parse_datatype("bool");
|
||||
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->found_varno = var->varno;
|
||||
var = plpgsql_build_variable(strdup("found"), 0,
|
||||
plpgsql_build_datatype(BOOLOID, -1),
|
||||
true);
|
||||
function->found_varno = var->dno;
|
||||
|
||||
/*
|
||||
* Forget about the above created variables
|
||||
@ -848,11 +720,11 @@ plpgsql_parse_word(char *word)
|
||||
trigarg->argnum = plpgsql_read_expression(']', "]");
|
||||
|
||||
plpgsql_adddatum((PLpgSQL_datum *) trigarg);
|
||||
plpgsql_yylval.variable = (PLpgSQL_datum *) trigarg;
|
||||
plpgsql_yylval.scalar = (PLpgSQL_datum *) trigarg;
|
||||
|
||||
plpgsql_SpaceScanned = save_spacescanned;
|
||||
pfree(cp[0]);
|
||||
return T_VARIABLE;
|
||||
return T_SCALAR;
|
||||
}
|
||||
}
|
||||
|
||||
@ -869,8 +741,8 @@ plpgsql_parse_word(char *word)
|
||||
return T_LABEL;
|
||||
|
||||
case PLPGSQL_NSTYPE_VAR:
|
||||
plpgsql_yylval.var = (PLpgSQL_var *) (plpgsql_Datums[nse->itemno]);
|
||||
return T_VARIABLE;
|
||||
plpgsql_yylval.scalar = plpgsql_Datums[nse->itemno];
|
||||
return T_SCALAR;
|
||||
|
||||
case PLPGSQL_NSTYPE_REC:
|
||||
plpgsql_yylval.rec = (PLpgSQL_rec *) (plpgsql_Datums[nse->itemno]);
|
||||
@ -937,8 +809,8 @@ plpgsql_parse_dblword(char *word)
|
||||
switch (ns->itemtype)
|
||||
{
|
||||
case PLPGSQL_NSTYPE_VAR:
|
||||
plpgsql_yylval.var = (PLpgSQL_var *) (plpgsql_Datums[ns->itemno]);
|
||||
return T_VARIABLE;
|
||||
plpgsql_yylval.scalar = plpgsql_Datums[ns->itemno];
|
||||
return T_SCALAR;
|
||||
|
||||
case PLPGSQL_NSTYPE_REC:
|
||||
plpgsql_yylval.rec = (PLpgSQL_rec *) (plpgsql_Datums[ns->itemno]);
|
||||
@ -968,11 +840,11 @@ plpgsql_parse_dblword(char *word)
|
||||
|
||||
plpgsql_adddatum((PLpgSQL_datum *) new);
|
||||
|
||||
plpgsql_yylval.variable = (PLpgSQL_datum *) new;
|
||||
plpgsql_yylval.scalar = (PLpgSQL_datum *) new;
|
||||
|
||||
pfree(cp[0]);
|
||||
pfree(cp[1]);
|
||||
return T_VARIABLE;
|
||||
return T_SCALAR;
|
||||
}
|
||||
|
||||
case PLPGSQL_NSTYPE_ROW:
|
||||
@ -990,10 +862,10 @@ plpgsql_parse_dblword(char *word)
|
||||
if (row->fieldnames[i] &&
|
||||
strcmp(row->fieldnames[i], cp[1]) == 0)
|
||||
{
|
||||
plpgsql_yylval.var = (PLpgSQL_var *) (plpgsql_Datums[row->varnos[i]]);
|
||||
plpgsql_yylval.scalar = plpgsql_Datums[row->varnos[i]];
|
||||
pfree(cp[0]);
|
||||
pfree(cp[1]);
|
||||
return T_VARIABLE;
|
||||
return T_SCALAR;
|
||||
}
|
||||
}
|
||||
ereport(ERROR,
|
||||
@ -1074,12 +946,13 @@ plpgsql_parse_tripword(char *word)
|
||||
|
||||
plpgsql_adddatum((PLpgSQL_datum *) new);
|
||||
|
||||
plpgsql_yylval.variable = (PLpgSQL_datum *) new;
|
||||
plpgsql_yylval.scalar = (PLpgSQL_datum *) new;
|
||||
|
||||
pfree(cp[0]);
|
||||
pfree(cp[1]);
|
||||
pfree(cp[2]);
|
||||
return T_VARIABLE;
|
||||
|
||||
return T_SCALAR;
|
||||
}
|
||||
|
||||
case PLPGSQL_NSTYPE_ROW:
|
||||
@ -1097,11 +970,13 @@ plpgsql_parse_tripword(char *word)
|
||||
if (row->fieldnames[i] &&
|
||||
strcmp(row->fieldnames[i], cp[2]) == 0)
|
||||
{
|
||||
plpgsql_yylval.var = (PLpgSQL_var *) (plpgsql_Datums[row->varnos[i]]);
|
||||
plpgsql_yylval.scalar = plpgsql_Datums[row->varnos[i]];
|
||||
|
||||
pfree(cp[0]);
|
||||
pfree(cp[1]);
|
||||
pfree(cp[2]);
|
||||
return T_VARIABLE;
|
||||
|
||||
return T_SCALAR;
|
||||
}
|
||||
}
|
||||
ereport(ERROR,
|
||||
@ -1161,6 +1036,8 @@ plpgsql_parse_wordtype(char *word)
|
||||
plpgsql_yylval.dtype = ((PLpgSQL_var *) (plpgsql_Datums[nse->itemno]))->datatype;
|
||||
return T_DTYPE;
|
||||
|
||||
/* XXX perhaps allow REC here? */
|
||||
|
||||
default:
|
||||
return T_ERROR;
|
||||
}
|
||||
@ -1451,6 +1328,7 @@ plpgsql_parse_tripwordtype(char *word)
|
||||
ReleaseSysCache(typetup);
|
||||
pfree(cp[0]);
|
||||
pfree(cp[1]);
|
||||
|
||||
return T_DTYPE;
|
||||
}
|
||||
|
||||
@ -1482,21 +1360,20 @@ plpgsql_parse_wordrowtype(char *word)
|
||||
errmsg("relation \"%s\" does not exist", cp[0])));
|
||||
|
||||
/*
|
||||
* Build and return the complete row definition
|
||||
* Build and return the row type struct
|
||||
*/
|
||||
plpgsql_yylval.row = plpgsql_build_rowtype(classOid);
|
||||
|
||||
plpgsql_adddatum((PLpgSQL_datum *) plpgsql_yylval.row);
|
||||
plpgsql_yylval.dtype = plpgsql_build_datatype(get_rel_type_id(classOid),
|
||||
-1);
|
||||
|
||||
pfree(cp[0]);
|
||||
pfree(cp[1]);
|
||||
|
||||
return T_ROW;
|
||||
return T_DTYPE;
|
||||
}
|
||||
|
||||
/* ----------
|
||||
* plpgsql_parse_dblwordrowtype Scanner found word.word%ROWTYPE.
|
||||
* So word must be namespace qualified a table name.
|
||||
* So word must be a namespace qualified table name.
|
||||
* ----------
|
||||
*/
|
||||
#define ROWTYPE_JUNK_LEN 8
|
||||
@ -1527,22 +1404,120 @@ plpgsql_parse_dblwordrowtype(char *word)
|
||||
errmsg("relation \"%s\" does not exist", cp)));
|
||||
|
||||
/*
|
||||
* Build and return the complete row definition
|
||||
* Build and return the row type struct
|
||||
*/
|
||||
plpgsql_yylval.row = plpgsql_build_rowtype(classOid);
|
||||
|
||||
plpgsql_adddatum((PLpgSQL_datum *) plpgsql_yylval.row);
|
||||
plpgsql_yylval.dtype = plpgsql_build_datatype(get_rel_type_id(classOid),
|
||||
-1);
|
||||
|
||||
pfree(cp);
|
||||
|
||||
return T_ROW;
|
||||
return T_DTYPE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Build a rowtype data structure given the pg_class OID.
|
||||
* plpgsql_build_variable - build a datum-array entry of a given datatype
|
||||
*
|
||||
* The returned struct may be a PLpgSQL_var, PLpgSQL_row, or PLpgSQL_rec
|
||||
* depending on the given datatype. The struct is automatically added
|
||||
* to the current datum array, and optionally to the current namespace.
|
||||
*/
|
||||
PLpgSQL_row *
|
||||
plpgsql_build_rowtype(Oid classOid)
|
||||
PLpgSQL_variable *
|
||||
plpgsql_build_variable(char *refname, int lineno, PLpgSQL_type *dtype,
|
||||
bool add2namespace)
|
||||
{
|
||||
PLpgSQL_variable *result;
|
||||
|
||||
switch (dtype->ttype)
|
||||
{
|
||||
case PLPGSQL_TTYPE_SCALAR:
|
||||
{
|
||||
/* Ordinary scalar datatype */
|
||||
PLpgSQL_var *var;
|
||||
|
||||
var = malloc(sizeof(PLpgSQL_var));
|
||||
memset(var, 0, sizeof(PLpgSQL_var));
|
||||
|
||||
var->dtype = PLPGSQL_DTYPE_VAR;
|
||||
var->refname = refname;
|
||||
var->lineno = lineno;
|
||||
var->datatype = dtype;
|
||||
/* other fields might be filled by caller */
|
||||
|
||||
/* preset to NULL */
|
||||
var->value = 0;
|
||||
var->isnull = true;
|
||||
var->freeval = false;
|
||||
|
||||
plpgsql_adddatum((PLpgSQL_datum *) var);
|
||||
if (add2namespace)
|
||||
plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR,
|
||||
var->varno,
|
||||
refname);
|
||||
result = (PLpgSQL_variable *) var;
|
||||
break;
|
||||
}
|
||||
case PLPGSQL_TTYPE_ROW:
|
||||
{
|
||||
/* Composite type -- build a row variable */
|
||||
PLpgSQL_row *row;
|
||||
|
||||
row = build_row_var(dtype->typrelid);
|
||||
|
||||
row->dtype = PLPGSQL_DTYPE_ROW;
|
||||
row->refname = refname;
|
||||
row->lineno = lineno;
|
||||
|
||||
plpgsql_adddatum((PLpgSQL_datum *) row);
|
||||
if (add2namespace)
|
||||
plpgsql_ns_additem(PLPGSQL_NSTYPE_ROW,
|
||||
row->rowno,
|
||||
refname);
|
||||
result = (PLpgSQL_variable *) row;
|
||||
break;
|
||||
}
|
||||
case PLPGSQL_TTYPE_REC:
|
||||
{
|
||||
/* "record" type -- build a variable-contents record variable */
|
||||
PLpgSQL_rec *rec;
|
||||
|
||||
rec = malloc(sizeof(PLpgSQL_rec));
|
||||
memset(rec, 0, sizeof(PLpgSQL_rec));
|
||||
|
||||
rec->dtype = PLPGSQL_DTYPE_REC;
|
||||
rec->refname = refname;
|
||||
rec->lineno = lineno;
|
||||
|
||||
plpgsql_adddatum((PLpgSQL_datum *) rec);
|
||||
if (add2namespace)
|
||||
plpgsql_ns_additem(PLPGSQL_NSTYPE_REC,
|
||||
rec->recno,
|
||||
refname);
|
||||
result = (PLpgSQL_variable *) rec;
|
||||
break;
|
||||
}
|
||||
case PLPGSQL_TTYPE_PSEUDO:
|
||||
{
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("variable \"%s\" has pseudo-type %s",
|
||||
refname, format_type_be(dtype->typoid))));
|
||||
result = NULL; /* keep compiler quiet */
|
||||
break;
|
||||
}
|
||||
default:
|
||||
elog(ERROR, "unrecognized ttype: %d", dtype->ttype);
|
||||
result = NULL; /* keep compiler quiet */
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Build a row-variable data structure given the pg_class OID.
|
||||
*/
|
||||
static PLpgSQL_row *
|
||||
build_row_var(Oid classOid)
|
||||
{
|
||||
PLpgSQL_row *row;
|
||||
Relation rel;
|
||||
@ -1601,17 +1576,14 @@ plpgsql_build_rowtype(Oid classOid)
|
||||
if (!attrStruct->attisdropped)
|
||||
{
|
||||
const char *attname;
|
||||
HeapTuple typetup;
|
||||
PLpgSQL_var *var;
|
||||
char *refname;
|
||||
PLpgSQL_variable *var;
|
||||
|
||||
attname = NameStr(attrStruct->attname);
|
||||
|
||||
typetup = SearchSysCache(TYPEOID,
|
||||
ObjectIdGetDatum(attrStruct->atttypid),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(typetup))
|
||||
elog(ERROR, "cache lookup failed for type %u",
|
||||
attrStruct->atttypid);
|
||||
refname = malloc(strlen(relname) + strlen(attname) + 2);
|
||||
strcpy(refname, relname);
|
||||
strcat(refname, ".");
|
||||
strcat(refname, attname);
|
||||
|
||||
/*
|
||||
* Create the internal variable for the field
|
||||
@ -1623,30 +1595,16 @@ plpgsql_build_rowtype(Oid classOid)
|
||||
* the variables due to entering a block at execution time. Thus
|
||||
* we ignore this information for now.
|
||||
*/
|
||||
var = malloc(sizeof(PLpgSQL_var));
|
||||
MemSet(var, 0, sizeof(PLpgSQL_var));
|
||||
var->dtype = PLPGSQL_DTYPE_VAR;
|
||||
var->refname = malloc(strlen(relname) + strlen(attname) + 2);
|
||||
strcpy(var->refname, relname);
|
||||
strcat(var->refname, ".");
|
||||
strcat(var->refname, attname);
|
||||
var->datatype = build_datatype(typetup, attrStruct->atttypmod);
|
||||
var->isconst = false;
|
||||
var->notnull = false;
|
||||
var->default_val = NULL;
|
||||
var->value = (Datum) 0;
|
||||
var->isnull = true;
|
||||
var->freeval = false;
|
||||
|
||||
plpgsql_adddatum((PLpgSQL_datum *) var);
|
||||
var = plpgsql_build_variable(refname, 0,
|
||||
plpgsql_build_datatype(attrStruct->atttypid,
|
||||
attrStruct->atttypmod),
|
||||
false);
|
||||
|
||||
/*
|
||||
* Add the variable to the row.
|
||||
*/
|
||||
row->fieldnames[i] = strdup(attname);
|
||||
row->varnos[i] = var->varno;
|
||||
|
||||
ReleaseSysCache(typetup);
|
||||
row->varnos[i] = var->dno;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1668,22 +1626,33 @@ plpgsql_build_rowtype(Oid classOid)
|
||||
* ----------
|
||||
*/
|
||||
PLpgSQL_type *
|
||||
plpgsql_parse_datatype(char *string)
|
||||
plpgsql_parse_datatype(const char *string)
|
||||
{
|
||||
Oid type_id;
|
||||
int32 typmod;
|
||||
HeapTuple typeTup;
|
||||
PLpgSQL_type *typ;
|
||||
|
||||
/* Let the main parser try to parse it under standard SQL rules */
|
||||
parseTypeString(string, &type_id, &typmod);
|
||||
|
||||
/* Okay, build a PLpgSQL_type data structure for it */
|
||||
return plpgsql_build_datatype(type_id, typmod);
|
||||
}
|
||||
|
||||
/*
|
||||
* plpgsql_build_datatype
|
||||
* Build PLpgSQL_type struct given type OID and typmod.
|
||||
*/
|
||||
PLpgSQL_type *
|
||||
plpgsql_build_datatype(Oid typeOid, int32 typmod)
|
||||
{
|
||||
HeapTuple typeTup;
|
||||
PLpgSQL_type *typ;
|
||||
|
||||
typeTup = SearchSysCache(TYPEOID,
|
||||
ObjectIdGetDatum(type_id),
|
||||
ObjectIdGetDatum(typeOid),
|
||||
0, 0, 0);
|
||||
if (!HeapTupleIsValid(typeTup))
|
||||
elog(ERROR, "cache lookup failed for type %u", type_id);
|
||||
elog(ERROR, "cache lookup failed for type %u", typeOid);
|
||||
|
||||
typ = build_datatype(typeTup, typmod);
|
||||
|
||||
@ -1701,10 +1670,37 @@ build_datatype(HeapTuple typeTup, int32 typmod)
|
||||
Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
|
||||
PLpgSQL_type *typ;
|
||||
|
||||
if (!typeStruct->typisdefined)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("type \"%s\" is only a shell",
|
||||
NameStr(typeStruct->typname))));
|
||||
|
||||
typ = (PLpgSQL_type *) malloc(sizeof(PLpgSQL_type));
|
||||
|
||||
typ->typname = strdup(NameStr(typeStruct->typname));
|
||||
typ->typoid = HeapTupleGetOid(typeTup);
|
||||
switch (typeStruct->typtype)
|
||||
{
|
||||
case 'b': /* base type */
|
||||
case 'd': /* domain */
|
||||
typ->ttype = PLPGSQL_TTYPE_SCALAR;
|
||||
break;
|
||||
case 'c': /* composite, ie, rowtype */
|
||||
Assert(OidIsValid(typeStruct->typrelid));
|
||||
typ->ttype = PLPGSQL_TTYPE_ROW;
|
||||
break;
|
||||
case 'p': /* pseudo */
|
||||
if (typ->typoid == RECORDOID)
|
||||
typ->ttype = PLPGSQL_TTYPE_REC;
|
||||
else
|
||||
typ->ttype = PLPGSQL_TTYPE_PSEUDO;
|
||||
break;
|
||||
default:
|
||||
elog(ERROR, "unrecognized typtype: %d",
|
||||
(int) typeStruct->typtype);
|
||||
break;
|
||||
}
|
||||
typ->typlen = typeStruct->typlen;
|
||||
typ->typbyval = typeStruct->typbyval;
|
||||
typ->typrelid = typeStruct->typrelid;
|
||||
|
@ -3,7 +3,7 @@
|
||||
* procedural language
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.45 2004/03/19 18:58:07 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.46 2004/06/03 22:56:43 tgl Exp $
|
||||
*
|
||||
* This software is copyrighted by Jan Wieck - Hamburg.
|
||||
*
|
||||
@ -58,8 +58,7 @@ enum
|
||||
PLPGSQL_NSTYPE_LABEL,
|
||||
PLPGSQL_NSTYPE_VAR,
|
||||
PLPGSQL_NSTYPE_ROW,
|
||||
PLPGSQL_NSTYPE_REC,
|
||||
PLPGSQL_NSTYPE_RECFIELD
|
||||
PLPGSQL_NSTYPE_REC
|
||||
};
|
||||
|
||||
/* ----------
|
||||
@ -77,6 +76,18 @@ enum
|
||||
PLPGSQL_DTYPE_TRIGARG
|
||||
};
|
||||
|
||||
/* ----------
|
||||
* Variants distinguished in PLpgSQL_type structs
|
||||
* ----------
|
||||
*/
|
||||
enum
|
||||
{
|
||||
PLPGSQL_TTYPE_SCALAR, /* scalar types and domains */
|
||||
PLPGSQL_TTYPE_ROW, /* composite types */
|
||||
PLPGSQL_TTYPE_REC, /* RECORD pseudotype */
|
||||
PLPGSQL_TTYPE_PSEUDO /* other pseudotypes */
|
||||
};
|
||||
|
||||
/* ----------
|
||||
* Execution tree node types
|
||||
* ----------
|
||||
@ -142,9 +153,10 @@ typedef struct
|
||||
|
||||
|
||||
typedef struct
|
||||
{ /* Postgres data type */
|
||||
char *typname;
|
||||
{ /* Postgres data type */
|
||||
char *typname; /* (simple) name of the type */
|
||||
Oid typoid; /* OID of the data type */
|
||||
int ttype; /* PLPGSQL_TTYPE_ code */
|
||||
int16 typlen; /* stuff copied from its pg_type entry */
|
||||
bool typbyval;
|
||||
Oid typrelid;
|
||||
@ -165,6 +177,17 @@ typedef struct
|
||||
int dno;
|
||||
} PLpgSQL_datum;
|
||||
|
||||
/*
|
||||
* The variants PLpgSQL_var, PLpgSQL_row, and PLpgSQL_rec share these
|
||||
* fields
|
||||
*/
|
||||
typedef struct
|
||||
{ /* Scalar or composite variable */
|
||||
int dtype;
|
||||
int dno;
|
||||
char *refname;
|
||||
int lineno;
|
||||
} PLpgSQL_variable;
|
||||
|
||||
typedef struct PLpgSQL_expr
|
||||
{ /* SQL Query to plan and execute */
|
||||
@ -186,7 +209,7 @@ typedef struct PLpgSQL_expr
|
||||
|
||||
|
||||
typedef struct
|
||||
{ /* Local variable */
|
||||
{ /* Scalar variable */
|
||||
int dtype;
|
||||
int varno;
|
||||
char *refname;
|
||||
@ -206,11 +229,12 @@ typedef struct
|
||||
|
||||
|
||||
typedef struct
|
||||
{ /* Rowtype */
|
||||
{ /* Row variable */
|
||||
int dtype;
|
||||
int rowno;
|
||||
char *refname;
|
||||
int lineno;
|
||||
|
||||
TupleDesc rowtupdesc;
|
||||
|
||||
/*
|
||||
@ -227,7 +251,7 @@ typedef struct
|
||||
|
||||
|
||||
typedef struct
|
||||
{ /* Record of non-fixed structure */
|
||||
{ /* Record variable (non-fixed structure) */
|
||||
int dtype;
|
||||
int recno;
|
||||
char *refname;
|
||||
@ -630,9 +654,12 @@ extern int plpgsql_parse_dblwordtype(char *word);
|
||||
extern int plpgsql_parse_tripwordtype(char *word);
|
||||
extern int plpgsql_parse_wordrowtype(char *word);
|
||||
extern int plpgsql_parse_dblwordrowtype(char *word);
|
||||
extern PLpgSQL_type *plpgsql_parse_datatype(char *string);
|
||||
extern PLpgSQL_row *plpgsql_build_rowtype(Oid classOid);
|
||||
extern void plpgsql_adddatum(PLpgSQL_datum * new);
|
||||
extern PLpgSQL_type *plpgsql_parse_datatype(const char *string);
|
||||
extern PLpgSQL_type *plpgsql_build_datatype(Oid typeOid, int32 typmod);
|
||||
extern PLpgSQL_variable *plpgsql_build_variable(char *refname, int lineno,
|
||||
PLpgSQL_type *dtype,
|
||||
bool add2namespace);
|
||||
extern void plpgsql_adddatum(PLpgSQL_datum *new);
|
||||
extern int plpgsql_add_initdatums(int **varnos);
|
||||
extern void plpgsql_HashTableInit(void);
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
* procedural language
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/pl/plpgsql/src/scan.l,v 1.34 2004/03/21 22:29:11 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/pl/plpgsql/src/scan.l,v 1.35 2004/06/03 22:56:43 tgl Exp $
|
||||
*
|
||||
* This software is copyrighted by Jan Wieck - Hamburg.
|
||||
*
|
||||
@ -167,7 +167,6 @@ null { return K_NULL; }
|
||||
open { return K_OPEN; }
|
||||
perform { return K_PERFORM; }
|
||||
raise { return K_RAISE; }
|
||||
record { return K_RECORD; }
|
||||
rename { return K_RENAME; }
|
||||
result_oid { return K_RESULT_OID; }
|
||||
return { return K_RETURN; }
|
||||
|
Loading…
x
Reference in New Issue
Block a user