mirror of
https://github.com/postgres/postgres.git
synced 2025-07-18 17:42:25 +03:00
pgindent run before PG 9.1 beta 1.
This commit is contained in:
@ -66,7 +66,7 @@ static void set_cte_pathlist(PlannerInfo *root, RelOptInfo *rel,
|
||||
static void set_worktable_pathlist(PlannerInfo *root, RelOptInfo *rel,
|
||||
RangeTblEntry *rte);
|
||||
static void set_foreign_pathlist(PlannerInfo *root, RelOptInfo *rel,
|
||||
RangeTblEntry *rte);
|
||||
RangeTblEntry *rte);
|
||||
static RelOptInfo *make_rel_from_joinlist(PlannerInfo *root, List *joinlist);
|
||||
static bool subquery_is_pushdown_safe(Query *subquery, Query *topquery,
|
||||
bool *differentTypes);
|
||||
@ -413,11 +413,11 @@ set_append_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
|
||||
|
||||
/*
|
||||
* We have to make child entries in the EquivalenceClass data
|
||||
* structures as well. This is needed either if the parent
|
||||
* participates in some eclass joins (because we will want to
|
||||
* consider inner-indexscan joins on the individual children)
|
||||
* or if the parent has useful pathkeys (because we should try
|
||||
* to build MergeAppend paths that produce those sort orderings).
|
||||
* structures as well. This is needed either if the parent
|
||||
* participates in some eclass joins (because we will want to consider
|
||||
* inner-indexscan joins on the individual children) or if the parent
|
||||
* has useful pathkeys (because we should try to build MergeAppend
|
||||
* paths that produce those sort orderings).
|
||||
*/
|
||||
if (rel->has_eclass_joins || has_useful_pathkeys(root, rel))
|
||||
add_child_rel_equivalences(root, appinfo, rel, childrel);
|
||||
@ -462,7 +462,7 @@ set_append_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
|
||||
/* Have we already seen this ordering? */
|
||||
foreach(lpk, all_child_pathkeys)
|
||||
{
|
||||
List *existing_pathkeys = (List *) lfirst(lpk);
|
||||
List *existing_pathkeys = (List *) lfirst(lpk);
|
||||
|
||||
if (compare_pathkeys(existing_pathkeys,
|
||||
childkeys) == PATHKEYS_EQUAL)
|
||||
@ -540,18 +540,18 @@ set_append_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
|
||||
|
||||
/*
|
||||
* Next, build MergeAppend paths based on the collected list of child
|
||||
* pathkeys. We consider both cheapest-startup and cheapest-total
|
||||
* cases, ie, for each interesting ordering, collect all the cheapest
|
||||
* startup subpaths and all the cheapest total paths, and build a
|
||||
* MergeAppend path for each list.
|
||||
* pathkeys. We consider both cheapest-startup and cheapest-total cases,
|
||||
* ie, for each interesting ordering, collect all the cheapest startup
|
||||
* subpaths and all the cheapest total paths, and build a MergeAppend path
|
||||
* for each list.
|
||||
*/
|
||||
foreach(l, all_child_pathkeys)
|
||||
{
|
||||
List *pathkeys = (List *) lfirst(l);
|
||||
List *startup_subpaths = NIL;
|
||||
List *total_subpaths = NIL;
|
||||
bool startup_neq_total = false;
|
||||
ListCell *lcr;
|
||||
List *pathkeys = (List *) lfirst(l);
|
||||
List *startup_subpaths = NIL;
|
||||
List *total_subpaths = NIL;
|
||||
bool startup_neq_total = false;
|
||||
ListCell *lcr;
|
||||
|
||||
/* Select the child paths for this ordering... */
|
||||
foreach(lcr, live_childrels)
|
||||
@ -581,8 +581,8 @@ set_append_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
|
||||
|
||||
/*
|
||||
* Notice whether we actually have different paths for the
|
||||
* "cheapest" and "total" cases; frequently there will be no
|
||||
* point in two create_merge_append_path() calls.
|
||||
* "cheapest" and "total" cases; frequently there will be no point
|
||||
* in two create_merge_append_path() calls.
|
||||
*/
|
||||
if (cheapest_startup != cheapest_total)
|
||||
startup_neq_total = true;
|
||||
@ -623,7 +623,7 @@ accumulate_append_subpath(List *subpaths, Path *path)
|
||||
{
|
||||
if (IsA(path, AppendPath))
|
||||
{
|
||||
AppendPath *apath = (AppendPath *) path;
|
||||
AppendPath *apath = (AppendPath *) path;
|
||||
|
||||
/* list_copy is important here to avoid sharing list substructure */
|
||||
return list_concat(subpaths, list_copy(apath->subpaths));
|
||||
|
@ -1096,7 +1096,7 @@ cost_recursive_union(Plan *runion, Plan *nrterm, Plan *rterm)
|
||||
* accesses (XXX can't we refine that guess?)
|
||||
*
|
||||
* By default, we charge two operator evals per tuple comparison, which should
|
||||
* be in the right ballpark in most cases. The caller can tweak this by
|
||||
* be in the right ballpark in most cases. The caller can tweak this by
|
||||
* specifying nonzero comparison_cost; typically that's used for any extra
|
||||
* work that has to be done to prepare the inputs to the comparison operators.
|
||||
*
|
||||
@ -1218,7 +1218,7 @@ cost_sort(Path *path, PlannerInfo *root,
|
||||
* Determines and returns the cost of a MergeAppend node.
|
||||
*
|
||||
* MergeAppend merges several pre-sorted input streams, using a heap that
|
||||
* at any given instant holds the next tuple from each stream. If there
|
||||
* at any given instant holds the next tuple from each stream. If there
|
||||
* are N streams, we need about N*log2(N) tuple comparisons to construct
|
||||
* the heap at startup, and then for each output tuple, about log2(N)
|
||||
* comparisons to delete the top heap entry and another log2(N) comparisons
|
||||
@ -2909,7 +2909,7 @@ adjust_semi_join(PlannerInfo *root, JoinPath *path, SpecialJoinInfo *sjinfo,
|
||||
List *nrclauses;
|
||||
|
||||
nrclauses = select_nonredundant_join_clauses(root,
|
||||
path->joinrestrictinfo,
|
||||
path->joinrestrictinfo,
|
||||
path->innerjoinpath);
|
||||
*indexed_join_quals = (nrclauses == NIL);
|
||||
}
|
||||
@ -3185,7 +3185,7 @@ set_subquery_size_estimates(PlannerInfo *root, RelOptInfo *rel,
|
||||
|
||||
/*
|
||||
* Compute per-output-column width estimates by examining the subquery's
|
||||
* targetlist. For any output that is a plain Var, get the width estimate
|
||||
* targetlist. For any output that is a plain Var, get the width estimate
|
||||
* that was made while planning the subquery. Otherwise, fall back on a
|
||||
* datatype-based estimate.
|
||||
*/
|
||||
@ -3210,7 +3210,7 @@ set_subquery_size_estimates(PlannerInfo *root, RelOptInfo *rel,
|
||||
if (IsA(texpr, Var) &&
|
||||
subroot->parse->setOperations == NULL)
|
||||
{
|
||||
Var *var = (Var *) texpr;
|
||||
Var *var = (Var *) texpr;
|
||||
RelOptInfo *subrel = find_base_rel(subroot, var->varno);
|
||||
|
||||
item_width = subrel->attr_widths[var->varattno - subrel->min_attr];
|
||||
@ -3332,7 +3332,7 @@ set_cte_size_estimates(PlannerInfo *root, RelOptInfo *rel, Plan *cteplan)
|
||||
* of estimating baserestrictcost, so we set that, and we also set up width
|
||||
* using what will be purely datatype-driven estimates from the targetlist.
|
||||
* There is no way to do anything sane with the rows value, so we just put
|
||||
* a default estimate and hope that the wrapper can improve on it. The
|
||||
* a default estimate and hope that the wrapper can improve on it. The
|
||||
* wrapper's PlanForeignScan function will be called momentarily.
|
||||
*
|
||||
* The rel's targetlist and restrictinfo list must have been constructed
|
||||
@ -3396,8 +3396,8 @@ set_rel_width(PlannerInfo *root, RelOptInfo *rel)
|
||||
ndx = var->varattno - rel->min_attr;
|
||||
|
||||
/*
|
||||
* If it's a whole-row Var, we'll deal with it below after we
|
||||
* have already cached as many attr widths as possible.
|
||||
* If it's a whole-row Var, we'll deal with it below after we have
|
||||
* already cached as many attr widths as possible.
|
||||
*/
|
||||
if (var->varattno == 0)
|
||||
{
|
||||
@ -3406,8 +3406,8 @@ set_rel_width(PlannerInfo *root, RelOptInfo *rel)
|
||||
}
|
||||
|
||||
/*
|
||||
* The width may have been cached already (especially if it's
|
||||
* a subquery), so don't duplicate effort.
|
||||
* The width may have been cached already (especially if it's a
|
||||
* subquery), so don't duplicate effort.
|
||||
*/
|
||||
if (rel->attr_widths[ndx] > 0)
|
||||
{
|
||||
@ -3464,13 +3464,13 @@ set_rel_width(PlannerInfo *root, RelOptInfo *rel)
|
||||
*/
|
||||
if (have_wholerow_var)
|
||||
{
|
||||
int32 wholerow_width = sizeof(HeapTupleHeaderData);
|
||||
int32 wholerow_width = sizeof(HeapTupleHeaderData);
|
||||
|
||||
if (reloid != InvalidOid)
|
||||
{
|
||||
/* Real relation, so estimate true tuple width */
|
||||
wholerow_width += get_relation_data_width(reloid,
|
||||
rel->attr_widths - rel->min_attr);
|
||||
rel->attr_widths - rel->min_attr);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -3484,8 +3484,8 @@ set_rel_width(PlannerInfo *root, RelOptInfo *rel)
|
||||
rel->attr_widths[0 - rel->min_attr] = wholerow_width;
|
||||
|
||||
/*
|
||||
* Include the whole-row Var as part of the output tuple. Yes,
|
||||
* that really is what happens at runtime.
|
||||
* Include the whole-row Var as part of the output tuple. Yes, that
|
||||
* really is what happens at runtime.
|
||||
*/
|
||||
tuple_width += wholerow_width;
|
||||
}
|
||||
|
@ -385,7 +385,7 @@ process_equivalence(PlannerInfo *root, RestrictInfo *restrictinfo,
|
||||
* Also, the expression's exposed collation must match the EC's collation.
|
||||
* This is important because in comparisons like "foo < bar COLLATE baz",
|
||||
* only one of the expressions has the correct exposed collation as we receive
|
||||
* it from the parser. Forcing both of them to have it ensures that all
|
||||
* it from the parser. Forcing both of them to have it ensures that all
|
||||
* variant spellings of such a construct behave the same. Again, we can
|
||||
* stick on a RelabelType to force the right exposed collation. (It might
|
||||
* work to not label the collation at all in EC members, but this is risky
|
||||
@ -414,13 +414,13 @@ canonicalize_ec_expression(Expr *expr, Oid req_type, Oid req_collation)
|
||||
exprCollation((Node *) expr) != req_collation)
|
||||
{
|
||||
/*
|
||||
* Strip any existing RelabelType, then add a new one if needed.
|
||||
* This is to preserve the invariant of no redundant RelabelTypes.
|
||||
* Strip any existing RelabelType, then add a new one if needed. This
|
||||
* is to preserve the invariant of no redundant RelabelTypes.
|
||||
*
|
||||
* If we have to change the exposed type of the stripped expression,
|
||||
* set typmod to -1 (since the new type may not have the same typmod
|
||||
* interpretation). If we only have to change collation, preserve
|
||||
* the exposed typmod.
|
||||
* interpretation). If we only have to change collation, preserve the
|
||||
* exposed typmod.
|
||||
*/
|
||||
while (expr && IsA(expr, RelabelType))
|
||||
expr = (Expr *) ((RelabelType *) expr)->arg;
|
||||
@ -1784,8 +1784,8 @@ add_child_rel_equivalences(PlannerInfo *root,
|
||||
ListCell *lc2;
|
||||
|
||||
/*
|
||||
* If this EC contains a constant, then it's not useful for sorting
|
||||
* or driving an inner index-scan, so we skip generating child EMs.
|
||||
* If this EC contains a constant, then it's not useful for sorting or
|
||||
* driving an inner index-scan, so we skip generating child EMs.
|
||||
*
|
||||
* If this EC contains a volatile expression, then generating child
|
||||
* EMs would be downright dangerous. We rely on a volatile EC having
|
||||
|
@ -119,7 +119,7 @@ static bool match_special_index_operator(Expr *clause,
|
||||
static Expr *expand_boolean_index_clause(Node *clause, int indexcol,
|
||||
IndexOptInfo *index);
|
||||
static List *expand_indexqual_opclause(RestrictInfo *rinfo,
|
||||
Oid opfamily, Oid idxcollation);
|
||||
Oid opfamily, Oid idxcollation);
|
||||
static RestrictInfo *expand_indexqual_rowcompare(RestrictInfo *rinfo,
|
||||
IndexOptInfo *index,
|
||||
int indexcol);
|
||||
@ -1159,8 +1159,8 @@ group_clauses_by_indexkey(IndexOptInfo *index,
|
||||
* (2) must contain an operator which is in the same family as the index
|
||||
* operator for this column, or is a "special" operator as recognized
|
||||
* by match_special_index_operator();
|
||||
* and
|
||||
* (3) must match the collation of the index, if collation is relevant.
|
||||
* and
|
||||
* (3) must match the collation of the index, if collation is relevant.
|
||||
*
|
||||
* Our definition of "const" is pretty liberal: we allow Vars belonging
|
||||
* to the caller-specified outer_relids relations (which had better not
|
||||
@ -1312,7 +1312,7 @@ match_clause_to_indexcol(IndexOptInfo *index,
|
||||
* is a "special" indexable operator.
|
||||
*/
|
||||
if (plain_op &&
|
||||
match_special_index_operator(clause, opfamily, idxcollation, true))
|
||||
match_special_index_operator(clause, opfamily, idxcollation, true))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
@ -1438,7 +1438,7 @@ match_rowcompare_to_indexcol(IndexOptInfo *index,
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* ---- ROUTINES TO CHECK ORDERING OPERATORS ----
|
||||
* ---- ROUTINES TO CHECK ORDERING OPERATORS ----
|
||||
****************************************************************************/
|
||||
|
||||
/*
|
||||
@ -1461,7 +1461,7 @@ match_index_to_pathkeys(IndexOptInfo *index, List *pathkeys)
|
||||
|
||||
foreach(lc1, pathkeys)
|
||||
{
|
||||
PathKey *pathkey = (PathKey *) lfirst(lc1);
|
||||
PathKey *pathkey = (PathKey *) lfirst(lc1);
|
||||
bool found = false;
|
||||
ListCell *lc2;
|
||||
|
||||
@ -1483,7 +1483,7 @@ match_index_to_pathkeys(IndexOptInfo *index, List *pathkeys)
|
||||
foreach(lc2, pathkey->pk_eclass->ec_members)
|
||||
{
|
||||
EquivalenceMember *member = (EquivalenceMember *) lfirst(lc2);
|
||||
int indexcol;
|
||||
int indexcol;
|
||||
|
||||
/* No possibility of match if it references other relations */
|
||||
if (!bms_equal(member->em_relids, index->rel->relids))
|
||||
@ -1491,7 +1491,7 @@ match_index_to_pathkeys(IndexOptInfo *index, List *pathkeys)
|
||||
|
||||
for (indexcol = 0; indexcol < index->ncolumns; indexcol++)
|
||||
{
|
||||
Expr *expr;
|
||||
Expr *expr;
|
||||
|
||||
expr = match_clause_to_ordering_op(index,
|
||||
indexcol,
|
||||
@ -1535,7 +1535,7 @@ match_index_to_pathkeys(IndexOptInfo *index, List *pathkeys)
|
||||
* Note that we currently do not consider the collation of the ordering
|
||||
* operator's result. In practical cases the result type will be numeric
|
||||
* and thus have no collation, and it's not very clear what to match to
|
||||
* if it did have a collation. The index's collation should match the
|
||||
* if it did have a collation. The index's collation should match the
|
||||
* ordering operator's input collation, not its result.
|
||||
*
|
||||
* If successful, return 'clause' as-is if the indexkey is on the left,
|
||||
@ -1598,8 +1598,8 @@ match_clause_to_ordering_op(IndexOptInfo *index,
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* Is the (commuted) operator an ordering operator for the opfamily?
|
||||
* And if so, does it yield the right sorting semantics?
|
||||
* Is the (commuted) operator an ordering operator for the opfamily? And
|
||||
* if so, does it yield the right sorting semantics?
|
||||
*/
|
||||
sortfamily = get_op_opfamily_sortfamily(expr_op, opfamily);
|
||||
if (sortfamily != pk_opfamily)
|
||||
@ -2198,9 +2198,9 @@ relation_has_unique_index_for(PlannerInfo *root, RelOptInfo *rel,
|
||||
continue;
|
||||
|
||||
/*
|
||||
* XXX at some point we may need to check collations here
|
||||
* too. For the moment we assume all collations reduce to
|
||||
* the same notion of equality.
|
||||
* XXX at some point we may need to check collations here too.
|
||||
* For the moment we assume all collations reduce to the same
|
||||
* notion of equality.
|
||||
*/
|
||||
|
||||
/* OK, see if the condition operand matches the index key */
|
||||
@ -2544,10 +2544,10 @@ match_special_index_operator(Expr *clause, Oid opfamily, Oid idxcollation,
|
||||
*
|
||||
* The non-pattern opclasses will not sort the way we need in most non-C
|
||||
* locales. We can use such an index anyway for an exact match (simple
|
||||
* equality), but not for prefix-match cases. Note that we are looking
|
||||
* at the index's collation, not the expression's collation -- this test
|
||||
* is not dependent on the LIKE/regex operator's collation (which would
|
||||
* only affect case folding behavior of ILIKE, anyway).
|
||||
* equality), but not for prefix-match cases. Note that we are looking at
|
||||
* the index's collation, not the expression's collation -- this test is
|
||||
* not dependent on the LIKE/regex operator's collation (which would only
|
||||
* affect case folding behavior of ILIKE, anyway).
|
||||
*/
|
||||
switch (expr_op)
|
||||
{
|
||||
@ -2657,7 +2657,7 @@ expand_indexqual_conditions(IndexOptInfo *index, List *clausegroups)
|
||||
resultquals = list_concat(resultquals,
|
||||
expand_indexqual_opclause(rinfo,
|
||||
curFamily,
|
||||
curCollation));
|
||||
curCollation));
|
||||
}
|
||||
else if (IsA(clause, ScalarArrayOpExpr))
|
||||
{
|
||||
@ -3254,7 +3254,7 @@ network_prefix_quals(Node *leftop, Oid expr_op, Oid opfamily, Datum rightop)
|
||||
expr = make_opclause(opr1oid, BOOLOID, false,
|
||||
(Expr *) leftop,
|
||||
(Expr *) makeConst(datatype, -1,
|
||||
InvalidOid, /* not collatable */
|
||||
InvalidOid, /* not collatable */
|
||||
-1, opr1right,
|
||||
false, false),
|
||||
InvalidOid, InvalidOid);
|
||||
@ -3272,7 +3272,7 @@ network_prefix_quals(Node *leftop, Oid expr_op, Oid opfamily, Datum rightop)
|
||||
expr = make_opclause(opr2oid, BOOLOID, false,
|
||||
(Expr *) leftop,
|
||||
(Expr *) makeConst(datatype, -1,
|
||||
InvalidOid, /* not collatable */
|
||||
InvalidOid, /* not collatable */
|
||||
-1, opr2right,
|
||||
false, false),
|
||||
InvalidOid, InvalidOid);
|
||||
|
@ -97,11 +97,11 @@ add_paths_to_joinrel(PlannerInfo *root,
|
||||
|
||||
/*
|
||||
* 1. Consider mergejoin paths where both relations must be explicitly
|
||||
* sorted. Skip this if we can't mergejoin.
|
||||
* sorted. Skip this if we can't mergejoin.
|
||||
*/
|
||||
if (mergejoin_allowed)
|
||||
sort_inner_and_outer(root, joinrel, outerrel, innerrel,
|
||||
restrictlist, mergeclause_list, jointype, sjinfo);
|
||||
restrictlist, mergeclause_list, jointype, sjinfo);
|
||||
|
||||
/*
|
||||
* 2. Consider paths where the outer relation need not be explicitly
|
||||
@ -112,7 +112,7 @@ add_paths_to_joinrel(PlannerInfo *root,
|
||||
*/
|
||||
if (mergejoin_allowed)
|
||||
match_unsorted_outer(root, joinrel, outerrel, innerrel,
|
||||
restrictlist, mergeclause_list, jointype, sjinfo);
|
||||
restrictlist, mergeclause_list, jointype, sjinfo);
|
||||
|
||||
#ifdef NOT_USED
|
||||
|
||||
@ -129,7 +129,7 @@ add_paths_to_joinrel(PlannerInfo *root,
|
||||
*/
|
||||
if (mergejoin_allowed)
|
||||
match_unsorted_inner(root, joinrel, outerrel, innerrel,
|
||||
restrictlist, mergeclause_list, jointype, sjinfo);
|
||||
restrictlist, mergeclause_list, jointype, sjinfo);
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -30,7 +30,7 @@ static bool has_legal_joinclause(PlannerInfo *root, RelOptInfo *rel);
|
||||
static bool is_dummy_rel(RelOptInfo *rel);
|
||||
static void mark_dummy_rel(RelOptInfo *rel);
|
||||
static bool restriction_is_constant_false(List *restrictlist,
|
||||
bool only_pushed_down);
|
||||
bool only_pushed_down);
|
||||
|
||||
|
||||
/*
|
||||
@ -604,10 +604,10 @@ make_join_rel(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2)
|
||||
*
|
||||
* Also, a provably constant-false join restriction typically means that
|
||||
* we can skip evaluating one or both sides of the join. We do this by
|
||||
* marking the appropriate rel as dummy. For outer joins, a constant-false
|
||||
* restriction that is pushed down still means the whole join is dummy,
|
||||
* while a non-pushed-down one means that no inner rows will join so we
|
||||
* can treat the inner rel as dummy.
|
||||
* marking the appropriate rel as dummy. For outer joins, a
|
||||
* constant-false restriction that is pushed down still means the whole
|
||||
* join is dummy, while a non-pushed-down one means that no inner rows
|
||||
* will join so we can treat the inner rel as dummy.
|
||||
*
|
||||
* We need only consider the jointypes that appear in join_info_list, plus
|
||||
* JOIN_INNER.
|
||||
|
@ -253,7 +253,7 @@ make_pathkey_from_sortinfo(PlannerInfo *root,
|
||||
/*
|
||||
* EquivalenceClasses need to contain opfamily lists based on the family
|
||||
* membership of mergejoinable equality operators, which could belong to
|
||||
* more than one opfamily. So we have to look up the opfamily's equality
|
||||
* more than one opfamily. So we have to look up the opfamily's equality
|
||||
* operator and get its membership.
|
||||
*/
|
||||
equality_op = get_opfamily_member(opfamily,
|
||||
@ -558,9 +558,9 @@ build_index_pathkeys(PlannerInfo *root,
|
||||
true);
|
||||
|
||||
/*
|
||||
* If the sort key isn't already present in any EquivalenceClass,
|
||||
* then it's not an interesting sort order for this query. So
|
||||
* we can stop now --- lower-order sort keys aren't useful either.
|
||||
* If the sort key isn't already present in any EquivalenceClass, then
|
||||
* it's not an interesting sort order for this query. So we can stop
|
||||
* now --- lower-order sort keys aren't useful either.
|
||||
*/
|
||||
if (!cpathkey)
|
||||
break;
|
||||
@ -747,8 +747,8 @@ convert_subquery_pathkeys(PlannerInfo *root, RelOptInfo *rel,
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Build a representation of this targetlist entry as
|
||||
* an outer Var.
|
||||
* Build a representation of this targetlist entry as an
|
||||
* outer Var.
|
||||
*/
|
||||
outer_expr = (Expr *) makeVarFromTargetEntry(rel->relid,
|
||||
tle);
|
||||
@ -923,7 +923,7 @@ make_pathkeys_for_sortclauses(PlannerInfo *root,
|
||||
* right sides.
|
||||
*
|
||||
* Note this is called before EC merging is complete, so the links won't
|
||||
* necessarily point to canonical ECs. Before they are actually used for
|
||||
* necessarily point to canonical ECs. Before they are actually used for
|
||||
* anything, update_mergeclause_eclasses must be called to ensure that
|
||||
* they've been updated to point to canonical ECs.
|
||||
*/
|
||||
|
@ -31,7 +31,7 @@
|
||||
/* local functions */
|
||||
static bool join_is_removable(PlannerInfo *root, SpecialJoinInfo *sjinfo);
|
||||
static void remove_rel_from_query(PlannerInfo *root, int relid,
|
||||
Relids joinrelids);
|
||||
Relids joinrelids);
|
||||
static List *remove_rel_from_joinlist(List *joinlist, int relid, int *nremoved);
|
||||
|
||||
|
||||
@ -238,10 +238,10 @@ join_is_removable(PlannerInfo *root, SpecialJoinInfo *sjinfo)
|
||||
!bms_equal(restrictinfo->required_relids, joinrelids))
|
||||
{
|
||||
/*
|
||||
* If such a clause actually references the inner rel then
|
||||
* join removal has to be disallowed. We have to check this
|
||||
* despite the previous attr_needed checks because of the
|
||||
* possibility of pushed-down clauses referencing the rel.
|
||||
* If such a clause actually references the inner rel then join
|
||||
* removal has to be disallowed. We have to check this despite
|
||||
* the previous attr_needed checks because of the possibility of
|
||||
* pushed-down clauses referencing the rel.
|
||||
*/
|
||||
if (bms_is_member(innerrelid, restrictinfo->clause_relids))
|
||||
return false;
|
||||
@ -365,8 +365,8 @@ remove_rel_from_query(PlannerInfo *root, int relid, Relids joinrelids)
|
||||
* Likewise remove references from SpecialJoinInfo data structures.
|
||||
*
|
||||
* This is relevant in case the outer join we're deleting is nested inside
|
||||
* other outer joins: the upper joins' relid sets have to be adjusted.
|
||||
* The RHS of the target outer join will be made empty here, but that's OK
|
||||
* other outer joins: the upper joins' relid sets have to be adjusted. The
|
||||
* RHS of the target outer join will be made empty here, but that's OK
|
||||
* since caller will delete that SpecialJoinInfo entirely.
|
||||
*/
|
||||
foreach(l, root->join_info_list)
|
||||
@ -426,6 +426,7 @@ remove_rel_from_query(PlannerInfo *root, int relid, Relids joinrelids)
|
||||
{
|
||||
/* Recheck that qual doesn't actually reference the target rel */
|
||||
Assert(!bms_is_member(relid, rinfo->clause_relids));
|
||||
|
||||
/*
|
||||
* The required_relids probably aren't shared with anything else,
|
||||
* but let's copy them just to be sure.
|
||||
|
@ -108,7 +108,7 @@ static TidScan *make_tidscan(List *qptlist, List *qpqual, Index scanrelid,
|
||||
List *tidquals);
|
||||
static FunctionScan *make_functionscan(List *qptlist, List *qpqual,
|
||||
Index scanrelid, Node *funcexpr, List *funccolnames,
|
||||
List *funccoltypes, List *funccoltypmods, List *funccolcollations);
|
||||
List *funccoltypes, List *funccoltypmods, List *funccolcollations);
|
||||
static ValuesScan *make_valuesscan(List *qptlist, List *qpqual,
|
||||
Index scanrelid, List *values_lists);
|
||||
static CteScan *make_ctescan(List *qptlist, List *qpqual,
|
||||
@ -143,24 +143,25 @@ static MergeJoin *make_mergejoin(List *tlist,
|
||||
bool *mergenullsfirst,
|
||||
Plan *lefttree, Plan *righttree,
|
||||
JoinType jointype);
|
||||
static Sort *make_sort(PlannerInfo *root, Plan *lefttree, int numCols,
|
||||
AttrNumber *sortColIdx, Oid *sortOperators, Oid *collations, bool *nullsFirst,
|
||||
static Sort *
|
||||
make_sort(PlannerInfo *root, Plan *lefttree, int numCols,
|
||||
AttrNumber *sortColIdx, Oid *sortOperators, Oid *collations, bool *nullsFirst,
|
||||
double limit_tuples);
|
||||
static Plan *prepare_sort_from_pathkeys(PlannerInfo *root,
|
||||
Plan *lefttree, List *pathkeys,
|
||||
bool adjust_tlist_in_place,
|
||||
int *p_numsortkeys,
|
||||
AttrNumber **p_sortColIdx,
|
||||
Oid **p_sortOperators,
|
||||
Oid **p_collations,
|
||||
bool **p_nullsFirst);
|
||||
Plan *lefttree, List *pathkeys,
|
||||
bool adjust_tlist_in_place,
|
||||
int *p_numsortkeys,
|
||||
AttrNumber **p_sortColIdx,
|
||||
Oid **p_sortOperators,
|
||||
Oid **p_collations,
|
||||
bool **p_nullsFirst);
|
||||
static Material *make_material(Plan *lefttree);
|
||||
|
||||
|
||||
/*
|
||||
* create_plan
|
||||
* Creates the access plan for a query by recursively processing the
|
||||
* desired tree of pathnodes, starting at the node 'best_path'. For
|
||||
* desired tree of pathnodes, starting at the node 'best_path'. For
|
||||
* every pathnode found, we create a corresponding plan node containing
|
||||
* appropriate id, target list, and qualification information.
|
||||
*
|
||||
@ -737,7 +738,7 @@ create_merge_append_plan(PlannerInfo *root, MergeAppendPath *best_path)
|
||||
/* Now, insert a Sort node if subplan isn't sufficiently ordered */
|
||||
if (!pathkeys_contained_in(pathkeys, subpath->pathkeys))
|
||||
subplan = (Plan *) make_sort(root, subplan, numsortkeys,
|
||||
sortColIdx, sortOperators, collations, nullsFirst,
|
||||
sortColIdx, sortOperators, collations, nullsFirst,
|
||||
best_path->limit_tuples);
|
||||
|
||||
subplans = lappend(subplans, subplan);
|
||||
@ -983,7 +984,7 @@ create_unique_plan(PlannerInfo *root, UniquePath *best_path)
|
||||
sortcl->eqop = eqop;
|
||||
sortcl->sortop = sortop;
|
||||
sortcl->nulls_first = false;
|
||||
sortcl->hashable = false; /* no need to make this accurate */
|
||||
sortcl->hashable = false; /* no need to make this accurate */
|
||||
sortList = lappend(sortList, sortcl);
|
||||
groupColPos++;
|
||||
}
|
||||
@ -1153,8 +1154,8 @@ create_indexscan_plan(PlannerInfo *root,
|
||||
qpqual = extract_actual_clauses(qpqual, false);
|
||||
|
||||
/*
|
||||
* We have to replace any outer-relation variables with nestloop params
|
||||
* in the indexqualorig, qpqual, and indexorderbyorig expressions. A bit
|
||||
* We have to replace any outer-relation variables with nestloop params in
|
||||
* the indexqualorig, qpqual, and indexorderbyorig expressions. A bit
|
||||
* annoying to have to do this separately from the processing in
|
||||
* fix_indexqual_references --- rethink this when generalizing the inner
|
||||
* indexscan support. But note we can't really do this earlier because
|
||||
@ -1465,6 +1466,7 @@ create_bitmap_subplan(PlannerInfo *root, Path *bitmapqual,
|
||||
*indexqual = lappend(*indexqual, pred);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Replace outer-relation variables with nestloop params, but only
|
||||
* after doing the above comparisons to index predicates.
|
||||
@ -2330,10 +2332,10 @@ replace_nestloop_params_mutator(Node *node, PlannerInfo *root)
|
||||
return NULL;
|
||||
if (IsA(node, Var))
|
||||
{
|
||||
Var *var = (Var *) node;
|
||||
Param *param;
|
||||
Var *var = (Var *) node;
|
||||
Param *param;
|
||||
NestLoopParam *nlp;
|
||||
ListCell *lc;
|
||||
ListCell *lc;
|
||||
|
||||
/* Upper-level Vars should be long gone at this point */
|
||||
Assert(var->varlevelsup == 0);
|
||||
@ -2493,7 +2495,7 @@ fix_indexqual_references(PlannerInfo *root, IndexPath *index_path,
|
||||
*
|
||||
* This is a simplified version of fix_indexqual_references. The input does
|
||||
* not have RestrictInfo nodes, and we assume that indxqual.c already
|
||||
* commuted the clauses to put the index keys on the left. Also, we don't
|
||||
* commuted the clauses to put the index keys on the left. Also, we don't
|
||||
* bother to support any cases except simple OpExprs, since nothing else
|
||||
* is allowed for ordering operators.
|
||||
*/
|
||||
@ -3082,8 +3084,8 @@ make_append(List *appendplans, List *tlist)
|
||||
* If you change this, see also create_append_path(). Also, the size
|
||||
* calculations should match set_append_rel_pathlist(). It'd be better
|
||||
* not to duplicate all this logic, but some callers of this function
|
||||
* aren't working from an appendrel or AppendPath, so there's noplace
|
||||
* to copy the data from.
|
||||
* aren't working from an appendrel or AppendPath, so there's noplace to
|
||||
* copy the data from.
|
||||
*/
|
||||
plan->startup_cost = 0;
|
||||
plan->total_cost = 0;
|
||||
@ -3320,7 +3322,7 @@ make_mergejoin(List *tlist,
|
||||
*/
|
||||
static Sort *
|
||||
make_sort(PlannerInfo *root, Plan *lefttree, int numCols,
|
||||
AttrNumber *sortColIdx, Oid *sortOperators, Oid *collations, bool *nullsFirst,
|
||||
AttrNumber *sortColIdx, Oid *sortOperators, Oid *collations, bool *nullsFirst,
|
||||
double limit_tuples)
|
||||
{
|
||||
Sort *node = makeNode(Sort);
|
||||
@ -3398,7 +3400,7 @@ add_sort_column(AttrNumber colIdx, Oid sortOp, Oid coll, bool nulls_first,
|
||||
* prepare_sort_from_pathkeys
|
||||
* Prepare to sort according to given pathkeys
|
||||
*
|
||||
* This is used to set up for both Sort and MergeAppend nodes. It calculates
|
||||
* This is used to set up for both Sort and MergeAppend nodes. It calculates
|
||||
* the executor's representation of the sort key information, and adjusts the
|
||||
* plan targetlist if needed to add resjunk sort columns.
|
||||
*
|
||||
@ -3608,7 +3610,7 @@ prepare_sort_from_pathkeys(PlannerInfo *root, Plan *lefttree, List *pathkeys,
|
||||
pathkey->pk_eclass->ec_collation,
|
||||
pathkey->pk_nulls_first,
|
||||
numsortkeys,
|
||||
sortColIdx, sortOperators, collations, nullsFirst);
|
||||
sortColIdx, sortOperators, collations, nullsFirst);
|
||||
}
|
||||
|
||||
Assert(numsortkeys > 0);
|
||||
@ -3653,7 +3655,7 @@ make_sort_from_pathkeys(PlannerInfo *root, Plan *lefttree, List *pathkeys,
|
||||
|
||||
/* Now build the Sort node */
|
||||
return make_sort(root, lefttree, numsortkeys,
|
||||
sortColIdx, sortOperators, collations, nullsFirst, limit_tuples);
|
||||
sortColIdx, sortOperators, collations, nullsFirst, limit_tuples);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -3699,7 +3701,7 @@ make_sort_from_sortclauses(PlannerInfo *root, List *sortcls, Plan *lefttree)
|
||||
exprCollation((Node *) tle->expr),
|
||||
sortcl->nulls_first,
|
||||
numsortkeys,
|
||||
sortColIdx, sortOperators, collations, nullsFirst);
|
||||
sortColIdx, sortOperators, collations, nullsFirst);
|
||||
}
|
||||
|
||||
Assert(numsortkeys > 0);
|
||||
@ -3761,7 +3763,7 @@ make_sort_from_groupcols(PlannerInfo *root,
|
||||
exprCollation((Node *) tle->expr),
|
||||
grpcl->nulls_first,
|
||||
numsortkeys,
|
||||
sortColIdx, sortOperators, collations, nullsFirst);
|
||||
sortColIdx, sortOperators, collations, nullsFirst);
|
||||
grpno++;
|
||||
}
|
||||
|
||||
|
@ -188,10 +188,11 @@ add_vars_to_targetlist(PlannerInfo *root, List *vars, Relids where_needed)
|
||||
|
||||
phinfo->ph_needed = bms_add_members(phinfo->ph_needed,
|
||||
where_needed);
|
||||
|
||||
/*
|
||||
* Update ph_may_need too. This is currently only necessary
|
||||
* when being called from build_base_rel_tlists, but we may as
|
||||
* well do it always.
|
||||
* Update ph_may_need too. This is currently only necessary when
|
||||
* being called from build_base_rel_tlists, but we may as well do
|
||||
* it always.
|
||||
*/
|
||||
phinfo->ph_may_need = bms_add_members(phinfo->ph_may_need,
|
||||
where_needed);
|
||||
@ -704,8 +705,8 @@ make_outerjoininfo(PlannerInfo *root,
|
||||
* this join's nullable side, and it may get used above this join, then
|
||||
* ensure that min_righthand contains the full eval_at set of the PHV.
|
||||
* This ensures that the PHV actually can be evaluated within the RHS.
|
||||
* Note that this works only because we should already have determined
|
||||
* the final eval_at level for any PHV syntactically within this join.
|
||||
* Note that this works only because we should already have determined the
|
||||
* final eval_at level for any PHV syntactically within this join.
|
||||
*/
|
||||
foreach(l, root->placeholder_list)
|
||||
{
|
||||
@ -1070,7 +1071,7 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause,
|
||||
*
|
||||
* In all cases, it's important to initialize the left_ec and right_ec
|
||||
* fields of a mergejoinable clause, so that all possibly mergejoinable
|
||||
* expressions have representations in EquivalenceClasses. If
|
||||
* expressions have representations in EquivalenceClasses. If
|
||||
* process_equivalence is successful, it will take care of that;
|
||||
* otherwise, we have to call initialize_mergeclause_eclasses to do it.
|
||||
*/
|
||||
|
@ -10,9 +10,9 @@
|
||||
* ORDER BY col ASC/DESC
|
||||
* LIMIT 1)
|
||||
* Given a suitable index on tab.col, this can be much faster than the
|
||||
* generic scan-all-the-rows aggregation plan. We can handle multiple
|
||||
* generic scan-all-the-rows aggregation plan. We can handle multiple
|
||||
* MIN/MAX aggregates by generating multiple subqueries, and their
|
||||
* orderings can be different. However, if the query contains any
|
||||
* orderings can be different. However, if the query contains any
|
||||
* non-optimizable aggregates, there's no point since we'll have to
|
||||
* scan all the rows anyway.
|
||||
*
|
||||
@ -87,10 +87,10 @@ preprocess_minmax_aggregates(PlannerInfo *root, List *tlist)
|
||||
*
|
||||
* We don't handle GROUP BY or windowing, because our current
|
||||
* implementations of grouping require looking at all the rows anyway, and
|
||||
* so there's not much point in optimizing MIN/MAX. (Note: relaxing
|
||||
* this would likely require some restructuring in grouping_planner(),
|
||||
* since it performs assorted processing related to these features between
|
||||
* calling preprocess_minmax_aggregates and optimize_minmax_aggregates.)
|
||||
* so there's not much point in optimizing MIN/MAX. (Note: relaxing this
|
||||
* would likely require some restructuring in grouping_planner(), since it
|
||||
* performs assorted processing related to these features between calling
|
||||
* preprocess_minmax_aggregates and optimize_minmax_aggregates.)
|
||||
*/
|
||||
if (parse->groupClause || parse->hasWindowFuncs)
|
||||
return;
|
||||
@ -119,7 +119,7 @@ preprocess_minmax_aggregates(PlannerInfo *root, List *tlist)
|
||||
|
||||
/*
|
||||
* Scan the tlist and HAVING qual to find all the aggregates and verify
|
||||
* all are MIN/MAX aggregates. Stop as soon as we find one that isn't.
|
||||
* all are MIN/MAX aggregates. Stop as soon as we find one that isn't.
|
||||
*/
|
||||
aggs_list = NIL;
|
||||
if (find_minmax_aggs_walker((Node *) tlist, &aggs_list))
|
||||
@ -146,7 +146,7 @@ preprocess_minmax_aggregates(PlannerInfo *root, List *tlist)
|
||||
* ordering operator.
|
||||
*/
|
||||
eqop = get_equality_op_for_ordering_op(mminfo->aggsortop, &reverse);
|
||||
if (!OidIsValid(eqop)) /* shouldn't happen */
|
||||
if (!OidIsValid(eqop)) /* shouldn't happen */
|
||||
elog(ERROR, "could not find equality operator for ordering operator %u",
|
||||
mminfo->aggsortop);
|
||||
|
||||
@ -154,7 +154,7 @@ preprocess_minmax_aggregates(PlannerInfo *root, List *tlist)
|
||||
* We can use either an ordering that gives NULLS FIRST or one that
|
||||
* gives NULLS LAST; furthermore there's unlikely to be much
|
||||
* performance difference between them, so it doesn't seem worth
|
||||
* costing out both ways if we get a hit on the first one. NULLS
|
||||
* costing out both ways if we get a hit on the first one. NULLS
|
||||
* FIRST is more likely to be available if the operator is a
|
||||
* reverse-sort operator, so try that first if reverse.
|
||||
*/
|
||||
@ -169,8 +169,8 @@ preprocess_minmax_aggregates(PlannerInfo *root, List *tlist)
|
||||
|
||||
/*
|
||||
* We're done until path generation is complete. Save info for later.
|
||||
* (Setting root->minmax_aggs non-NIL signals we succeeded in making
|
||||
* index access paths for all the aggregates.)
|
||||
* (Setting root->minmax_aggs non-NIL signals we succeeded in making index
|
||||
* access paths for all the aggregates.)
|
||||
*/
|
||||
root->minmax_aggs = aggs_list;
|
||||
}
|
||||
@ -333,7 +333,7 @@ find_minmax_aggs_walker(Node *node, List **context)
|
||||
mminfo->aggfnoid = aggref->aggfnoid;
|
||||
mminfo->aggsortop = aggsortop;
|
||||
mminfo->target = curTarget->expr;
|
||||
mminfo->subroot = NULL; /* don't compute path yet */
|
||||
mminfo->subroot = NULL; /* don't compute path yet */
|
||||
mminfo->path = NULL;
|
||||
mminfo->pathcost = 0;
|
||||
mminfo->param = NULL;
|
||||
@ -424,7 +424,7 @@ build_minmax_path(PlannerInfo *root, MinMaxAggInfo *mminfo,
|
||||
sortcl->eqop = eqop;
|
||||
sortcl->sortop = sortop;
|
||||
sortcl->nulls_first = nulls_first;
|
||||
sortcl->hashable = false; /* no need to make this accurate */
|
||||
sortcl->hashable = false; /* no need to make this accurate */
|
||||
parse->sortClause = list_make1(sortcl);
|
||||
|
||||
/* set up expressions for LIMIT 1 */
|
||||
@ -450,8 +450,8 @@ build_minmax_path(PlannerInfo *root, MinMaxAggInfo *mminfo,
|
||||
subroot->query_pathkeys = subroot->sort_pathkeys;
|
||||
|
||||
/*
|
||||
* Generate the best paths for this query, telling query_planner that
|
||||
* we have LIMIT 1.
|
||||
* Generate the best paths for this query, telling query_planner that we
|
||||
* have LIMIT 1.
|
||||
*/
|
||||
query_planner(subroot, parse->targetList, 1.0, 1.0,
|
||||
&cheapest_path, &sorted_path, &dNumGroups);
|
||||
@ -527,11 +527,11 @@ make_agg_subplan(PlannerInfo *root, MinMaxAggInfo *mminfo)
|
||||
exprCollation((Node *) mminfo->target));
|
||||
|
||||
/*
|
||||
* Make sure the initplan gets into the outer PlannerInfo, along with
|
||||
* any other initplans generated by the sub-planning run. We had to
|
||||
* include the outer PlannerInfo's pre-existing initplans into the
|
||||
* inner one's init_plans list earlier, so make sure we don't put back
|
||||
* any duplicate entries.
|
||||
* Make sure the initplan gets into the outer PlannerInfo, along with any
|
||||
* other initplans generated by the sub-planning run. We had to include
|
||||
* the outer PlannerInfo's pre-existing initplans into the inner one's
|
||||
* init_plans list earlier, so make sure we don't put back any duplicate
|
||||
* entries.
|
||||
*/
|
||||
root->init_plans = list_concat_unique_ptr(root->init_plans,
|
||||
subroot->init_plans);
|
||||
|
@ -179,12 +179,12 @@ query_planner(PlannerInfo *root, List *tlist,
|
||||
/*
|
||||
* Examine the targetlist and join tree, adding entries to baserel
|
||||
* targetlists for all referenced Vars, and generating PlaceHolderInfo
|
||||
* entries for all referenced PlaceHolderVars. Restrict and join clauses
|
||||
* are added to appropriate lists belonging to the mentioned relations.
|
||||
* We also build EquivalenceClasses for provably equivalent expressions.
|
||||
* The SpecialJoinInfo list is also built to hold information about join
|
||||
* order restrictions. Finally, we form a target joinlist for
|
||||
* make_one_rel() to work from.
|
||||
* entries for all referenced PlaceHolderVars. Restrict and join clauses
|
||||
* are added to appropriate lists belonging to the mentioned relations. We
|
||||
* also build EquivalenceClasses for provably equivalent expressions. The
|
||||
* SpecialJoinInfo list is also built to hold information about join order
|
||||
* restrictions. Finally, we form a target joinlist for make_one_rel() to
|
||||
* work from.
|
||||
*/
|
||||
build_base_rel_tlists(root, tlist);
|
||||
|
||||
@ -216,7 +216,7 @@ query_planner(PlannerInfo *root, List *tlist,
|
||||
/*
|
||||
* Examine any "placeholder" expressions generated during subquery pullup.
|
||||
* Make sure that the Vars they need are marked as needed at the relevant
|
||||
* join level. This must be done before join removal because it might
|
||||
* join level. This must be done before join removal because it might
|
||||
* cause Vars or placeholders to be needed above a join when they weren't
|
||||
* so marked before.
|
||||
*/
|
||||
|
@ -345,16 +345,16 @@ subquery_planner(PlannerGlobal *glob, Query *parse,
|
||||
inline_set_returning_functions(root);
|
||||
|
||||
/*
|
||||
* Check to see if any subqueries in the jointree can be merged into
|
||||
* this query.
|
||||
* Check to see if any subqueries in the jointree can be merged into this
|
||||
* query.
|
||||
*/
|
||||
parse->jointree = (FromExpr *)
|
||||
pull_up_subqueries(root, (Node *) parse->jointree, NULL, NULL);
|
||||
|
||||
/*
|
||||
* If this is a simple UNION ALL query, flatten it into an appendrel.
|
||||
* We do this now because it requires applying pull_up_subqueries to the
|
||||
* leaf queries of the UNION ALL, which weren't touched above because they
|
||||
* If this is a simple UNION ALL query, flatten it into an appendrel. We
|
||||
* do this now because it requires applying pull_up_subqueries to the leaf
|
||||
* queries of the UNION ALL, which weren't touched above because they
|
||||
* weren't referenced by the jointree (they will be after we do this).
|
||||
*/
|
||||
if (parse->setOperations)
|
||||
@ -575,7 +575,7 @@ subquery_planner(PlannerGlobal *glob, Query *parse,
|
||||
|
||||
plan = (Plan *) make_modifytable(parse->commandType,
|
||||
parse->canSetTag,
|
||||
list_make1_int(parse->resultRelation),
|
||||
list_make1_int(parse->resultRelation),
|
||||
list_make1(plan),
|
||||
returningLists,
|
||||
rowMarks,
|
||||
@ -3116,9 +3116,9 @@ plan_cluster_use_sort(Oid tableOid, Oid indexOid)
|
||||
|
||||
/*
|
||||
* Determine eval cost of the index expressions, if any. We need to
|
||||
* charge twice that amount for each tuple comparison that happens
|
||||
* during the sort, since tuplesort.c will have to re-evaluate the
|
||||
* index expressions each time. (XXX that's pretty inefficient...)
|
||||
* charge twice that amount for each tuple comparison that happens during
|
||||
* the sort, since tuplesort.c will have to re-evaluate the index
|
||||
* expressions each time. (XXX that's pretty inefficient...)
|
||||
*/
|
||||
cost_qual_eval(&indexExprCost, indexInfo->indexprs, root);
|
||||
comparisonCost = 2.0 * (indexExprCost.startup + indexExprCost.per_tuple);
|
||||
|
@ -1429,7 +1429,7 @@ pullup_replace_vars_callback(Var *var,
|
||||
*
|
||||
* If a query's setOperations tree consists entirely of simple UNION ALL
|
||||
* operations, flatten it into an append relation, which we can process more
|
||||
* intelligently than the general setops case. Otherwise, do nothing.
|
||||
* intelligently than the general setops case. Otherwise, do nothing.
|
||||
*
|
||||
* In most cases, this can succeed only for a top-level query, because for a
|
||||
* subquery in FROM, the parent query's invocation of pull_up_subqueries would
|
||||
@ -1478,10 +1478,10 @@ flatten_simple_union_all(PlannerInfo *root)
|
||||
|
||||
/*
|
||||
* Make a copy of the leftmost RTE and add it to the rtable. This copy
|
||||
* will represent the leftmost leaf query in its capacity as a member
|
||||
* of the appendrel. The original will represent the appendrel as a
|
||||
* whole. (We must do things this way because the upper query's Vars
|
||||
* have to be seen as referring to the whole appendrel.)
|
||||
* will represent the leftmost leaf query in its capacity as a member of
|
||||
* the appendrel. The original will represent the appendrel as a whole.
|
||||
* (We must do things this way because the upper query's Vars have to be
|
||||
* seen as referring to the whole appendrel.)
|
||||
*/
|
||||
childRTE = copyObject(leftmostRTE);
|
||||
parse->rtable = lappend(parse->rtable, childRTE);
|
||||
@ -1503,8 +1503,8 @@ flatten_simple_union_all(PlannerInfo *root)
|
||||
parse->jointree->fromlist = list_make1(rtr);
|
||||
|
||||
/*
|
||||
* Now pretend the query has no setops. We must do this before trying
|
||||
* to do subquery pullup, because of Assert in pull_up_simple_subquery.
|
||||
* Now pretend the query has no setops. We must do this before trying to
|
||||
* do subquery pullup, because of Assert in pull_up_simple_subquery.
|
||||
*/
|
||||
parse->setOperations = NULL;
|
||||
|
||||
@ -1842,9 +1842,9 @@ reduce_outer_joins_pass2(Node *jtnode,
|
||||
* never both, to the children of an outer join.
|
||||
*
|
||||
* Note that a SEMI join works like an inner join here: it's okay
|
||||
* to pass down both local and upper constraints. (There can't
|
||||
* be any upper constraints affecting its inner side, but it's
|
||||
* not worth having a separate code path to avoid passing them.)
|
||||
* to pass down both local and upper constraints. (There can't be
|
||||
* any upper constraints affecting its inner side, but it's not
|
||||
* worth having a separate code path to avoid passing them.)
|
||||
*
|
||||
* At a FULL join we just punt and pass nothing down --- is it
|
||||
* possible to be smarter?
|
||||
@ -1882,7 +1882,7 @@ reduce_outer_joins_pass2(Node *jtnode,
|
||||
pass_nonnullable_vars = local_nonnullable_vars;
|
||||
pass_forced_null_vars = local_forced_null_vars;
|
||||
}
|
||||
else if (jointype != JOIN_FULL) /* ie, LEFT or ANTI */
|
||||
else if (jointype != JOIN_FULL) /* ie, LEFT or ANTI */
|
||||
{
|
||||
/* can't pass local constraints to non-nullable side */
|
||||
pass_nonnullable_rels = nonnullable_rels;
|
||||
|
@ -54,12 +54,12 @@ static Expr *process_duplicate_ors(List *orlist);
|
||||
* Although this can be invoked on its own, it's mainly intended as a helper
|
||||
* for eval_const_expressions(), and that context drives several design
|
||||
* decisions. In particular, if the input is already AND/OR flat, we must
|
||||
* preserve that property. We also don't bother to recurse in situations
|
||||
* preserve that property. We also don't bother to recurse in situations
|
||||
* where we can assume that lower-level executions of eval_const_expressions
|
||||
* would already have simplified sub-clauses of the input.
|
||||
*
|
||||
* The difference between this and a simple make_notclause() is that this
|
||||
* tries to get rid of the NOT node by logical simplification. It's clearly
|
||||
* tries to get rid of the NOT node by logical simplification. It's clearly
|
||||
* always a win if the NOT node can be eliminated altogether. However, our
|
||||
* use of DeMorgan's laws could result in having more NOT nodes rather than
|
||||
* fewer. We do that unconditionally anyway, because in WHERE clauses it's
|
||||
@ -141,21 +141,21 @@ negate_clause(Node *node)
|
||||
|
||||
switch (expr->boolop)
|
||||
{
|
||||
/*--------------------
|
||||
* Apply DeMorgan's Laws:
|
||||
* (NOT (AND A B)) => (OR (NOT A) (NOT B))
|
||||
* (NOT (OR A B)) => (AND (NOT A) (NOT B))
|
||||
* i.e., swap AND for OR and negate each subclause.
|
||||
*
|
||||
* If the input is already AND/OR flat and has no NOT
|
||||
* directly above AND or OR, this transformation preserves
|
||||
* those properties. For example, if no direct child of
|
||||
* the given AND clause is an AND or a NOT-above-OR, then
|
||||
* the recursive calls of negate_clause() can't return any
|
||||
* OR clauses. So we needn't call pull_ors() before
|
||||
* building a new OR clause. Similarly for the OR case.
|
||||
*--------------------
|
||||
*/
|
||||
/*--------------------
|
||||
* Apply DeMorgan's Laws:
|
||||
* (NOT (AND A B)) => (OR (NOT A) (NOT B))
|
||||
* (NOT (OR A B)) => (AND (NOT A) (NOT B))
|
||||
* i.e., swap AND for OR and negate each subclause.
|
||||
*
|
||||
* If the input is already AND/OR flat and has no NOT
|
||||
* directly above AND or OR, this transformation preserves
|
||||
* those properties. For example, if no direct child of
|
||||
* the given AND clause is an AND or a NOT-above-OR, then
|
||||
* the recursive calls of negate_clause() can't return any
|
||||
* OR clauses. So we needn't call pull_ors() before
|
||||
* building a new OR clause. Similarly for the OR case.
|
||||
*--------------------
|
||||
*/
|
||||
case AND_EXPR:
|
||||
{
|
||||
List *nargs = NIL;
|
||||
@ -183,6 +183,7 @@ negate_clause(Node *node)
|
||||
}
|
||||
break;
|
||||
case NOT_EXPR:
|
||||
|
||||
/*
|
||||
* NOT underneath NOT: they cancel. We assume the
|
||||
* input is already simplified, so no need to recurse.
|
||||
@ -218,8 +219,8 @@ negate_clause(Node *node)
|
||||
break;
|
||||
case T_BooleanTest:
|
||||
{
|
||||
BooleanTest *expr = (BooleanTest *) node;
|
||||
BooleanTest *newexpr = makeNode(BooleanTest);
|
||||
BooleanTest *expr = (BooleanTest *) node;
|
||||
BooleanTest *newexpr = makeNode(BooleanTest);
|
||||
|
||||
newexpr->arg = expr->arg;
|
||||
switch (expr->booltesttype)
|
||||
|
@ -4,7 +4,7 @@
|
||||
* Routines to preprocess the parse tree target list
|
||||
*
|
||||
* For INSERT and UPDATE queries, the targetlist must contain an entry for
|
||||
* each attribute of the target relation in the correct order. For all query
|
||||
* each attribute of the target relation in the correct order. For all query
|
||||
* types, we may need to add junk tlist entries for Vars used in the RETURNING
|
||||
* list and row ID information needed for EvalPlanQual checking.
|
||||
*
|
||||
@ -80,7 +80,7 @@ preprocess_targetlist(PlannerInfo *root, List *tlist)
|
||||
/*
|
||||
* Add necessary junk columns for rowmarked rels. These values are needed
|
||||
* for locking of rels selected FOR UPDATE/SHARE, and to do EvalPlanQual
|
||||
* rechecking. See comments for PlanRowMark in plannodes.h.
|
||||
* rechecking. See comments for PlanRowMark in plannodes.h.
|
||||
*/
|
||||
foreach(lc, root->rowMarks)
|
||||
{
|
||||
|
@ -938,7 +938,7 @@ generate_setop_tlist(List *colTypes, int flag,
|
||||
* The Vars are always generated with varno 0.
|
||||
*/
|
||||
static List *
|
||||
generate_append_tlist(List *colTypes, List*colCollations, bool flag,
|
||||
generate_append_tlist(List *colTypes, List *colCollations, bool flag,
|
||||
List *input_plans,
|
||||
List *refnames_tlist)
|
||||
{
|
||||
|
@ -2042,7 +2042,7 @@ rowtype_field_matches(Oid rowtypeid, int fieldnum,
|
||||
*
|
||||
* Whenever a function is eliminated from the expression by means of
|
||||
* constant-expression evaluation or inlining, we add the function to
|
||||
* root->glob->invalItems. This ensures the plan is known to depend on
|
||||
* root->glob->invalItems. This ensures the plan is known to depend on
|
||||
* such functions, even though they aren't referenced anymore.
|
||||
*
|
||||
* We assume that the tree has already been type-checked and contains
|
||||
@ -2437,8 +2437,8 @@ eval_const_expressions_mutator(Node *node,
|
||||
context);
|
||||
|
||||
/*
|
||||
* Use negate_clause() to see if we can simplify away
|
||||
* the NOT.
|
||||
* Use negate_clause() to see if we can simplify away the
|
||||
* NOT.
|
||||
*/
|
||||
return negate_clause(arg);
|
||||
}
|
||||
@ -2548,9 +2548,9 @@ eval_const_expressions_mutator(Node *node,
|
||||
makeConst(OIDOID, -1, InvalidOid, sizeof(Oid),
|
||||
ObjectIdGetDatum(intypioparam),
|
||||
false, true),
|
||||
makeConst(INT4OID, -1, InvalidOid, sizeof(int32),
|
||||
Int32GetDatum(-1),
|
||||
false, true));
|
||||
makeConst(INT4OID, -1, InvalidOid, sizeof(int32),
|
||||
Int32GetDatum(-1),
|
||||
false, true));
|
||||
|
||||
simple = simplify_function(infunc,
|
||||
expr->resulttype, -1,
|
||||
@ -2618,9 +2618,9 @@ eval_const_expressions_mutator(Node *node,
|
||||
/*
|
||||
* If we can simplify the input to a constant, then we don't need the
|
||||
* CollateExpr node at all: just change the constcollid field of the
|
||||
* Const node. Otherwise, replace the CollateExpr with a RelabelType.
|
||||
* (We do that so as to improve uniformity of expression representation
|
||||
* and thus simplify comparison of expressions.)
|
||||
* Const node. Otherwise, replace the CollateExpr with a RelabelType.
|
||||
* (We do that so as to improve uniformity of expression
|
||||
* representation and thus simplify comparison of expressions.)
|
||||
*/
|
||||
CollateExpr *collate = (CollateExpr *) node;
|
||||
Node *arg;
|
||||
@ -2675,7 +2675,7 @@ eval_const_expressions_mutator(Node *node,
|
||||
* placeholder nodes, so that we have the opportunity to reduce
|
||||
* constant test conditions. For example this allows
|
||||
* CASE 0 WHEN 0 THEN 1 ELSE 1/0 END
|
||||
* to reduce to 1 rather than drawing a divide-by-0 error. Note
|
||||
* to reduce to 1 rather than drawing a divide-by-0 error. Note
|
||||
* that when the test expression is constant, we don't have to
|
||||
* include it in the resulting CASE; for example
|
||||
* CASE 0 WHEN x THEN y ELSE z END
|
||||
@ -2855,9 +2855,9 @@ eval_const_expressions_mutator(Node *node,
|
||||
/*
|
||||
* We can remove null constants from the list. For a non-null
|
||||
* constant, if it has not been preceded by any other
|
||||
* non-null-constant expressions then it is the result. Otherwise,
|
||||
* it's the next argument, but we can drop following arguments
|
||||
* since they will never be reached.
|
||||
* non-null-constant expressions then it is the result.
|
||||
* Otherwise, it's the next argument, but we can drop following
|
||||
* arguments since they will never be reached.
|
||||
*/
|
||||
if (IsA(e, Const))
|
||||
{
|
||||
@ -3353,12 +3353,12 @@ simplify_boolean_equality(Oid opno, List *args)
|
||||
if (DatumGetBool(((Const *) leftop)->constvalue))
|
||||
return rightop; /* true = foo */
|
||||
else
|
||||
return negate_clause(rightop); /* false = foo */
|
||||
return negate_clause(rightop); /* false = foo */
|
||||
}
|
||||
else
|
||||
{
|
||||
if (DatumGetBool(((Const *) leftop)->constvalue))
|
||||
return negate_clause(rightop); /* true <> foo */
|
||||
return negate_clause(rightop); /* true <> foo */
|
||||
else
|
||||
return rightop; /* false <> foo */
|
||||
}
|
||||
@ -3902,7 +3902,7 @@ inline_function(Oid funcid, Oid result_type, Oid result_collid,
|
||||
fexpr->funcresulttype = result_type;
|
||||
fexpr->funcretset = false;
|
||||
fexpr->funcformat = COERCE_DONTCARE; /* doesn't matter */
|
||||
fexpr->funccollid = result_collid; /* doesn't matter */
|
||||
fexpr->funccollid = result_collid; /* doesn't matter */
|
||||
fexpr->inputcollid = input_collid;
|
||||
fexpr->args = args;
|
||||
fexpr->location = -1;
|
||||
@ -4060,18 +4060,18 @@ inline_function(Oid funcid, Oid result_type, Oid result_collid,
|
||||
MemoryContextDelete(mycxt);
|
||||
|
||||
/*
|
||||
* If the result is of a collatable type, force the result to expose
|
||||
* the correct collation. In most cases this does not matter, but
|
||||
* it's possible that the function result is used directly as a sort key
|
||||
* or in other places where we expect exprCollation() to tell the truth.
|
||||
* If the result is of a collatable type, force the result to expose the
|
||||
* correct collation. In most cases this does not matter, but it's
|
||||
* possible that the function result is used directly as a sort key or in
|
||||
* other places where we expect exprCollation() to tell the truth.
|
||||
*/
|
||||
if (OidIsValid(result_collid))
|
||||
{
|
||||
Oid exprcoll = exprCollation(newexpr);
|
||||
Oid exprcoll = exprCollation(newexpr);
|
||||
|
||||
if (OidIsValid(exprcoll) && exprcoll != result_collid)
|
||||
{
|
||||
CollateExpr *newnode = makeNode(CollateExpr);
|
||||
CollateExpr *newnode = makeNode(CollateExpr);
|
||||
|
||||
newnode->arg = (Expr *) newexpr;
|
||||
newnode->collOid = result_collid;
|
||||
@ -4370,11 +4370,11 @@ inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte)
|
||||
oldcxt = MemoryContextSwitchTo(mycxt);
|
||||
|
||||
/*
|
||||
* When we call eval_const_expressions below, it might try to add items
|
||||
* to root->glob->invalItems. Since it is running in the temp context,
|
||||
* those items will be in that context, and will need to be copied out
|
||||
* if we're successful. Temporarily reset the list so that we can keep
|
||||
* those items separate from the pre-existing list contents.
|
||||
* When we call eval_const_expressions below, it might try to add items to
|
||||
* root->glob->invalItems. Since it is running in the temp context, those
|
||||
* items will be in that context, and will need to be copied out if we're
|
||||
* successful. Temporarily reset the list so that we can keep those items
|
||||
* separate from the pre-existing list contents.
|
||||
*/
|
||||
saveInvalItems = root->glob->invalItems;
|
||||
root->glob->invalItems = NIL;
|
||||
@ -4419,8 +4419,8 @@ inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte)
|
||||
goto fail;
|
||||
|
||||
/*
|
||||
* Set up to handle parameters while parsing the function body. We
|
||||
* can use the FuncExpr just created as the input for
|
||||
* Set up to handle parameters while parsing the function body. We can
|
||||
* use the FuncExpr just created as the input for
|
||||
* prepare_sql_fn_parse_info.
|
||||
*/
|
||||
pinfo = prepare_sql_fn_parse_info(func_tuple,
|
||||
@ -4438,7 +4438,7 @@ inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte)
|
||||
|
||||
querytree_list = pg_analyze_and_rewrite_params(linitial(raw_parsetree_list),
|
||||
src,
|
||||
(ParserSetupHook) sql_fn_parser_setup,
|
||||
(ParserSetupHook) sql_fn_parser_setup,
|
||||
pinfo);
|
||||
if (list_length(querytree_list) != 1)
|
||||
goto fail;
|
||||
@ -4513,8 +4513,8 @@ inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte)
|
||||
ReleaseSysCache(func_tuple);
|
||||
|
||||
/*
|
||||
* We don't have to fix collations here because the upper query is
|
||||
* already parsed, ie, the collations in the RTE are what count.
|
||||
* We don't have to fix collations here because the upper query is already
|
||||
* parsed, ie, the collations in the RTE are what count.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -745,7 +745,7 @@ create_merge_append_path(PlannerInfo *root,
|
||||
else
|
||||
{
|
||||
/* We'll need to insert a Sort node, so include cost for that */
|
||||
Path sort_path; /* dummy for result of cost_sort */
|
||||
Path sort_path; /* dummy for result of cost_sort */
|
||||
|
||||
cost_sort(&sort_path,
|
||||
root,
|
||||
@ -1432,11 +1432,11 @@ create_foreignscan_path(PlannerInfo *root, RelOptInfo *rel)
|
||||
ForeignPath *pathnode = makeNode(ForeignPath);
|
||||
RangeTblEntry *rte;
|
||||
FdwRoutine *fdwroutine;
|
||||
FdwPlan *fdwplan;
|
||||
FdwPlan *fdwplan;
|
||||
|
||||
pathnode->path.pathtype = T_ForeignScan;
|
||||
pathnode->path.parent = rel;
|
||||
pathnode->path.pathkeys = NIL; /* result is always unordered */
|
||||
pathnode->path.pathkeys = NIL; /* result is always unordered */
|
||||
|
||||
/* Get FDW's callback info */
|
||||
rte = planner_rt_fetch(rel->relid, root);
|
||||
|
@ -25,7 +25,7 @@
|
||||
/* Local functions */
|
||||
static Relids find_placeholders_recurse(PlannerInfo *root, Node *jtnode);
|
||||
static void find_placeholders_in_qual(PlannerInfo *root, Node *qual,
|
||||
Relids relids);
|
||||
Relids relids);
|
||||
|
||||
|
||||
/*
|
||||
@ -179,7 +179,7 @@ find_placeholders_recurse(PlannerInfo *root, Node *jtnode)
|
||||
{
|
||||
elog(ERROR, "unrecognized node type: %d",
|
||||
(int) nodeTag(jtnode));
|
||||
jtrelids = NULL; /* keep compiler quiet */
|
||||
jtrelids = NULL; /* keep compiler quiet */
|
||||
}
|
||||
return jtrelids;
|
||||
}
|
||||
|
@ -1696,7 +1696,7 @@ get_btree_test_op(Oid pred_op, Oid clause_op, bool refute_it)
|
||||
else if (OidIsValid(clause_op_negator))
|
||||
{
|
||||
clause_tuple = SearchSysCache3(AMOPOPID,
|
||||
ObjectIdGetDatum(clause_op_negator),
|
||||
ObjectIdGetDatum(clause_op_negator),
|
||||
CharGetDatum(AMOP_SEARCH),
|
||||
ObjectIdGetDatum(opfamily_id));
|
||||
if (HeapTupleIsValid(clause_tuple))
|
||||
|
@ -694,7 +694,7 @@ pull_var_clause_walker(Node *node, pull_var_clause_context *context)
|
||||
* entries might now be arbitrary expressions, not just Vars. This affects
|
||||
* this function in one important way: we might find ourselves inserting
|
||||
* SubLink expressions into subqueries, and we must make sure that their
|
||||
* Query.hasSubLinks fields get set to TRUE if so. If there are any
|
||||
* Query.hasSubLinks fields get set to TRUE if so. If there are any
|
||||
* SubLinks in the join alias lists, the outer Query should already have
|
||||
* hasSubLinks = TRUE, so this is only relevant to un-flattened subqueries.
|
||||
*
|
||||
|
Reference in New Issue
Block a user