Commit dd759b96 authored by Tom Lane's avatar Tom Lane

In plpgsql, unify duplicate variables for record and row cases.

plpgsql's function exec_move_row() handles assignment of a composite
source value to either a PLpgSQL_rec or PLpgSQL_row target variable.
Oddly, rather than taking a single target argument which it could do
run-time type detection on, it was coded to take two separate arguments
(only one of which is allowed to be non-NULL).  This choice had then
back-propagated into storing two separate target variables in various
plpgsql statement nodes, with lots of duplicative coding and awkward
interface logic to support that.  Simplify matters by folding those
pairs down to single variables, distinguishing the two cases only
where we must ... which turns out to be only in exec_move_row itself.
This is purely refactoring and should not change any behavior.

In passing, remove unused field PLpgSQL_stmt_open.returntype.

Discussion: https://postgr.es/m/11787.1512713374@sss.pgh.pa.us
parent 2d2d06b7
...@@ -545,7 +545,7 @@ do_compile(FunctionCallInfo fcinfo, ...@@ -545,7 +545,7 @@ do_compile(FunctionCallInfo fcinfo,
{ {
if (rettypeid == VOIDOID || if (rettypeid == VOIDOID ||
rettypeid == RECORDOID) rettypeid == RECORDOID)
/* okay */ ; /* okay */ ;
else if (rettypeid == TRIGGEROID || rettypeid == EVTTRIGGEROID) else if (rettypeid == TRIGGEROID || rettypeid == EVTTRIGGEROID)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
......
...@@ -272,8 +272,7 @@ static ParamListInfo setup_unshared_param_list(PLpgSQL_execstate *estate, ...@@ -272,8 +272,7 @@ static ParamListInfo setup_unshared_param_list(PLpgSQL_execstate *estate,
PLpgSQL_expr *expr); PLpgSQL_expr *expr);
static void plpgsql_param_fetch(ParamListInfo params, int paramid); static void plpgsql_param_fetch(ParamListInfo params, int paramid);
static void exec_move_row(PLpgSQL_execstate *estate, static void exec_move_row(PLpgSQL_execstate *estate,
PLpgSQL_rec *rec, PLpgSQL_variable *target,
PLpgSQL_row *row,
HeapTuple tup, TupleDesc tupdesc); HeapTuple tup, TupleDesc tupdesc);
static HeapTuple make_tuple_from_row(PLpgSQL_execstate *estate, static HeapTuple make_tuple_from_row(PLpgSQL_execstate *estate,
PLpgSQL_row *row, PLpgSQL_row *row,
...@@ -281,8 +280,7 @@ static HeapTuple make_tuple_from_row(PLpgSQL_execstate *estate, ...@@ -281,8 +280,7 @@ static HeapTuple make_tuple_from_row(PLpgSQL_execstate *estate,
static HeapTuple get_tuple_from_datum(Datum value); static HeapTuple get_tuple_from_datum(Datum value);
static TupleDesc get_tupdesc_from_datum(Datum value); static TupleDesc get_tupdesc_from_datum(Datum value);
static void exec_move_row_from_datum(PLpgSQL_execstate *estate, static void exec_move_row_from_datum(PLpgSQL_execstate *estate,
PLpgSQL_rec *rec, PLpgSQL_variable *target,
PLpgSQL_row *row,
Datum value); Datum value);
static char *convert_value_to_string(PLpgSQL_execstate *estate, static char *convert_value_to_string(PLpgSQL_execstate *estate,
Datum value, Oid valtype); Datum value, Oid valtype);
...@@ -425,13 +423,15 @@ plpgsql_exec_function(PLpgSQL_function *func, FunctionCallInfo fcinfo, ...@@ -425,13 +423,15 @@ plpgsql_exec_function(PLpgSQL_function *func, FunctionCallInfo fcinfo,
if (!fcinfo->argnull[i]) if (!fcinfo->argnull[i])
{ {
/* Assign row value from composite datum */ /* 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]); fcinfo->arg[i]);
} }
else else
{ {
/* If arg is null, treat it as an empty row */ /* 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() */ /* clean up after exec_move_row() */
exec_eval_cleanup(&estate); exec_eval_cleanup(&estate);
...@@ -2327,7 +2327,7 @@ exec_stmt_forc(PLpgSQL_execstate *estate, PLpgSQL_stmt_forc *stmt) ...@@ -2327,7 +2327,7 @@ exec_stmt_forc(PLpgSQL_execstate *estate, PLpgSQL_stmt_forc *stmt)
set_args.sqlstmt = stmt->argquery; set_args.sqlstmt = stmt->argquery;
set_args.into = true; set_args.into = true;
/* XXX historically this has not been STRICT */ /* XXX historically this has not been STRICT */
set_args.row = (PLpgSQL_row *) set_args.target = (PLpgSQL_variable *)
(estate->datums[curvar->cursor_explicit_argrow]); (estate->datums[curvar->cursor_explicit_argrow]);
if (exec_stmt_execsql(estate, &set_args) != PLPGSQL_RC_OK) if (exec_stmt_execsql(estate, &set_args) != PLPGSQL_RC_OK)
...@@ -3755,8 +3755,7 @@ exec_stmt_execsql(PLpgSQL_execstate *estate, ...@@ -3755,8 +3755,7 @@ exec_stmt_execsql(PLpgSQL_execstate *estate,
{ {
SPITupleTable *tuptab = SPI_tuptable; SPITupleTable *tuptab = SPI_tuptable;
uint64 n = SPI_processed; uint64 n = SPI_processed;
PLpgSQL_rec *rec = NULL; PLpgSQL_variable *target;
PLpgSQL_row *row = NULL;
/* If the statement did not return a tuple table, complain */ /* If the statement did not return a tuple table, complain */
if (tuptab == NULL) if (tuptab == NULL)
...@@ -3764,13 +3763,8 @@ exec_stmt_execsql(PLpgSQL_execstate *estate, ...@@ -3764,13 +3763,8 @@ exec_stmt_execsql(PLpgSQL_execstate *estate,
(errcode(ERRCODE_SYNTAX_ERROR), (errcode(ERRCODE_SYNTAX_ERROR),
errmsg("INTO used with a command that cannot return data"))); errmsg("INTO used with a command that cannot return data")));
/* Determine if we assign to a record or a row */ /* Fetch target's datum entry */
if (stmt->rec != NULL) target = (PLpgSQL_variable *) estate->datums[stmt->target->dno];
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");
/* /*
* If SELECT ... INTO specified STRICT, and the query didn't find * If SELECT ... INTO specified STRICT, and the query didn't find
...@@ -3794,7 +3788,7 @@ exec_stmt_execsql(PLpgSQL_execstate *estate, ...@@ -3794,7 +3788,7 @@ exec_stmt_execsql(PLpgSQL_execstate *estate,
errdetail ? errdetail_internal("parameters: %s", errdetail) : 0)); errdetail ? errdetail_internal("parameters: %s", errdetail) : 0));
} }
/* set the target to NULL(s) */ /* set the target to NULL(s) */
exec_move_row(estate, rec, row, NULL, tuptab->tupdesc); exec_move_row(estate, target, NULL, tuptab->tupdesc);
} }
else else
{ {
...@@ -3813,7 +3807,7 @@ exec_stmt_execsql(PLpgSQL_execstate *estate, ...@@ -3813,7 +3807,7 @@ exec_stmt_execsql(PLpgSQL_execstate *estate,
errdetail ? errdetail_internal("parameters: %s", errdetail) : 0)); errdetail ? errdetail_internal("parameters: %s", errdetail) : 0));
} }
/* Put the first result row into the target */ /* 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 */ /* Clean up */
...@@ -3946,8 +3940,7 @@ exec_stmt_dynexecute(PLpgSQL_execstate *estate, ...@@ -3946,8 +3940,7 @@ exec_stmt_dynexecute(PLpgSQL_execstate *estate,
{ {
SPITupleTable *tuptab = SPI_tuptable; SPITupleTable *tuptab = SPI_tuptable;
uint64 n = SPI_processed; uint64 n = SPI_processed;
PLpgSQL_rec *rec = NULL; PLpgSQL_variable *target;
PLpgSQL_row *row = NULL;
/* If the statement did not return a tuple table, complain */ /* If the statement did not return a tuple table, complain */
if (tuptab == NULL) if (tuptab == NULL)
...@@ -3955,13 +3948,8 @@ exec_stmt_dynexecute(PLpgSQL_execstate *estate, ...@@ -3955,13 +3948,8 @@ exec_stmt_dynexecute(PLpgSQL_execstate *estate,
(errcode(ERRCODE_SYNTAX_ERROR), (errcode(ERRCODE_SYNTAX_ERROR),
errmsg("INTO used with a command that cannot return data"))); errmsg("INTO used with a command that cannot return data")));
/* Determine if we assign to a record or a row */ /* Fetch target's datum entry */
if (stmt->rec != NULL) target = (PLpgSQL_variable *) estate->datums[stmt->target->dno];
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");
/* /*
* If SELECT ... INTO specified STRICT, and the query didn't find * If SELECT ... INTO specified STRICT, and the query didn't find
...@@ -3985,7 +3973,7 @@ exec_stmt_dynexecute(PLpgSQL_execstate *estate, ...@@ -3985,7 +3973,7 @@ exec_stmt_dynexecute(PLpgSQL_execstate *estate,
errdetail ? errdetail_internal("parameters: %s", errdetail) : 0)); errdetail ? errdetail_internal("parameters: %s", errdetail) : 0));
} }
/* set the target to NULL(s) */ /* set the target to NULL(s) */
exec_move_row(estate, rec, row, NULL, tuptab->tupdesc); exec_move_row(estate, target, NULL, tuptab->tupdesc);
} }
else else
{ {
...@@ -4005,7 +3993,7 @@ exec_stmt_dynexecute(PLpgSQL_execstate *estate, ...@@ -4005,7 +3993,7 @@ exec_stmt_dynexecute(PLpgSQL_execstate *estate,
} }
/* Put the first result row into the target */ /* 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() */ /* clean up after exec_move_row() */
exec_eval_cleanup(estate); exec_eval_cleanup(estate);
...@@ -4163,7 +4151,7 @@ exec_stmt_open(PLpgSQL_execstate *estate, PLpgSQL_stmt_open *stmt) ...@@ -4163,7 +4151,7 @@ exec_stmt_open(PLpgSQL_execstate *estate, PLpgSQL_stmt_open *stmt)
set_args.sqlstmt = stmt->argquery; set_args.sqlstmt = stmt->argquery;
set_args.into = true; set_args.into = true;
/* XXX historically this has not been STRICT */ /* XXX historically this has not been STRICT */
set_args.row = (PLpgSQL_row *) set_args.target = (PLpgSQL_variable *)
(estate->datums[curvar->cursor_explicit_argrow]); (estate->datums[curvar->cursor_explicit_argrow]);
if (exec_stmt_execsql(estate, &set_args) != PLPGSQL_RC_OK) if (exec_stmt_execsql(estate, &set_args) != PLPGSQL_RC_OK)
...@@ -4221,8 +4209,6 @@ static int ...@@ -4221,8 +4209,6 @@ static int
exec_stmt_fetch(PLpgSQL_execstate *estate, PLpgSQL_stmt_fetch *stmt) exec_stmt_fetch(PLpgSQL_execstate *estate, PLpgSQL_stmt_fetch *stmt)
{ {
PLpgSQL_var *curvar; PLpgSQL_var *curvar;
PLpgSQL_rec *rec = NULL;
PLpgSQL_row *row = NULL;
long how_many = stmt->how_many; long how_many = stmt->how_many;
SPITupleTable *tuptab; SPITupleTable *tuptab;
Portal portal; Portal portal;
...@@ -4269,16 +4255,7 @@ exec_stmt_fetch(PLpgSQL_execstate *estate, PLpgSQL_stmt_fetch *stmt) ...@@ -4269,16 +4255,7 @@ exec_stmt_fetch(PLpgSQL_execstate *estate, PLpgSQL_stmt_fetch *stmt)
if (!stmt->is_move) if (!stmt->is_move)
{ {
/* ---------- PLpgSQL_variable *target;
* 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");
/* ---------- /* ----------
* Fetch 1 tuple from the cursor * Fetch 1 tuple from the cursor
...@@ -4292,10 +4269,11 @@ exec_stmt_fetch(PLpgSQL_execstate *estate, PLpgSQL_stmt_fetch *stmt) ...@@ -4292,10 +4269,11 @@ exec_stmt_fetch(PLpgSQL_execstate *estate, PLpgSQL_stmt_fetch *stmt)
* Set the target appropriately. * Set the target appropriately.
* ---------- * ----------
*/ */
target = (PLpgSQL_variable *) estate->datums[stmt->target->dno];
if (n == 0) if (n == 0)
exec_move_row(estate, rec, row, NULL, tuptab->tupdesc); exec_move_row(estate, target, NULL, tuptab->tupdesc);
else 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); exec_eval_cleanup(estate);
SPI_freetuptable(tuptab); SPI_freetuptable(tuptab);
...@@ -4514,7 +4492,8 @@ exec_assign_value(PLpgSQL_execstate *estate, ...@@ -4514,7 +4492,8 @@ exec_assign_value(PLpgSQL_execstate *estate,
if (isNull) if (isNull)
{ {
/* If source is null, just assign nulls to the row */ /* 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 else
{ {
...@@ -4523,7 +4502,8 @@ exec_assign_value(PLpgSQL_execstate *estate, ...@@ -4523,7 +4502,8 @@ exec_assign_value(PLpgSQL_execstate *estate,
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH), (errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("cannot assign non-composite value to a row variable"))); 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; break;
} }
...@@ -4538,7 +4518,8 @@ exec_assign_value(PLpgSQL_execstate *estate, ...@@ -4538,7 +4518,8 @@ exec_assign_value(PLpgSQL_execstate *estate,
if (isNull) if (isNull)
{ {
/* If source is null, just assign nulls to the record */ /* 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 else
{ {
...@@ -4547,7 +4528,8 @@ exec_assign_value(PLpgSQL_execstate *estate, ...@@ -4547,7 +4528,8 @@ exec_assign_value(PLpgSQL_execstate *estate,
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH), (errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("cannot assign non-composite value to a record variable"))); 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; break;
} }
...@@ -5341,22 +5323,14 @@ static int ...@@ -5341,22 +5323,14 @@ static int
exec_for_query(PLpgSQL_execstate *estate, PLpgSQL_stmt_forq *stmt, exec_for_query(PLpgSQL_execstate *estate, PLpgSQL_stmt_forq *stmt,
Portal portal, bool prefetch_ok) Portal portal, bool prefetch_ok)
{ {
PLpgSQL_rec *rec = NULL; PLpgSQL_variable *var;
PLpgSQL_row *row = NULL;
SPITupleTable *tuptab; SPITupleTable *tuptab;
bool found = false; bool found = false;
int rc = PLPGSQL_RC_OK; int rc = PLPGSQL_RC_OK;
uint64 n; uint64 n;
/* /* Fetch loop variable's datum entry */
* Determine if we assign to a record or a row var = (PLpgSQL_variable *) estate->datums[stmt->var->dno];
*/
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");
/* /*
* Make sure the portal doesn't get closed by the user statements we * 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, ...@@ -5379,7 +5353,7 @@ exec_for_query(PLpgSQL_execstate *estate, PLpgSQL_stmt_forq *stmt,
*/ */
if (n == 0) if (n == 0)
{ {
exec_move_row(estate, rec, row, NULL, tuptab->tupdesc); exec_move_row(estate, var, NULL, tuptab->tupdesc);
exec_eval_cleanup(estate); exec_eval_cleanup(estate);
} }
else else
...@@ -5397,7 +5371,7 @@ exec_for_query(PLpgSQL_execstate *estate, PLpgSQL_stmt_forq *stmt, ...@@ -5397,7 +5371,7 @@ exec_for_query(PLpgSQL_execstate *estate, PLpgSQL_stmt_forq *stmt,
/* /*
* Assign the tuple to the target * 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); exec_eval_cleanup(estate);
/* /*
...@@ -5949,16 +5923,17 @@ plpgsql_param_fetch(ParamListInfo params, int paramid) ...@@ -5949,16 +5923,17 @@ plpgsql_param_fetch(ParamListInfo params, int paramid)
*/ */
static void static void
exec_move_row(PLpgSQL_execstate *estate, exec_move_row(PLpgSQL_execstate *estate,
PLpgSQL_rec *rec, PLpgSQL_variable *target,
PLpgSQL_row *row,
HeapTuple tup, TupleDesc tupdesc) HeapTuple tup, TupleDesc tupdesc)
{ {
/* /*
* Record is simple - just copy the tuple and its descriptor into the * Record is simple - just copy the tuple and its descriptor into the
* record variable * 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 * Copy input first, just in case it is pointing at variable's value
*/ */
...@@ -6027,8 +6002,9 @@ exec_move_row(PLpgSQL_execstate *estate, ...@@ -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 * If we have no tuple data at all, we'll assign NULL to all columns of
* the row variable. * 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 td_natts = tupdesc ? tupdesc->natts : 0;
int t_natts; int t_natts;
int fnum; int fnum;
...@@ -6195,8 +6171,7 @@ get_tupdesc_from_datum(Datum value) ...@@ -6195,8 +6171,7 @@ get_tupdesc_from_datum(Datum value)
*/ */
static void static void
exec_move_row_from_datum(PLpgSQL_execstate *estate, exec_move_row_from_datum(PLpgSQL_execstate *estate,
PLpgSQL_rec *rec, PLpgSQL_variable *target,
PLpgSQL_row *row,
Datum value) Datum value)
{ {
HeapTupleHeader td = DatumGetHeapTupleHeader(value); HeapTupleHeader td = DatumGetHeapTupleHeader(value);
...@@ -6217,7 +6192,7 @@ exec_move_row_from_datum(PLpgSQL_execstate *estate, ...@@ -6217,7 +6192,7 @@ exec_move_row_from_datum(PLpgSQL_execstate *estate,
tmptup.t_data = td; tmptup.t_data = td;
/* Do the move */ /* Do the move */
exec_move_row(estate, rec, row, &tmptup, tupdesc); exec_move_row(estate, target, &tmptup, tupdesc);
/* Release tupdesc usage count */ /* Release tupdesc usage count */
ReleaseTupleDesc(tupdesc); ReleaseTupleDesc(tupdesc);
......
...@@ -1062,7 +1062,7 @@ static void ...@@ -1062,7 +1062,7 @@ static void
dump_fors(PLpgSQL_stmt_fors *stmt) dump_fors(PLpgSQL_stmt_fors *stmt)
{ {
dump_ind(); dump_ind();
printf("FORS %s ", (stmt->rec != NULL) ? stmt->rec->refname : stmt->row->refname); printf("FORS %s ", stmt->var->refname);
dump_expr(stmt->query); dump_expr(stmt->query);
printf("\n"); printf("\n");
...@@ -1076,7 +1076,7 @@ static void ...@@ -1076,7 +1076,7 @@ static void
dump_forc(PLpgSQL_stmt_forc *stmt) dump_forc(PLpgSQL_stmt_forc *stmt)
{ {
dump_ind(); dump_ind();
printf("FORC %s ", stmt->rec->refname); printf("FORC %s ", stmt->var->refname);
printf("curvar=%d\n", stmt->curvar); printf("curvar=%d\n", stmt->curvar);
dump_indent += 2; dump_indent += 2;
...@@ -1174,15 +1174,11 @@ dump_fetch(PLpgSQL_stmt_fetch *stmt) ...@@ -1174,15 +1174,11 @@ dump_fetch(PLpgSQL_stmt_fetch *stmt)
dump_cursor_direction(stmt); dump_cursor_direction(stmt);
dump_indent += 2; dump_indent += 2;
if (stmt->rec != NULL) if (stmt->target != NULL)
{ {
dump_ind(); dump_ind();
printf(" target = %d %s\n", stmt->rec->dno, stmt->rec->refname); printf(" target = %d %s\n",
} stmt->target->dno, stmt->target->refname);
if (stmt->row != NULL)
{
dump_ind();
printf(" target = %d %s\n", stmt->row->dno, stmt->row->refname);
} }
dump_indent -= 2; dump_indent -= 2;
} }
...@@ -1420,19 +1416,12 @@ dump_execsql(PLpgSQL_stmt_execsql *stmt) ...@@ -1420,19 +1416,12 @@ dump_execsql(PLpgSQL_stmt_execsql *stmt)
printf("\n"); printf("\n");
dump_indent += 2; dump_indent += 2;
if (stmt->rec != NULL) if (stmt->target != NULL)
{ {
dump_ind(); dump_ind();
printf(" INTO%s target = %d %s\n", printf(" INTO%s target = %d %s\n",
stmt->strict ? " STRICT" : "", stmt->strict ? " STRICT" : "",
stmt->rec->dno, stmt->rec->refname); stmt->target->dno, stmt->target->refname);
}
if (stmt->row != NULL)
{
dump_ind();
printf(" INTO%s target = %d %s\n",
stmt->strict ? " STRICT" : "",
stmt->row->dno, stmt->row->refname);
} }
dump_indent -= 2; dump_indent -= 2;
} }
...@@ -1446,19 +1435,12 @@ dump_dynexecute(PLpgSQL_stmt_dynexecute *stmt) ...@@ -1446,19 +1435,12 @@ dump_dynexecute(PLpgSQL_stmt_dynexecute *stmt)
printf("\n"); printf("\n");
dump_indent += 2; 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(); dump_ind();
printf(" INTO%s target = %d %s\n", printf(" INTO%s target = %d %s\n",
stmt->strict ? " STRICT" : "", stmt->strict ? " STRICT" : "",
stmt->row->dno, stmt->row->refname); stmt->target->dno, stmt->target->refname);
} }
if (stmt->params != NIL) if (stmt->params != NIL)
{ {
...@@ -1485,8 +1467,7 @@ static void ...@@ -1485,8 +1467,7 @@ static void
dump_dynfors(PLpgSQL_stmt_dynfors *stmt) dump_dynfors(PLpgSQL_stmt_dynfors *stmt)
{ {
dump_ind(); dump_ind();
printf("FORS %s EXECUTE ", printf("FORS %s EXECUTE ", stmt->var->refname);
(stmt->rec != NULL) ? stmt->rec->refname : stmt->row->refname);
dump_expr(stmt->query); dump_expr(stmt->query);
printf("\n"); printf("\n");
if (stmt->params != NIL) if (stmt->params != NIL)
......
...@@ -90,7 +90,7 @@ static PLpgSQL_stmt *make_case(int location, PLpgSQL_expr *t_expr, ...@@ -90,7 +90,7 @@ static PLpgSQL_stmt *make_case(int location, PLpgSQL_expr *t_expr,
List *case_when_list, List *else_stmts); List *case_when_list, List *else_stmts);
static char *NameOfDatum(PLwdatum *wdatum); static char *NameOfDatum(PLwdatum *wdatum);
static void check_assignable(PLpgSQL_datum *datum, int location); 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); bool *strict);
static PLpgSQL_row *read_into_scalar_list(char *initial_name, static PLpgSQL_row *read_into_scalar_list(char *initial_name,
PLpgSQL_datum *initial_datum, PLpgSQL_datum *initial_datum,
...@@ -138,8 +138,7 @@ static void check_raise_parameters(PLpgSQL_stmt_raise *stmt); ...@@ -138,8 +138,7 @@ static void check_raise_parameters(PLpgSQL_stmt_raise *stmt);
char *name; char *name;
int lineno; int lineno;
PLpgSQL_datum *scalar; PLpgSQL_datum *scalar;
PLpgSQL_rec *rec; PLpgSQL_datum *row;
PLpgSQL_row *row;
} forvariable; } forvariable;
struct struct
{ {
...@@ -1310,22 +1309,18 @@ for_control : for_variable K_IN ...@@ -1310,22 +1309,18 @@ for_control : for_variable K_IN
new = palloc0(sizeof(PLpgSQL_stmt_dynfors)); new = palloc0(sizeof(PLpgSQL_stmt_dynfors));
new->cmd_type = PLPGSQL_STMT_DYNFORS; new->cmd_type = PLPGSQL_STMT_DYNFORS;
if ($1.rec) if ($1.row)
{ {
new->rec = $1.rec; new->var = (PLpgSQL_variable *) $1.row;
check_assignable((PLpgSQL_datum *) new->rec, @1); check_assignable($1.row, @1);
}
else if ($1.row)
{
new->row = $1.row;
check_assignable((PLpgSQL_datum *) new->row, @1);
} }
else if ($1.scalar) else if ($1.scalar)
{ {
/* convert single scalar to list */ /* convert single scalar to list */
new->row = make_scalar_list1($1.name, $1.scalar, new->var = (PLpgSQL_variable *)
$1.lineno, @1); make_scalar_list1($1.name, $1.scalar,
/* no need for check_assignable */ $1.lineno, @1);
/* make_scalar_list1 did check_assignable */
} }
else else
{ {
...@@ -1381,9 +1376,10 @@ for_control : for_variable K_IN ...@@ -1381,9 +1376,10 @@ for_control : for_variable K_IN
"LOOP"); "LOOP");
/* create loop's private RECORD variable */ /* create loop's private RECORD variable */
new->rec = plpgsql_build_record($1.name, new->var = (PLpgSQL_variable *)
$1.lineno, plpgsql_build_record($1.name,
true); $1.lineno,
true);
$$ = (PLpgSQL_stmt *) new; $$ = (PLpgSQL_stmt *) new;
} }
...@@ -1504,22 +1500,18 @@ for_control : for_variable K_IN ...@@ -1504,22 +1500,18 @@ for_control : for_variable K_IN
new = palloc0(sizeof(PLpgSQL_stmt_fors)); new = palloc0(sizeof(PLpgSQL_stmt_fors));
new->cmd_type = PLPGSQL_STMT_FORS; new->cmd_type = PLPGSQL_STMT_FORS;
if ($1.rec) if ($1.row)
{ {
new->rec = $1.rec; new->var = (PLpgSQL_variable *) $1.row;
check_assignable((PLpgSQL_datum *) new->rec, @1); check_assignable($1.row, @1);
}
else if ($1.row)
{
new->row = $1.row;
check_assignable((PLpgSQL_datum *) new->row, @1);
} }
else if ($1.scalar) else if ($1.scalar)
{ {
/* convert single scalar to list */ /* convert single scalar to list */
new->row = make_scalar_list1($1.name, $1.scalar, new->var = (PLpgSQL_variable *)
$1.lineno, @1); make_scalar_list1($1.name, $1.scalar,
/* no need for check_assignable */ $1.lineno, @1);
/* make_scalar_list1 did check_assignable */
} }
else else
{ {
...@@ -1558,32 +1550,26 @@ for_variable : T_DATUM ...@@ -1558,32 +1550,26 @@ for_variable : T_DATUM
{ {
$$.name = NameOfDatum(&($1)); $$.name = NameOfDatum(&($1));
$$.lineno = plpgsql_location_to_lineno(@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; $$.scalar = NULL;
$$.rec = NULL; $$.row = $1.datum;
$$.row = (PLpgSQL_row *) $1.datum;
}
else if ($1.datum->dtype == PLPGSQL_DTYPE_REC)
{
$$.scalar = NULL;
$$.rec = (PLpgSQL_rec *) $1.datum;
$$.row = NULL;
} }
else else
{ {
int tok; int tok;
$$.scalar = $1.datum; $$.scalar = $1.datum;
$$.rec = NULL;
$$.row = NULL; $$.row = NULL;
/* check for comma-separated list */ /* check for comma-separated list */
tok = yylex(); tok = yylex();
plpgsql_push_back_token(tok); plpgsql_push_back_token(tok);
if (tok == ',') if (tok == ',')
$$.row = read_into_scalar_list($$.name, $$.row = (PLpgSQL_datum *)
$$.scalar, read_into_scalar_list($$.name,
@1); $$.scalar,
@1);
} }
} }
| T_WORD | T_WORD
...@@ -1593,7 +1579,6 @@ for_variable : T_DATUM ...@@ -1593,7 +1579,6 @@ for_variable : T_DATUM
$$.name = $1.ident; $$.name = $1.ident;
$$.lineno = plpgsql_location_to_lineno(@1); $$.lineno = plpgsql_location_to_lineno(@1);
$$.scalar = NULL; $$.scalar = NULL;
$$.rec = NULL;
$$.row = NULL; $$.row = NULL;
/* check for comma-separated list */ /* check for comma-separated list */
tok = yylex(); tok = yylex();
...@@ -1620,15 +1605,10 @@ stmt_foreach_a : opt_loop_label K_FOREACH for_variable foreach_slice K_IN K_ARRA ...@@ -1620,15 +1605,10 @@ stmt_foreach_a : opt_loop_label K_FOREACH for_variable foreach_slice K_IN K_ARRA
new->expr = $7; new->expr = $7;
new->body = $8.stmts; new->body = $8.stmts;
if ($3.rec) if ($3.row)
{
new->varno = $3.rec->dno;
check_assignable((PLpgSQL_datum *) $3.rec, @3);
}
else if ($3.row)
{ {
new->varno = $3.row->dno; new->varno = $3.row->dno;
check_assignable((PLpgSQL_datum *) $3.row, @3); check_assignable($3.row, @3);
} }
else if ($3.scalar) else if ($3.scalar)
{ {
...@@ -1981,8 +1961,7 @@ stmt_dynexecute : K_EXECUTE ...@@ -1981,8 +1961,7 @@ stmt_dynexecute : K_EXECUTE
new->query = expr; new->query = expr;
new->into = false; new->into = false;
new->strict = false; new->strict = false;
new->rec = NULL; new->target = NULL;
new->row = NULL;
new->params = NIL; new->params = NIL;
/* /*
...@@ -1999,7 +1978,7 @@ stmt_dynexecute : K_EXECUTE ...@@ -1999,7 +1978,7 @@ stmt_dynexecute : K_EXECUTE
if (new->into) /* multiple INTO */ if (new->into) /* multiple INTO */
yyerror("syntax error"); yyerror("syntax error");
new->into = true; new->into = true;
read_into_target(&new->rec, &new->row, &new->strict); read_into_target(&new->target, &new->strict);
endtoken = yylex(); endtoken = yylex();
} }
else if (endtoken == K_USING) else if (endtoken == K_USING)
...@@ -2107,11 +2086,10 @@ stmt_open : K_OPEN cursor_variable ...@@ -2107,11 +2086,10 @@ stmt_open : K_OPEN cursor_variable
stmt_fetch : K_FETCH opt_fetch_direction cursor_variable K_INTO stmt_fetch : K_FETCH opt_fetch_direction cursor_variable K_INTO
{ {
PLpgSQL_stmt_fetch *fetch = $2; PLpgSQL_stmt_fetch *fetch = $2;
PLpgSQL_rec *rec; PLpgSQL_variable *target;
PLpgSQL_row *row;
/* We have already parsed everything through the INTO keyword */ /* We have already parsed everything through the INTO keyword */
read_into_target(&rec, &row, NULL); read_into_target(&target, NULL);
if (yylex() != ';') if (yylex() != ';')
yyerror("syntax error"); yyerror("syntax error");
...@@ -2127,8 +2105,7 @@ stmt_fetch : K_FETCH opt_fetch_direction cursor_variable K_INTO ...@@ -2127,8 +2105,7 @@ stmt_fetch : K_FETCH opt_fetch_direction cursor_variable K_INTO
parser_errposition(@1))); parser_errposition(@1)));
fetch->lineno = plpgsql_location_to_lineno(@1); fetch->lineno = plpgsql_location_to_lineno(@1);
fetch->rec = rec; fetch->target = target;
fetch->row = row;
fetch->curvar = $3->dno; fetch->curvar = $3->dno;
fetch->is_move = false; fetch->is_move = false;
...@@ -2842,8 +2819,7 @@ make_execsql_stmt(int firsttoken, int location) ...@@ -2842,8 +2819,7 @@ make_execsql_stmt(int firsttoken, int location)
IdentifierLookup save_IdentifierLookup; IdentifierLookup save_IdentifierLookup;
PLpgSQL_stmt_execsql *execsql; PLpgSQL_stmt_execsql *execsql;
PLpgSQL_expr *expr; PLpgSQL_expr *expr;
PLpgSQL_row *row = NULL; PLpgSQL_variable *target = NULL;
PLpgSQL_rec *rec = NULL;
int tok; int tok;
int prev_tok; int prev_tok;
bool have_into = false; bool have_into = false;
...@@ -2907,7 +2883,7 @@ make_execsql_stmt(int firsttoken, int location) ...@@ -2907,7 +2883,7 @@ make_execsql_stmt(int firsttoken, int location)
have_into = true; have_into = true;
into_start_loc = yylloc; into_start_loc = yylloc;
plpgsql_IdentifierLookup = IDENTIFIER_LOOKUP_NORMAL; plpgsql_IdentifierLookup = IDENTIFIER_LOOKUP_NORMAL;
read_into_target(&rec, &row, &have_strict); read_into_target(&target, &have_strict);
plpgsql_IdentifierLookup = IDENTIFIER_LOOKUP_EXPR; plpgsql_IdentifierLookup = IDENTIFIER_LOOKUP_EXPR;
} }
} }
...@@ -2949,8 +2925,7 @@ make_execsql_stmt(int firsttoken, int location) ...@@ -2949,8 +2925,7 @@ make_execsql_stmt(int firsttoken, int location)
execsql->sqlstmt = expr; execsql->sqlstmt = expr;
execsql->into = have_into; execsql->into = have_into;
execsql->strict = have_strict; execsql->strict = have_strict;
execsql->rec = rec; execsql->target = target;
execsql->row = row;
return (PLpgSQL_stmt *) execsql; return (PLpgSQL_stmt *) execsql;
} }
...@@ -3341,13 +3316,12 @@ check_assignable(PLpgSQL_datum *datum, int location) ...@@ -3341,13 +3316,12 @@ check_assignable(PLpgSQL_datum *datum, int location)
* INTO keyword. * INTO keyword.
*/ */
static void static void
read_into_target(PLpgSQL_rec **rec, PLpgSQL_row **row, bool *strict) read_into_target(PLpgSQL_variable **target, bool *strict)
{ {
int tok; int tok;
/* Set default results */ /* Set default results */
*rec = NULL; *target = NULL;
*row = NULL;
if (strict) if (strict)
*strict = false; *strict = false;
...@@ -3368,22 +3342,11 @@ read_into_target(PLpgSQL_rec **rec, PLpgSQL_row **row, bool *strict) ...@@ -3368,22 +3342,11 @@ read_into_target(PLpgSQL_rec **rec, PLpgSQL_row **row, bool *strict)
switch (tok) switch (tok)
{ {
case T_DATUM: case T_DATUM:
if (yylval.wdatum.datum->dtype == PLPGSQL_DTYPE_ROW) if (yylval.wdatum.datum->dtype == PLPGSQL_DTYPE_ROW ||
{ yylval.wdatum.datum->dtype == PLPGSQL_DTYPE_REC)
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)
{ {
check_assignable(yylval.wdatum.datum, yylloc); check_assignable(yylval.wdatum.datum, yylloc);
*rec = (PLpgSQL_rec *) yylval.wdatum.datum; *target = (PLpgSQL_variable *) yylval.wdatum.datum;
if ((tok = yylex()) == ',') if ((tok = yylex()) == ',')
ereport(ERROR, ereport(ERROR,
...@@ -3394,8 +3357,9 @@ read_into_target(PLpgSQL_rec **rec, PLpgSQL_row **row, bool *strict) ...@@ -3394,8 +3357,9 @@ read_into_target(PLpgSQL_rec **rec, PLpgSQL_row **row, bool *strict)
} }
else else
{ {
*row = read_into_scalar_list(NameOfDatum(&(yylval.wdatum)), *target = (PLpgSQL_variable *)
yylval.wdatum.datum, yylloc); read_into_scalar_list(NameOfDatum(&(yylval.wdatum)),
yylval.wdatum.datum, yylloc);
} }
break; break;
......
...@@ -549,8 +549,7 @@ typedef struct PLpgSQL_stmt_forq ...@@ -549,8 +549,7 @@ typedef struct PLpgSQL_stmt_forq
PLpgSQL_stmt_type cmd_type; PLpgSQL_stmt_type cmd_type;
int lineno; int lineno;
char *label; char *label;
PLpgSQL_rec *rec; PLpgSQL_variable *var; /* Loop variable (record or row) */
PLpgSQL_row *row;
List *body; /* List of statements */ List *body; /* List of statements */
} PLpgSQL_stmt_forq; } PLpgSQL_stmt_forq;
...@@ -562,8 +561,7 @@ typedef struct PLpgSQL_stmt_fors ...@@ -562,8 +561,7 @@ typedef struct PLpgSQL_stmt_fors
PLpgSQL_stmt_type cmd_type; PLpgSQL_stmt_type cmd_type;
int lineno; int lineno;
char *label; char *label;
PLpgSQL_rec *rec; PLpgSQL_variable *var; /* Loop variable (record or row) */
PLpgSQL_row *row;
List *body; /* List of statements */ List *body; /* List of statements */
/* end of fields that must match PLpgSQL_stmt_forq */ /* end of fields that must match PLpgSQL_stmt_forq */
PLpgSQL_expr *query; PLpgSQL_expr *query;
...@@ -577,8 +575,7 @@ typedef struct PLpgSQL_stmt_forc ...@@ -577,8 +575,7 @@ typedef struct PLpgSQL_stmt_forc
PLpgSQL_stmt_type cmd_type; PLpgSQL_stmt_type cmd_type;
int lineno; int lineno;
char *label; char *label;
PLpgSQL_rec *rec; PLpgSQL_variable *var; /* Loop variable (record or row) */
PLpgSQL_row *row;
List *body; /* List of statements */ List *body; /* List of statements */
/* end of fields that must match PLpgSQL_stmt_forq */ /* end of fields that must match PLpgSQL_stmt_forq */
int curvar; int curvar;
...@@ -593,8 +590,7 @@ typedef struct PLpgSQL_stmt_dynfors ...@@ -593,8 +590,7 @@ typedef struct PLpgSQL_stmt_dynfors
PLpgSQL_stmt_type cmd_type; PLpgSQL_stmt_type cmd_type;
int lineno; int lineno;
char *label; char *label;
PLpgSQL_rec *rec; PLpgSQL_variable *var; /* Loop variable (record or row) */
PLpgSQL_row *row;
List *body; /* List of statements */ List *body; /* List of statements */
/* end of fields that must match PLpgSQL_stmt_forq */ /* end of fields that must match PLpgSQL_stmt_forq */
PLpgSQL_expr *query; PLpgSQL_expr *query;
...@@ -624,7 +620,6 @@ typedef struct PLpgSQL_stmt_open ...@@ -624,7 +620,6 @@ typedef struct PLpgSQL_stmt_open
int lineno; int lineno;
int curvar; int curvar;
int cursor_options; int cursor_options;
PLpgSQL_row *returntype;
PLpgSQL_expr *argquery; PLpgSQL_expr *argquery;
PLpgSQL_expr *query; PLpgSQL_expr *query;
PLpgSQL_expr *dynquery; PLpgSQL_expr *dynquery;
...@@ -638,8 +633,7 @@ typedef struct PLpgSQL_stmt_fetch ...@@ -638,8 +633,7 @@ typedef struct PLpgSQL_stmt_fetch
{ {
PLpgSQL_stmt_type cmd_type; PLpgSQL_stmt_type cmd_type;
int lineno; int lineno;
PLpgSQL_rec *rec; /* target, as record or row */ PLpgSQL_variable *target; /* target (record or row) */
PLpgSQL_row *row;
int curvar; /* cursor variable to fetch from */ int curvar; /* cursor variable to fetch from */
FetchDirection direction; /* fetch direction */ FetchDirection direction; /* fetch direction */
long how_many; /* count, if constant (expr is NULL) */ long how_many; /* count, if constant (expr is NULL) */
...@@ -750,8 +744,7 @@ typedef struct PLpgSQL_stmt_execsql ...@@ -750,8 +744,7 @@ typedef struct PLpgSQL_stmt_execsql
* mod_stmt is set when we plan the query */ * mod_stmt is set when we plan the query */
bool into; /* INTO supplied? */ bool into; /* INTO supplied? */
bool strict; /* INTO STRICT flag */ bool strict; /* INTO STRICT flag */
PLpgSQL_rec *rec; /* INTO target, if record */ PLpgSQL_variable *target; /* INTO target (record or row) */
PLpgSQL_row *row; /* INTO target, if row */
} PLpgSQL_stmt_execsql; } PLpgSQL_stmt_execsql;
/* /*
...@@ -764,8 +757,7 @@ typedef struct PLpgSQL_stmt_dynexecute ...@@ -764,8 +757,7 @@ typedef struct PLpgSQL_stmt_dynexecute
PLpgSQL_expr *query; /* string expression */ PLpgSQL_expr *query; /* string expression */
bool into; /* INTO supplied? */ bool into; /* INTO supplied? */
bool strict; /* INTO STRICT flag */ bool strict; /* INTO STRICT flag */
PLpgSQL_rec *rec; /* INTO target, if record */ PLpgSQL_variable *target; /* INTO target (record or row) */
PLpgSQL_row *row; /* INTO target, if row */
List *params; /* USING expressions */ List *params; /* USING expressions */
} PLpgSQL_stmt_dynexecute; } PLpgSQL_stmt_dynexecute;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment