Put function expressions and values lists into FunctionScan and ValuesScan
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 19 Feb 2007 02:23:12 +0000 (02:23 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 19 Feb 2007 02:23:12 +0000 (02:23 +0000)
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.

src/backend/commands/explain.c
src/backend/executor/execAmi.c
src/backend/executor/nodeFunctionscan.c
src/backend/executor/nodeValuesscan.c
src/backend/nodes/copyfuncs.c
src/backend/nodes/outfuncs.c
src/backend/optimizer/plan/createplan.c
src/backend/optimizer/plan/setrefs.c
src/backend/optimizer/plan/subselect.c
src/include/nodes/plannodes.h

index e5726e7ba0a8a8cef812e647b48c6b1fdc13865c..177e0d5f24f9eac801567f3dd5c2f29ddfdd2af1 100644 (file)
@@ -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);
index d6dd3b021b0b560a13ac5d67230f40bd7971b19e..8e3c545b5a53018f7fe962544480b91015829e7e 100644 (file)
@@ -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:
index 34cc1438943f5a95e6d0197760d3deca8d347091..0417dfa76fff6df2b9d3c0adcee9fa5ea59dd977 100644 (file)
@@ -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;
index 0b75ea94426fd4bbe5d11bd6a8f043d5552a5feb..d5f8f4a9a372146c3e90e479a31f635e0f900426 100644 (file)
@@ -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);
        }
index 8c86ac82695a77220649639e21e8dfcdc2e8e543..b1bb94c55d8ff927cbf4fe337d4bd7403452b815 100644 (file)
@@ -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;
 }
 
index 6e2ac92aefb60d6afe23a92399a3a60d42a3893f..90c2b5153608aa778fe4831fc04e5e5ca45aef97 100644 (file)
@@ -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
index a3a9c1f1035ce299465ceac9a35cade64ffb4230..1981a27c5b8bd12f5befa8ad504ea5476aa9a743 100644 (file)
@@ -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;
 }
index 4a7a6b6e5217f0d31025e3689816f5599e144deb..caab8f88eba93a105caef66b68a568bb6993dba5 100644 (file)
@@ -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);
index 5a368f3ba17198ea3a3688342eda6bc49e21ed88..e781ee8706167918167d7aab909aea6b2e797e69 100644 (file)
@@ -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:
index bd8e014cd97da58dd09dcdab774192ed2c812d09..9186cfb7d9a144e188a1929ae4602a8a4a7fbb6d 100644 (file)
@@ -270,9 +270,11 @@ typedef struct TidScan
  *             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
@@ -293,7 +295,10 @@ typedef struct SubqueryScan
 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;
 
 /* ----------------
@@ -303,7 +308,7 @@ typedef struct FunctionScan
 typedef struct ValuesScan
 {
        Scan            scan;
-       /* no other fields needed at present */
+       List       *values_lists;       /* list of expression lists */
 } ValuesScan;
 
 /*