aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/prep/prepunion.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/prep/prepunion.c')
-rw-r--r--src/backend/optimizer/prep/prepunion.c196
1 files changed, 105 insertions, 91 deletions
diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c
index 85058757e5e..968b9ded780 100644
--- a/src/backend/optimizer/prep/prepunion.c
+++ b/src/backend/optimizer/prep/prepunion.c
@@ -5,7 +5,7 @@
* from a time when only UNIONs were implemented.
*
* There is also some code here to support planning of queries that use
- * inheritance (SELECT FROM foo*). This no longer has much connection
+ * inheritance (SELECT FROM foo*). This no longer has much connection
* to the processing of UNION queries, but it's still here.
*
*
@@ -14,7 +14,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.60 2001/01/24 19:42:59 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.61 2001/03/22 03:59:38 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -50,22 +50,22 @@ typedef struct
} adjust_inherited_attrs_context;
static Plan *recurse_set_operations(Node *setOp, Query *parse,
- List *colTypes, bool junkOK,
- int flag, List *refnames_tlist);
+ List *colTypes, bool junkOK,
+ int flag, List *refnames_tlist);
static Plan *generate_union_plan(SetOperationStmt *op, Query *parse,
- List *refnames_tlist);
+ List *refnames_tlist);
static Plan *generate_nonunion_plan(SetOperationStmt *op, Query *parse,
- List *refnames_tlist);
+ List *refnames_tlist);
static List *recurse_union_children(Node *setOp, Query *parse,
- SetOperationStmt *top_union,
- List *refnames_tlist);
+ SetOperationStmt *top_union,
+ List *refnames_tlist);
static List *generate_setop_tlist(List *colTypes, int flag,
- bool hack_constants,
- List *input_tlist,
- List *refnames_tlist);
+ bool hack_constants,
+ List *input_tlist,
+ List *refnames_tlist);
static bool tlist_same_datatypes(List *tlist, List *colTypes, bool junkOK);
static Node *adjust_inherited_attrs_mutator(Node *node,
- adjust_inherited_attrs_context *context);
+ adjust_inherited_attrs_context *context);
/*
@@ -99,10 +99,10 @@ plan_set_operations(Query *parse)
Assert(leftmostQuery != NULL);
/*
- * Recurse on setOperations tree to generate plans for set ops.
- * The final output plan should have just the column types shown
- * as the output from the top-level node, plus possibly a resjunk
- * working column (we can rely on upper-level nodes to deal with that).
+ * Recurse on setOperations tree to generate plans for set ops. The
+ * final output plan should have just the column types shown as the
+ * output from the top-level node, plus possibly a resjunk working
+ * column (we can rely on upper-level nodes to deal with that).
*/
return recurse_set_operations((Node *) topop, parse,
topop->colTypes, true, -1,
@@ -127,16 +127,18 @@ recurse_set_operations(Node *setOp, Query *parse,
{
RangeTblRef *rtr = (RangeTblRef *) setOp;
RangeTblEntry *rte = rt_fetch(rtr->rtindex, parse->rtable);
- Query *subquery = rte->subquery;
- Plan *subplan,
- *plan;
+ Query *subquery = rte->subquery;
+ Plan *subplan,
+ *plan;
Assert(subquery != NULL);
+
/*
* Generate plan for primitive subquery
*/
subplan = subquery_planner(subquery,
-1.0 /* default case */ );
+
/*
* Add a SubqueryScan with the caller-requested targetlist
*/
@@ -152,28 +154,30 @@ recurse_set_operations(Node *setOp, Query *parse,
else if (IsA(setOp, SetOperationStmt))
{
SetOperationStmt *op = (SetOperationStmt *) setOp;
- Plan *plan;
+ Plan *plan;
/* UNIONs are much different from INTERSECT/EXCEPT */
if (op->op == SETOP_UNION)
plan = generate_union_plan(op, parse, refnames_tlist);
else
plan = generate_nonunion_plan(op, parse, refnames_tlist);
+
/*
* If necessary, add a Result node to project the caller-requested
* output columns.
*
* XXX you don't really want to know about this: setrefs.c will apply
* replace_vars_with_subplan_refs() to the Result node's tlist.
- * This would fail if the input plan's non-resjunk tlist entries were
- * not all simple Vars equal() to the referencing Vars generated by
- * generate_setop_tlist(). However, since the input plan was
- * generated by generate_union_plan() or generate_nonunion_plan(),
- * the referencing Vars will equal the tlist entries they reference.
- * Ugly but I don't feel like making that code more general right now.
+ * This would fail if the input plan's non-resjunk tlist entries
+ * were not all simple Vars equal() to the referencing Vars
+ * generated by generate_setop_tlist(). However, since the input
+ * plan was generated by generate_union_plan() or
+ * generate_nonunion_plan(), the referencing Vars will equal the
+ * tlist entries they reference. Ugly but I don't feel like making
+ * that code more general right now.
*/
if (flag >= 0 ||
- ! tlist_same_datatypes(plan->targetlist, colTypes, junkOK))
+ !tlist_same_datatypes(plan->targetlist, colTypes, junkOK))
{
plan = (Plan *)
make_result(generate_setop_tlist(colTypes, flag, false,
@@ -199,8 +203,8 @@ static Plan *
generate_union_plan(SetOperationStmt *op, Query *parse,
List *refnames_tlist)
{
- List *planlist;
- Plan *plan;
+ List *planlist;
+ Plan *plan;
/*
* If any of my children are identical UNION nodes (same op, all-flag,
@@ -212,27 +216,29 @@ generate_union_plan(SetOperationStmt *op, Query *parse,
op, refnames_tlist),
recurse_union_children(op->rarg, parse,
op, refnames_tlist));
+
/*
* Append the child results together.
*
- * The tlist for an Append plan isn't important as far as the Append
- * is concerned, but we must make it look real anyway for the benefit
- * of the next plan level up.
+ * The tlist for an Append plan isn't important as far as the Append is
+ * concerned, but we must make it look real anyway for the benefit of
+ * the next plan level up.
*/
plan = (Plan *)
make_append(planlist,
false,
generate_setop_tlist(op->colTypes, -1, false,
- ((Plan *) lfirst(planlist))->targetlist,
- refnames_tlist));
+ ((Plan *) lfirst(planlist))->targetlist,
+ refnames_tlist));
+
/*
- * For UNION ALL, we just need the Append plan. For UNION,
- * need to add Sort and Unique nodes to produce unique output.
+ * For UNION ALL, we just need the Append plan. For UNION, need to
+ * add Sort and Unique nodes to produce unique output.
*/
- if (! op->all)
+ if (!op->all)
{
- List *tlist,
- *sortList;
+ List *tlist,
+ *sortList;
tlist = new_unsorted_tlist(plan->targetlist);
sortList = addAllTargetsToSortList(NIL, tlist);
@@ -249,12 +255,12 @@ static Plan *
generate_nonunion_plan(SetOperationStmt *op, Query *parse,
List *refnames_tlist)
{
- Plan *lplan,
- *rplan,
- *plan;
- List *tlist,
- *sortList;
- SetOpCmd cmd;
+ Plan *lplan,
+ *rplan,
+ *plan;
+ List *tlist,
+ *sortList;
+ SetOpCmd cmd;
/* Recurse on children, ensuring their outputs are marked */
lplan = recurse_set_operations(op->larg, parse,
@@ -263,12 +269,13 @@ generate_nonunion_plan(SetOperationStmt *op, Query *parse,
rplan = recurse_set_operations(op->rarg, parse,
op->colTypes, false, 1,
refnames_tlist);
+
/*
* Append the child results together.
*
- * The tlist for an Append plan isn't important as far as the Append
- * is concerned, but we must make it look real anyway for the benefit
- * of the next plan level up.
+ * The tlist for an Append plan isn't important as far as the Append is
+ * concerned, but we must make it look real anyway for the benefit of
+ * the next plan level up.
*/
plan = (Plan *)
make_append(makeList2(lplan, rplan),
@@ -276,9 +283,10 @@ generate_nonunion_plan(SetOperationStmt *op, Query *parse,
generate_setop_tlist(op->colTypes, 0, false,
lplan->targetlist,
refnames_tlist));
+
/*
- * Sort the child results, then add a SetOp plan node to
- * generate the correct output.
+ * Sort the child results, then add a SetOp plan node to generate the
+ * correct output.
*/
tlist = new_unsorted_tlist(plan->targetlist);
sortList = addAllTargetsToSortList(NIL, tlist);
@@ -293,11 +301,11 @@ generate_nonunion_plan(SetOperationStmt *op, Query *parse,
break;
default:
elog(ERROR, "generate_nonunion_plan: bogus operation code");
- cmd = SETOPCMD_INTERSECT; /* keep compiler quiet */
+ cmd = SETOPCMD_INTERSECT; /* keep compiler quiet */
break;
}
plan = (Plan *) make_setop(cmd, tlist, plan, sortList,
- length(op->colTypes)+1);
+ length(op->colTypes) + 1);
return plan;
}
@@ -322,20 +330,21 @@ recurse_union_children(Node *setOp, Query *parse,
{
/* Same UNION, so fold children into parent's subplan list */
return nconc(recurse_union_children(op->larg, parse,
- top_union, refnames_tlist),
+ top_union, refnames_tlist),
recurse_union_children(op->rarg, parse,
- top_union, refnames_tlist));
+ top_union, refnames_tlist));
}
}
+
/*
* Not same, so plan this child separately.
*
- * Note we disallow any resjunk columns in child results. This
- * is necessary since the Append node that implements the union
- * won't do any projection, and upper levels will get confused if
- * some of our output tuples have junk and some don't. This case
- * only arises when we have an EXCEPT or INTERSECT as child, else
- * there won't be resjunk anyway.
+ * Note we disallow any resjunk columns in child results. This is
+ * necessary since the Append node that implements the union won't do
+ * any projection, and upper levels will get confused if some of our
+ * output tuples have junk and some don't. This case only arises when
+ * we have an EXCEPT or INTERSECT as child, else there won't be
+ * resjunk anyway.
*/
return makeList1(recurse_set_operations(setOp, parse,
top_union->colTypes, false,
@@ -359,7 +368,7 @@ generate_setop_tlist(List *colTypes, int flag,
foreach(i, colTypes)
{
- Oid colType = (Oid) lfirsti(i);
+ Oid colType = (Oid) lfirsti(i);
TargetEntry *inputtle = (TargetEntry *) lfirst(input_tlist);
TargetEntry *reftle = (TargetEntry *) lfirst(refnames_tlist);
@@ -367,18 +376,19 @@ generate_setop_tlist(List *colTypes, int flag,
Assert(reftle->resdom->resno == resno);
Assert(!inputtle->resdom->resjunk);
Assert(!reftle->resdom->resjunk);
+
/*
* Generate columns referencing input columns and having
* appropriate data types and column names. Insert datatype
* coercions where necessary.
*
* HACK: constants in the input's targetlist are copied up as-is
- * rather than being referenced as subquery outputs. This is mainly
- * to ensure that when we try to coerce them to the output column's
- * datatype, the right things happen for UNKNOWN constants. But do
- * this only at the first level of subquery-scan plans; we don't
- * want phony constants appearing in the output tlists of upper-level
- * nodes!
+ * rather than being referenced as subquery outputs. This is
+ * mainly to ensure that when we try to coerce them to the output
+ * column's datatype, the right things happen for UNKNOWN
+ * constants. But do this only at the first level of
+ * subquery-scan plans; we don't want phony constants appearing in
+ * the output tlists of upper-level nodes!
*/
resdom = makeResdom((AttrNumber) resno++,
colType,
@@ -440,7 +450,7 @@ tlist_same_datatypes(List *tlist, List *colTypes, bool junkOK)
if (tle->resdom->resjunk)
{
- if (! junkOK)
+ if (!junkOK)
return false;
}
else
@@ -484,11 +494,11 @@ find_all_inheritors(Oid parentrel)
currentchildren = find_inheritance_children(currentrel);
/*
- * Add to the queue only those children not already seen.
- * This avoids making duplicate entries in case of multiple
- * inheritance paths from the same parent. (It'll also keep
- * us from getting into an infinite loop, though theoretically
- * there can't be any cycles in the inheritance graph anyway.)
+ * Add to the queue only those children not already seen. This
+ * avoids making duplicate entries in case of multiple inheritance
+ * paths from the same parent. (It'll also keep us from getting
+ * into an infinite loop, though theoretically there can't be any
+ * cycles in the inheritance graph anyway.)
*/
currentchildren = set_differencei(currentchildren, examined_relids);
unexamined_relids = set_unioni(unexamined_relids, currentchildren);
@@ -524,20 +534,21 @@ expand_inherted_rtentry(Query *parse, Index rti)
List *l;
/* Does RT entry allow inheritance? */
- if (! rte->inh)
+ if (!rte->inh)
return NIL;
Assert(parentOID != InvalidOid && rte->subquery == NULL);
/* Always clear the parent's inh flag, see above comments */
rte->inh = false;
/* Fast path for common case of childless table */
- if (! has_subclass(parentOID))
+ if (!has_subclass(parentOID))
return NIL;
/* Scan for all members of inheritance set */
inhOIDs = find_all_inheritors(parentOID);
+
/*
- * Check that there's at least one descendant, else treat as
- * no-child case. This could happen despite above has_subclass()
- * check, if table once had a child but no longer does.
+ * Check that there's at least one descendant, else treat as no-child
+ * case. This could happen despite above has_subclass() check, if
+ * table once had a child but no longer does.
*/
if (lnext(inhOIDs) == NIL)
return NIL;
@@ -545,18 +556,19 @@ expand_inherted_rtentry(Query *parse, Index rti)
inhRTIs = makeListi1(rti);
foreach(l, inhOIDs)
{
- Oid childOID = (Oid) lfirsti(l);
+ Oid childOID = (Oid) lfirsti(l);
RangeTblEntry *childrte;
- Index childRTindex;
+ Index childRTindex;
/* parent will be in the list too, so ignore it */
if (childOID == parentOID)
continue;
/*
- * Build an RTE for the child, and attach to query's rangetable list.
- * We copy most fields of the parent's RTE, but replace relation
- * real name and OID. Note that inh will be false at this point.
+ * Build an RTE for the child, and attach to query's rangetable
+ * list. We copy most fields of the parent's RTE, but replace
+ * relation real name and OID. Note that inh will be false at
+ * this point.
*/
childrte = copyObject(rte);
childrte->relname = get_rel_name(childOID);
@@ -575,12 +587,12 @@ expand_inherted_rtentry(Query *parse, Index rti)
* to old_rt_index to refer to new_rt_index.
*
* We also adjust varattno to match the new table by column name, rather
- * than column number. This hack makes it possible for child tables to have
+ * than column number. This hack makes it possible for child tables to have
* different column positions for the "same" attribute as a parent, which
* helps ALTER TABLE ADD COLUMN. Unfortunately this isn't nearly enough to
* make it work transparently; there are other places where things fall down
* if children and parents don't have the same column numbers for inherited
- * attributes. It'd be better to rip this code out and fix ALTER TABLE...
+ * attributes. It'd be better to rip this code out and fix ALTER TABLE...
*/
Node *
adjust_inherited_attrs(Node *node,
@@ -643,12 +655,13 @@ adjust_inherited_attrs_mutator(Node *node,
}
if (IsA(node, RangeTblRef))
{
- RangeTblRef *rtr = (RangeTblRef *) copyObject(node);
+ RangeTblRef *rtr = (RangeTblRef *) copyObject(node);
if (rtr->rtindex == context->old_rt_index)
rtr->rtindex = context->new_rt_index;
return (Node *) rtr;
}
+
/*
* We have to process RestrictInfo nodes specially: we do NOT want to
* copy the original subclauseindices list, since the new rel may have
@@ -656,8 +669,8 @@ adjust_inherited_attrs_mutator(Node *node,
*/
if (IsA(node, RestrictInfo))
{
- RestrictInfo *oldinfo = (RestrictInfo *) node;
- RestrictInfo *newinfo = makeNode(RestrictInfo);
+ RestrictInfo *oldinfo = (RestrictInfo *) node;
+ RestrictInfo *newinfo = makeNode(RestrictInfo);
/* Copy all flat-copiable fields */
memcpy(newinfo, oldinfo, sizeof(RestrictInfo));
@@ -666,18 +679,19 @@ adjust_inherited_attrs_mutator(Node *node,
adjust_inherited_attrs_mutator((Node *) oldinfo->clause, context);
newinfo->subclauseindices = NIL;
- newinfo->eval_cost = -1; /* reset this too */
- newinfo->left_pathkey = NIL; /* and these */
+ newinfo->eval_cost = -1;/* reset this too */
+ newinfo->left_pathkey = NIL; /* and these */
newinfo->right_pathkey = NIL;
newinfo->left_dispersion = -1;
newinfo->right_dispersion = -1;
return (Node *) newinfo;
}
+
/*
* NOTE: we do not need to recurse into sublinks, because they should
* already have been converted to subplans before we see them.
*/
return expression_tree_mutator(node, adjust_inherited_attrs_mutator,
- (void *) context);
+ (void *) context);
}