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,
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);
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);
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)
{
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)
(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
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
{
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 */
{
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)
(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
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
{
}
/* 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);
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)
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;
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
* 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);
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
{
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;
}
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
{
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;
}
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
*/
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
/*
* 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);
/*
*/
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
*/
* 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;
*/
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);
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);
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");
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;
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;
}
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;
}
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)
{
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)
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,
char *name;
int lineno;
PLpgSQL_datum *scalar;
- PLpgSQL_rec *rec;
- PLpgSQL_row *row;
+ PLpgSQL_datum *row;
} forvariable;
struct
{
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
{
"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;
}
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
{
{
$$.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
$$.name = $1.ident;
$$.lineno = plpgsql_location_to_lineno(@1);
$$.scalar = NULL;
- $$.rec = NULL;
$$.row = NULL;
/* check for comma-separated list */
tok = yylex();
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)
{
new->query = expr;
new->into = false;
new->strict = false;
- new->rec = NULL;
- new->row = NULL;
+ new->target = NULL;
new->params = NIL;
/*
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)
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");
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;
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;
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;
}
}
execsql->sqlstmt = expr;
execsql->into = have_into;
execsql->strict = have_strict;
- execsql->rec = rec;
- execsql->row = row;
+ execsql->target = target;
return (PLpgSQL_stmt *) execsql;
}
* 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;
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,
}
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;