mirror of
https://github.com/postgres/postgres.git
synced 2025-08-27 07:42:10 +03:00
pgindent run for 8.2.
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/path/allpaths.c,v 1.153 2006/09/19 22:49:52 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/path/allpaths.c,v 1.154 2006/10/04 00:29:53 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -43,13 +43,13 @@ static void set_rel_pathlist(PlannerInfo *root, RelOptInfo *rel, Index rti);
|
||||
static void set_plain_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
|
||||
RangeTblEntry *rte);
|
||||
static void set_append_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
|
||||
Index rti, RangeTblEntry *rte);
|
||||
Index rti, RangeTblEntry *rte);
|
||||
static void set_subquery_pathlist(PlannerInfo *root, RelOptInfo *rel,
|
||||
Index rti, RangeTblEntry *rte);
|
||||
static void set_function_pathlist(PlannerInfo *root, RelOptInfo *rel,
|
||||
RangeTblEntry *rte);
|
||||
static void set_values_pathlist(PlannerInfo *root, RelOptInfo *rel,
|
||||
RangeTblEntry *rte);
|
||||
RangeTblEntry *rte);
|
||||
static RelOptInfo *make_rel_from_joinlist(PlannerInfo *root, List *joinlist);
|
||||
static RelOptInfo *make_one_rel_by_joins(PlannerInfo *root, int levels_needed,
|
||||
List *initial_rels);
|
||||
@@ -253,7 +253,7 @@ set_plain_rel_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte)
|
||||
* set_append_rel_pathlist
|
||||
* Build access paths for an "append relation"
|
||||
*
|
||||
* The passed-in rel and RTE represent the entire append relation. The
|
||||
* The passed-in rel and RTE represent the entire append relation. The
|
||||
* relation's contents are computed by appending together the output of
|
||||
* the individual member relations. Note that in the inheritance case,
|
||||
* the first member relation is actually the same table as is mentioned in
|
||||
@@ -271,8 +271,8 @@ set_append_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
|
||||
/*
|
||||
* XXX for now, can't handle inherited expansion of FOR UPDATE/SHARE; can
|
||||
* we do better? (This will take some redesign because the executor
|
||||
* currently supposes that every rowMark relation is involved in every
|
||||
* row returned by the query.)
|
||||
* currently supposes that every rowMark relation is involved in every row
|
||||
* returned by the query.)
|
||||
*/
|
||||
if (get_rowmark(root->parse, parentRTindex))
|
||||
ereport(ERROR,
|
||||
@@ -336,16 +336,16 @@ set_append_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
|
||||
childrel->max_attr);
|
||||
|
||||
/*
|
||||
* Compute the child's access paths, and add the cheapest one
|
||||
* to the Append path we are constructing for the parent.
|
||||
* Compute the child's access paths, and add the cheapest one to the
|
||||
* Append path we are constructing for the parent.
|
||||
*
|
||||
* It's possible that the child is itself an appendrel, in which
|
||||
* case we can "cut out the middleman" and just add its child
|
||||
* paths to our own list. (We don't try to do this earlier because
|
||||
* we need to apply both levels of transformation to the quals.)
|
||||
* This test also handles the case where the child rel need not
|
||||
* be scanned because of constraint exclusion: it'll have an
|
||||
* Append path with no subpaths, and will vanish from our list.
|
||||
* It's possible that the child is itself an appendrel, in which case
|
||||
* we can "cut out the middleman" and just add its child paths to our
|
||||
* own list. (We don't try to do this earlier because we need to
|
||||
* apply both levels of transformation to the quals.) This test also
|
||||
* handles the case where the child rel need not be scanned because of
|
||||
* constraint exclusion: it'll have an Append path with no subpaths,
|
||||
* and will vanish from our list.
|
||||
*/
|
||||
set_rel_pathlist(root, childrel, childRTindex);
|
||||
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/path/clausesel.c,v 1.81 2006/07/14 14:52:20 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/path/clausesel.c,v 1.82 2006/10/04 00:29:53 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -429,16 +429,16 @@ clause_selectivity(PlannerInfo *root,
|
||||
rinfo = (RestrictInfo *) clause;
|
||||
|
||||
/*
|
||||
* If the clause is marked pseudoconstant, then it will be used as
|
||||
* a gating qual and should not affect selectivity estimates; hence
|
||||
* return 1.0. The only exception is that a constant FALSE may
|
||||
* be taken as having selectivity 0.0, since it will surely mean
|
||||
* no rows out of the plan. This case is simple enough that we
|
||||
* need not bother caching the result.
|
||||
* If the clause is marked pseudoconstant, then it will be used as a
|
||||
* gating qual and should not affect selectivity estimates; hence
|
||||
* return 1.0. The only exception is that a constant FALSE may be
|
||||
* taken as having selectivity 0.0, since it will surely mean no rows
|
||||
* out of the plan. This case is simple enough that we need not
|
||||
* bother caching the result.
|
||||
*/
|
||||
if (rinfo->pseudoconstant)
|
||||
{
|
||||
if (! IsA(rinfo->clause, Const))
|
||||
if (!IsA(rinfo->clause, Const))
|
||||
return s1;
|
||||
}
|
||||
|
||||
@@ -529,7 +529,7 @@ clause_selectivity(PlannerInfo *root,
|
||||
else if (IsA(clause, Const))
|
||||
{
|
||||
/* bool constant is pretty easy... */
|
||||
Const *con = (Const *) clause;
|
||||
Const *con = (Const *) clause;
|
||||
|
||||
s1 = con->constisnull ? 0.0 :
|
||||
DatumGetBool(con->constvalue) ? 1.0 : 0.0;
|
||||
@@ -542,7 +542,7 @@ clause_selectivity(PlannerInfo *root,
|
||||
if (IsA(subst, Const))
|
||||
{
|
||||
/* bool constant is pretty easy... */
|
||||
Const *con = (Const *) subst;
|
||||
Const *con = (Const *) subst;
|
||||
|
||||
s1 = con->constisnull ? 0.0 :
|
||||
DatumGetBool(con->constvalue) ? 1.0 : 0.0;
|
||||
|
@@ -54,7 +54,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.166 2006/09/19 22:49:52 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.167 2006/10/04 00:29:53 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -92,7 +92,7 @@ double cpu_tuple_cost = DEFAULT_CPU_TUPLE_COST;
|
||||
double cpu_index_tuple_cost = DEFAULT_CPU_INDEX_TUPLE_COST;
|
||||
double cpu_operator_cost = DEFAULT_CPU_OPERATOR_COST;
|
||||
|
||||
int effective_cache_size = DEFAULT_EFFECTIVE_CACHE_SIZE;
|
||||
int effective_cache_size = DEFAULT_EFFECTIVE_CACHE_SIZE;
|
||||
|
||||
Cost disable_cost = 100000000.0;
|
||||
|
||||
@@ -276,13 +276,13 @@ cost_index(IndexPath *path, PlannerInfo *root,
|
||||
if (outer_rel != NULL && outer_rel->rows > 1)
|
||||
{
|
||||
/*
|
||||
* For repeated indexscans, scale up the number of tuples fetched
|
||||
* in the Mackert and Lohman formula by the number of scans, so
|
||||
* that we estimate the number of pages fetched by all the scans.
|
||||
* Then pro-rate the costs for one scan. In this case we assume
|
||||
* all the fetches are random accesses. XXX it'd be good to
|
||||
* include correlation in this model, but it's not clear how to do
|
||||
* that without double-counting cache effects.
|
||||
* For repeated indexscans, scale up the number of tuples fetched in
|
||||
* the Mackert and Lohman formula by the number of scans, so that we
|
||||
* estimate the number of pages fetched by all the scans. Then
|
||||
* pro-rate the costs for one scan. In this case we assume all the
|
||||
* fetches are random accesses. XXX it'd be good to include
|
||||
* correlation in this model, but it's not clear how to do that
|
||||
* without double-counting cache effects.
|
||||
*/
|
||||
double num_scans = outer_rel->rows;
|
||||
|
||||
@@ -385,7 +385,7 @@ cost_index(IndexPath *path, PlannerInfo *root,
|
||||
* computed for us by query_planner.
|
||||
*
|
||||
* Caller is expected to have ensured that tuples_fetched is greater than zero
|
||||
* and rounded to integer (see clamp_row_est). The result will likewise be
|
||||
* and rounded to integer (see clamp_row_est). The result will likewise be
|
||||
* greater than zero and integral.
|
||||
*/
|
||||
double
|
||||
@@ -406,7 +406,8 @@ index_pages_fetched(double tuples_fetched, BlockNumber pages,
|
||||
Assert(T <= total_pages);
|
||||
|
||||
/* b is pro-rated share of effective_cache_size */
|
||||
b = (double) effective_cache_size * T / total_pages;
|
||||
b = (double) effective_cache_size *T / total_pages;
|
||||
|
||||
/* force it positive and integral */
|
||||
if (b <= 1.0)
|
||||
b = 1.0;
|
||||
@@ -543,10 +544,10 @@ cost_bitmap_heap_scan(Path *path, PlannerInfo *root, RelOptInfo *baserel,
|
||||
if (outer_rel != NULL && outer_rel->rows > 1)
|
||||
{
|
||||
/*
|
||||
* For repeated bitmap scans, scale up the number of tuples fetched
|
||||
* in the Mackert and Lohman formula by the number of scans, so
|
||||
* that we estimate the number of pages fetched by all the scans.
|
||||
* Then pro-rate for one scan.
|
||||
* For repeated bitmap scans, scale up the number of tuples fetched in
|
||||
* the Mackert and Lohman formula by the number of scans, so that we
|
||||
* estimate the number of pages fetched by all the scans. Then
|
||||
* pro-rate for one scan.
|
||||
*/
|
||||
double num_scans = outer_rel->rows;
|
||||
|
||||
@@ -573,7 +574,7 @@ cost_bitmap_heap_scan(Path *path, PlannerInfo *root, RelOptInfo *baserel,
|
||||
/*
|
||||
* For small numbers of pages we should charge random_page_cost apiece,
|
||||
* while if nearly all the table's pages are being read, it's more
|
||||
* appropriate to charge seq_page_cost apiece. The effect is nonlinear,
|
||||
* appropriate to charge seq_page_cost apiece. The effect is nonlinear,
|
||||
* too. For lack of a better idea, interpolate like this to determine the
|
||||
* cost per page.
|
||||
*/
|
||||
@@ -748,7 +749,7 @@ cost_tidscan(Path *path, PlannerInfo *root,
|
||||
{
|
||||
/* Each element of the array yields 1 tuple */
|
||||
ScalarArrayOpExpr *saop = (ScalarArrayOpExpr *) lfirst(l);
|
||||
Node *arraynode = (Node *) lsecond(saop->args);
|
||||
Node *arraynode = (Node *) lsecond(saop->args);
|
||||
|
||||
ntuples += estimate_array_length(arraynode);
|
||||
}
|
||||
@@ -849,8 +850,8 @@ cost_valuesscan(Path *path, PlannerInfo *root, RelOptInfo *baserel)
|
||||
Assert(baserel->rtekind == RTE_VALUES);
|
||||
|
||||
/*
|
||||
* For now, estimate list evaluation cost at one operator eval per
|
||||
* list (probably pretty bogus, but is it worth being smarter?)
|
||||
* For now, estimate list evaluation cost at one operator eval per list
|
||||
* (probably pretty bogus, but is it worth being smarter?)
|
||||
*/
|
||||
cpu_per_tuple = cpu_operator_cost;
|
||||
|
||||
@@ -875,7 +876,7 @@ cost_valuesscan(Path *path, PlannerInfo *root, RelOptInfo *baserel)
|
||||
* If the total volume exceeds work_mem, we switch to a tape-style merge
|
||||
* algorithm. There will still be about t*log2(t) tuple comparisons in
|
||||
* total, but we will also need to write and read each tuple once per
|
||||
* merge pass. We expect about ceil(logM(r)) merge passes where r is the
|
||||
* merge pass. We expect about ceil(logM(r)) merge passes where r is the
|
||||
* number of initial runs formed and M is the merge order used by tuplesort.c.
|
||||
* Since the average initial run should be about twice work_mem, we have
|
||||
* disk traffic = 2 * relsize * ceil(logM(p / (2*work_mem)))
|
||||
@@ -1745,7 +1746,7 @@ cost_qual_eval_walker(Node *node, QualCost *total)
|
||||
* array elements before the answer is determined.
|
||||
*/
|
||||
ScalarArrayOpExpr *saop = (ScalarArrayOpExpr *) node;
|
||||
Node *arraynode = (Node *) lsecond(saop->args);
|
||||
Node *arraynode = (Node *) lsecond(saop->args);
|
||||
|
||||
total->per_tuple +=
|
||||
cpu_operator_cost * estimate_array_length(arraynode) * 0.5;
|
||||
@@ -1967,7 +1968,7 @@ set_joinrel_size_estimates(PlannerInfo *root, RelOptInfo *rel,
|
||||
*
|
||||
* If we are doing an outer join, take that into account: the output must
|
||||
* be at least as large as the non-nullable input. (Is there any chance
|
||||
* of being even smarter?) (XXX this is not really right, because it
|
||||
* of being even smarter?) (XXX this is not really right, because it
|
||||
* assumes all the restriction clauses are join clauses; we should figure
|
||||
* pushed-down clauses separately.)
|
||||
*
|
||||
@@ -2132,10 +2133,10 @@ set_values_size_estimates(PlannerInfo *root, RelOptInfo *rel)
|
||||
Assert(rte->rtekind == RTE_VALUES);
|
||||
|
||||
/*
|
||||
* Estimate number of rows the values list will return.
|
||||
* We know this precisely based on the list length (well,
|
||||
* barring set-returning functions in list items, but that's
|
||||
* a refinement not catered for anywhere else either).
|
||||
* Estimate number of rows the values list will return. We know this
|
||||
* precisely based on the list length (well, barring set-returning
|
||||
* functions in list items, but that's a refinement not catered for
|
||||
* anywhere else either).
|
||||
*/
|
||||
rel->tuples = list_length(rte->values_lists);
|
||||
|
||||
|
@@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.211 2006/07/22 15:41:55 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.212 2006/10/04 00:29:54 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -54,10 +54,10 @@ static List *find_saop_paths(PlannerInfo *root, RelOptInfo *rel,
|
||||
List *clauses, List *outer_clauses,
|
||||
bool istoplevel, RelOptInfo *outer_rel);
|
||||
static Path *choose_bitmap_and(PlannerInfo *root, RelOptInfo *rel,
|
||||
List *paths, RelOptInfo *outer_rel);
|
||||
List *paths, RelOptInfo *outer_rel);
|
||||
static int bitmap_path_comparator(const void *a, const void *b);
|
||||
static Cost bitmap_and_cost_est(PlannerInfo *root, RelOptInfo *rel,
|
||||
List *paths, RelOptInfo *outer_rel);
|
||||
List *paths, RelOptInfo *outer_rel);
|
||||
static List *pull_indexpath_quals(Path *bitmapqual);
|
||||
static bool lists_intersect_ptr(List *list1, List *list2);
|
||||
static bool match_clause_to_indexcol(IndexOptInfo *index,
|
||||
@@ -66,7 +66,7 @@ static bool match_clause_to_indexcol(IndexOptInfo *index,
|
||||
Relids outer_relids,
|
||||
SaOpControl saop_control);
|
||||
static bool is_indexable_operator(Oid expr_op, Oid opclass,
|
||||
bool indexkey_on_left);
|
||||
bool indexkey_on_left);
|
||||
static bool match_rowcompare_to_indexcol(IndexOptInfo *index,
|
||||
int indexcol,
|
||||
Oid opclass,
|
||||
@@ -324,8 +324,8 @@ find_usable_indexes(PlannerInfo *root, RelOptInfo *rel,
|
||||
/*
|
||||
* 1. Match the index against the available restriction clauses.
|
||||
* found_clause is set true only if at least one of the current
|
||||
* clauses was used (and, if saop_control is SAOP_REQUIRE, it
|
||||
* has to have been a ScalarArrayOpExpr clause).
|
||||
* clauses was used (and, if saop_control is SAOP_REQUIRE, it has to
|
||||
* have been a ScalarArrayOpExpr clause).
|
||||
*/
|
||||
restrictclauses = group_clauses_by_indexkey(index,
|
||||
clauses,
|
||||
@@ -422,8 +422,8 @@ find_saop_paths(PlannerInfo *root, RelOptInfo *rel,
|
||||
ListCell *l;
|
||||
|
||||
/*
|
||||
* Since find_usable_indexes is relatively expensive, don't bother to
|
||||
* run it unless there are some top-level ScalarArrayOpExpr clauses.
|
||||
* Since find_usable_indexes is relatively expensive, don't bother to run
|
||||
* it unless there are some top-level ScalarArrayOpExpr clauses.
|
||||
*/
|
||||
foreach(l, clauses)
|
||||
{
|
||||
@@ -588,15 +588,15 @@ choose_bitmap_and(PlannerInfo *root, RelOptInfo *rel,
|
||||
* In theory we should consider every nonempty subset of the given paths.
|
||||
* In practice that seems like overkill, given the crude nature of the
|
||||
* estimates, not to mention the possible effects of higher-level AND and
|
||||
* OR clauses. As a compromise, we sort the paths by selectivity. We
|
||||
* OR clauses. As a compromise, we sort the paths by selectivity. We
|
||||
* always take the first, and sequentially add on paths that result in a
|
||||
* lower estimated cost.
|
||||
*
|
||||
* We also make some effort to detect directly redundant input paths, as
|
||||
* can happen if there are multiple possibly usable indexes. (Another
|
||||
* way it can happen is that best_inner_indexscan will find the same OR
|
||||
* join clauses that create_or_index_quals has pulled OR restriction
|
||||
* clauses out of, and then both versions show up as duplicate paths.) We
|
||||
* can happen if there are multiple possibly usable indexes. (Another way
|
||||
* it can happen is that best_inner_indexscan will find the same OR join
|
||||
* clauses that create_or_index_quals has pulled OR restriction clauses
|
||||
* out of, and then both versions show up as duplicate paths.) We
|
||||
* consider an index redundant if any of its index conditions were already
|
||||
* used by earlier indexes. (We could use predicate_implied_by to have a
|
||||
* more intelligent, but much more expensive, check --- but in most cases
|
||||
@@ -796,7 +796,7 @@ lists_intersect_ptr(List *list1, List *list2)
|
||||
|
||||
foreach(cell1, list1)
|
||||
{
|
||||
void *datum1 = lfirst(cell1);
|
||||
void *datum1 = lfirst(cell1);
|
||||
ListCell *cell2;
|
||||
|
||||
foreach(cell2, list2)
|
||||
@@ -963,7 +963,7 @@ group_clauses_by_indexkey(IndexOptInfo *index,
|
||||
* It is also possible to match RowCompareExpr clauses to indexes (but
|
||||
* currently, only btree indexes handle this). In this routine we will
|
||||
* report a match if the first column of the row comparison matches the
|
||||
* target index column. This is sufficient to guarantee that some index
|
||||
* target index column. This is sufficient to guarantee that some index
|
||||
* condition can be constructed from the RowCompareExpr --- whether the
|
||||
* remaining columns match the index too is considered in
|
||||
* expand_indexqual_rowcompare().
|
||||
@@ -1004,10 +1004,10 @@ match_clause_to_indexcol(IndexOptInfo *index,
|
||||
bool plain_op;
|
||||
|
||||
/*
|
||||
* Never match pseudoconstants to indexes. (Normally this could not
|
||||
* happen anyway, since a pseudoconstant clause couldn't contain a
|
||||
* Var, but what if someone builds an expression index on a constant?
|
||||
* It's not totally unreasonable to do so with a partial index, either.)
|
||||
* Never match pseudoconstants to indexes. (Normally this could not
|
||||
* happen anyway, since a pseudoconstant clause couldn't contain a Var,
|
||||
* but what if someone builds an expression index on a constant? It's not
|
||||
* totally unreasonable to do so with a partial index, either.)
|
||||
*/
|
||||
if (rinfo->pseudoconstant)
|
||||
return false;
|
||||
@@ -1421,9 +1421,9 @@ best_inner_indexscan(PlannerInfo *root, RelOptInfo *rel,
|
||||
* NOTE: because we cache on outer_relids rather than outer_rel->relids,
|
||||
* we will report the same path and hence path cost for joins with
|
||||
* different sets of irrelevant rels on the outside. Now that cost_index
|
||||
* is sensitive to outer_rel->rows, this is not really right. However
|
||||
* the error is probably not large. Is it worth establishing a separate
|
||||
* cache entry for each distinct outer_rel->relids set to get this right?
|
||||
* is sensitive to outer_rel->rows, this is not really right. However the
|
||||
* error is probably not large. Is it worth establishing a separate cache
|
||||
* entry for each distinct outer_rel->relids set to get this right?
|
||||
*/
|
||||
foreach(l, rel->index_inner_paths)
|
||||
{
|
||||
@@ -1442,11 +1442,11 @@ best_inner_indexscan(PlannerInfo *root, RelOptInfo *rel,
|
||||
*
|
||||
* Note: because we include restriction clauses, we will find indexscans
|
||||
* that could be plain indexscans, ie, they don't require the join context
|
||||
* at all. This may seem redundant, but we need to include those scans in
|
||||
* at all. This may seem redundant, but we need to include those scans in
|
||||
* the input given to choose_bitmap_and() to be sure we find optimal AND
|
||||
* combinations of join and non-join scans. Also, even if the "best
|
||||
* inner indexscan" is just a plain indexscan, it will have a different
|
||||
* cost estimate because of cache effects.
|
||||
* combinations of join and non-join scans. Also, even if the "best inner
|
||||
* indexscan" is just a plain indexscan, it will have a different cost
|
||||
* estimate because of cache effects.
|
||||
*/
|
||||
clause_list = find_clauses_for_join(root, rel, outer_relids, isouterjoin);
|
||||
|
||||
@@ -2210,7 +2210,7 @@ expand_indexqual_conditions(IndexOptInfo *index, List *clausegroups)
|
||||
foreach(l, (List *) lfirst(clausegroup_item))
|
||||
{
|
||||
RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
|
||||
Expr *clause = rinfo->clause;
|
||||
Expr *clause = rinfo->clause;
|
||||
|
||||
/* First check for boolean cases */
|
||||
if (IsBooleanOpclass(curClass))
|
||||
@@ -2240,7 +2240,7 @@ expand_indexqual_conditions(IndexOptInfo *index, List *clausegroups)
|
||||
{
|
||||
resultquals = list_concat(resultquals,
|
||||
expand_indexqual_opclause(rinfo,
|
||||
curClass));
|
||||
curClass));
|
||||
}
|
||||
else if (IsA(clause, ScalarArrayOpExpr))
|
||||
{
|
||||
@@ -2340,6 +2340,7 @@ static List *
|
||||
expand_indexqual_opclause(RestrictInfo *rinfo, Oid opclass)
|
||||
{
|
||||
Expr *clause = rinfo->clause;
|
||||
|
||||
/* we know these will succeed */
|
||||
Node *leftop = get_leftop(clause);
|
||||
Node *rightop = get_rightop(clause);
|
||||
@@ -2421,7 +2422,7 @@ expand_indexqual_opclause(RestrictInfo *rinfo, Oid opclass)
|
||||
* column matches) or a simple OpExpr (if the first-column match is all
|
||||
* there is). In these cases the modified clause is always "<=" or ">="
|
||||
* even when the original was "<" or ">" --- this is necessary to match all
|
||||
* the rows that could match the original. (We are essentially building a
|
||||
* the rows that could match the original. (We are essentially building a
|
||||
* lossy version of the row comparison when we do this.)
|
||||
*/
|
||||
static RestrictInfo *
|
||||
@@ -2430,18 +2431,18 @@ expand_indexqual_rowcompare(RestrictInfo *rinfo,
|
||||
int indexcol)
|
||||
{
|
||||
RowCompareExpr *clause = (RowCompareExpr *) rinfo->clause;
|
||||
bool var_on_left;
|
||||
int op_strategy;
|
||||
Oid op_subtype;
|
||||
bool op_recheck;
|
||||
int matching_cols;
|
||||
Oid expr_op;
|
||||
List *opclasses;
|
||||
List *subtypes;
|
||||
List *new_ops;
|
||||
ListCell *largs_cell;
|
||||
ListCell *rargs_cell;
|
||||
ListCell *opnos_cell;
|
||||
bool var_on_left;
|
||||
int op_strategy;
|
||||
Oid op_subtype;
|
||||
bool op_recheck;
|
||||
int matching_cols;
|
||||
Oid expr_op;
|
||||
List *opclasses;
|
||||
List *subtypes;
|
||||
List *new_ops;
|
||||
ListCell *largs_cell;
|
||||
ListCell *rargs_cell;
|
||||
ListCell *opnos_cell;
|
||||
|
||||
/* We have to figure out (again) how the first col matches */
|
||||
var_on_left = match_index_to_operand((Node *) linitial(clause->largs),
|
||||
@@ -2459,12 +2460,12 @@ expand_indexqual_rowcompare(RestrictInfo *rinfo,
|
||||
subtypes = list_make1_oid(op_subtype);
|
||||
|
||||
/*
|
||||
* See how many of the remaining columns match some index column
|
||||
* in the same way. A note about rel membership tests: we assume
|
||||
* that the clause as a whole is already known to use only Vars from
|
||||
* the indexed relation and possibly some acceptable outer relations.
|
||||
* So the "other" side of any potential index condition is OK as long
|
||||
* as it doesn't use Vars from the indexed relation.
|
||||
* See how many of the remaining columns match some index column in the
|
||||
* same way. A note about rel membership tests: we assume that the clause
|
||||
* as a whole is already known to use only Vars from the indexed relation
|
||||
* and possibly some acceptable outer relations. So the "other" side of
|
||||
* any potential index condition is OK as long as it doesn't use Vars from
|
||||
* the indexed relation.
|
||||
*/
|
||||
matching_cols = 1;
|
||||
largs_cell = lnext(list_head(clause->largs));
|
||||
@@ -2498,10 +2499,10 @@ expand_indexqual_rowcompare(RestrictInfo *rinfo,
|
||||
break; /* no good, volatile comparison value */
|
||||
|
||||
/*
|
||||
* The Var side can match any column of the index. If the user
|
||||
* does something weird like having multiple identical index
|
||||
* columns, we insist the match be on the first such column,
|
||||
* to avoid confusing the executor.
|
||||
* The Var side can match any column of the index. If the user does
|
||||
* something weird like having multiple identical index columns, we
|
||||
* insist the match be on the first such column, to avoid confusing
|
||||
* the executor.
|
||||
*/
|
||||
for (i = 0; i < index->ncolumns; i++)
|
||||
{
|
||||
@@ -2534,9 +2535,9 @@ expand_indexqual_rowcompare(RestrictInfo *rinfo,
|
||||
return rinfo;
|
||||
|
||||
/*
|
||||
* We have to generate a subset rowcompare (possibly just one OpExpr).
|
||||
* The painful part of this is changing < to <= or > to >=, so deal with
|
||||
* that first.
|
||||
* We have to generate a subset rowcompare (possibly just one OpExpr). The
|
||||
* painful part of this is changing < to <= or > to >=, so deal with that
|
||||
* first.
|
||||
*/
|
||||
if (op_strategy == BTLessEqualStrategyNumber ||
|
||||
op_strategy == BTGreaterEqualStrategyNumber)
|
||||
@@ -2546,8 +2547,8 @@ expand_indexqual_rowcompare(RestrictInfo *rinfo,
|
||||
}
|
||||
else
|
||||
{
|
||||
ListCell *opclasses_cell;
|
||||
ListCell *subtypes_cell;
|
||||
ListCell *opclasses_cell;
|
||||
ListCell *subtypes_cell;
|
||||
|
||||
if (op_strategy == BTLessStrategyNumber)
|
||||
op_strategy = BTLessEqualStrategyNumber;
|
||||
@@ -2561,13 +2562,13 @@ expand_indexqual_rowcompare(RestrictInfo *rinfo,
|
||||
expr_op = get_opclass_member(lfirst_oid(opclasses_cell),
|
||||
lfirst_oid(subtypes_cell),
|
||||
op_strategy);
|
||||
if (!OidIsValid(expr_op)) /* should not happen */
|
||||
if (!OidIsValid(expr_op)) /* should not happen */
|
||||
elog(ERROR, "could not find member %d of opclass %u",
|
||||
op_strategy, lfirst_oid(opclasses_cell));
|
||||
if (!var_on_left)
|
||||
{
|
||||
expr_op = get_commutator(expr_op);
|
||||
if (!OidIsValid(expr_op)) /* should not happen */
|
||||
if (!OidIsValid(expr_op)) /* should not happen */
|
||||
elog(ERROR, "could not find commutator of member %d of opclass %u",
|
||||
op_strategy, lfirst_oid(opclasses_cell));
|
||||
}
|
||||
@@ -2596,7 +2597,7 @@ expand_indexqual_rowcompare(RestrictInfo *rinfo,
|
||||
}
|
||||
else
|
||||
{
|
||||
Expr *opexpr;
|
||||
Expr *opexpr;
|
||||
|
||||
opexpr = make_opclause(linitial_oid(new_ops), BOOLOID, false,
|
||||
copyObject(linitial(clause->largs)),
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/path/joinpath.c,v 1.106 2006/08/17 17:06:37 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/path/joinpath.c,v 1.107 2006/10/04 00:29:54 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -33,7 +33,7 @@ static void hash_inner_and_outer(PlannerInfo *root, RelOptInfo *joinrel,
|
||||
RelOptInfo *outerrel, RelOptInfo *innerrel,
|
||||
List *restrictlist, JoinType jointype);
|
||||
static Path *best_appendrel_indexscan(PlannerInfo *root, RelOptInfo *rel,
|
||||
RelOptInfo *outer_rel, JoinType jointype);
|
||||
RelOptInfo *outer_rel, JoinType jointype);
|
||||
static List *select_mergejoin_clauses(RelOptInfo *joinrel,
|
||||
RelOptInfo *outerrel,
|
||||
RelOptInfo *innerrel,
|
||||
@@ -544,9 +544,9 @@ match_unsorted_outer(PlannerInfo *root,
|
||||
* mergejoin using a subset of the merge clauses. Here, we consider
|
||||
* both cheap startup cost and cheap total cost. We can ignore
|
||||
* inner_cheapest_total on the first iteration, since we already made
|
||||
* a path with it --- but not on later iterations with shorter
|
||||
* sort keys, because then we are considering a different situation,
|
||||
* viz using a simpler mergejoin to avoid a sort of the inner rel.
|
||||
* a path with it --- but not on later iterations with shorter sort
|
||||
* keys, because then we are considering a different situation, viz
|
||||
* using a simpler mergejoin to avoid a sort of the inner rel.
|
||||
*/
|
||||
num_sortkeys = list_length(innersortkeys);
|
||||
if (num_sortkeys > 1 && !useallclauses)
|
||||
@@ -792,7 +792,7 @@ hash_inner_and_outer(PlannerInfo *root,
|
||||
* best_appendrel_indexscan
|
||||
* Finds the best available set of inner indexscans for a nestloop join
|
||||
* with the given append relation on the inside and the given outer_rel
|
||||
* outside. Returns an AppendPath comprising the best inner scans, or
|
||||
* outside. Returns an AppendPath comprising the best inner scans, or
|
||||
* NULL if there are no possible inner indexscans.
|
||||
*/
|
||||
static Path *
|
||||
@@ -820,9 +820,9 @@ best_appendrel_indexscan(PlannerInfo *root, RelOptInfo *rel,
|
||||
Assert(childrel->reloptkind == RELOPT_OTHER_MEMBER_REL);
|
||||
|
||||
/*
|
||||
* Check to see if child was rejected by constraint exclusion.
|
||||
* If so, it will have a cheapest_total_path that's an Append path
|
||||
* with no members (see set_plain_rel_pathlist).
|
||||
* Check to see if child was rejected by constraint exclusion. If so,
|
||||
* it will have a cheapest_total_path that's an Append path with no
|
||||
* members (see set_plain_rel_pathlist).
|
||||
*/
|
||||
if (IsA(childrel->cheapest_total_path, AppendPath) &&
|
||||
((AppendPath *) childrel->cheapest_total_path)->subpaths == NIL)
|
||||
@@ -835,10 +835,10 @@ best_appendrel_indexscan(PlannerInfo *root, RelOptInfo *rel,
|
||||
outer_rel, jointype);
|
||||
|
||||
/*
|
||||
* If no luck on an indexpath for this rel, we'll still consider
|
||||
* an Append substituting the cheapest-total inner path. However
|
||||
* we must find at least one indexpath, else there's not going to
|
||||
* be any improvement over the base path for the appendrel.
|
||||
* If no luck on an indexpath for this rel, we'll still consider an
|
||||
* Append substituting the cheapest-total inner path. However we must
|
||||
* find at least one indexpath, else there's not going to be any
|
||||
* improvement over the base path for the appendrel.
|
||||
*/
|
||||
if (bestinnerjoin)
|
||||
found_indexscan = true;
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/path/joinrels.c,v 1.79 2006/03/05 15:58:28 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/path/joinrels.c,v 1.80 2006/10/04 00:29:54 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -87,11 +87,11 @@ make_rels_by_joins(PlannerInfo *root, int level, List **joinrels)
|
||||
|
||||
/*
|
||||
* An exception occurs when there is a clauseless join inside a
|
||||
* construct that restricts join order, i.e., an outer join RHS
|
||||
* or an IN (sub-SELECT) construct. Here, the rel may well have
|
||||
* join clauses against stuff outside the OJ RHS or IN sub-SELECT,
|
||||
* but the clauseless join *must* be done before we can make use
|
||||
* of those join clauses. So do the clauseless join bit.
|
||||
* construct that restricts join order, i.e., an outer join RHS or
|
||||
* an IN (sub-SELECT) construct. Here, the rel may well have join
|
||||
* clauses against stuff outside the OJ RHS or IN sub-SELECT, but
|
||||
* the clauseless join *must* be done before we can make use of
|
||||
* those join clauses. So do the clauseless join bit.
|
||||
*
|
||||
* See also the last-ditch case below.
|
||||
*/
|
||||
@@ -386,9 +386,9 @@ make_join_rel(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2)
|
||||
joinrelids = bms_union(rel1->relids, rel2->relids);
|
||||
|
||||
/*
|
||||
* If we have any outer joins, the proposed join might be illegal; and
|
||||
* in any case we have to determine its join type. Scan the OJ list
|
||||
* for conflicts.
|
||||
* If we have any outer joins, the proposed join might be illegal; and in
|
||||
* any case we have to determine its join type. Scan the OJ list for
|
||||
* conflicts.
|
||||
*/
|
||||
jointype = JOIN_INNER; /* default if no match to an OJ */
|
||||
is_valid_inner = true;
|
||||
@@ -485,16 +485,16 @@ make_join_rel(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2)
|
||||
InClauseInfo *ininfo = (InClauseInfo *) lfirst(l);
|
||||
|
||||
/*
|
||||
* This IN clause is not relevant unless its RHS overlaps the
|
||||
* proposed join. (Check this first as a fast path for dismissing
|
||||
* most irrelevant INs quickly.)
|
||||
* This IN clause is not relevant unless its RHS overlaps the proposed
|
||||
* join. (Check this first as a fast path for dismissing most
|
||||
* irrelevant INs quickly.)
|
||||
*/
|
||||
if (!bms_overlap(ininfo->righthand, joinrelids))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* If we are still building the IN clause's RHS, then this IN
|
||||
* clause isn't relevant yet.
|
||||
* If we are still building the IN clause's RHS, then this IN clause
|
||||
* isn't relevant yet.
|
||||
*/
|
||||
if (bms_is_subset(joinrelids, ininfo->righthand))
|
||||
continue;
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/path/orindxpath.c,v 1.80 2006/07/14 14:52:20 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/path/orindxpath.c,v 1.81 2006/10/04 00:29:54 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -106,8 +106,8 @@ create_or_index_quals(PlannerInfo *root, RelOptInfo *rel)
|
||||
* Use the generate_bitmap_or_paths() machinery to estimate the
|
||||
* value of each OR clause. We can use regular restriction
|
||||
* clauses along with the OR clause contents to generate
|
||||
* indexquals. We pass outer_rel = NULL so that sub-clauses
|
||||
* that are actually joins will be ignored.
|
||||
* indexquals. We pass outer_rel = NULL so that sub-clauses that
|
||||
* are actually joins will be ignored.
|
||||
*/
|
||||
List *orpaths;
|
||||
ListCell *k;
|
||||
|
@@ -11,7 +11,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/path/pathkeys.c,v 1.78 2006/08/17 17:02:49 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/path/pathkeys.c,v 1.79 2006/10/04 00:29:54 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -909,7 +909,7 @@ get_cheapest_fractional_path_for_pathkeys(List *paths,
|
||||
* representing a backwards scan of the index. Return NIL if can't do it.
|
||||
*
|
||||
* If 'canonical' is TRUE, we remove duplicate pathkeys (which can occur
|
||||
* if two index columns are equijoined, eg WHERE x = 1 AND y = 1). This
|
||||
* if two index columns are equijoined, eg WHERE x = 1 AND y = 1). This
|
||||
* is required if the result is to be compared directly to a canonical query
|
||||
* pathkeys list. However, some callers want a list with exactly one entry
|
||||
* per index column, and they must pass FALSE.
|
||||
@@ -1106,8 +1106,8 @@ convert_subquery_pathkeys(PlannerInfo *root, RelOptInfo *rel,
|
||||
outer_expr = (Node *)
|
||||
makeRelabelType((Expr *) outer_expr,
|
||||
((RelabelType *) sub_key)->resulttype,
|
||||
((RelabelType *) sub_key)->resulttypmod,
|
||||
((RelabelType *) sub_key)->relabelformat);
|
||||
((RelabelType *) sub_key)->resulttypmod,
|
||||
((RelabelType *) sub_key)->relabelformat);
|
||||
}
|
||||
else
|
||||
continue;
|
||||
|
@@ -24,7 +24,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/path/tidpath.c,v 1.27 2006/03/05 15:58:28 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/path/tidpath.c,v 1.28 2006/10/04 00:29:54 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -125,7 +125,7 @@ IsTidEqualAnyClause(ScalarArrayOpExpr *node, int varno)
|
||||
/* CTID must be first argument */
|
||||
if (arg1 && IsA(arg1, Var))
|
||||
{
|
||||
Var *var = (Var *) arg1;
|
||||
Var *var = (Var *) arg1;
|
||||
|
||||
if (var->varattno == SelfItemPointerAttributeNumber &&
|
||||
var->vartype == TIDOID &&
|
||||
@@ -187,7 +187,7 @@ TidQualFromExpr(Node *expr, int varno)
|
||||
{
|
||||
foreach(l, ((BoolExpr *) expr)->args)
|
||||
{
|
||||
List *frtn = TidQualFromExpr((Node *) lfirst(l), varno);
|
||||
List *frtn = TidQualFromExpr((Node *) lfirst(l), varno);
|
||||
|
||||
if (frtn)
|
||||
rlst = list_concat(rlst, frtn);
|
||||
|
@@ -10,7 +10,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.216 2006/08/02 01:59:45 joe Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.217 2006/10/04 00:29:54 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -60,7 +60,7 @@ static SubqueryScan *create_subqueryscan_plan(PlannerInfo *root, Path *best_path
|
||||
static FunctionScan *create_functionscan_plan(PlannerInfo *root, Path *best_path,
|
||||
List *tlist, List *scan_clauses);
|
||||
static ValuesScan *create_valuesscan_plan(PlannerInfo *root, Path *best_path,
|
||||
List *tlist, List *scan_clauses);
|
||||
List *tlist, List *scan_clauses);
|
||||
static NestLoop *create_nestloop_plan(PlannerInfo *root, NestPath *best_path,
|
||||
Plan *outer_plan, Plan *inner_plan);
|
||||
static MergeJoin *create_mergejoin_plan(PlannerInfo *root, MergePath *best_path,
|
||||
@@ -98,7 +98,7 @@ static TidScan *make_tidscan(List *qptlist, List *qpqual, Index scanrelid,
|
||||
static FunctionScan *make_functionscan(List *qptlist, List *qpqual,
|
||||
Index scanrelid);
|
||||
static ValuesScan *make_valuesscan(List *qptlist, List *qpqual,
|
||||
Index scanrelid);
|
||||
Index scanrelid);
|
||||
static BitmapAnd *make_bitmap_and(List *bitmapplans);
|
||||
static BitmapOr *make_bitmap_or(List *bitmapplans);
|
||||
static NestLoop *make_nestloop(List *tlist,
|
||||
@@ -216,9 +216,9 @@ create_scan_plan(PlannerInfo *root, Path *best_path)
|
||||
tlist = build_relation_tlist(rel);
|
||||
|
||||
/*
|
||||
* Extract the relevant restriction clauses from the parent relation.
|
||||
* The executor must apply all these restrictions during the scan,
|
||||
* except for pseudoconstants which we'll take care of below.
|
||||
* Extract the relevant restriction clauses from the parent relation. The
|
||||
* executor must apply all these restrictions during the scan, except for
|
||||
* pseudoconstants which we'll take care of below.
|
||||
*/
|
||||
scan_clauses = rel->baserestrictinfo;
|
||||
|
||||
@@ -282,9 +282,9 @@ create_scan_plan(PlannerInfo *root, Path *best_path)
|
||||
}
|
||||
|
||||
/*
|
||||
* If there are any pseudoconstant clauses attached to this node,
|
||||
* insert a gating Result node that evaluates the pseudoconstants
|
||||
* as one-time quals.
|
||||
* If there are any pseudoconstant clauses attached to this node, insert a
|
||||
* gating Result node that evaluates the pseudoconstants as one-time
|
||||
* quals.
|
||||
*/
|
||||
if (root->hasPseudoConstantQuals)
|
||||
plan = create_gating_plan(root, plan, scan_clauses);
|
||||
@@ -327,8 +327,8 @@ use_physical_tlist(RelOptInfo *rel)
|
||||
int i;
|
||||
|
||||
/*
|
||||
* We can do this for real relation scans, subquery scans, function
|
||||
* scans, and values scans (but not for, eg, joins).
|
||||
* We can do this for real relation scans, subquery scans, function scans,
|
||||
* and values scans (but not for, eg, joins).
|
||||
*/
|
||||
if (rel->rtekind != RTE_RELATION &&
|
||||
rel->rtekind != RTE_SUBQUERY &&
|
||||
@@ -466,9 +466,9 @@ create_join_plan(PlannerInfo *root, JoinPath *best_path)
|
||||
}
|
||||
|
||||
/*
|
||||
* If there are any pseudoconstant clauses attached to this node,
|
||||
* insert a gating Result node that evaluates the pseudoconstants
|
||||
* as one-time quals.
|
||||
* If there are any pseudoconstant clauses attached to this node, insert a
|
||||
* gating Result node that evaluates the pseudoconstants as one-time
|
||||
* quals.
|
||||
*/
|
||||
if (root->hasPseudoConstantQuals)
|
||||
plan = create_gating_plan(root, plan, best_path->joinrestrictinfo);
|
||||
@@ -991,9 +991,9 @@ create_bitmap_scan_plan(PlannerInfo *root,
|
||||
*
|
||||
* Unlike create_indexscan_plan(), we need take no special thought here
|
||||
* for partial index predicates; this is because the predicate conditions
|
||||
* are already listed in bitmapqualorig and indexquals. Bitmap scans
|
||||
* have to do it that way because predicate conditions need to be rechecked
|
||||
* if the scan becomes lossy.
|
||||
* are already listed in bitmapqualorig and indexquals. Bitmap scans have
|
||||
* to do it that way because predicate conditions need to be rechecked if
|
||||
* the scan becomes lossy.
|
||||
*/
|
||||
qpqual = NIL;
|
||||
foreach(l, scan_clauses)
|
||||
@@ -1137,6 +1137,7 @@ create_bitmap_subplan(PlannerInfo *root, Path *bitmapqual,
|
||||
subindexquals = lappend(subindexquals,
|
||||
make_ands_explicit(subindexqual));
|
||||
}
|
||||
|
||||
/*
|
||||
* In the presence of ScalarArrayOpExpr quals, we might have built
|
||||
* BitmapOrPaths with just one subpath; don't add an OR step.
|
||||
@@ -1152,7 +1153,7 @@ create_bitmap_subplan(PlannerInfo *root, Path *bitmapqual,
|
||||
plan->total_cost = opath->path.total_cost;
|
||||
plan->plan_rows =
|
||||
clamp_row_est(opath->bitmapselectivity * opath->path.parent->tuples);
|
||||
plan->plan_width = 0; /* meaningless */
|
||||
plan->plan_width = 0; /* meaningless */
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1202,10 +1203,10 @@ create_bitmap_subplan(PlannerInfo *root, Path *bitmapqual,
|
||||
Expr *pred = (Expr *) lfirst(l);
|
||||
|
||||
/*
|
||||
* We know that the index predicate must have been implied by
|
||||
* the query condition as a whole, but it may or may not be
|
||||
* implied by the conditions that got pushed into the
|
||||
* bitmapqual. Avoid generating redundant conditions.
|
||||
* We know that the index predicate must have been implied by the
|
||||
* query condition as a whole, but it may or may not be implied by
|
||||
* the conditions that got pushed into the bitmapqual. Avoid
|
||||
* generating redundant conditions.
|
||||
*/
|
||||
if (!predicate_implied_by(list_make1(pred), ipath->indexclauses))
|
||||
{
|
||||
@@ -1244,8 +1245,8 @@ create_tidscan_plan(PlannerInfo *root, TidPath *best_path,
|
||||
scan_clauses = extract_actual_clauses(scan_clauses, false);
|
||||
|
||||
/*
|
||||
* Remove any clauses that are TID quals. This is a bit tricky since
|
||||
* the tidquals list has implicit OR semantics.
|
||||
* Remove any clauses that are TID quals. This is a bit tricky since the
|
||||
* tidquals list has implicit OR semantics.
|
||||
*/
|
||||
ortidquals = best_path->tidquals;
|
||||
if (list_length(ortidquals) > 1)
|
||||
@@ -1333,7 +1334,7 @@ create_functionscan_plan(PlannerInfo *root, Path *best_path,
|
||||
*/
|
||||
static ValuesScan *
|
||||
create_valuesscan_plan(PlannerInfo *root, Path *best_path,
|
||||
List *tlist, List *scan_clauses)
|
||||
List *tlist, List *scan_clauses)
|
||||
{
|
||||
ValuesScan *scan_plan;
|
||||
Index scan_relid = best_path->parent->relid;
|
||||
@@ -1411,9 +1412,9 @@ create_nestloop_plan(PlannerInfo *root,
|
||||
* join quals; failing to prove that doesn't result in an incorrect
|
||||
* plan. It is the right way to proceed because adding more quals to
|
||||
* the stuff we got from the original query would just make it harder
|
||||
* to detect duplication. (Also, to change this we'd have to be
|
||||
* wary of UPDATE/DELETE/SELECT FOR UPDATE target relations; see
|
||||
* notes above about EvalPlanQual.)
|
||||
* to detect duplication. (Also, to change this we'd have to be wary
|
||||
* of UPDATE/DELETE/SELECT FOR UPDATE target relations; see notes
|
||||
* above about EvalPlanQual.)
|
||||
*/
|
||||
BitmapHeapPath *innerpath = (BitmapHeapPath *) best_path->innerjoinpath;
|
||||
|
||||
@@ -1693,7 +1694,7 @@ fix_indexqual_references(List *indexquals, IndexPath *index_path,
|
||||
|
||||
if (IsA(clause, OpExpr))
|
||||
{
|
||||
OpExpr *op = (OpExpr *) clause;
|
||||
OpExpr *op = (OpExpr *) clause;
|
||||
|
||||
if (list_length(op->args) != 2)
|
||||
elog(ERROR, "indexqual clause is not binary opclause");
|
||||
@@ -1718,7 +1719,7 @@ fix_indexqual_references(List *indexquals, IndexPath *index_path,
|
||||
else if (IsA(clause, RowCompareExpr))
|
||||
{
|
||||
RowCompareExpr *rc = (RowCompareExpr *) clause;
|
||||
ListCell *lc;
|
||||
ListCell *lc;
|
||||
|
||||
/*
|
||||
* Check to see if the indexkey is on the right; if so, commute
|
||||
@@ -1734,13 +1735,13 @@ fix_indexqual_references(List *indexquals, IndexPath *index_path,
|
||||
* attribute this is and change the indexkey operand as needed.
|
||||
*
|
||||
* Save the index opclass for only the first column. We will
|
||||
* return the operator and opclass info for just the first
|
||||
* column of the row comparison; the executor will have to
|
||||
* look up the rest if it needs them.
|
||||
* return the operator and opclass info for just the first column
|
||||
* of the row comparison; the executor will have to look up the
|
||||
* rest if it needs them.
|
||||
*/
|
||||
foreach(lc, rc->largs)
|
||||
{
|
||||
Oid tmp_opclass;
|
||||
Oid tmp_opclass;
|
||||
|
||||
lfirst(lc) = fix_indexqual_operand(lfirst(lc),
|
||||
index,
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/plan/initsplan.c,v 1.122 2006/09/19 22:49:52 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/plan/initsplan.c,v 1.123 2006/10/04 00:29:54 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -40,10 +40,10 @@ int join_collapse_limit;
|
||||
static void add_vars_to_targetlist(PlannerInfo *root, List *vars,
|
||||
Relids where_needed);
|
||||
static List *deconstruct_recurse(PlannerInfo *root, Node *jtnode,
|
||||
bool below_outer_join, Relids *qualscope);
|
||||
bool below_outer_join, Relids *qualscope);
|
||||
static OuterJoinInfo *make_outerjoininfo(PlannerInfo *root,
|
||||
Relids left_rels, Relids right_rels,
|
||||
bool is_full_join, Node *clause);
|
||||
Relids left_rels, Relids right_rels,
|
||||
bool is_full_join, Node *clause);
|
||||
static void distribute_qual_to_rels(PlannerInfo *root, Node *clause,
|
||||
bool is_pushed_down,
|
||||
bool is_deduced,
|
||||
@@ -71,12 +71,12 @@ static void check_hashjoinable(RestrictInfo *restrictinfo);
|
||||
* appearing in the jointree.
|
||||
*
|
||||
* The initial invocation must pass root->parse->jointree as the value of
|
||||
* jtnode. Internally, the function recurses through the jointree.
|
||||
* jtnode. Internally, the function recurses through the jointree.
|
||||
*
|
||||
* At the end of this process, there should be one baserel RelOptInfo for
|
||||
* every non-join RTE that is used in the query. Therefore, this routine
|
||||
* is the only place that should call build_simple_rel with reloptkind
|
||||
* RELOPT_BASEREL. (Note: build_simple_rel recurses internally to build
|
||||
* RELOPT_BASEREL. (Note: build_simple_rel recurses internally to build
|
||||
* "other rel" RelOptInfos for the members of any appendrels we find here.)
|
||||
*/
|
||||
void
|
||||
@@ -181,7 +181,7 @@ add_vars_to_targetlist(PlannerInfo *root, List *vars, Relids where_needed)
|
||||
* deconstruct_jointree
|
||||
* Recursively scan the query's join tree for WHERE and JOIN/ON qual
|
||||
* clauses, and add these to the appropriate restrictinfo and joininfo
|
||||
* lists belonging to base RelOptInfos. Also, add OuterJoinInfo nodes
|
||||
* lists belonging to base RelOptInfos. Also, add OuterJoinInfo nodes
|
||||
* to root->oj_info_list for any outer joins appearing in the query tree.
|
||||
* Return a "joinlist" data structure showing the join order decisions
|
||||
* that need to be made by make_one_rel().
|
||||
@@ -198,9 +198,9 @@ add_vars_to_targetlist(PlannerInfo *root, List *vars, Relids where_needed)
|
||||
* be evaluated at the lowest level where all the variables it mentions are
|
||||
* available. However, we cannot push a qual down into the nullable side(s)
|
||||
* of an outer join since the qual might eliminate matching rows and cause a
|
||||
* NULL row to be incorrectly emitted by the join. Therefore, we artificially
|
||||
* NULL row to be incorrectly emitted by the join. Therefore, we artificially
|
||||
* OR the minimum-relids of such an outer join into the required_relids of
|
||||
* clauses appearing above it. This forces those clauses to be delayed until
|
||||
* clauses appearing above it. This forces those clauses to be delayed until
|
||||
* application of the outer join (or maybe even higher in the join tree).
|
||||
*/
|
||||
List *
|
||||
@@ -258,20 +258,19 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join,
|
||||
ListCell *l;
|
||||
|
||||
/*
|
||||
* First, recurse to handle child joins. We collapse subproblems
|
||||
* into a single joinlist whenever the resulting joinlist wouldn't
|
||||
* exceed from_collapse_limit members. Also, always collapse
|
||||
* one-element subproblems, since that won't lengthen the joinlist
|
||||
* anyway.
|
||||
* First, recurse to handle child joins. We collapse subproblems into
|
||||
* a single joinlist whenever the resulting joinlist wouldn't exceed
|
||||
* from_collapse_limit members. Also, always collapse one-element
|
||||
* subproblems, since that won't lengthen the joinlist anyway.
|
||||
*/
|
||||
*qualscope = NULL;
|
||||
joinlist = NIL;
|
||||
remaining = list_length(f->fromlist);
|
||||
foreach(l, f->fromlist)
|
||||
{
|
||||
Relids sub_qualscope;
|
||||
List *sub_joinlist;
|
||||
int sub_members;
|
||||
Relids sub_qualscope;
|
||||
List *sub_joinlist;
|
||||
int sub_members;
|
||||
|
||||
sub_joinlist = deconstruct_recurse(root, lfirst(l),
|
||||
below_outer_join,
|
||||
@@ -407,7 +406,8 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join,
|
||||
(list_length(leftjoinlist) + list_length(rightjoinlist) <=
|
||||
join_collapse_limit))
|
||||
joinlist = list_concat(leftjoinlist, rightjoinlist);
|
||||
else /* force the join order at this node */
|
||||
else
|
||||
/* force the join order at this node */
|
||||
joinlist = list_make1(list_make2(leftjoinlist, rightjoinlist));
|
||||
}
|
||||
else
|
||||
@@ -454,9 +454,9 @@ make_outerjoininfo(PlannerInfo *root,
|
||||
* any nullable rel is FOR UPDATE/SHARE.
|
||||
*
|
||||
* You might be wondering why this test isn't made far upstream in the
|
||||
* parser. It's because the parser hasn't got enough info --- consider
|
||||
* FOR UPDATE applied to a view. Only after rewriting and flattening
|
||||
* do we know whether the view contains an outer join.
|
||||
* parser. It's because the parser hasn't got enough info --- consider
|
||||
* FOR UPDATE applied to a view. Only after rewriting and flattening do
|
||||
* we know whether the view contains an outer join.
|
||||
*/
|
||||
foreach(l, root->parse->rowMarks)
|
||||
{
|
||||
@@ -475,7 +475,7 @@ make_outerjoininfo(PlannerInfo *root,
|
||||
{
|
||||
ojinfo->min_lefthand = left_rels;
|
||||
ojinfo->min_righthand = right_rels;
|
||||
ojinfo->lhs_strict = false; /* don't care about this */
|
||||
ojinfo->lhs_strict = false; /* don't care about this */
|
||||
return ojinfo;
|
||||
}
|
||||
|
||||
@@ -494,19 +494,19 @@ make_outerjoininfo(PlannerInfo *root,
|
||||
ojinfo->lhs_strict = bms_overlap(strict_relids, left_rels);
|
||||
|
||||
/*
|
||||
* Required LHS is basically the LHS rels mentioned in the clause...
|
||||
* but if there aren't any, punt and make it the full LHS, to avoid
|
||||
* having an empty min_lefthand which will confuse later processing.
|
||||
* (We don't try to be smart about such cases, just correct.)
|
||||
* We may have to add more rels based on lower outer joins; see below.
|
||||
* Required LHS is basically the LHS rels mentioned in the clause... but
|
||||
* if there aren't any, punt and make it the full LHS, to avoid having an
|
||||
* empty min_lefthand which will confuse later processing. (We don't try
|
||||
* to be smart about such cases, just correct.) We may have to add more
|
||||
* rels based on lower outer joins; see below.
|
||||
*/
|
||||
ojinfo->min_lefthand = bms_intersect(clause_relids, left_rels);
|
||||
if (bms_is_empty(ojinfo->min_lefthand))
|
||||
ojinfo->min_lefthand = bms_copy(left_rels);
|
||||
|
||||
/*
|
||||
* Required RHS is normally the full set of RHS rels. Sometimes we
|
||||
* can exclude some, see below.
|
||||
* Required RHS is normally the full set of RHS rels. Sometimes we can
|
||||
* exclude some, see below.
|
||||
*/
|
||||
ojinfo->min_righthand = bms_copy(right_rels);
|
||||
|
||||
@@ -532,6 +532,7 @@ make_outerjoininfo(PlannerInfo *root,
|
||||
ojinfo->min_lefthand = bms_add_members(ojinfo->min_lefthand,
|
||||
otherinfo->min_righthand);
|
||||
}
|
||||
|
||||
/*
|
||||
* For a lower OJ in our RHS, if our join condition does not use the
|
||||
* lower join's RHS and the lower OJ's join condition is strict, we
|
||||
@@ -630,23 +631,23 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause,
|
||||
* If the clause is an outer-join clause, we must force it to the OJ's
|
||||
* semantic level to preserve semantics.
|
||||
*
|
||||
* Otherwise, when the clause contains volatile functions, we force it
|
||||
* to be evaluated at its original syntactic level. This preserves the
|
||||
* Otherwise, when the clause contains volatile functions, we force it to
|
||||
* be evaluated at its original syntactic level. This preserves the
|
||||
* expected semantics.
|
||||
*
|
||||
* When the clause contains no volatile functions either, it is actually
|
||||
* a pseudoconstant clause that will not change value during any one
|
||||
* execution of the plan, and hence can be used as a one-time qual in
|
||||
* a gating Result plan node. We put such a clause into the regular
|
||||
* When the clause contains no volatile functions either, it is actually a
|
||||
* pseudoconstant clause that will not change value during any one
|
||||
* execution of the plan, and hence can be used as a one-time qual in a
|
||||
* gating Result plan node. We put such a clause into the regular
|
||||
* RestrictInfo lists for the moment, but eventually createplan.c will
|
||||
* pull it out and make a gating Result node immediately above whatever
|
||||
* plan node the pseudoconstant clause is assigned to. It's usually
|
||||
* best to put a gating node as high in the plan tree as possible.
|
||||
* If we are not below an outer join, we can actually push the
|
||||
* pseudoconstant qual all the way to the top of the tree. If we are
|
||||
* below an outer join, we leave the qual at its original syntactic level
|
||||
* (we could push it up to just below the outer join, but that seems more
|
||||
* complex than it's worth).
|
||||
* plan node the pseudoconstant clause is assigned to. It's usually best
|
||||
* to put a gating node as high in the plan tree as possible. If we are
|
||||
* not below an outer join, we can actually push the pseudoconstant qual
|
||||
* all the way to the top of the tree. If we are below an outer join, we
|
||||
* leave the qual at its original syntactic level (we could push it up to
|
||||
* just below the outer join, but that seems more complex than it's
|
||||
* worth).
|
||||
*/
|
||||
if (bms_is_empty(relids))
|
||||
{
|
||||
@@ -793,8 +794,8 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause,
|
||||
* Mark the qual as "pushed down" if it can be applied at a level below
|
||||
* its original syntactic level. This allows us to distinguish original
|
||||
* JOIN/ON quals from higher-level quals pushed down to the same joinrel.
|
||||
* A qual originating from WHERE is always considered "pushed down".
|
||||
* Note that for an outer-join qual, we have to compare to ojscope not
|
||||
* A qual originating from WHERE is always considered "pushed down". Note
|
||||
* that for an outer-join qual, we have to compare to ojscope not
|
||||
* qualscope.
|
||||
*/
|
||||
if (!is_pushed_down)
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/plan/planagg.c,v 1.21 2006/08/12 02:52:04 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/plan/planagg.c,v 1.22 2006/10/04 00:29:54 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -217,7 +217,7 @@ find_minmax_aggs_walker(Node *node, List **context)
|
||||
{
|
||||
Aggref *aggref = (Aggref *) node;
|
||||
Oid aggsortop;
|
||||
Expr *curTarget;
|
||||
Expr *curTarget;
|
||||
MinMaxAggInfo *info;
|
||||
ListCell *l;
|
||||
|
||||
@@ -464,7 +464,7 @@ make_agg_subplan(PlannerInfo *root, MinMaxAggInfo *info)
|
||||
subparse->limitOffset = NULL;
|
||||
subparse->limitCount = (Node *) makeConst(INT8OID, sizeof(int64),
|
||||
Int64GetDatum(1),
|
||||
false, false /* not by val */);
|
||||
false, false /* not by val */ );
|
||||
|
||||
/*
|
||||
* Generate the plan for the subquery. We already have a Path for the
|
||||
@@ -478,9 +478,9 @@ make_agg_subplan(PlannerInfo *root, MinMaxAggInfo *info)
|
||||
* in our cost estimates. But that looks painful, and in most cases the
|
||||
* fraction of NULLs isn't high enough to change the decision.
|
||||
*
|
||||
* The NOT NULL qual has to go on the actual indexscan; create_plan
|
||||
* might have stuck a gating Result atop that, if there were any
|
||||
* pseudoconstant quals.
|
||||
* The NOT NULL qual has to go on the actual indexscan; create_plan might
|
||||
* have stuck a gating Result atop that, if there were any pseudoconstant
|
||||
* quals.
|
||||
*/
|
||||
plan = create_plan(&subroot, (Path *) info->path);
|
||||
|
||||
|
@@ -14,7 +14,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/plan/planmain.c,v 1.96 2006/09/19 22:49:52 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/plan/planmain.c,v 1.97 2006/10/04 00:29:54 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -126,8 +126,8 @@ query_planner(PlannerInfo *root, List *tlist, double tuple_fraction,
|
||||
/*
|
||||
* Construct RelOptInfo nodes for all base relations in query, and
|
||||
* indirectly for all appendrel member relations ("other rels"). This
|
||||
* will give us a RelOptInfo for every "simple" (non-join) rel involved
|
||||
* in the query.
|
||||
* will give us a RelOptInfo for every "simple" (non-join) rel involved in
|
||||
* the query.
|
||||
*
|
||||
* Note: the reason we find the rels by searching the jointree and
|
||||
* appendrel list, rather than just scanning the rangetable, is that the
|
||||
@@ -137,11 +137,11 @@ query_planner(PlannerInfo *root, List *tlist, double tuple_fraction,
|
||||
add_base_rels_to_query(root, (Node *) parse->jointree);
|
||||
|
||||
/*
|
||||
* We should now have size estimates for every actual table involved
|
||||
* in the query, so we can compute total_table_pages. Note that
|
||||
* appendrels are not double-counted here, even though we don't bother
|
||||
* to distinguish RelOptInfos for appendrel parents, because the parents
|
||||
* will still have size zero.
|
||||
* We should now have size estimates for every actual table involved in
|
||||
* the query, so we can compute total_table_pages. Note that appendrels
|
||||
* are not double-counted here, even though we don't bother to distinguish
|
||||
* RelOptInfos for appendrel parents, because the parents will still have
|
||||
* size zero.
|
||||
*
|
||||
* XXX if a table is self-joined, we will count it once per appearance,
|
||||
* which perhaps is the wrong thing ... but that's not completely clear,
|
||||
@@ -155,7 +155,7 @@ query_planner(PlannerInfo *root, List *tlist, double tuple_fraction,
|
||||
if (brel == NULL)
|
||||
continue;
|
||||
|
||||
Assert(brel->relid == rti); /* sanity check on array */
|
||||
Assert(brel->relid == rti); /* sanity check on array */
|
||||
|
||||
total_pages += (double) brel->pages;
|
||||
}
|
||||
@@ -165,8 +165,8 @@ query_planner(PlannerInfo *root, List *tlist, double tuple_fraction,
|
||||
* Examine the targetlist and qualifications, adding entries to baserel
|
||||
* targetlists for all referenced Vars. Restrict and join clauses are
|
||||
* added to appropriate lists belonging to the mentioned relations. We
|
||||
* also build lists of equijoined keys for pathkey construction, and
|
||||
* form a target joinlist for make_one_rel() to work from.
|
||||
* also build lists of equijoined keys for pathkey construction, and form
|
||||
* a target joinlist for make_one_rel() to work from.
|
||||
*
|
||||
* Note: all subplan nodes will have "flat" (var-only) tlists. This
|
||||
* implies that all expression evaluations are done at the root of the
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.208 2006/08/12 02:52:04 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.209 2006/10/04 00:29:54 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -427,9 +427,9 @@ preprocess_expression(PlannerInfo *root, Node *expr, int kind)
|
||||
/*
|
||||
* If the query has any join RTEs, replace join alias variables with
|
||||
* base-relation variables. We must do this before sublink processing,
|
||||
* else sublinks expanded out from join aliases wouldn't get processed.
|
||||
* We can skip it in VALUES lists, however, since they can't contain
|
||||
* any Vars at all.
|
||||
* else sublinks expanded out from join aliases wouldn't get processed. We
|
||||
* can skip it in VALUES lists, however, since they can't contain any Vars
|
||||
* at all.
|
||||
*/
|
||||
if (root->hasJoinRTEs && kind != EXPRKIND_VALUES)
|
||||
expr = flatten_join_alias_vars(root, expr);
|
||||
@@ -450,8 +450,8 @@ preprocess_expression(PlannerInfo *root, Node *expr, int kind)
|
||||
* still must do it for quals (to get AND/OR flatness); and if we are in a
|
||||
* subquery we should not assume it will be done only once.
|
||||
*
|
||||
* For VALUES lists we never do this at all, again on the grounds that
|
||||
* we should optimize for one-time evaluation.
|
||||
* For VALUES lists we never do this at all, again on the grounds that we
|
||||
* should optimize for one-time evaluation.
|
||||
*/
|
||||
if (kind != EXPRKIND_VALUES &&
|
||||
(root->parse->jointree->fromlist != NIL ||
|
||||
@@ -593,8 +593,8 @@ inheritance_planner(PlannerInfo *root)
|
||||
subplan = grouping_planner(&subroot, 0.0 /* retrieve all tuples */ );
|
||||
|
||||
/*
|
||||
* If this child rel was excluded by constraint exclusion, exclude
|
||||
* it from the plan.
|
||||
* If this child rel was excluded by constraint exclusion, exclude it
|
||||
* from the plan.
|
||||
*/
|
||||
if (is_dummy_plan(subplan))
|
||||
continue;
|
||||
@@ -1098,12 +1098,12 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
|
||||
|
||||
/*
|
||||
* Deal with the RETURNING clause if any. It's convenient to pass the
|
||||
* returningList through setrefs.c now rather than at top level (if
|
||||
* we waited, handling inherited UPDATE/DELETE would be much harder).
|
||||
* returningList through setrefs.c now rather than at top level (if we
|
||||
* waited, handling inherited UPDATE/DELETE would be much harder).
|
||||
*/
|
||||
if (parse->returningList)
|
||||
{
|
||||
List *rlist;
|
||||
List *rlist;
|
||||
|
||||
rlist = set_returning_clause_references(parse->returningList,
|
||||
result_plan,
|
||||
@@ -1132,11 +1132,11 @@ is_dummy_plan(Plan *plan)
|
||||
{
|
||||
if (IsA(plan, Result))
|
||||
{
|
||||
List *rcqual = (List *) ((Result *) plan)->resconstantqual;
|
||||
List *rcqual = (List *) ((Result *) plan)->resconstantqual;
|
||||
|
||||
if (list_length(rcqual) == 1)
|
||||
{
|
||||
Const *constqual = (Const *) linitial(rcqual);
|
||||
Const *constqual = (Const *) linitial(rcqual);
|
||||
|
||||
if (constqual && IsA(constqual, Const))
|
||||
{
|
||||
|
@@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/plan/setrefs.c,v 1.125 2006/08/28 14:32:41 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/plan/setrefs.c,v 1.126 2006/10/04 00:29:54 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -453,13 +453,13 @@ trivial_subqueryscan(SubqueryScan *plan)
|
||||
return false; /* tlist doesn't match junk status */
|
||||
|
||||
/*
|
||||
* We accept either a Var referencing the corresponding element of
|
||||
* the subplan tlist, or a Const equaling the subplan element.
|
||||
* See generate_setop_tlist() for motivation.
|
||||
* We accept either a Var referencing the corresponding element of the
|
||||
* subplan tlist, or a Const equaling the subplan element. See
|
||||
* generate_setop_tlist() for motivation.
|
||||
*/
|
||||
if (ptle->expr && IsA(ptle->expr, Var))
|
||||
{
|
||||
Var *var = (Var *) ptle->expr;
|
||||
Var *var = (Var *) ptle->expr;
|
||||
|
||||
Assert(var->varno == plan->scan.scanrelid);
|
||||
Assert(var->varlevelsup == 0);
|
||||
@@ -793,7 +793,7 @@ set_join_references(Join *join)
|
||||
*
|
||||
* To handle bitmap-scan plan trees, we have to be able to recurse down
|
||||
* to the bottom BitmapIndexScan nodes; likewise, appendrel indexscans
|
||||
* require recursing through Append nodes. This is split out as a separate
|
||||
* require recursing through Append nodes. This is split out as a separate
|
||||
* function so that it can recurse.
|
||||
*/
|
||||
static void
|
||||
@@ -1339,7 +1339,7 @@ replace_vars_with_subplan_refs_mutator(Node *node,
|
||||
* adjust any Vars that refer to other tables to reference junk tlist
|
||||
* entries in the top plan's targetlist. Vars referencing the result
|
||||
* table should be left alone, however (the executor will evaluate them
|
||||
* using the actual heap tuple, after firing triggers if any). In the
|
||||
* using the actual heap tuple, after firing triggers if any). In the
|
||||
* adjusted RETURNING list, result-table Vars will still have their
|
||||
* original varno, but Vars for other rels will have varno OUTER.
|
||||
*
|
||||
@@ -1359,8 +1359,8 @@ set_returning_clause_references(List *rlist,
|
||||
|
||||
/*
|
||||
* We can perform the desired Var fixup by abusing the join_references
|
||||
* machinery that normally handles inner indexscan fixup. We search
|
||||
* the top plan's targetlist for Vars of non-result relations, and use
|
||||
* machinery that normally handles inner indexscan fixup. We search the
|
||||
* top plan's targetlist for Vars of non-result relations, and use
|
||||
* join_references to convert RETURNING Vars into references to those
|
||||
* tlist entries, while leaving result-rel Vars as-is.
|
||||
*/
|
||||
|
@@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.111 2006/08/02 01:59:46 joe Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.112 2006/10/04 00:29:54 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -85,10 +85,10 @@ typedef struct finalize_primnode_context
|
||||
|
||||
|
||||
static Node *convert_testexpr(Node *testexpr,
|
||||
int rtindex,
|
||||
List **righthandIds);
|
||||
int rtindex,
|
||||
List **righthandIds);
|
||||
static Node *convert_testexpr_mutator(Node *node,
|
||||
convert_testexpr_context *context);
|
||||
convert_testexpr_context *context);
|
||||
static bool subplan_is_hashable(SubLink *slink, SubPlan *node);
|
||||
static bool hash_ok_operator(OpExpr *expr);
|
||||
static Node *replace_correlation_vars_mutator(Node *node, void *context);
|
||||
@@ -498,13 +498,13 @@ convert_testexpr_mutator(Node *node,
|
||||
return NULL;
|
||||
if (IsA(node, Param))
|
||||
{
|
||||
Param *param = (Param *) node;
|
||||
Param *param = (Param *) node;
|
||||
|
||||
if (param->paramkind == PARAM_SUBLINK)
|
||||
{
|
||||
/*
|
||||
* We expect to encounter the Params in column-number sequence.
|
||||
* We could handle non-sequential order if necessary, but for now
|
||||
* We expect to encounter the Params in column-number sequence. We
|
||||
* could handle non-sequential order if necessary, but for now
|
||||
* there's no need. (This is also a useful cross-check that we
|
||||
* aren't finding any unexpected Params.)
|
||||
*/
|
||||
@@ -514,13 +514,14 @@ convert_testexpr_mutator(Node *node,
|
||||
if (context->rtindex)
|
||||
{
|
||||
/* Make the Var node representing the subplan's result */
|
||||
Var *newvar;
|
||||
Var *newvar;
|
||||
|
||||
newvar = makeVar(context->rtindex,
|
||||
param->paramid,
|
||||
param->paramtype,
|
||||
-1,
|
||||
0);
|
||||
|
||||
/*
|
||||
* Copy it for caller. NB: we need a copy to avoid having
|
||||
* doubly-linked substructure in the modified parse tree.
|
||||
@@ -584,10 +585,10 @@ subplan_is_hashable(SubLink *slink, SubPlan *node)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* The estimated size of the subquery result must fit in work_mem.
|
||||
* (Note: we use sizeof(HeapTupleHeaderData) here even though the tuples
|
||||
* will actually be stored as MinimalTuples; this provides some fudge
|
||||
* factor for hashtable overhead.)
|
||||
* The estimated size of the subquery result must fit in work_mem. (Note:
|
||||
* we use sizeof(HeapTupleHeaderData) here even though the tuples will
|
||||
* actually be stored as MinimalTuples; this provides some fudge factor
|
||||
* for hashtable overhead.)
|
||||
*/
|
||||
subquery_size = node->plan->plan_rows *
|
||||
(MAXALIGN(node->plan->plan_width) + MAXALIGN(sizeof(HeapTupleHeaderData)));
|
||||
@@ -616,7 +617,7 @@ subplan_is_hashable(SubLink *slink, SubPlan *node)
|
||||
{
|
||||
foreach(l, ((BoolExpr *) slink->testexpr)->args)
|
||||
{
|
||||
Node *andarg = (Node *) lfirst(l);
|
||||
Node *andarg = (Node *) lfirst(l);
|
||||
|
||||
if (!IsA(andarg, OpExpr))
|
||||
return false; /* probably can't happen */
|
||||
@@ -686,8 +687,8 @@ convert_IN_to_join(PlannerInfo *root, SubLink *sublink)
|
||||
return NULL;
|
||||
if (sublink->testexpr && IsA(sublink->testexpr, OpExpr))
|
||||
{
|
||||
List *opclasses;
|
||||
List *opstrats;
|
||||
List *opclasses;
|
||||
List *opstrats;
|
||||
|
||||
get_op_btree_interpretation(((OpExpr *) sublink->testexpr)->opno,
|
||||
&opclasses, &opstrats);
|
||||
|
@@ -15,7 +15,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/prep/prepjointree.c,v 1.43 2006/08/19 02:48:53 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/prep/prepjointree.c,v 1.44 2006/10/04 00:29:54 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -40,20 +40,20 @@ typedef struct reduce_outer_joins_state
|
||||
} reduce_outer_joins_state;
|
||||
|
||||
static Node *pull_up_simple_subquery(PlannerInfo *root, Node *jtnode,
|
||||
RangeTblEntry *rte,
|
||||
bool below_outer_join,
|
||||
bool append_rel_member);
|
||||
RangeTblEntry *rte,
|
||||
bool below_outer_join,
|
||||
bool append_rel_member);
|
||||
static Node *pull_up_simple_union_all(PlannerInfo *root, Node *jtnode,
|
||||
RangeTblEntry *rte);
|
||||
RangeTblEntry *rte);
|
||||
static void pull_up_union_leaf_queries(Node *setOp, PlannerInfo *root,
|
||||
int parentRTindex, Query *setOpQuery);
|
||||
int parentRTindex, Query *setOpQuery);
|
||||
static void make_setop_translation_lists(Query *query,
|
||||
Index newvarno,
|
||||
List **col_mappings, List **translated_vars);
|
||||
static bool is_simple_subquery(Query *subquery);
|
||||
static bool is_simple_union_all(Query *subquery);
|
||||
static bool is_simple_union_all_recurse(Node *setOp, Query *setOpQuery,
|
||||
List *colTypes);
|
||||
List *colTypes);
|
||||
static bool has_nullable_targetlist(Query *subquery);
|
||||
static bool is_safe_append_member(Query *subquery);
|
||||
static void resolvenew_in_jointree(Node *jtnode, int varno,
|
||||
@@ -66,7 +66,7 @@ static void reduce_outer_joins_pass2(Node *jtnode,
|
||||
static void fix_in_clause_relids(List *in_info_list, int varno,
|
||||
Relids subrelids);
|
||||
static void fix_append_rel_relids(List *append_rel_list, int varno,
|
||||
Relids subrelids);
|
||||
Relids subrelids);
|
||||
static Node *find_jointree_node_for_rel(Node *jtnode, int relid);
|
||||
|
||||
|
||||
@@ -136,7 +136,7 @@ pull_up_IN_clauses(PlannerInfo *root, Node *node)
|
||||
* side of an outer join. This restricts what we can do.
|
||||
*
|
||||
* append_rel_member is true if we are looking at a member subquery of
|
||||
* an append relation. This puts some different restrictions on what
|
||||
* an append relation. This puts some different restrictions on what
|
||||
* we can do.
|
||||
*
|
||||
* A tricky aspect of this code is that if we pull up a subquery we have
|
||||
@@ -173,8 +173,8 @@ pull_up_subqueries(PlannerInfo *root, Node *jtnode,
|
||||
* variables evaluated at the right place in the modified plan tree.
|
||||
* Fix it someday.
|
||||
*
|
||||
* If we are looking at an append-relation member, we can't pull
|
||||
* it up unless is_safe_append_member says so.
|
||||
* If we are looking at an append-relation member, we can't pull it up
|
||||
* unless is_safe_append_member says so.
|
||||
*/
|
||||
if (rte->rtekind == RTE_SUBQUERY &&
|
||||
is_simple_subquery(rte->subquery) &&
|
||||
@@ -186,14 +186,15 @@ pull_up_subqueries(PlannerInfo *root, Node *jtnode,
|
||||
|
||||
/*
|
||||
* Alternatively, is it a simple UNION ALL subquery? If so, flatten
|
||||
* into an "append relation". We can do this regardless of nullability
|
||||
* considerations since this transformation does not result in
|
||||
* propagating non-Var expressions into upper levels of the query.
|
||||
* into an "append relation". We can do this regardless of
|
||||
* nullability considerations since this transformation does not
|
||||
* result in propagating non-Var expressions into upper levels of the
|
||||
* query.
|
||||
*
|
||||
* It's also safe to do this regardless of whether this query is
|
||||
* itself an appendrel member. (If you're thinking we should try
|
||||
* to flatten the two levels of appendrel together, you're right;
|
||||
* but we handle that in set_append_rel_pathlist, not here.)
|
||||
* itself an appendrel member. (If you're thinking we should try to
|
||||
* flatten the two levels of appendrel together, you're right; but we
|
||||
* handle that in set_append_rel_pathlist, not here.)
|
||||
*/
|
||||
if (rte->rtekind == RTE_SUBQUERY &&
|
||||
is_simple_union_all(rte->subquery))
|
||||
@@ -258,7 +259,7 @@ pull_up_subqueries(PlannerInfo *root, Node *jtnode,
|
||||
* Attempt to pull up a single simple subquery.
|
||||
*
|
||||
* jtnode is a RangeTblRef that has been tentatively identified as a simple
|
||||
* subquery by pull_up_subqueries. We return the replacement jointree node,
|
||||
* subquery by pull_up_subqueries. We return the replacement jointree node,
|
||||
* or jtnode itself if we determine that the subquery can't be pulled up after
|
||||
* all.
|
||||
*/
|
||||
@@ -275,11 +276,10 @@ pull_up_simple_subquery(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte,
|
||||
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(rte->subquery);
|
||||
|
||||
@@ -287,8 +287,8 @@ pull_up_simple_subquery(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte,
|
||||
* 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?
|
||||
* subquery_planner(). Can we refactor to avoid code duplication, or
|
||||
* would that just make things uglier?
|
||||
*/
|
||||
subroot = makeNode(PlannerInfo);
|
||||
subroot->parse = subquery;
|
||||
@@ -296,12 +296,12 @@ pull_up_simple_subquery(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte,
|
||||
subroot->append_rel_list = NIL;
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
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
|
||||
@@ -310,19 +310,19 @@ pull_up_simple_subquery(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte,
|
||||
*
|
||||
* Note: below_outer_join = 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. Likewise, we say we aren't handling
|
||||
* an appendrel member.
|
||||
* slate for outer-join semantics. Likewise, we say we aren't handling an
|
||||
* appendrel member.
|
||||
*/
|
||||
subquery->jointree = (FromExpr *)
|
||||
pull_up_subqueries(subroot, (Node *) subquery->jointree, false, 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 in pull_up_subqueries.
|
||||
* 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 in
|
||||
* pull_up_subqueries.
|
||||
*/
|
||||
if (is_simple_subquery(subquery) &&
|
||||
(!below_outer_join || has_nullable_targetlist(subquery)) &&
|
||||
@@ -335,18 +335,18 @@ pull_up_simple_subquery(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte,
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
/*
|
||||
* Adjust level-0 varnos in subquery so that we can append its
|
||||
* rangetable to upper query's. We have to fix the subquery's
|
||||
* in_info_list and append_rel_list, as well.
|
||||
* Adjust level-0 varnos in subquery so that we can append its rangetable
|
||||
* to upper query's. We have to fix the subquery's in_info_list and
|
||||
* append_rel_list, as well.
|
||||
*/
|
||||
rtoffset = list_length(parse->rtable);
|
||||
OffsetVarNodes((Node *) subquery, rtoffset, 0);
|
||||
@@ -354,18 +354,18 @@ pull_up_simple_subquery(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte,
|
||||
OffsetVarNodes((Node *) subroot->append_rel_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);
|
||||
IncrementVarSublevelsUp((Node *) subroot->append_rel_list, -1, 1);
|
||||
|
||||
/*
|
||||
* 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.)
|
||||
* 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.)
|
||||
*/
|
||||
subtlist = subquery->targetList;
|
||||
parse->targetList = (List *)
|
||||
@@ -404,27 +404,27 @@ pull_up_simple_subquery(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte,
|
||||
}
|
||||
|
||||
/*
|
||||
* 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);
|
||||
|
||||
/*
|
||||
* Pull up any FOR UPDATE/SHARE markers, too. (OffsetVarNodes
|
||||
* already adjusted the marker rtindexes, so just concat the lists.)
|
||||
* Pull up any FOR UPDATE/SHARE markers, too. (OffsetVarNodes already
|
||||
* adjusted the marker rtindexes, so just concat the lists.)
|
||||
*/
|
||||
parse->rowMarks = list_concat(parse->rowMarks, subquery->rowMarks);
|
||||
|
||||
/*
|
||||
* 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.)
|
||||
*
|
||||
* Likewise, relids appearing in AppendRelInfo nodes have to be fixed
|
||||
* (but we took care of their translated_vars lists above). We already
|
||||
* checked that this won't require introducing multiple subrelids into
|
||||
* the single-slot AppendRelInfo structs.
|
||||
* Likewise, relids appearing in AppendRelInfo nodes have to be fixed (but
|
||||
* we took care of their translated_vars lists above). We already checked
|
||||
* that this won't require introducing multiple subrelids into the
|
||||
* single-slot AppendRelInfo structs.
|
||||
*/
|
||||
if (root->in_info_list || root->append_rel_list)
|
||||
{
|
||||
@@ -444,8 +444,8 @@ pull_up_simple_subquery(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte,
|
||||
subroot->append_rel_list);
|
||||
|
||||
/*
|
||||
* We don't have to do the equivalent bookkeeping for outer-join
|
||||
* info, because that hasn't been set up yet.
|
||||
* We don't have to do the equivalent bookkeeping for outer-join info,
|
||||
* because that hasn't been set up yet.
|
||||
*/
|
||||
Assert(root->oj_info_list == NIL);
|
||||
Assert(subroot->oj_info_list == NIL);
|
||||
@@ -457,8 +457,8 @@ pull_up_simple_subquery(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte,
|
||||
/* subquery won't be pulled up if it hasAggs, so no work there */
|
||||
|
||||
/*
|
||||
* Return the adjusted subquery jointree to replace the
|
||||
* RangeTblRef entry in parent's jointree.
|
||||
* Return the adjusted subquery jointree to replace the RangeTblRef entry
|
||||
* in parent's jointree.
|
||||
*/
|
||||
return (Node *) subquery->jointree;
|
||||
}
|
||||
@@ -468,7 +468,7 @@ pull_up_simple_subquery(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte,
|
||||
* Pull up a single simple UNION ALL subquery.
|
||||
*
|
||||
* jtnode is a RangeTblRef that has been identified as a simple UNION ALL
|
||||
* subquery by pull_up_subqueries. We pull up the leaf subqueries and
|
||||
* subquery by pull_up_subqueries. We pull up the leaf subqueries and
|
||||
* build an "append relation" for the union set. The result value is just
|
||||
* jtnode, since we don't actually need to change the query jointree.
|
||||
*/
|
||||
@@ -524,9 +524,9 @@ pull_up_union_leaf_queries(Node *setOp, PlannerInfo *root, int parentRTindex,
|
||||
|
||||
/*
|
||||
* Upper-level vars in subquery are now one level closer to their
|
||||
* parent than before. We don't have to worry about offsetting
|
||||
* varnos, though, because any such vars must refer to stuff above
|
||||
* the level of the query we are pulling into.
|
||||
* parent than before. We don't have to worry about offsetting
|
||||
* varnos, though, because any such vars must refer to stuff above the
|
||||
* level of the query we are pulling into.
|
||||
*/
|
||||
IncrementVarSublevelsUp((Node *) subquery, -1, 1);
|
||||
|
||||
@@ -658,9 +658,9 @@ is_simple_subquery(Query *subquery)
|
||||
|
||||
/*
|
||||
* Don't pull up a subquery that has any volatile functions in its
|
||||
* targetlist. Otherwise we might introduce multiple evaluations of
|
||||
* these functions, if they get copied to multiple places in the upper
|
||||
* query, leading to surprising results.
|
||||
* targetlist. Otherwise we might introduce multiple evaluations of these
|
||||
* functions, if they get copied to multiple places in the upper query,
|
||||
* leading to surprising results.
|
||||
*/
|
||||
if (contain_volatile_functions((Node *) subquery->targetList))
|
||||
return false;
|
||||
@@ -799,16 +799,15 @@ is_safe_append_member(Query *subquery)
|
||||
ListCell *l;
|
||||
|
||||
/*
|
||||
* It's only safe to pull up the child if its jointree contains
|
||||
* exactly one RTE, else the AppendRelInfo data structure breaks.
|
||||
* The one base RTE could be buried in several levels of FromExpr,
|
||||
* however.
|
||||
* It's only safe to pull up the child if its jointree contains exactly
|
||||
* one RTE, else the AppendRelInfo data structure breaks. The one base RTE
|
||||
* could be buried in several levels of FromExpr, however.
|
||||
*
|
||||
* Also, the child can't have any WHERE quals because there's no
|
||||
* place to put them in an appendrel. (This is a bit annoying...)
|
||||
* If we didn't need to check this, we'd just test whether
|
||||
* get_relids_in_jointree() yields a singleton set, to be more
|
||||
* consistent with the coding of fix_append_rel_relids().
|
||||
* Also, the child can't have any WHERE quals because there's no place to
|
||||
* put them in an appendrel. (This is a bit annoying...) If we didn't
|
||||
* need to check this, we'd just test whether get_relids_in_jointree()
|
||||
* yields a singleton set, to be more consistent with the coding of
|
||||
* fix_append_rel_relids().
|
||||
*/
|
||||
jtnode = subquery->jointree;
|
||||
while (IsA(jtnode, FromExpr))
|
||||
@@ -825,10 +824,10 @@ is_safe_append_member(Query *subquery)
|
||||
/*
|
||||
* XXX For the moment we also have to insist that the subquery's tlist
|
||||
* includes only simple Vars. This is pretty annoying, but fixing it
|
||||
* seems to require nontrivial changes --- mainly because joinrel
|
||||
* tlists are presently assumed to contain only Vars. Perhaps a
|
||||
* pseudo-variable mechanism similar to the one speculated about
|
||||
* in pull_up_subqueries' comments would help? FIXME someday.
|
||||
* seems to require nontrivial changes --- mainly because joinrel tlists
|
||||
* are presently assumed to contain only Vars. Perhaps a pseudo-variable
|
||||
* mechanism similar to the one speculated about in pull_up_subqueries'
|
||||
* comments would help? FIXME someday.
|
||||
*/
|
||||
foreach(l, subquery->targetList)
|
||||
{
|
||||
@@ -1190,9 +1189,9 @@ fix_append_rel_relids(List *append_rel_list, int varno, Relids subrelids)
|
||||
|
||||
/*
|
||||
* We only want to extract the member relid once, but we mustn't fail
|
||||
* immediately if there are multiple members; it could be that none of
|
||||
* the AppendRelInfo nodes refer to it. So compute it on first use.
|
||||
* Note that bms_singleton_member will complain if set is not singleton.
|
||||
* immediately if there are multiple members; it could be that none of the
|
||||
* AppendRelInfo nodes refer to it. So compute it on first use. Note that
|
||||
* bms_singleton_member will complain if set is not singleton.
|
||||
*/
|
||||
foreach(l, append_rel_list)
|
||||
{
|
||||
|
@@ -25,7 +25,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/prep/prepqual.c,v 1.55 2006/07/14 14:52:21 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/prep/prepqual.c,v 1.56 2006/10/04 00:29:54 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -212,7 +212,7 @@ push_nots(Expr *qual)
|
||||
|
||||
if (negator)
|
||||
{
|
||||
OpExpr *newopexpr = makeNode(OpExpr);
|
||||
OpExpr *newopexpr = makeNode(OpExpr);
|
||||
|
||||
newopexpr->opno = negator;
|
||||
newopexpr->opfuncid = InvalidOid;
|
||||
@@ -228,9 +228,9 @@ push_nots(Expr *qual)
|
||||
{
|
||||
/*
|
||||
* Negate a ScalarArrayOpExpr if there is a negator for its operator;
|
||||
* for example x = ANY (list) becomes x <> ALL (list).
|
||||
* Otherwise, retain the clause as it is (the NOT can't be pushed down
|
||||
* any farther).
|
||||
* for example x = ANY (list) becomes x <> ALL (list). Otherwise,
|
||||
* retain the clause as it is (the NOT can't be pushed down any
|
||||
* farther).
|
||||
*/
|
||||
ScalarArrayOpExpr *saopexpr = (ScalarArrayOpExpr *) qual;
|
||||
Oid negator = get_negator(saopexpr->opno);
|
||||
|
@@ -16,7 +16,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/prep/preptlist.c,v 1.83 2006/08/12 02:52:05 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/prep/preptlist.c,v 1.84 2006/10/04 00:29:55 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -157,13 +157,13 @@ preprocess_targetlist(PlannerInfo *root, List *tlist)
|
||||
/*
|
||||
* If the query has a RETURNING list, add resjunk entries for any Vars
|
||||
* used in RETURNING that belong to other relations. We need to do this
|
||||
* to make these Vars available for the RETURNING calculation. Vars
|
||||
* that belong to the result rel don't need to be added, because they
|
||||
* will be made to refer to the actual heap tuple.
|
||||
* to make these Vars available for the RETURNING calculation. Vars that
|
||||
* belong to the result rel don't need to be added, because they will be
|
||||
* made to refer to the actual heap tuple.
|
||||
*/
|
||||
if (parse->returningList && list_length(parse->rtable) > 1)
|
||||
{
|
||||
List *vars;
|
||||
List *vars;
|
||||
ListCell *l;
|
||||
|
||||
vars = pull_var_clause((Node *) parse->returningList, false);
|
||||
|
@@ -6,14 +6,14 @@
|
||||
*
|
||||
* There are two code paths in the planner for set-operation queries.
|
||||
* If a subquery consists entirely of simple UNION ALL operations, it
|
||||
* is converted into an "append relation". Otherwise, it is handled
|
||||
* is converted into an "append relation". Otherwise, it is handled
|
||||
* by the general code in this module (plan_set_operations and its
|
||||
* subroutines). There is some support code here for the append-relation
|
||||
* case, but most of the heavy lifting for that is done elsewhere,
|
||||
* notably in prepjointree.c and allpaths.c.
|
||||
*
|
||||
* There is also some code here to support planning of queries that use
|
||||
* inheritance (SELECT FROM foo*). Inheritance trees are converted into
|
||||
* inheritance (SELECT FROM foo*). Inheritance trees are converted into
|
||||
* append relations, and thenceforth share code with the UNION ALL case.
|
||||
*
|
||||
*
|
||||
@@ -22,7 +22,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/prep/prepunion.c,v 1.133 2006/08/10 02:36:28 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/prep/prepunion.c,v 1.134 2006/10/04 00:29:55 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -69,14 +69,14 @@ static List *generate_append_tlist(List *colTypes, bool flag,
|
||||
List *input_plans,
|
||||
List *refnames_tlist);
|
||||
static void expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte,
|
||||
Index rti);
|
||||
Index rti);
|
||||
static void make_inh_translation_lists(Relation oldrelation,
|
||||
Relation newrelation,
|
||||
Index newvarno,
|
||||
List **col_mappings,
|
||||
List **translated_vars);
|
||||
Relation newrelation,
|
||||
Index newvarno,
|
||||
List **col_mappings,
|
||||
List **translated_vars);
|
||||
static Node *adjust_appendrel_attrs_mutator(Node *node,
|
||||
AppendRelInfo *context);
|
||||
AppendRelInfo *context);
|
||||
static Relids adjust_relid_set(Relids relids, Index oldrelid, Index newrelid);
|
||||
static List *adjust_inherited_tlist(List *tlist,
|
||||
AppendRelInfo *context);
|
||||
@@ -713,21 +713,21 @@ find_all_inheritors(Oid parentrel)
|
||||
/*
|
||||
* expand_inherited_tables
|
||||
* Expand each rangetable entry that represents an inheritance set
|
||||
* into an "append relation". At the conclusion of this process,
|
||||
* into an "append relation". At the conclusion of this process,
|
||||
* the "inh" flag is set in all and only those RTEs that are append
|
||||
* relation parents.
|
||||
*/
|
||||
void
|
||||
expand_inherited_tables(PlannerInfo *root)
|
||||
{
|
||||
Index nrtes;
|
||||
Index rti;
|
||||
ListCell *rl;
|
||||
Index nrtes;
|
||||
Index rti;
|
||||
ListCell *rl;
|
||||
|
||||
/*
|
||||
* expand_inherited_rtentry may add RTEs to parse->rtable; there is
|
||||
* no need to scan them since they can't have inh=true. So just
|
||||
* scan as far as the original end of the rtable list.
|
||||
* expand_inherited_rtentry may add RTEs to parse->rtable; there is no
|
||||
* need to scan them since they can't have inh=true. So just scan as far
|
||||
* as the original end of the rtable list.
|
||||
*/
|
||||
nrtes = list_length(root->parse->rtable);
|
||||
rl = list_head(root->parse->rtable);
|
||||
@@ -745,7 +745,7 @@ expand_inherited_tables(PlannerInfo *root)
|
||||
* Check whether a rangetable entry represents an inheritance set.
|
||||
* If so, add entries for all the child tables to the query's
|
||||
* rangetable, and build AppendRelInfo nodes for all the child tables
|
||||
* and add them to root->append_rel_list. If not, clear the entry's
|
||||
* and add them to root->append_rel_list. If not, clear the entry's
|
||||
* "inh" flag to prevent later code from looking for AppendRelInfos.
|
||||
*
|
||||
* Note that the original RTE is considered to represent the whole
|
||||
@@ -801,22 +801,22 @@ expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte, Index rti)
|
||||
}
|
||||
|
||||
/*
|
||||
* Must open the parent relation to examine its tupdesc. We need not
|
||||
* lock it since the rewriter already obtained at least AccessShareLock
|
||||
* on each relation used in the query.
|
||||
* Must open the parent relation to examine its tupdesc. We need not lock
|
||||
* it since the rewriter already obtained at least AccessShareLock on each
|
||||
* relation used in the query.
|
||||
*/
|
||||
oldrelation = heap_open(parentOID, NoLock);
|
||||
|
||||
/*
|
||||
* However, for each child relation we add to the query, we must obtain
|
||||
* an appropriate lock, because this will be the first use of those
|
||||
* relations in the parse/rewrite/plan pipeline.
|
||||
* However, for each child relation we add to the query, we must obtain an
|
||||
* appropriate lock, because this will be the first use of those relations
|
||||
* in the parse/rewrite/plan pipeline.
|
||||
*
|
||||
* If the parent relation is the query's result relation, then we need
|
||||
* RowExclusiveLock. Otherwise, check to see if the relation is accessed
|
||||
* FOR UPDATE/SHARE or not. We can't just grab AccessShareLock because
|
||||
* then the executor would be trying to upgrade the lock, leading to
|
||||
* possible deadlocks. (This code should match the parser and rewriter.)
|
||||
* possible deadlocks. (This code should match the parser and rewriter.)
|
||||
*/
|
||||
if (rti == parse->resultRelation)
|
||||
lockmode = RowExclusiveLock;
|
||||
@@ -900,8 +900,8 @@ expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte, Index rti)
|
||||
|
||||
/*
|
||||
* The executor will check the parent table's access permissions when it
|
||||
* examines the parent's added RTE entry. There's no need to check
|
||||
* twice, so turn off access check bits in the original RTE.
|
||||
* examines the parent's added RTE entry. There's no need to check twice,
|
||||
* so turn off access check bits in the original RTE.
|
||||
*/
|
||||
rte->requiredPerms = 0;
|
||||
}
|
||||
@@ -948,8 +948,8 @@ make_inh_translation_lists(Relation oldrelation, Relation newrelation,
|
||||
atttypmod = att->atttypmod;
|
||||
|
||||
/*
|
||||
* When we are generating the "translation list" for the parent
|
||||
* table of an inheritance set, no need to search for matches.
|
||||
* When we are generating the "translation list" for the parent table
|
||||
* of an inheritance set, no need to search for matches.
|
||||
*/
|
||||
if (oldrelation == newrelation)
|
||||
{
|
||||
@@ -964,9 +964,8 @@ make_inh_translation_lists(Relation oldrelation, Relation newrelation,
|
||||
|
||||
/*
|
||||
* Otherwise we have to search for the matching column by name.
|
||||
* There's no guarantee it'll have the same column position,
|
||||
* because of cases like ALTER TABLE ADD COLUMN and multiple
|
||||
* inheritance.
|
||||
* There's no guarantee it'll have the same column position, because
|
||||
* of cases like ALTER TABLE ADD COLUMN and multiple inheritance.
|
||||
*/
|
||||
for (new_attno = 0; new_attno < newnatts; new_attno++)
|
||||
{
|
||||
@@ -979,7 +978,7 @@ make_inh_translation_lists(Relation oldrelation, Relation newrelation,
|
||||
if (atttypid != att->atttypid || atttypmod != att->atttypmod)
|
||||
elog(ERROR, "attribute \"%s\" of relation \"%s\" does not match parent's type",
|
||||
attname, RelationGetRelationName(newrelation));
|
||||
|
||||
|
||||
numbers = lappend_int(numbers, new_attno + 1);
|
||||
vars = lappend(vars, makeVar(newvarno,
|
||||
(AttrNumber) (new_attno + 1),
|
||||
@@ -1060,7 +1059,7 @@ adjust_appendrel_attrs_mutator(Node *node, AppendRelInfo *context)
|
||||
var->varnoold = context->child_relid;
|
||||
if (var->varattno > 0)
|
||||
{
|
||||
Node *newnode;
|
||||
Node *newnode;
|
||||
|
||||
if (var->varattno > list_length(context->translated_vars))
|
||||
elog(ERROR, "attribute %d of relation \"%s\" does not exist",
|
||||
@@ -1075,10 +1074,10 @@ adjust_appendrel_attrs_mutator(Node *node, AppendRelInfo *context)
|
||||
else if (var->varattno == 0)
|
||||
{
|
||||
/*
|
||||
* Whole-row Var: if we are dealing with named rowtypes,
|
||||
* we can use a whole-row Var for the child table plus a
|
||||
* coercion step to convert the tuple layout to the parent's
|
||||
* rowtype. Otherwise we have to generate a RowExpr.
|
||||
* Whole-row Var: if we are dealing with named rowtypes, we
|
||||
* can use a whole-row Var for the child table plus a coercion
|
||||
* step to convert the tuple layout to the parent's rowtype.
|
||||
* Otherwise we have to generate a RowExpr.
|
||||
*/
|
||||
if (OidIsValid(context->child_reltype))
|
||||
{
|
||||
@@ -1217,9 +1216,9 @@ adjust_appendrel_attrs_mutator(Node *node, AppendRelInfo *context)
|
||||
* 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 finished APPEND
|
||||
* plan, which will cause trouble in the executor. This is a kluge that
|
||||
* should go away when we redesign querytrees.
|
||||
* same subplan node referenced from each arm of the finished 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))
|
||||
{
|
||||
@@ -1267,7 +1266,7 @@ adjust_relid_set(Relids relids, Index oldrelid, Index newrelid)
|
||||
*
|
||||
* The relid sets are adjusted by substituting child_relid for parent_relid.
|
||||
* (NOTE: oldrel is not necessarily the parent_relid relation!) We are also
|
||||
* careful to map attribute numbers within the array properly. User
|
||||
* careful to map attribute numbers within the array properly. User
|
||||
* attributes have to be mapped through col_mappings, but system attributes
|
||||
* and whole-row references always have the same attno.
|
||||
*
|
||||
@@ -1353,7 +1352,7 @@ adjust_inherited_tlist(List *tlist, AppendRelInfo *context)
|
||||
foreach(tl, tlist)
|
||||
{
|
||||
TargetEntry *tle = (TargetEntry *) lfirst(tl);
|
||||
int newattno;
|
||||
int newattno;
|
||||
|
||||
if (tle->resjunk)
|
||||
continue; /* ignore junk items */
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.221 2006/09/28 20:51:41 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.222 2006/10/04 00:29:55 momjian Exp $
|
||||
*
|
||||
* HISTORY
|
||||
* AUTHOR DATE MAJOR EVENT
|
||||
@@ -403,7 +403,7 @@ count_agg_clauses_walker(Node *node, AggClauseCounts *counts)
|
||||
Form_pg_aggregate aggform;
|
||||
Oid aggtranstype;
|
||||
int i;
|
||||
ListCell *l;
|
||||
ListCell *l;
|
||||
|
||||
Assert(aggref->agglevelsup == 0);
|
||||
counts->numAggs++;
|
||||
@@ -887,7 +887,7 @@ contain_nonstrict_functions_walker(Node *node, void *context)
|
||||
*
|
||||
* Returns the set of all Relids that are referenced in the clause in such
|
||||
* a way that the clause cannot possibly return TRUE if any of these Relids
|
||||
* is an all-NULL row. (It is OK to err on the side of conservatism; hence
|
||||
* is an all-NULL row. (It is OK to err on the side of conservatism; hence
|
||||
* the analysis here is simplistic.)
|
||||
*
|
||||
* The semantics here are subtly different from contain_nonstrict_functions:
|
||||
@@ -1020,7 +1020,7 @@ find_nonnullable_rels_walker(Node *node, bool top_level)
|
||||
static bool
|
||||
is_strict_saop(ScalarArrayOpExpr *expr, bool falseOK)
|
||||
{
|
||||
Node *rightop;
|
||||
Node *rightop;
|
||||
|
||||
/* The contained operator must be strict. */
|
||||
if (!op_strict(expr->opno))
|
||||
@@ -1288,12 +1288,13 @@ CommuteRowCompareExpr(RowCompareExpr *clause)
|
||||
}
|
||||
|
||||
clause->opnos = newops;
|
||||
|
||||
/*
|
||||
* Note: we don't bother to update the opclasses list, but just set
|
||||
* it to empty. This is OK since this routine is currently only used
|
||||
* for index quals, and the index machinery won't use the opclass
|
||||
* information. The original opclass list is NOT valid if we have
|
||||
* commuted any cross-type comparisons, so don't leave it in place.
|
||||
* Note: we don't bother to update the opclasses list, but just set it to
|
||||
* empty. This is OK since this routine is currently only used for index
|
||||
* quals, and the index machinery won't use the opclass information. The
|
||||
* original opclass list is NOT valid if we have commuted any cross-type
|
||||
* comparisons, so don't leave it in place.
|
||||
*/
|
||||
clause->opclasses = NIL; /* XXX */
|
||||
|
||||
@@ -2109,9 +2110,9 @@ eval_const_expressions_mutator(Node *node,
|
||||
context);
|
||||
if (arg && IsA(arg, RowExpr))
|
||||
{
|
||||
RowExpr *rarg = (RowExpr *) arg;
|
||||
List *newargs = NIL;
|
||||
ListCell *l;
|
||||
RowExpr *rarg = (RowExpr *) arg;
|
||||
List *newargs = NIL;
|
||||
ListCell *l;
|
||||
|
||||
/*
|
||||
* We break ROW(...) IS [NOT] NULL into separate tests on its
|
||||
@@ -2120,15 +2121,15 @@ eval_const_expressions_mutator(Node *node,
|
||||
*/
|
||||
foreach(l, rarg->args)
|
||||
{
|
||||
Node *relem = (Node *) lfirst(l);
|
||||
Node *relem = (Node *) lfirst(l);
|
||||
|
||||
/*
|
||||
* A constant field refutes the whole NullTest if it's of
|
||||
* the wrong nullness; else we can discard it.
|
||||
* A constant field refutes the whole NullTest if it's of the
|
||||
* wrong nullness; else we can discard it.
|
||||
*/
|
||||
if (relem && IsA(relem, Const))
|
||||
{
|
||||
Const *carg = (Const *) relem;
|
||||
Const *carg = (Const *) relem;
|
||||
|
||||
if (carg->constisnull ?
|
||||
(ntest->nulltesttype == IS_NOT_NULL) :
|
||||
@@ -2152,8 +2153,8 @@ eval_const_expressions_mutator(Node *node,
|
||||
}
|
||||
if (arg && IsA(arg, Const))
|
||||
{
|
||||
Const *carg = (Const *) arg;
|
||||
bool result;
|
||||
Const *carg = (Const *) arg;
|
||||
bool result;
|
||||
|
||||
switch (ntest->nulltesttype)
|
||||
{
|
||||
@@ -2166,7 +2167,7 @@ eval_const_expressions_mutator(Node *node,
|
||||
default:
|
||||
elog(ERROR, "unrecognized nulltesttype: %d",
|
||||
(int) ntest->nulltesttype);
|
||||
result = false; /* keep compiler quiet */
|
||||
result = false; /* keep compiler quiet */
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2188,8 +2189,8 @@ eval_const_expressions_mutator(Node *node,
|
||||
context);
|
||||
if (arg && IsA(arg, Const))
|
||||
{
|
||||
Const *carg = (Const *) arg;
|
||||
bool result;
|
||||
Const *carg = (Const *) arg;
|
||||
bool result;
|
||||
|
||||
switch (btest->booltesttype)
|
||||
{
|
||||
@@ -2218,7 +2219,7 @@ eval_const_expressions_mutator(Node *node,
|
||||
default:
|
||||
elog(ERROR, "unrecognized booltesttype: %d",
|
||||
(int) btest->booltesttype);
|
||||
result = false; /* keep compiler quiet */
|
||||
result = false; /* keep compiler quiet */
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -3174,7 +3175,7 @@ expression_tree_walker(Node *node,
|
||||
break;
|
||||
case T_Aggref:
|
||||
{
|
||||
Aggref *expr = (Aggref *) node;
|
||||
Aggref *expr = (Aggref *) node;
|
||||
|
||||
if (expression_tree_walker((Node *) expr->args,
|
||||
walker, context))
|
||||
@@ -3452,8 +3453,8 @@ query_tree_walker(Query *query,
|
||||
if (query->utilityStmt)
|
||||
{
|
||||
/*
|
||||
* Certain utility commands contain general-purpose Querys embedded
|
||||
* in them --- if this is one, invoke the walker on the sub-Query.
|
||||
* Certain utility commands contain general-purpose Querys embedded in
|
||||
* them --- if this is one, invoke the walker on the sub-Query.
|
||||
*/
|
||||
if (IsA(query->utilityStmt, CopyStmt))
|
||||
{
|
||||
@@ -3828,8 +3829,8 @@ expression_tree_mutator(Node *node,
|
||||
break;
|
||||
case T_RowCompareExpr:
|
||||
{
|
||||
RowCompareExpr *rcexpr = (RowCompareExpr *) node;
|
||||
RowCompareExpr *newnode;
|
||||
RowCompareExpr *rcexpr = (RowCompareExpr *) node;
|
||||
RowCompareExpr *newnode;
|
||||
|
||||
FLATCOPY(newnode, rcexpr, RowCompareExpr);
|
||||
MUTATE(newnode->largs, rcexpr->largs, List *);
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/util/pathnode.c,v 1.132 2006/08/02 01:59:46 joe Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/util/pathnode.c,v 1.133 2006/10/04 00:29:55 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -418,7 +418,7 @@ create_seqscan_path(PlannerInfo *root, RelOptInfo *rel)
|
||||
* for an ordered index, or NoMovementScanDirection for
|
||||
* an unordered index.
|
||||
* 'outer_rel' is the outer relation if this is a join inner indexscan path.
|
||||
* (pathkeys and indexscandir are ignored if so.) NULL if not.
|
||||
* (pathkeys and indexscandir are ignored if so.) NULL if not.
|
||||
*
|
||||
* Returns the new path node.
|
||||
*/
|
||||
@@ -680,12 +680,12 @@ create_result_path(List *quals)
|
||||
/* Ideally should define cost_result(), but I'm too lazy */
|
||||
pathnode->path.startup_cost = 0;
|
||||
pathnode->path.total_cost = cpu_tuple_cost;
|
||||
|
||||
/*
|
||||
* In theory we should include the qual eval cost as well, but
|
||||
* at present that doesn't accomplish much except duplicate work that
|
||||
* will be done again in make_result; since this is only used for
|
||||
* degenerate cases, nothing interesting will be done with the path
|
||||
* cost values...
|
||||
* In theory we should include the qual eval cost as well, but at present
|
||||
* that doesn't accomplish much except duplicate work that will be done
|
||||
* again in make_result; since this is only used for degenerate cases,
|
||||
* nothing interesting will be done with the path cost values...
|
||||
*/
|
||||
|
||||
return pathnode;
|
||||
|
@@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/util/plancat.c,v 1.126 2006/09/19 22:49:53 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/util/plancat.c,v 1.127 2006/10/04 00:29:55 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -78,9 +78,9 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
|
||||
List *indexinfos = NIL;
|
||||
|
||||
/*
|
||||
* We need not lock the relation since it was already locked, either
|
||||
* by the rewriter or when expand_inherited_rtentry() added it to the
|
||||
* query's rangetable.
|
||||
* We need not lock the relation since it was already locked, either by
|
||||
* the rewriter or when expand_inherited_rtentry() added it to the query's
|
||||
* rangetable.
|
||||
*/
|
||||
relation = heap_open(relationObjectId, NoLock);
|
||||
|
||||
@@ -95,8 +95,8 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
|
||||
|
||||
/*
|
||||
* Estimate relation size --- unless it's an inheritance parent, in which
|
||||
* case the size will be computed later in set_append_rel_pathlist, and
|
||||
* we must leave it zero for now to avoid bollixing the total_table_pages
|
||||
* case the size will be computed later in set_append_rel_pathlist, and we
|
||||
* must leave it zero for now to avoid bollixing the total_table_pages
|
||||
* calculation.
|
||||
*/
|
||||
if (!inhparent)
|
||||
@@ -152,9 +152,9 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
|
||||
|
||||
/*
|
||||
* Ignore invalid indexes, since they can't safely be used for
|
||||
* queries. Note that this is OK because the data structure
|
||||
* we are constructing is only used by the planner --- the
|
||||
* executor still needs to insert into "invalid" indexes!
|
||||
* queries. Note that this is OK because the data structure we
|
||||
* are constructing is only used by the planner --- the executor
|
||||
* still needs to insert into "invalid" indexes!
|
||||
*/
|
||||
if (!index->indisvalid)
|
||||
{
|
||||
@@ -508,14 +508,14 @@ relation_excluded_by_constraints(RelOptInfo *rel, RangeTblEntry *rte)
|
||||
/*
|
||||
* We do not currently enforce that CHECK constraints contain only
|
||||
* immutable functions, so it's necessary to check here. We daren't draw
|
||||
* conclusions from plan-time evaluation of non-immutable functions.
|
||||
* Since they're ANDed, we can just ignore any mutable constraints in
|
||||
* the list, and reason about the rest.
|
||||
* conclusions from plan-time evaluation of non-immutable functions. Since
|
||||
* they're ANDed, we can just ignore any mutable constraints in the list,
|
||||
* and reason about the rest.
|
||||
*/
|
||||
safe_constraints = NIL;
|
||||
foreach(lc, constraint_pred)
|
||||
{
|
||||
Node *pred = (Node *) lfirst(lc);
|
||||
Node *pred = (Node *) lfirst(lc);
|
||||
|
||||
if (!contain_mutable_functions(pred))
|
||||
safe_constraints = lappend(safe_constraints, pred);
|
||||
@@ -526,9 +526,9 @@ relation_excluded_by_constraints(RelOptInfo *rel, RangeTblEntry *rte)
|
||||
* refute the entire collection at once. This may allow us to make proofs
|
||||
* that would fail if we took them individually.
|
||||
*
|
||||
* Note: we use rel->baserestrictinfo, not safe_restrictions as might
|
||||
* seem an obvious optimization. Some of the clauses might be OR clauses
|
||||
* that have volatile and nonvolatile subclauses, and it's OK to make
|
||||
* Note: we use rel->baserestrictinfo, not safe_restrictions as might seem
|
||||
* an obvious optimization. Some of the clauses might be OR clauses that
|
||||
* have volatile and nonvolatile subclauses, and it's OK to make
|
||||
* deductions with the nonvolatile parts.
|
||||
*/
|
||||
if (predicate_refuted_by(safe_constraints, rel->baserestrictinfo))
|
||||
|
@@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/util/predtest.c,v 1.9 2006/09/28 20:51:42 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/util/predtest.c,v 1.10 2006/10/04 00:29:55 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -208,6 +208,7 @@ predicate_implied_by_recurse(Node *clause, Node *predicate)
|
||||
switch (pclass)
|
||||
{
|
||||
case CLASS_AND:
|
||||
|
||||
/*
|
||||
* AND-clause => AND-clause if A implies each of B's items
|
||||
*/
|
||||
@@ -224,6 +225,7 @@ predicate_implied_by_recurse(Node *clause, Node *predicate)
|
||||
return result;
|
||||
|
||||
case CLASS_OR:
|
||||
|
||||
/*
|
||||
* AND-clause => OR-clause if A implies any of B's items
|
||||
*
|
||||
@@ -241,6 +243,7 @@ predicate_implied_by_recurse(Node *clause, Node *predicate)
|
||||
iterate_end(pred_info);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
/*
|
||||
* Also check if any of A's items implies B
|
||||
*
|
||||
@@ -258,6 +261,7 @@ predicate_implied_by_recurse(Node *clause, Node *predicate)
|
||||
return result;
|
||||
|
||||
case CLASS_ATOM:
|
||||
|
||||
/*
|
||||
* AND-clause => atom if any of A's items implies B
|
||||
*/
|
||||
@@ -279,6 +283,7 @@ predicate_implied_by_recurse(Node *clause, Node *predicate)
|
||||
switch (pclass)
|
||||
{
|
||||
case CLASS_OR:
|
||||
|
||||
/*
|
||||
* OR-clause => OR-clause if each of A's items implies any
|
||||
* of B's items. Messy but can't do it any more simply.
|
||||
@@ -286,7 +291,7 @@ predicate_implied_by_recurse(Node *clause, Node *predicate)
|
||||
result = true;
|
||||
iterate_begin(citem, clause, clause_info)
|
||||
{
|
||||
bool presult = false;
|
||||
bool presult = false;
|
||||
|
||||
iterate_begin(pitem, predicate, pred_info)
|
||||
{
|
||||
@@ -308,6 +313,7 @@ predicate_implied_by_recurse(Node *clause, Node *predicate)
|
||||
|
||||
case CLASS_AND:
|
||||
case CLASS_ATOM:
|
||||
|
||||
/*
|
||||
* OR-clause => AND-clause if each of A's items implies B
|
||||
*
|
||||
@@ -331,6 +337,7 @@ predicate_implied_by_recurse(Node *clause, Node *predicate)
|
||||
switch (pclass)
|
||||
{
|
||||
case CLASS_AND:
|
||||
|
||||
/*
|
||||
* atom => AND-clause if A implies each of B's items
|
||||
*/
|
||||
@@ -347,6 +354,7 @@ predicate_implied_by_recurse(Node *clause, Node *predicate)
|
||||
return result;
|
||||
|
||||
case CLASS_OR:
|
||||
|
||||
/*
|
||||
* atom => OR-clause if A implies any of B's items
|
||||
*/
|
||||
@@ -363,6 +371,7 @@ predicate_implied_by_recurse(Node *clause, Node *predicate)
|
||||
return result;
|
||||
|
||||
case CLASS_ATOM:
|
||||
|
||||
/*
|
||||
* atom => atom is the base case
|
||||
*/
|
||||
@@ -427,6 +436,7 @@ predicate_refuted_by_recurse(Node *clause, Node *predicate)
|
||||
switch (pclass)
|
||||
{
|
||||
case CLASS_AND:
|
||||
|
||||
/*
|
||||
* AND-clause R=> AND-clause if A refutes any of B's items
|
||||
*
|
||||
@@ -444,6 +454,7 @@ predicate_refuted_by_recurse(Node *clause, Node *predicate)
|
||||
iterate_end(pred_info);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
/*
|
||||
* Also check if any of A's items refutes B
|
||||
*
|
||||
@@ -461,6 +472,7 @@ predicate_refuted_by_recurse(Node *clause, Node *predicate)
|
||||
return result;
|
||||
|
||||
case CLASS_OR:
|
||||
|
||||
/*
|
||||
* AND-clause R=> OR-clause if A refutes each of B's items
|
||||
*/
|
||||
@@ -477,6 +489,7 @@ predicate_refuted_by_recurse(Node *clause, Node *predicate)
|
||||
return result;
|
||||
|
||||
case CLASS_ATOM:
|
||||
|
||||
/*
|
||||
* If B is a NOT-clause, A R=> B if A => B's arg
|
||||
*/
|
||||
@@ -484,6 +497,7 @@ predicate_refuted_by_recurse(Node *clause, Node *predicate)
|
||||
if (not_arg &&
|
||||
predicate_implied_by_recurse(clause, not_arg))
|
||||
return true;
|
||||
|
||||
/*
|
||||
* AND-clause R=> atom if any of A's items refutes B
|
||||
*/
|
||||
@@ -505,6 +519,7 @@ predicate_refuted_by_recurse(Node *clause, Node *predicate)
|
||||
switch (pclass)
|
||||
{
|
||||
case CLASS_OR:
|
||||
|
||||
/*
|
||||
* OR-clause R=> OR-clause if A refutes each of B's items
|
||||
*/
|
||||
@@ -521,6 +536,7 @@ predicate_refuted_by_recurse(Node *clause, Node *predicate)
|
||||
return result;
|
||||
|
||||
case CLASS_AND:
|
||||
|
||||
/*
|
||||
* OR-clause R=> AND-clause if each of A's items refutes
|
||||
* any of B's items.
|
||||
@@ -528,7 +544,7 @@ predicate_refuted_by_recurse(Node *clause, Node *predicate)
|
||||
result = true;
|
||||
iterate_begin(citem, clause, clause_info)
|
||||
{
|
||||
bool presult = false;
|
||||
bool presult = false;
|
||||
|
||||
iterate_begin(pitem, predicate, pred_info)
|
||||
{
|
||||
@@ -549,6 +565,7 @@ predicate_refuted_by_recurse(Node *clause, Node *predicate)
|
||||
return result;
|
||||
|
||||
case CLASS_ATOM:
|
||||
|
||||
/*
|
||||
* If B is a NOT-clause, A R=> B if A => B's arg
|
||||
*/
|
||||
@@ -556,6 +573,7 @@ predicate_refuted_by_recurse(Node *clause, Node *predicate)
|
||||
if (not_arg &&
|
||||
predicate_implied_by_recurse(clause, not_arg))
|
||||
return true;
|
||||
|
||||
/*
|
||||
* OR-clause R=> atom if each of A's items refutes B
|
||||
*/
|
||||
@@ -574,6 +592,7 @@ predicate_refuted_by_recurse(Node *clause, Node *predicate)
|
||||
break;
|
||||
|
||||
case CLASS_ATOM:
|
||||
|
||||
/*
|
||||
* If A is a NOT-clause, A R=> B if B => A's arg
|
||||
*/
|
||||
@@ -584,6 +603,7 @@ predicate_refuted_by_recurse(Node *clause, Node *predicate)
|
||||
switch (pclass)
|
||||
{
|
||||
case CLASS_AND:
|
||||
|
||||
/*
|
||||
* atom R=> AND-clause if A refutes any of B's items
|
||||
*/
|
||||
@@ -600,6 +620,7 @@ predicate_refuted_by_recurse(Node *clause, Node *predicate)
|
||||
return result;
|
||||
|
||||
case CLASS_OR:
|
||||
|
||||
/*
|
||||
* atom R=> OR-clause if A refutes each of B's items
|
||||
*/
|
||||
@@ -616,6 +637,7 @@ predicate_refuted_by_recurse(Node *clause, Node *predicate)
|
||||
return result;
|
||||
|
||||
case CLASS_ATOM:
|
||||
|
||||
/*
|
||||
* If B is a NOT-clause, A R=> B if A => B's arg
|
||||
*/
|
||||
@@ -623,6 +645,7 @@ predicate_refuted_by_recurse(Node *clause, Node *predicate)
|
||||
if (not_arg &&
|
||||
predicate_implied_by_recurse(clause, not_arg))
|
||||
return true;
|
||||
|
||||
/*
|
||||
* atom R=> atom is the base case
|
||||
*/
|
||||
@@ -654,8 +677,8 @@ predicate_classify(Node *clause, PredIterInfo info)
|
||||
Assert(!IsA(clause, RestrictInfo));
|
||||
|
||||
/*
|
||||
* If we see a List, assume it's an implicit-AND list; this is the
|
||||
* correct semantics for lists of RestrictInfo nodes.
|
||||
* If we see a List, assume it's an implicit-AND list; this is the correct
|
||||
* semantics for lists of RestrictInfo nodes.
|
||||
*/
|
||||
if (IsA(clause, List))
|
||||
{
|
||||
@@ -685,13 +708,13 @@ predicate_classify(Node *clause, PredIterInfo info)
|
||||
if (IsA(clause, ScalarArrayOpExpr))
|
||||
{
|
||||
ScalarArrayOpExpr *saop = (ScalarArrayOpExpr *) clause;
|
||||
Node *arraynode = (Node *) lsecond(saop->args);
|
||||
Node *arraynode = (Node *) lsecond(saop->args);
|
||||
|
||||
/*
|
||||
* We can break this down into an AND or OR structure, but only if
|
||||
* we know how to iterate through expressions for the array's
|
||||
* elements. We can do that if the array operand is a non-null
|
||||
* constant or a simple ArrayExpr.
|
||||
* We can break this down into an AND or OR structure, but only if we
|
||||
* know how to iterate through expressions for the array's elements.
|
||||
* We can do that if the array operand is a non-null constant or a
|
||||
* simple ArrayExpr.
|
||||
*/
|
||||
if (arraynode && IsA(arraynode, Const) &&
|
||||
!((Const *) arraynode)->constisnull)
|
||||
@@ -716,7 +739,7 @@ predicate_classify(Node *clause, PredIterInfo info)
|
||||
}
|
||||
|
||||
/*
|
||||
* PredIterInfo routines for iterating over regular Lists. The iteration
|
||||
* PredIterInfo routines for iterating over regular Lists. The iteration
|
||||
* state variable is the next ListCell to visit.
|
||||
*/
|
||||
static void
|
||||
@@ -852,7 +875,7 @@ arrayexpr_startup_fn(Node *clause, PredIterInfo info)
|
||||
{
|
||||
ScalarArrayOpExpr *saop = (ScalarArrayOpExpr *) clause;
|
||||
ArrayExprIterState *state;
|
||||
ArrayExpr *arrayexpr;
|
||||
ArrayExpr *arrayexpr;
|
||||
|
||||
/* Create working state struct */
|
||||
state = (ArrayExprIterState *) palloc(sizeof(ArrayExprIterState));
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/util/relnode.c,v 1.82 2006/09/19 22:49:53 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/util/relnode.c,v 1.83 2006/10/04 00:29:55 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -97,9 +97,10 @@ build_simple_rel(PlannerInfo *root, int relid, RelOptKind reloptkind)
|
||||
case RTE_SUBQUERY:
|
||||
case RTE_FUNCTION:
|
||||
case RTE_VALUES:
|
||||
|
||||
/*
|
||||
* Subquery, function, or values list --- set up attr range
|
||||
* and arrays
|
||||
* Subquery, function, or values list --- set up attr range and
|
||||
* arrays
|
||||
*
|
||||
* Note: 0 is included in range to support whole-row Vars
|
||||
*/
|
||||
@@ -417,8 +418,8 @@ build_joinrel_tlist(PlannerInfo *root, RelOptInfo *joinrel,
|
||||
int ndx;
|
||||
|
||||
/*
|
||||
* We can't run into any child RowExprs here, but we could find
|
||||
* a whole-row Var with a ConvertRowtypeExpr atop it.
|
||||
* We can't run into any child RowExprs here, but we could find a
|
||||
* whole-row Var with a ConvertRowtypeExpr atop it.
|
||||
*/
|
||||
var = origvar;
|
||||
while (!IsA(var, Var))
|
||||
|
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/util/restrictinfo.c,v 1.48 2006/07/01 18:38:33 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/util/restrictinfo.c,v 1.49 2006/10/04 00:29:55 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -169,14 +169,15 @@ make_restrictinfo_from_bitmapqual(Path *bitmapqual,
|
||||
*/
|
||||
return NIL;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the sublist contains multiple RestrictInfos, we create an
|
||||
* AND subclause. If there's just one, we have to check if it's
|
||||
* an OR clause, and if so flatten it to preserve AND/OR flatness
|
||||
* of our output.
|
||||
*
|
||||
* We construct lists with and without sub-RestrictInfos, so
|
||||
* as not to have to regenerate duplicate RestrictInfos below.
|
||||
* We construct lists with and without sub-RestrictInfos, so as
|
||||
* not to have to regenerate duplicate RestrictInfos below.
|
||||
*/
|
||||
if (list_length(sublist) > 1)
|
||||
{
|
||||
@@ -186,7 +187,7 @@ make_restrictinfo_from_bitmapqual(Path *bitmapqual,
|
||||
}
|
||||
else
|
||||
{
|
||||
RestrictInfo *subri = (RestrictInfo *) linitial(sublist);
|
||||
RestrictInfo *subri = (RestrictInfo *) linitial(sublist);
|
||||
|
||||
Assert(IsA(subri, RestrictInfo));
|
||||
if (restriction_is_or_clause(subri))
|
||||
|
Reference in New Issue
Block a user