Restructure plpgsql's parsing of datatype declarations to unify the
authorTom Lane
Thu, 3 Jun 2004 22:56:43 +0000 (22:56 +0000)
committerTom Lane
Thu, 3 Jun 2004 22:56:43 +0000 (22:56 +0000)
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.

src/pl/plpgsql/src/gram.y
src/pl/plpgsql/src/pl_comp.c
src/pl/plpgsql/src/plpgsql.h
src/pl/plpgsql/src/scan.l

index fb46e1083b08822ccad2a0a95a6828e92f53eebe..36427e2ceaa3be5cb79612d625b33dfcb1c61bcf 100644 (file)
@@ -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    decl_const decl_notnull
 %type    decl_defval decl_cursor_query
 %type   decl_datatype
-%type         decl_rowtype decl_cursor_args decl_cursor_arglist
+%type         decl_cursor_args decl_cursor_arglist
 %type  decl_aliasitem
 %type         decl_stmts decl_stmt
 
@@ -109,7 +110,8 @@ static  void check_assignable(PLpgSQL_datum *datum);
 %type    opt_exitcond
 
 %type    assign_var cursor_variable
-%type         fori_var cursor_varptr decl_cursor_arg
+%type         fori_var cursor_varptr
+%type    decl_cursor_arg
 %type  fori_varname
 %type  fori_lower
 %type         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:
index 8c930de9c237ec01b3f4a015b455cc11a857e902..1c0fe6f8cc4a44c698f52654ad0141fefda40f1d 100644 (file)
@@ -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;
index cb3c4c2944feb013785fa1b72079e8fb2b4757f6..90ed37ada2003ccc27333a38b8deca68d1c63829 100644 (file)
@@ -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);
 
index 077efe6671e440dad4a4b2fadc07e65c75b27099..d369170cf3eafd9365e5bae212dcf1720785b68c 100644 (file)
@@ -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;          }