mirror of
https://github.com/postgres/postgres.git
synced 2025-07-02 09:02:37 +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:
@ -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;
|
||||
|
@ -15,7 +15,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/executor/execTuples.c,v 1.76 2004/04/01 21:28:44 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/executor/execTuples.c,v 1.77 2004/05/10 22:44:44 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -111,6 +111,7 @@
|
||||
#include "access/heapam.h"
|
||||
#include "catalog/pg_type.h"
|
||||
#include "executor/executor.h"
|
||||
#include "parser/parse_expr.h"
|
||||
#include "utils/lsyscache.h"
|
||||
#include "utils/typcache.h"
|
||||
|
||||
@ -118,6 +119,7 @@
|
||||
static TupleDesc ExecTypeFromTLInternal(List *targetList,
|
||||
bool hasoid, bool skipjunk);
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* tuple table create/delete functions
|
||||
* ----------------------------------------------------------------
|
||||
@ -595,6 +597,38 @@ ExecTypeFromTLInternal(List *targetList, bool hasoid, bool skipjunk)
|
||||
return typeInfo;
|
||||
}
|
||||
|
||||
/*
|
||||
* ExecTypeFromExprList - build a tuple descriptor from a list of Exprs
|
||||
*
|
||||
* Here we must make up an arbitrary set of field names.
|
||||
*/
|
||||
TupleDesc
|
||||
ExecTypeFromExprList(List *exprList)
|
||||
{
|
||||
TupleDesc typeInfo;
|
||||
List *l;
|
||||
int cur_resno = 1;
|
||||
char fldname[NAMEDATALEN];
|
||||
|
||||
typeInfo = CreateTemplateTupleDesc(length(exprList), false);
|
||||
|
||||
foreach(l, exprList)
|
||||
{
|
||||
Node *e = lfirst(l);
|
||||
|
||||
sprintf(fldname, "f%d", cur_resno);
|
||||
|
||||
TupleDescInitEntry(typeInfo,
|
||||
cur_resno++,
|
||||
fldname,
|
||||
exprType(e),
|
||||
exprTypmod(e),
|
||||
0);
|
||||
}
|
||||
|
||||
return typeInfo;
|
||||
}
|
||||
|
||||
/*
|
||||
* BlessTupleDesc - make a completed tuple descriptor useful for SRFs
|
||||
*
|
||||
|
Reference in New Issue
Block a user