aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/execQual.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2004-05-10 22:44:49 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2004-05-10 22:44:49 +0000
commit2f63232d30ca64a8f2684af855230f23a701d371 (patch)
treeb7a7707d1ec9edf368780cd3f4a23755527c5884 /src/backend/executor/execQual.c
parent9a939886ac782cfee3cd5fdd1c58689163ed84be (diff)
downloadpostgresql-2f63232d30ca64a8f2684af855230f23a701d371.tar.gz
postgresql-2f63232d30ca64a8f2684af855230f23a701d371.zip
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.
Diffstat (limited to 'src/backend/executor/execQual.c')
-rw-r--r--src/backend/executor/execQual.c87
1 files changed, 86 insertions, 1 deletions
diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c
index b27e86122bc..d44f580be02 100644
--- a/src/backend/executor/execQual.c
+++ b/src/backend/executor/execQual.c
@@ -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);
@@ -2102,6 +2106,54 @@ ExecEvalArray(ArrayExprState *astate, ExprContext *econtext,
}
/* ----------------------------------------------------------------
+ * 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;