* 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 $
*
*-------------------------------------------------------------------------
*/
{
RangeTblEntry *rte = rt_fetch(((Scan *) plan)->scanrelid,
es->rtable);
+ Node *funcexpr;
char *proname;
/* Assert it's on a RangeFunction */
* 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);
* 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 $
*
*-------------------------------------------------------------------------
*/
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:
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags)
{
FunctionScanState *scanstate;
- RangeTblEntry *rte;
Oid funcrettype;
TypeFuncClass functypclass;
TupleDesc tupdesc = NULL;
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);
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,
}
else if (functypclass == TYPEFUNC_RECORD)
{
- tupdesc = BuildDescFromLists(rte->eref->colnames,
- rte->funccoltypes,
- rte->funccoltypmods);
+ tupdesc = BuildDescFromLists(node->funccolnames,
+ node->funccoltypes,
+ node->funccoltypmods);
}
else
{
* 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;
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
ExecInitValuesScan(ValuesScan *node, EState *estate, int eflags)
{
ValuesScanState *scanstate;
- RangeTblEntry *rte;
TupleDesc tupdesc;
ListCell *vtl;
int i;
/*
* 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);
*/
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);
}
* 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 $
*
*-------------------------------------------------------------------------
*/
*/
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;
}
*/
CopyScanFields((Scan *) from, (Scan *) newnode);
+ /*
+ * copy remainder of node
+ */
+ COPY_NODE_FIELD(values_lists);
+
return newnode;
}
*
*
* 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*
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
WRITE_NODE_TYPE("VALUESSCAN");
_outScanInfo(str, (Scan *) node);
+
+ WRITE_NODE_FIELD(values_lists);
}
static void
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
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,
{
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);
/* 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);
{
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);
/* 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);
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;
plan->lefttree = NULL;
plan->righttree = NULL;
node->scan.scanrelid = scanrelid;
+ node->funcexpr = funcexpr;
+ node->funccolnames = funccolnames;
+ node->funccoltypes = funccoltypes;
+ node->funccoltypmods = funccoltypmods;
return node;
}
static ValuesScan *
make_valuesscan(List *qptlist,
List *qpqual,
- Index scanrelid)
+ Index scanrelid,
+ List *values_lists)
{
ValuesScan *node = makeNode(ValuesScan);
Plan *plan = &node->scan.plan;
plan->lefttree = NULL;
plan->righttree = NULL;
node->scan.scanrelid = scanrelid;
+ node->values_lists = values_lists;
return node;
}
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
/* 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);
*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);
/*
((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);
* 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 $
*
*-------------------------------------------------------------------------
*/
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:
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* 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 $
*
*-------------------------------------------------------------------------
*/
* subquery scan node
*
* 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
- * execution contexts. Although we are not scanning a physical relation,
- * we make this a descendant of Scan anyway for code-sharing purposes.
+ * We often need an extra plan node above the sub-query's plan to perform
+ * expression evaluations (which we can't push into the sub-query without
+ * 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
* the generic lefttree field as you might expect. This is because we do
typedef struct FunctionScan
{
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;
/* ----------------
typedef struct ValuesScan
{
Scan scan;
- /* no other fields needed at present */
+ List *values_lists; /* list of expression lists */
} ValuesScan;
/*