Commit b8c32677 authored by Tom Lane's avatar Tom Lane

Put function expressions and values lists into FunctionScan and ValuesScan

plan nodes, so that the executor does not need to get these items from
the range table at runtime.  This will avoid needing to include these
fields in the compact range table I'm expecting to make the executor use.
parent f1f2b271
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994-5, Regents of the University of California * Portions Copyright (c) 1994-5, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.154 2007/02/14 01:58:56 tgl Exp $ * $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.155 2007/02/19 02:23:11 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -640,6 +640,7 @@ explain_outNode(StringInfo str, ...@@ -640,6 +640,7 @@ explain_outNode(StringInfo str,
{ {
RangeTblEntry *rte = rt_fetch(((Scan *) plan)->scanrelid, RangeTblEntry *rte = rt_fetch(((Scan *) plan)->scanrelid,
es->rtable); es->rtable);
Node *funcexpr;
char *proname; char *proname;
/* Assert it's on a RangeFunction */ /* Assert it's on a RangeFunction */
...@@ -651,10 +652,10 @@ explain_outNode(StringInfo str, ...@@ -651,10 +652,10 @@ explain_outNode(StringInfo str,
* happen if the optimizer simplified away the function call, * happen if the optimizer simplified away the function call,
* for example). * for example).
*/ */
if (rte->funcexpr && IsA(rte->funcexpr, FuncExpr)) funcexpr = ((FunctionScan *) plan)->funcexpr;
if (funcexpr && IsA(funcexpr, FuncExpr))
{ {
FuncExpr *funcexpr = (FuncExpr *) rte->funcexpr; Oid funcid = ((FuncExpr *) funcexpr)->funcid;
Oid funcid = funcexpr->funcid;
/* We only show the func name, not schema name */ /* We only show the func name, not schema name */
proname = get_func_name(funcid); proname = get_func_name(funcid);
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/backend/executor/execAmi.c,v 1.91 2007/02/15 03:07:13 tgl Exp $ * $PostgreSQL: pgsql/src/backend/executor/execAmi.c,v 1.92 2007/02/19 02:23:11 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -444,13 +444,16 @@ ExecMayReturnRawTuples(PlanState *node) ...@@ -444,13 +444,16 @@ ExecMayReturnRawTuples(PlanState *node)
case T_IndexScanState: case T_IndexScanState:
case T_BitmapHeapScanState: case T_BitmapHeapScanState:
case T_TidScanState: case T_TidScanState:
case T_SubqueryScanState:
case T_FunctionScanState:
case T_ValuesScanState:
if (node->ps_ProjInfo == NULL) if (node->ps_ProjInfo == NULL)
return true; return true;
break; break;
case T_SubqueryScanState:
/* If not projecting, look at input plan */
if (node->ps_ProjInfo == NULL)
return ExecMayReturnRawTuples(((SubqueryScanState *) node)->subplan);
break;
/* Non-projecting nodes */ /* Non-projecting nodes */
case T_HashState: case T_HashState:
case T_MaterialState: case T_MaterialState:
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/nodeFunctionscan.c,v 1.42 2007/01/05 22:19:28 momjian Exp $ * $PostgreSQL: pgsql/src/backend/executor/nodeFunctionscan.c,v 1.43 2007/02/19 02:23:11 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -118,7 +118,6 @@ FunctionScanState * ...@@ -118,7 +118,6 @@ FunctionScanState *
ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags) ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags)
{ {
FunctionScanState *scanstate; FunctionScanState *scanstate;
RangeTblEntry *rte;
Oid funcrettype; Oid funcrettype;
TypeFuncClass functypclass; TypeFuncClass functypclass;
TupleDesc tupdesc = NULL; TupleDesc tupdesc = NULL;
...@@ -161,17 +160,11 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags) ...@@ -161,17 +160,11 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags)
ExecInitExpr((Expr *) node->scan.plan.qual, ExecInitExpr((Expr *) node->scan.plan.qual,
(PlanState *) scanstate); (PlanState *) scanstate);
/*
* get info about function
*/
rte = rt_fetch(node->scan.scanrelid, estate->es_range_table);
Assert(rte->rtekind == RTE_FUNCTION);
/* /*
* Now determine if the function returns a simple or composite type, and * Now determine if the function returns a simple or composite type, and
* build an appropriate tupdesc. * build an appropriate tupdesc.
*/ */
functypclass = get_expr_result_type(rte->funcexpr, functypclass = get_expr_result_type(node->funcexpr,
&funcrettype, &funcrettype,
&tupdesc); &tupdesc);
...@@ -185,7 +178,7 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags) ...@@ -185,7 +178,7 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags)
else if (functypclass == TYPEFUNC_SCALAR) else if (functypclass == TYPEFUNC_SCALAR)
{ {
/* Base data type, i.e. scalar */ /* Base data type, i.e. scalar */
char *attname = strVal(linitial(rte->eref->colnames)); char *attname = strVal(linitial(node->funccolnames));
tupdesc = CreateTemplateTupleDesc(1, false); tupdesc = CreateTemplateTupleDesc(1, false);
TupleDescInitEntry(tupdesc, TupleDescInitEntry(tupdesc,
...@@ -197,9 +190,9 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags) ...@@ -197,9 +190,9 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags)
} }
else if (functypclass == TYPEFUNC_RECORD) else if (functypclass == TYPEFUNC_RECORD)
{ {
tupdesc = BuildDescFromLists(rte->eref->colnames, tupdesc = BuildDescFromLists(node->funccolnames,
rte->funccoltypes, node->funccoltypes,
rte->funccoltypmods); node->funccoltypmods);
} }
else else
{ {
...@@ -221,7 +214,7 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags) ...@@ -221,7 +214,7 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags)
* Other node-specific setup * Other node-specific setup
*/ */
scanstate->tuplestorestate = NULL; scanstate->tuplestorestate = NULL;
scanstate->funcexpr = ExecInitExpr((Expr *) rte->funcexpr, scanstate->funcexpr = ExecInitExpr((Expr *) node->funcexpr,
(PlanState *) scanstate); (PlanState *) scanstate);
scanstate->ss.ps.ps_TupFromTlist = false; scanstate->ss.ps.ps_TupFromTlist = false;
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/nodeValuesscan.c,v 1.5 2007/01/05 22:19:28 momjian Exp $ * $PostgreSQL: pgsql/src/backend/executor/nodeValuesscan.c,v 1.6 2007/02/19 02:23:11 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -182,7 +182,6 @@ ValuesScanState * ...@@ -182,7 +182,6 @@ ValuesScanState *
ExecInitValuesScan(ValuesScan *node, EState *estate, int eflags) ExecInitValuesScan(ValuesScan *node, EState *estate, int eflags)
{ {
ValuesScanState *scanstate; ValuesScanState *scanstate;
RangeTblEntry *rte;
TupleDesc tupdesc; TupleDesc tupdesc;
ListCell *vtl; ListCell *vtl;
int i; int i;
...@@ -236,9 +235,7 @@ ExecInitValuesScan(ValuesScan *node, EState *estate, int eflags) ...@@ -236,9 +235,7 @@ ExecInitValuesScan(ValuesScan *node, EState *estate, int eflags)
/* /*
* get info about values list * get info about values list
*/ */
rte = rt_fetch(node->scan.scanrelid, estate->es_range_table); tupdesc = ExecTypeFromExprList((List *) linitial(node->values_lists));
Assert(rte->rtekind == RTE_VALUES);
tupdesc = ExecTypeFromExprList((List *) linitial(rte->values_lists));
ExecAssignScanType(&scanstate->ss, tupdesc); ExecAssignScanType(&scanstate->ss, tupdesc);
...@@ -247,13 +244,13 @@ ExecInitValuesScan(ValuesScan *node, EState *estate, int eflags) ...@@ -247,13 +244,13 @@ ExecInitValuesScan(ValuesScan *node, EState *estate, int eflags)
*/ */
scanstate->marked_idx = -1; scanstate->marked_idx = -1;
scanstate->curr_idx = -1; scanstate->curr_idx = -1;
scanstate->array_len = list_length(rte->values_lists); scanstate->array_len = list_length(node->values_lists);
/* convert list of sublists into array of sublists for easy addressing */ /* convert list of sublists into array of sublists for easy addressing */
scanstate->exprlists = (List **) scanstate->exprlists = (List **)
palloc(scanstate->array_len * sizeof(List *)); palloc(scanstate->array_len * sizeof(List *));
i = 0; i = 0;
foreach(vtl, rte->values_lists) foreach(vtl, node->values_lists)
{ {
scanstate->exprlists[i++] = (List *) lfirst(vtl); scanstate->exprlists[i++] = (List *) lfirst(vtl);
} }
......
...@@ -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
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.365 2007/02/03 14:06:54 petere Exp $ * $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.366 2007/02/19 02:23:11 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -363,6 +363,14 @@ _copyFunctionScan(FunctionScan *from) ...@@ -363,6 +363,14 @@ _copyFunctionScan(FunctionScan *from)
*/ */
CopyScanFields((Scan *) from, (Scan *) newnode); CopyScanFields((Scan *) from, (Scan *) newnode);
/*
* copy remainder of node
*/
COPY_NODE_FIELD(funcexpr);
COPY_NODE_FIELD(funccolnames);
COPY_NODE_FIELD(funccoltypes);
COPY_NODE_FIELD(funccoltypmods);
return newnode; return newnode;
} }
...@@ -379,6 +387,11 @@ _copyValuesScan(ValuesScan *from) ...@@ -379,6 +387,11 @@ _copyValuesScan(ValuesScan *from)
*/ */
CopyScanFields((Scan *) from, (Scan *) newnode); CopyScanFields((Scan *) from, (Scan *) newnode);
/*
* copy remainder of node
*/
COPY_NODE_FIELD(values_lists);
return newnode; return newnode;
} }
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.297 2007/02/12 17:19:30 tgl Exp $ * $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.298 2007/02/19 02:23:12 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*
...@@ -408,6 +408,11 @@ _outFunctionScan(StringInfo str, FunctionScan *node) ...@@ -408,6 +408,11 @@ _outFunctionScan(StringInfo str, FunctionScan *node)
WRITE_NODE_TYPE("FUNCTIONSCAN"); WRITE_NODE_TYPE("FUNCTIONSCAN");
_outScanInfo(str, (Scan *) node); _outScanInfo(str, (Scan *) node);
WRITE_NODE_FIELD(funcexpr);
WRITE_NODE_FIELD(funccolnames);
WRITE_NODE_FIELD(funccoltypes);
WRITE_NODE_FIELD(funccoltypmods);
} }
static void static void
...@@ -416,6 +421,8 @@ _outValuesScan(StringInfo str, ValuesScan *node) ...@@ -416,6 +421,8 @@ _outValuesScan(StringInfo str, ValuesScan *node)
WRITE_NODE_TYPE("VALUESSCAN"); WRITE_NODE_TYPE("VALUESSCAN");
_outScanInfo(str, (Scan *) node); _outScanInfo(str, (Scan *) node);
WRITE_NODE_FIELD(values_lists);
} }
static void static void
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.224 2007/01/30 01:33:36 tgl Exp $ * $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.225 2007/02/19 02:23:12 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -96,9 +96,10 @@ static BitmapHeapScan *make_bitmap_heapscan(List *qptlist, ...@@ -96,9 +96,10 @@ static BitmapHeapScan *make_bitmap_heapscan(List *qptlist,
static TidScan *make_tidscan(List *qptlist, List *qpqual, Index scanrelid, static TidScan *make_tidscan(List *qptlist, List *qpqual, Index scanrelid,
List *tidquals); List *tidquals);
static FunctionScan *make_functionscan(List *qptlist, List *qpqual, static FunctionScan *make_functionscan(List *qptlist, List *qpqual,
Index scanrelid); Index scanrelid, Node *funcexpr, List *funccolnames,
List *funccoltypes, List *funccoltypmods);
static ValuesScan *make_valuesscan(List *qptlist, List *qpqual, static ValuesScan *make_valuesscan(List *qptlist, List *qpqual,
Index scanrelid); Index scanrelid, List *values_lists);
static BitmapAnd *make_bitmap_and(List *bitmapplans); static BitmapAnd *make_bitmap_and(List *bitmapplans);
static BitmapOr *make_bitmap_or(List *bitmapplans); static BitmapOr *make_bitmap_or(List *bitmapplans);
static NestLoop *make_nestloop(List *tlist, static NestLoop *make_nestloop(List *tlist,
...@@ -1350,10 +1351,12 @@ create_functionscan_plan(PlannerInfo *root, Path *best_path, ...@@ -1350,10 +1351,12 @@ create_functionscan_plan(PlannerInfo *root, Path *best_path,
{ {
FunctionScan *scan_plan; FunctionScan *scan_plan;
Index scan_relid = best_path->parent->relid; Index scan_relid = best_path->parent->relid;
RangeTblEntry *rte;
/* it should be a function base rel... */ /* it should be a function base rel... */
Assert(scan_relid > 0); Assert(scan_relid > 0);
Assert(best_path->parent->rtekind == RTE_FUNCTION); rte = rt_fetch(scan_relid, root->parse->rtable);
Assert(rte->rtekind == RTE_FUNCTION);
/* Sort clauses into best execution order */ /* Sort clauses into best execution order */
scan_clauses = order_qual_clauses(root, scan_clauses); scan_clauses = order_qual_clauses(root, scan_clauses);
...@@ -1361,7 +1364,11 @@ create_functionscan_plan(PlannerInfo *root, Path *best_path, ...@@ -1361,7 +1364,11 @@ create_functionscan_plan(PlannerInfo *root, Path *best_path,
/* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */ /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
scan_clauses = extract_actual_clauses(scan_clauses, false); scan_clauses = extract_actual_clauses(scan_clauses, false);
scan_plan = make_functionscan(tlist, scan_clauses, scan_relid); scan_plan = make_functionscan(tlist, scan_clauses, scan_relid,
rte->funcexpr,
rte->eref->colnames,
rte->funccoltypes,
rte->funccoltypmods);
copy_path_costsize(&scan_plan->scan.plan, best_path); copy_path_costsize(&scan_plan->scan.plan, best_path);
...@@ -1379,10 +1386,12 @@ create_valuesscan_plan(PlannerInfo *root, Path *best_path, ...@@ -1379,10 +1386,12 @@ create_valuesscan_plan(PlannerInfo *root, Path *best_path,
{ {
ValuesScan *scan_plan; ValuesScan *scan_plan;
Index scan_relid = best_path->parent->relid; Index scan_relid = best_path->parent->relid;
RangeTblEntry *rte;
/* it should be a values base rel... */ /* it should be a values base rel... */
Assert(scan_relid > 0); Assert(scan_relid > 0);
Assert(best_path->parent->rtekind == RTE_VALUES); rte = rt_fetch(scan_relid, root->parse->rtable);
Assert(rte->rtekind == RTE_VALUES);
/* Sort clauses into best execution order */ /* Sort clauses into best execution order */
scan_clauses = order_qual_clauses(root, scan_clauses); scan_clauses = order_qual_clauses(root, scan_clauses);
...@@ -1390,7 +1399,8 @@ create_valuesscan_plan(PlannerInfo *root, Path *best_path, ...@@ -1390,7 +1399,8 @@ create_valuesscan_plan(PlannerInfo *root, Path *best_path,
/* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */ /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
scan_clauses = extract_actual_clauses(scan_clauses, false); scan_clauses = extract_actual_clauses(scan_clauses, false);
scan_plan = make_valuesscan(tlist, scan_clauses, scan_relid); scan_plan = make_valuesscan(tlist, scan_clauses, scan_relid,
rte->values_lists);
copy_path_costsize(&scan_plan->scan.plan, best_path); copy_path_costsize(&scan_plan->scan.plan, best_path);
...@@ -2342,7 +2352,11 @@ make_subqueryscan(List *qptlist, ...@@ -2342,7 +2352,11 @@ make_subqueryscan(List *qptlist,
static FunctionScan * static FunctionScan *
make_functionscan(List *qptlist, make_functionscan(List *qptlist,
List *qpqual, List *qpqual,
Index scanrelid) Index scanrelid,
Node *funcexpr,
List *funccolnames,
List *funccoltypes,
List *funccoltypmods)
{ {
FunctionScan *node = makeNode(FunctionScan); FunctionScan *node = makeNode(FunctionScan);
Plan *plan = &node->scan.plan; Plan *plan = &node->scan.plan;
...@@ -2353,6 +2367,10 @@ make_functionscan(List *qptlist, ...@@ -2353,6 +2367,10 @@ make_functionscan(List *qptlist,
plan->lefttree = NULL; plan->lefttree = NULL;
plan->righttree = NULL; plan->righttree = NULL;
node->scan.scanrelid = scanrelid; node->scan.scanrelid = scanrelid;
node->funcexpr = funcexpr;
node->funccolnames = funccolnames;
node->funccoltypes = funccoltypes;
node->funccoltypmods = funccoltypmods;
return node; return node;
} }
...@@ -2360,7 +2378,8 @@ make_functionscan(List *qptlist, ...@@ -2360,7 +2378,8 @@ make_functionscan(List *qptlist,
static ValuesScan * static ValuesScan *
make_valuesscan(List *qptlist, make_valuesscan(List *qptlist,
List *qpqual, List *qpqual,
Index scanrelid) Index scanrelid,
List *values_lists)
{ {
ValuesScan *node = makeNode(ValuesScan); ValuesScan *node = makeNode(ValuesScan);
Plan *plan = &node->scan.plan; Plan *plan = &node->scan.plan;
...@@ -2371,6 +2390,7 @@ make_valuesscan(List *qptlist, ...@@ -2371,6 +2390,7 @@ make_valuesscan(List *qptlist,
plan->lefttree = NULL; plan->lefttree = NULL;
plan->righttree = NULL; plan->righttree = NULL;
node->scan.scanrelid = scanrelid; node->scan.scanrelid = scanrelid;
node->values_lists = values_lists;
return node; return node;
} }
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/plan/setrefs.c,v 1.129 2007/02/16 03:49:04 tgl Exp $ * $PostgreSQL: pgsql/src/backend/optimizer/plan/setrefs.c,v 1.130 2007/02/19 02:23:12 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -171,28 +171,15 @@ set_plan_references(Plan *plan, List *rtable) ...@@ -171,28 +171,15 @@ set_plan_references(Plan *plan, List *rtable)
/* Needs special treatment, see comments below */ /* Needs special treatment, see comments below */
return set_subqueryscan_references((SubqueryScan *) plan, rtable); return set_subqueryscan_references((SubqueryScan *) plan, rtable);
case T_FunctionScan: case T_FunctionScan:
{ fix_expr_references(plan, (Node *) plan->targetlist);
RangeTblEntry *rte; fix_expr_references(plan, (Node *) plan->qual);
fix_expr_references(plan, ((FunctionScan *) plan)->funcexpr);
fix_expr_references(plan, (Node *) plan->targetlist);
fix_expr_references(plan, (Node *) plan->qual);
rte = rt_fetch(((FunctionScan *) plan)->scan.scanrelid,
rtable);
Assert(rte->rtekind == RTE_FUNCTION);
fix_expr_references(plan, rte->funcexpr);
}
break; break;
case T_ValuesScan: case T_ValuesScan:
{ fix_expr_references(plan, (Node *) plan->targetlist);
RangeTblEntry *rte; fix_expr_references(plan, (Node *) plan->qual);
fix_expr_references(plan,
fix_expr_references(plan, (Node *) plan->targetlist); (Node *) ((ValuesScan *) plan)->values_lists);
fix_expr_references(plan, (Node *) plan->qual);
rte = rt_fetch(((ValuesScan *) plan)->scan.scanrelid,
rtable);
Assert(rte->rtekind == RTE_VALUES);
fix_expr_references(plan, (Node *) rte->values_lists);
}
break; break;
case T_NestLoop: case T_NestLoop:
set_join_references((Join *) plan); set_join_references((Join *) plan);
...@@ -369,10 +356,6 @@ set_subqueryscan_references(SubqueryScan *plan, List *rtable) ...@@ -369,10 +356,6 @@ set_subqueryscan_references(SubqueryScan *plan, List *rtable)
*lc; *lc;
sub_rtable = copyObject(rte->subquery->rtable); sub_rtable = copyObject(rte->subquery->rtable);
range_table_walker(sub_rtable,
adjust_expr_varnos_walker,
(void *) &rtoffset,
QTW_IGNORE_RT_SUBQUERIES);
rtable = list_concat(rtable, sub_rtable); rtable = list_concat(rtable, sub_rtable);
/* /*
...@@ -544,13 +527,15 @@ adjust_plan_varnos(Plan *plan, int rtoffset) ...@@ -544,13 +527,15 @@ adjust_plan_varnos(Plan *plan, int rtoffset)
((FunctionScan *) plan)->scan.scanrelid += rtoffset; ((FunctionScan *) plan)->scan.scanrelid += rtoffset;
adjust_expr_varnos((Node *) plan->targetlist, rtoffset); adjust_expr_varnos((Node *) plan->targetlist, rtoffset);
adjust_expr_varnos((Node *) plan->qual, rtoffset); adjust_expr_varnos((Node *) plan->qual, rtoffset);
/* rte was already fixed by set_subqueryscan_references */ adjust_expr_varnos(((FunctionScan *) plan)->funcexpr,
rtoffset);
break; break;
case T_ValuesScan: case T_ValuesScan:
((ValuesScan *) plan)->scan.scanrelid += rtoffset; ((ValuesScan *) plan)->scan.scanrelid += rtoffset;
adjust_expr_varnos((Node *) plan->targetlist, rtoffset); adjust_expr_varnos((Node *) plan->targetlist, rtoffset);
adjust_expr_varnos((Node *) plan->qual, rtoffset); adjust_expr_varnos((Node *) plan->qual, rtoffset);
/* rte was already fixed by set_subqueryscan_references */ adjust_expr_varnos((Node *) ((ValuesScan *) plan)->values_lists,
rtoffset);
break; break;
case T_NestLoop: case T_NestLoop:
adjust_expr_varnos((Node *) plan->targetlist, rtoffset); adjust_expr_varnos((Node *) plan->targetlist, rtoffset);
......
...@@ -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
* $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.118 2007/02/06 02:59:11 tgl Exp $ * $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.119 2007/02/19 02:23:12 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1103,25 +1103,13 @@ finalize_plan(Plan *plan, List *rtable, ...@@ -1103,25 +1103,13 @@ finalize_plan(Plan *plan, List *rtable,
break; break;
case T_FunctionScan: case T_FunctionScan:
{ finalize_primnode(((FunctionScan *) plan)->funcexpr,
RangeTblEntry *rte; &context);
rte = rt_fetch(((FunctionScan *) plan)->scan.scanrelid,
rtable);
Assert(rte->rtekind == RTE_FUNCTION);
finalize_primnode(rte->funcexpr, &context);
}
break; break;
case T_ValuesScan: case T_ValuesScan:
{ finalize_primnode((Node *) ((ValuesScan *) plan)->values_lists,
RangeTblEntry *rte; &context);
rte = rt_fetch(((ValuesScan *) plan)->scan.scanrelid,
rtable);
Assert(rte->rtekind == RTE_VALUES);
finalize_primnode((Node *) rte->values_lists, &context);
}
break; break;
case T_Append: case T_Append:
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/nodes/plannodes.h,v 1.89 2007/01/10 18:06:04 tgl Exp $ * $PostgreSQL: pgsql/src/include/nodes/plannodes.h,v 1.90 2007/02/19 02:23:12 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -270,9 +270,11 @@ typedef struct TidScan ...@@ -270,9 +270,11 @@ typedef struct TidScan
* subquery scan node * subquery scan node
* *
* SubqueryScan is for scanning the output of a sub-query in the range table. * SubqueryScan is for scanning the output of a sub-query in the range table.
* We need a special plan node above the sub-query's plan as a place to switch * We often need an extra plan node above the sub-query's plan to perform
* execution contexts. Although we are not scanning a physical relation, * expression evaluations (which we can't push into the sub-query without
* we make this a descendant of Scan anyway for code-sharing purposes. * risking changing its semantics). Although we are not scanning a physical
* relation, we make this a descendant of Scan anyway for code-sharing
* purposes.
* *
* Note: we store the sub-plan in the type-specific subplan field, not in * Note: we store the sub-plan in the type-specific subplan field, not in
* the generic lefttree field as you might expect. This is because we do * the generic lefttree field as you might expect. This is because we do
...@@ -293,7 +295,10 @@ typedef struct SubqueryScan ...@@ -293,7 +295,10 @@ typedef struct SubqueryScan
typedef struct FunctionScan typedef struct FunctionScan
{ {
Scan scan; Scan scan;
/* no other fields needed at present */ Node *funcexpr; /* expression tree for func call */
List *funccolnames; /* output column names (string Value nodes) */
List *funccoltypes; /* OID list of column type OIDs */
List *funccoltypmods; /* integer list of column typmods */
} FunctionScan; } FunctionScan;
/* ---------------- /* ----------------
...@@ -303,7 +308,7 @@ typedef struct FunctionScan ...@@ -303,7 +308,7 @@ typedef struct FunctionScan
typedef struct ValuesScan typedef struct ValuesScan
{ {
Scan scan; Scan scan;
/* no other fields needed at present */ List *values_lists; /* list of expression lists */
} ValuesScan; } ValuesScan;
/* /*
......
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