mirror of
https://github.com/postgres/postgres.git
synced 2025-08-24 09:27:52 +03:00
pgindent run. Make it all clean.
This commit is contained in:
@@ -104,7 +104,8 @@ transformKeySetQuery(Query *origNode)
|
||||
Node_Copy(origNode, unionNode, distinctClause);
|
||||
Node_Copy(origNode, unionNode, sortClause);
|
||||
Node_Copy(origNode, unionNode, rtable);
|
||||
origNode->jointree->quals = NULL; /* avoid unnecessary copying */
|
||||
origNode->jointree->quals = NULL; /* avoid unnecessary
|
||||
* copying */
|
||||
Node_Copy(origNode, unionNode, jointree);
|
||||
Node_Copy(origNode, unionNode, targetList);
|
||||
|
||||
@@ -216,4 +217,4 @@ inspectOpNode(Expr *expr)
|
||||
return (firstExpr && secondExpr && nodeTag(firstExpr) == T_Var && nodeTag(secondExpr) == T_Const);
|
||||
}
|
||||
|
||||
#endif /* ENABLE_KEY_SET_QUERY */
|
||||
#endif /* ENABLE_KEY_SET_QUERY */
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepqual.c,v 1.28 2001/01/24 19:42:59 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepqual.c,v 1.29 2001/03/22 03:59:38 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -260,6 +260,7 @@ dnfify(Expr *qual)
|
||||
|
||||
return newqual;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*--------------------
|
||||
@@ -663,11 +664,11 @@ or_normalize(List *orlist)
|
||||
* We are going to insert the orlist into multiple places in the
|
||||
* result expression. For most expression types, it'd be OK to
|
||||
* just have multiple links to the same subtree, but this fails
|
||||
* badly for SubLinks (and perhaps other cases?). For safety,
|
||||
* we make a distinct copy for each place the orlist is inserted.
|
||||
* badly for SubLinks (and perhaps other cases?). For safety, we
|
||||
* make a distinct copy for each place the orlist is inserted.
|
||||
*/
|
||||
if (lnext(temp) == NIL)
|
||||
neworlist = orlist; /* can use original tree at the end */
|
||||
neworlist = orlist; /* can use original tree at the end */
|
||||
else
|
||||
neworlist = copyObject(orlist);
|
||||
|
||||
@@ -791,11 +792,12 @@ and_normalize(List *andlist)
|
||||
* We are going to insert the andlist into multiple places in the
|
||||
* result expression. For most expression types, it'd be OK to
|
||||
* just have multiple links to the same subtree, but this fails
|
||||
* badly for SubLinks (and perhaps other cases?). For safety,
|
||||
* we make a distinct copy for each place the andlist is inserted.
|
||||
* badly for SubLinks (and perhaps other cases?). For safety, we
|
||||
* make a distinct copy for each place the andlist is inserted.
|
||||
*/
|
||||
if (lnext(temp) == NIL)
|
||||
newandlist = andlist; /* can use original tree at the end */
|
||||
newandlist = andlist; /* can use original tree at the
|
||||
* end */
|
||||
else
|
||||
newandlist = copyObject(andlist);
|
||||
|
||||
@@ -957,8 +959,10 @@ count_bool_nodes(Expr *qual,
|
||||
}
|
||||
else if (contain_subplans((Node *) qual))
|
||||
{
|
||||
/* charge extra for subexpressions containing sub-SELECTs,
|
||||
* to discourage us from rearranging them in a way that might
|
||||
|
||||
/*
|
||||
* charge extra for subexpressions containing sub-SELECTs, to
|
||||
* discourage us from rearranging them in a way that might
|
||||
* generate N copies of a subselect rather than one. The magic
|
||||
* constant here interacts with the "4x maximum growth" heuristic
|
||||
* in canonicalize_qual().
|
||||
|
@@ -15,7 +15,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/prep/preptlist.c,v 1.41 2001/01/24 19:42:59 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/prep/preptlist.c,v 1.42 2001/03/22 03:59:38 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -33,8 +33,8 @@
|
||||
static List *expand_targetlist(List *tlist, int command_type,
|
||||
Index result_relation, List *range_table);
|
||||
static TargetEntry *process_matched_tle(TargetEntry *src_tle,
|
||||
TargetEntry *prior_tle,
|
||||
int attrno);
|
||||
TargetEntry *prior_tle,
|
||||
int attrno);
|
||||
|
||||
|
||||
/*
|
||||
@@ -49,9 +49,10 @@ preprocess_targetlist(List *tlist,
|
||||
Index result_relation,
|
||||
List *range_table)
|
||||
{
|
||||
|
||||
/*
|
||||
* Sanity check: if there is a result relation, it'd better be a
|
||||
* real relation not a subquery. Else parser or rewriter messed up.
|
||||
* Sanity check: if there is a result relation, it'd better be a real
|
||||
* relation not a subquery. Else parser or rewriter messed up.
|
||||
*/
|
||||
if (result_relation)
|
||||
{
|
||||
@@ -250,7 +251,7 @@ expand_targetlist(List *tlist, int command_type,
|
||||
new_tle = makeTargetEntry(makeResdom(attrno,
|
||||
atttype,
|
||||
atttypmod,
|
||||
pstrdup(attrname),
|
||||
pstrdup(attrname),
|
||||
false),
|
||||
(Node *) temp_var);
|
||||
break;
|
||||
@@ -280,7 +281,7 @@ expand_targetlist(List *tlist, int command_type,
|
||||
{
|
||||
Resdom *resdom = old_tle->resdom;
|
||||
|
||||
if (! resdom->resjunk)
|
||||
if (!resdom->resjunk)
|
||||
elog(ERROR, "Unexpected assignment to attribute \"%s\"",
|
||||
resdom->resname);
|
||||
/* Get the resno right, but don't copy unnecessarily */
|
||||
@@ -314,9 +315,10 @@ expand_targetlist(List *tlist, int command_type,
|
||||
* Essentially, the expression we want to produce in this case is like
|
||||
* foo = array_set(array_set(foo, 2, 42), 4, 43)
|
||||
*/
|
||||
static TargetEntry *process_matched_tle(TargetEntry *src_tle,
|
||||
TargetEntry *prior_tle,
|
||||
int attrno)
|
||||
static TargetEntry *
|
||||
process_matched_tle(TargetEntry *src_tle,
|
||||
TargetEntry *prior_tle,
|
||||
int attrno)
|
||||
{
|
||||
Resdom *resdom = src_tle->resdom;
|
||||
Node *priorbottom;
|
||||
@@ -324,11 +326,13 @@ static TargetEntry *process_matched_tle(TargetEntry *src_tle,
|
||||
|
||||
if (prior_tle == NULL)
|
||||
{
|
||||
|
||||
/*
|
||||
* Normal case where this is the first assignment to the attribute.
|
||||
* Normal case where this is the first assignment to the
|
||||
* attribute.
|
||||
*
|
||||
* We can recycle the old TLE+resdom if right resno; else make a
|
||||
* new one to avoid modifying the old tlist structure. (Is preserving
|
||||
* We can recycle the old TLE+resdom if right resno; else make a new
|
||||
* one to avoid modifying the old tlist structure. (Is preserving
|
||||
* old tlist actually necessary? Not sure, be safe.)
|
||||
*/
|
||||
if (resdom->resno == attrno)
|
||||
@@ -339,7 +343,7 @@ static TargetEntry *process_matched_tle(TargetEntry *src_tle,
|
||||
}
|
||||
|
||||
/*
|
||||
* Multiple assignments to same attribute. Allow only if all are
|
||||
* Multiple assignments to same attribute. Allow only if all are
|
||||
* array-assign operators with same bottom array object.
|
||||
*/
|
||||
if (src_tle->expr == NULL || !IsA(src_tle->expr, ArrayRef) ||
|
||||
@@ -350,16 +354,19 @@ static TargetEntry *process_matched_tle(TargetEntry *src_tle,
|
||||
((ArrayRef *) prior_tle->expr)->refelemtype)
|
||||
elog(ERROR, "Multiple assignments to same attribute \"%s\"",
|
||||
resdom->resname);
|
||||
|
||||
/*
|
||||
* Prior TLE could be a nest of ArrayRefs if we do this more than once.
|
||||
* Prior TLE could be a nest of ArrayRefs if we do this more than
|
||||
* once.
|
||||
*/
|
||||
priorbottom = ((ArrayRef *) prior_tle->expr)->refexpr;
|
||||
while (priorbottom != NULL && IsA(priorbottom, ArrayRef) &&
|
||||
((ArrayRef *) priorbottom)->refassgnexpr != NULL)
|
||||
priorbottom = ((ArrayRef *) priorbottom)->refexpr;
|
||||
if (! equal(priorbottom, ((ArrayRef *) src_tle->expr)->refexpr))
|
||||
if (!equal(priorbottom, ((ArrayRef *) src_tle->expr)->refexpr))
|
||||
elog(ERROR, "Multiple assignments to same attribute \"%s\"",
|
||||
resdom->resname);
|
||||
|
||||
/*
|
||||
* Looks OK to nest 'em.
|
||||
*/
|
||||
|
@@ -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