mirror of
https://github.com/postgres/postgres.git
synced 2025-11-26 23:43:30 +03:00
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.
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1994-5, Regents of the University of California
|
||||
*
|
||||
* 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,
|
||||
{
|
||||
RangeTblEntry *rte = rt_fetch(((Scan *) plan)->scanrelid,
|
||||
es->rtable);
|
||||
Node *funcexpr;
|
||||
char *proname;
|
||||
|
||||
/* Assert it's on a RangeFunction */
|
||||
@@ -651,10 +652,10 @@ explain_outNode(StringInfo str,
|
||||
* happen if the optimizer simplified away the function call,
|
||||
* 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->funcid;
|
||||
Oid funcid = ((FuncExpr *) funcexpr)->funcid;
|
||||
|
||||
/* We only show the func name, not schema name */
|
||||
proname = get_func_name(funcid);
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
|
||||
* 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)
|
||||
case T_IndexScanState:
|
||||
case T_BitmapHeapScanState:
|
||||
case T_TidScanState:
|
||||
case T_SubqueryScanState:
|
||||
case T_FunctionScanState:
|
||||
case T_ValuesScanState:
|
||||
if (node->ps_ProjInfo == NULL)
|
||||
return true;
|
||||
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 */
|
||||
case T_HashState:
|
||||
case T_MaterialState:
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* 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 *
|
||||
ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags)
|
||||
{
|
||||
FunctionScanState *scanstate;
|
||||
RangeTblEntry *rte;
|
||||
Oid funcrettype;
|
||||
TypeFuncClass functypclass;
|
||||
TupleDesc tupdesc = NULL;
|
||||
@@ -161,17 +160,11 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags)
|
||||
ExecInitExpr((Expr *) node->scan.plan.qual,
|
||||
(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
|
||||
* build an appropriate tupdesc.
|
||||
*/
|
||||
functypclass = get_expr_result_type(rte->funcexpr,
|
||||
functypclass = get_expr_result_type(node->funcexpr,
|
||||
&funcrettype,
|
||||
&tupdesc);
|
||||
|
||||
@@ -185,7 +178,7 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags)
|
||||
else if (functypclass == TYPEFUNC_SCALAR)
|
||||
{
|
||||
/* Base data type, i.e. scalar */
|
||||
char *attname = strVal(linitial(rte->eref->colnames));
|
||||
char *attname = strVal(linitial(node->funccolnames));
|
||||
|
||||
tupdesc = CreateTemplateTupleDesc(1, false);
|
||||
TupleDescInitEntry(tupdesc,
|
||||
@@ -197,9 +190,9 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags)
|
||||
}
|
||||
else if (functypclass == TYPEFUNC_RECORD)
|
||||
{
|
||||
tupdesc = BuildDescFromLists(rte->eref->colnames,
|
||||
rte->funccoltypes,
|
||||
rte->funccoltypmods);
|
||||
tupdesc = BuildDescFromLists(node->funccolnames,
|
||||
node->funccoltypes,
|
||||
node->funccoltypmods);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -221,7 +214,7 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags)
|
||||
* Other node-specific setup
|
||||
*/
|
||||
scanstate->tuplestorestate = NULL;
|
||||
scanstate->funcexpr = ExecInitExpr((Expr *) rte->funcexpr,
|
||||
scanstate->funcexpr = ExecInitExpr((Expr *) node->funcexpr,
|
||||
(PlanState *) scanstate);
|
||||
|
||||
scanstate->ss.ps.ps_TupFromTlist = false;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* 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 *
|
||||
ExecInitValuesScan(ValuesScan *node, EState *estate, int eflags)
|
||||
{
|
||||
ValuesScanState *scanstate;
|
||||
RangeTblEntry *rte;
|
||||
TupleDesc tupdesc;
|
||||
ListCell *vtl;
|
||||
int i;
|
||||
@@ -236,9 +235,7 @@ ExecInitValuesScan(ValuesScan *node, EState *estate, int eflags)
|
||||
/*
|
||||
* get info about values list
|
||||
*/
|
||||
rte = rt_fetch(node->scan.scanrelid, estate->es_range_table);
|
||||
Assert(rte->rtekind == RTE_VALUES);
|
||||
tupdesc = ExecTypeFromExprList((List *) linitial(rte->values_lists));
|
||||
tupdesc = ExecTypeFromExprList((List *) linitial(node->values_lists));
|
||||
|
||||
ExecAssignScanType(&scanstate->ss, tupdesc);
|
||||
|
||||
@@ -247,13 +244,13 @@ ExecInitValuesScan(ValuesScan *node, EState *estate, int eflags)
|
||||
*/
|
||||
scanstate->marked_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 */
|
||||
scanstate->exprlists = (List **)
|
||||
palloc(scanstate->array_len * sizeof(List *));
|
||||
i = 0;
|
||||
foreach(vtl, rte->values_lists)
|
||||
foreach(vtl, node->values_lists)
|
||||
{
|
||||
scanstate->exprlists[i++] = (List *) lfirst(vtl);
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* 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)
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -379,6 +387,11 @@ _copyValuesScan(ValuesScan *from)
|
||||
*/
|
||||
CopyScanFields((Scan *) from, (Scan *) newnode);
|
||||
|
||||
/*
|
||||
* copy remainder of node
|
||||
*/
|
||||
COPY_NODE_FIELD(values_lists);
|
||||
|
||||
return newnode;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* 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
|
||||
* Every node type that can appear in stored rules' parsetrees *must*
|
||||
@@ -408,6 +408,11 @@ _outFunctionScan(StringInfo str, FunctionScan *node)
|
||||
WRITE_NODE_TYPE("FUNCTIONSCAN");
|
||||
|
||||
_outScanInfo(str, (Scan *) node);
|
||||
|
||||
WRITE_NODE_FIELD(funcexpr);
|
||||
WRITE_NODE_FIELD(funccolnames);
|
||||
WRITE_NODE_FIELD(funccoltypes);
|
||||
WRITE_NODE_FIELD(funccoltypmods);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -416,6 +421,8 @@ _outValuesScan(StringInfo str, ValuesScan *node)
|
||||
WRITE_NODE_TYPE("VALUESSCAN");
|
||||
|
||||
_outScanInfo(str, (Scan *) node);
|
||||
|
||||
WRITE_NODE_FIELD(values_lists);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
*
|
||||
*
|
||||
* 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,
|
||||
static TidScan *make_tidscan(List *qptlist, List *qpqual, Index scanrelid,
|
||||
List *tidquals);
|
||||
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,
|
||||
Index scanrelid);
|
||||
Index scanrelid, List *values_lists);
|
||||
static BitmapAnd *make_bitmap_and(List *bitmapplans);
|
||||
static BitmapOr *make_bitmap_or(List *bitmapplans);
|
||||
static NestLoop *make_nestloop(List *tlist,
|
||||
@@ -1350,10 +1351,12 @@ create_functionscan_plan(PlannerInfo *root, Path *best_path,
|
||||
{
|
||||
FunctionScan *scan_plan;
|
||||
Index scan_relid = best_path->parent->relid;
|
||||
RangeTblEntry *rte;
|
||||
|
||||
/* it should be a function base rel... */
|
||||
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 */
|
||||
scan_clauses = order_qual_clauses(root, scan_clauses);
|
||||
@@ -1361,7 +1364,11 @@ create_functionscan_plan(PlannerInfo *root, Path *best_path,
|
||||
/* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
|
||||
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);
|
||||
|
||||
@@ -1379,10 +1386,12 @@ create_valuesscan_plan(PlannerInfo *root, Path *best_path,
|
||||
{
|
||||
ValuesScan *scan_plan;
|
||||
Index scan_relid = best_path->parent->relid;
|
||||
RangeTblEntry *rte;
|
||||
|
||||
/* it should be a values base rel... */
|
||||
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 */
|
||||
scan_clauses = order_qual_clauses(root, scan_clauses);
|
||||
@@ -1390,7 +1399,8 @@ create_valuesscan_plan(PlannerInfo *root, Path *best_path,
|
||||
/* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
|
||||
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);
|
||||
|
||||
@@ -2342,7 +2352,11 @@ make_subqueryscan(List *qptlist,
|
||||
static FunctionScan *
|
||||
make_functionscan(List *qptlist,
|
||||
List *qpqual,
|
||||
Index scanrelid)
|
||||
Index scanrelid,
|
||||
Node *funcexpr,
|
||||
List *funccolnames,
|
||||
List *funccoltypes,
|
||||
List *funccoltypmods)
|
||||
{
|
||||
FunctionScan *node = makeNode(FunctionScan);
|
||||
Plan *plan = &node->scan.plan;
|
||||
@@ -2353,6 +2367,10 @@ make_functionscan(List *qptlist,
|
||||
plan->lefttree = NULL;
|
||||
plan->righttree = NULL;
|
||||
node->scan.scanrelid = scanrelid;
|
||||
node->funcexpr = funcexpr;
|
||||
node->funccolnames = funccolnames;
|
||||
node->funccoltypes = funccoltypes;
|
||||
node->funccoltypmods = funccoltypmods;
|
||||
|
||||
return node;
|
||||
}
|
||||
@@ -2360,7 +2378,8 @@ make_functionscan(List *qptlist,
|
||||
static ValuesScan *
|
||||
make_valuesscan(List *qptlist,
|
||||
List *qpqual,
|
||||
Index scanrelid)
|
||||
Index scanrelid,
|
||||
List *values_lists)
|
||||
{
|
||||
ValuesScan *node = makeNode(ValuesScan);
|
||||
Plan *plan = &node->scan.plan;
|
||||
@@ -2371,6 +2390,7 @@ make_valuesscan(List *qptlist,
|
||||
plan->lefttree = NULL;
|
||||
plan->righttree = NULL;
|
||||
node->scan.scanrelid = scanrelid;
|
||||
node->values_lists = values_lists;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* 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)
|
||||
/* Needs special treatment, see comments below */
|
||||
return set_subqueryscan_references((SubqueryScan *) plan, rtable);
|
||||
case T_FunctionScan:
|
||||
{
|
||||
RangeTblEntry *rte;
|
||||
|
||||
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);
|
||||
}
|
||||
fix_expr_references(plan, (Node *) plan->targetlist);
|
||||
fix_expr_references(plan, (Node *) plan->qual);
|
||||
fix_expr_references(plan, ((FunctionScan *) plan)->funcexpr);
|
||||
break;
|
||||
case T_ValuesScan:
|
||||
{
|
||||
RangeTblEntry *rte;
|
||||
|
||||
fix_expr_references(plan, (Node *) plan->targetlist);
|
||||
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);
|
||||
}
|
||||
fix_expr_references(plan, (Node *) plan->targetlist);
|
||||
fix_expr_references(plan, (Node *) plan->qual);
|
||||
fix_expr_references(plan,
|
||||
(Node *) ((ValuesScan *) plan)->values_lists);
|
||||
break;
|
||||
case T_NestLoop:
|
||||
set_join_references((Join *) plan);
|
||||
@@ -369,10 +356,6 @@ set_subqueryscan_references(SubqueryScan *plan, List *rtable)
|
||||
*lc;
|
||||
|
||||
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);
|
||||
|
||||
/*
|
||||
@@ -544,13 +527,15 @@ adjust_plan_varnos(Plan *plan, int rtoffset)
|
||||
((FunctionScan *) plan)->scan.scanrelid += rtoffset;
|
||||
adjust_expr_varnos((Node *) plan->targetlist, rtoffset);
|
||||
adjust_expr_varnos((Node *) plan->qual, rtoffset);
|
||||
/* rte was already fixed by set_subqueryscan_references */
|
||||
adjust_expr_varnos(((FunctionScan *) plan)->funcexpr,
|
||||
rtoffset);
|
||||
break;
|
||||
case T_ValuesScan:
|
||||
((ValuesScan *) plan)->scan.scanrelid += rtoffset;
|
||||
adjust_expr_varnos((Node *) plan->targetlist, 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;
|
||||
case T_NestLoop:
|
||||
adjust_expr_varnos((Node *) plan->targetlist, rtoffset);
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* 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,
|
||||
break;
|
||||
|
||||
case T_FunctionScan:
|
||||
{
|
||||
RangeTblEntry *rte;
|
||||
|
||||
rte = rt_fetch(((FunctionScan *) plan)->scan.scanrelid,
|
||||
rtable);
|
||||
Assert(rte->rtekind == RTE_FUNCTION);
|
||||
finalize_primnode(rte->funcexpr, &context);
|
||||
}
|
||||
finalize_primnode(((FunctionScan *) plan)->funcexpr,
|
||||
&context);
|
||||
break;
|
||||
|
||||
case T_ValuesScan:
|
||||
{
|
||||
RangeTblEntry *rte;
|
||||
|
||||
rte = rt_fetch(((ValuesScan *) plan)->scan.scanrelid,
|
||||
rtable);
|
||||
Assert(rte->rtekind == RTE_VALUES);
|
||||
finalize_primnode((Node *) rte->values_lists, &context);
|
||||
}
|
||||
finalize_primnode((Node *) ((ValuesScan *) plan)->values_lists,
|
||||
&context);
|
||||
break;
|
||||
|
||||
case T_Append:
|
||||
|
||||
Reference in New Issue
Block a user