1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-30 21:42:05 +03:00

Promote row expressions to full-fledged citizens of the expression syntax,

rather than allowing them only in a few special cases as before.  In
particular you can now pass a ROW() construct to a function that accepts
a rowtype parameter.  Internal generation of RowExprs fixes a number of
corner cases that used to not work very well, such as referencing the
whole-row result of a JOIN or subquery.  This represents a further step in
the work I started a month or so back to make rowtype values into
first-class citizens.
This commit is contained in:
Tom Lane
2004-05-10 22:44:49 +00:00
parent 9a939886ac
commit 2f63232d30
34 changed files with 1281 additions and 551 deletions

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.158 2004/04/01 21:28:44 tgl Exp $
* $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.159 2004/05/10 22:44:43 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -42,6 +42,7 @@
#include "executor/execdebug.h"
#include "executor/functions.h"
#include "executor/nodeSubplan.h"
#include "funcapi.h"
#include "miscadmin.h"
#include "optimizer/planmain.h"
#include "parser/parse_expr.h"
@ -93,6 +94,9 @@ static Datum ExecEvalCaseTestExpr(ExprState *exprstate,
static Datum ExecEvalArray(ArrayExprState *astate,
ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone);
static Datum ExecEvalRow(RowExprState *rstate,
ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone);
static Datum ExecEvalCoalesce(CoalesceExprState *coalesceExpr,
ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone);
@ -2101,6 +2105,54 @@ ExecEvalArray(ArrayExprState *astate, ExprContext *econtext,
return PointerGetDatum(result);
}
/* ----------------------------------------------------------------
* ExecEvalRow - ROW() expressions
* ----------------------------------------------------------------
*/
static Datum
ExecEvalRow(RowExprState *rstate,
ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone)
{
HeapTuple tuple;
Datum *values;
char *nulls;
int nargs;
List *arg;
int i;
/* Set default values for result flags: non-null, not a set result */
*isNull = false;
if (isDone)
*isDone = ExprSingleResult;
/* Allocate workspace */
nargs = length(rstate->args);
if (nargs == 0) /* avoid palloc(0) if no fields */
nargs = 1;
values = (Datum *) palloc(nargs * sizeof(Datum));
nulls = (char *) palloc(nargs * sizeof(char));
/* Evaluate field values */
i = 0;
foreach(arg, rstate->args)
{
ExprState *e = (ExprState *) lfirst(arg);
bool eisnull;
values[i] = ExecEvalExpr(e, econtext, &eisnull, NULL);
nulls[i] = eisnull ? 'n' : ' ';
i++;
}
tuple = heap_formtuple(rstate->tupdesc, values, nulls);
pfree(values);
pfree(nulls);
return HeapTupleGetDatum(tuple);
}
/* ----------------------------------------------------------------
* ExecEvalCoalesce
* ----------------------------------------------------------------
@ -2822,6 +2874,39 @@ ExecInitExpr(Expr *node, PlanState *parent)
state = (ExprState *) astate;
}
break;
case T_RowExpr:
{
RowExpr *rowexpr = (RowExpr *) node;
RowExprState *rstate = makeNode(RowExprState);
List *outlist;
List *inlist;
rstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalRow;
outlist = NIL;
foreach(inlist, rowexpr->args)
{
Expr *e = (Expr *) lfirst(inlist);
ExprState *estate;
estate = ExecInitExpr(e, parent);
outlist = lappend(outlist, estate);
}
rstate->args = outlist;
/* Build tupdesc to describe result tuples */
if (rowexpr->row_typeid == RECORDOID)
{
/* generic record, use runtime type assignment */
rstate->tupdesc = ExecTypeFromExprList(rowexpr->args);
rstate->tupdesc = BlessTupleDesc(rstate->tupdesc);
}
else
{
/* it's been cast to a named type, use that */
rstate->tupdesc = lookup_rowtype_tupdesc(rowexpr->row_typeid, -1);
}
state = (ExprState *) rstate;
}
break;
case T_CoalesceExpr:
{
CoalesceExpr *coalesceexpr = (CoalesceExpr *) node;