mirror of
https://github.com/postgres/postgres.git
synced 2025-11-07 19:06:32 +03:00
Standard pgindent run for 8.1.
This commit is contained in:
@@ -16,7 +16,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/prep/prepjointree.c,v 1.30 2005/08/01 20:31:09 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/prep/prepjointree.c,v 1.31 2005/10/15 02:49:20 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -143,8 +143,8 @@ pull_up_subqueries(PlannerInfo *root, Node *jtnode, bool below_outer_join)
|
||||
Query *subquery = rte->subquery;
|
||||
|
||||
/*
|
||||
* Is this a subquery RTE, and if so, is the subquery simple
|
||||
* enough to pull up? (If not, do nothing at this node.)
|
||||
* Is this a subquery RTE, and if so, is the subquery simple enough to
|
||||
* pull up? (If not, do nothing at this node.)
|
||||
*
|
||||
* If we are inside an outer join, only pull up subqueries whose
|
||||
* targetlists are nullable --- otherwise substituting their tlist
|
||||
@@ -153,8 +153,8 @@ pull_up_subqueries(PlannerInfo *root, Node *jtnode, bool below_outer_join)
|
||||
*
|
||||
* XXX This could be improved by generating pseudo-variables for such
|
||||
* expressions; we'd have to figure out how to get the pseudo-
|
||||
* variables evaluated at the right place in the modified plan
|
||||
* tree. Fix it someday.
|
||||
* variables evaluated at the right place in the modified plan tree.
|
||||
* Fix it someday.
|
||||
*/
|
||||
if (rte->rtekind == RTE_SUBQUERY &&
|
||||
is_simple_subquery(subquery) &&
|
||||
@@ -166,53 +166,53 @@ pull_up_subqueries(PlannerInfo *root, Node *jtnode, bool below_outer_join)
|
||||
ListCell *rt;
|
||||
|
||||
/*
|
||||
* Need a modifiable copy of the subquery to hack on. Even if
|
||||
* we didn't sometimes choose not to pull up below, we must do
|
||||
* this to avoid problems if the same subquery is referenced
|
||||
* from multiple jointree items (which can't happen normally,
|
||||
* but might after rule rewriting).
|
||||
* Need a modifiable copy of the subquery to hack on. Even if we
|
||||
* didn't sometimes choose not to pull up below, we must do this
|
||||
* to avoid problems if the same subquery is referenced from
|
||||
* multiple jointree items (which can't happen normally, but might
|
||||
* after rule rewriting).
|
||||
*/
|
||||
subquery = copyObject(subquery);
|
||||
|
||||
/*
|
||||
* Create a PlannerInfo data structure for this subquery.
|
||||
*
|
||||
* NOTE: the next few steps should match the first processing
|
||||
* in subquery_planner(). Can we refactor to avoid code
|
||||
* duplication, or would that just make things uglier?
|
||||
* NOTE: the next few steps should match the first processing in
|
||||
* subquery_planner(). Can we refactor to avoid code duplication,
|
||||
* or would that just make things uglier?
|
||||
*/
|
||||
subroot = makeNode(PlannerInfo);
|
||||
subroot->parse = subquery;
|
||||
|
||||
/*
|
||||
* Pull up any IN clauses within the subquery's WHERE, so that
|
||||
* we don't leave unoptimized INs behind.
|
||||
* Pull up any IN clauses within the subquery's WHERE, so that we
|
||||
* don't leave unoptimized INs behind.
|
||||
*/
|
||||
subroot->in_info_list = NIL;
|
||||
if (subquery->hasSubLinks)
|
||||
subquery->jointree->quals = pull_up_IN_clauses(subroot,
|
||||
subquery->jointree->quals);
|
||||
subquery->jointree->quals);
|
||||
|
||||
/*
|
||||
* Recursively pull up the subquery's subqueries, so that this
|
||||
* routine's processing is complete for its jointree and
|
||||
* rangetable.
|
||||
*
|
||||
* Note: 'false' is correct here even if we are within an outer
|
||||
* join in the upper query; the lower query starts with a
|
||||
* clean slate for outer-join semantics.
|
||||
* Note: 'false' is correct here even if we are within an outer join
|
||||
* in the upper query; the lower query starts with a clean slate
|
||||
* for outer-join semantics.
|
||||
*/
|
||||
subquery->jointree = (FromExpr *)
|
||||
pull_up_subqueries(subroot, (Node *) subquery->jointree,
|
||||
false);
|
||||
|
||||
/*
|
||||
* Now we must recheck whether the subquery is still simple
|
||||
* enough to pull up. If not, abandon processing it.
|
||||
* Now we must recheck whether the subquery is still simple enough
|
||||
* to pull up. If not, abandon processing it.
|
||||
*
|
||||
* We don't really need to recheck all the conditions involved,
|
||||
* but it's easier just to keep this "if" looking the same as
|
||||
* the one above.
|
||||
* We don't really need to recheck all the conditions involved, but
|
||||
* it's easier just to keep this "if" looking the same as the one
|
||||
* above.
|
||||
*/
|
||||
if (is_simple_subquery(subquery) &&
|
||||
(!below_outer_join || has_nullable_targetlist(subquery)))
|
||||
@@ -224,10 +224,10 @@ pull_up_subqueries(PlannerInfo *root, Node *jtnode, bool below_outer_join)
|
||||
/*
|
||||
* Give up, return unmodified RangeTblRef.
|
||||
*
|
||||
* Note: The work we just did will be redone when the
|
||||
* subquery gets planned on its own. Perhaps we could
|
||||
* avoid that by storing the modified subquery back into
|
||||
* the rangetable, but I'm not gonna risk it now.
|
||||
* Note: The work we just did will be redone when the subquery
|
||||
* gets planned on its own. Perhaps we could avoid that by
|
||||
* storing the modified subquery back into the rangetable, but
|
||||
* I'm not gonna risk it now.
|
||||
*/
|
||||
return jtnode;
|
||||
}
|
||||
@@ -242,8 +242,8 @@ pull_up_subqueries(PlannerInfo *root, Node *jtnode, bool below_outer_join)
|
||||
OffsetVarNodes((Node *) subroot->in_info_list, rtoffset, 0);
|
||||
|
||||
/*
|
||||
* Upper-level vars in subquery are now one level closer to
|
||||
* their parent than before.
|
||||
* Upper-level vars in subquery are now one level closer to their
|
||||
* parent than before.
|
||||
*/
|
||||
IncrementVarSublevelsUp((Node *) subquery, -1, 1);
|
||||
IncrementVarSublevelsUp((Node *) subroot->in_info_list, -1, 1);
|
||||
@@ -251,9 +251,8 @@ pull_up_subqueries(PlannerInfo *root, Node *jtnode, bool below_outer_join)
|
||||
/*
|
||||
* Replace all of the top query's references to the subquery's
|
||||
* outputs with copies of the adjusted subtlist items, being
|
||||
* careful not to replace any of the jointree structure.
|
||||
* (This'd be a lot cleaner if we could use
|
||||
* query_tree_mutator.)
|
||||
* careful not to replace any of the jointree structure. (This'd
|
||||
* be a lot cleaner if we could use query_tree_mutator.)
|
||||
*/
|
||||
subtlist = subquery->targetList;
|
||||
parse->targetList = (List *)
|
||||
@@ -284,9 +283,9 @@ pull_up_subqueries(PlannerInfo *root, Node *jtnode, bool below_outer_join)
|
||||
}
|
||||
|
||||
/*
|
||||
* Now append the adjusted rtable entries to upper query. (We
|
||||
* hold off until after fixing the upper rtable entries; no
|
||||
* point in running that code on the subquery ones too.)
|
||||
* Now append the adjusted rtable entries to upper query. (We hold
|
||||
* off until after fixing the upper rtable entries; no point in
|
||||
* running that code on the subquery ones too.)
|
||||
*/
|
||||
parse->rtable = list_concat(parse->rtable, subquery->rtable);
|
||||
|
||||
@@ -295,8 +294,8 @@ pull_up_subqueries(PlannerInfo *root, Node *jtnode, bool below_outer_join)
|
||||
* already adjusted the marker values, so just list_concat the
|
||||
* list.)
|
||||
*
|
||||
* Executor can't handle multiple FOR UPDATE/SHARE/NOWAIT flags,
|
||||
* so complain if they are valid but different
|
||||
* Executor can't handle multiple FOR UPDATE/SHARE/NOWAIT flags, so
|
||||
* complain if they are valid but different
|
||||
*/
|
||||
if (parse->rowMarks && subquery->rowMarks)
|
||||
{
|
||||
@@ -307,7 +306,7 @@ pull_up_subqueries(PlannerInfo *root, Node *jtnode, bool below_outer_join)
|
||||
if (parse->rowNoWait != subquery->rowNoWait)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("cannot use both wait and NOWAIT in one query")));
|
||||
errmsg("cannot use both wait and NOWAIT in one query")));
|
||||
}
|
||||
parse->rowMarks = list_concat(parse->rowMarks, subquery->rowMarks);
|
||||
if (subquery->rowMarks)
|
||||
@@ -317,10 +316,9 @@ pull_up_subqueries(PlannerInfo *root, Node *jtnode, bool below_outer_join)
|
||||
}
|
||||
|
||||
/*
|
||||
* We also have to fix the relid sets of any parent
|
||||
* InClauseInfo nodes. (This could perhaps be done by
|
||||
* ResolveNew, but it would clutter that routine's API
|
||||
* unreasonably.)
|
||||
* We also have to fix the relid sets of any parent InClauseInfo
|
||||
* nodes. (This could perhaps be done by ResolveNew, but it would
|
||||
* clutter that routine's API unreasonably.)
|
||||
*/
|
||||
if (root->in_info_list)
|
||||
{
|
||||
@@ -392,8 +390,8 @@ pull_up_subqueries(PlannerInfo *root, Node *jtnode, bool below_outer_join)
|
||||
case JOIN_UNION:
|
||||
|
||||
/*
|
||||
* This is where we fail if upper levels of planner
|
||||
* haven't rewritten UNION JOIN as an Append ...
|
||||
* This is where we fail if upper levels of planner haven't
|
||||
* rewritten UNION JOIN as an Append ...
|
||||
*/
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
@@ -436,8 +434,8 @@ is_simple_subquery(Query *subquery)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* Can't pull up a subquery involving grouping, aggregation, sorting,
|
||||
* or limiting.
|
||||
* Can't pull up a subquery involving grouping, aggregation, sorting, or
|
||||
* limiting.
|
||||
*/
|
||||
if (subquery->hasAggs ||
|
||||
subquery->groupClause ||
|
||||
@@ -449,21 +447,20 @@ is_simple_subquery(Query *subquery)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* Don't pull up a subquery that has any set-returning functions in
|
||||
* its targetlist. Otherwise we might well wind up inserting
|
||||
* set-returning functions into places where they mustn't go, such as
|
||||
* quals of higher queries.
|
||||
* Don't pull up a subquery that has any set-returning functions in its
|
||||
* targetlist. Otherwise we might well wind up inserting set-returning
|
||||
* functions into places where they mustn't go, such as quals of higher
|
||||
* queries.
|
||||
*/
|
||||
if (expression_returns_set((Node *) subquery->targetList))
|
||||
return false;
|
||||
|
||||
/*
|
||||
* Hack: don't try to pull up a subquery with an empty jointree.
|
||||
* query_planner() will correctly generate a Result plan for a
|
||||
* jointree that's totally empty, but I don't think the right things
|
||||
* happen if an empty FromExpr appears lower down in a jointree. Not
|
||||
* worth working hard on this, just to collapse SubqueryScan/Result
|
||||
* into Result...
|
||||
* query_planner() will correctly generate a Result plan for a jointree
|
||||
* that's totally empty, but I don't think the right things happen if an
|
||||
* empty FromExpr appears lower down in a jointree. Not worth working hard
|
||||
* on this, just to collapse SubqueryScan/Result into Result...
|
||||
*/
|
||||
if (subquery->jointree->fromlist == NIL)
|
||||
return false;
|
||||
@@ -545,8 +542,8 @@ resolvenew_in_jointree(Node *jtnode, int varno,
|
||||
subtlist, CMD_SELECT, 0);
|
||||
|
||||
/*
|
||||
* We don't bother to update the colvars list, since it won't be
|
||||
* used again ...
|
||||
* We don't bother to update the colvars list, since it won't be used
|
||||
* again ...
|
||||
*/
|
||||
}
|
||||
else
|
||||
@@ -583,14 +580,13 @@ reduce_outer_joins(PlannerInfo *root)
|
||||
reduce_outer_joins_state *state;
|
||||
|
||||
/*
|
||||
* To avoid doing strictness checks on more quals than necessary, we
|
||||
* want to stop descending the jointree as soon as there are no outer
|
||||
* joins below our current point. This consideration forces a
|
||||
* two-pass process. The first pass gathers information about which
|
||||
* base rels appear below each side of each join clause, and about
|
||||
* whether there are outer join(s) below each side of each join
|
||||
* clause. The second pass examines qual clauses and changes join
|
||||
* types as it descends the tree.
|
||||
* To avoid doing strictness checks on more quals than necessary, we want
|
||||
* to stop descending the jointree as soon as there are no outer joins
|
||||
* below our current point. This consideration forces a two-pass process.
|
||||
* The first pass gathers information about which base rels appear below
|
||||
* each side of each join clause, and about whether there are outer
|
||||
* join(s) below each side of each join clause. The second pass examines
|
||||
* qual clauses and changes join types as it descends the tree.
|
||||
*/
|
||||
state = reduce_outer_joins_pass1((Node *) root->parse->jointree);
|
||||
|
||||
@@ -768,12 +764,11 @@ reduce_outer_joins_pass2(Node *jtnode,
|
||||
|
||||
/*
|
||||
* If this join is (now) inner, we can add any nonnullability
|
||||
* constraints its quals provide to those we got from above.
|
||||
* But if it is outer, we can only pass down the local
|
||||
* constraints into the nullable side, because an outer join
|
||||
* never eliminates any rows from its non-nullable side. If
|
||||
* it's a FULL join then it doesn't eliminate anything from
|
||||
* either side.
|
||||
* constraints its quals provide to those we got from above. But
|
||||
* if it is outer, we can only pass down the local constraints
|
||||
* into the nullable side, because an outer join never eliminates
|
||||
* any rows from its non-nullable side. If it's a FULL join then
|
||||
* it doesn't eliminate anything from either side.
|
||||
*/
|
||||
if (jointype != JOIN_FULL)
|
||||
{
|
||||
@@ -782,8 +777,7 @@ reduce_outer_joins_pass2(Node *jtnode,
|
||||
nonnullable_rels);
|
||||
}
|
||||
else
|
||||
local_nonnullable = NULL; /* no use in calculating
|
||||
* it */
|
||||
local_nonnullable = NULL; /* no use in calculating it */
|
||||
|
||||
if (left_state->contains_outer)
|
||||
{
|
||||
@@ -886,8 +880,8 @@ find_nonnullable_rels(Node *node, bool top_level)
|
||||
NullTest *expr = (NullTest *) node;
|
||||
|
||||
/*
|
||||
* IS NOT NULL can be considered strict, but only at top level;
|
||||
* else we might have something like NOT (x IS NOT NULL).
|
||||
* IS NOT NULL can be considered strict, but only at top level; else
|
||||
* we might have something like NOT (x IS NOT NULL).
|
||||
*/
|
||||
if (top_level && expr->nulltesttype == IS_NOT_NULL)
|
||||
result = find_nonnullable_rels((Node *) expr->arg, false);
|
||||
@@ -960,10 +954,10 @@ simplify_jointree(PlannerInfo *root, Node *jtnode)
|
||||
if (child && IsA(child, FromExpr))
|
||||
{
|
||||
/*
|
||||
* Yes, so do we want to merge it into parent? Always do
|
||||
* so if child has just one element (since that doesn't
|
||||
* make the parent's list any longer). Otherwise merge if
|
||||
* the resulting join list would be no longer than
|
||||
* Yes, so do we want to merge it into parent? Always do so
|
||||
* if child has just one element (since that doesn't make the
|
||||
* parent's list any longer). Otherwise merge if the
|
||||
* resulting join list would be no longer than
|
||||
* from_collapse_limit.
|
||||
*/
|
||||
FromExpr *subf = (FromExpr *) child;
|
||||
@@ -976,9 +970,9 @@ simplify_jointree(PlannerInfo *root, Node *jtnode)
|
||||
newlist = list_concat(newlist, subf->fromlist);
|
||||
|
||||
/*
|
||||
* By now, the quals have been converted to
|
||||
* implicit-AND lists, so we just need to join the
|
||||
* lists. NOTE: we put the pulled-up quals first.
|
||||
* By now, the quals have been converted to implicit-AND
|
||||
* lists, so we just need to join the lists. NOTE: we put
|
||||
* the pulled-up quals first.
|
||||
*/
|
||||
f->quals = (Node *) list_concat((List *) subf->quals,
|
||||
(List *) f->quals);
|
||||
@@ -1000,8 +994,8 @@ simplify_jointree(PlannerInfo *root, Node *jtnode)
|
||||
j->rarg = simplify_jointree(root, j->rarg);
|
||||
|
||||
/*
|
||||
* If it is an outer join, we must not flatten it. An inner join
|
||||
* is semantically equivalent to a FromExpr; we convert it to one,
|
||||
* If it is an outer join, we must not flatten it. An inner join is
|
||||
* semantically equivalent to a FromExpr; we convert it to one,
|
||||
* allowing it to be flattened into its parent, if the resulting
|
||||
* FromExpr would have no more than join_collapse_limit members.
|
||||
*/
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/prep/prepqual.c,v 1.50 2005/07/29 21:40:02 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/prep/prepqual.c,v 1.51 2005/10/15 02:49:21 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -73,10 +73,10 @@ canonicalize_qual(Expr *qual)
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* Push down NOTs. We do this only in the top-level boolean
|
||||
* expression, without examining arguments of operators/functions. The
|
||||
* main reason for doing this is to expose as much top-level AND/OR
|
||||
* structure as we can, so there's no point in descending further.
|
||||
* Push down NOTs. We do this only in the top-level boolean expression,
|
||||
* without examining arguments of operators/functions. The main reason for
|
||||
* doing this is to expose as much top-level AND/OR structure as we can,
|
||||
* so there's no point in descending further.
|
||||
*/
|
||||
newqual = find_nots(qual);
|
||||
|
||||
@@ -110,12 +110,12 @@ pull_ands(List *andlist)
|
||||
/*
|
||||
* Note: we can destructively concat the subexpression's arglist
|
||||
* because we know the recursive invocation of pull_ands will have
|
||||
* built a new arglist not shared with any other expr. Otherwise
|
||||
* we'd need a list_copy here.
|
||||
* built a new arglist not shared with any other expr. Otherwise we'd
|
||||
* need a list_copy here.
|
||||
*/
|
||||
if (and_clause(subexpr))
|
||||
out_list = list_concat(out_list,
|
||||
pull_ands(((BoolExpr *) subexpr)->args));
|
||||
pull_ands(((BoolExpr *) subexpr)->args));
|
||||
else
|
||||
out_list = lappend(out_list, subexpr);
|
||||
}
|
||||
@@ -142,12 +142,12 @@ pull_ors(List *orlist)
|
||||
/*
|
||||
* Note: we can destructively concat the subexpression's arglist
|
||||
* because we know the recursive invocation of pull_ors will have
|
||||
* built a new arglist not shared with any other expr. Otherwise
|
||||
* we'd need a list_copy here.
|
||||
* built a new arglist not shared with any other expr. Otherwise we'd
|
||||
* need a list_copy here.
|
||||
*/
|
||||
if (or_clause(subexpr))
|
||||
out_list = list_concat(out_list,
|
||||
pull_ors(((BoolExpr *) subexpr)->args));
|
||||
pull_ors(((BoolExpr *) subexpr)->args));
|
||||
else
|
||||
out_list = lappend(out_list, subexpr);
|
||||
}
|
||||
@@ -249,8 +249,8 @@ push_nots(Expr *qual)
|
||||
{
|
||||
/*
|
||||
* Another NOT cancels this NOT, so eliminate the NOT and stop
|
||||
* negating this branch. But search the subexpression for more
|
||||
* NOTs to simplify.
|
||||
* negating this branch. But search the subexpression for more NOTs
|
||||
* to simplify.
|
||||
*/
|
||||
return find_nots(get_notclausearg(qual));
|
||||
}
|
||||
@@ -307,8 +307,8 @@ find_duplicate_ors(Expr *qual)
|
||||
orlist = lappend(orlist, find_duplicate_ors(lfirst(temp)));
|
||||
|
||||
/*
|
||||
* Don't need pull_ors() since this routine will never introduce
|
||||
* an OR where there wasn't one before.
|
||||
* Don't need pull_ors() since this routine will never introduce an OR
|
||||
* where there wasn't one before.
|
||||
*/
|
||||
return process_duplicate_ors(orlist);
|
||||
}
|
||||
@@ -353,10 +353,10 @@ process_duplicate_ors(List *orlist)
|
||||
return linitial(orlist);
|
||||
|
||||
/*
|
||||
* Choose the shortest AND clause as the reference list --- obviously,
|
||||
* any subclause not in this clause isn't in all the clauses. If we
|
||||
* find a clause that's not an AND, we can treat it as a one-element
|
||||
* AND clause, which necessarily wins as shortest.
|
||||
* Choose the shortest AND clause as the reference list --- obviously, any
|
||||
* subclause not in this clause isn't in all the clauses. If we find a
|
||||
* clause that's not an AND, we can treat it as a one-element AND clause,
|
||||
* which necessarily wins as shortest.
|
||||
*/
|
||||
foreach(temp, orlist)
|
||||
{
|
||||
@@ -386,8 +386,8 @@ process_duplicate_ors(List *orlist)
|
||||
reference = list_union(NIL, reference);
|
||||
|
||||
/*
|
||||
* Check each element of the reference list to see if it's in all the
|
||||
* OR clauses. Build a new list of winning clauses.
|
||||
* Check each element of the reference list to see if it's in all the OR
|
||||
* clauses. Build a new list of winning clauses.
|
||||
*/
|
||||
winners = NIL;
|
||||
foreach(temp, reference)
|
||||
@@ -431,13 +431,12 @@ process_duplicate_ors(List *orlist)
|
||||
/*
|
||||
* Generate new OR list consisting of the remaining sub-clauses.
|
||||
*
|
||||
* If any clause degenerates to empty, then we have a situation like (A
|
||||
* AND B) OR (A), which can be reduced to just A --- that is, the
|
||||
* additional conditions in other arms of the OR are irrelevant.
|
||||
* If any clause degenerates to empty, then we have a situation like (A AND
|
||||
* B) OR (A), which can be reduced to just A --- that is, the additional
|
||||
* conditions in other arms of the OR are irrelevant.
|
||||
*
|
||||
* Note that because we use list_difference, any multiple occurrences of
|
||||
* a winning clause in an AND sub-clause will be removed
|
||||
* automatically.
|
||||
* Note that because we use list_difference, any multiple occurrences of a
|
||||
* winning clause in an AND sub-clause will be removed automatically.
|
||||
*/
|
||||
neworlist = NIL;
|
||||
foreach(temp, orlist)
|
||||
@@ -475,10 +474,10 @@ process_duplicate_ors(List *orlist)
|
||||
}
|
||||
|
||||
/*
|
||||
* Append reduced OR to the winners list, if it's not degenerate,
|
||||
* handling the special case of one element correctly (can that really
|
||||
* happen?). Also be careful to maintain AND/OR flatness in case we
|
||||
* pulled up a sub-sub-OR-clause.
|
||||
* Append reduced OR to the winners list, if it's not degenerate, handling
|
||||
* the special case of one element correctly (can that really happen?).
|
||||
* Also be careful to maintain AND/OR flatness in case we pulled up a
|
||||
* sub-sub-OR-clause.
|
||||
*/
|
||||
if (neworlist != NIL)
|
||||
{
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/prep/preptlist.c,v 1.77 2005/06/05 22:32:56 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/prep/preptlist.c,v 1.78 2005/10/15 02:49:21 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -45,10 +45,10 @@ static List *expand_targetlist(List *tlist, int command_type,
|
||||
List *
|
||||
preprocess_targetlist(PlannerInfo *root, List *tlist)
|
||||
{
|
||||
Query *parse = root->parse;
|
||||
int result_relation = parse->resultRelation;
|
||||
List *range_table = parse->rtable;
|
||||
CmdType command_type = parse->commandType;
|
||||
Query *parse = root->parse;
|
||||
int result_relation = parse->resultRelation;
|
||||
List *range_table = parse->rtable;
|
||||
CmdType command_type = parse->commandType;
|
||||
|
||||
/*
|
||||
* Sanity check: if there is a result relation, it'd better be a real
|
||||
@@ -63,20 +63,20 @@ preprocess_targetlist(PlannerInfo *root, List *tlist)
|
||||
}
|
||||
|
||||
/*
|
||||
* for heap_formtuple to work, the targetlist must match the exact
|
||||
* order of the attributes. We also need to fill in any missing
|
||||
* attributes. -ay 10/94
|
||||
* for heap_formtuple to work, the targetlist must match the exact order
|
||||
* of the attributes. We also need to fill in any missing attributes.
|
||||
* -ay 10/94
|
||||
*/
|
||||
if (command_type == CMD_INSERT || command_type == CMD_UPDATE)
|
||||
tlist = expand_targetlist(tlist, command_type,
|
||||
result_relation, range_table);
|
||||
|
||||
/*
|
||||
* for "update" and "delete" queries, add ctid of the result relation
|
||||
* into the target list so that the ctid will propagate through
|
||||
* execution and ExecutePlan() will be able to identify the right
|
||||
* tuple to replace or delete. This extra field is marked "junk" so
|
||||
* that it is not stored back into the tuple.
|
||||
* for "update" and "delete" queries, add ctid of the result relation into
|
||||
* the target list so that the ctid will propagate through execution and
|
||||
* ExecutePlan() will be able to identify the right tuple to replace or
|
||||
* delete. This extra field is marked "junk" so that it is not stored
|
||||
* back into the tuple.
|
||||
*/
|
||||
if (command_type == CMD_UPDATE || command_type == CMD_DELETE)
|
||||
{
|
||||
@@ -92,9 +92,9 @@ preprocess_targetlist(PlannerInfo *root, List *tlist)
|
||||
true);
|
||||
|
||||
/*
|
||||
* For an UPDATE, expand_targetlist already created a fresh tlist.
|
||||
* For DELETE, better do a listCopy so that we don't destructively
|
||||
* modify the original tlist (is this really necessary?).
|
||||
* For an UPDATE, expand_targetlist already created a fresh tlist. For
|
||||
* DELETE, better do a listCopy so that we don't destructively modify
|
||||
* the original tlist (is this really necessary?).
|
||||
*/
|
||||
if (command_type == CMD_DELETE)
|
||||
tlist = list_copy(tlist);
|
||||
@@ -103,31 +103,28 @@ preprocess_targetlist(PlannerInfo *root, List *tlist)
|
||||
}
|
||||
|
||||
/*
|
||||
* Add TID targets for rels selected FOR UPDATE/SHARE. The executor
|
||||
* uses the TID to know which rows to lock, much as for UPDATE or
|
||||
* DELETE.
|
||||
* Add TID targets for rels selected FOR UPDATE/SHARE. The executor uses
|
||||
* the TID to know which rows to lock, much as for UPDATE or DELETE.
|
||||
*/
|
||||
if (parse->rowMarks)
|
||||
{
|
||||
ListCell *l;
|
||||
|
||||
/*
|
||||
* We've got trouble if the FOR UPDATE/SHARE appears inside
|
||||
* grouping, since grouping renders a reference to individual
|
||||
* tuple CTIDs invalid. This is also checked at parse time,
|
||||
* but that's insufficient because of rule substitution, query
|
||||
* pullup, etc.
|
||||
* We've got trouble if the FOR UPDATE/SHARE appears inside grouping,
|
||||
* since grouping renders a reference to individual tuple CTIDs
|
||||
* invalid. This is also checked at parse time, but that's
|
||||
* insufficient because of rule substitution, query pullup, etc.
|
||||
*/
|
||||
CheckSelectLocking(parse, parse->forUpdate);
|
||||
|
||||
/*
|
||||
* Currently the executor only supports FOR UPDATE/SHARE at top
|
||||
* level
|
||||
* Currently the executor only supports FOR UPDATE/SHARE at top level
|
||||
*/
|
||||
if (PlannerQueryLevel > 1)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("SELECT FOR UPDATE/SHARE is not allowed in subqueries")));
|
||||
errmsg("SELECT FOR UPDATE/SHARE is not allowed in subqueries")));
|
||||
|
||||
foreach(l, parse->rowMarks)
|
||||
{
|
||||
@@ -185,14 +182,13 @@ expand_targetlist(List *tlist, int command_type,
|
||||
tlist_item = list_head(tlist);
|
||||
|
||||
/*
|
||||
* The rewriter should have already ensured that the TLEs are in
|
||||
* correct order; but we have to insert TLEs for any missing
|
||||
* attributes.
|
||||
* The rewriter should have already ensured that the TLEs are in correct
|
||||
* order; but we have to insert TLEs for any missing attributes.
|
||||
*
|
||||
* Scan the tuple description in the relation's relcache entry to make
|
||||
* sure we have all the user attributes in the right order. We assume
|
||||
* that the rewriter already acquired at least AccessShareLock on the
|
||||
* relation, so we need no lock here.
|
||||
* Scan the tuple description in the relation's relcache entry to make sure
|
||||
* we have all the user attributes in the right order. We assume that the
|
||||
* rewriter already acquired at least AccessShareLock on the relation, so
|
||||
* we need no lock here.
|
||||
*/
|
||||
rel = heap_open(getrelid(result_relation, range_table), NoLock);
|
||||
|
||||
@@ -220,23 +216,22 @@ expand_targetlist(List *tlist, int command_type,
|
||||
* Didn't find a matching tlist entry, so make one.
|
||||
*
|
||||
* For INSERT, generate a NULL constant. (We assume the rewriter
|
||||
* would have inserted any available default value.) Also, if
|
||||
* the column isn't dropped, apply any domain constraints that
|
||||
* might exist --- this is to catch domain NOT NULL.
|
||||
* would have inserted any available default value.) Also, if the
|
||||
* column isn't dropped, apply any domain constraints that might
|
||||
* exist --- this is to catch domain NOT NULL.
|
||||
*
|
||||
* For UPDATE, generate a Var reference to the existing value of
|
||||
* the attribute, so that it gets copied to the new tuple. But
|
||||
* generate a NULL for dropped columns (we want to drop any
|
||||
* old values).
|
||||
* For UPDATE, generate a Var reference to the existing value of the
|
||||
* attribute, so that it gets copied to the new tuple. But
|
||||
* generate a NULL for dropped columns (we want to drop any old
|
||||
* values).
|
||||
*
|
||||
* When generating a NULL constant for a dropped column, we label
|
||||
* it INT4 (any other guaranteed-to-exist datatype would do as
|
||||
* well). We can't label it with the dropped column's
|
||||
* datatype since that might not exist anymore. It does not
|
||||
* really matter what we claim the type is, since NULL is NULL
|
||||
* --- its representation is datatype-independent. This could
|
||||
* perhaps confuse code comparing the finished plan to the
|
||||
* target relation, however.
|
||||
* When generating a NULL constant for a dropped column, we label it
|
||||
* INT4 (any other guaranteed-to-exist datatype would do as well).
|
||||
* We can't label it with the dropped column's datatype since that
|
||||
* might not exist anymore. It does not really matter what we
|
||||
* claim the type is, since NULL is NULL --- its representation is
|
||||
* datatype-independent. This could perhaps confuse code
|
||||
* comparing the finished plan to the target relation, however.
|
||||
*/
|
||||
Oid atttype = att_tup->atttypid;
|
||||
int32 atttypmod = att_tup->atttypmod;
|
||||
@@ -305,12 +300,12 @@ expand_targetlist(List *tlist, int command_type,
|
||||
}
|
||||
|
||||
/*
|
||||
* The remaining tlist entries should be resjunk; append them all to
|
||||
* the end of the new tlist, making sure they have resnos higher than
|
||||
* the last real attribute. (Note: although the rewriter already did
|
||||
* such renumbering, we have to do it again here in case we are doing
|
||||
* an UPDATE in a table with dropped columns, or an inheritance child
|
||||
* table with extra columns.)
|
||||
* The remaining tlist entries should be resjunk; append them all to the
|
||||
* end of the new tlist, making sure they have resnos higher than the last
|
||||
* real attribute. (Note: although the rewriter already did such
|
||||
* renumbering, we have to do it again here in case we are doing an UPDATE
|
||||
* in a table with dropped columns, or an inheritance child table with
|
||||
* extra columns.)
|
||||
*/
|
||||
while (tlist_item)
|
||||
{
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/prep/prepunion.c,v 1.126 2005/08/02 20:27:45 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/prep/prepunion.c,v 1.127 2005/10/15 02:49:21 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -51,19 +51,19 @@ typedef struct
|
||||
} adjust_inherited_attrs_context;
|
||||
|
||||
static Plan *recurse_set_operations(Node *setOp, PlannerInfo *root,
|
||||
double tuple_fraction,
|
||||
List *colTypes, bool junkOK,
|
||||
int flag, List *refnames_tlist,
|
||||
List **sortClauses);
|
||||
double tuple_fraction,
|
||||
List *colTypes, bool junkOK,
|
||||
int flag, List *refnames_tlist,
|
||||
List **sortClauses);
|
||||
static Plan *generate_union_plan(SetOperationStmt *op, PlannerInfo *root,
|
||||
double tuple_fraction,
|
||||
List *refnames_tlist, List **sortClauses);
|
||||
double tuple_fraction,
|
||||
List *refnames_tlist, List **sortClauses);
|
||||
static Plan *generate_nonunion_plan(SetOperationStmt *op, PlannerInfo *root,
|
||||
List *refnames_tlist, List **sortClauses);
|
||||
static List *recurse_union_children(Node *setOp, PlannerInfo *root,
|
||||
double tuple_fraction,
|
||||
SetOperationStmt *top_union,
|
||||
List *refnames_tlist);
|
||||
double tuple_fraction,
|
||||
SetOperationStmt *top_union,
|
||||
List *refnames_tlist);
|
||||
static List *generate_setop_tlist(List *colTypes, int flag,
|
||||
Index varno,
|
||||
bool hack_constants,
|
||||
@@ -117,8 +117,8 @@ plan_set_operations(PlannerInfo *root, double tuple_fraction,
|
||||
Assert(parse->distinctClause == NIL);
|
||||
|
||||
/*
|
||||
* Find the leftmost component Query. We need to use its column names
|
||||
* for all generated tlists (else SELECT INTO won't work right).
|
||||
* Find the leftmost component Query. We need to use its column names for
|
||||
* all generated tlists (else SELECT INTO won't work right).
|
||||
*/
|
||||
node = topop->larg;
|
||||
while (node && IsA(node, SetOperationStmt))
|
||||
@@ -129,10 +129,10 @@ plan_set_operations(PlannerInfo *root, double tuple_fraction,
|
||||
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 resjunk working
|
||||
* columns (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 resjunk working columns (we can rely
|
||||
* on upper-level nodes to deal with that).
|
||||
*/
|
||||
return recurse_set_operations((Node *) topop, root, tuple_fraction,
|
||||
topop->colTypes, true, -1,
|
||||
@@ -187,8 +187,8 @@ recurse_set_operations(Node *setOp, PlannerInfo *root,
|
||||
subplan);
|
||||
|
||||
/*
|
||||
* We don't bother to determine the subquery's output ordering
|
||||
* since it won't be reflected in the set-op result anyhow.
|
||||
* We don't bother to determine the subquery's output ordering since
|
||||
* it won't be reflected in the set-op result anyhow.
|
||||
*/
|
||||
*sortClauses = NIL;
|
||||
|
||||
@@ -214,13 +214,13 @@ recurse_set_operations(Node *setOp, PlannerInfo *root,
|
||||
* 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 Vars generated by generate_setop_tlist()
|
||||
* were not exactly equal() to the corresponding tlist entries of
|
||||
* the subplan. However, since the subplan was generated by
|
||||
* generate_union_plan() or generate_nonunion_plan(), and hence
|
||||
* its tlist was generated by generate_append_tlist(), this will
|
||||
* work. We just tell generate_setop_tlist() to use varno 0.
|
||||
* replace_vars_with_subplan_refs() to the Result node's tlist. This
|
||||
* would fail if the Vars generated by generate_setop_tlist() were not
|
||||
* exactly equal() to the corresponding tlist entries of the subplan.
|
||||
* However, since the subplan was generated by generate_union_plan()
|
||||
* or generate_nonunion_plan(), and hence its tlist was generated by
|
||||
* generate_append_tlist(), this will work. We just tell
|
||||
* generate_setop_tlist() to use varno 0.
|
||||
*/
|
||||
if (flag >= 0 ||
|
||||
!tlist_same_datatypes(plan->targetlist, colTypes, junkOK))
|
||||
@@ -260,22 +260,22 @@ generate_union_plan(SetOperationStmt *op, PlannerInfo *root,
|
||||
/*
|
||||
* If plain UNION, tell children to fetch all tuples.
|
||||
*
|
||||
* Note: in UNION ALL, we pass the top-level tuple_fraction unmodified
|
||||
* to each arm of the UNION ALL. One could make a case for reducing
|
||||
* the tuple fraction for later arms (discounting by the expected size
|
||||
* of the earlier arms' results) but it seems not worth the trouble.
|
||||
* The normal case where tuple_fraction isn't already zero is a LIMIT
|
||||
* at top level, and passing it down as-is is usually enough to get the
|
||||
* desired result of preferring fast-start plans.
|
||||
* Note: in UNION ALL, we pass the top-level tuple_fraction unmodified to
|
||||
* each arm of the UNION ALL. One could make a case for reducing the
|
||||
* tuple fraction for later arms (discounting by the expected size of the
|
||||
* earlier arms' results) but it seems not worth the trouble. The normal
|
||||
* case where tuple_fraction isn't already zero is a LIMIT at top level,
|
||||
* and passing it down as-is is usually enough to get the desired result
|
||||
* of preferring fast-start plans.
|
||||
*/
|
||||
if (!op->all)
|
||||
tuple_fraction = 0.0;
|
||||
|
||||
/*
|
||||
* If any of my children are identical UNION nodes (same op, all-flag,
|
||||
* and colTypes) then they can be merged into this node so that we
|
||||
* generate only one Append and Sort for the lot. Recurse to find
|
||||
* such nodes and compute their children's plans.
|
||||
* If any of my children are identical UNION nodes (same op, all-flag, and
|
||||
* colTypes) then they can be merged into this node so that we generate
|
||||
* only one Append and Sort for the lot. Recurse to find such nodes and
|
||||
* compute their children's plans.
|
||||
*/
|
||||
planlist = list_concat(recurse_union_children(op->larg, root,
|
||||
tuple_fraction,
|
||||
@@ -288,8 +288,8 @@ generate_union_plan(SetOperationStmt *op, PlannerInfo *root,
|
||||
* Generate tlist for Append plan node.
|
||||
*
|
||||
* 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.
|
||||
* concerned, but we must make it look real anyway for the benefit of the
|
||||
* next plan level up.
|
||||
*/
|
||||
tlist = generate_append_tlist(op->colTypes, false,
|
||||
planlist, refnames_tlist);
|
||||
@@ -300,8 +300,8 @@ generate_union_plan(SetOperationStmt *op, PlannerInfo *root,
|
||||
plan = (Plan *) make_append(planlist, false, 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)
|
||||
{
|
||||
@@ -340,12 +340,12 @@ generate_nonunion_plan(SetOperationStmt *op, PlannerInfo *root,
|
||||
|
||||
/* Recurse on children, ensuring their outputs are marked */
|
||||
lplan = recurse_set_operations(op->larg, root,
|
||||
0.0 /* all tuples needed */,
|
||||
0.0 /* all tuples needed */ ,
|
||||
op->colTypes, false, 0,
|
||||
refnames_tlist,
|
||||
&child_sortclauses);
|
||||
rplan = recurse_set_operations(op->rarg, root,
|
||||
0.0 /* all tuples needed */,
|
||||
0.0 /* all tuples needed */ ,
|
||||
op->colTypes, false, 1,
|
||||
refnames_tlist,
|
||||
&child_sortclauses);
|
||||
@@ -355,10 +355,10 @@ generate_nonunion_plan(SetOperationStmt *op, PlannerInfo *root,
|
||||
* Generate tlist for Append plan node.
|
||||
*
|
||||
* 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. In fact, it has to be real enough that the
|
||||
* flag column is shown as a variable not a constant, else setrefs.c
|
||||
* will get confused.
|
||||
* concerned, but we must make it look real anyway for the benefit of the
|
||||
* next plan level up. In fact, it has to be real enough that the flag
|
||||
* column is shown as a variable not a constant, else setrefs.c will get
|
||||
* confused.
|
||||
*/
|
||||
tlist = generate_append_tlist(op->colTypes, true,
|
||||
planlist, refnames_tlist);
|
||||
@@ -439,12 +439,11 @@ recurse_union_children(Node *setOp, PlannerInfo *root,
|
||||
/*
|
||||
* 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 list_make1(recurse_set_operations(setOp, root,
|
||||
tuple_fraction,
|
||||
@@ -492,17 +491,17 @@ generate_setop_tlist(List *colTypes, int flag,
|
||||
Assert(!reftle->resjunk);
|
||||
|
||||
/*
|
||||
* Generate columns referencing input columns and having
|
||||
* appropriate data types and column names. Insert datatype
|
||||
* coercions where necessary.
|
||||
* 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!
|
||||
* 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!
|
||||
*/
|
||||
if (hack_constants && inputtle->expr && IsA(inputtle->expr, Const))
|
||||
expr = (Node *) inputtle->expr;
|
||||
@@ -710,7 +709,7 @@ find_all_inheritors(Oid parentrel)
|
||||
List *rels_list;
|
||||
ListCell *l;
|
||||
|
||||
/*
|
||||
/*
|
||||
* We build a list starting with the given rel and adding all direct and
|
||||
* indirect children. We can use a single list as both the record of
|
||||
* already-found rels and the agenda of rels yet to be scanned for more
|
||||
@@ -728,11 +727,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.)
|
||||
*/
|
||||
rels_list = list_concat_unique_oid(rels_list, currentchildren);
|
||||
}
|
||||
@@ -790,8 +789,8 @@ expand_inherited_rtentry(PlannerInfo *root, Index rti)
|
||||
|
||||
/*
|
||||
* 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.
|
||||
* case. This could happen despite above has_subclass() check, if table
|
||||
* once had a child but no longer does.
|
||||
*/
|
||||
if (list_length(inhOIDs) < 2)
|
||||
{
|
||||
@@ -809,19 +808,19 @@ expand_inherited_rtentry(PlannerInfo *root, Index rti)
|
||||
Index childRTindex;
|
||||
|
||||
/*
|
||||
* It is possible that the parent table has children that are
|
||||
* temp tables of other backends. We cannot safely access such
|
||||
* tables (because of buffering issues), and the best thing to do
|
||||
* seems to be to silently ignore them.
|
||||
* It is possible that the parent table has children that are temp
|
||||
* tables of other backends. We cannot safely access such tables
|
||||
* (because of buffering issues), and the best thing to do seems to be
|
||||
* to silently ignore them.
|
||||
*/
|
||||
if (childOID != parentOID &&
|
||||
isOtherTempNamespace(get_rel_namespace(childOID)))
|
||||
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 OID, and set inh = false.
|
||||
* 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 OID,
|
||||
* and set inh = false.
|
||||
*/
|
||||
childrte = copyObject(rte);
|
||||
childrte->relid = childOID;
|
||||
@@ -833,7 +832,8 @@ expand_inherited_rtentry(PlannerInfo *root, Index rti)
|
||||
|
||||
/*
|
||||
* If all the children were temp tables, pretend it's a non-inheritance
|
||||
* situation. The duplicate RTE we added for the parent table is harmless.
|
||||
* situation. The duplicate RTE we added for the parent table is
|
||||
* harmless.
|
||||
*/
|
||||
if (list_length(inhRTIs) < 2)
|
||||
{
|
||||
@@ -843,11 +843,11 @@ expand_inherited_rtentry(PlannerInfo *root, Index rti)
|
||||
}
|
||||
|
||||
/*
|
||||
* The executor will check the parent table's access permissions when
|
||||
* it examines the parent's inheritlist entry. There's no need to
|
||||
* check twice, so turn off access check bits in the original RTE.
|
||||
* (If we are invoked more than once, extra copies of the child RTEs
|
||||
* will also not cause duplicate permission checks.)
|
||||
* The executor will check the parent table's access permissions when it
|
||||
* examines the parent's inheritlist entry. There's no need to check
|
||||
* twice, so turn off access check bits in the original RTE. (If we are
|
||||
* invoked more than once, extra copies of the child RTEs will also not
|
||||
* cause duplicate permission checks.)
|
||||
*/
|
||||
rte->requiredPerms = 0;
|
||||
|
||||
@@ -882,9 +882,8 @@ adjust_inherited_attrs(Node *node,
|
||||
}
|
||||
|
||||
/*
|
||||
* We assume that by now the planner has acquired at least
|
||||
* AccessShareLock on both rels, and so we need no additional lock
|
||||
* now.
|
||||
* We assume that by now the planner has acquired at least AccessShareLock
|
||||
* on both rels, and so we need no additional lock now.
|
||||
*/
|
||||
oldrelation = heap_open(old_relid, NoLock);
|
||||
newrelation = heap_open(new_relid, NoLock);
|
||||
@@ -1035,7 +1034,7 @@ adjust_inherited_attrs_mutator(Node *node,
|
||||
JoinExpr *j;
|
||||
|
||||
j = (JoinExpr *) expression_tree_mutator(node,
|
||||
adjust_inherited_attrs_mutator,
|
||||
adjust_inherited_attrs_mutator,
|
||||
(void *) context);
|
||||
/* now fix JoinExpr's rtindex */
|
||||
if (j->rtindex == context->old_rt_index)
|
||||
@@ -1048,8 +1047,8 @@ adjust_inherited_attrs_mutator(Node *node,
|
||||
InClauseInfo *ininfo;
|
||||
|
||||
ininfo = (InClauseInfo *) expression_tree_mutator(node,
|
||||
adjust_inherited_attrs_mutator,
|
||||
(void *) context);
|
||||
adjust_inherited_attrs_mutator,
|
||||
(void *) context);
|
||||
/* now fix InClauseInfo's relid sets */
|
||||
ininfo->lefthand = adjust_relid_set(ininfo->lefthand,
|
||||
context->old_rt_index,
|
||||
@@ -1119,10 +1118,10 @@ adjust_inherited_attrs_mutator(Node *node,
|
||||
/*
|
||||
* BUT: although we don't need to recurse into subplans, we do need to
|
||||
* make sure that they are copied, not just referenced as
|
||||
* expression_tree_mutator will do by default. Otherwise we'll have
|
||||
* the same subplan node referenced from each arm of the inheritance
|
||||
* APPEND plan, which will cause trouble in the executor. This is a
|
||||
* kluge that should go away when we redesign querytrees.
|
||||
* expression_tree_mutator will do by default. Otherwise we'll have the
|
||||
* same subplan node referenced from each arm of the inheritance APPEND
|
||||
* plan, which will cause trouble in the executor. This is a kluge that
|
||||
* should go away when we redesign querytrees.
|
||||
*/
|
||||
if (is_subplan(node))
|
||||
{
|
||||
@@ -1205,8 +1204,8 @@ adjust_inherited_tlist(List *tlist,
|
||||
/*
|
||||
* If we changed anything, re-sort the tlist by resno, and make sure
|
||||
* resjunk entries have resnos above the last real resno. The sort
|
||||
* algorithm is a bit stupid, but for such a seldom-taken path, small
|
||||
* is probably better than fast.
|
||||
* algorithm is a bit stupid, but for such a seldom-taken path, small is
|
||||
* probably better than fast.
|
||||
*/
|
||||
if (!changed_it)
|
||||
return tlist;
|
||||
|
||||
Reference in New Issue
Block a user