static bool extract_query_dependencies_walker(Node *node,
PlannerInfo *context);
-
/*****************************************************************************
*
* SUBPLAN REFERENCES
* Currently, relations and user-defined functions are the only types of
* objects that are explicitly tracked this way.
*
+ * 7. We assign every plan node in the tree a unique ID.
+ *
* We also perform one final optimization step, which is to delete
* SubqueryScan plan nodes that aren't doing anything useful (ie, have
* no qual and a no-op targetlist). The reason for doing this last is that
*
* In the flat rangetable, we zero out substructure pointers that are not
* needed by the executor; this reduces the storage space and copying cost
- * for cached plans. We keep only the alias and eref Alias fields, which are
- * needed by EXPLAIN, and the selectedCols, insertedCols and updatedCols
- * bitmaps, which are needed for executor-startup permissions checking and for
- * trigger event checking.
+ * for cached plans. We keep only the ctename, alias and eref Alias fields,
+ * which are needed by EXPLAIN, and the selectedCols, insertedCols and
+ * updatedCols bitmaps, which are needed for executor-startup permissions
+ * checking and for trigger event checking.
*/
static void
add_rte_to_flat_rtable(PlannerGlobal *glob, RangeTblEntry *rte)
memcpy(newrte, rte, sizeof(RangeTblEntry));
/* zap unneeded sub-structure */
+ newrte->tablesample = NULL;
newrte->subquery = NULL;
newrte->joinaliasvars = NIL;
newrte->functions = NIL;
newrte->ctecoltypes = NIL;
newrte->ctecoltypmods = NIL;
newrte->ctecolcollations = NIL;
+ newrte->securityQuals = NIL;
glob->finalrtable = lappend(glob->finalrtable, newrte);
if (plan == NULL)
return NULL;
+ /* Assign this node a unique ID. */
+ plan->plan_node_id = root->glob->lastPlanNodeId++;
+
/*
* Plan-type-specific fixes
*/
fix_scan_list(root, splan->plan.qual, rtoffset);
}
break;
+ case T_SampleScan:
+ {
+ SampleScan *splan = (SampleScan *) plan;
+
+ splan->scan.scanrelid += rtoffset;
+ splan->scan.plan.targetlist =
+ fix_scan_list(root, splan->scan.plan.targetlist, rtoffset);
+ splan->scan.plan.qual =
+ fix_scan_list(root, splan->scan.plan.qual, rtoffset);
+ splan->tablesample = (TableSampleClause *)
+ fix_scan_expr(root, (Node *) splan->tablesample, rtoffset);
+ }
+ break;
case T_IndexScan:
{
IndexScan *splan = (IndexScan *) plan;
case T_Sort:
case T_Unique:
case T_SetOp:
+ case T_Gather:
/*
* These plan types don't actually bother to evaluate their
}
break;
case T_Agg:
+ set_upper_references(root, plan, rtoffset);
+ break;
case T_Group:
set_upper_references(root, plan, rtoffset);
break;
linitial_int(splan->resultRelations),
rtoffset);
+ pfree(itlist);
+
splan->exclRelTlist =
fix_scan_list(root, splan->exclRelTlist, rtoffset);
}
if (fscan->fdw_scan_tlist != NIL || fscan->scan.scanrelid == 0)
{
- /* Adjust tlist, qual, fdw_exprs to reference custom scan tuple */
+ /* Adjust tlist, qual, fdw_exprs to reference foreign scan tuple */
indexed_tlist *itlist = build_tlist_index(fscan->fdw_scan_tlist);
fscan->scan.plan.targetlist = (List *)
CustomScan *cscan,
int rtoffset)
{
+ ListCell *lc;
+
/* Adjust scanrelid if it's valid */
if (cscan->scan.scanrelid > 0)
cscan->scan.scanrelid += rtoffset;
fix_scan_list(root, cscan->custom_exprs, rtoffset);
}
+ /* Adjust child plan-nodes recursively, if needed */
+ foreach(lc, cscan->custom_plans)
+ {
+ lfirst(lc) = set_plan_refs(root, (Plan *) lfirst(lc), rtoffset);
+ }
+
/* Adjust custom_relids if needed */
if (rtoffset > 0)
{
* This is code that is common to all variants of expression-fixing.
* We must look up operator opcode info for OpExpr and related nodes,
* add OIDs from regclass Const nodes into root->glob->relationOids, and
- * add catalog TIDs for user-defined functions into root->glob->invalItems.
+ * add PlanInvalItems for user-defined functions into root->glob->invalItems.
+ * We also fill in column index lists for GROUPING() expressions.
*
* We assume it's okay to update opcode info in-place. So this could possibly
* scribble on the planner's input data structures, but it's OK.
lappend_oid(root->glob->relationOids,
DatumGetObjectId(con->constvalue));
}
+ else if (IsA(node, GroupingFunc))
+ {
+ GroupingFunc *g = (GroupingFunc *) node;
+ AttrNumber *grouping_map = root->grouping_map;
+
+ /* If there are no grouping sets, we don't need this. */
+
+ Assert(grouping_map || g->cols == NIL);
+
+ if (grouping_map)
+ {
+ ListCell *lc;
+ List *cols = NIL;
+
+ foreach(lc, g->refs)
+ {
+ cols = lappend_int(cols, grouping_map[lfirst_int(lc)]);
+ }
+
+ Assert(!g->cols || equal(cols, g->cols));
+
+ if (!g->cols)
+ g->cols = cols;
+ }
+ }
}
/*
* subplans, by setting the varnos to OUTER_VAR or INNER_VAR and setting
* attno values to the result domain number of either the corresponding
* outer or inner join tuple item. Also perform opcode lookup for these
- * expressions. and add regclass OIDs to root->glob->relationOids.
+ * expressions, and add regclass OIDs to root->glob->relationOids.
*/
static void
set_join_references(PlannerInfo *root, Join *join, int rtoffset)
return rlist;
}
+
/*****************************************************************************
* OPERATOR REGPROC LOOKUP
*****************************************************************************/