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
|
* procedural language
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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.
|
* This software is copyrighted by Jan Wieck - Hamburg.
|
||||||
*
|
*
|
||||||
@ -83,7 +83,8 @@ static void check_assignable(PLpgSQL_datum *datum);
|
|||||||
int *initvarnos;
|
int *initvarnos;
|
||||||
} declhdr;
|
} declhdr;
|
||||||
PLpgSQL_type *dtype;
|
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_var *var;
|
||||||
PLpgSQL_row *row;
|
PLpgSQL_row *row;
|
||||||
PLpgSQL_rec *rec;
|
PLpgSQL_rec *rec;
|
||||||
@ -100,7 +101,7 @@ static void check_assignable(PLpgSQL_datum *datum);
|
|||||||
%type <ival> decl_const decl_notnull
|
%type <ival> decl_const decl_notnull
|
||||||
%type <expr> decl_defval decl_cursor_query
|
%type <expr> decl_defval decl_cursor_query
|
||||||
%type <dtype> decl_datatype
|
%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 <nsitem> decl_aliasitem
|
||||||
%type <str> decl_stmts decl_stmt
|
%type <str> decl_stmts decl_stmt
|
||||||
|
|
||||||
@ -109,7 +110,8 @@ static void check_assignable(PLpgSQL_datum *datum);
|
|||||||
%type <expr> opt_exitcond
|
%type <expr> opt_exitcond
|
||||||
|
|
||||||
%type <ival> assign_var cursor_variable
|
%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 <varname> fori_varname
|
||||||
%type <forilow> fori_lower
|
%type <forilow> fori_lower
|
||||||
%type <rec> fors_target
|
%type <rec> fors_target
|
||||||
@ -174,7 +176,6 @@ static void check_assignable(PLpgSQL_datum *datum);
|
|||||||
%token K_PERFORM
|
%token K_PERFORM
|
||||||
%token K_ROW_COUNT
|
%token K_ROW_COUNT
|
||||||
%token K_RAISE
|
%token K_RAISE
|
||||||
%token K_RECORD
|
|
||||||
%token K_RENAME
|
%token K_RENAME
|
||||||
%token K_RESULT_OID
|
%token K_RESULT_OID
|
||||||
%token K_RETURN
|
%token K_RETURN
|
||||||
@ -195,7 +196,7 @@ static void check_assignable(PLpgSQL_datum *datum);
|
|||||||
%token T_TRIGGER
|
%token T_TRIGGER
|
||||||
%token T_STRING
|
%token T_STRING
|
||||||
%token T_NUMBER
|
%token T_NUMBER
|
||||||
%token T_VARIABLE /* a VAR, RECFIELD, or TRIGARG */
|
%token T_SCALAR /* a VAR, RECFIELD, or TRIGARG */
|
||||||
%token T_ROW
|
%token T_ROW
|
||||||
%token T_RECORD
|
%token T_RECORD
|
||||||
%token T_DTYPE
|
%token T_DTYPE
|
||||||
@ -306,82 +307,38 @@ decl_stmt : '<' '<' opt_lblname '>' '>'
|
|||||||
|
|
||||||
decl_statement : decl_varname decl_const decl_datatype decl_notnull decl_defval
|
decl_statement : decl_varname decl_const decl_datatype decl_notnull decl_defval
|
||||||
{
|
{
|
||||||
if (!OidIsValid($3->typrelid))
|
PLpgSQL_variable *var;
|
||||||
{
|
|
||||||
/* 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);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* 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;
|
|
||||||
|
|
||||||
|
var = plpgsql_build_variable($1.name, $1.lineno,
|
||||||
|
$3, true);
|
||||||
if ($2)
|
if ($2)
|
||||||
|
{
|
||||||
|
if (var->dtype == PLPGSQL_DTYPE_VAR)
|
||||||
|
((PLpgSQL_var *) var)->isconst = $2;
|
||||||
|
else
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||||
errmsg("rowtype variable cannot be CONSTANT")));
|
errmsg("row or record variable cannot be CONSTANT")));
|
||||||
|
}
|
||||||
if ($4)
|
if ($4)
|
||||||
|
{
|
||||||
|
if (var->dtype == PLPGSQL_DTYPE_VAR)
|
||||||
|
((PLpgSQL_var *) var)->notnull = $4;
|
||||||
|
else
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||||
errmsg("rowtype variable cannot be NOT NULL")));
|
errmsg("row or record variable cannot be NOT NULL")));
|
||||||
|
}
|
||||||
if ($5 != NULL)
|
if ($5 != NULL)
|
||||||
|
{
|
||||||
|
if (var->dtype == PLPGSQL_DTYPE_VAR)
|
||||||
|
((PLpgSQL_var *) var)->default_val = $5;
|
||||||
|
else
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||||
errmsg("default value for rowtype variable is not supported")));
|
errmsg("default value for row or record variable is not supported")));
|
||||||
|
|
||||||
plpgsql_adddatum((PLpgSQL_datum *)row);
|
|
||||||
plpgsql_ns_additem(PLPGSQL_NSTYPE_ROW,
|
|
||||||
row->rowno,
|
|
||||||
$1.name);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
| 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 ';'
|
| decl_varname K_ALIAS K_FOR decl_aliasitem ';'
|
||||||
{
|
{
|
||||||
plpgsql_ns_additem($4->itemtype,
|
plpgsql_ns_additem($4->itemtype,
|
||||||
@ -404,16 +361,15 @@ decl_statement : decl_varname decl_const decl_datatype decl_notnull decl_defval
|
|||||||
/* pop local namespace for cursor args */
|
/* pop local namespace for cursor args */
|
||||||
plpgsql_ns_pop();
|
plpgsql_ns_pop();
|
||||||
|
|
||||||
new = malloc(sizeof(PLpgSQL_var));
|
new = (PLpgSQL_var *)
|
||||||
memset(new, 0, sizeof(PLpgSQL_var));
|
plpgsql_build_variable($1.name, $1.lineno,
|
||||||
|
plpgsql_build_datatype(REFCURSOROID,
|
||||||
|
-1),
|
||||||
|
true);
|
||||||
|
|
||||||
curname_def = malloc(sizeof(PLpgSQL_expr));
|
curname_def = malloc(sizeof(PLpgSQL_expr));
|
||||||
memset(curname_def, 0, 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;
|
curname_def->dtype = PLPGSQL_DTYPE_EXPR;
|
||||||
strcpy(buf, "SELECT '");
|
strcpy(buf, "SELECT '");
|
||||||
cp1 = new->refname;
|
cp1 = new->refname;
|
||||||
@ -428,17 +384,11 @@ decl_statement : decl_varname decl_const decl_datatype decl_notnull decl_defval
|
|||||||
curname_def->query = strdup(buf);
|
curname_def->query = strdup(buf);
|
||||||
new->default_val = curname_def;
|
new->default_val = curname_def;
|
||||||
|
|
||||||
new->datatype = plpgsql_parse_datatype("refcursor");
|
|
||||||
|
|
||||||
new->cursor_explicit_expr = $6;
|
new->cursor_explicit_expr = $6;
|
||||||
if ($4 == NULL)
|
if ($4 == NULL)
|
||||||
new->cursor_explicit_argrow = -1;
|
new->cursor_explicit_argrow = -1;
|
||||||
else
|
else
|
||||||
new->cursor_explicit_argrow = $4->rowno;
|
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->nfields = 1;
|
||||||
|
|
||||||
new->fieldnames[0] = $1->refname;
|
new->fieldnames[0] = $1->refname;
|
||||||
new->varnos[0] = $1->varno;
|
new->varnos[0] = $1->dno;
|
||||||
|
|
||||||
$$ = new;
|
$$ = new;
|
||||||
}
|
}
|
||||||
@ -513,7 +463,7 @@ decl_cursor_arglist : decl_cursor_arg
|
|||||||
int i = $1->nfields++;
|
int i = $1->nfields++;
|
||||||
|
|
||||||
$1->fieldnames[i] = $3->refname;
|
$1->fieldnames[i] = $3->refname;
|
||||||
$1->varnos[i] = $3->varno;
|
$1->varnos[i] = $3->dno;
|
||||||
|
|
||||||
$$ = $1;
|
$$ = $1;
|
||||||
}
|
}
|
||||||
@ -521,24 +471,8 @@ decl_cursor_arglist : decl_cursor_arg
|
|||||||
|
|
||||||
decl_cursor_arg : decl_varname decl_datatype
|
decl_cursor_arg : decl_varname decl_datatype
|
||||||
{
|
{
|
||||||
PLpgSQL_var *new;
|
$$ = plpgsql_build_variable($1.name, $1.lineno,
|
||||||
|
$2, true);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -573,12 +507,6 @@ decl_aliasitem : T_WORD
|
|||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
decl_rowtype : T_ROW
|
|
||||||
{
|
|
||||||
$$ = yylval.row;
|
|
||||||
}
|
|
||||||
;
|
|
||||||
|
|
||||||
decl_varname : T_WORD
|
decl_varname : T_WORD
|
||||||
{
|
{
|
||||||
char *name;
|
char *name;
|
||||||
@ -803,18 +731,18 @@ getdiag_item : K_ROW_COUNT
|
|||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
getdiag_target : T_VARIABLE
|
getdiag_target : T_SCALAR
|
||||||
{
|
{
|
||||||
check_assignable(yylval.variable);
|
check_assignable(yylval.scalar);
|
||||||
$$ = yylval.variable->dno;
|
$$ = yylval.scalar->dno;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
assign_var : T_VARIABLE
|
assign_var : T_SCALAR
|
||||||
{
|
{
|
||||||
check_assignable(yylval.variable);
|
check_assignable(yylval.scalar);
|
||||||
$$ = yylval.variable->dno;
|
$$ = yylval.scalar->dno;
|
||||||
}
|
}
|
||||||
| assign_var '[' expr_until_rightbracket
|
| assign_var '[' expr_until_rightbracket
|
||||||
{
|
{
|
||||||
@ -970,21 +898,11 @@ fori_var : fori_varname
|
|||||||
{
|
{
|
||||||
PLpgSQL_var *new;
|
PLpgSQL_var *new;
|
||||||
|
|
||||||
new = malloc(sizeof(PLpgSQL_var));
|
new = (PLpgSQL_var *)
|
||||||
memset(new, 0, sizeof(PLpgSQL_var));
|
plpgsql_build_variable($1.name, $1.lineno,
|
||||||
|
plpgsql_build_datatype(INT4OID,
|
||||||
new->dtype = PLPGSQL_DTYPE_VAR;
|
-1),
|
||||||
new->refname = $1.name;
|
true);
|
||||||
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);
|
|
||||||
|
|
||||||
plpgsql_add_initdatums(NULL);
|
plpgsql_add_initdatums(NULL);
|
||||||
|
|
||||||
@ -992,7 +910,7 @@ fori_var : fori_varname
|
|||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
fori_varname : T_VARIABLE
|
fori_varname : T_SCALAR
|
||||||
{
|
{
|
||||||
char *name;
|
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");
|
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();
|
plpgsql_error_lineno = plpgsql_scanner_lineno();
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
||||||
errmsg("\"%s\" must be of type cursor or refcursor",
|
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");
|
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();
|
plpgsql_error_lineno = plpgsql_scanner_lineno();
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
(errcode(ERRCODE_DATATYPE_MISMATCH),
|
||||||
errmsg("\"%s\" must be of type refcursor",
|
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, " ");
|
plpgsql_dstring_append(&ds, " ");
|
||||||
switch (tok)
|
switch (tok)
|
||||||
{
|
{
|
||||||
case T_VARIABLE:
|
case T_SCALAR:
|
||||||
params[nparams] = yylval.variable->dno;
|
params[nparams] = yylval.scalar->dno;
|
||||||
snprintf(buf, sizeof(buf), " $%d ", ++nparams);
|
snprintf(buf, sizeof(buf), " $%d ", ++nparams);
|
||||||
plpgsql_dstring_append(&ds, buf);
|
plpgsql_dstring_append(&ds, buf);
|
||||||
break;
|
break;
|
||||||
@ -1821,25 +1739,25 @@ make_select_stmt(void)
|
|||||||
have_into = 1;
|
have_into = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_VARIABLE:
|
case T_SCALAR:
|
||||||
{
|
{
|
||||||
int nfields = 1;
|
int nfields = 1;
|
||||||
char *fieldnames[1024];
|
char *fieldnames[1024];
|
||||||
int varnos[1024];
|
int varnos[1024];
|
||||||
|
|
||||||
check_assignable(yylval.variable);
|
check_assignable(yylval.scalar);
|
||||||
fieldnames[0] = strdup(yytext);
|
fieldnames[0] = strdup(yytext);
|
||||||
varnos[0] = yylval.variable->dno;
|
varnos[0] = yylval.scalar->dno;
|
||||||
|
|
||||||
while ((tok = yylex()) == ',')
|
while ((tok = yylex()) == ',')
|
||||||
{
|
{
|
||||||
tok = yylex();
|
tok = yylex();
|
||||||
switch(tok)
|
switch(tok)
|
||||||
{
|
{
|
||||||
case T_VARIABLE:
|
case T_SCALAR:
|
||||||
check_assignable(yylval.variable);
|
check_assignable(yylval.scalar);
|
||||||
fieldnames[nfields] = strdup(yytext);
|
fieldnames[nfields] = strdup(yytext);
|
||||||
varnos[nfields++] = yylval.variable->dno;
|
varnos[nfields++] = yylval.scalar->dno;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -1885,8 +1803,8 @@ make_select_stmt(void)
|
|||||||
plpgsql_dstring_append(&ds, " ");
|
plpgsql_dstring_append(&ds, " ");
|
||||||
switch (tok)
|
switch (tok)
|
||||||
{
|
{
|
||||||
case T_VARIABLE:
|
case T_SCALAR:
|
||||||
params[nparams] = yylval.variable->dno;
|
params[nparams] = yylval.scalar->dno;
|
||||||
snprintf(buf, sizeof(buf), " $%d ", ++nparams);
|
snprintf(buf, sizeof(buf), " $%d ", ++nparams);
|
||||||
plpgsql_dstring_append(&ds, buf);
|
plpgsql_dstring_append(&ds, buf);
|
||||||
break;
|
break;
|
||||||
@ -1968,25 +1886,25 @@ make_fetch_stmt(void)
|
|||||||
rec = yylval.rec;
|
rec = yylval.rec;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_VARIABLE:
|
case T_SCALAR:
|
||||||
{
|
{
|
||||||
int nfields = 1;
|
int nfields = 1;
|
||||||
char *fieldnames[1024];
|
char *fieldnames[1024];
|
||||||
int varnos[1024];
|
int varnos[1024];
|
||||||
|
|
||||||
check_assignable(yylval.variable);
|
check_assignable(yylval.scalar);
|
||||||
fieldnames[0] = strdup(yytext);
|
fieldnames[0] = strdup(yytext);
|
||||||
varnos[0] = yylval.variable->dno;
|
varnos[0] = yylval.scalar->dno;
|
||||||
|
|
||||||
while ((tok = yylex()) == ',')
|
while ((tok = yylex()) == ',')
|
||||||
{
|
{
|
||||||
tok = yylex();
|
tok = yylex();
|
||||||
switch(tok)
|
switch(tok)
|
||||||
{
|
{
|
||||||
case T_VARIABLE:
|
case T_SCALAR:
|
||||||
check_assignable(yylval.variable);
|
check_assignable(yylval.scalar);
|
||||||
fieldnames[nfields] = strdup(yytext);
|
fieldnames[nfields] = strdup(yytext);
|
||||||
varnos[nfields++] = yylval.variable->dno;
|
varnos[nfields++] = yylval.scalar->dno;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
* procedural language
|
* procedural language
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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.
|
* This software is copyrighted by Jan Wieck - Hamburg.
|
||||||
*
|
*
|
||||||
@ -56,6 +56,7 @@
|
|||||||
#include "tcop/tcopprot.h"
|
#include "tcop/tcopprot.h"
|
||||||
#include "utils/array.h"
|
#include "utils/array.h"
|
||||||
#include "utils/builtins.h"
|
#include "utils/builtins.h"
|
||||||
|
#include "utils/lsyscache.h"
|
||||||
#include "utils/syscache.h"
|
#include "utils/syscache.h"
|
||||||
|
|
||||||
|
|
||||||
@ -105,6 +106,7 @@ static PLpgSQL_function *do_compile(FunctionCallInfo fcinfo,
|
|||||||
bool forValidator);
|
bool forValidator);
|
||||||
static void plpgsql_compile_error_callback(void *arg);
|
static void plpgsql_compile_error_callback(void *arg);
|
||||||
static char **fetchArgNames(HeapTuple procTup, int nargs);
|
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 PLpgSQL_type *build_datatype(HeapTuple typeTup, int32 typmod);
|
||||||
static void compute_function_hashkey(FunctionCallInfo fcinfo,
|
static void compute_function_hashkey(FunctionCallInfo fcinfo,
|
||||||
Form_pg_proc procStruct,
|
Form_pg_proc procStruct,
|
||||||
@ -249,8 +251,7 @@ do_compile(FunctionCallInfo fcinfo,
|
|||||||
char *proc_source;
|
char *proc_source;
|
||||||
HeapTuple typeTup;
|
HeapTuple typeTup;
|
||||||
Form_pg_type typeStruct;
|
Form_pg_type typeStruct;
|
||||||
PLpgSQL_var *var;
|
PLpgSQL_variable *var;
|
||||||
PLpgSQL_row *row;
|
|
||||||
PLpgSQL_rec *rec;
|
PLpgSQL_rec *rec;
|
||||||
int i;
|
int i;
|
||||||
int arg_varnos[FUNC_MAX_ARGS];
|
int arg_varnos[FUNC_MAX_ARGS];
|
||||||
@ -392,33 +393,9 @@ do_compile(FunctionCallInfo fcinfo,
|
|||||||
if (procStruct->prorettype == ANYARRAYOID ||
|
if (procStruct->prorettype == ANYARRAYOID ||
|
||||||
procStruct->prorettype == ANYELEMENTOID)
|
procStruct->prorettype == ANYELEMENTOID)
|
||||||
{
|
{
|
||||||
char buf[32];
|
(void) plpgsql_build_variable(strdup("$0"), 0,
|
||||||
|
build_datatype(typeTup, -1),
|
||||||
/* name for variable */
|
true);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ReleaseSysCache(typeTup);
|
ReleaseSysCache(typeTup);
|
||||||
@ -432,7 +409,8 @@ do_compile(FunctionCallInfo fcinfo,
|
|||||||
{
|
{
|
||||||
char buf[32];
|
char buf[32];
|
||||||
Oid argtypeid;
|
Oid argtypeid;
|
||||||
PLpgSQL_datum *argdatum;
|
PLpgSQL_type *argdtype;
|
||||||
|
PLpgSQL_variable *argvariable;
|
||||||
int argitemtype;
|
int argitemtype;
|
||||||
|
|
||||||
/* Create $n name for variable */
|
/* Create $n name for variable */
|
||||||
@ -444,70 +422,44 @@ do_compile(FunctionCallInfo fcinfo,
|
|||||||
* the hashkey, we can just use those results.
|
* the hashkey, we can just use those results.
|
||||||
*/
|
*/
|
||||||
argtypeid = hashkey->argtypes[i];
|
argtypeid = hashkey->argtypes[i];
|
||||||
|
argdtype = plpgsql_build_datatype(argtypeid, -1);
|
||||||
/*
|
|
||||||
* 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);
|
|
||||||
|
|
||||||
/* Disallow pseudotype argument */
|
/* Disallow pseudotype argument */
|
||||||
/* (note we already replaced ANYARRAY/ANYELEMENT) */
|
/* (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,
|
ereport(ERROR,
|
||||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||||
errmsg("plpgsql functions cannot take type %s",
|
errmsg("plpgsql functions cannot take type %s",
|
||||||
format_type_be(argtypeid))));
|
format_type_be(argtypeid))));
|
||||||
|
|
||||||
if (typeStruct->typrelid != InvalidOid)
|
/* Build variable and add to datum list */
|
||||||
{
|
argvariable = plpgsql_build_variable(strdup(buf), 0,
|
||||||
/*
|
argdtype, false);
|
||||||
* 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;
|
if (argvariable->dtype == PLPGSQL_DTYPE_VAR)
|
||||||
argitemtype = PLPGSQL_NSTYPE_ROW;
|
{
|
||||||
|
/* argument vars are forced to be CONSTANT (why?) */
|
||||||
|
((PLpgSQL_var *) argvariable)->isconst = true;
|
||||||
|
argitemtype = PLPGSQL_NSTYPE_VAR;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/*
|
Assert(argvariable->dtype == PLPGSQL_DTYPE_ROW);
|
||||||
* Normal parameters get a var node
|
argitemtype = PLPGSQL_NSTYPE_ROW;
|
||||||
*/
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add it to datum list, and remember datum number */
|
/* Remember datum number */
|
||||||
plpgsql_adddatum(argdatum);
|
arg_varnos[i] = argvariable->dno;
|
||||||
arg_varnos[i] = argdatum->dno;
|
|
||||||
|
|
||||||
/* Add to namespace under the $n name */
|
/* 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 there's a name for the argument, make an alias */
|
||||||
if (argnames && argnames[i] && argnames[i][0])
|
if (argnames && argnames[i] && argnames[i][0])
|
||||||
plpgsql_ns_additem(argitemtype, argdatum->dno,
|
plpgsql_ns_additem(argitemtype, argvariable->dno,
|
||||||
argnames[i]);
|
argnames[i]);
|
||||||
|
|
||||||
ReleaseSysCache(typeTup);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -552,128 +504,58 @@ do_compile(FunctionCallInfo fcinfo,
|
|||||||
/*
|
/*
|
||||||
* Add the variable tg_name
|
* Add the variable tg_name
|
||||||
*/
|
*/
|
||||||
var = malloc(sizeof(PLpgSQL_var));
|
var = plpgsql_build_variable(strdup("tg_name"), 0,
|
||||||
memset(var, 0, sizeof(PLpgSQL_var));
|
plpgsql_build_datatype(NAMEOID, -1),
|
||||||
|
true);
|
||||||
var->dtype = PLPGSQL_DTYPE_VAR;
|
function->tg_name_varno = var->dno;
|
||||||
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;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add the variable tg_when
|
* Add the variable tg_when
|
||||||
*/
|
*/
|
||||||
var = malloc(sizeof(PLpgSQL_var));
|
var = plpgsql_build_variable(strdup("tg_when"), 0,
|
||||||
memset(var, 0, sizeof(PLpgSQL_var));
|
plpgsql_build_datatype(TEXTOID, -1),
|
||||||
|
true);
|
||||||
var->dtype = PLPGSQL_DTYPE_VAR;
|
function->tg_when_varno = var->dno;
|
||||||
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;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add the variable tg_level
|
* Add the variable tg_level
|
||||||
*/
|
*/
|
||||||
var = malloc(sizeof(PLpgSQL_var));
|
var = plpgsql_build_variable(strdup("tg_level"), 0,
|
||||||
memset(var, 0, sizeof(PLpgSQL_var));
|
plpgsql_build_datatype(TEXTOID, -1),
|
||||||
|
true);
|
||||||
var->dtype = PLPGSQL_DTYPE_VAR;
|
function->tg_level_varno = var->dno;
|
||||||
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;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add the variable tg_op
|
* Add the variable tg_op
|
||||||
*/
|
*/
|
||||||
var = malloc(sizeof(PLpgSQL_var));
|
var = plpgsql_build_variable(strdup("tg_op"), 0,
|
||||||
memset(var, 0, sizeof(PLpgSQL_var));
|
plpgsql_build_datatype(TEXTOID, -1),
|
||||||
|
true);
|
||||||
var->dtype = PLPGSQL_DTYPE_VAR;
|
function->tg_op_varno = var->dno;
|
||||||
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;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add the variable tg_relid
|
* Add the variable tg_relid
|
||||||
*/
|
*/
|
||||||
var = malloc(sizeof(PLpgSQL_var));
|
var = plpgsql_build_variable(strdup("tg_relid"), 0,
|
||||||
memset(var, 0, sizeof(PLpgSQL_var));
|
plpgsql_build_datatype(OIDOID, -1),
|
||||||
|
true);
|
||||||
var->dtype = PLPGSQL_DTYPE_VAR;
|
function->tg_relid_varno = var->dno;
|
||||||
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;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add the variable tg_relname
|
* Add the variable tg_relname
|
||||||
*/
|
*/
|
||||||
var = malloc(sizeof(PLpgSQL_var));
|
var = plpgsql_build_variable(strdup("tg_relname"), 0,
|
||||||
memset(var, 0, sizeof(PLpgSQL_var));
|
plpgsql_build_datatype(NAMEOID, -1),
|
||||||
|
true);
|
||||||
var->dtype = PLPGSQL_DTYPE_VAR;
|
function->tg_relname_varno = var->dno;
|
||||||
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;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add the variable tg_nargs
|
* Add the variable tg_nargs
|
||||||
*/
|
*/
|
||||||
var = malloc(sizeof(PLpgSQL_var));
|
var = plpgsql_build_variable(strdup("tg_nargs"), 0,
|
||||||
memset(var, 0, sizeof(PLpgSQL_var));
|
plpgsql_build_datatype(INT4OID, -1),
|
||||||
|
true);
|
||||||
var->dtype = PLPGSQL_DTYPE_VAR;
|
function->tg_nargs_varno = var->dno;
|
||||||
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;
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -685,20 +567,10 @@ do_compile(FunctionCallInfo fcinfo,
|
|||||||
/*
|
/*
|
||||||
* Create the magic FOUND variable.
|
* Create the magic FOUND variable.
|
||||||
*/
|
*/
|
||||||
var = malloc(sizeof(PLpgSQL_var));
|
var = plpgsql_build_variable(strdup("found"), 0,
|
||||||
memset(var, 0, sizeof(PLpgSQL_var));
|
plpgsql_build_datatype(BOOLOID, -1),
|
||||||
|
true);
|
||||||
var->dtype = PLPGSQL_DTYPE_VAR;
|
function->found_varno = var->dno;
|
||||||
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;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Forget about the above created variables
|
* Forget about the above created variables
|
||||||
@ -848,11 +720,11 @@ plpgsql_parse_word(char *word)
|
|||||||
trigarg->argnum = plpgsql_read_expression(']', "]");
|
trigarg->argnum = plpgsql_read_expression(']', "]");
|
||||||
|
|
||||||
plpgsql_adddatum((PLpgSQL_datum *) trigarg);
|
plpgsql_adddatum((PLpgSQL_datum *) trigarg);
|
||||||
plpgsql_yylval.variable = (PLpgSQL_datum *) trigarg;
|
plpgsql_yylval.scalar = (PLpgSQL_datum *) trigarg;
|
||||||
|
|
||||||
plpgsql_SpaceScanned = save_spacescanned;
|
plpgsql_SpaceScanned = save_spacescanned;
|
||||||
pfree(cp[0]);
|
pfree(cp[0]);
|
||||||
return T_VARIABLE;
|
return T_SCALAR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -869,8 +741,8 @@ plpgsql_parse_word(char *word)
|
|||||||
return T_LABEL;
|
return T_LABEL;
|
||||||
|
|
||||||
case PLPGSQL_NSTYPE_VAR:
|
case PLPGSQL_NSTYPE_VAR:
|
||||||
plpgsql_yylval.var = (PLpgSQL_var *) (plpgsql_Datums[nse->itemno]);
|
plpgsql_yylval.scalar = plpgsql_Datums[nse->itemno];
|
||||||
return T_VARIABLE;
|
return T_SCALAR;
|
||||||
|
|
||||||
case PLPGSQL_NSTYPE_REC:
|
case PLPGSQL_NSTYPE_REC:
|
||||||
plpgsql_yylval.rec = (PLpgSQL_rec *) (plpgsql_Datums[nse->itemno]);
|
plpgsql_yylval.rec = (PLpgSQL_rec *) (plpgsql_Datums[nse->itemno]);
|
||||||
@ -937,8 +809,8 @@ plpgsql_parse_dblword(char *word)
|
|||||||
switch (ns->itemtype)
|
switch (ns->itemtype)
|
||||||
{
|
{
|
||||||
case PLPGSQL_NSTYPE_VAR:
|
case PLPGSQL_NSTYPE_VAR:
|
||||||
plpgsql_yylval.var = (PLpgSQL_var *) (plpgsql_Datums[ns->itemno]);
|
plpgsql_yylval.scalar = plpgsql_Datums[ns->itemno];
|
||||||
return T_VARIABLE;
|
return T_SCALAR;
|
||||||
|
|
||||||
case PLPGSQL_NSTYPE_REC:
|
case PLPGSQL_NSTYPE_REC:
|
||||||
plpgsql_yylval.rec = (PLpgSQL_rec *) (plpgsql_Datums[ns->itemno]);
|
plpgsql_yylval.rec = (PLpgSQL_rec *) (plpgsql_Datums[ns->itemno]);
|
||||||
@ -968,11 +840,11 @@ plpgsql_parse_dblword(char *word)
|
|||||||
|
|
||||||
plpgsql_adddatum((PLpgSQL_datum *) new);
|
plpgsql_adddatum((PLpgSQL_datum *) new);
|
||||||
|
|
||||||
plpgsql_yylval.variable = (PLpgSQL_datum *) new;
|
plpgsql_yylval.scalar = (PLpgSQL_datum *) new;
|
||||||
|
|
||||||
pfree(cp[0]);
|
pfree(cp[0]);
|
||||||
pfree(cp[1]);
|
pfree(cp[1]);
|
||||||
return T_VARIABLE;
|
return T_SCALAR;
|
||||||
}
|
}
|
||||||
|
|
||||||
case PLPGSQL_NSTYPE_ROW:
|
case PLPGSQL_NSTYPE_ROW:
|
||||||
@ -990,10 +862,10 @@ plpgsql_parse_dblword(char *word)
|
|||||||
if (row->fieldnames[i] &&
|
if (row->fieldnames[i] &&
|
||||||
strcmp(row->fieldnames[i], cp[1]) == 0)
|
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[0]);
|
||||||
pfree(cp[1]);
|
pfree(cp[1]);
|
||||||
return T_VARIABLE;
|
return T_SCALAR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
@ -1074,12 +946,13 @@ plpgsql_parse_tripword(char *word)
|
|||||||
|
|
||||||
plpgsql_adddatum((PLpgSQL_datum *) new);
|
plpgsql_adddatum((PLpgSQL_datum *) new);
|
||||||
|
|
||||||
plpgsql_yylval.variable = (PLpgSQL_datum *) new;
|
plpgsql_yylval.scalar = (PLpgSQL_datum *) new;
|
||||||
|
|
||||||
pfree(cp[0]);
|
pfree(cp[0]);
|
||||||
pfree(cp[1]);
|
pfree(cp[1]);
|
||||||
pfree(cp[2]);
|
pfree(cp[2]);
|
||||||
return T_VARIABLE;
|
|
||||||
|
return T_SCALAR;
|
||||||
}
|
}
|
||||||
|
|
||||||
case PLPGSQL_NSTYPE_ROW:
|
case PLPGSQL_NSTYPE_ROW:
|
||||||
@ -1097,11 +970,13 @@ plpgsql_parse_tripword(char *word)
|
|||||||
if (row->fieldnames[i] &&
|
if (row->fieldnames[i] &&
|
||||||
strcmp(row->fieldnames[i], cp[2]) == 0)
|
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[0]);
|
||||||
pfree(cp[1]);
|
pfree(cp[1]);
|
||||||
pfree(cp[2]);
|
pfree(cp[2]);
|
||||||
return T_VARIABLE;
|
|
||||||
|
return T_SCALAR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ereport(ERROR,
|
ereport(ERROR,
|
||||||
@ -1161,6 +1036,8 @@ plpgsql_parse_wordtype(char *word)
|
|||||||
plpgsql_yylval.dtype = ((PLpgSQL_var *) (plpgsql_Datums[nse->itemno]))->datatype;
|
plpgsql_yylval.dtype = ((PLpgSQL_var *) (plpgsql_Datums[nse->itemno]))->datatype;
|
||||||
return T_DTYPE;
|
return T_DTYPE;
|
||||||
|
|
||||||
|
/* XXX perhaps allow REC here? */
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return T_ERROR;
|
return T_ERROR;
|
||||||
}
|
}
|
||||||
@ -1451,6 +1328,7 @@ plpgsql_parse_tripwordtype(char *word)
|
|||||||
ReleaseSysCache(typetup);
|
ReleaseSysCache(typetup);
|
||||||
pfree(cp[0]);
|
pfree(cp[0]);
|
||||||
pfree(cp[1]);
|
pfree(cp[1]);
|
||||||
|
|
||||||
return T_DTYPE;
|
return T_DTYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1482,21 +1360,20 @@ plpgsql_parse_wordrowtype(char *word)
|
|||||||
errmsg("relation \"%s\" does not exist", cp[0])));
|
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_yylval.dtype = plpgsql_build_datatype(get_rel_type_id(classOid),
|
||||||
|
-1);
|
||||||
plpgsql_adddatum((PLpgSQL_datum *) plpgsql_yylval.row);
|
|
||||||
|
|
||||||
pfree(cp[0]);
|
pfree(cp[0]);
|
||||||
pfree(cp[1]);
|
pfree(cp[1]);
|
||||||
|
|
||||||
return T_ROW;
|
return T_DTYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------
|
/* ----------
|
||||||
* plpgsql_parse_dblwordrowtype Scanner found word.word%ROWTYPE.
|
* 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
|
#define ROWTYPE_JUNK_LEN 8
|
||||||
@ -1527,22 +1404,120 @@ plpgsql_parse_dblwordrowtype(char *word)
|
|||||||
errmsg("relation \"%s\" does not exist", cp)));
|
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_yylval.dtype = plpgsql_build_datatype(get_rel_type_id(classOid),
|
||||||
|
-1);
|
||||||
plpgsql_adddatum((PLpgSQL_datum *) plpgsql_yylval.row);
|
|
||||||
|
|
||||||
pfree(cp);
|
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_variable *
|
||||||
plpgsql_build_rowtype(Oid classOid)
|
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;
|
PLpgSQL_row *row;
|
||||||
Relation rel;
|
Relation rel;
|
||||||
@ -1601,17 +1576,14 @@ plpgsql_build_rowtype(Oid classOid)
|
|||||||
if (!attrStruct->attisdropped)
|
if (!attrStruct->attisdropped)
|
||||||
{
|
{
|
||||||
const char *attname;
|
const char *attname;
|
||||||
HeapTuple typetup;
|
char *refname;
|
||||||
PLpgSQL_var *var;
|
PLpgSQL_variable *var;
|
||||||
|
|
||||||
attname = NameStr(attrStruct->attname);
|
attname = NameStr(attrStruct->attname);
|
||||||
|
refname = malloc(strlen(relname) + strlen(attname) + 2);
|
||||||
typetup = SearchSysCache(TYPEOID,
|
strcpy(refname, relname);
|
||||||
ObjectIdGetDatum(attrStruct->atttypid),
|
strcat(refname, ".");
|
||||||
0, 0, 0);
|
strcat(refname, attname);
|
||||||
if (!HeapTupleIsValid(typetup))
|
|
||||||
elog(ERROR, "cache lookup failed for type %u",
|
|
||||||
attrStruct->atttypid);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create the internal variable for the field
|
* 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
|
* the variables due to entering a block at execution time. Thus
|
||||||
* we ignore this information for now.
|
* we ignore this information for now.
|
||||||
*/
|
*/
|
||||||
var = malloc(sizeof(PLpgSQL_var));
|
var = plpgsql_build_variable(refname, 0,
|
||||||
MemSet(var, 0, sizeof(PLpgSQL_var));
|
plpgsql_build_datatype(attrStruct->atttypid,
|
||||||
var->dtype = PLPGSQL_DTYPE_VAR;
|
attrStruct->atttypmod),
|
||||||
var->refname = malloc(strlen(relname) + strlen(attname) + 2);
|
false);
|
||||||
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);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add the variable to the row.
|
* Add the variable to the row.
|
||||||
*/
|
*/
|
||||||
row->fieldnames[i] = strdup(attname);
|
row->fieldnames[i] = strdup(attname);
|
||||||
row->varnos[i] = var->varno;
|
row->varnos[i] = var->dno;
|
||||||
|
|
||||||
ReleaseSysCache(typetup);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1668,22 +1626,33 @@ plpgsql_build_rowtype(Oid classOid)
|
|||||||
* ----------
|
* ----------
|
||||||
*/
|
*/
|
||||||
PLpgSQL_type *
|
PLpgSQL_type *
|
||||||
plpgsql_parse_datatype(char *string)
|
plpgsql_parse_datatype(const char *string)
|
||||||
{
|
{
|
||||||
Oid type_id;
|
Oid type_id;
|
||||||
int32 typmod;
|
int32 typmod;
|
||||||
HeapTuple typeTup;
|
|
||||||
PLpgSQL_type *typ;
|
|
||||||
|
|
||||||
/* Let the main parser try to parse it under standard SQL rules */
|
/* Let the main parser try to parse it under standard SQL rules */
|
||||||
parseTypeString(string, &type_id, &typmod);
|
parseTypeString(string, &type_id, &typmod);
|
||||||
|
|
||||||
/* Okay, build a PLpgSQL_type data structure for it */
|
/* 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,
|
typeTup = SearchSysCache(TYPEOID,
|
||||||
ObjectIdGetDatum(type_id),
|
ObjectIdGetDatum(typeOid),
|
||||||
0, 0, 0);
|
0, 0, 0);
|
||||||
if (!HeapTupleIsValid(typeTup))
|
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);
|
typ = build_datatype(typeTup, typmod);
|
||||||
|
|
||||||
@ -1701,10 +1670,37 @@ build_datatype(HeapTuple typeTup, int32 typmod)
|
|||||||
Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
|
Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);
|
||||||
PLpgSQL_type *typ;
|
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 = (PLpgSQL_type *) malloc(sizeof(PLpgSQL_type));
|
||||||
|
|
||||||
typ->typname = strdup(NameStr(typeStruct->typname));
|
typ->typname = strdup(NameStr(typeStruct->typname));
|
||||||
typ->typoid = HeapTupleGetOid(typeTup);
|
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->typlen = typeStruct->typlen;
|
||||||
typ->typbyval = typeStruct->typbyval;
|
typ->typbyval = typeStruct->typbyval;
|
||||||
typ->typrelid = typeStruct->typrelid;
|
typ->typrelid = typeStruct->typrelid;
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
* procedural language
|
* procedural language
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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.
|
* This software is copyrighted by Jan Wieck - Hamburg.
|
||||||
*
|
*
|
||||||
@ -58,8 +58,7 @@ enum
|
|||||||
PLPGSQL_NSTYPE_LABEL,
|
PLPGSQL_NSTYPE_LABEL,
|
||||||
PLPGSQL_NSTYPE_VAR,
|
PLPGSQL_NSTYPE_VAR,
|
||||||
PLPGSQL_NSTYPE_ROW,
|
PLPGSQL_NSTYPE_ROW,
|
||||||
PLPGSQL_NSTYPE_REC,
|
PLPGSQL_NSTYPE_REC
|
||||||
PLPGSQL_NSTYPE_RECFIELD
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ----------
|
/* ----------
|
||||||
@ -77,6 +76,18 @@ enum
|
|||||||
PLPGSQL_DTYPE_TRIGARG
|
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
|
* Execution tree node types
|
||||||
* ----------
|
* ----------
|
||||||
@ -143,8 +154,9 @@ typedef struct
|
|||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{ /* Postgres data type */
|
{ /* Postgres data type */
|
||||||
char *typname;
|
char *typname; /* (simple) name of the type */
|
||||||
Oid typoid; /* OID of the data type */
|
Oid typoid; /* OID of the data type */
|
||||||
|
int ttype; /* PLPGSQL_TTYPE_ code */
|
||||||
int16 typlen; /* stuff copied from its pg_type entry */
|
int16 typlen; /* stuff copied from its pg_type entry */
|
||||||
bool typbyval;
|
bool typbyval;
|
||||||
Oid typrelid;
|
Oid typrelid;
|
||||||
@ -165,6 +177,17 @@ typedef struct
|
|||||||
int dno;
|
int dno;
|
||||||
} PLpgSQL_datum;
|
} 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
|
typedef struct PLpgSQL_expr
|
||||||
{ /* SQL Query to plan and execute */
|
{ /* SQL Query to plan and execute */
|
||||||
@ -186,7 +209,7 @@ typedef struct PLpgSQL_expr
|
|||||||
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{ /* Local variable */
|
{ /* Scalar variable */
|
||||||
int dtype;
|
int dtype;
|
||||||
int varno;
|
int varno;
|
||||||
char *refname;
|
char *refname;
|
||||||
@ -206,11 +229,12 @@ typedef struct
|
|||||||
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{ /* Rowtype */
|
{ /* Row variable */
|
||||||
int dtype;
|
int dtype;
|
||||||
int rowno;
|
int rowno;
|
||||||
char *refname;
|
char *refname;
|
||||||
int lineno;
|
int lineno;
|
||||||
|
|
||||||
TupleDesc rowtupdesc;
|
TupleDesc rowtupdesc;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -227,7 +251,7 @@ typedef struct
|
|||||||
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{ /* Record of non-fixed structure */
|
{ /* Record variable (non-fixed structure) */
|
||||||
int dtype;
|
int dtype;
|
||||||
int recno;
|
int recno;
|
||||||
char *refname;
|
char *refname;
|
||||||
@ -630,9 +654,12 @@ extern int plpgsql_parse_dblwordtype(char *word);
|
|||||||
extern int plpgsql_parse_tripwordtype(char *word);
|
extern int plpgsql_parse_tripwordtype(char *word);
|
||||||
extern int plpgsql_parse_wordrowtype(char *word);
|
extern int plpgsql_parse_wordrowtype(char *word);
|
||||||
extern int plpgsql_parse_dblwordrowtype(char *word);
|
extern int plpgsql_parse_dblwordrowtype(char *word);
|
||||||
extern PLpgSQL_type *plpgsql_parse_datatype(char *string);
|
extern PLpgSQL_type *plpgsql_parse_datatype(const char *string);
|
||||||
extern PLpgSQL_row *plpgsql_build_rowtype(Oid classOid);
|
extern PLpgSQL_type *plpgsql_build_datatype(Oid typeOid, int32 typmod);
|
||||||
extern void plpgsql_adddatum(PLpgSQL_datum * new);
|
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 int plpgsql_add_initdatums(int **varnos);
|
||||||
extern void plpgsql_HashTableInit(void);
|
extern void plpgsql_HashTableInit(void);
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
* procedural language
|
* procedural language
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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.
|
* This software is copyrighted by Jan Wieck - Hamburg.
|
||||||
*
|
*
|
||||||
@ -167,7 +167,6 @@ null { return K_NULL; }
|
|||||||
open { return K_OPEN; }
|
open { return K_OPEN; }
|
||||||
perform { return K_PERFORM; }
|
perform { return K_PERFORM; }
|
||||||
raise { return K_RAISE; }
|
raise { return K_RAISE; }
|
||||||
record { return K_RECORD; }
|
|
||||||
rename { return K_RENAME; }
|
rename { return K_RENAME; }
|
||||||
result_oid { return K_RESULT_OID; }
|
result_oid { return K_RESULT_OID; }
|
||||||
return { return K_RETURN; }
|
return { return K_RETURN; }
|
||||||
|
Loading…
x
Reference in New Issue
Block a user