Commit 3a4f7dde authored by Tom Lane's avatar Tom Lane

Phase 3 of read-only-plans project: ExecInitExpr now builds expression

execution state trees, and ExecEvalExpr takes an expression state tree
not an expression plan tree.  The plan tree is now read-only as far as
the executor is concerned.  Next step is to begin actually exploiting
this property.
parent 77b7a740
...@@ -25,7 +25,6 @@ ...@@ -25,7 +25,6 @@
#include "catalog/pg_proc.h" #include "catalog/pg_proc.h"
#include "catalog/pg_type.h" #include "catalog/pg_type.h"
#include "executor/executor.h" #include "executor/executor.h"
#include "utils/fcache.h"
#include "utils/sets.h" #include "utils/sets.h"
#include "utils/syscache.h" #include "utils/syscache.h"
#include "access/tupmacs.h" #include "access/tupmacs.h"
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.145 2002/11/14 23:53:27 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.146 2002/12/13 19:45:45 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include "catalog/catname.h" #include "catalog/catname.h"
#include "catalog/index.h" #include "catalog/index.h"
#include "catalog/pg_type.h" #include "catalog/pg_type.h"
#include "executor/executor.h"
#include "libpq/pqsignal.h" #include "libpq/pqsignal.h"
#include "miscadmin.h" #include "miscadmin.h"
#include "storage/ipc.h" #include "storage/ipc.h"
...@@ -1142,6 +1143,8 @@ index_register(Oid heap, ...@@ -1142,6 +1143,8 @@ index_register(Oid heap,
/* predicate will likely be null, but may as well copy it */ /* predicate will likely be null, but may as well copy it */
newind->il_info->ii_Predicate = (List *) newind->il_info->ii_Predicate = (List *)
copyObject(indexInfo->ii_Predicate); copyObject(indexInfo->ii_Predicate);
newind->il_info->ii_PredicateState = (List *)
ExecInitExpr((Expr *) newind->il_info->ii_Predicate, NULL);
newind->il_next = ILHead; newind->il_next = ILHead;
ILHead = newind; ILHead = newind;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.206 2002/12/12 15:49:24 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.207 2002/12/13 19:45:47 tgl Exp $
* *
* *
* INTERFACE ROUTINES * INTERFACE ROUTINES
...@@ -912,6 +912,7 @@ BuildIndexInfo(Form_pg_index indexStruct) ...@@ -912,6 +912,7 @@ BuildIndexInfo(Form_pg_index indexStruct)
/* /*
* If partial index, convert predicate into expression nodetree * If partial index, convert predicate into expression nodetree
* and prepare an execution state nodetree for it
*/ */
if (VARSIZE(&indexStruct->indpred) > VARHDRSZ) if (VARSIZE(&indexStruct->indpred) > VARHDRSZ)
{ {
...@@ -921,10 +922,15 @@ BuildIndexInfo(Form_pg_index indexStruct) ...@@ -921,10 +922,15 @@ BuildIndexInfo(Form_pg_index indexStruct)
PointerGetDatum(&indexStruct->indpred))); PointerGetDatum(&indexStruct->indpred)));
ii->ii_Predicate = stringToNode(predString); ii->ii_Predicate = stringToNode(predString);
fix_opfuncids((Node *) ii->ii_Predicate); fix_opfuncids((Node *) ii->ii_Predicate);
ii->ii_PredicateState = (List *)
ExecInitExpr((Expr *) ii->ii_Predicate, NULL);
pfree(predString); pfree(predString);
} }
else else
{
ii->ii_Predicate = NIL; ii->ii_Predicate = NIL;
ii->ii_PredicateState = NIL;
}
/* Other info */ /* Other info */
ii->ii_Unique = indexStruct->indisunique; ii->ii_Unique = indexStruct->indisunique;
...@@ -1483,7 +1489,7 @@ IndexBuildHeapScan(Relation heapRelation, ...@@ -1483,7 +1489,7 @@ IndexBuildHeapScan(Relation heapRelation,
Datum attdata[INDEX_MAX_KEYS]; Datum attdata[INDEX_MAX_KEYS];
char nulls[INDEX_MAX_KEYS]; char nulls[INDEX_MAX_KEYS];
double reltuples; double reltuples;
List *predicate = indexInfo->ii_Predicate; List *predicate = indexInfo->ii_PredicateState;
TupleTable tupleTable; TupleTable tupleTable;
TupleTableSlot *slot; TupleTableSlot *slot;
ExprContext *econtext; ExprContext *econtext;
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.185 2002/12/12 15:49:24 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.186 2002/12/13 19:45:48 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -758,7 +758,7 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids, ...@@ -758,7 +758,7 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
num_defaults; num_defaults;
FmgrInfo *in_functions; FmgrInfo *in_functions;
Oid *elements; Oid *elements;
Node **constraintexprs; ExprState **constraintexprs;
bool hasConstraints = false; bool hasConstraints = false;
int i; int i;
List *cur; List *cur;
...@@ -772,7 +772,7 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids, ...@@ -772,7 +772,7 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
TupleTableSlot *slot; TupleTableSlot *slot;
bool file_has_oids; bool file_has_oids;
int *defmap; int *defmap;
Node **defexprs; /* array of default att expressions */ ExprState **defexprs; /* array of default att expressions */
ExprContext *econtext; /* used for ExecEvalExpr for default atts */ ExprContext *econtext; /* used for ExecEvalExpr for default atts */
MemoryContext oldcontext = CurrentMemoryContext; MemoryContext oldcontext = CurrentMemoryContext;
...@@ -812,8 +812,8 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids, ...@@ -812,8 +812,8 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
in_functions = (FmgrInfo *) palloc(num_phys_attrs * sizeof(FmgrInfo)); in_functions = (FmgrInfo *) palloc(num_phys_attrs * sizeof(FmgrInfo));
elements = (Oid *) palloc(num_phys_attrs * sizeof(Oid)); elements = (Oid *) palloc(num_phys_attrs * sizeof(Oid));
defmap = (int *) palloc(num_phys_attrs * sizeof(int)); defmap = (int *) palloc(num_phys_attrs * sizeof(int));
defexprs = (Node **) palloc(num_phys_attrs * sizeof(Node *)); defexprs = (ExprState **) palloc(num_phys_attrs * sizeof(ExprState *));
constraintexprs = (Node **) palloc0(num_phys_attrs * sizeof(Node *)); constraintexprs = (ExprState **) palloc0(num_phys_attrs * sizeof(ExprState *));
for (i = 0; i < num_phys_attrs; i++) for (i = 0; i < num_phys_attrs; i++)
{ {
...@@ -837,10 +837,12 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids, ...@@ -837,10 +837,12 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
{ {
/* attribute is NOT to be copied */ /* attribute is NOT to be copied */
/* use default value if one exists */ /* use default value if one exists */
defexprs[num_defaults] = build_column_default(rel, i + 1); Node *defexpr = build_column_default(rel, i + 1);
if (defexprs[num_defaults] != NULL)
if (defexpr != NULL)
{ {
fix_opfuncids(defexprs[num_defaults]); fix_opfuncids(defexpr);
defexprs[num_defaults] = ExecInitExpr((Expr *) defexpr, NULL);
defmap[num_defaults] = i; defmap[num_defaults] = i;
num_defaults++; num_defaults++;
} }
...@@ -872,7 +874,7 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids, ...@@ -872,7 +874,7 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
if (node != (Node *) prm) if (node != (Node *) prm)
{ {
fix_opfuncids(node); fix_opfuncids(node);
constraintexprs[i] = node; constraintexprs[i] = ExecInitExpr((Expr *) node, NULL);
hasConstraints = true; hasConstraints = true;
} }
} }
...@@ -1165,10 +1167,10 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids, ...@@ -1165,10 +1167,10 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
for (i = 0; i < num_phys_attrs; i++) for (i = 0; i < num_phys_attrs; i++)
{ {
Node *node = constraintexprs[i]; ExprState *exprstate = constraintexprs[i];
bool isnull; bool isnull;
if (node == NULL) if (exprstate == NULL)
continue; /* no constraint for this attr */ continue; /* no constraint for this attr */
/* Insert current row's value into the Param value */ /* Insert current row's value into the Param value */
...@@ -1180,7 +1182,7 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids, ...@@ -1180,7 +1182,7 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
* to replace the value (consider e.g. a timestamp precision * to replace the value (consider e.g. a timestamp precision
* restriction). * restriction).
*/ */
values[i] = ExecEvalExpr(node, econtext, values[i] = ExecEvalExpr(exprstate, econtext,
&isnull, NULL); &isnull, NULL);
nulls[i] = isnull ? 'n' : ' '; nulls[i] = isnull ? 'n' : ' ';
} }
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994-5, Regents of the University of California * Portions Copyright (c) 1994-5, Regents of the University of California
* *
* $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.96 2002/12/12 15:49:24 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.97 2002/12/13 19:45:49 tgl Exp $
* *
*/ */
...@@ -582,26 +582,24 @@ explain_outNode(StringInfo str, ...@@ -582,26 +582,24 @@ explain_outNode(StringInfo str,
if (plan->initPlan) if (plan->initPlan)
{ {
List *saved_rtable = es->rtable; List *saved_rtable = es->rtable;
List *pslist = planstate->initPlan;
List *lst; List *lst;
for (i = 0; i < indent; i++) for (i = 0; i < indent; i++)
appendStringInfo(str, " "); appendStringInfo(str, " ");
appendStringInfo(str, " InitPlan\n"); appendStringInfo(str, " InitPlan\n");
foreach(lst, plan->initPlan) foreach(lst, planstate->initPlan)
{ {
SubPlanExpr *subplan = (SubPlanExpr *) lfirst(lst); SubPlanExprState *sps = (SubPlanExprState *) lfirst(lst);
SubPlanState *subplanstate = (SubPlanState *) lfirst(pslist); SubPlanExpr *sp = (SubPlanExpr *) sps->xprstate.expr;
es->rtable = subplan->rtable; es->rtable = sp->rtable;
for (i = 0; i < indent; i++) for (i = 0; i < indent; i++)
appendStringInfo(str, " "); appendStringInfo(str, " ");
appendStringInfo(str, " -> "); appendStringInfo(str, " -> ");
explain_outNode(str, subplan->plan, explain_outNode(str, sp->plan,
subplanstate->planstate, sps->planstate,
NULL, NULL,
indent + 4, es); indent + 4, es);
pslist = lnext(pslist);
} }
es->rtable = saved_rtable; es->rtable = saved_rtable;
} }
...@@ -689,8 +687,8 @@ explain_outNode(StringInfo str, ...@@ -689,8 +687,8 @@ explain_outNode(StringInfo str,
appendStringInfo(str, " SubPlan\n"); appendStringInfo(str, " SubPlan\n");
foreach(lst, planstate->subPlan) foreach(lst, planstate->subPlan)
{ {
SubPlanState *sps = (SubPlanState *) lfirst(lst); SubPlanExprState *sps = (SubPlanExprState *) lfirst(lst);
SubPlanExpr *sp = (SubPlanExpr *) sps->ps.plan; SubPlanExpr *sp = (SubPlanExpr *) sps->xprstate.expr;
es->rtable = sp->rtable; es->rtable = sp->rtable;
for (i = 0; i < indent; i++) for (i = 0; i < indent; i++)
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.93 2002/12/12 15:49:24 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.94 2002/12/13 19:45:50 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include "catalog/pg_opclass.h" #include "catalog/pg_opclass.h"
#include "catalog/pg_proc.h" #include "catalog/pg_proc.h"
#include "commands/defrem.h" #include "commands/defrem.h"
#include "executor/executor.h"
#include "miscadmin.h" #include "miscadmin.h"
#include "optimizer/clauses.h" #include "optimizer/clauses.h"
#include "optimizer/planmain.h" #include "optimizer/planmain.h"
...@@ -172,6 +173,8 @@ DefineIndex(RangeVar *heapRelation, ...@@ -172,6 +173,8 @@ DefineIndex(RangeVar *heapRelation,
*/ */
indexInfo = makeNode(IndexInfo); indexInfo = makeNode(IndexInfo);
indexInfo->ii_Predicate = cnfPred; indexInfo->ii_Predicate = cnfPred;
indexInfo->ii_PredicateState = (List *)
ExecInitExpr((Expr *) cnfPred, NULL);
indexInfo->ii_FuncOid = InvalidOid; indexInfo->ii_FuncOid = InvalidOid;
indexInfo->ii_Unique = unique; indexInfo->ii_Unique = unique;
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Copyright (c) 2002, PostgreSQL Global Development Group * Copyright (c) 2002, PostgreSQL Global Development Group
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/prepare.c,v 1.9 2002/12/05 15:50:30 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/prepare.c,v 1.10 2002/12/13 19:45:51 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "commands/prepare.h" #include "commands/prepare.h"
#include "executor/executor.h" #include "executor/executor.h"
#include "utils/guc.h" #include "utils/guc.h"
#include "optimizer/planmain.h"
#include "optimizer/planner.h" #include "optimizer/planner.h"
#include "rewrite/rewriteHandler.h" #include "rewrite/rewriteHandler.h"
#include "tcop/pquery.h" #include "tcop/pquery.h"
...@@ -110,17 +111,22 @@ ExecuteQuery(ExecuteStmt *stmt, CommandDest outputDest) ...@@ -110,17 +111,22 @@ ExecuteQuery(ExecuteStmt *stmt, CommandDest outputDest)
{ {
int nargs = length(entry->argtype_list); int nargs = length(entry->argtype_list);
int i = 0; int i = 0;
List *exprstates;
ExprContext *econtext = MakeExprContext(NULL, CurrentMemoryContext); ExprContext *econtext = MakeExprContext(NULL, CurrentMemoryContext);
/* Parser should have caught this error, but check */ /* Parser should have caught this error, but check */
if (nargs != length(stmt->params)) if (nargs != length(stmt->params))
elog(ERROR, "ExecuteQuery: wrong number of arguments"); elog(ERROR, "ExecuteQuery: wrong number of arguments");
fix_opfuncids((Node *) stmt->params);
exprstates = (List *) ExecInitExpr((Expr *) stmt->params, NULL);
paramLI = (ParamListInfo) palloc0((nargs + 1) * sizeof(ParamListInfoData)); paramLI = (ParamListInfo) palloc0((nargs + 1) * sizeof(ParamListInfoData));
foreach(l, stmt->params) foreach(l, exprstates)
{ {
Node *n = lfirst(l); ExprState *n = lfirst(l);
bool isNull; bool isNull;
paramLI[i].value = ExecEvalExprSwitchContext(n, paramLI[i].value = ExecEvalExprSwitchContext(n,
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.59 2002/12/12 20:35:12 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.60 2002/12/13 19:45:51 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -2718,6 +2718,7 @@ AlterTableAddCheckConstraint(Relation rel, Constraint *constr) ...@@ -2718,6 +2718,7 @@ AlterTableAddCheckConstraint(Relation rel, Constraint *constr)
HeapTuple tuple; HeapTuple tuple;
RangeTblEntry *rte; RangeTblEntry *rte;
List *qual; List *qual;
List *qualstate;
Node *expr; Node *expr;
/* /*
...@@ -2769,6 +2770,9 @@ AlterTableAddCheckConstraint(Relation rel, Constraint *constr) ...@@ -2769,6 +2770,9 @@ AlterTableAddCheckConstraint(Relation rel, Constraint *constr)
qual = makeList1(expr); qual = makeList1(expr);
/* build execution state for qual */
qualstate = (List *) ExecInitExpr((Expr *) qual, NULL);
/* Make tuple slot to hold tuples */ /* Make tuple slot to hold tuples */
slot = MakeTupleTableSlot(); slot = MakeTupleTableSlot();
ExecSetSlotDescriptor(slot, RelationGetDescr(rel), false); ExecSetSlotDescriptor(slot, RelationGetDescr(rel), false);
...@@ -2783,7 +2787,7 @@ AlterTableAddCheckConstraint(Relation rel, Constraint *constr) ...@@ -2783,7 +2787,7 @@ AlterTableAddCheckConstraint(Relation rel, Constraint *constr)
while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL) while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
{ {
ExecStoreTuple(tuple, slot, InvalidBuffer, false); ExecStoreTuple(tuple, slot, InvalidBuffer, false);
if (!ExecQual(qual, econtext, true)) if (!ExecQual(qualstate, econtext, true))
{ {
successful = false; successful = false;
break; break;
...@@ -3820,6 +3824,7 @@ AlterTableCreateToastTable(Oid relOid, bool silent) ...@@ -3820,6 +3824,7 @@ AlterTableCreateToastTable(Oid relOid, bool silent)
indexInfo->ii_KeyAttrNumbers[0] = 1; indexInfo->ii_KeyAttrNumbers[0] = 1;
indexInfo->ii_KeyAttrNumbers[1] = 2; indexInfo->ii_KeyAttrNumbers[1] = 2;
indexInfo->ii_Predicate = NIL; indexInfo->ii_Predicate = NIL;
indexInfo->ii_PredicateState = NIL;
indexInfo->ii_FuncOid = InvalidOid; indexInfo->ii_FuncOid = InvalidOid;
indexInfo->ii_Unique = true; indexInfo->ii_Unique = true;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/typecmds.c,v 1.23 2002/12/12 20:35:12 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/typecmds.c,v 1.24 2002/12/13 19:45:52 tgl Exp $
* *
* DESCRIPTION * DESCRIPTION
* The "DefineFoo" routines take the parse tree and pick out the * The "DefineFoo" routines take the parse tree and pick out the
...@@ -1244,7 +1244,8 @@ AlterDomainAddConstraint(List *names, Node *newConstraint) ...@@ -1244,7 +1244,8 @@ AlterDomainAddConstraint(List *names, Node *newConstraint)
Form_pg_type typTup; Form_pg_type typTup;
ExprContext *econtext; ExprContext *econtext;
char *ccbin; char *ccbin;
Node *expr; Expr *expr;
ExprState *exprstate;
int counter = 0; int counter = 0;
Constraint *constr; Constraint *constr;
...@@ -1336,10 +1337,11 @@ AlterDomainAddConstraint(List *names, Node *newConstraint) ...@@ -1336,10 +1337,11 @@ AlterDomainAddConstraint(List *names, Node *newConstraint)
* Test all values stored in the attributes based on the domain * Test all values stored in the attributes based on the domain
* the constraint is being added to. * the constraint is being added to.
*/ */
expr = stringToNode(ccbin); expr = (Expr *) stringToNode(ccbin);
fix_opfuncids(expr); fix_opfuncids((Node *) expr);
exprstate = ExecInitExpr(expr, NULL);
/* Make an expression context for ExecQual */ /* Make an expression context for ExecEvalExpr */
econtext = MakeExprContext(NULL, CurrentMemoryContext); econtext = MakeExprContext(NULL, CurrentMemoryContext);
rels = get_rels_with_domain(domainoid); rels = get_rels_with_domain(domainoid);
...@@ -1375,7 +1377,7 @@ AlterDomainAddConstraint(List *names, Node *newConstraint) ...@@ -1375,7 +1377,7 @@ AlterDomainAddConstraint(List *names, Node *newConstraint)
econtext->domainValue_datum = d; econtext->domainValue_datum = d;
econtext->domainValue_isNull = isNull; econtext->domainValue_isNull = isNull;
conResult = ExecEvalExpr(expr, econtext, &isNull, NULL); conResult = ExecEvalExpr(exprstate, econtext, &isNull, NULL);
if (!isNull && !DatumGetBool(conResult)) if (!isNull && !DatumGetBool(conResult))
elog(ERROR, "AlterDomainAddConstraint: Domain %s constraint %s failed", elog(ERROR, "AlterDomainAddConstraint: Domain %s constraint %s failed",
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Header: /cvsroot/pgsql/src/backend/executor/execAmi.c,v 1.66 2002/12/05 15:50:30 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/execAmi.c,v 1.67 2002/12/13 19:45:52 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -61,17 +61,19 @@ ExecReScan(PlanState *node, ExprContext *exprCtxt) ...@@ -61,17 +61,19 @@ ExecReScan(PlanState *node, ExprContext *exprCtxt)
foreach(lst, node->initPlan) foreach(lst, node->initPlan)
{ {
PlanState *splan = ((SubPlanState *) lfirst(lst))->planstate; SubPlanExprState *sstate = (SubPlanExprState *) lfirst(lst);
PlanState *splan = sstate->planstate;
if (splan->plan->extParam != NIL) /* don't care about child if (splan->plan->extParam != NIL) /* don't care about child
* locParam */ * locParam */
SetChangedParamList(splan, node->chgParam); SetChangedParamList(splan, node->chgParam);
if (splan->chgParam != NIL) if (splan->chgParam != NIL)
ExecReScanSetParamPlan((SubPlanState *) lfirst(lst), node); ExecReScanSetParamPlan(sstate, node);
} }
foreach(lst, node->subPlan) foreach(lst, node->subPlan)
{ {
PlanState *splan = ((SubPlanState *) lfirst(lst))->planstate; SubPlanExprState *sstate = (SubPlanExprState *) lfirst(lst);
PlanState *splan = sstate->planstate;
if (splan->plan->extParam != NIL) if (splan->plan->extParam != NIL)
SetChangedParamList(splan, node->chgParam); SetChangedParamList(splan, node->chgParam);
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.191 2002/12/12 15:49:24 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.192 2002/12/13 19:45:52 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1543,7 +1543,8 @@ ExecRelCheck(ResultRelInfo *resultRelInfo, ...@@ -1543,7 +1543,8 @@ ExecRelCheck(ResultRelInfo *resultRelInfo,
{ {
qual = (List *) stringToNode(check[i].ccbin); qual = (List *) stringToNode(check[i].ccbin);
fix_opfuncids((Node *) qual); fix_opfuncids((Node *) qual);
resultRelInfo->ri_ConstraintExprs[i] = qual; resultRelInfo->ri_ConstraintExprs[i] = (List *)
ExecInitExpr((Expr *) qual, NULL);
} }
MemoryContextSwitchTo(oldContext); MemoryContextSwitchTo(oldContext);
} }
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/execProcnode.c,v 1.32 2002/12/12 15:49:24 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/execProcnode.c,v 1.33 2002/12/13 19:45:52 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -229,23 +229,29 @@ ExecInitNode(Plan *node, EState *estate) ...@@ -229,23 +229,29 @@ ExecInitNode(Plan *node, EState *estate)
foreach(subp, node->initPlan) foreach(subp, node->initPlan)
{ {
SubPlanExpr *subplan = (SubPlanExpr *) lfirst(subp); SubPlanExpr *subplan = (SubPlanExpr *) lfirst(subp);
SubPlanExprState *sstate;
Assert(IsA(subplan, SubPlanExpr)); Assert(IsA(subplan, SubPlanExpr));
subps = lappend(subps, ExecInitSubPlan(subplan, estate)); sstate = ExecInitExprInitPlan(subplan, result);
ExecInitSubPlan(sstate, estate);
subps = lappend(subps, sstate);
} }
result->initPlan = subps; result->initPlan = subps;
/* /*
* Initialize any subPlans present in this node. These were found * Initialize any subPlans present in this node. These were found
* by ExecInitExpr during initialization of the PlanState. * by ExecInitExpr during initialization of the PlanState. Note we
* must do this after initializing initPlans, in case their arguments
* contain subPlans (is that actually possible? perhaps not).
*/ */
subps = NIL; subps = NIL;
foreach(subp, result->subPlan) foreach(subp, result->subPlan)
{ {
SubPlanExpr *subplan = (SubPlanExpr *) lfirst(subp); SubPlanExprState *sstate = (SubPlanExprState *) lfirst(subp);
Assert(IsA(subplan, SubPlanExpr)); Assert(IsA(sstate, SubPlanExprState));
subps = lappend(subps, ExecInitSubPlan(subplan, estate)); ExecInitSubPlan(sstate, estate);
subps = lappend(subps, sstate);
} }
result->subPlan = subps; result->subPlan = subps;
...@@ -492,14 +498,11 @@ ExecEndNode(PlanState *node) ...@@ -492,14 +498,11 @@ ExecEndNode(PlanState *node)
if (node == NULL) if (node == NULL)
return; return;
if (node->instrument)
InstrEndLoop(node->instrument);
/* Clean up initPlans and subPlans */ /* Clean up initPlans and subPlans */
foreach(subp, node->initPlan) foreach(subp, node->initPlan)
ExecEndSubPlan((SubPlanState *) lfirst(subp)); ExecEndSubPlan((SubPlanExprState *) lfirst(subp));
foreach(subp, node->subPlan) foreach(subp, node->subPlan)
ExecEndSubPlan((SubPlanState *) lfirst(subp)); ExecEndSubPlan((SubPlanExprState *) lfirst(subp));
if (node->chgParam != NIL) if (node->chgParam != NIL)
{ {
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.118 2002/12/12 20:35:12 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.119 2002/12/13 19:45:52 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -41,43 +41,52 @@ ...@@ -41,43 +41,52 @@
#include "executor/nodeSubplan.h" #include "executor/nodeSubplan.h"
#include "miscadmin.h" #include "miscadmin.h"
#include "parser/parse_expr.h" #include "parser/parse_expr.h"
#include "utils/acl.h"
#include "utils/array.h" #include "utils/array.h"
#include "utils/builtins.h" #include "utils/builtins.h"
#include "utils/fcache.h"
#include "utils/lsyscache.h" #include "utils/lsyscache.h"
/* static function decls */ /* static function decls */
static Datum ExecEvalAggref(Aggref *aggref, ExprContext *econtext, static Datum ExecEvalAggref(AggrefExprState *aggref,
ExprContext *econtext,
bool *isNull); bool *isNull);
static Datum ExecEvalArrayRef(ArrayRef *arrayRef, ExprContext *econtext, static Datum ExecEvalArrayRef(ArrayRefExprState *astate,
ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone); bool *isNull, ExprDoneCond *isDone);
static Datum ExecEvalVar(Var *variable, ExprContext *econtext, bool *isNull); static Datum ExecEvalVar(Var *variable, ExprContext *econtext, bool *isNull);
static Datum ExecEvalOper(OpExpr *op, ExprContext *econtext, static Datum ExecEvalParam(Param *expression, ExprContext *econtext,
bool *isNull);
static Datum ExecEvalFunc(FuncExprState *fcache, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone); bool *isNull, ExprDoneCond *isDone);
static Datum ExecEvalDistinct(DistinctExpr *op, ExprContext *econtext, static Datum ExecEvalOper(FuncExprState *fcache, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone); bool *isNull, ExprDoneCond *isDone);
static Datum ExecEvalFunc(FuncExpr *func, ExprContext *econtext, static Datum ExecEvalDistinct(FuncExprState *fcache, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone); bool *isNull, ExprDoneCond *isDone);
static ExprDoneCond ExecEvalFuncArgs(FunctionCallInfo fcinfo, static ExprDoneCond ExecEvalFuncArgs(FunctionCallInfo fcinfo,
List *argList, ExprContext *econtext); List *argList, ExprContext *econtext);
static Datum ExecEvalNot(BoolExpr *notclause, ExprContext *econtext, static Datum ExecEvalNot(BoolExprState *notclause, ExprContext *econtext,
bool *isNull); bool *isNull);
static Datum ExecEvalOr(BoolExpr *orExpr, ExprContext *econtext, static Datum ExecEvalOr(BoolExprState *orExpr, ExprContext *econtext,
bool *isNull); bool *isNull);
static Datum ExecEvalAnd(BoolExpr *andExpr, ExprContext *econtext, static Datum ExecEvalAnd(BoolExprState *andExpr, ExprContext *econtext,
bool *isNull); bool *isNull);
static Datum ExecEvalCase(CaseExpr *caseExpr, ExprContext *econtext, static Datum ExecEvalCase(CaseExprState *caseExpr, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone); bool *isNull, ExprDoneCond *isDone);
static Datum ExecEvalNullTest(NullTest *ntest, ExprContext *econtext, static Datum ExecEvalNullTest(GenericExprState *nstate,
ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone); bool *isNull, ExprDoneCond *isDone);
static Datum ExecEvalBooleanTest(BooleanTest *btest, ExprContext *econtext, static Datum ExecEvalBooleanTest(GenericExprState *bstate,
ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone); bool *isNull, ExprDoneCond *isDone);
static Datum ExecEvalConstraintTest(ConstraintTest *constraint, static Datum ExecEvalConstraintTest(ConstraintTestState *cstate,
ExprContext *econtext, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone); bool *isNull, ExprDoneCond *isDone);
static Datum ExecEvalConstraintTestValue(ConstraintTestValue *conVal, static Datum ExecEvalConstraintTestValue(ConstraintTestValue *conVal,
ExprContext *econtext, bool *isNull); ExprContext *econtext, bool *isNull);
static Datum ExecEvalFieldSelect(GenericExprState *fstate,
ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone);
/*---------- /*----------
...@@ -106,11 +115,12 @@ static Datum ExecEvalConstraintTestValue(ConstraintTestValue *conVal, ...@@ -106,11 +115,12 @@ static Datum ExecEvalConstraintTestValue(ConstraintTestValue *conVal,
*---------- *----------
*/ */
static Datum static Datum
ExecEvalArrayRef(ArrayRef *arrayRef, ExecEvalArrayRef(ArrayRefExprState *astate,
ExprContext *econtext, ExprContext *econtext,
bool *isNull, bool *isNull,
ExprDoneCond *isDone) ExprDoneCond *isDone)
{ {
ArrayRef *arrayRef = (ArrayRef *) astate->xprstate.expr;
ArrayType *array_source; ArrayType *array_source;
ArrayType *resultArray; ArrayType *resultArray;
bool isAssignment = (arrayRef->refassgnexpr != NULL); bool isAssignment = (arrayRef->refassgnexpr != NULL);
...@@ -124,7 +134,7 @@ ExecEvalArrayRef(ArrayRef *arrayRef, ...@@ -124,7 +134,7 @@ ExecEvalArrayRef(ArrayRef *arrayRef,
if (arrayRef->refexpr != NULL) if (arrayRef->refexpr != NULL)
{ {
array_source = (ArrayType *) array_source = (ArrayType *)
DatumGetPointer(ExecEvalExpr((Node *) arrayRef->refexpr, DatumGetPointer(ExecEvalExpr(astate->refexpr,
econtext, econtext,
isNull, isNull,
isDone)); isDone));
...@@ -150,13 +160,13 @@ ExecEvalArrayRef(ArrayRef *arrayRef, ...@@ -150,13 +160,13 @@ ExecEvalArrayRef(ArrayRef *arrayRef,
array_source = NULL; array_source = NULL;
} }
foreach(elt, arrayRef->refupperindexpr) foreach(elt, astate->refupperindexpr)
{ {
if (i >= MAXDIM) if (i >= MAXDIM)
elog(ERROR, "ExecEvalArrayRef: can only handle %d dimensions", elog(ERROR, "ExecEvalArrayRef: can only handle %d dimensions",
MAXDIM); MAXDIM);
upper.indx[i++] = DatumGetInt32(ExecEvalExpr((Node *) lfirst(elt), upper.indx[i++] = DatumGetInt32(ExecEvalExpr((ExprState *) lfirst(elt),
econtext, econtext,
isNull, isNull,
NULL)); NULL));
...@@ -170,15 +180,15 @@ ExecEvalArrayRef(ArrayRef *arrayRef, ...@@ -170,15 +180,15 @@ ExecEvalArrayRef(ArrayRef *arrayRef,
} }
} }
if (arrayRef->reflowerindexpr != NIL) if (astate->reflowerindexpr != NIL)
{ {
foreach(elt, arrayRef->reflowerindexpr) foreach(elt, astate->reflowerindexpr)
{ {
if (j >= MAXDIM) if (j >= MAXDIM)
elog(ERROR, "ExecEvalArrayRef: can only handle %d dimensions", elog(ERROR, "ExecEvalArrayRef: can only handle %d dimensions",
MAXDIM); MAXDIM);
lower.indx[j++] = DatumGetInt32(ExecEvalExpr((Node *) lfirst(elt), lower.indx[j++] = DatumGetInt32(ExecEvalExpr((ExprState *) lfirst(elt),
econtext, econtext,
isNull, isNull,
NULL)); NULL));
...@@ -205,7 +215,7 @@ ExecEvalArrayRef(ArrayRef *arrayRef, ...@@ -205,7 +215,7 @@ ExecEvalArrayRef(ArrayRef *arrayRef,
if (isAssignment) if (isAssignment)
{ {
Datum sourceData = ExecEvalExpr((Node *) arrayRef->refassgnexpr, Datum sourceData = ExecEvalExpr(astate->refassgnexpr,
econtext, econtext,
isNull, isNull,
NULL); NULL);
...@@ -275,7 +285,7 @@ ExecEvalArrayRef(ArrayRef *arrayRef, ...@@ -275,7 +285,7 @@ ExecEvalArrayRef(ArrayRef *arrayRef,
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
static Datum static Datum
ExecEvalAggref(Aggref *aggref, ExprContext *econtext, bool *isNull) ExecEvalAggref(AggrefExprState *aggref, ExprContext *econtext, bool *isNull)
{ {
if (econtext->ecxt_aggvalues == NULL) /* safety check */ if (econtext->ecxt_aggvalues == NULL) /* safety check */
elog(ERROR, "ExecEvalAggref: no aggregates in this expression context"); elog(ERROR, "ExecEvalAggref: no aggregates in this expression context");
...@@ -403,7 +413,7 @@ ExecEvalVar(Var *variable, ExprContext *econtext, bool *isNull) ...@@ -403,7 +413,7 @@ ExecEvalVar(Var *variable, ExprContext *econtext, bool *isNull)
* (in which case we could return NULL)? -cim 10/13/89 * (in which case we could return NULL)? -cim 10/13/89
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
Datum static Datum
ExecEvalParam(Param *expression, ExprContext *econtext, bool *isNull) ExecEvalParam(Param *expression, ExprContext *econtext, bool *isNull)
{ {
int thisParamKind = expression->paramkind; int thisParamKind = expression->paramkind;
...@@ -574,6 +584,30 @@ GetAttributeByName(TupleTableSlot *slot, char *attname, bool *isNull) ...@@ -574,6 +584,30 @@ GetAttributeByName(TupleTableSlot *slot, char *attname, bool *isNull)
return retval; return retval;
} }
/*
* init_fcache - initialize a FuncExprState node during first use
*/
void
init_fcache(Oid foid, FuncExprState *fcache, MemoryContext fcacheCxt)
{
AclResult aclresult;
/* Check permission to call function */
aclresult = pg_proc_aclcheck(foid, GetUserId(), ACL_EXECUTE);
if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, get_func_name(foid));
/* Safety check (should never fail, as parser should check sooner) */
if (length(fcache->args) > FUNC_MAX_ARGS)
elog(ERROR, "init_fcache: too many arguments");
/* Set up the primary fmgr lookup information */
fmgr_info_cxt(foid, &(fcache->func), fcacheCxt);
/* Initialize additional info */
fcache->setArgsValid = false;
}
/* /*
* Evaluate arguments for a function. * Evaluate arguments for a function.
*/ */
...@@ -593,7 +627,7 @@ ExecEvalFuncArgs(FunctionCallInfo fcinfo, ...@@ -593,7 +627,7 @@ ExecEvalFuncArgs(FunctionCallInfo fcinfo,
{ {
ExprDoneCond thisArgIsDone; ExprDoneCond thisArgIsDone;
fcinfo->arg[i] = ExecEvalExpr((Node *) lfirst(arg), fcinfo->arg[i] = ExecEvalExpr((ExprState *) lfirst(arg),
econtext, econtext,
&fcinfo->argnull[i], &fcinfo->argnull[i],
&thisArgIsDone); &thisArgIsDone);
...@@ -624,12 +658,12 @@ ExecEvalFuncArgs(FunctionCallInfo fcinfo, ...@@ -624,12 +658,12 @@ ExecEvalFuncArgs(FunctionCallInfo fcinfo,
* Evaluate the arguments to a function and then the function itself. * Evaluate the arguments to a function and then the function itself.
*/ */
Datum Datum
ExecMakeFunctionResult(FunctionCachePtr fcache, ExecMakeFunctionResult(FuncExprState *fcache,
List *arguments,
ExprContext *econtext, ExprContext *econtext,
bool *isNull, bool *isNull,
ExprDoneCond *isDone) ExprDoneCond *isDone)
{ {
List *arguments = fcache->args;
Datum result; Datum result;
FunctionCallInfoData fcinfo; FunctionCallInfoData fcinfo;
ReturnSetInfo rsinfo; /* for functions returning sets */ ReturnSetInfo rsinfo; /* for functions returning sets */
...@@ -823,7 +857,7 @@ ExecMakeFunctionResult(FunctionCachePtr fcache, ...@@ -823,7 +857,7 @@ ExecMakeFunctionResult(FunctionCachePtr fcache,
* object. (If function returns an empty set, we just return NULL instead.) * object. (If function returns an empty set, we just return NULL instead.)
*/ */
Tuplestorestate * Tuplestorestate *
ExecMakeTableFunctionResult(Node *funcexpr, ExecMakeTableFunctionResult(ExprState *funcexpr,
ExprContext *econtext, ExprContext *econtext,
TupleDesc expectedDesc, TupleDesc expectedDesc,
TupleDesc *returnDesc) TupleDesc *returnDesc)
...@@ -841,7 +875,7 @@ ExecMakeTableFunctionResult(Node *funcexpr, ...@@ -841,7 +875,7 @@ ExecMakeTableFunctionResult(Node *funcexpr,
bool returnsTuple = false; bool returnsTuple = false;
/* /*
* Normally the passed expression tree will be a FuncExpr, since the * Normally the passed expression tree will be a FuncExprState, since the
* grammar only allows a function call at the top level of a table * grammar only allows a function call at the top level of a table
* function reference. However, if the function doesn't return set then * function reference. However, if the function doesn't return set then
* the planner might have replaced the function call via constant-folding * the planner might have replaced the function call via constant-folding
...@@ -850,11 +884,10 @@ ExecMakeTableFunctionResult(Node *funcexpr, ...@@ -850,11 +884,10 @@ ExecMakeTableFunctionResult(Node *funcexpr,
* we don't get a chance to pass a special ReturnSetInfo to any functions * we don't get a chance to pass a special ReturnSetInfo to any functions
* buried in the expression. * buried in the expression.
*/ */
if (funcexpr && IsA(funcexpr, FuncExpr)) if (funcexpr && IsA(funcexpr, FuncExprState) &&
IsA(funcexpr->expr, FuncExpr))
{ {
FuncExpr *func = (FuncExpr *) funcexpr; FuncExprState *fcache = (FuncExprState *) funcexpr;
List *argList;
FunctionCachePtr fcache;
ExprDoneCond argDone; ExprDoneCond argDone;
/* /*
...@@ -862,19 +895,14 @@ ExecMakeTableFunctionResult(Node *funcexpr, ...@@ -862,19 +895,14 @@ ExecMakeTableFunctionResult(Node *funcexpr,
*/ */
direct_function_call = true; direct_function_call = true;
funcrettype = func->funcresulttype;
argList = func->args;
/* /*
* get the fcache from the FuncExpr node. If it is NULL, then * Initialize function cache if first time through
* initialize it
*/ */
fcache = func->func_fcache; if (fcache->func.fn_oid == InvalidOid)
if (fcache == NULL)
{ {
fcache = init_fcache(func->funcid, length(argList), FuncExpr *func = (FuncExpr *) fcache->xprstate.expr;
econtext->ecxt_per_query_memory);
func->func_fcache = fcache; init_fcache(func->funcid, fcache, econtext->ecxt_per_query_memory);
} }
/* /*
...@@ -887,7 +915,7 @@ ExecMakeTableFunctionResult(Node *funcexpr, ...@@ -887,7 +915,7 @@ ExecMakeTableFunctionResult(Node *funcexpr,
*/ */
MemSet(&fcinfo, 0, sizeof(fcinfo)); MemSet(&fcinfo, 0, sizeof(fcinfo));
fcinfo.flinfo = &(fcache->func); fcinfo.flinfo = &(fcache->func);
argDone = ExecEvalFuncArgs(&fcinfo, argList, econtext); argDone = ExecEvalFuncArgs(&fcinfo, fcache->args, econtext);
/* We don't allow sets in the arguments of the table function */ /* We don't allow sets in the arguments of the table function */
if (argDone != ExprSingleResult) if (argDone != ExprSingleResult)
elog(ERROR, "Set-valued function called in context that cannot accept a set"); elog(ERROR, "Set-valued function called in context that cannot accept a set");
...@@ -914,9 +942,10 @@ ExecMakeTableFunctionResult(Node *funcexpr, ...@@ -914,9 +942,10 @@ ExecMakeTableFunctionResult(Node *funcexpr,
{ {
/* Treat funcexpr as a generic expression */ /* Treat funcexpr as a generic expression */
direct_function_call = false; direct_function_call = false;
funcrettype = exprType(funcexpr);
} }
funcrettype = exprType((Node *) funcexpr->expr);
/* /*
* Prepare a resultinfo node for communication. We always do this * Prepare a resultinfo node for communication. We always do this
* even if not expecting a set result, so that we can pass * even if not expecting a set result, so that we can pass
...@@ -1087,8 +1116,8 @@ ExecMakeTableFunctionResult(Node *funcexpr, ...@@ -1087,8 +1116,8 @@ ExecMakeTableFunctionResult(Node *funcexpr,
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
* ExecEvalOper
* ExecEvalFunc * ExecEvalFunc
* ExecEvalOper
* ExecEvalDistinct * ExecEvalDistinct
* *
* Evaluate the functional result of a list of arguments by calling the * Evaluate the functional result of a list of arguments by calling the
...@@ -1097,80 +1126,49 @@ ExecMakeTableFunctionResult(Node *funcexpr, ...@@ -1097,80 +1126,49 @@ ExecMakeTableFunctionResult(Node *funcexpr,
*/ */
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
* ExecEvalOper * ExecEvalFunc
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
static Datum static Datum
ExecEvalOper(OpExpr *op, ExecEvalFunc(FuncExprState *fcache,
ExprContext *econtext, ExprContext *econtext,
bool *isNull, bool *isNull,
ExprDoneCond *isDone) ExprDoneCond *isDone)
{ {
List *argList;
FunctionCachePtr fcache;
/*
* we extract the oid of the function associated with the op and then
* pass the work onto ExecMakeFunctionResult which evaluates the
* arguments and returns the result of calling the function on the
* evaluated arguments.
*/
argList = op->args;
/* /*
* get the fcache from the OpExpr node. If it is NULL, then initialize * Initialize function cache if first time through
* it
*/ */
fcache = op->op_fcache; if (fcache->func.fn_oid == InvalidOid)
if (fcache == NULL)
{ {
fcache = init_fcache(op->opfuncid, length(argList), FuncExpr *func = (FuncExpr *) fcache->xprstate.expr;
econtext->ecxt_per_query_memory);
op->op_fcache = fcache; init_fcache(func->funcid, fcache, econtext->ecxt_per_query_memory);
} }
return ExecMakeFunctionResult(fcache, argList, econtext, return ExecMakeFunctionResult(fcache, econtext, isNull, isDone);
isNull, isDone);
} }
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
* ExecEvalFunc * ExecEvalOper
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
static Datum static Datum
ExecEvalFunc(FuncExpr *func, ExecEvalOper(FuncExprState *fcache,
ExprContext *econtext, ExprContext *econtext,
bool *isNull, bool *isNull,
ExprDoneCond *isDone) ExprDoneCond *isDone)
{ {
List *argList;
FunctionCachePtr fcache;
/* /*
* we extract the oid of the function associated with the func node * Initialize function cache if first time through
* and then pass the work onto ExecMakeFunctionResult which evaluates
* the arguments and returns the result of calling the function on the
* evaluated arguments.
*
* this is nearly identical to the ExecEvalOper code.
*/
argList = func->args;
/*
* get the fcache from the FuncExpr node. If it is NULL, then initialize
* it
*/ */
fcache = func->func_fcache; if (fcache->func.fn_oid == InvalidOid)
if (fcache == NULL)
{ {
fcache = init_fcache(func->funcid, length(argList), OpExpr *op = (OpExpr *) fcache->xprstate.expr;
econtext->ecxt_per_query_memory);
func->func_fcache = fcache; init_fcache(op->opfuncid, fcache, econtext->ecxt_per_query_memory);
} }
return ExecMakeFunctionResult(fcache, argList, econtext, return ExecMakeFunctionResult(fcache, econtext, isNull, isDone);
isNull, isDone);
} }
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
...@@ -1185,34 +1183,31 @@ ExecEvalFunc(FuncExpr *func, ...@@ -1185,34 +1183,31 @@ ExecEvalFunc(FuncExpr *func,
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
static Datum static Datum
ExecEvalDistinct(DistinctExpr *op, ExecEvalDistinct(FuncExprState *fcache,
ExprContext *econtext, ExprContext *econtext,
bool *isNull, bool *isNull,
ExprDoneCond *isDone) ExprDoneCond *isDone)
{ {
Datum result; Datum result;
FunctionCachePtr fcache;
FunctionCallInfoData fcinfo; FunctionCallInfoData fcinfo;
ExprDoneCond argDone; ExprDoneCond argDone;
List *argList; List *argList;
/* /*
* extract info from op * Initialize function cache if first time through
*/ */
argList = op->args; if (fcache->func.fn_oid == InvalidOid)
{
DistinctExpr *op = (DistinctExpr *) fcache->xprstate.expr;
init_fcache(op->opfuncid, fcache, econtext->ecxt_per_query_memory);
Assert(!fcache->func.fn_retset);
}
/* /*
* get the fcache from the DistinctExpr node. If it is NULL, then * extract info from fcache
* initialize it
*/ */
fcache = op->op_fcache; argList = fcache->args;
if (fcache == NULL)
{
fcache = init_fcache(op->opfuncid, length(argList),
econtext->ecxt_per_query_memory);
op->op_fcache = fcache;
}
Assert(!fcache->func.fn_retset);
/* Need to prep callinfo structure */ /* Need to prep callinfo structure */
MemSet(&fcinfo, 0, sizeof(fcinfo)); MemSet(&fcinfo, 0, sizeof(fcinfo));
...@@ -1260,9 +1255,9 @@ ExecEvalDistinct(DistinctExpr *op, ...@@ -1260,9 +1255,9 @@ ExecEvalDistinct(DistinctExpr *op,
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
static Datum static Datum
ExecEvalNot(BoolExpr *notclause, ExprContext *econtext, bool *isNull) ExecEvalNot(BoolExprState *notclause, ExprContext *econtext, bool *isNull)
{ {
Node *clause; ExprState *clause;
Datum expr_value; Datum expr_value;
clause = lfirst(notclause->args); clause = lfirst(notclause->args);
...@@ -1288,7 +1283,7 @@ ExecEvalNot(BoolExpr *notclause, ExprContext *econtext, bool *isNull) ...@@ -1288,7 +1283,7 @@ ExecEvalNot(BoolExpr *notclause, ExprContext *econtext, bool *isNull)
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
static Datum static Datum
ExecEvalOr(BoolExpr *orExpr, ExprContext *econtext, bool *isNull) ExecEvalOr(BoolExprState *orExpr, ExprContext *econtext, bool *isNull)
{ {
List *clauses; List *clauses;
List *clause; List *clause;
...@@ -1314,7 +1309,7 @@ ExecEvalOr(BoolExpr *orExpr, ExprContext *econtext, bool *isNull) ...@@ -1314,7 +1309,7 @@ ExecEvalOr(BoolExpr *orExpr, ExprContext *econtext, bool *isNull)
*/ */
foreach(clause, clauses) foreach(clause, clauses)
{ {
clause_value = ExecEvalExpr((Node *) lfirst(clause), clause_value = ExecEvalExpr((ExprState *) lfirst(clause),
econtext, isNull, NULL); econtext, isNull, NULL);
/* /*
...@@ -1336,7 +1331,7 @@ ExecEvalOr(BoolExpr *orExpr, ExprContext *econtext, bool *isNull) ...@@ -1336,7 +1331,7 @@ ExecEvalOr(BoolExpr *orExpr, ExprContext *econtext, bool *isNull)
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
static Datum static Datum
ExecEvalAnd(BoolExpr *andExpr, ExprContext *econtext, bool *isNull) ExecEvalAnd(BoolExprState *andExpr, ExprContext *econtext, bool *isNull)
{ {
List *clauses; List *clauses;
List *clause; List *clause;
...@@ -1356,7 +1351,7 @@ ExecEvalAnd(BoolExpr *andExpr, ExprContext *econtext, bool *isNull) ...@@ -1356,7 +1351,7 @@ ExecEvalAnd(BoolExpr *andExpr, ExprContext *econtext, bool *isNull)
*/ */
foreach(clause, clauses) foreach(clause, clauses)
{ {
clause_value = ExecEvalExpr((Node *) lfirst(clause), clause_value = ExecEvalExpr((ExprState *) lfirst(clause),
econtext, isNull, NULL); econtext, isNull, NULL);
/* /*
...@@ -1383,7 +1378,7 @@ ExecEvalAnd(BoolExpr *andExpr, ExprContext *econtext, bool *isNull) ...@@ -1383,7 +1378,7 @@ ExecEvalAnd(BoolExpr *andExpr, ExprContext *econtext, bool *isNull)
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
static Datum static Datum
ExecEvalCase(CaseExpr *caseExpr, ExprContext *econtext, ExecEvalCase(CaseExprState *caseExpr, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone) bool *isNull, ExprDoneCond *isDone)
{ {
List *clauses; List *clauses;
...@@ -1399,9 +1394,9 @@ ExecEvalCase(CaseExpr *caseExpr, ExprContext *econtext, ...@@ -1399,9 +1394,9 @@ ExecEvalCase(CaseExpr *caseExpr, ExprContext *econtext,
*/ */
foreach(clause, clauses) foreach(clause, clauses)
{ {
CaseWhen *wclause = lfirst(clause); CaseWhenState *wclause = lfirst(clause);
clause_value = ExecEvalExpr((Node *) wclause->expr, clause_value = ExecEvalExpr(wclause->expr,
econtext, econtext,
isNull, isNull,
NULL); NULL);
...@@ -1413,7 +1408,7 @@ ExecEvalCase(CaseExpr *caseExpr, ExprContext *econtext, ...@@ -1413,7 +1408,7 @@ ExecEvalCase(CaseExpr *caseExpr, ExprContext *econtext,
*/ */
if (DatumGetBool(clause_value) && !*isNull) if (DatumGetBool(clause_value) && !*isNull)
{ {
return ExecEvalExpr((Node *) wclause->result, return ExecEvalExpr(wclause->result,
econtext, econtext,
isNull, isNull,
isDone); isDone);
...@@ -1422,7 +1417,7 @@ ExecEvalCase(CaseExpr *caseExpr, ExprContext *econtext, ...@@ -1422,7 +1417,7 @@ ExecEvalCase(CaseExpr *caseExpr, ExprContext *econtext,
if (caseExpr->defresult) if (caseExpr->defresult)
{ {
return ExecEvalExpr((Node *) caseExpr->defresult, return ExecEvalExpr(caseExpr->defresult,
econtext, econtext,
isNull, isNull,
isDone); isDone);
...@@ -1439,14 +1434,19 @@ ExecEvalCase(CaseExpr *caseExpr, ExprContext *econtext, ...@@ -1439,14 +1434,19 @@ ExecEvalCase(CaseExpr *caseExpr, ExprContext *econtext,
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
static Datum static Datum
ExecEvalNullTest(NullTest *ntest, ExecEvalNullTest(GenericExprState *nstate,
ExprContext *econtext, ExprContext *econtext,
bool *isNull, bool *isNull,
ExprDoneCond *isDone) ExprDoneCond *isDone)
{ {
NullTest *ntest = (NullTest *) nstate->xprstate.expr;
Datum result; Datum result;
result = ExecEvalExpr((Node *) ntest->arg, econtext, isNull, isDone); result = ExecEvalExpr(nstate->arg, econtext, isNull, isDone);
if (isDone && *isDone == ExprEndResult)
return result; /* nothing to check */
switch (ntest->nulltesttype) switch (ntest->nulltesttype)
{ {
case IS_NULL: case IS_NULL:
...@@ -1479,14 +1479,19 @@ ExecEvalNullTest(NullTest *ntest, ...@@ -1479,14 +1479,19 @@ ExecEvalNullTest(NullTest *ntest,
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
static Datum static Datum
ExecEvalBooleanTest(BooleanTest *btest, ExecEvalBooleanTest(GenericExprState *bstate,
ExprContext *econtext, ExprContext *econtext,
bool *isNull, bool *isNull,
ExprDoneCond *isDone) ExprDoneCond *isDone)
{ {
BooleanTest *btest = (BooleanTest *) bstate->xprstate.expr;
Datum result; Datum result;
result = ExecEvalExpr((Node *) btest->arg, econtext, isNull, isDone); result = ExecEvalExpr(bstate->arg, econtext, isNull, isDone);
if (isDone && *isDone == ExprEndResult)
return result; /* nothing to check */
switch (btest->booltesttype) switch (btest->booltesttype)
{ {
case IS_TRUE: case IS_TRUE:
...@@ -1560,12 +1565,13 @@ ExecEvalBooleanTest(BooleanTest *btest, ...@@ -1560,12 +1565,13 @@ ExecEvalBooleanTest(BooleanTest *btest,
* datum) otherwise throw an error. * datum) otherwise throw an error.
*/ */
static Datum static Datum
ExecEvalConstraintTest(ConstraintTest *constraint, ExprContext *econtext, ExecEvalConstraintTest(ConstraintTestState *cstate, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone) bool *isNull, ExprDoneCond *isDone)
{ {
ConstraintTest *constraint = (ConstraintTest *) cstate->xprstate.expr;
Datum result; Datum result;
result = ExecEvalExpr((Node *) constraint->arg, econtext, isNull, isDone); result = ExecEvalExpr(cstate->arg, econtext, isNull, isDone);
if (isDone && *isDone == ExprEndResult) if (isDone && *isDone == ExprEndResult)
return result; /* nothing to check */ return result; /* nothing to check */
...@@ -1596,7 +1602,7 @@ ExecEvalConstraintTest(ConstraintTest *constraint, ExprContext *econtext, ...@@ -1596,7 +1602,7 @@ ExecEvalConstraintTest(ConstraintTest *constraint, ExprContext *econtext,
econtext->domainValue_datum = result; econtext->domainValue_datum = result;
econtext->domainValue_isNull = *isNull; econtext->domainValue_isNull = *isNull;
conResult = ExecEvalExpr((Node *) constraint->check_expr, conResult = ExecEvalExpr(cstate->check_expr,
econtext, &conIsNull, NULL); econtext, &conIsNull, NULL);
if (!conIsNull && if (!conIsNull &&
...@@ -1637,17 +1643,21 @@ ExecEvalConstraintTestValue(ConstraintTestValue *conVal, ExprContext *econtext, ...@@ -1637,17 +1643,21 @@ ExecEvalConstraintTestValue(ConstraintTestValue *conVal, ExprContext *econtext,
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
static Datum static Datum
ExecEvalFieldSelect(FieldSelect *fselect, ExecEvalFieldSelect(GenericExprState *fstate,
ExprContext *econtext, ExprContext *econtext,
bool *isNull, bool *isNull,
ExprDoneCond *isDone) ExprDoneCond *isDone)
{ {
FieldSelect *fselect = (FieldSelect *) fstate->xprstate.expr;
Datum result; Datum result;
TupleTableSlot *resSlot; TupleTableSlot *resSlot;
result = ExecEvalExpr((Node *) fselect->arg, econtext, isNull, isDone); result = ExecEvalExpr(fstate->arg, econtext, isNull, isDone);
/* this test covers the isDone exception too: */
if (*isNull) if (*isNull)
return result; return result;
resSlot = (TupleTableSlot *) DatumGetPointer(result); resSlot = (TupleTableSlot *) DatumGetPointer(result);
Assert(resSlot != NULL && IsA(resSlot, TupleTableSlot)); Assert(resSlot != NULL && IsA(resSlot, TupleTableSlot));
result = heap_getattr(resSlot->val, result = heap_getattr(resSlot->val,
...@@ -1663,7 +1673,7 @@ ExecEvalFieldSelect(FieldSelect *fselect, ...@@ -1663,7 +1673,7 @@ ExecEvalFieldSelect(FieldSelect *fselect,
* Recursively evaluate a targetlist or qualification expression. * Recursively evaluate a targetlist or qualification expression.
* *
* Inputs: * Inputs:
* expression: the expression tree to evaluate * expression: the expression state tree to evaluate
* econtext: evaluation context information * econtext: evaluation context information
* *
* Outputs: * Outputs:
...@@ -1697,12 +1707,13 @@ ExecEvalFieldSelect(FieldSelect *fselect, ...@@ -1697,12 +1707,13 @@ ExecEvalFieldSelect(FieldSelect *fselect,
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
Datum Datum
ExecEvalExpr(Node *expression, ExecEvalExpr(ExprState *expression,
ExprContext *econtext, ExprContext *econtext,
bool *isNull, bool *isNull,
ExprDoneCond *isDone) ExprDoneCond *isDone)
{ {
Datum retDatum; Datum retDatum;
Expr *expr;
/* Set default values for result flags: non-null, not a set result */ /* Set default values for result flags: non-null, not a set result */
*isNull = false; *isNull = false;
...@@ -1720,111 +1731,112 @@ ExecEvalExpr(Node *expression, ...@@ -1720,111 +1731,112 @@ ExecEvalExpr(Node *expression,
* here we dispatch the work to the appropriate type of function given * here we dispatch the work to the appropriate type of function given
* the type of our expression. * the type of our expression.
*/ */
switch (nodeTag(expression)) expr = expression->expr;
switch (nodeTag(expr))
{ {
case T_Var: case T_Var:
retDatum = ExecEvalVar((Var *) expression, econtext, isNull); retDatum = ExecEvalVar((Var *) expr, econtext, isNull);
break; break;
case T_Const: case T_Const:
{ {
Const *con = (Const *) expression; Const *con = (Const *) expr;
retDatum = con->constvalue; retDatum = con->constvalue;
*isNull = con->constisnull; *isNull = con->constisnull;
break; break;
} }
case T_Param: case T_Param:
retDatum = ExecEvalParam((Param *) expression, econtext, isNull); retDatum = ExecEvalParam((Param *) expr, econtext, isNull);
break; break;
case T_Aggref: case T_Aggref:
retDatum = ExecEvalAggref((Aggref *) expression, econtext, isNull); retDatum = ExecEvalAggref((AggrefExprState *) expression,
econtext,
isNull);
break; break;
case T_ArrayRef: case T_ArrayRef:
retDatum = ExecEvalArrayRef((ArrayRef *) expression, retDatum = ExecEvalArrayRef((ArrayRefExprState *) expression,
econtext, econtext,
isNull, isNull,
isDone); isDone);
break; break;
case T_FuncExpr: case T_FuncExpr:
retDatum = ExecEvalFunc((FuncExpr *) expression, econtext, retDatum = ExecEvalFunc((FuncExprState *) expression, econtext,
isNull, isDone); isNull, isDone);
break; break;
case T_OpExpr: case T_OpExpr:
retDatum = ExecEvalOper((OpExpr *) expression, econtext, retDatum = ExecEvalOper((FuncExprState *) expression, econtext,
isNull, isDone); isNull, isDone);
break; break;
case T_DistinctExpr: case T_DistinctExpr:
retDatum = ExecEvalDistinct((DistinctExpr *) expression, econtext, retDatum = ExecEvalDistinct((FuncExprState *) expression, econtext,
isNull, isDone); isNull, isDone);
break; break;
case T_BoolExpr: case T_BoolExpr:
{ {
BoolExpr *expr = (BoolExpr *) expression; BoolExprState *state = (BoolExprState *) expression;
switch (expr->boolop) switch (((BoolExpr *) expr)->boolop)
{ {
case AND_EXPR: case AND_EXPR:
retDatum = ExecEvalAnd(expr, econtext, isNull); retDatum = ExecEvalAnd(state, econtext, isNull);
break; break;
case OR_EXPR: case OR_EXPR:
retDatum = ExecEvalOr(expr, econtext, isNull); retDatum = ExecEvalOr(state, econtext, isNull);
break; break;
case NOT_EXPR: case NOT_EXPR:
retDatum = ExecEvalNot(expr, econtext, isNull); retDatum = ExecEvalNot(state, econtext, isNull);
break; break;
default: default:
elog(ERROR, "ExecEvalExpr: unknown boolop %d", elog(ERROR, "ExecEvalExpr: unknown boolop %d",
expr->boolop); ((BoolExpr *) expr)->boolop);
retDatum = 0; /* keep compiler quiet */ retDatum = 0; /* keep compiler quiet */
break; break;
} }
break; break;
} }
case T_SubPlanExpr: case T_SubPlanExpr:
/* XXX temporary hack to find exec state node */ retDatum = ExecSubPlan((SubPlanExprState *) expression,
retDatum = ExecSubPlan(((SubPlanExpr *) expression)->pstate,
((SubPlanExpr *) expression)->args,
econtext, econtext,
isNull); isNull);
break; break;
case T_FieldSelect: case T_FieldSelect:
retDatum = ExecEvalFieldSelect((FieldSelect *) expression, retDatum = ExecEvalFieldSelect((GenericExprState *) expression,
econtext, econtext,
isNull, isNull,
isDone); isDone);
break; break;
case T_RelabelType: case T_RelabelType:
retDatum = ExecEvalExpr((Node *) ((RelabelType *) expression)->arg, retDatum = ExecEvalExpr(((GenericExprState *) expression)->arg,
econtext, econtext,
isNull, isNull,
isDone); isDone);
break; break;
case T_CaseExpr: case T_CaseExpr:
retDatum = ExecEvalCase((CaseExpr *) expression, retDatum = ExecEvalCase((CaseExprState *) expression,
econtext, econtext,
isNull, isNull,
isDone); isDone);
break; break;
case T_NullTest: case T_NullTest:
retDatum = ExecEvalNullTest((NullTest *) expression, retDatum = ExecEvalNullTest((GenericExprState *) expression,
econtext, econtext,
isNull, isNull,
isDone); isDone);
break; break;
case T_BooleanTest: case T_BooleanTest:
retDatum = ExecEvalBooleanTest((BooleanTest *) expression, retDatum = ExecEvalBooleanTest((GenericExprState *) expression,
econtext, econtext,
isNull, isNull,
isDone); isDone);
break; break;
case T_ConstraintTest: case T_ConstraintTest:
retDatum = ExecEvalConstraintTest((ConstraintTest *) expression, retDatum = ExecEvalConstraintTest((ConstraintTestState *) expression,
econtext, econtext,
isNull, isNull,
isDone); isDone);
break; break;
case T_ConstraintTestValue: case T_ConstraintTestValue:
retDatum = ExecEvalConstraintTestValue((ConstraintTestValue *) expression, retDatum = ExecEvalConstraintTestValue((ConstraintTestValue *) expr,
econtext, econtext,
isNull); isNull);
break; break;
...@@ -1843,7 +1855,7 @@ ExecEvalExpr(Node *expression, ...@@ -1843,7 +1855,7 @@ ExecEvalExpr(Node *expression,
* Same as above, but get into the right allocation context explicitly. * Same as above, but get into the right allocation context explicitly.
*/ */
Datum Datum
ExecEvalExprSwitchContext(Node *expression, ExecEvalExprSwitchContext(ExprState *expression,
ExprContext *econtext, ExprContext *econtext,
bool *isNull, bool *isNull,
ExprDoneCond *isDone) ExprDoneCond *isDone)
...@@ -1861,40 +1873,63 @@ ExecEvalExprSwitchContext(Node *expression, ...@@ -1861,40 +1873,63 @@ ExecEvalExprSwitchContext(Node *expression,
/* /*
* ExecInitExpr: prepare an expression tree for execution * ExecInitExpr: prepare an expression tree for execution
* *
* This function builds and returns an ExprState tree paralleling the given
* Expr node tree. The ExprState tree can then be handed to ExecEvalExpr
* for execution. Because the Expr tree itself is read-only as far as
* ExecInitExpr and ExecEvalExpr are concerned, several different executions
* of the same plan tree can occur concurrently.
*
* This must be called in a memory context that will last as long as repeated
* executions of the expression are needed. Typically the context will be
* the same as the per-query context of the associated ExprContext.
*
* Any Aggref and SubplanExpr nodes found in the tree are added to the lists
* of such nodes held by the parent PlanState. Otherwise, we do very little
* initialization here other than building the state-node tree. Any nontrivial
* work associated with initializing runtime info for a node should happen
* during the first actual evaluation of that node. (This policy lets us
* avoid work if the node is never actually evaluated.)
*
* Note: there is no ExecEndExpr function; we assume that any resource
* cleanup needed will be handled by just releasing the memory context
* in which the state tree is built. Functions that require additional
* cleanup work can register a shutdown callback in the ExprContext.
*
* 'node' is the root of the expression tree to examine * 'node' is the root of the expression tree to examine
* 'parent' is the PlanState node that owns the expression, * 'parent' is the PlanState node that owns the expression,
* or NULL if we are preparing an expression that is not associated * or NULL if we are preparing an expression that is not associated
* with a plan. (If so, it can't have Aggrefs or SubPlans.) * with a plan. (If so, it can't have aggs or subplans.)
*
* Soon this will generate an expression state tree paralleling the given
* expression tree. Right now, it just searches the expression tree for
* Aggref and SubPlanExpr nodes.
*/ */
Node * ExprState *
ExecInitExpr(Node *node, PlanState *parent) ExecInitExpr(Expr *node, PlanState *parent)
{ {
List *temp; ExprState *state;
if (node == NULL) if (node == NULL)
return NULL; return NULL;
switch (nodeTag(node)) switch (nodeTag(node))
{ {
case T_Var: case T_Var:
break;
case T_Const: case T_Const:
break;
case T_Param: case T_Param:
case T_ConstraintTestValue:
/* No special setup needed for these node types */
state = (ExprState *) makeNode(ExprState);
break; break;
case T_Aggref: case T_Aggref:
{
Aggref *aggref = (Aggref *) node;
AggrefExprState *astate = makeNode(AggrefExprState);
if (parent && IsA(parent, AggState)) if (parent && IsA(parent, AggState))
{ {
AggState *aggstate = (AggState *) parent; AggState *aggstate = (AggState *) parent;
int naggs; int naggs;
aggstate->aggs = lcons(node, aggstate->aggs); aggstate->aggs = lcons(astate, aggstate->aggs);
naggs = ++aggstate->numaggs; naggs = ++aggstate->numaggs;
ExecInitExpr((Node *) ((Aggref *) node)->target, parent); astate->target = ExecInitExpr(aggref->target, parent);
/* /*
* Complain if the aggregate's argument contains any * Complain if the aggregate's argument contains any
...@@ -1907,120 +1942,232 @@ ExecInitExpr(Node *node, PlanState *parent) ...@@ -1907,120 +1942,232 @@ ExecInitExpr(Node *node, PlanState *parent)
} }
else else
elog(ERROR, "ExecInitExpr: Aggref not expected here"); elog(ERROR, "ExecInitExpr: Aggref not expected here");
state = (ExprState *) astate;
}
break; break;
case T_ArrayRef: case T_ArrayRef:
{ {
ArrayRef *aref = (ArrayRef *) node; ArrayRef *aref = (ArrayRef *) node;
ArrayRefExprState *astate = makeNode(ArrayRefExprState);
ExecInitExpr((Node *) aref->refupperindexpr, parent); astate->refupperindexpr = (List *)
ExecInitExpr((Node *) aref->reflowerindexpr, parent); ExecInitExpr((Expr *) aref->refupperindexpr, parent);
ExecInitExpr((Node *) aref->refexpr, parent); astate->reflowerindexpr = (List *)
ExecInitExpr((Node *) aref->refassgnexpr, parent); ExecInitExpr((Expr *) aref->reflowerindexpr, parent);
astate->refexpr = ExecInitExpr(aref->refexpr, parent);
astate->refassgnexpr = ExecInitExpr(aref->refassgnexpr,
parent);
state = (ExprState *) astate;
} }
break; break;
case T_FuncExpr: case T_FuncExpr:
{ {
FuncExpr *funcexpr = (FuncExpr *) node; FuncExpr *funcexpr = (FuncExpr *) node;
FuncExprState *fstate = makeNode(FuncExprState);
ExecInitExpr((Node *) funcexpr->args, parent); fstate->args = (List *)
ExecInitExpr((Expr *) funcexpr->args, parent);
fstate->func.fn_oid = InvalidOid; /* not initialized */
state = (ExprState *) fstate;
} }
break; break;
case T_OpExpr: case T_OpExpr:
{ {
OpExpr *opexpr = (OpExpr *) node; OpExpr *opexpr = (OpExpr *) node;
FuncExprState *fstate = makeNode(FuncExprState);
ExecInitExpr((Node *) opexpr->args, parent); fstate->args = (List *)
ExecInitExpr((Expr *) opexpr->args, parent);
fstate->func.fn_oid = InvalidOid; /* not initialized */
state = (ExprState *) fstate;
} }
break; break;
case T_DistinctExpr: case T_DistinctExpr:
{ {
DistinctExpr *distinctexpr = (DistinctExpr *) node; DistinctExpr *distinctexpr = (DistinctExpr *) node;
FuncExprState *fstate = makeNode(FuncExprState);
ExecInitExpr((Node *) distinctexpr->args, parent); fstate->args = (List *)
ExecInitExpr((Expr *) distinctexpr->args, parent);
fstate->func.fn_oid = InvalidOid; /* not initialized */
state = (ExprState *) fstate;
} }
break; break;
case T_BoolExpr: case T_BoolExpr:
{ {
BoolExpr *boolexpr = (BoolExpr *) node; BoolExpr *boolexpr = (BoolExpr *) node;
BoolExprState *bstate = makeNode(BoolExprState);
ExecInitExpr((Node *) boolexpr->args, parent); bstate->args = (List *)
ExecInitExpr((Expr *) boolexpr->args, parent);
state = (ExprState *) bstate;
} }
break; break;
case T_SubPlanExpr: case T_SubPlanExpr:
{ {
/* Keep this in sync with ExecInitExprInitPlan, below */
SubPlanExpr *subplanexpr = (SubPlanExpr *) node; SubPlanExpr *subplanexpr = (SubPlanExpr *) node;
SubLink *sublink = subplanexpr->sublink; SubLink *sublink = subplanexpr->sublink;
SubPlanExprState *sstate = makeNode(SubPlanExprState);
Assert(IsA(sublink, SubLink)); Assert(IsA(sublink, SubLink));
if (!parent) if (!parent)
elog(ERROR, "ExecInitExpr: SubPlanExpr not expected here"); elog(ERROR, "ExecInitExpr: SubPlanExpr not expected here");
/* /*
* Here we just add the SubPlanExpr nodes to * Here we just add the SubPlanExprState nodes to
* parent->subPlan. Later they will be expanded * parent->subPlan. The subplans will be initialized later.
* to SubPlanState nodes.
*/ */
parent->subPlan = lcons(subplanexpr, parent->subPlan); parent->subPlan = lcons(sstate, parent->subPlan);
sstate->planstate = NULL;
sstate->args = (List *)
ExecInitExpr((Expr *) subplanexpr->args, parent);
/* Must recurse into oper list too */
if (sublink->lefthand) if (sublink->lefthand)
elog(ERROR, "ExecInitExpr: sublink has not been transformed"); elog(ERROR, "ExecInitExpr: sublink has not been transformed");
ExecInitExpr((Node *) sublink->oper, parent); sstate->oper = (List *)
ExecInitExpr((Expr *) sublink->oper, parent);
ExecInitExpr((Node *) subplanexpr->args, parent); state = (ExprState *) sstate;
} }
break; break;
case T_FieldSelect: case T_FieldSelect:
ExecInitExpr((Node *) ((FieldSelect *) node)->arg, parent); {
FieldSelect *fselect = (FieldSelect *) node;
GenericExprState *gstate = makeNode(GenericExprState);
gstate->arg = ExecInitExpr(fselect->arg, parent);
state = (ExprState *) gstate;
}
break; break;
case T_RelabelType: case T_RelabelType:
ExecInitExpr((Node *) ((RelabelType *) node)->arg, parent); {
RelabelType *relabel = (RelabelType *) node;
GenericExprState *gstate = makeNode(GenericExprState);
gstate->arg = ExecInitExpr(relabel->arg, parent);
state = (ExprState *) gstate;
}
break; break;
case T_CaseExpr: case T_CaseExpr:
{ {
CaseExpr *caseexpr = (CaseExpr *) node; CaseExpr *caseexpr = (CaseExpr *) node;
CaseExprState *cstate = makeNode(CaseExprState);
List *outlist = NIL;
List *inlist;
foreach(temp, caseexpr->args) foreach(inlist, caseexpr->args)
{ {
CaseWhen *when = (CaseWhen *) lfirst(temp); CaseWhen *when = (CaseWhen *) lfirst(inlist);
CaseWhenState *wstate = makeNode(CaseWhenState);
Assert(IsA(when, CaseWhen)); Assert(IsA(when, CaseWhen));
ExecInitExpr((Node *) when->expr, parent); wstate->xprstate.expr = (Expr *) when;
ExecInitExpr((Node *) when->result, parent); wstate->expr = ExecInitExpr(when->expr, parent);
wstate->result = ExecInitExpr(when->result, parent);
outlist = lappend(outlist, wstate);
} }
/* caseexpr->arg should be null, but we'll check it anyway */ cstate->args = outlist;
ExecInitExpr((Node *) caseexpr->arg, parent); /* caseexpr->arg should be null by now */
ExecInitExpr((Node *) caseexpr->defresult, parent); Assert(caseexpr->arg == NULL);
cstate->defresult = ExecInitExpr(caseexpr->defresult, parent);
state = (ExprState *) cstate;
} }
break; break;
case T_NullTest: case T_NullTest:
ExecInitExpr((Node *) ((NullTest *) node)->arg, parent); {
NullTest *ntest = (NullTest *) node;
GenericExprState *gstate = makeNode(GenericExprState);
gstate->arg = ExecInitExpr(ntest->arg, parent);
state = (ExprState *) gstate;
}
break; break;
case T_BooleanTest: case T_BooleanTest:
ExecInitExpr((Node *) ((BooleanTest *) node)->arg, parent); {
BooleanTest *btest = (BooleanTest *) node;
GenericExprState *gstate = makeNode(GenericExprState);
gstate->arg = ExecInitExpr(btest->arg, parent);
state = (ExprState *) gstate;
}
break; break;
case T_ConstraintTest: case T_ConstraintTest:
ExecInitExpr((Node *) ((ConstraintTest *) node)->arg, parent); {
ExecInitExpr((Node *) ((ConstraintTest *) node)->check_expr, parent); ConstraintTest *ctest = (ConstraintTest *) node;
break; ConstraintTestState *cstate = makeNode(ConstraintTestState);
case T_ConstraintTestValue:
cstate->arg = ExecInitExpr(ctest->arg, parent);
cstate->check_expr = ExecInitExpr(ctest->check_expr, parent);
state = (ExprState *) cstate;
}
break; break;
case T_TargetEntry: case T_TargetEntry:
ExecInitExpr((Node *) ((TargetEntry *) node)->expr, parent); {
TargetEntry *tle = (TargetEntry *) node;
GenericExprState *gstate = makeNode(GenericExprState);
gstate->arg = ExecInitExpr(tle->expr, parent);
state = (ExprState *) gstate;
}
break; break;
case T_List: case T_List:
foreach(temp, (List *) node)
{ {
ExecInitExpr((Node *) lfirst(temp), parent); List *outlist = NIL;
List *inlist;
foreach(inlist, (List *) node)
{
outlist = lappend(outlist,
ExecInitExpr((Expr *) lfirst(inlist),
parent));
}
/* Don't fall through to the "common" code below */
return (ExprState *) outlist;
} }
break;
default: default:
elog(ERROR, "ExecInitExpr: unknown expression type %d", elog(ERROR, "ExecInitExpr: unknown expression type %d",
nodeTag(node)); nodeTag(node));
state = NULL; /* keep compiler quiet */
break; break;
} }
return node; /* Common code for all state-node types */
state->expr = node;
return state;
}
/*
* ExecInitExprInitPlan --- initialize a subplan expr that's being handled
* as an InitPlan. This is identical to ExecInitExpr's handling of a regular
* subplan expr, except we do NOT want to add the node to the parent's
* subplan list.
*/
SubPlanExprState *
ExecInitExprInitPlan(SubPlanExpr *node, PlanState *parent)
{
SubLink *sublink = node->sublink;
SubPlanExprState *sstate = makeNode(SubPlanExprState);
Assert(IsA(sublink, SubLink));
if (!parent)
elog(ERROR, "ExecInitExpr: SubPlanExpr not expected here");
/* The subplan's state will be initialized later */
sstate->planstate = NULL;
sstate->args = (List *) ExecInitExpr((Expr *) node->args, parent);
if (sublink->lefthand)
elog(ERROR, "ExecInitExpr: sublink has not been transformed");
sstate->oper = (List *) ExecInitExpr((Expr *) sublink->oper, parent);
sstate->xprstate.expr = (Expr *) node;
return sstate;
} }
...@@ -2094,7 +2241,7 @@ ExecQual(List *qual, ExprContext *econtext, bool resultForNull) ...@@ -2094,7 +2241,7 @@ ExecQual(List *qual, ExprContext *econtext, bool resultForNull)
foreach(qlist, qual) foreach(qlist, qual)
{ {
Node *clause = (Node *) lfirst(qlist); ExprState *clause = (ExprState *) lfirst(qlist);
Datum expr_value; Datum expr_value;
bool isNull; bool isNull;
...@@ -2146,6 +2293,7 @@ ExecCleanTargetListLength(List *targetlist) ...@@ -2146,6 +2293,7 @@ ExecCleanTargetListLength(List *targetlist)
{ {
TargetEntry *curTle = (TargetEntry *) lfirst(tl); TargetEntry *curTle = (TargetEntry *) lfirst(tl);
Assert(IsA(curTle, TargetEntry));
if (!curTle->resdom->resjunk) if (!curTle->resdom->resjunk)
len++; len++;
} }
...@@ -2180,8 +2328,6 @@ ExecTargetList(List *targetlist, ...@@ -2180,8 +2328,6 @@ ExecTargetList(List *targetlist,
char *nulls; char *nulls;
ExprDoneCond *itemIsDone; ExprDoneCond *itemIsDone;
List *tl; List *tl;
TargetEntry *tle;
AttrNumber resind;
HeapTuple newTuple; HeapTuple newTuple;
bool isNull; bool isNull;
bool haveDoneSets; bool haveDoneSets;
...@@ -2243,11 +2389,11 @@ ExecTargetList(List *targetlist, ...@@ -2243,11 +2389,11 @@ ExecTargetList(List *targetlist,
foreach(tl, targetlist) foreach(tl, targetlist)
{ {
tle = lfirst(tl); GenericExprState *gstate = (GenericExprState *) lfirst(tl);
TargetEntry *tle = (TargetEntry *) gstate->xprstate.expr;
resind = tle->resdom->resno - 1; AttrNumber resind = tle->resdom->resno - 1;
values[resind] = ExecEvalExpr((Node *) tle->expr, values[resind] = ExecEvalExpr(gstate->arg,
econtext, econtext,
&isNull, &isNull,
&itemIsDone[resind]); &itemIsDone[resind]);
...@@ -2295,15 +2441,13 @@ ExecTargetList(List *targetlist, ...@@ -2295,15 +2441,13 @@ ExecTargetList(List *targetlist,
*/ */
foreach(tl, targetlist) foreach(tl, targetlist)
{ {
tle = lfirst(tl); GenericExprState *gstate = (GenericExprState *) lfirst(tl);
TargetEntry *tle = (TargetEntry *) gstate->xprstate.expr;
if (tle->resdom != NULL) AttrNumber resind = tle->resdom->resno - 1;
{
resind = tle->resdom->resno - 1;
if (itemIsDone[resind] == ExprEndResult) if (itemIsDone[resind] == ExprEndResult)
{ {
values[resind] = ExecEvalExpr((Node *) tle->expr, values[resind] = ExecEvalExpr(gstate->arg,
econtext, econtext,
&isNull, &isNull,
&itemIsDone[resind]); &itemIsDone[resind]);
...@@ -2320,32 +2464,30 @@ ExecTargetList(List *targetlist, ...@@ -2320,32 +2464,30 @@ ExecTargetList(List *targetlist,
} }
} }
} }
}
/* /*
* If we cannot make a tuple because some sets are empty, we * If we cannot make a tuple because some sets are empty, we
* still have to cycle the nonempty sets to completion, else * still have to cycle the nonempty sets to completion, else
* resources will not be released from subplans etc. * resources will not be released from subplans etc.
*
* XXX is that still necessary?
*/ */
if (*isDone == ExprEndResult) if (*isDone == ExprEndResult)
{ {
foreach(tl, targetlist) foreach(tl, targetlist)
{ {
tle = lfirst(tl); GenericExprState *gstate = (GenericExprState *) lfirst(tl);
TargetEntry *tle = (TargetEntry *) gstate->xprstate.expr;
if (tle->resdom != NULL) AttrNumber resind = tle->resdom->resno - 1;
{
resind = tle->resdom->resno - 1;
while (itemIsDone[resind] == ExprMultipleResult) while (itemIsDone[resind] == ExprMultipleResult)
{ {
(void) ExecEvalExpr((Node *) tle->expr, (void) ExecEvalExpr(gstate->arg,
econtext, econtext,
&isNull, &isNull,
&itemIsDone[resind]); &itemIsDone[resind]);
} }
} }
}
MemoryContextSwitchTo(oldContext); MemoryContextSwitchTo(oldContext);
newTuple = NULL; newTuple = NULL;
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.62 2002/12/12 15:49:28 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.63 2002/12/13 19:45:52 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -550,6 +550,7 @@ ExecInitNullTupleSlot(EState *estate, TupleDesc tupType) ...@@ -550,6 +550,7 @@ ExecInitNullTupleSlot(EState *estate, TupleDesc tupType)
* ExecTypeFromTL * ExecTypeFromTL
* *
* Generate a tuple descriptor for the result tuple of a targetlist. * Generate a tuple descriptor for the result tuple of a targetlist.
* (A parse/plan tlist must be passed, not an ExprState tlist.)
* Note that resjunk columns, if any, are included in the result. * Note that resjunk columns, if any, are included in the result.
* *
* Currently there are about 4 different places where we create * Currently there are about 4 different places where we create
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.91 2002/12/05 15:50:32 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.92 2002/12/13 19:45:52 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -321,9 +321,9 @@ ExecAssignResultTypeFromTL(PlanState *planstate) ...@@ -321,9 +321,9 @@ ExecAssignResultTypeFromTL(PlanState *planstate)
} }
/* /*
* XXX Some plan nodes don't bother to set up planstate->targetlist, * ExecTypeFromTL needs the parse-time representation of the tlist, not
* so use the underlying plan's targetlist instead. This will probably * a list of ExprStates. This is good because some plan nodes don't
* need to be fixed later. * bother to set up planstate->targetlist ...
*/ */
tupDesc = ExecTypeFromTL(planstate->plan->targetlist, hasoid); tupDesc = ExecTypeFromTL(planstate->plan->targetlist, hasoid);
ExecAssignResultType(planstate, tupDesc, true); ExecAssignResultType(planstate, tupDesc, true);
...@@ -681,7 +681,7 @@ ExecInsertIndexTuples(TupleTableSlot *slot, ...@@ -681,7 +681,7 @@ ExecInsertIndexTuples(TupleTableSlot *slot,
continue; continue;
indexInfo = indexInfoArray[i]; indexInfo = indexInfoArray[i];
predicate = indexInfo->ii_Predicate; predicate = indexInfo->ii_PredicateState;
if (predicate != NIL) if (predicate != NIL)
{ {
/* Skip this index-update if the predicate isn't satisfied */ /* Skip this index-update if the predicate isn't satisfied */
......
...@@ -45,7 +45,7 @@ ...@@ -45,7 +45,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeAgg.c,v 1.99 2002/12/12 15:49:24 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/nodeAgg.c,v 1.100 2002/12/13 19:45:52 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -82,7 +82,8 @@ typedef struct AggStatePerAggData ...@@ -82,7 +82,8 @@ typedef struct AggStatePerAggData
* thereafter: * thereafter:
*/ */
/* Link to Aggref node this working state is for */ /* Links to Aggref expr and state nodes this working state is for */
AggrefExprState *aggrefstate;
Aggref *aggref; Aggref *aggref;
/* Oids of transfer functions */ /* Oids of transfer functions */
...@@ -411,11 +412,12 @@ advance_aggregates(AggState *aggstate, AggStatePerGroup pergroup) ...@@ -411,11 +412,12 @@ advance_aggregates(AggState *aggstate, AggStatePerGroup pergroup)
{ {
AggStatePerAgg peraggstate = &aggstate->peragg[aggno]; AggStatePerAgg peraggstate = &aggstate->peragg[aggno];
AggStatePerGroup pergroupstate = &pergroup[aggno]; AggStatePerGroup pergroupstate = &pergroup[aggno];
AggrefExprState *aggrefstate = peraggstate->aggrefstate;
Aggref *aggref = peraggstate->aggref; Aggref *aggref = peraggstate->aggref;
Datum newVal; Datum newVal;
bool isNull; bool isNull;
newVal = ExecEvalExprSwitchContext((Node *) aggref->target, econtext, newVal = ExecEvalExprSwitchContext(aggrefstate->target, econtext,
&isNull, NULL); &isNull, NULL);
if (aggref->aggdistinct) if (aggref->aggdistinct)
...@@ -1145,10 +1147,10 @@ ExecInitAgg(Agg *node, EState *estate) ...@@ -1145,10 +1147,10 @@ ExecInitAgg(Agg *node, EState *estate)
* particular order. * particular order.
*/ */
aggstate->ss.ps.targetlist = (List *) aggstate->ss.ps.targetlist = (List *)
ExecInitExpr((Node *) node->plan.targetlist, ExecInitExpr((Expr *) node->plan.targetlist,
(PlanState *) aggstate); (PlanState *) aggstate);
aggstate->ss.ps.qual = (List *) aggstate->ss.ps.qual = (List *)
ExecInitExpr((Node *) node->plan.qual, ExecInitExpr((Expr *) node->plan.qual,
(PlanState *) aggstate); (PlanState *) aggstate);
/* /*
...@@ -1227,7 +1229,8 @@ ExecInitAgg(Agg *node, EState *estate) ...@@ -1227,7 +1229,8 @@ ExecInitAgg(Agg *node, EState *estate)
aggno = -1; aggno = -1;
foreach(alist, aggstate->aggs) foreach(alist, aggstate->aggs)
{ {
Aggref *aggref = (Aggref *) lfirst(alist); AggrefExprState *aggrefstate = (AggrefExprState *) lfirst(alist);
Aggref *aggref = (Aggref *) aggrefstate->xprstate.expr;
AggStatePerAgg peraggstate = &peragg[++aggno]; AggStatePerAgg peraggstate = &peragg[++aggno];
HeapTuple aggTuple; HeapTuple aggTuple;
Form_pg_aggregate aggform; Form_pg_aggregate aggform;
...@@ -1236,10 +1239,11 @@ ExecInitAgg(Agg *node, EState *estate) ...@@ -1236,10 +1239,11 @@ ExecInitAgg(Agg *node, EState *estate)
finalfn_oid; finalfn_oid;
Datum textInitVal; Datum textInitVal;
/* Mark Aggref node with its associated index in the result array */ /* Mark Aggref state node with assigned index in the result array */
aggref->aggno = aggno; aggrefstate->aggno = aggno;
/* Fill in the peraggstate data */ /* Fill in the peraggstate data */
peraggstate->aggrefstate = aggrefstate;
peraggstate->aggref = aggref; peraggstate->aggref = aggref;
aggTuple = SearchSysCache(AGGFNOID, aggTuple = SearchSysCache(AGGFNOID,
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeFunctionscan.c,v 1.14 2002/12/05 15:50:33 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/nodeFunctionscan.c,v 1.15 2002/12/13 19:45:52 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -172,10 +172,10 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate) ...@@ -172,10 +172,10 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate)
* initialize child expressions * initialize child expressions
*/ */
scanstate->ss.ps.targetlist = (List *) scanstate->ss.ps.targetlist = (List *)
ExecInitExpr((Node *) node->scan.plan.targetlist, ExecInitExpr((Expr *) node->scan.plan.targetlist,
(PlanState *) scanstate); (PlanState *) scanstate);
scanstate->ss.ps.qual = (List *) scanstate->ss.ps.qual = (List *)
ExecInitExpr((Node *) node->scan.plan.qual, ExecInitExpr((Expr *) node->scan.plan.qual,
(PlanState *) scanstate); (PlanState *) scanstate);
/* /*
...@@ -241,7 +241,8 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate) ...@@ -241,7 +241,8 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate)
* Other node-specific setup * Other node-specific setup
*/ */
scanstate->tuplestorestate = NULL; scanstate->tuplestorestate = NULL;
scanstate->funcexpr = rte->funcexpr; scanstate->funcexpr = ExecInitExpr((Expr *) rte->funcexpr,
(PlanState *) scanstate);
scanstate->ss.ps.ps_TupFromTlist = false; scanstate->ss.ps.ps_TupFromTlist = false;
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
* locate group boundaries. * locate group boundaries.
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeGroup.c,v 1.51 2002/12/05 15:50:33 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/nodeGroup.c,v 1.52 2002/12/13 19:45:52 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -168,10 +168,10 @@ ExecInitGroup(Group *node, EState *estate) ...@@ -168,10 +168,10 @@ ExecInitGroup(Group *node, EState *estate)
* initialize child expressions * initialize child expressions
*/ */
grpstate->ss.ps.targetlist = (List *) grpstate->ss.ps.targetlist = (List *)
ExecInitExpr((Node *) node->plan.targetlist, ExecInitExpr((Expr *) node->plan.targetlist,
(PlanState *) grpstate); (PlanState *) grpstate);
grpstate->ss.ps.qual = (List *) grpstate->ss.ps.qual = (List *)
ExecInitExpr((Node *) node->plan.qual, ExecInitExpr((Expr *) node->plan.qual,
(PlanState *) grpstate); (PlanState *) grpstate);
/* /*
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeHash.c,v 1.69 2002/12/05 15:50:33 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/nodeHash.c,v 1.70 2002/12/13 19:45:52 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -76,7 +76,7 @@ ExecHash(HashState *node) ...@@ -76,7 +76,7 @@ ExecHash(HashState *node)
/* /*
* set expression context * set expression context
*/ */
hashkeys = ((Hash *) node->ps.plan)->hashkeys; hashkeys = node->hashkeys;
econtext = node->ps.ps_ExprContext; econtext = node->ps.ps_ExprContext;
/* /*
...@@ -138,10 +138,10 @@ ExecInitHash(Hash *node, EState *estate) ...@@ -138,10 +138,10 @@ ExecInitHash(Hash *node, EState *estate)
* initialize child expressions * initialize child expressions
*/ */
hashstate->ps.targetlist = (List *) hashstate->ps.targetlist = (List *)
ExecInitExpr((Node *) node->plan.targetlist, ExecInitExpr((Expr *) node->plan.targetlist,
(PlanState *) hashstate); (PlanState *) hashstate);
hashstate->ps.qual = (List *) hashstate->ps.qual = (List *)
ExecInitExpr((Node *) node->plan.qual, ExecInitExpr((Expr *) node->plan.qual,
(PlanState *) hashstate); (PlanState *) hashstate);
/* /*
...@@ -554,7 +554,8 @@ ExecHashGetBucket(HashJoinTable hashtable, ...@@ -554,7 +554,8 @@ ExecHashGetBucket(HashJoinTable hashtable,
/* /*
* Get the join attribute value of the tuple * Get the join attribute value of the tuple
*/ */
keyval = ExecEvalExpr(lfirst(hk), econtext, &isNull, NULL); keyval = ExecEvalExpr((ExprState *) lfirst(hk),
econtext, &isNull, NULL);
/* /*
* Compute the hash function * Compute the hash function
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeHashjoin.c,v 1.43 2002/12/05 15:50:33 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/nodeHashjoin.c,v 1.44 2002/12/13 19:45:52 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -302,6 +302,7 @@ ExecInitHashJoin(HashJoin *node, EState *estate) ...@@ -302,6 +302,7 @@ ExecInitHashJoin(HashJoin *node, EState *estate)
HashJoinState *hjstate; HashJoinState *hjstate;
Plan *outerNode; Plan *outerNode;
Hash *hashNode; Hash *hashNode;
List *hclauses;
List *hcl; List *hcl;
/* /*
...@@ -322,17 +323,17 @@ ExecInitHashJoin(HashJoin *node, EState *estate) ...@@ -322,17 +323,17 @@ ExecInitHashJoin(HashJoin *node, EState *estate)
* initialize child expressions * initialize child expressions
*/ */
hjstate->js.ps.targetlist = (List *) hjstate->js.ps.targetlist = (List *)
ExecInitExpr((Node *) node->join.plan.targetlist, ExecInitExpr((Expr *) node->join.plan.targetlist,
(PlanState *) hjstate); (PlanState *) hjstate);
hjstate->js.ps.qual = (List *) hjstate->js.ps.qual = (List *)
ExecInitExpr((Node *) node->join.plan.qual, ExecInitExpr((Expr *) node->join.plan.qual,
(PlanState *) hjstate); (PlanState *) hjstate);
hjstate->js.jointype = node->join.jointype; hjstate->js.jointype = node->join.jointype;
hjstate->js.joinqual = (List *) hjstate->js.joinqual = (List *)
ExecInitExpr((Node *) node->join.joinqual, ExecInitExpr((Expr *) node->join.joinqual,
(PlanState *) hjstate); (PlanState *) hjstate);
hjstate->hashclauses = (List *) hjstate->hashclauses = (List *)
ExecInitExpr((Node *) node->hashclauses, ExecInitExpr((Expr *) node->hashclauses,
(PlanState *) hjstate); (PlanState *) hjstate);
/* /*
...@@ -402,15 +403,23 @@ ExecInitHashJoin(HashJoin *node, EState *estate) ...@@ -402,15 +403,23 @@ ExecInitHashJoin(HashJoin *node, EState *estate)
/* /*
* The planner already made a list of the inner hashkeys for us, * The planner already made a list of the inner hashkeys for us,
* but we also need a list of the outer hashkeys. * but we also need a list of the outer hashkeys. Each list of
* exprs must then be prepared for execution.
*/ */
hjstate->hj_InnerHashKeys = hashNode->hashkeys; hjstate->hj_InnerHashKeys = (List *)
hjstate->hj_OuterHashKeys = NIL; ExecInitExpr((Expr *) hashNode->hashkeys,
innerPlanState(hjstate));
((HashState *) innerPlanState(hjstate))->hashkeys =
hjstate->hj_InnerHashKeys;
hclauses = NIL;
foreach(hcl, node->hashclauses) foreach(hcl, node->hashclauses)
{ {
hjstate->hj_OuterHashKeys = lappend(hjstate->hj_OuterHashKeys, hclauses = lappend(hclauses, get_leftop(lfirst(hcl)));
get_leftop(lfirst(hcl)));
} }
hjstate->hj_OuterHashKeys = (List *)
ExecInitExpr((Expr *) hclauses,
(PlanState *) hjstate);
hjstate->js.ps.ps_OuterTupleSlot = NULL; hjstate->js.ps.ps_OuterTupleSlot = NULL;
hjstate->js.ps.ps_TupFromTlist = false; hjstate->js.ps.ps_TupFromTlist = false;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.73 2002/12/12 15:49:24 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.74 2002/12/13 19:45:52 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -283,7 +283,7 @@ ExecIndexReScan(IndexScanState *node, ExprContext *exprCtxt) ...@@ -283,7 +283,7 @@ ExecIndexReScan(IndexScanState *node, ExprContext *exprCtxt)
int numIndices; int numIndices;
IndexScanDescPtr scanDescs; IndexScanDescPtr scanDescs;
ScanKey *scanKeys; ScanKey *scanKeys;
int **runtimeKeyInfo; ExprState ***runtimeKeyInfo;
int *numScanKeys; int *numScanKeys;
Index scanrelid; Index scanrelid;
int i; int i;
...@@ -328,29 +328,18 @@ ExecIndexReScan(IndexScanState *node, ExprContext *exprCtxt) ...@@ -328,29 +328,18 @@ ExecIndexReScan(IndexScanState *node, ExprContext *exprCtxt)
*/ */
if (runtimeKeyInfo) if (runtimeKeyInfo)
{ {
List *indxqual;
indxqual = node->indxqual;
for (i = 0; i < numIndices; i++) for (i = 0; i < numIndices; i++)
{ {
List *qual = lfirst(indxqual);
int n_keys; int n_keys;
ScanKey scan_keys; ScanKey scan_keys;
int *run_keys; ExprState **run_keys;
List *listscan;
indxqual = lnext(indxqual);
n_keys = numScanKeys[i]; n_keys = numScanKeys[i];
scan_keys = scanKeys[i]; scan_keys = scanKeys[i];
run_keys = runtimeKeyInfo[i]; run_keys = runtimeKeyInfo[i];
listscan = qual;
for (j = 0; j < n_keys; j++) for (j = 0; j < n_keys; j++)
{ {
Expr *clause = lfirst(listscan);
listscan = lnext(listscan);
/* /*
* If we have a run-time key, then extract the run-time * If we have a run-time key, then extract the run-time
* expression and evaluate it with respect to the current * expression and evaluate it with respect to the current
...@@ -364,17 +353,12 @@ ExecIndexReScan(IndexScanState *node, ExprContext *exprCtxt) ...@@ -364,17 +353,12 @@ ExecIndexReScan(IndexScanState *node, ExprContext *exprCtxt)
* is wrong, we could copy the result into our context * is wrong, we could copy the result into our context
* explicitly, but I think that's not necessary... * explicitly, but I think that's not necessary...
*/ */
if (run_keys[j] != NO_OP) if (run_keys[j] != NULL)
{ {
Node *scanexpr;
Datum scanvalue; Datum scanvalue;
bool isNull; bool isNull;
scanexpr = (run_keys[j] == RIGHT_OP) ? scanvalue = ExecEvalExprSwitchContext(run_keys[j],
(Node *) get_rightop(clause) :
(Node *) get_leftop(clause);
scanvalue = ExecEvalExprSwitchContext(scanexpr,
econtext, econtext,
&isNull, &isNull,
NULL); NULL);
...@@ -424,7 +408,7 @@ ExecIndexReScan(IndexScanState *node, ExprContext *exprCtxt) ...@@ -424,7 +408,7 @@ ExecIndexReScan(IndexScanState *node, ExprContext *exprCtxt)
void void
ExecEndIndexScan(IndexScanState *node) ExecEndIndexScan(IndexScanState *node)
{ {
int **runtimeKeyInfo; ExprState ***runtimeKeyInfo;
ScanKey *scanKeys; ScanKey *scanKeys;
int *numScanKeys; int *numScanKeys;
int numIndices; int numIndices;
...@@ -585,7 +569,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate) ...@@ -585,7 +569,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate)
int *numScanKeys; int *numScanKeys;
RelationPtr indexDescs; RelationPtr indexDescs;
IndexScanDescPtr scanDescs; IndexScanDescPtr scanDescs;
int **runtimeKeyInfo; ExprState ***runtimeKeyInfo;
bool have_runtime_keys; bool have_runtime_keys;
RangeTblEntry *rtentry; RangeTblEntry *rtentry;
Index relid; Index relid;
...@@ -610,16 +594,16 @@ ExecInitIndexScan(IndexScan *node, EState *estate) ...@@ -610,16 +594,16 @@ ExecInitIndexScan(IndexScan *node, EState *estate)
* initialize child expressions * initialize child expressions
*/ */
indexstate->ss.ps.targetlist = (List *) indexstate->ss.ps.targetlist = (List *)
ExecInitExpr((Node *) node->scan.plan.targetlist, ExecInitExpr((Expr *) node->scan.plan.targetlist,
(PlanState *) indexstate); (PlanState *) indexstate);
indexstate->ss.ps.qual = (List *) indexstate->ss.ps.qual = (List *)
ExecInitExpr((Node *) node->scan.plan.qual, ExecInitExpr((Expr *) node->scan.plan.qual,
(PlanState *) indexstate); (PlanState *) indexstate);
indexstate->indxqual = (List *) indexstate->indxqual = (List *)
ExecInitExpr((Node *) node->indxqual, ExecInitExpr((Expr *) node->indxqual,
(PlanState *) indexstate); (PlanState *) indexstate);
indexstate->indxqualorig = (List *) indexstate->indxqualorig = (List *)
ExecInitExpr((Node *) node->indxqualorig, ExecInitExpr((Expr *) node->indxqualorig,
(PlanState *) indexstate); (PlanState *) indexstate);
#define INDEXSCAN_NSLOTS 2 #define INDEXSCAN_NSLOTS 2
...@@ -672,7 +656,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate) ...@@ -672,7 +656,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate)
* initialize space for runtime key info (may not be needed) * initialize space for runtime key info (may not be needed)
*/ */
have_runtime_keys = false; have_runtime_keys = false;
runtimeKeyInfo = (int **) palloc(numIndices * sizeof(int *)); runtimeKeyInfo = (ExprState ***) palloc0(numIndices * sizeof(ExprState **));
/* /*
* build the index scan keys from the index qualification * build the index scan keys from the index qualification
...@@ -684,15 +668,15 @@ ExecInitIndexScan(IndexScan *node, EState *estate) ...@@ -684,15 +668,15 @@ ExecInitIndexScan(IndexScan *node, EState *estate)
List *qual; List *qual;
int n_keys; int n_keys;
ScanKey scan_keys; ScanKey scan_keys;
int *run_keys; ExprState **run_keys;
qual = lfirst(indxqual); qual = lfirst(indxqual);
indxqual = lnext(indxqual); indxqual = lnext(indxqual);
n_keys = length(qual); n_keys = length(qual);
scan_keys = (n_keys <= 0) ? (ScanKey) NULL : scan_keys = (n_keys <= 0) ? (ScanKey) NULL :
(ScanKey) palloc(n_keys * sizeof(ScanKeyData)); (ScanKey) palloc(n_keys * sizeof(ScanKeyData));
run_keys = (n_keys <= 0) ? (int *) NULL : run_keys = (n_keys <= 0) ? (ExprState **) NULL :
(int *) palloc(n_keys * sizeof(int)); (ExprState **) palloc(n_keys * sizeof(ExprState *));
CXT1_printf("ExecInitIndexScan: context is %d\n", CurrentMemoryContext); CXT1_printf("ExecInitIndexScan: context is %d\n", CurrentMemoryContext);
...@@ -704,8 +688,8 @@ ExecInitIndexScan(IndexScan *node, EState *estate) ...@@ -704,8 +688,8 @@ ExecInitIndexScan(IndexScan *node, EState *estate)
for (j = 0; j < n_keys; j++) for (j = 0; j < n_keys; j++)
{ {
OpExpr *clause; /* one clause of index qual */ OpExpr *clause; /* one clause of index qual */
Node *leftop; /* expr on lhs of operator */ Expr *leftop; /* expr on lhs of operator */
Node *rightop; /* expr on rhs ... */ Expr *rightop; /* expr on rhs ... */
bits16 flags = 0; bits16 flags = 0;
int scanvar; /* which var identifies varattno */ int scanvar; /* which var identifies varattno */
...@@ -740,9 +724,9 @@ ExecInitIndexScan(IndexScan *node, EState *estate) ...@@ -740,9 +724,9 @@ ExecInitIndexScan(IndexScan *node, EState *estate)
* which case we need to recalculate the index scan key at run * which case we need to recalculate the index scan key at run
* time. * time.
* *
* Hence, we set have_runtime_keys to true and then set the * Hence, we set have_runtime_keys to true and place the
* appropriate flag in run_keys to LEFT_OP or RIGHT_OP. The * appropriate subexpression in run_keys. The corresponding
* corresponding scan keys are recomputed at run time. * scan key values are recomputed at run time.
* *
* XXX Although this code *thinks* it can handle an indexqual * XXX Although this code *thinks* it can handle an indexqual
* with the indexkey on either side, in fact it cannot. * with the indexkey on either side, in fact it cannot.
...@@ -760,19 +744,20 @@ ExecInitIndexScan(IndexScan *node, EState *estate) ...@@ -760,19 +744,20 @@ ExecInitIndexScan(IndexScan *node, EState *estate)
*/ */
scanvar = NO_OP; scanvar = NO_OP;
run_keys[j] = NO_OP; run_keys[j] = NULL;
/* /*
* determine information in leftop * determine information in leftop
*/ */
leftop = (Node *) get_leftop((Expr *) clause); leftop = (Expr *) get_leftop((Expr *) clause);
if (leftop && IsA(leftop, RelabelType)) if (leftop && IsA(leftop, RelabelType))
leftop = (Node *) ((RelabelType *) leftop)->arg; leftop = ((RelabelType *) leftop)->arg;
Assert(leftop != NULL); Assert(leftop != NULL);
if (IsA(leftop, Var) &&var_is_rel((Var *) leftop)) if (IsA(leftop, Var) &&
var_is_rel((Var *) leftop))
{ {
/* /*
* if the leftop is a "rel-var", then it means that it is * if the leftop is a "rel-var", then it means that it is
...@@ -792,32 +777,6 @@ ExecInitIndexScan(IndexScan *node, EState *estate) ...@@ -792,32 +777,6 @@ ExecInitIndexScan(IndexScan *node, EState *estate)
if (((Const *) leftop)->constisnull) if (((Const *) leftop)->constisnull)
flags |= SK_ISNULL; flags |= SK_ISNULL;
} }
else if (IsA(leftop, Param))
{
bool isnull;
/*
* if the leftop is a Param node then it means it
* identifies the value to place in our scan key.
*/
/* Life was so easy before ... subselects */
if (((Param *) leftop)->paramkind == PARAM_EXEC)
{
/* treat Param as runtime key */
have_runtime_keys = true;
run_keys[j] = LEFT_OP;
}
else
{
/* treat Param like a constant */
scanvalue = ExecEvalParam((Param *) leftop,
indexstate->ss.ps.ps_ExprContext,
&isnull);
if (isnull)
flags |= SK_ISNULL;
}
}
else else
{ {
/* /*
...@@ -826,20 +785,21 @@ ExecInitIndexScan(IndexScan *node, EState *estate) ...@@ -826,20 +785,21 @@ ExecInitIndexScan(IndexScan *node, EState *estate)
* key. * key.
*/ */
have_runtime_keys = true; have_runtime_keys = true;
run_keys[j] = LEFT_OP; run_keys[j] = ExecInitExpr(leftop, (PlanState *) indexstate);
} }
/* /*
* now determine information in rightop * now determine information in rightop
*/ */
rightop = (Node *) get_rightop((Expr *) clause); rightop = (Expr *) get_rightop((Expr *) clause);
if (rightop && IsA(rightop, RelabelType)) if (rightop && IsA(rightop, RelabelType))
rightop = (Node *) ((RelabelType *) rightop)->arg; rightop = ((RelabelType *) rightop)->arg;
Assert(rightop != NULL); Assert(rightop != NULL);
if (IsA(rightop, Var) &&var_is_rel((Var *) rightop)) if (IsA(rightop, Var) &&
var_is_rel((Var *) rightop))
{ {
/* /*
* here we make sure only one op identifies the * here we make sure only one op identifies the
...@@ -867,32 +827,6 @@ ExecInitIndexScan(IndexScan *node, EState *estate) ...@@ -867,32 +827,6 @@ ExecInitIndexScan(IndexScan *node, EState *estate)
if (((Const *) rightop)->constisnull) if (((Const *) rightop)->constisnull)
flags |= SK_ISNULL; flags |= SK_ISNULL;
} }
else if (IsA(rightop, Param))
{
bool isnull;
/*
* if the rightop is a Param node then it means it
* identifies the value to place in our scan key.
*/
/* Life was so easy before ... subselects */
if (((Param *) rightop)->paramkind == PARAM_EXEC)
{
/* treat Param as runtime key */
have_runtime_keys = true;
run_keys[j] = RIGHT_OP;
}
else
{
/* treat Param like a constant */
scanvalue = ExecEvalParam((Param *) rightop,
indexstate->ss.ps.ps_ExprContext,
&isnull);
if (isnull)
flags |= SK_ISNULL;
}
}
else else
{ {
/* /*
...@@ -901,7 +835,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate) ...@@ -901,7 +835,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate)
* key. * key.
*/ */
have_runtime_keys = true; have_runtime_keys = true;
run_keys[j] = RIGHT_OP; run_keys[j] = ExecInitExpr(rightop, (PlanState *) indexstate);
} }
/* /*
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeLimit.c,v 1.12 2002/12/05 15:50:33 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/nodeLimit.c,v 1.13 2002/12/13 19:45:54 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -301,9 +301,9 @@ ExecInitLimit(Limit *node, EState *estate) ...@@ -301,9 +301,9 @@ ExecInitLimit(Limit *node, EState *estate)
/* /*
* initialize child expressions * initialize child expressions
*/ */
limitstate->limitOffset = ExecInitExpr(node->limitOffset, limitstate->limitOffset = ExecInitExpr((Expr *) node->limitOffset,
(PlanState *) limitstate); (PlanState *) limitstate);
limitstate->limitCount = ExecInitExpr(node->limitCount, limitstate->limitCount = ExecInitExpr((Expr *) node->limitCount,
(PlanState *) limitstate); (PlanState *) limitstate);
#define LIMIT_NSLOTS 1 #define LIMIT_NSLOTS 1
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeMergejoin.c,v 1.53 2002/12/12 15:49:25 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/nodeMergejoin.c,v 1.54 2002/12/13 19:45:54 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -101,23 +101,26 @@ static bool MergeCompare(List *eqQual, List *compareQual, ExprContext *econtext) ...@@ -101,23 +101,26 @@ static bool MergeCompare(List *eqQual, List *compareQual, ExprContext *econtext)
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
static void static void
MJFormSkipQuals(List *qualList, List **ltQuals, List **gtQuals) MJFormSkipQuals(List *qualList, List **ltQuals, List **gtQuals,
PlanState *parent)
{ {
List *ltcdr, List *ltexprs,
*gtexprs,
*ltcdr,
*gtcdr; *gtcdr;
/* /*
* Make modifiable copies of the qualList. * Make modifiable copies of the qualList.
*/ */
*ltQuals = (List *) copyObject((Node *) qualList); ltexprs = (List *) copyObject((Node *) qualList);
*gtQuals = (List *) copyObject((Node *) qualList); gtexprs = (List *) copyObject((Node *) qualList);
/* /*
* Scan both lists in parallel, so that we can update the operators * Scan both lists in parallel, so that we can update the operators
* with the minimum number of syscache searches. * with the minimum number of syscache searches.
*/ */
ltcdr = *ltQuals; ltcdr = ltexprs;
foreach(gtcdr, *gtQuals) foreach(gtcdr, gtexprs)
{ {
OpExpr *ltop = (OpExpr *) lfirst(ltcdr); OpExpr *ltop = (OpExpr *) lfirst(ltcdr);
OpExpr *gtop = (OpExpr *) lfirst(gtcdr); OpExpr *gtop = (OpExpr *) lfirst(gtcdr);
...@@ -137,11 +140,15 @@ MJFormSkipQuals(List *qualList, List **ltQuals, List **gtQuals) ...@@ -137,11 +140,15 @@ MJFormSkipQuals(List *qualList, List **ltQuals, List **gtQuals)
&gtop->opno, &gtop->opno,
&ltop->opfuncid, &ltop->opfuncid,
&gtop->opfuncid); &gtop->opfuncid);
ltop->op_fcache = NULL;
gtop->op_fcache = NULL;
ltcdr = lnext(ltcdr); ltcdr = lnext(ltcdr);
} }
/*
* Prepare both lists for execution.
*/
*ltQuals = (List *) ExecInitExpr((Expr *) ltexprs, parent);
*gtQuals = (List *) ExecInitExpr((Expr *) gtexprs, parent);
} }
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
...@@ -193,8 +200,10 @@ MergeCompare(List *eqQual, List *compareQual, ExprContext *econtext) ...@@ -193,8 +200,10 @@ MergeCompare(List *eqQual, List *compareQual, ExprContext *econtext)
* *
* A NULL result is considered false. * A NULL result is considered false.
*/ */
const_value = ExecEvalExpr((Node *) lfirst(clause), econtext, const_value = ExecEvalExpr((ExprState *) lfirst(clause),
&isNull, NULL); econtext,
&isNull,
NULL);
if (DatumGetBool(const_value) && !isNull) if (DatumGetBool(const_value) && !isNull)
{ {
...@@ -208,7 +217,7 @@ MergeCompare(List *eqQual, List *compareQual, ExprContext *econtext) ...@@ -208,7 +217,7 @@ MergeCompare(List *eqQual, List *compareQual, ExprContext *econtext)
* key1 = key2 so we move on to the next pair of keys. * key1 = key2 so we move on to the next pair of keys.
*----------- *-----------
*/ */
const_value = ExecEvalExpr((Node *) lfirst(eqclause), const_value = ExecEvalExpr((ExprState *) lfirst(eqclause),
econtext, econtext,
&isNull, &isNull,
NULL); NULL);
...@@ -1409,17 +1418,17 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate) ...@@ -1409,17 +1418,17 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate)
* initialize child expressions * initialize child expressions
*/ */
mergestate->js.ps.targetlist = (List *) mergestate->js.ps.targetlist = (List *)
ExecInitExpr((Node *) node->join.plan.targetlist, ExecInitExpr((Expr *) node->join.plan.targetlist,
(PlanState *) mergestate); (PlanState *) mergestate);
mergestate->js.ps.qual = (List *) mergestate->js.ps.qual = (List *)
ExecInitExpr((Node *) node->join.plan.qual, ExecInitExpr((Expr *) node->join.plan.qual,
(PlanState *) mergestate); (PlanState *) mergestate);
mergestate->js.jointype = node->join.jointype; mergestate->js.jointype = node->join.jointype;
mergestate->js.joinqual = (List *) mergestate->js.joinqual = (List *)
ExecInitExpr((Node *) node->join.joinqual, ExecInitExpr((Expr *) node->join.joinqual,
(PlanState *) mergestate); (PlanState *) mergestate);
mergestate->mergeclauses = (List *) mergestate->mergeclauses = (List *)
ExecInitExpr((Node *) node->mergeclauses, ExecInitExpr((Expr *) node->mergeclauses,
(PlanState *) mergestate); (PlanState *) mergestate);
/* /*
...@@ -1492,7 +1501,8 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate) ...@@ -1492,7 +1501,8 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate)
*/ */
MJFormSkipQuals(node->mergeclauses, MJFormSkipQuals(node->mergeclauses,
&mergestate->mj_OuterSkipQual, &mergestate->mj_OuterSkipQual,
&mergestate->mj_InnerSkipQual); &mergestate->mj_InnerSkipQual,
(PlanState *) mergestate);
MJ_printf("\nExecInitMergeJoin: OuterSkipQual is "); MJ_printf("\nExecInitMergeJoin: OuterSkipQual is ");
MJ_nodeDisplay(mergestate->mj_OuterSkipQual); MJ_nodeDisplay(mergestate->mj_OuterSkipQual);
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeNestloop.c,v 1.27 2002/12/05 15:50:33 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/nodeNestloop.c,v 1.28 2002/12/13 19:45:55 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -286,14 +286,14 @@ ExecInitNestLoop(NestLoop *node, EState *estate) ...@@ -286,14 +286,14 @@ ExecInitNestLoop(NestLoop *node, EState *estate)
* initialize child expressions * initialize child expressions
*/ */
nlstate->js.ps.targetlist = (List *) nlstate->js.ps.targetlist = (List *)
ExecInitExpr((Node *) node->join.plan.targetlist, ExecInitExpr((Expr *) node->join.plan.targetlist,
(PlanState *) nlstate); (PlanState *) nlstate);
nlstate->js.ps.qual = (List *) nlstate->js.ps.qual = (List *)
ExecInitExpr((Node *) node->join.plan.qual, ExecInitExpr((Expr *) node->join.plan.qual,
(PlanState *) nlstate); (PlanState *) nlstate);
nlstate->js.jointype = node->join.jointype; nlstate->js.jointype = node->join.jointype;
nlstate->js.joinqual = (List *) nlstate->js.joinqual = (List *)
ExecInitExpr((Node *) node->join.joinqual, ExecInitExpr((Expr *) node->join.joinqual,
(PlanState *) nlstate); (PlanState *) nlstate);
/* /*
......
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeResult.c,v 1.22 2002/12/05 15:50:33 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/nodeResult.c,v 1.23 2002/12/13 19:45:55 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -205,12 +205,12 @@ ExecInitResult(Result *node, EState *estate) ...@@ -205,12 +205,12 @@ ExecInitResult(Result *node, EState *estate)
* initialize child expressions * initialize child expressions
*/ */
resstate->ps.targetlist = (List *) resstate->ps.targetlist = (List *)
ExecInitExpr((Node *) node->plan.targetlist, ExecInitExpr((Expr *) node->plan.targetlist,
(PlanState *) resstate); (PlanState *) resstate);
resstate->ps.qual = (List *) resstate->ps.qual = (List *)
ExecInitExpr((Node *) node->plan.qual, ExecInitExpr((Expr *) node->plan.qual,
(PlanState *) resstate); (PlanState *) resstate);
resstate->resconstantqual = ExecInitExpr(node->resconstantqual, resstate->resconstantqual = ExecInitExpr((Expr *) node->resconstantqual,
(PlanState *) resstate); (PlanState *) resstate);
/* /*
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeSeqscan.c,v 1.39 2002/12/05 15:50:33 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/nodeSeqscan.c,v 1.40 2002/12/13 19:45:55 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -207,10 +207,10 @@ ExecInitSeqScan(SeqScan *node, EState *estate) ...@@ -207,10 +207,10 @@ ExecInitSeqScan(SeqScan *node, EState *estate)
* initialize child expressions * initialize child expressions
*/ */
scanstate->ps.targetlist = (List *) scanstate->ps.targetlist = (List *)
ExecInitExpr((Node *) node->plan.targetlist, ExecInitExpr((Expr *) node->plan.targetlist,
(PlanState *) scanstate); (PlanState *) scanstate);
scanstate->ps.qual = (List *) scanstate->ps.qual = (List *)
ExecInitExpr((Node *) node->plan.qual, ExecInitExpr((Expr *) node->plan.qual,
(PlanState *) scanstate); (PlanState *) scanstate);
#define SEQSCAN_NSLOTS 2 #define SEQSCAN_NSLOTS 2
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeSubplan.c,v 1.36 2002/12/12 15:49:27 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/nodeSubplan.c,v 1.37 2002/12/13 19:45:55 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -30,11 +30,12 @@ ...@@ -30,11 +30,12 @@
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
Datum Datum
ExecSubPlan(SubPlanState *node, List *pvar, ExecSubPlan(SubPlanExprState *node,
ExprContext *econtext, bool *isNull) ExprContext *econtext,
bool *isNull)
{ {
PlanState *planstate = node->planstate; PlanState *planstate = node->planstate;
SubPlanExpr *subplan = (SubPlanExpr *) node->ps.plan; SubPlanExpr *subplan = (SubPlanExpr *) node->xprstate.expr;
SubLink *sublink = subplan->sublink; SubLink *sublink = subplan->sublink;
SubLinkType subLinkType = sublink->subLinkType; SubLinkType subLinkType = sublink->subLinkType;
bool useor = sublink->useor; bool useor = sublink->useor;
...@@ -42,6 +43,7 @@ ExecSubPlan(SubPlanState *node, List *pvar, ...@@ -42,6 +43,7 @@ ExecSubPlan(SubPlanState *node, List *pvar,
TupleTableSlot *slot; TupleTableSlot *slot;
Datum result; Datum result;
bool found = false; /* TRUE if got at least one subplan tuple */ bool found = false; /* TRUE if got at least one subplan tuple */
List *pvar;
List *lst; List *lst;
/* /*
...@@ -56,6 +58,7 @@ ExecSubPlan(SubPlanState *node, List *pvar, ...@@ -56,6 +58,7 @@ ExecSubPlan(SubPlanState *node, List *pvar,
/* /*
* Set Params of this plan from parent plan correlation Vars * Set Params of this plan from parent plan correlation Vars
*/ */
pvar = node->args;
if (subplan->parParam != NIL) if (subplan->parParam != NIL)
{ {
foreach(lst, subplan->parParam) foreach(lst, subplan->parParam)
...@@ -64,7 +67,7 @@ ExecSubPlan(SubPlanState *node, List *pvar, ...@@ -64,7 +67,7 @@ ExecSubPlan(SubPlanState *node, List *pvar,
prm = &(econtext->ecxt_param_exec_vals[lfirsti(lst)]); prm = &(econtext->ecxt_param_exec_vals[lfirsti(lst)]);
Assert(pvar != NIL); Assert(pvar != NIL);
prm->value = ExecEvalExprSwitchContext((Node *) lfirst(pvar), prm->value = ExecEvalExprSwitchContext((ExprState *) lfirst(pvar),
econtext, econtext,
&(prm->isnull), &(prm->isnull),
NULL); NULL);
...@@ -149,9 +152,10 @@ ExecSubPlan(SubPlanState *node, List *pvar, ...@@ -149,9 +152,10 @@ ExecSubPlan(SubPlanState *node, List *pvar,
* For ALL, ANY, and MULTIEXPR sublinks, iterate over combining * For ALL, ANY, and MULTIEXPR sublinks, iterate over combining
* operators for columns of tuple. * operators for columns of tuple.
*/ */
foreach(lst, sublink->oper) foreach(lst, node->oper)
{ {
OpExpr *expr = (OpExpr *) lfirst(lst); ExprState *exprstate = (ExprState *) lfirst(lst);
OpExpr *expr = (OpExpr *) exprstate->expr;
Param *prm = lsecond(expr->args); Param *prm = lsecond(expr->args);
ParamExecData *prmdata; ParamExecData *prmdata;
Datum expresult; Datum expresult;
...@@ -194,7 +198,7 @@ ExecSubPlan(SubPlanState *node, List *pvar, ...@@ -194,7 +198,7 @@ ExecSubPlan(SubPlanState *node, List *pvar,
/* /*
* Now we can eval the combining operator for this column. * Now we can eval the combining operator for this column.
*/ */
expresult = ExecEvalExprSwitchContext((Node *) expr, econtext, expresult = ExecEvalExprSwitchContext(exprstate, econtext,
&expnull, NULL); &expnull, NULL);
/* /*
...@@ -287,64 +291,57 @@ ExecSubPlan(SubPlanState *node, List *pvar, ...@@ -287,64 +291,57 @@ ExecSubPlan(SubPlanState *node, List *pvar,
* ExecInitSubPlan * ExecInitSubPlan
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
SubPlanState * void
ExecInitSubPlan(SubPlanExpr *node, EState *estate) ExecInitSubPlan(SubPlanExprState *sstate, EState *estate)
{ {
SubPlanState *subplanstate; SubPlanExpr *expr = (SubPlanExpr *) sstate->xprstate.expr;
EState *sp_estate; EState *sp_estate;
/* /*
* Do access checking on the rangetable entries in the subquery. * Do access checking on the rangetable entries in the subquery.
* Here, we assume the subquery is a SELECT. * Here, we assume the subquery is a SELECT.
*/ */
ExecCheckRTPerms(node->rtable, CMD_SELECT); ExecCheckRTPerms(expr->rtable, CMD_SELECT);
/* /*
* create state structure * initialize state
*/ */
subplanstate = makeNode(SubPlanState); sstate->needShutdown = false;
subplanstate->ps.plan = (Plan *) node; sstate->curTuple = NULL;
subplanstate->ps.state = estate;
subplanstate->needShutdown = false;
subplanstate->curTuple = NULL;
/* XXX temporary hack */
node->pstate = subplanstate;
/* /*
* create an EState for the subplan * create an EState for the subplan
*/ */
sp_estate = CreateExecutorState(); sp_estate = CreateExecutorState();
sp_estate->es_range_table = node->rtable; sp_estate->es_range_table = expr->rtable;
sp_estate->es_param_list_info = estate->es_param_list_info; sp_estate->es_param_list_info = estate->es_param_list_info;
sp_estate->es_param_exec_vals = estate->es_param_exec_vals; sp_estate->es_param_exec_vals = estate->es_param_exec_vals;
sp_estate->es_tupleTable = sp_estate->es_tupleTable =
ExecCreateTupleTable(ExecCountSlotsNode(node->plan) + 10); ExecCreateTupleTable(ExecCountSlotsNode(expr->plan) + 10);
sp_estate->es_snapshot = estate->es_snapshot; sp_estate->es_snapshot = estate->es_snapshot;
sp_estate->es_instrument = estate->es_instrument; sp_estate->es_instrument = estate->es_instrument;
/* /*
* Start up the subplan * Start up the subplan
*/ */
subplanstate->planstate = ExecInitNode(node->plan, sp_estate); sstate->planstate = ExecInitNode(expr->plan, sp_estate);
subplanstate->needShutdown = true; /* now we need to shutdown the subplan */ sstate->needShutdown = true; /* now we need to shutdown the subplan */
/* /*
* If this plan is un-correlated or undirect correlated one and want * If this plan is un-correlated or undirect correlated one and want
* to set params for parent plan then prepare parameters. * to set params for parent plan then prepare parameters.
*/ */
if (node->setParam != NIL) if (expr->setParam != NIL)
{ {
List *lst; List *lst;
foreach(lst, node->setParam) foreach(lst, expr->setParam)
{ {
ParamExecData *prm = &(estate->es_param_exec_vals[lfirsti(lst)]); ParamExecData *prm = &(estate->es_param_exec_vals[lfirsti(lst)]);
prm->execPlan = subplanstate; prm->execPlan = sstate;
} }
/* /*
...@@ -353,8 +350,6 @@ ExecInitSubPlan(SubPlanExpr *node, EState *estate) ...@@ -353,8 +350,6 @@ ExecInitSubPlan(SubPlanExpr *node, EState *estate)
* it, for others - it doesn't matter... * it, for others - it doesn't matter...
*/ */
} }
return subplanstate;
} }
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
...@@ -371,12 +366,11 @@ ExecInitSubPlan(SubPlanExpr *node, EState *estate) ...@@ -371,12 +366,11 @@ ExecInitSubPlan(SubPlanExpr *node, EState *estate)
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
void void
ExecSetParamPlan(SubPlanState *node, ExprContext *econtext) ExecSetParamPlan(SubPlanExprState *node, ExprContext *econtext)
{ {
PlanState *planstate = node->planstate; PlanState *planstate = node->planstate;
SubPlanExpr *subplan = (SubPlanExpr *) node->ps.plan; SubPlanExpr *subplan = (SubPlanExpr *) node->xprstate.expr;
SubLink *sublink = subplan->sublink; SubLinkType subLinkType = subplan->sublink->subLinkType;
EState *estate = node->ps.state;
MemoryContext oldcontext; MemoryContext oldcontext;
TupleTableSlot *slot; TupleTableSlot *slot;
List *lst; List *lst;
...@@ -388,8 +382,8 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext) ...@@ -388,8 +382,8 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext)
*/ */
oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory); oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
if (sublink->subLinkType == ANY_SUBLINK || if (subLinkType == ANY_SUBLINK ||
sublink->subLinkType == ALL_SUBLINK) subLinkType == ALL_SUBLINK)
elog(ERROR, "ExecSetParamPlan: ANY/ALL subselect unsupported"); elog(ERROR, "ExecSetParamPlan: ANY/ALL subselect unsupported");
if (planstate->chgParam != NULL) if (planstate->chgParam != NULL)
...@@ -403,9 +397,9 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext) ...@@ -403,9 +397,9 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext)
TupleDesc tdesc = slot->ttc_tupleDescriptor; TupleDesc tdesc = slot->ttc_tupleDescriptor;
int i = 1; int i = 1;
if (sublink->subLinkType == EXISTS_SUBLINK) if (subLinkType == EXISTS_SUBLINK)
{ {
ParamExecData *prm = &(estate->es_param_exec_vals[lfirsti(subplan->setParam)]); ParamExecData *prm = &(econtext->ecxt_param_exec_vals[lfirsti(subplan->setParam)]);
prm->execPlan = NULL; prm->execPlan = NULL;
prm->value = BoolGetDatum(true); prm->value = BoolGetDatum(true);
...@@ -415,8 +409,8 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext) ...@@ -415,8 +409,8 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext)
} }
if (found && if (found &&
(sublink->subLinkType == EXPR_SUBLINK || (subLinkType == EXPR_SUBLINK ||
sublink->subLinkType == MULTIEXPR_SUBLINK)) subLinkType == MULTIEXPR_SUBLINK))
elog(ERROR, "More than one tuple returned by a subselect used as an expression."); elog(ERROR, "More than one tuple returned by a subselect used as an expression.");
found = true; found = true;
...@@ -434,7 +428,7 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext) ...@@ -434,7 +428,7 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext)
foreach(lst, subplan->setParam) foreach(lst, subplan->setParam)
{ {
ParamExecData *prm = &(estate->es_param_exec_vals[lfirsti(lst)]); ParamExecData *prm = &(econtext->ecxt_param_exec_vals[lfirsti(lst)]);
prm->execPlan = NULL; prm->execPlan = NULL;
prm->value = heap_getattr(tup, i, tdesc, &(prm->isnull)); prm->value = heap_getattr(tup, i, tdesc, &(prm->isnull));
...@@ -444,9 +438,9 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext) ...@@ -444,9 +438,9 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext)
if (!found) if (!found)
{ {
if (sublink->subLinkType == EXISTS_SUBLINK) if (subLinkType == EXISTS_SUBLINK)
{ {
ParamExecData *prm = &(estate->es_param_exec_vals[lfirsti(subplan->setParam)]); ParamExecData *prm = &(econtext->ecxt_param_exec_vals[lfirsti(subplan->setParam)]);
prm->execPlan = NULL; prm->execPlan = NULL;
prm->value = BoolGetDatum(false); prm->value = BoolGetDatum(false);
...@@ -456,7 +450,7 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext) ...@@ -456,7 +450,7 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext)
{ {
foreach(lst, subplan->setParam) foreach(lst, subplan->setParam)
{ {
ParamExecData *prm = &(estate->es_param_exec_vals[lfirsti(lst)]); ParamExecData *prm = &(econtext->ecxt_param_exec_vals[lfirsti(lst)]);
prm->execPlan = NULL; prm->execPlan = NULL;
prm->value = (Datum) 0; prm->value = (Datum) 0;
...@@ -479,7 +473,7 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext) ...@@ -479,7 +473,7 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext)
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
void void
ExecEndSubPlan(SubPlanState *node) ExecEndSubPlan(SubPlanExprState *node)
{ {
if (node->needShutdown) if (node->needShutdown)
{ {
...@@ -494,11 +488,11 @@ ExecEndSubPlan(SubPlanState *node) ...@@ -494,11 +488,11 @@ ExecEndSubPlan(SubPlanState *node)
} }
void void
ExecReScanSetParamPlan(SubPlanState *node, PlanState *parent) ExecReScanSetParamPlan(SubPlanExprState *node, PlanState *parent)
{ {
PlanState *planstate = node->planstate; PlanState *planstate = node->planstate;
SubPlanExpr *subplan = (SubPlanExpr *) node->ps.plan; SubPlanExpr *subplan = (SubPlanExpr *) node->xprstate.expr;
EState *estate = node->ps.state; EState *estate = parent->state;
List *lst; List *lst;
if (subplan->parParam != NULL) if (subplan->parParam != NULL)
...@@ -509,8 +503,7 @@ ExecReScanSetParamPlan(SubPlanState *node, PlanState *parent) ...@@ -509,8 +503,7 @@ ExecReScanSetParamPlan(SubPlanState *node, PlanState *parent)
elog(ERROR, "ExecReScanSetParamPlan: extParam list of plan is NULL"); elog(ERROR, "ExecReScanSetParamPlan: extParam list of plan is NULL");
/* /*
* Don't actual re-scan: ExecSetParamPlan does re-scan if * Don't actually re-scan: ExecSetParamPlan does it if needed.
* subplan->plan->chgParam is not NULL... ExecReScan (planstate, NULL);
*/ */
/* /*
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeSubqueryscan.c,v 1.14 2002/12/05 15:50:33 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/nodeSubqueryscan.c,v 1.15 2002/12/13 19:45:55 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -131,10 +131,10 @@ ExecInitSubqueryScan(SubqueryScan *node, EState *estate) ...@@ -131,10 +131,10 @@ ExecInitSubqueryScan(SubqueryScan *node, EState *estate)
* initialize child expressions * initialize child expressions
*/ */
subquerystate->ss.ps.targetlist = (List *) subquerystate->ss.ps.targetlist = (List *)
ExecInitExpr((Node *) node->scan.plan.targetlist, ExecInitExpr((Expr *) node->scan.plan.targetlist,
(PlanState *) subquerystate); (PlanState *) subquerystate);
subquerystate->ss.ps.qual = (List *) subquerystate->ss.ps.qual = (List *)
ExecInitExpr((Node *) node->scan.plan.qual, ExecInitExpr((Expr *) node->scan.plan.qual,
(PlanState *) subquerystate); (PlanState *) subquerystate);
#define SUBQUERYSCAN_NSLOTS 1 #define SUBQUERYSCAN_NSLOTS 1
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeTidscan.c,v 1.28 2002/12/05 15:50:34 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/nodeTidscan.c,v 1.29 2002/12/13 19:45:56 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -380,10 +380,10 @@ ExecInitTidScan(TidScan *node, EState *estate) ...@@ -380,10 +380,10 @@ ExecInitTidScan(TidScan *node, EState *estate)
* initialize child expressions * initialize child expressions
*/ */
tidstate->ss.ps.targetlist = (List *) tidstate->ss.ps.targetlist = (List *)
ExecInitExpr((Node *) node->scan.plan.targetlist, ExecInitExpr((Expr *) node->scan.plan.targetlist,
(PlanState *) tidstate); (PlanState *) tidstate);
tidstate->ss.ps.qual = (List *) tidstate->ss.ps.qual = (List *)
ExecInitExpr((Node *) node->scan.plan.qual, ExecInitExpr((Expr *) node->scan.plan.qual,
(PlanState *) tidstate); (PlanState *) tidstate);
#define TIDSCAN_NSLOTS 2 #define TIDSCAN_NSLOTS 2
...@@ -404,7 +404,10 @@ ExecInitTidScan(TidScan *node, EState *estate) ...@@ -404,7 +404,10 @@ ExecInitTidScan(TidScan *node, EState *estate)
* get the tid node information * get the tid node information
*/ */
tidList = (ItemPointerData *) palloc(length(node->tideval) * sizeof(ItemPointerData)); tidList = (ItemPointerData *) palloc(length(node->tideval) * sizeof(ItemPointerData));
numTids = TidListCreate(node->tideval, tidstate->tss_tideval = (List *)
ExecInitExpr((Expr *) node->tideval,
(PlanState *) tidstate);
numTids = TidListCreate(tidstate->tss_tideval,
tidstate->ss.ps.ps_ExprContext, tidstate->ss.ps.ps_ExprContext,
tidList); tidList);
tidPtr = -1; tidPtr = -1;
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.231 2002/12/12 20:35:12 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.232 2002/12/13 19:45:56 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -710,7 +710,6 @@ _copyAggref(Aggref *from) ...@@ -710,7 +710,6 @@ _copyAggref(Aggref *from)
COPY_NODE_FIELD(target); COPY_NODE_FIELD(target);
COPY_SCALAR_FIELD(aggstar); COPY_SCALAR_FIELD(aggstar);
COPY_SCALAR_FIELD(aggdistinct); COPY_SCALAR_FIELD(aggdistinct);
COPY_SCALAR_FIELD(aggno); /* will go away soon */
return newnode; return newnode;
} }
...@@ -750,9 +749,6 @@ _copyFuncExpr(FuncExpr *from) ...@@ -750,9 +749,6 @@ _copyFuncExpr(FuncExpr *from)
COPY_SCALAR_FIELD(funcformat); COPY_SCALAR_FIELD(funcformat);
COPY_NODE_FIELD(args); COPY_NODE_FIELD(args);
/* Do not copy the run-time state, if any */
newnode->func_fcache = NULL;
return newnode; return newnode;
} }
...@@ -770,9 +766,6 @@ _copyOpExpr(OpExpr *from) ...@@ -770,9 +766,6 @@ _copyOpExpr(OpExpr *from)
COPY_SCALAR_FIELD(opretset); COPY_SCALAR_FIELD(opretset);
COPY_NODE_FIELD(args); COPY_NODE_FIELD(args);
/* Do not copy the run-time state, if any */
newnode->op_fcache = NULL;
return newnode; return newnode;
} }
...@@ -790,9 +783,6 @@ _copyDistinctExpr(DistinctExpr *from) ...@@ -790,9 +783,6 @@ _copyDistinctExpr(DistinctExpr *from)
COPY_SCALAR_FIELD(opretset); COPY_SCALAR_FIELD(opretset);
COPY_NODE_FIELD(args); COPY_NODE_FIELD(args);
/* Do not copy the run-time state, if any */
newnode->op_fcache = NULL;
return newnode; return newnode;
} }
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/nodeFuncs.c,v 1.20 2002/12/12 15:49:28 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/nodes/nodeFuncs.c,v 1.21 2002/12/13 19:45:56 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -88,5 +88,4 @@ set_opfuncid(OpExpr *opexpr) ...@@ -88,5 +88,4 @@ set_opfuncid(OpExpr *opexpr)
{ {
if (opexpr->opfuncid == InvalidOid) if (opexpr->opfuncid == InvalidOid)
opexpr->opfuncid = get_opcode(opexpr->opno); opexpr->opfuncid = get_opcode(opexpr->opno);
opexpr->op_fcache = NULL; /* XXX will go away soon */
} }
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.188 2002/12/12 20:35:12 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.189 2002/12/13 19:45:56 tgl Exp $
* *
* NOTES * NOTES
* Every node type that can appear in stored rules' parsetrees *must* * Every node type that can appear in stored rules' parsetrees *must*
...@@ -214,8 +214,6 @@ _outDatum(StringInfo str, Datum value, int typlen, bool typbyval) ...@@ -214,8 +214,6 @@ _outDatum(StringInfo str, Datum value, int typlen, bool typbyval)
/* /*
* print the basic stuff of all nodes that inherit from Plan * print the basic stuff of all nodes that inherit from Plan
*
* NOTE: we deliberately omit the execution state (EState)
*/ */
static void static void
_outPlanInfo(StringInfo str, Plan *node) _outPlanInfo(StringInfo str, Plan *node)
......
...@@ -8,12 +8,13 @@ ...@@ -8,12 +8,13 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.142 2002/12/12 20:35:12 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.143 2002/12/13 19:45:56 tgl Exp $
* *
* NOTES * NOTES
* Path and Plan nodes do not have any readfuncs support, because we * Path and Plan nodes do not have any readfuncs support, because we
* never have occasion to read them in. (There was once code here that * never have occasion to read them in. (There was once code here that
* claimed to read them, but it was broken as well as unused.) * claimed to read them, but it was broken as well as unused.) We
* never read executor state trees, either.
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -439,8 +440,6 @@ _readFuncExpr(void) ...@@ -439,8 +440,6 @@ _readFuncExpr(void)
READ_ENUM_FIELD(funcformat, CoercionForm); READ_ENUM_FIELD(funcformat, CoercionForm);
READ_NODE_FIELD(args); READ_NODE_FIELD(args);
local_node->func_fcache = NULL;
READ_DONE(); READ_DONE();
} }
...@@ -468,8 +467,6 @@ _readOpExpr(void) ...@@ -468,8 +467,6 @@ _readOpExpr(void)
READ_BOOL_FIELD(opretset); READ_BOOL_FIELD(opretset);
READ_NODE_FIELD(args); READ_NODE_FIELD(args);
local_node->op_fcache = NULL;
READ_DONE(); READ_DONE();
} }
...@@ -497,8 +494,6 @@ _readDistinctExpr(void) ...@@ -497,8 +494,6 @@ _readDistinctExpr(void)
READ_BOOL_FIELD(opretset); READ_BOOL_FIELD(opretset);
READ_NODE_FIELD(args); READ_NODE_FIELD(args);
local_node->op_fcache = NULL;
READ_DONE(); READ_DONE();
} }
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.127 2002/12/12 15:49:28 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.128 2002/12/13 19:45:56 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1124,6 +1124,7 @@ pred_test_simple_clause(Expr *predicate, Node *clause) ...@@ -1124,6 +1124,7 @@ pred_test_simple_clause(Expr *predicate, Node *clause)
clause_strategy, clause_strategy,
test_strategy; test_strategy;
Expr *test_expr; Expr *test_expr;
ExprState *test_exprstate;
Datum test_result; Datum test_result;
bool isNull; bool isNull;
Relation relation; Relation relation;
...@@ -1274,9 +1275,10 @@ pred_test_simple_clause(Expr *predicate, Node *clause) ...@@ -1274,9 +1275,10 @@ pred_test_simple_clause(Expr *predicate, Node *clause)
(Expr *) clause_const, (Expr *) clause_const,
(Expr *) pred_const); (Expr *) pred_const);
set_opfuncid((OpExpr *) test_expr); set_opfuncid((OpExpr *) test_expr);
test_exprstate = ExecInitExpr(test_expr, NULL);
econtext = MakeExprContext(NULL, TransactionCommandContext); econtext = MakeExprContext(NULL, CurrentMemoryContext);
test_result = ExecEvalExprSwitchContext((Node *) test_expr, econtext, test_result = ExecEvalExprSwitchContext(test_exprstate, econtext,
&isNull, NULL); &isNull, NULL);
FreeExprContext(econtext); FreeExprContext(econtext);
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.117 2002/12/12 20:35:12 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.118 2002/12/13 19:45:56 tgl Exp $
* *
* HISTORY * HISTORY
* AUTHOR DATE MAJOR EVENT * AUTHOR DATE MAJOR EVENT
...@@ -1315,7 +1315,18 @@ eval_const_expressions_mutator(Node *node, List *active_fns) ...@@ -1315,7 +1315,18 @@ eval_const_expressions_mutator(Node *node, List *active_fns)
simple = simplify_function(expr->opfuncid, args, simple = simplify_function(expr->opfuncid, args,
false, active_fns); false, active_fns);
if (simple) /* successfully simplified it */ if (simple) /* successfully simplified it */
return (Node *) simple; {
/*
* Since the underlying operator is "=", must negate its
* result
*/
Const *csimple = (Const *) simple;
Assert(IsA(csimple, Const));
csimple->constvalue =
BoolGetDatum(!DatumGetBool(csimple->constvalue));
return (Node *) csimple;
}
} }
/* /*
...@@ -1672,6 +1683,7 @@ evaluate_function(Oid funcid, List *args, HeapTuple func_tuple) ...@@ -1672,6 +1683,7 @@ evaluate_function(Oid funcid, List *args, HeapTuple func_tuple)
bool has_nonconst_input = false; bool has_nonconst_input = false;
bool has_null_input = false; bool has_null_input = false;
FuncExpr *newexpr; FuncExpr *newexpr;
ExprState *newexprstate;
ExprContext *econtext; ExprContext *econtext;
Datum const_val; Datum const_val;
bool const_is_null; bool const_is_null;
...@@ -1738,7 +1750,9 @@ evaluate_function(Oid funcid, List *args, HeapTuple func_tuple) ...@@ -1738,7 +1750,9 @@ evaluate_function(Oid funcid, List *args, HeapTuple func_tuple)
*/ */
econtext = MakeExprContext(NULL, CurrentMemoryContext); econtext = MakeExprContext(NULL, CurrentMemoryContext);
const_val = ExecEvalExprSwitchContext((Node *) newexpr, econtext, newexprstate = ExecInitExpr((Expr *) newexpr, NULL);
const_val = ExecEvalExprSwitchContext(newexprstate, econtext,
&const_is_null, NULL); &const_is_null, NULL);
/* Must copy result out of sub-context used by expression eval */ /* Must copy result out of sub-context used by expression eval */
...@@ -1746,7 +1760,6 @@ evaluate_function(Oid funcid, List *args, HeapTuple func_tuple) ...@@ -1746,7 +1760,6 @@ evaluate_function(Oid funcid, List *args, HeapTuple func_tuple)
const_val = datumCopy(const_val, resultTypByVal, resultTypLen); const_val = datumCopy(const_val, resultTypByVal, resultTypLen);
FreeExprContext(econtext); FreeExprContext(econtext);
pfree(newexpr);
/* /*
* Make the constant result node. * Make the constant result node.
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.256 2002/12/12 20:35:12 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.257 2002/12/13 19:45:56 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -23,7 +23,6 @@ ...@@ -23,7 +23,6 @@
#include "commands/prepare.h" #include "commands/prepare.h"
#include "nodes/makefuncs.h" #include "nodes/makefuncs.h"
#include "optimizer/clauses.h" #include "optimizer/clauses.h"
#include "optimizer/planmain.h"
#include "parser/analyze.h" #include "parser/analyze.h"
#include "parser/gramparse.h" #include "parser/gramparse.h"
#include "parser/parsetree.h" #include "parser/parsetree.h"
...@@ -2424,8 +2423,6 @@ transformExecuteStmt(ParseState *pstate, ExecuteStmt *stmt) ...@@ -2424,8 +2423,6 @@ transformExecuteStmt(ParseState *pstate, ExecuteStmt *stmt)
format_type_be(given_type_id), format_type_be(given_type_id),
format_type_be(expected_type_id)); format_type_be(expected_type_id));
fix_opfuncids(expr);
lfirst(l) = expr; lfirst(l) = expr;
paramtypes = lnext(paramtypes); paramtypes = lnext(paramtypes);
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/sets.c,v 1.54 2002/09/04 20:31:29 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/sets.c,v 1.55 2002/12/13 19:45:56 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -24,7 +24,6 @@ ...@@ -24,7 +24,6 @@
#include "catalog/pg_namespace.h" #include "catalog/pg_namespace.h"
#include "catalog/pg_proc.h" #include "catalog/pg_proc.h"
#include "executor/executor.h" #include "executor/executor.h"
#include "utils/fcache.h"
#include "utils/fmgroids.h" #include "utils/fmgroids.h"
#include "utils/sets.h" #include "utils/sets.h"
#include "utils/syscache.h" #include "utils/syscache.h"
...@@ -143,7 +142,7 @@ Datum ...@@ -143,7 +142,7 @@ Datum
seteval(PG_FUNCTION_ARGS) seteval(PG_FUNCTION_ARGS)
{ {
Oid funcoid = PG_GETARG_OID(0); Oid funcoid = PG_GETARG_OID(0);
FunctionCachePtr fcache; FuncExprState *fcache;
Datum result; Datum result;
bool isNull; bool isNull;
ExprDoneCond isDone; ExprDoneCond isDone;
...@@ -152,10 +151,27 @@ seteval(PG_FUNCTION_ARGS) ...@@ -152,10 +151,27 @@ seteval(PG_FUNCTION_ARGS)
* If this is the first call, we need to set up the fcache for the * If this is the first call, we need to set up the fcache for the
* target set's function. * target set's function.
*/ */
fcache = (FunctionCachePtr) fcinfo->flinfo->fn_extra; fcache = (FuncExprState *) fcinfo->flinfo->fn_extra;
if (fcache == NULL) if (fcache == NULL)
{ {
fcache = init_fcache(funcoid, 0, fcinfo->flinfo->fn_mcxt); MemoryContext oldcontext;
FuncExpr *func;
oldcontext = MemoryContextSwitchTo(fcinfo->flinfo->fn_mcxt);
func = makeNode(FuncExpr);
func->funcid = funcoid;
func->funcresulttype = InvalidOid; /* nothing will look at this */
func->funcretset = true;
func->funcformat = COERCE_EXPLICIT_CALL;
func->args = NIL; /* there are no arguments */
fcache = (FuncExprState *) ExecInitExpr((Expr *) func, NULL);
MemoryContextSwitchTo(oldcontext);
init_fcache(funcoid, fcache, fcinfo->flinfo->fn_mcxt);
fcinfo->flinfo->fn_extra = (void *) fcache; fcinfo->flinfo->fn_extra = (void *) fcache;
} }
...@@ -169,22 +185,10 @@ seteval(PG_FUNCTION_ARGS) ...@@ -169,22 +185,10 @@ seteval(PG_FUNCTION_ARGS)
isDone = ExprSingleResult; isDone = ExprSingleResult;
result = ExecMakeFunctionResult(fcache, result = ExecMakeFunctionResult(fcache,
NIL,
NULL, /* no econtext, see above */ NULL, /* no econtext, see above */
&isNull, &isNull,
&isDone); &isDone);
/*
* If we're done with the results of this set function, get rid of its
* func cache so that we will start from the top next time. (Can you
* say "memory leak"? This feature is a crock anyway...)
*/
if (isDone != ExprMultipleResult)
{
pfree(fcache);
fcinfo->flinfo->fn_extra = NULL;
}
/* /*
* Return isNull/isDone status. * Return isNull/isDone status.
*/ */
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
# Makefile for utils/cache # Makefile for utils/cache
# #
# IDENTIFICATION # IDENTIFICATION
# $Header: /cvsroot/pgsql/src/backend/utils/cache/Makefile,v 1.16 2002/03/31 06:26:31 tgl Exp $ # $Header: /cvsroot/pgsql/src/backend/utils/cache/Makefile,v 1.17 2002/12/13 19:45:56 tgl Exp $
# #
#------------------------------------------------------------------------- #-------------------------------------------------------------------------
...@@ -12,8 +12,7 @@ subdir = src/backend/utils/cache ...@@ -12,8 +12,7 @@ subdir = src/backend/utils/cache
top_builddir = ../../../.. top_builddir = ../../../..
include $(top_builddir)/src/Makefile.global include $(top_builddir)/src/Makefile.global
OBJS = catcache.o inval.o relcache.o syscache.o lsyscache.o \ OBJS = catcache.o inval.o relcache.o syscache.o lsyscache.o
fcache.o
all: SUBSYS.o all: SUBSYS.o
......
/*-------------------------------------------------------------------------
*
* fcache.c
* Code for the 'function cache' used in Oper and Func nodes.
*
*
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/cache/Attic/fcache.c,v 1.45 2002/06/20 20:29:39 momjian Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "miscadmin.h"
#include "utils/acl.h"
#include "utils/fcache.h"
#include "utils/lsyscache.h"
/*
* Build a 'FunctionCache' struct given the PG_PROC oid.
*/
FunctionCachePtr
init_fcache(Oid foid, int nargs, MemoryContext fcacheCxt)
{
FunctionCachePtr retval;
AclResult aclresult;
/* Check permission to call function */
aclresult = pg_proc_aclcheck(foid, GetUserId(), ACL_EXECUTE);
if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, get_func_name(foid));
/* Safety check (should never fail, as parser should check sooner) */
if (nargs > FUNC_MAX_ARGS)
elog(ERROR, "init_fcache: too many arguments");
/* Create fcache entry in the desired context */
retval = (FunctionCachePtr) MemoryContextAlloc(fcacheCxt,
sizeof(FunctionCache));
MemSet(retval, 0, sizeof(FunctionCache));
/* Set up the primary fmgr lookup information */
fmgr_info_cxt(foid, &(retval->func), fcacheCxt);
/* Initialize additional info */
retval->setArgsValid = false;
return retval;
}
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: executor.h,v 1.81 2002/12/05 15:50:36 tgl Exp $ * $Id: executor.h,v 1.82 2002/12/13 19:45:56 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -73,26 +73,27 @@ extern TupleDesc ExecGetTupType(PlanState *node); ...@@ -73,26 +73,27 @@ extern TupleDesc ExecGetTupType(PlanState *node);
/* /*
* prototypes from functions in execQual.c * prototypes from functions in execQual.c
*/ */
extern Datum ExecEvalParam(Param *expression, ExprContext *econtext,
bool *isNull);
extern Datum GetAttributeByNum(TupleTableSlot *slot, AttrNumber attrno, extern Datum GetAttributeByNum(TupleTableSlot *slot, AttrNumber attrno,
bool *isNull); bool *isNull);
extern Datum GetAttributeByName(TupleTableSlot *slot, char *attname, extern Datum GetAttributeByName(TupleTableSlot *slot, char *attname,
bool *isNull); bool *isNull);
extern Datum ExecMakeFunctionResult(FunctionCachePtr fcache, extern void init_fcache(Oid foid, FuncExprState *fcache,
List *arguments, MemoryContext fcacheCxt);
extern Datum ExecMakeFunctionResult(FuncExprState *fcache,
ExprContext *econtext, ExprContext *econtext,
bool *isNull, bool *isNull,
ExprDoneCond *isDone); ExprDoneCond *isDone);
extern Tuplestorestate *ExecMakeTableFunctionResult(Node *funcexpr, extern Tuplestorestate *ExecMakeTableFunctionResult(ExprState *funcexpr,
ExprContext *econtext, ExprContext *econtext,
TupleDesc expectedDesc, TupleDesc expectedDesc,
TupleDesc *returnDesc); TupleDesc *returnDesc);
extern Datum ExecEvalExpr(Node *expression, ExprContext *econtext, extern Datum ExecEvalExpr(ExprState *expression, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone); bool *isNull, ExprDoneCond *isDone);
extern Datum ExecEvalExprSwitchContext(Node *expression, ExprContext *econtext, extern Datum ExecEvalExprSwitchContext(ExprState *expression, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone); bool *isNull, ExprDoneCond *isDone);
extern Node *ExecInitExpr(Node *node, PlanState *parent); extern ExprState *ExecInitExpr(Expr *node, PlanState *parent);
extern SubPlanExprState *ExecInitExprInitPlan(SubPlanExpr *node,
PlanState *parent);
extern bool ExecQual(List *qual, ExprContext *econtext, bool resultForNull); extern bool ExecQual(List *qual, ExprContext *econtext, bool resultForNull);
extern int ExecTargetListLength(List *targetlist); extern int ExecTargetListLength(List *targetlist);
extern int ExecCleanTargetListLength(List *targetlist); extern int ExecCleanTargetListLength(List *targetlist);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: nodeSubplan.h,v 1.13 2002/12/12 15:49:40 tgl Exp $ * $Id: nodeSubplan.h,v 1.14 2002/12/13 19:45:56 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -16,12 +16,13 @@ ...@@ -16,12 +16,13 @@
#include "nodes/execnodes.h" #include "nodes/execnodes.h"
extern SubPlanState *ExecInitSubPlan(SubPlanExpr *node, EState *estate); extern void ExecInitSubPlan(SubPlanExprState *sstate, EState *estate);
extern Datum ExecSubPlan(SubPlanState *node, List *pvar, ExprContext *econtext, extern Datum ExecSubPlan(SubPlanExprState *node,
ExprContext *econtext,
bool *isNull); bool *isNull);
extern void ExecEndSubPlan(SubPlanState *node); extern void ExecEndSubPlan(SubPlanExprState *node);
extern void ExecReScanSetParamPlan(SubPlanState *node, PlanState *parent); extern void ExecReScanSetParamPlan(SubPlanExprState *node, PlanState *parent);
extern void ExecSetParamPlan(SubPlanState *node, ExprContext *econtext); extern void ExecSetParamPlan(SubPlanExprState *node, ExprContext *econtext);
#endif /* NODESUBPLAN_H */ #endif /* NODESUBPLAN_H */
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* *
* spi.h * spi.h
* *
* $Id: spi.h,v 1.33 2001/11/08 20:37:52 momjian Exp $ * $Id: spi.h,v 1.34 2002/12/13 19:45:56 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -30,7 +30,6 @@ ...@@ -30,7 +30,6 @@
#include "tcop/utility.h" #include "tcop/utility.h"
#include "tcop/dest.h" #include "tcop/dest.h"
#include "nodes/params.h" #include "nodes/params.h"
#include "utils/fcache.h"
#include "utils/datum.h" #include "utils/datum.h"
#include "utils/syscache.h" #include "utils/syscache.h"
#include "utils/builtins.h" #include "utils/builtins.h"
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: execnodes.h,v 1.83 2002/12/12 20:35:13 tgl Exp $ * $Id: execnodes.h,v 1.84 2002/12/13 19:45:57 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
* (ie, number of attrs from underlying relation) * (ie, number of attrs from underlying relation)
* KeyAttrNumbers underlying-rel attribute numbers used as keys * KeyAttrNumbers underlying-rel attribute numbers used as keys
* Predicate partial-index predicate, or NIL if none * Predicate partial-index predicate, or NIL if none
* PredicateState exec state for predicate, or NIL if none
* FuncOid OID of function, or InvalidOid if not f. index * FuncOid OID of function, or InvalidOid if not f. index
* FuncInfo fmgr lookup data for function, if FuncOid valid * FuncInfo fmgr lookup data for function, if FuncOid valid
* Unique is it a unique index? * Unique is it a unique index?
...@@ -47,7 +48,8 @@ typedef struct IndexInfo ...@@ -47,7 +48,8 @@ typedef struct IndexInfo
int ii_NumIndexAttrs; int ii_NumIndexAttrs;
int ii_NumKeyAttrs; int ii_NumKeyAttrs;
AttrNumber ii_KeyAttrNumbers[INDEX_MAX_KEYS]; AttrNumber ii_KeyAttrNumbers[INDEX_MAX_KEYS];
List *ii_Predicate; List *ii_Predicate; /* list of Expr */
List *ii_PredicateState; /* list of ExprState */
Oid ii_FuncOid; Oid ii_FuncOid;
FmgrInfo ii_FuncInfo; FmgrInfo ii_FuncInfo;
bool ii_Unique; bool ii_Unique;
...@@ -254,7 +256,7 @@ typedef struct JunkFilter ...@@ -254,7 +256,7 @@ typedef struct JunkFilter
* IndexRelationInfo array of key/attr info for indices * IndexRelationInfo array of key/attr info for indices
* TrigDesc triggers to be fired, if any * TrigDesc triggers to be fired, if any
* TrigFunctions cached lookup info for trigger functions * TrigFunctions cached lookup info for trigger functions
* ConstraintExprs array of constraint-checking expressions * ConstraintExprs array of constraint-checking expr states
* junkFilter for removing junk attributes from tuples * junkFilter for removing junk attributes from tuples
* ---------------- * ----------------
*/ */
...@@ -332,7 +334,178 @@ typedef struct EState ...@@ -332,7 +334,178 @@ typedef struct EState
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
* Executor State Information * Expression State Trees
*
* Each executable expression tree has a parallel ExprState tree.
*
* Unlike PlanState, there is not an exact one-for-one correspondence between
* ExprState node types and Expr node types. Many Expr node types have no
* need for node-type-specific run-time state, and so they can use plain
* ExprState or GenericExprState as their associated ExprState node type.
* ----------------------------------------------------------------
*/
/* ----------------
* ExprState node
*
* ExprState is the common superclass for all ExprState-type nodes.
*
* It can also be instantiated directly for leaf Expr nodes that need no
* local run-time state (such as Var, Const, or Param).
* ----------------
*/
typedef struct ExprState
{
NodeTag type;
Expr *expr; /* associated Expr node */
} ExprState;
/* ----------------
* GenericExprState node
*
* This is used for Expr node types that need no local run-time state,
* but have one child Expr node.
* ----------------
*/
typedef struct GenericExprState
{
ExprState xprstate;
ExprState *arg; /* state of my child node */
} GenericExprState;
/* ----------------
* AggrefExprState node
* ----------------
*/
typedef struct AggrefExprState
{
ExprState xprstate;
ExprState *target; /* state of my child node */
int aggno; /* ID number for agg within its plan node */
} AggrefExprState;
/* ----------------
* ArrayRefExprState node
* ----------------
*/
typedef struct ArrayRefExprState
{
ExprState xprstate;
List *refupperindexpr; /* states for child nodes */
List *reflowerindexpr;
ExprState *refexpr;
ExprState *refassgnexpr;
} ArrayRefExprState;
/* ----------------
* FuncExprState node
*
* Although named for FuncExpr, this is also used for OpExpr and DistinctExpr
* nodes; be careful to check what xprstate.expr is actually pointing at!
* ----------------
*/
typedef struct FuncExprState
{
ExprState xprstate;
List *args; /* states of argument expressions */
/*
* Function manager's lookup info for the target function. If func.fn_oid
* is InvalidOid, we haven't initialized it yet.
*/
FmgrInfo func;
/*
* We also need to store argument values across calls when evaluating a
* function-returning-set.
*
* setArgsValid is true when we are evaluating a set-valued function
* and we are in the middle of a call series; we want to pass the same
* argument values to the function again (and again, until it returns
* ExprEndResult).
*/
bool setArgsValid;
/*
* Flag to remember whether we found a set-valued argument to the
* function. This causes the function result to be a set as well.
* Valid only when setArgsValid is true.
*/
bool setHasSetArg; /* some argument returns a set */
/*
* Current argument data for a set-valued function; contains valid
* data only if setArgsValid is true.
*/
FunctionCallInfoData setArgs;
} FuncExprState;
/* ----------------
* BoolExprState node
* ----------------
*/
typedef struct BoolExprState
{
ExprState xprstate;
List *args; /* states of argument expression(s) */
} BoolExprState;
/* ----------------
* SubPlanExprState node
*
* Note: there is no separate ExprState node for the SubLink. All it would
* need is the oper field, which we can just as easily put here.
* ----------------
*/
typedef struct SubPlanExprState
{
ExprState xprstate;
struct PlanState *planstate; /* subselect plan's state tree */
bool needShutdown; /* TRUE = need to shutdown subplan */
HeapTuple curTuple; /* copy of most recent tuple from subplan */
List *args; /* states of argument expression(s) */
List *oper; /* states for executable combining exprs */
} SubPlanExprState;
/* ----------------
* CaseExprState node
* ----------------
*/
typedef struct CaseExprState
{
ExprState xprstate;
List *args; /* the arguments (list of WHEN clauses) */
ExprState *defresult; /* the default result (ELSE clause) */
} CaseExprState;
/* ----------------
* CaseWhenState node
* ----------------
*/
typedef struct CaseWhenState
{
ExprState xprstate;
ExprState *expr; /* condition expression */
ExprState *result; /* substitution result */
} CaseWhenState;
/* ----------------
* ConstraintTestState node
* ----------------
*/
typedef struct ConstraintTestState
{
ExprState xprstate;
ExprState *arg; /* input expression */
ExprState *check_expr; /* for CHECK test, a boolean expression */
} ConstraintTestState;
/* ----------------------------------------------------------------
* Executor State Trees
*
* An executing query has a PlanState tree paralleling the Plan tree
* that describes the plan.
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
...@@ -365,9 +538,9 @@ typedef struct PlanState ...@@ -365,9 +538,9 @@ typedef struct PlanState
List *qual; /* implicitly-ANDed qual conditions */ List *qual; /* implicitly-ANDed qual conditions */
struct PlanState *lefttree; /* input plan tree(s) */ struct PlanState *lefttree; /* input plan tree(s) */
struct PlanState *righttree; struct PlanState *righttree;
List *initPlan; /* Init SubPlanState nodes (un-correlated List *initPlan; /* Init SubPlanExprState nodes (un-correlated
* expr subselects) */ * expr subselects) */
List *subPlan; /* SubPlanState nodes in my expressions */ List *subPlan; /* SubPlanExprState nodes in my expressions */
/* /*
* State for management of parameter-change-driven rescanning * State for management of parameter-change-driven rescanning
...@@ -403,7 +576,7 @@ typedef struct PlanState ...@@ -403,7 +576,7 @@ typedef struct PlanState
typedef struct ResultState typedef struct ResultState
{ {
PlanState ps; /* its first field is NodeTag */ PlanState ps; /* its first field is NodeTag */
Node *resconstantqual; ExprState *resconstantqual;
bool rs_done; /* are we done? */ bool rs_done; /* are we done? */
bool rs_checkqual; /* do we need to check the qual? */ bool rs_checkqual; /* do we need to check the qual? */
} ResultState; } ResultState;
...@@ -467,7 +640,8 @@ typedef ScanState SeqScanState; ...@@ -467,7 +640,8 @@ typedef ScanState SeqScanState;
* IndexPtr current index in use * IndexPtr current index in use
* ScanKeys Skey structures to scan index rels * ScanKeys Skey structures to scan index rels
* NumScanKeys array of no of keys in each Skey struct * NumScanKeys array of no of keys in each Skey struct
* RuntimeKeyInfo array of array of flags for Skeys evaled at runtime * RuntimeKeyInfo array of array of exprstates for Skeys
* that will be evaluated at runtime
* RuntimeContext expr context for evaling runtime Skeys * RuntimeContext expr context for evaling runtime Skeys
* RuntimeKeysReady true if runtime Skeys have been computed * RuntimeKeysReady true if runtime Skeys have been computed
* RelationDescs ptr to array of relation descriptors * RelationDescs ptr to array of relation descriptors
...@@ -484,7 +658,7 @@ typedef struct IndexScanState ...@@ -484,7 +658,7 @@ typedef struct IndexScanState
int iss_MarkIndexPtr; int iss_MarkIndexPtr;
ScanKey *iss_ScanKeys; ScanKey *iss_ScanKeys;
int *iss_NumScanKeys; int *iss_NumScanKeys;
int **iss_RuntimeKeyInfo; ExprState ***iss_RuntimeKeyInfo;
ExprContext *iss_RuntimeContext; ExprContext *iss_RuntimeContext;
bool iss_RuntimeKeysReady; bool iss_RuntimeKeysReady;
RelationPtr iss_RelationDescs; RelationPtr iss_RelationDescs;
...@@ -502,6 +676,7 @@ typedef struct IndexScanState ...@@ -502,6 +676,7 @@ typedef struct IndexScanState
typedef struct TidScanState typedef struct TidScanState
{ {
ScanState ss; /* its first field is NodeTag */ ScanState ss; /* its first field is NodeTag */
List *tss_tideval; /* list of ExprState nodes */
int tss_NumTids; int tss_NumTids;
int tss_TidPtr; int tss_TidPtr;
int tss_MarkTidPtr; int tss_MarkTidPtr;
...@@ -542,7 +717,7 @@ typedef struct FunctionScanState ...@@ -542,7 +717,7 @@ typedef struct FunctionScanState
ScanState ss; /* its first field is NodeTag */ ScanState ss; /* its first field is NodeTag */
TupleDesc tupdesc; TupleDesc tupdesc;
Tuplestorestate *tuplestorestate; Tuplestorestate *tuplestorestate;
Node *funcexpr; ExprState *funcexpr;
} FunctionScanState; } FunctionScanState;
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
...@@ -597,9 +772,9 @@ typedef struct NestLoopState ...@@ -597,9 +772,9 @@ typedef struct NestLoopState
typedef struct MergeJoinState typedef struct MergeJoinState
{ {
JoinState js; /* its first field is NodeTag */ JoinState js; /* its first field is NodeTag */
List *mergeclauses; List *mergeclauses; /* list of ExprState nodes */
List *mj_OuterSkipQual; List *mj_OuterSkipQual; /* list of ExprState nodes */
List *mj_InnerSkipQual; List *mj_InnerSkipQual; /* list of ExprState nodes */
int mj_JoinState; int mj_JoinState;
bool mj_MatchedOuter; bool mj_MatchedOuter;
bool mj_MatchedInner; bool mj_MatchedInner;
...@@ -632,12 +807,12 @@ typedef struct MergeJoinState ...@@ -632,12 +807,12 @@ typedef struct MergeJoinState
typedef struct HashJoinState typedef struct HashJoinState
{ {
JoinState js; /* its first field is NodeTag */ JoinState js; /* its first field is NodeTag */
List *hashclauses; List *hashclauses; /* list of ExprState nodes */
HashJoinTable hj_HashTable; HashJoinTable hj_HashTable;
int hj_CurBucketNo; int hj_CurBucketNo;
HashJoinTuple hj_CurTuple; HashJoinTuple hj_CurTuple;
List *hj_OuterHashKeys; List *hj_OuterHashKeys; /* list of ExprState nodes */
List *hj_InnerHashKeys; List *hj_InnerHashKeys; /* list of ExprState nodes */
TupleTableSlot *hj_OuterTupleSlot; TupleTableSlot *hj_OuterTupleSlot;
TupleTableSlot *hj_HashTupleSlot; TupleTableSlot *hj_HashTupleSlot;
TupleTableSlot *hj_NullInnerTupleSlot; TupleTableSlot *hj_NullInnerTupleSlot;
...@@ -757,6 +932,8 @@ typedef struct HashState ...@@ -757,6 +932,8 @@ typedef struct HashState
{ {
PlanState ps; /* its first field is NodeTag */ PlanState ps; /* its first field is NodeTag */
HashJoinTable hashtable; /* hash table for the hashjoin */ HashJoinTable hashtable; /* hash table for the hashjoin */
List *hashkeys; /* list of ExprState nodes */
/* hashkeys is same as parent's hj_InnerHashKeys */
} HashState; } HashState;
/* ---------------- /* ----------------
...@@ -804,8 +981,8 @@ typedef enum ...@@ -804,8 +981,8 @@ typedef enum
typedef struct LimitState typedef struct LimitState
{ {
PlanState ps; /* its first field is NodeTag */ PlanState ps; /* its first field is NodeTag */
Node *limitOffset; /* OFFSET parameter, or NULL if none */ ExprState *limitOffset; /* OFFSET parameter, or NULL if none */
Node *limitCount; /* COUNT parameter, or NULL if none */ ExprState *limitCount; /* COUNT parameter, or NULL if none */
long offset; /* current OFFSET value */ long offset; /* current OFFSET value */
long count; /* current COUNT, if any */ long count; /* current COUNT, if any */
bool noCount; /* if true, ignore count */ bool noCount; /* if true, ignore count */
...@@ -814,16 +991,4 @@ typedef struct LimitState ...@@ -814,16 +991,4 @@ typedef struct LimitState
TupleTableSlot *subSlot; /* tuple last obtained from subplan */ TupleTableSlot *subSlot; /* tuple last obtained from subplan */
} LimitState; } LimitState;
/* ---------------------
* SubPlanState information
* ---------------------
*/
typedef struct SubPlanState
{
PlanState ps; /* its first field is NodeTag */
PlanState *planstate; /* subselect plan's state tree */
bool needShutdown; /* TRUE = need to shutdown subplan */
HeapTuple curTuple; /* copy of most recent tuple from subplan */
} SubPlanState;
#endif /* EXECNODES_H */ #endif /* EXECNODES_H */
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: nodes.h,v 1.131 2002/12/12 20:35:14 tgl Exp $ * $Id: nodes.h,v 1.132 2002/12/13 19:46:00 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -31,12 +31,12 @@ typedef enum NodeTag ...@@ -31,12 +31,12 @@ typedef enum NodeTag
* TAGS FOR EXECUTOR NODES (execnodes.h) * TAGS FOR EXECUTOR NODES (execnodes.h)
*/ */
T_IndexInfo = 10, T_IndexInfo = 10,
T_ResultRelInfo,
T_TupleTableSlot,
T_ExprContext, T_ExprContext,
T_ProjectionInfo, T_ProjectionInfo,
T_JunkFilter, T_JunkFilter,
T_ResultRelInfo,
T_EState, T_EState,
T_TupleTableSlot,
/* /*
* TAGS FOR PLAN NODES (plannodes.h) * TAGS FOR PLAN NODES (plannodes.h)
...@@ -89,7 +89,6 @@ typedef enum NodeTag ...@@ -89,7 +89,6 @@ typedef enum NodeTag
T_HashState, T_HashState,
T_SetOpState, T_SetOpState,
T_LimitState, T_LimitState,
T_SubPlanState,
/* /*
* TAGS FOR PRIMITIVE NODES (primnodes.h) * TAGS FOR PRIMITIVE NODES (primnodes.h)
...@@ -122,10 +121,27 @@ typedef enum NodeTag ...@@ -122,10 +121,27 @@ typedef enum NodeTag
T_JoinExpr, T_JoinExpr,
T_FromExpr, T_FromExpr,
/*
* TAGS FOR EXPRESSION STATE NODES (execnodes.h)
*
* These correspond (not always one-for-one) to primitive nodes
* derived from Expr.
*/
T_ExprState = 400,
T_GenericExprState,
T_AggrefExprState,
T_ArrayRefExprState,
T_FuncExprState,
T_BoolExprState,
T_SubPlanExprState,
T_CaseExprState,
T_CaseWhenState,
T_ConstraintTestState,
/* /*
* TAGS FOR PLANNER NODES (relation.h) * TAGS FOR PLANNER NODES (relation.h)
*/ */
T_RelOptInfo = 400, T_RelOptInfo = 500,
T_IndexOptInfo, T_IndexOptInfo,
T_Path, T_Path,
T_IndexPath, T_IndexPath,
...@@ -144,13 +160,13 @@ typedef enum NodeTag ...@@ -144,13 +160,13 @@ typedef enum NodeTag
/* /*
* TAGS FOR MEMORY NODES (memnodes.h) * TAGS FOR MEMORY NODES (memnodes.h)
*/ */
T_MemoryContext = 500, T_MemoryContext = 600,
T_AllocSetContext, T_AllocSetContext,
/* /*
* TAGS FOR VALUE NODES (pg_list.h) * TAGS FOR VALUE NODES (pg_list.h)
*/ */
T_Value = 600, T_Value = 650,
T_List, T_List,
T_Integer, T_Integer,
T_Float, T_Float,
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: params.h,v 1.19 2002/12/05 15:50:39 tgl Exp $ * $Id: params.h,v 1.20 2002/12/13 19:46:00 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -88,8 +88,8 @@ typedef ParamListInfoData *ParamListInfo; ...@@ -88,8 +88,8 @@ typedef ParamListInfoData *ParamListInfo;
* array of ParamExecData records, which is referenced through * array of ParamExecData records, which is referenced through
* es_param_exec_vals or ecxt_param_exec_vals. * es_param_exec_vals or ecxt_param_exec_vals.
* *
* If execPlan is not NULL, it points to a SubPlanState node that needs to * If execPlan is not NULL, it points to a SubPlanExprState node that needs
* be executed to produce the value. (This is done so that we can have * to be executed to produce the value. (This is done so that we can have
* lazy evaluation of InitPlans: they aren't executed until/unless a * lazy evaluation of InitPlans: they aren't executed until/unless a
* result value is needed.) Otherwise the value is assumed to be valid * result value is needed.) Otherwise the value is assumed to be valid
* when needed. * when needed.
...@@ -98,7 +98,7 @@ typedef ParamListInfoData *ParamListInfo; ...@@ -98,7 +98,7 @@ typedef ParamListInfoData *ParamListInfo;
typedef struct ParamExecData typedef struct ParamExecData
{ {
void *execPlan; /* should be "SubPlanState *" */ void *execPlan; /* should be "SubPlanExprState *" */
Datum value; Datum value;
bool isnull; bool isnull;
} ParamExecData; } ParamExecData;
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: primnodes.h,v 1.73 2002/12/12 20:35:16 tgl Exp $ * $Id: primnodes.h,v 1.74 2002/12/13 19:46:00 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -20,9 +20,6 @@ ...@@ -20,9 +20,6 @@
#include "access/attnum.h" #include "access/attnum.h"
#include "nodes/pg_list.h" #include "nodes/pg_list.h"
/* FunctionCache is declared in utils/fcache.h */
typedef struct FunctionCache *FunctionCachePtr;
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
* node definitions * node definitions
...@@ -221,9 +218,6 @@ typedef struct Aggref ...@@ -221,9 +218,6 @@ typedef struct Aggref
Expr *target; /* expression we are aggregating on */ Expr *target; /* expression we are aggregating on */
bool aggstar; /* TRUE if argument was really '*' */ bool aggstar; /* TRUE if argument was really '*' */
bool aggdistinct; /* TRUE if it's agg(DISTINCT ...) */ bool aggdistinct; /* TRUE if it's agg(DISTINCT ...) */
/* XXX this should move to AggrefExprState: */
int aggno; /* workspace for executor (see nodeAgg.c) */
} Aggref; } Aggref;
/* ---------------- /* ----------------
...@@ -307,8 +301,6 @@ typedef struct FuncExpr ...@@ -307,8 +301,6 @@ typedef struct FuncExpr
bool funcretset; /* true if function returns set */ bool funcretset; /* true if function returns set */
CoercionForm funcformat; /* how to display this function call */ CoercionForm funcformat; /* how to display this function call */
List *args; /* arguments to the function */ List *args; /* arguments to the function */
FunctionCachePtr func_fcache; /* XXX runtime state, or NULL */
} FuncExpr; } FuncExpr;
/* /*
...@@ -328,8 +320,6 @@ typedef struct OpExpr ...@@ -328,8 +320,6 @@ typedef struct OpExpr
Oid opresulttype; /* PG_TYPE OID of result value */ Oid opresulttype; /* PG_TYPE OID of result value */
bool opretset; /* true if operator returns set */ bool opretset; /* true if operator returns set */
List *args; /* arguments to the operator (1 or 2) */ List *args; /* arguments to the operator (1 or 2) */
FunctionCachePtr op_fcache; /* XXX runtime state, else NULL */
} OpExpr; } OpExpr;
/* /*
...@@ -463,8 +453,6 @@ typedef struct SubPlanExpr ...@@ -463,8 +453,6 @@ typedef struct SubPlanExpr
SubLink *sublink; /* SubLink node from parser; holds info SubLink *sublink; /* SubLink node from parser; holds info
* about what to do with subselect's * about what to do with subselect's
* results */ * results */
struct SubPlanState *pstate; /* XXX TEMPORARY HACK */
} SubPlanExpr; } SubPlanExpr;
/* ---------------- /* ----------------
......
/*-------------------------------------------------------------------------
*
* fcache.h
* Declarations for function cache records.
*
* The first time any Oper or Func node is evaluated, we compute a cache
* record for the function being invoked, and save a pointer to the cache
* record in the Oper or Func node. This saves repeated lookup of info
* about the function.
*
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: fcache.h,v 1.23 2002/06/20 20:29:52 momjian Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef FCACHE_H
#define FCACHE_H
#include "fmgr.h"
#include "nodes/execnodes.h"
/*
* A FunctionCache record is built for all functions regardless of language.
*
* We store the fmgr lookup info to avoid recomputing it on each call.
*
* We also need to store argument values across calls when evaluating a
* function-returning-set. This is pretty ugly (and not re-entrant);
* current-evaluation info should be somewhere in the econtext, not in
* the querytree. As it stands, a function-returning-set can't safely be
* recursive, at least not if it's in plpgsql which will try to re-use
* the querytree at multiple execution nesting levels. FIXME someday.
*/
typedef struct FunctionCache
{
/*
* Function manager's lookup info for the target function.
*/
FmgrInfo func;
/*
* setArgsValid is true when we are evaluating a set-valued function
* and we are in the middle of a call series; we want to pass the same
* argument values to the function again (and again, until it returns
* ExprEndResult).
*/
bool setArgsValid;
/*
* Flag to remember whether we found a set-valued argument to the
* function. This causes the function result to be a set as well.
* Valid only when setArgsValid is true.
*/
bool setHasSetArg; /* some argument returns a set */
/*
* Current argument data for a set-valued function; contains valid
* data only if setArgsValid is true.
*/
FunctionCallInfoData setArgs;
} FunctionCache;
extern FunctionCachePtr init_fcache(Oid foid, int nargs,
MemoryContext fcacheCxt);
#endif /* FCACHE_H */
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* procedural language * procedural language
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.73 2002/12/12 15:49:42 tgl Exp $ * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.74 2002/12/13 19:46:01 tgl Exp $
* *
* This software is copyrighted by Jan Wieck - Hamburg. * This software is copyrighted by Jan Wieck - Hamburg.
* *
...@@ -1981,6 +1981,7 @@ exec_prepare_plan(PLpgSQL_execstate * estate, ...@@ -1981,6 +1981,7 @@ exec_prepare_plan(PLpgSQL_execstate * estate,
PLpgSQL_recfield *recfield; PLpgSQL_recfield *recfield;
int i; int i;
int fno; int fno;
_SPI_plan *spi_plan;
void *plan; void *plan;
Oid *argtypes; Oid *argtypes;
...@@ -2030,7 +2031,8 @@ exec_prepare_plan(PLpgSQL_execstate * estate, ...@@ -2030,7 +2031,8 @@ exec_prepare_plan(PLpgSQL_execstate * estate,
if (plan == NULL) if (plan == NULL)
elog(ERROR, "SPI_prepare() failed on \"%s\"", expr->query); elog(ERROR, "SPI_prepare() failed on \"%s\"", expr->query);
expr->plan = SPI_saveplan(plan); expr->plan = SPI_saveplan(plan);
expr->plan_argtypes = ((_SPI_plan *) expr->plan)->argtypes; spi_plan = (_SPI_plan *) expr->plan;
expr->plan_argtypes = spi_plan->argtypes;
expr->plan_simple_expr = NULL; expr->plan_simple_expr = NULL;
exec_simple_check_plan(expr); exec_simple_check_plan(expr);
...@@ -3642,6 +3644,7 @@ exec_simple_check_plan(PLpgSQL_expr * expr) ...@@ -3642,6 +3644,7 @@ exec_simple_check_plan(PLpgSQL_expr * expr)
_SPI_plan *spi_plan = (_SPI_plan *) expr->plan; _SPI_plan *spi_plan = (_SPI_plan *) expr->plan;
Plan *plan; Plan *plan;
TargetEntry *tle; TargetEntry *tle;
MemoryContext oldcontext;
expr->plan_simple_expr = NULL; expr->plan_simple_expr = NULL;
...@@ -3688,10 +3691,13 @@ exec_simple_check_plan(PLpgSQL_expr * expr) ...@@ -3688,10 +3691,13 @@ exec_simple_check_plan(PLpgSQL_expr * expr)
return; return;
/* /*
* Yes - this is a simple expression. Remember the expression and the * Yes - this is a simple expression. Prepare to execute it, and
* return type * stash away the result type. Put the expression state tree in the
* plan context so it will have appropriate lifespan.
*/ */
expr->plan_simple_expr = (Node *) tle->expr; oldcontext = MemoryContextSwitchTo(spi_plan->plancxt);
expr->plan_simple_expr = ExecInitExpr(tle->expr, NULL);
MemoryContextSwitchTo(oldcontext);
expr->plan_simple_type = exprType((Node *) tle->expr); expr->plan_simple_type = exprType((Node *) tle->expr);
} }
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* procedural language * procedural language
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.29 2002/11/10 00:35:58 momjian Exp $ * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.30 2002/12/13 19:46:01 tgl Exp $
* *
* This software is copyrighted by Jan Wieck - Hamburg. * This software is copyrighted by Jan Wieck - Hamburg.
* *
...@@ -165,7 +165,7 @@ typedef struct ...@@ -165,7 +165,7 @@ typedef struct
int exprno; int exprno;
char *query; char *query;
void *plan; void *plan;
Node *plan_simple_expr; ExprState *plan_simple_expr;
Oid plan_simple_type; Oid plan_simple_type;
Oid *plan_argtypes; Oid *plan_argtypes;
int nparams; int nparams;
......
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