plpgsql: remove useless distinctions between record and row cases - Mailing list pgsql-hackers

From Tom Lane
Subject plpgsql: remove useless distinctions between record and row cases
Date
Msg-id 11787.1512713374@sss.pgh.pa.us
Whole thread Raw
List pgsql-hackers
I've been fooling around with rewriting plpgsql's composite-variable
handling, along the way to getting it to handle domains over composite.
I noticed that there's some really unnecessary complication in places
where it insists on separating "row" variables from "record" variables.
More usually, we'd handle that by using a generically-typed pointer and
then doing a node-type check where it's actually necessary to distinguish;
which it turns out is exactly one place, exec_move_row().  So attached is
a simple patch that eliminates the duplicative coding.

Barring objection, I'd like to push this shortly.

            regards, tom lane

diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c
index ec480cb..1959d6d 100644
--- a/src/pl/plpgsql/src/pl_exec.c
+++ b/src/pl/plpgsql/src/pl_exec.c
@@ -272,8 +272,7 @@ static ParamListInfo setup_unshared_param_list(PLpgSQL_execstate *estate,
                           PLpgSQL_expr *expr);
 static void plpgsql_param_fetch(ParamListInfo params, int paramid);
 static void exec_move_row(PLpgSQL_execstate *estate,
-              PLpgSQL_rec *rec,
-              PLpgSQL_row *row,
+              PLpgSQL_variable *target,
               HeapTuple tup, TupleDesc tupdesc);
 static HeapTuple make_tuple_from_row(PLpgSQL_execstate *estate,
                     PLpgSQL_row *row,
@@ -281,8 +280,7 @@ static HeapTuple make_tuple_from_row(PLpgSQL_execstate *estate,
 static HeapTuple get_tuple_from_datum(Datum value);
 static TupleDesc get_tupdesc_from_datum(Datum value);
 static void exec_move_row_from_datum(PLpgSQL_execstate *estate,
-                         PLpgSQL_rec *rec,
-                         PLpgSQL_row *row,
+                         PLpgSQL_variable *target,
                          Datum value);
 static char *convert_value_to_string(PLpgSQL_execstate *estate,
                         Datum value, Oid valtype);
@@ -425,13 +423,15 @@ plpgsql_exec_function(PLpgSQL_function *func, FunctionCallInfo fcinfo,
                     if (!fcinfo->argnull[i])
                     {
                         /* Assign row value from composite datum */
-                        exec_move_row_from_datum(&estate, NULL, row,
+                        exec_move_row_from_datum(&estate,
+                                                 (PLpgSQL_variable *) row,
                                                  fcinfo->arg[i]);
                     }
                     else
                     {
                         /* If arg is null, treat it as an empty row */
-                        exec_move_row(&estate, NULL, row, NULL, NULL);
+                        exec_move_row(&estate, (PLpgSQL_variable *) row,
+                                      NULL, NULL);
                     }
                     /* clean up after exec_move_row() */
                     exec_eval_cleanup(&estate);
@@ -2327,7 +2327,7 @@ exec_stmt_forc(PLpgSQL_execstate *estate, PLpgSQL_stmt_forc *stmt)
         set_args.sqlstmt = stmt->argquery;
         set_args.into = true;
         /* XXX historically this has not been STRICT */
-        set_args.row = (PLpgSQL_row *)
+        set_args.target = (PLpgSQL_variable *)
             (estate->datums[curvar->cursor_explicit_argrow]);

         if (exec_stmt_execsql(estate, &set_args) != PLPGSQL_RC_OK)
@@ -3755,8 +3755,7 @@ exec_stmt_execsql(PLpgSQL_execstate *estate,
     {
         SPITupleTable *tuptab = SPI_tuptable;
         uint64        n = SPI_processed;
-        PLpgSQL_rec *rec = NULL;
-        PLpgSQL_row *row = NULL;
+        PLpgSQL_variable *target;

         /* If the statement did not return a tuple table, complain */
         if (tuptab == NULL)
@@ -3764,13 +3763,8 @@ exec_stmt_execsql(PLpgSQL_execstate *estate,
                     (errcode(ERRCODE_SYNTAX_ERROR),
                      errmsg("INTO used with a command that cannot return data")));

-        /* Determine if we assign to a record or a row */
-        if (stmt->rec != NULL)
-            rec = (PLpgSQL_rec *) (estate->datums[stmt->rec->dno]);
-        else if (stmt->row != NULL)
-            row = (PLpgSQL_row *) (estate->datums[stmt->row->dno]);
-        else
-            elog(ERROR, "unsupported target");
+        /* Fetch target's datum entry */
+        target = (PLpgSQL_variable *) estate->datums[stmt->target->dno];

         /*
          * If SELECT ... INTO specified STRICT, and the query didn't find
@@ -3794,7 +3788,7 @@ exec_stmt_execsql(PLpgSQL_execstate *estate,
                          errdetail ? errdetail_internal("parameters: %s", errdetail) : 0));
             }
             /* set the target to NULL(s) */
-            exec_move_row(estate, rec, row, NULL, tuptab->tupdesc);
+            exec_move_row(estate, target, NULL, tuptab->tupdesc);
         }
         else
         {
@@ -3813,7 +3807,7 @@ exec_stmt_execsql(PLpgSQL_execstate *estate,
                          errdetail ? errdetail_internal("parameters: %s", errdetail) : 0));
             }
             /* Put the first result row into the target */
-            exec_move_row(estate, rec, row, tuptab->vals[0], tuptab->tupdesc);
+            exec_move_row(estate, target, tuptab->vals[0], tuptab->tupdesc);
         }

         /* Clean up */
@@ -3946,8 +3940,7 @@ exec_stmt_dynexecute(PLpgSQL_execstate *estate,
     {
         SPITupleTable *tuptab = SPI_tuptable;
         uint64        n = SPI_processed;
-        PLpgSQL_rec *rec = NULL;
-        PLpgSQL_row *row = NULL;
+        PLpgSQL_variable *target;

         /* If the statement did not return a tuple table, complain */
         if (tuptab == NULL)
@@ -3955,13 +3948,8 @@ exec_stmt_dynexecute(PLpgSQL_execstate *estate,
                     (errcode(ERRCODE_SYNTAX_ERROR),
                      errmsg("INTO used with a command that cannot return data")));

-        /* Determine if we assign to a record or a row */
-        if (stmt->rec != NULL)
-            rec = (PLpgSQL_rec *) (estate->datums[stmt->rec->dno]);
-        else if (stmt->row != NULL)
-            row = (PLpgSQL_row *) (estate->datums[stmt->row->dno]);
-        else
-            elog(ERROR, "unsupported target");
+        /* Fetch target's datum entry */
+        target = (PLpgSQL_variable *) estate->datums[stmt->target->dno];

         /*
          * If SELECT ... INTO specified STRICT, and the query didn't find
@@ -3985,7 +3973,7 @@ exec_stmt_dynexecute(PLpgSQL_execstate *estate,
                          errdetail ? errdetail_internal("parameters: %s", errdetail) : 0));
             }
             /* set the target to NULL(s) */
-            exec_move_row(estate, rec, row, NULL, tuptab->tupdesc);
+            exec_move_row(estate, target, NULL, tuptab->tupdesc);
         }
         else
         {
@@ -4005,7 +3993,7 @@ exec_stmt_dynexecute(PLpgSQL_execstate *estate,
             }

             /* Put the first result row into the target */
-            exec_move_row(estate, rec, row, tuptab->vals[0], tuptab->tupdesc);
+            exec_move_row(estate, target, tuptab->vals[0], tuptab->tupdesc);
         }
         /* clean up after exec_move_row() */
         exec_eval_cleanup(estate);
@@ -4163,7 +4151,7 @@ exec_stmt_open(PLpgSQL_execstate *estate, PLpgSQL_stmt_open *stmt)
             set_args.sqlstmt = stmt->argquery;
             set_args.into = true;
             /* XXX historically this has not been STRICT */
-            set_args.row = (PLpgSQL_row *)
+            set_args.target = (PLpgSQL_variable *)
                 (estate->datums[curvar->cursor_explicit_argrow]);

             if (exec_stmt_execsql(estate, &set_args) != PLPGSQL_RC_OK)
@@ -4221,8 +4209,6 @@ static int
 exec_stmt_fetch(PLpgSQL_execstate *estate, PLpgSQL_stmt_fetch *stmt)
 {
     PLpgSQL_var *curvar;
-    PLpgSQL_rec *rec = NULL;
-    PLpgSQL_row *row = NULL;
     long        how_many = stmt->how_many;
     SPITupleTable *tuptab;
     Portal        portal;
@@ -4269,16 +4255,7 @@ exec_stmt_fetch(PLpgSQL_execstate *estate, PLpgSQL_stmt_fetch *stmt)

     if (!stmt->is_move)
     {
-        /* ----------
-         * Determine if we fetch into a record or a row
-         * ----------
-         */
-        if (stmt->rec != NULL)
-            rec = (PLpgSQL_rec *) (estate->datums[stmt->rec->dno]);
-        else if (stmt->row != NULL)
-            row = (PLpgSQL_row *) (estate->datums[stmt->row->dno]);
-        else
-            elog(ERROR, "unsupported target");
+        PLpgSQL_variable *target;

         /* ----------
          * Fetch 1 tuple from the cursor
@@ -4292,10 +4269,11 @@ exec_stmt_fetch(PLpgSQL_execstate *estate, PLpgSQL_stmt_fetch *stmt)
          * Set the target appropriately.
          * ----------
          */
+        target = (PLpgSQL_variable *) estate->datums[stmt->target->dno];
         if (n == 0)
-            exec_move_row(estate, rec, row, NULL, tuptab->tupdesc);
+            exec_move_row(estate, target, NULL, tuptab->tupdesc);
         else
-            exec_move_row(estate, rec, row, tuptab->vals[0], tuptab->tupdesc);
+            exec_move_row(estate, target, tuptab->vals[0], tuptab->tupdesc);

         exec_eval_cleanup(estate);
         SPI_freetuptable(tuptab);
@@ -4514,7 +4492,8 @@ exec_assign_value(PLpgSQL_execstate *estate,
                 if (isNull)
                 {
                     /* If source is null, just assign nulls to the row */
-                    exec_move_row(estate, NULL, row, NULL, NULL);
+                    exec_move_row(estate, (PLpgSQL_variable *) row,
+                                  NULL, NULL);
                 }
                 else
                 {
@@ -4523,7 +4502,8 @@ exec_assign_value(PLpgSQL_execstate *estate,
                         ereport(ERROR,
                                 (errcode(ERRCODE_DATATYPE_MISMATCH),
                                  errmsg("cannot assign non-composite value to a row variable")));
-                    exec_move_row_from_datum(estate, NULL, row, value);
+                    exec_move_row_from_datum(estate, (PLpgSQL_variable *) row,
+                                             value);
                 }
                 break;
             }
@@ -4538,7 +4518,8 @@ exec_assign_value(PLpgSQL_execstate *estate,
                 if (isNull)
                 {
                     /* If source is null, just assign nulls to the record */
-                    exec_move_row(estate, rec, NULL, NULL, NULL);
+                    exec_move_row(estate, (PLpgSQL_variable *) rec,
+                                  NULL, NULL);
                 }
                 else
                 {
@@ -4547,7 +4528,8 @@ exec_assign_value(PLpgSQL_execstate *estate,
                         ereport(ERROR,
                                 (errcode(ERRCODE_DATATYPE_MISMATCH),
                                  errmsg("cannot assign non-composite value to a record variable")));
-                    exec_move_row_from_datum(estate, rec, NULL, value);
+                    exec_move_row_from_datum(estate, (PLpgSQL_variable *) rec,
+                                             value);
                 }
                 break;
             }
@@ -5341,22 +5323,14 @@ static int
 exec_for_query(PLpgSQL_execstate *estate, PLpgSQL_stmt_forq *stmt,
                Portal portal, bool prefetch_ok)
 {
-    PLpgSQL_rec *rec = NULL;
-    PLpgSQL_row *row = NULL;
+    PLpgSQL_variable *var;
     SPITupleTable *tuptab;
     bool        found = false;
     int            rc = PLPGSQL_RC_OK;
     uint64        n;

-    /*
-     * Determine if we assign to a record or a row
-     */
-    if (stmt->rec != NULL)
-        rec = (PLpgSQL_rec *) (estate->datums[stmt->rec->dno]);
-    else if (stmt->row != NULL)
-        row = (PLpgSQL_row *) (estate->datums[stmt->row->dno]);
-    else
-        elog(ERROR, "unsupported target");
+    /* Fetch loop variable's datum entry */
+    var = (PLpgSQL_variable *) estate->datums[stmt->var->dno];

     /*
      * Make sure the portal doesn't get closed by the user statements we
@@ -5379,7 +5353,7 @@ exec_for_query(PLpgSQL_execstate *estate, PLpgSQL_stmt_forq *stmt,
      */
     if (n == 0)
     {
-        exec_move_row(estate, rec, row, NULL, tuptab->tupdesc);
+        exec_move_row(estate, var, NULL, tuptab->tupdesc);
         exec_eval_cleanup(estate);
     }
     else
@@ -5397,7 +5371,7 @@ exec_for_query(PLpgSQL_execstate *estate, PLpgSQL_stmt_forq *stmt,
             /*
              * Assign the tuple to the target
              */
-            exec_move_row(estate, rec, row, tuptab->vals[i], tuptab->tupdesc);
+            exec_move_row(estate, var, tuptab->vals[i], tuptab->tupdesc);
             exec_eval_cleanup(estate);

             /*
@@ -5949,16 +5923,17 @@ plpgsql_param_fetch(ParamListInfo params, int paramid)
  */
 static void
 exec_move_row(PLpgSQL_execstate *estate,
-              PLpgSQL_rec *rec,
-              PLpgSQL_row *row,
+              PLpgSQL_variable *target,
               HeapTuple tup, TupleDesc tupdesc)
 {
     /*
      * Record is simple - just copy the tuple and its descriptor into the
      * record variable
      */
-    if (rec != NULL)
+    if (target->dtype == PLPGSQL_DTYPE_REC)
     {
+        PLpgSQL_rec *rec = (PLpgSQL_rec *) target;
+
         /*
          * Copy input first, just in case it is pointing at variable's value
          */
@@ -6027,8 +6002,9 @@ exec_move_row(PLpgSQL_execstate *estate,
      * If we have no tuple data at all, we'll assign NULL to all columns of
      * the row variable.
      */
-    if (row != NULL)
+    if (target->dtype == PLPGSQL_DTYPE_ROW)
     {
+        PLpgSQL_row *row = (PLpgSQL_row *) target;
         int            td_natts = tupdesc ? tupdesc->natts : 0;
         int            t_natts;
         int            fnum;
@@ -6195,8 +6171,7 @@ get_tupdesc_from_datum(Datum value)
  */
 static void
 exec_move_row_from_datum(PLpgSQL_execstate *estate,
-                         PLpgSQL_rec *rec,
-                         PLpgSQL_row *row,
+                         PLpgSQL_variable *target,
                          Datum value)
 {
     HeapTupleHeader td = DatumGetHeapTupleHeader(value);
@@ -6217,7 +6192,7 @@ exec_move_row_from_datum(PLpgSQL_execstate *estate,
     tmptup.t_data = td;

     /* Do the move */
-    exec_move_row(estate, rec, row, &tmptup, tupdesc);
+    exec_move_row(estate, target, &tmptup, tupdesc);

     /* Release tupdesc usage count */
     ReleaseTupleDesc(tupdesc);
diff --git a/src/pl/plpgsql/src/pl_funcs.c b/src/pl/plpgsql/src/pl_funcs.c
index 23f54e1..be779b6 100644
--- a/src/pl/plpgsql/src/pl_funcs.c
+++ b/src/pl/plpgsql/src/pl_funcs.c
@@ -1062,7 +1062,7 @@ static void
 dump_fors(PLpgSQL_stmt_fors *stmt)
 {
     dump_ind();
-    printf("FORS %s ", (stmt->rec != NULL) ? stmt->rec->refname : stmt->row->refname);
+    printf("FORS %s ", stmt->var->refname);
     dump_expr(stmt->query);
     printf("\n");

@@ -1076,7 +1076,7 @@ static void
 dump_forc(PLpgSQL_stmt_forc *stmt)
 {
     dump_ind();
-    printf("FORC %s ", stmt->rec->refname);
+    printf("FORC %s ", stmt->var->refname);
     printf("curvar=%d\n", stmt->curvar);

     dump_indent += 2;
@@ -1174,15 +1174,11 @@ dump_fetch(PLpgSQL_stmt_fetch *stmt)
         dump_cursor_direction(stmt);

         dump_indent += 2;
-        if (stmt->rec != NULL)
+        if (stmt->target != NULL)
         {
             dump_ind();
-            printf("    target = %d %s\n", stmt->rec->dno, stmt->rec->refname);
-        }
-        if (stmt->row != NULL)
-        {
-            dump_ind();
-            printf("    target = %d %s\n", stmt->row->dno, stmt->row->refname);
+            printf("    target = %d %s\n",
+                   stmt->target->dno, stmt->target->refname);
         }
         dump_indent -= 2;
     }
@@ -1420,19 +1416,12 @@ dump_execsql(PLpgSQL_stmt_execsql *stmt)
     printf("\n");

     dump_indent += 2;
-    if (stmt->rec != NULL)
+    if (stmt->target != NULL)
     {
         dump_ind();
         printf("    INTO%s target = %d %s\n",
                stmt->strict ? " STRICT" : "",
-               stmt->rec->dno, stmt->rec->refname);
-    }
-    if (stmt->row != NULL)
-    {
-        dump_ind();
-        printf("    INTO%s target = %d %s\n",
-               stmt->strict ? " STRICT" : "",
-               stmt->row->dno, stmt->row->refname);
+               stmt->target->dno, stmt->target->refname);
     }
     dump_indent -= 2;
 }
@@ -1446,19 +1435,12 @@ dump_dynexecute(PLpgSQL_stmt_dynexecute *stmt)
     printf("\n");

     dump_indent += 2;
-    if (stmt->rec != NULL)
-    {
-        dump_ind();
-        printf("    INTO%s target = %d %s\n",
-               stmt->strict ? " STRICT" : "",
-               stmt->rec->dno, stmt->rec->refname);
-    }
-    if (stmt->row != NULL)
+    if (stmt->target != NULL)
     {
         dump_ind();
         printf("    INTO%s target = %d %s\n",
                stmt->strict ? " STRICT" : "",
-               stmt->row->dno, stmt->row->refname);
+               stmt->target->dno, stmt->target->refname);
     }
     if (stmt->params != NIL)
     {
@@ -1485,8 +1467,7 @@ static void
 dump_dynfors(PLpgSQL_stmt_dynfors *stmt)
 {
     dump_ind();
-    printf("FORS %s EXECUTE ",
-           (stmt->rec != NULL) ? stmt->rec->refname : stmt->row->refname);
+    printf("FORS %s EXECUTE ", stmt->var->refname);
     dump_expr(stmt->query);
     printf("\n");
     if (stmt->params != NIL)
diff --git a/src/pl/plpgsql/src/pl_gram.y b/src/pl/plpgsql/src/pl_gram.y
index 94f1f58..e802440 100644
--- a/src/pl/plpgsql/src/pl_gram.y
+++ b/src/pl/plpgsql/src/pl_gram.y
@@ -90,7 +90,7 @@ static  PLpgSQL_stmt    *make_case(int location, PLpgSQL_expr *t_expr,
                                    List *case_when_list, List *else_stmts);
 static    char            *NameOfDatum(PLwdatum *wdatum);
 static    void             check_assignable(PLpgSQL_datum *datum, int location);
-static    void             read_into_target(PLpgSQL_rec **rec, PLpgSQL_row **row,
+static    void             read_into_target(PLpgSQL_variable **target,
                                           bool *strict);
 static    PLpgSQL_row        *read_into_scalar_list(char *initial_name,
                                                PLpgSQL_datum *initial_datum,
@@ -138,8 +138,7 @@ static    void            check_raise_parameters(PLpgSQL_stmt_raise *stmt);
             char *name;
             int  lineno;
             PLpgSQL_datum   *scalar;
-            PLpgSQL_rec        *rec;
-            PLpgSQL_row        *row;
+            PLpgSQL_datum   *row;
         }                        forvariable;
         struct
         {
@@ -1310,22 +1309,18 @@ for_control        : for_variable K_IN

                             new = palloc0(sizeof(PLpgSQL_stmt_dynfors));
                             new->cmd_type = PLPGSQL_STMT_DYNFORS;
-                            if ($1.rec)
+                            if ($1.row)
                             {
-                                new->rec = $1.rec;
-                                check_assignable((PLpgSQL_datum *) new->rec, @1);
-                            }
-                            else if ($1.row)
-                            {
-                                new->row = $1.row;
-                                check_assignable((PLpgSQL_datum *) new->row, @1);
+                                new->var = (PLpgSQL_variable *) $1.row;
+                                check_assignable($1.row, @1);
                             }
                             else if ($1.scalar)
                             {
                                 /* convert single scalar to list */
-                                new->row = make_scalar_list1($1.name, $1.scalar,
-                                                             $1.lineno, @1);
-                                /* no need for check_assignable */
+                                new->var = (PLpgSQL_variable *)
+                                    make_scalar_list1($1.name, $1.scalar,
+                                                      $1.lineno, @1);
+                                /* make_scalar_list1 did check_assignable */
                             }
                             else
                             {
@@ -1381,9 +1376,10 @@ for_control        : for_variable K_IN
                                                              "LOOP");

                             /* create loop's private RECORD variable */
-                            new->rec = plpgsql_build_record($1.name,
-                                                            $1.lineno,
-                                                            true);
+                            new->var = (PLpgSQL_variable *)
+                                plpgsql_build_record($1.name,
+                                                     $1.lineno,
+                                                     true);

                             $$ = (PLpgSQL_stmt *) new;
                         }
@@ -1504,22 +1500,18 @@ for_control        : for_variable K_IN

                                 new = palloc0(sizeof(PLpgSQL_stmt_fors));
                                 new->cmd_type = PLPGSQL_STMT_FORS;
-                                if ($1.rec)
+                                if ($1.row)
                                 {
-                                    new->rec = $1.rec;
-                                    check_assignable((PLpgSQL_datum *) new->rec, @1);
-                                }
-                                else if ($1.row)
-                                {
-                                    new->row = $1.row;
-                                    check_assignable((PLpgSQL_datum *) new->row, @1);
+                                    new->var = (PLpgSQL_variable *) $1.row;
+                                    check_assignable($1.row, @1);
                                 }
                                 else if ($1.scalar)
                                 {
                                     /* convert single scalar to list */
-                                    new->row = make_scalar_list1($1.name, $1.scalar,
-                                                                 $1.lineno, @1);
-                                    /* no need for check_assignable */
+                                    new->var = (PLpgSQL_variable *)
+                                        make_scalar_list1($1.name, $1.scalar,
+                                                          $1.lineno, @1);
+                                    /* make_scalar_list1 did check_assignable */
                                 }
                                 else
                                 {
@@ -1558,32 +1550,26 @@ for_variable    : T_DATUM
                     {
                         $$.name = NameOfDatum(&($1));
                         $$.lineno = plpgsql_location_to_lineno(@1);
-                        if ($1.datum->dtype == PLPGSQL_DTYPE_ROW)
+                        if ($1.datum->dtype == PLPGSQL_DTYPE_ROW ||
+                            $1.datum->dtype == PLPGSQL_DTYPE_REC)
                         {
                             $$.scalar = NULL;
-                            $$.rec = NULL;
-                            $$.row = (PLpgSQL_row *) $1.datum;
-                        }
-                        else if ($1.datum->dtype == PLPGSQL_DTYPE_REC)
-                        {
-                            $$.scalar = NULL;
-                            $$.rec = (PLpgSQL_rec *) $1.datum;
-                            $$.row = NULL;
+                            $$.row = $1.datum;
                         }
                         else
                         {
                             int            tok;

                             $$.scalar = $1.datum;
-                            $$.rec = NULL;
                             $$.row = NULL;
                             /* check for comma-separated list */
                             tok = yylex();
                             plpgsql_push_back_token(tok);
                             if (tok == ',')
-                                $$.row = read_into_scalar_list($$.name,
-                                                               $$.scalar,
-                                                               @1);
+                                $$.row = (PLpgSQL_datum *)
+                                    read_into_scalar_list($$.name,
+                                                          $$.scalar,
+                                                          @1);
                         }
                     }
                 | T_WORD
@@ -1593,7 +1579,6 @@ for_variable    : T_DATUM
                         $$.name = $1.ident;
                         $$.lineno = plpgsql_location_to_lineno(@1);
                         $$.scalar = NULL;
-                        $$.rec = NULL;
                         $$.row = NULL;
                         /* check for comma-separated list */
                         tok = yylex();
@@ -1620,15 +1605,10 @@ stmt_foreach_a    : opt_loop_label K_FOREACH for_variable foreach_slice K_IN K_ARRA
                         new->expr = $7;
                         new->body = $8.stmts;

-                        if ($3.rec)
-                        {
-                            new->varno = $3.rec->dno;
-                            check_assignable((PLpgSQL_datum *) $3.rec, @3);
-                        }
-                        else if ($3.row)
+                        if ($3.row)
                         {
                             new->varno = $3.row->dno;
-                            check_assignable((PLpgSQL_datum *) $3.row, @3);
+                            check_assignable($3.row, @3);
                         }
                         else if ($3.scalar)
                         {
@@ -1981,8 +1961,7 @@ stmt_dynexecute : K_EXECUTE
                         new->query = expr;
                         new->into = false;
                         new->strict = false;
-                        new->rec = NULL;
-                        new->row = NULL;
+                        new->target = NULL;
                         new->params = NIL;

                         /*
@@ -1999,7 +1978,7 @@ stmt_dynexecute : K_EXECUTE
                                 if (new->into)            /* multiple INTO */
                                     yyerror("syntax error");
                                 new->into = true;
-                                read_into_target(&new->rec, &new->row, &new->strict);
+                                read_into_target(&new->target, &new->strict);
                                 endtoken = yylex();
                             }
                             else if (endtoken == K_USING)
@@ -2107,11 +2086,10 @@ stmt_open        : K_OPEN cursor_variable
 stmt_fetch        : K_FETCH opt_fetch_direction cursor_variable K_INTO
                     {
                         PLpgSQL_stmt_fetch *fetch = $2;
-                        PLpgSQL_rec       *rec;
-                        PLpgSQL_row       *row;
+                        PLpgSQL_variable *target;

                         /* We have already parsed everything through the INTO keyword */
-                        read_into_target(&rec, &row, NULL);
+                        read_into_target(&target, NULL);

                         if (yylex() != ';')
                             yyerror("syntax error");
@@ -2127,8 +2105,7 @@ stmt_fetch        : K_FETCH opt_fetch_direction cursor_variable K_INTO
                                      parser_errposition(@1)));

                         fetch->lineno = plpgsql_location_to_lineno(@1);
-                        fetch->rec        = rec;
-                        fetch->row        = row;
+                        fetch->target    = target;
                         fetch->curvar    = $3->dno;
                         fetch->is_move    = false;

@@ -2842,8 +2819,7 @@ make_execsql_stmt(int firsttoken, int location)
     IdentifierLookup    save_IdentifierLookup;
     PLpgSQL_stmt_execsql *execsql;
     PLpgSQL_expr        *expr;
-    PLpgSQL_row            *row = NULL;
-    PLpgSQL_rec            *rec = NULL;
+    PLpgSQL_variable    *target = NULL;
     int                    tok;
     int                    prev_tok;
     bool                have_into = false;
@@ -2907,7 +2883,7 @@ make_execsql_stmt(int firsttoken, int location)
             have_into = true;
             into_start_loc = yylloc;
             plpgsql_IdentifierLookup = IDENTIFIER_LOOKUP_NORMAL;
-            read_into_target(&rec, &row, &have_strict);
+            read_into_target(&target, &have_strict);
             plpgsql_IdentifierLookup = IDENTIFIER_LOOKUP_EXPR;
         }
     }
@@ -2949,8 +2925,7 @@ make_execsql_stmt(int firsttoken, int location)
     execsql->sqlstmt = expr;
     execsql->into     = have_into;
     execsql->strict     = have_strict;
-    execsql->rec     = rec;
-    execsql->row     = row;
+    execsql->target     = target;

     return (PLpgSQL_stmt *) execsql;
 }
@@ -3341,13 +3316,12 @@ check_assignable(PLpgSQL_datum *datum, int location)
  * INTO keyword.
  */
 static void
-read_into_target(PLpgSQL_rec **rec, PLpgSQL_row **row, bool *strict)
+read_into_target(PLpgSQL_variable **target, bool *strict)
 {
     int            tok;

     /* Set default results */
-    *rec = NULL;
-    *row = NULL;
+    *target = NULL;
     if (strict)
         *strict = false;

@@ -3368,22 +3342,11 @@ read_into_target(PLpgSQL_rec **rec, PLpgSQL_row **row, bool *strict)
     switch (tok)
     {
         case T_DATUM:
-            if (yylval.wdatum.datum->dtype == PLPGSQL_DTYPE_ROW)
-            {
-                check_assignable(yylval.wdatum.datum, yylloc);
-                *row = (PLpgSQL_row *) yylval.wdatum.datum;
-
-                if ((tok = yylex()) == ',')
-                    ereport(ERROR,
-                            (errcode(ERRCODE_SYNTAX_ERROR),
-                             errmsg("record or row variable cannot be part of multiple-item INTO list"),
-                             parser_errposition(yylloc)));
-                plpgsql_push_back_token(tok);
-            }
-            else if (yylval.wdatum.datum->dtype == PLPGSQL_DTYPE_REC)
+            if (yylval.wdatum.datum->dtype == PLPGSQL_DTYPE_ROW ||
+                yylval.wdatum.datum->dtype == PLPGSQL_DTYPE_REC)
             {
                 check_assignable(yylval.wdatum.datum, yylloc);
-                *rec = (PLpgSQL_rec *) yylval.wdatum.datum;
+                *target = (PLpgSQL_variable *) yylval.wdatum.datum;

                 if ((tok = yylex()) == ',')
                     ereport(ERROR,
@@ -3394,8 +3357,9 @@ read_into_target(PLpgSQL_rec **rec, PLpgSQL_row **row, bool *strict)
             }
             else
             {
-                *row = read_into_scalar_list(NameOfDatum(&(yylval.wdatum)),
-                                             yylval.wdatum.datum, yylloc);
+                *target = (PLpgSQL_variable *)
+                    read_into_scalar_list(NameOfDatum(&(yylval.wdatum)),
+                                          yylval.wdatum.datum, yylloc);
             }
             break;

diff --git a/src/pl/plpgsql/src/plpgsql.h b/src/pl/plpgsql/src/plpgsql.h
index 2b19948..8448578 100644
--- a/src/pl/plpgsql/src/plpgsql.h
+++ b/src/pl/plpgsql/src/plpgsql.h
@@ -549,8 +549,7 @@ typedef struct PLpgSQL_stmt_forq
     PLpgSQL_stmt_type cmd_type;
     int            lineno;
     char       *label;
-    PLpgSQL_rec *rec;
-    PLpgSQL_row *row;
+    PLpgSQL_variable *var;        /* Loop variable (record or row) */
     List       *body;            /* List of statements */
 } PLpgSQL_stmt_forq;

@@ -562,8 +561,7 @@ typedef struct PLpgSQL_stmt_fors
     PLpgSQL_stmt_type cmd_type;
     int            lineno;
     char       *label;
-    PLpgSQL_rec *rec;
-    PLpgSQL_row *row;
+    PLpgSQL_variable *var;        /* Loop variable (record or row) */
     List       *body;            /* List of statements */
     /* end of fields that must match PLpgSQL_stmt_forq */
     PLpgSQL_expr *query;
@@ -577,8 +575,7 @@ typedef struct PLpgSQL_stmt_forc
     PLpgSQL_stmt_type cmd_type;
     int            lineno;
     char       *label;
-    PLpgSQL_rec *rec;
-    PLpgSQL_row *row;
+    PLpgSQL_variable *var;        /* Loop variable (record or row) */
     List       *body;            /* List of statements */
     /* end of fields that must match PLpgSQL_stmt_forq */
     int            curvar;
@@ -593,8 +590,7 @@ typedef struct PLpgSQL_stmt_dynfors
     PLpgSQL_stmt_type cmd_type;
     int            lineno;
     char       *label;
-    PLpgSQL_rec *rec;
-    PLpgSQL_row *row;
+    PLpgSQL_variable *var;        /* Loop variable (record or row) */
     List       *body;            /* List of statements */
     /* end of fields that must match PLpgSQL_stmt_forq */
     PLpgSQL_expr *query;
@@ -624,7 +620,6 @@ typedef struct PLpgSQL_stmt_open
     int            lineno;
     int            curvar;
     int            cursor_options;
-    PLpgSQL_row *returntype;
     PLpgSQL_expr *argquery;
     PLpgSQL_expr *query;
     PLpgSQL_expr *dynquery;
@@ -638,8 +633,7 @@ typedef struct PLpgSQL_stmt_fetch
 {
     PLpgSQL_stmt_type cmd_type;
     int            lineno;
-    PLpgSQL_rec *rec;            /* target, as record or row */
-    PLpgSQL_row *row;
+    PLpgSQL_variable *target;    /* target (record or row) */
     int            curvar;            /* cursor variable to fetch from */
     FetchDirection direction;    /* fetch direction */
     long        how_many;        /* count, if constant (expr is NULL) */
@@ -750,8 +744,7 @@ typedef struct PLpgSQL_stmt_execsql
                                  * mod_stmt is set when we plan the query */
     bool        into;            /* INTO supplied? */
     bool        strict;            /* INTO STRICT flag */
-    PLpgSQL_rec *rec;            /* INTO target, if record */
-    PLpgSQL_row *row;            /* INTO target, if row */
+    PLpgSQL_variable *target;    /* INTO target (record or row) */
 } PLpgSQL_stmt_execsql;

 /*
@@ -764,8 +757,7 @@ typedef struct PLpgSQL_stmt_dynexecute
     PLpgSQL_expr *query;        /* string expression */
     bool        into;            /* INTO supplied? */
     bool        strict;            /* INTO STRICT flag */
-    PLpgSQL_rec *rec;            /* INTO target, if record */
-    PLpgSQL_row *row;            /* INTO target, if row */
+    PLpgSQL_variable *target;    /* INTO target (record or row) */
     List       *params;            /* USING expressions */
 } PLpgSQL_stmt_dynexecute;


pgsql-hackers by date:

Previous
From: Laurenz Albe
Date:
Subject: Re: proposal: alternative psql commands quit and exit
Next
From: Bruce Momjian
Date:
Subject: Re: Speeding up pg_upgrade