aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2004-06-03 22:56:43 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2004-06-03 22:56:43 +0000
commit724c706400db2e885a5ecc654ce3a391fdb1c60d (patch)
tree3826eb08c275013ea7531c569cf711a150516d92 /src
parent2a22750c9693f24c4d179c6b1dedb1c4a7eadbd6 (diff)
downloadpostgresql-724c706400db2e885a5ecc654ce3a391fdb1c60d.tar.gz
postgresql-724c706400db2e885a5ecc654ce3a391fdb1c60d.zip
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.
Diffstat (limited to 'src')
-rw-r--r--src/pl/plpgsql/src/gram.y240
-rw-r--r--src/pl/plpgsql/src/pl_comp.c496
-rw-r--r--src/pl/plpgsql/src/plpgsql.h49
-rw-r--r--src/pl/plpgsql/src/scan.l3
4 files changed, 364 insertions, 424 deletions
diff --git a/src/pl/plpgsql/src/gram.y b/src/pl/plpgsql/src/gram.y
index fb46e1083b0..36427e2ceaa 100644
--- a/src/pl/plpgsql/src/gram.y
+++ b/src/pl/plpgsql/src/gram.y
@@ -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))
- {
- /* 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;
+ PLpgSQL_variable *var;
- 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
+ var = plpgsql_build_variable($1.name, $1.lineno,
+ $3, true);
+ if ($2)
{
- /* 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)->isconst = $2;
+ else
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("rowtype variable cannot be CONSTANT")));
- if ($4)
+ errmsg("row or record variable cannot be CONSTANT")));
+ }
+ if ($4)
+ {
+ if (var->dtype == PLPGSQL_DTYPE_VAR)
+ ((PLpgSQL_var *) var)->notnull = $4;
+ else
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("rowtype variable cannot be NOT NULL")));
- if ($5 != NULL)
+ 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 rowtype variable is not supported")));
-
- plpgsql_adddatum((PLpgSQL_datum *)row);
- plpgsql_ns_additem(PLPGSQL_NSTYPE_ROW,
- row->rowno,
- $1.name);
-
+ 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:
diff --git a/src/pl/plpgsql/src/pl_comp.c b/src/pl/plpgsql/src/pl_comp.c
index 8c930de9c23..1c0fe6f8cc4 100644
--- a/src/pl/plpgsql/src/pl_comp.c
+++ b/src/pl/plpgsql/src/pl_comp.c
@@ -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))));
+
+ /* Build variable and add to datum list */
+ argvariable = plpgsql_build_variable(strdup(buf), 0,
+ argdtype, false);
- if (typeStruct->typrelid != InvalidOid)
+ 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;
diff --git a/src/pl/plpgsql/src/plpgsql.h b/src/pl/plpgsql/src/plpgsql.h
index cb3c4c2944f..90ed37ada20 100644
--- a/src/pl/plpgsql/src/plpgsql.h
+++ b/src/pl/plpgsql/src/plpgsql.h
@@ -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
};
/* ----------
@@ -78,6 +77,18 @@ enum
};
/* ----------
+ * 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);
diff --git a/src/pl/plpgsql/src/scan.l b/src/pl/plpgsql/src/scan.l
index 077efe6671e..d369170cf3e 100644
--- a/src/pl/plpgsql/src/scan.l
+++ b/src/pl/plpgsql/src/scan.l
@@ -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; }