mirror of
https://github.com/postgres/postgres.git
synced 2025-07-11 10:01:57 +03:00
pgindent run. Make it all clean.
This commit is contained in:
@ -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);
|
||||
}
|
||||
|
Reference in New Issue
Block a user