Add a back-link from IndexOptInfo structs to their parent RelOptInfo
structs. There are many places in the planner where we were passing both a rel and an index to subroutines, and now need only pass the index struct. Notationally simpler, and perhaps a tad faster.
This commit is contained in:
parent
febc9a613c
commit
926e8a00d3
|
@ -49,7 +49,7 @@
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.138 2005/03/06 22:15:04 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.139 2005/03/27 06:29:35 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -227,7 +227,6 @@ cost_nonsequential_access(double relpages)
|
||||||
* but here we consider the cost of just one pass.
|
* but here we consider the cost of just one pass.
|
||||||
*
|
*
|
||||||
* 'root' is the query root
|
* 'root' is the query root
|
||||||
* 'baserel' is the base relation the index is for
|
|
||||||
* 'index' is the index to be used
|
* 'index' is the index to be used
|
||||||
* 'indexQuals' is the list of applicable qual clauses (implicit AND semantics)
|
* 'indexQuals' is the list of applicable qual clauses (implicit AND semantics)
|
||||||
* 'is_injoin' is T if we are considering using the index scan as the inside
|
* 'is_injoin' is T if we are considering using the index scan as the inside
|
||||||
|
@ -243,11 +242,11 @@ cost_nonsequential_access(double relpages)
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
cost_index(Path *path, Query *root,
|
cost_index(Path *path, Query *root,
|
||||||
RelOptInfo *baserel,
|
|
||||||
IndexOptInfo *index,
|
IndexOptInfo *index,
|
||||||
List *indexQuals,
|
List *indexQuals,
|
||||||
bool is_injoin)
|
bool is_injoin)
|
||||||
{
|
{
|
||||||
|
RelOptInfo *baserel = index->rel;
|
||||||
Cost startup_cost = 0;
|
Cost startup_cost = 0;
|
||||||
Cost run_cost = 0;
|
Cost run_cost = 0;
|
||||||
Cost indexStartupCost;
|
Cost indexStartupCost;
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.170 2005/03/26 23:29:17 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.171 2005/03/27 06:29:36 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -54,36 +54,31 @@
|
||||||
((opclass) == BOOL_BTREE_OPS_OID || (opclass) == BOOL_HASH_OPS_OID)
|
((opclass) == BOOL_BTREE_OPS_OID || (opclass) == BOOL_HASH_OPS_OID)
|
||||||
|
|
||||||
|
|
||||||
static List *group_clauses_by_indexkey(RelOptInfo *rel, IndexOptInfo *index);
|
static List *group_clauses_by_indexkey(IndexOptInfo *index);
|
||||||
static List *group_clauses_by_indexkey_for_join(Query *root,
|
static List *group_clauses_by_indexkey_for_join(Query *root,
|
||||||
RelOptInfo *rel, IndexOptInfo *index,
|
IndexOptInfo *index,
|
||||||
Relids outer_relids,
|
Relids outer_relids,
|
||||||
JoinType jointype, bool isouterjoin);
|
JoinType jointype, bool isouterjoin);
|
||||||
static bool match_clause_to_indexcol(RelOptInfo *rel, IndexOptInfo *index,
|
static bool match_clause_to_indexcol(IndexOptInfo *index,
|
||||||
int indexcol, Oid opclass,
|
int indexcol, Oid opclass,
|
||||||
RestrictInfo *rinfo);
|
RestrictInfo *rinfo);
|
||||||
static bool match_join_clause_to_indexcol(RelOptInfo *rel, IndexOptInfo *index,
|
static bool match_join_clause_to_indexcol(IndexOptInfo *index,
|
||||||
int indexcol, Oid opclass,
|
int indexcol, Oid opclass,
|
||||||
RestrictInfo *rinfo);
|
RestrictInfo *rinfo);
|
||||||
static Oid indexable_operator(Expr *clause, Oid opclass,
|
static Oid indexable_operator(Expr *clause, Oid opclass,
|
||||||
bool indexkey_on_left);
|
bool indexkey_on_left);
|
||||||
static bool pred_test_recurse(Node *clause, Node *predicate);
|
static bool pred_test_recurse(Node *clause, Node *predicate);
|
||||||
static bool pred_test_simple_clause(Expr *predicate, Node *clause);
|
static bool pred_test_simple_clause(Expr *predicate, Node *clause);
|
||||||
static Relids indexable_outerrelids(RelOptInfo *rel, IndexOptInfo *index);
|
static Relids indexable_outerrelids(IndexOptInfo *index);
|
||||||
static Path *make_innerjoin_index_path(Query *root,
|
static Path *make_innerjoin_index_path(Query *root, IndexOptInfo *index,
|
||||||
RelOptInfo *rel, IndexOptInfo *index,
|
|
||||||
List *clausegroups);
|
List *clausegroups);
|
||||||
static bool match_index_to_operand(Node *operand, int indexcol,
|
static bool match_index_to_operand(Node *operand, int indexcol,
|
||||||
RelOptInfo *rel, IndexOptInfo *index);
|
IndexOptInfo *index);
|
||||||
static bool match_boolean_index_clause(Node *clause,
|
static bool match_boolean_index_clause(Node *clause, int indexcol,
|
||||||
int indexcol,
|
|
||||||
RelOptInfo *rel,
|
|
||||||
IndexOptInfo *index);
|
IndexOptInfo *index);
|
||||||
static bool match_special_index_operator(Expr *clause, Oid opclass,
|
static bool match_special_index_operator(Expr *clause, Oid opclass,
|
||||||
bool indexkey_on_left);
|
bool indexkey_on_left);
|
||||||
static Expr *expand_boolean_index_clause(Node *clause,
|
static Expr *expand_boolean_index_clause(Node *clause, int indexcol,
|
||||||
int indexcol,
|
|
||||||
RelOptInfo *rel,
|
|
||||||
IndexOptInfo *index);
|
IndexOptInfo *index);
|
||||||
static List *expand_indexqual_condition(RestrictInfo *rinfo, Oid opclass);
|
static List *expand_indexqual_condition(RestrictInfo *rinfo, Oid opclass);
|
||||||
static List *prefix_quals(Node *leftop, Oid opclass,
|
static List *prefix_quals(Node *leftop, Oid opclass,
|
||||||
|
@ -148,13 +143,13 @@ create_index_paths(Query *root, RelOptInfo *rel)
|
||||||
* 1. Match the index against non-OR restriction clauses. (OR
|
* 1. Match the index against non-OR restriction clauses. (OR
|
||||||
* clauses will be considered later by orindxpath.c.)
|
* clauses will be considered later by orindxpath.c.)
|
||||||
*/
|
*/
|
||||||
restrictclauses = group_clauses_by_indexkey(rel, index);
|
restrictclauses = group_clauses_by_indexkey(index);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 2. Compute pathkeys describing index's ordering, if any, then
|
* 2. Compute pathkeys describing index's ordering, if any, then
|
||||||
* see how many of them are actually useful for this query.
|
* see how many of them are actually useful for this query.
|
||||||
*/
|
*/
|
||||||
index_pathkeys = build_index_pathkeys(root, rel, index,
|
index_pathkeys = build_index_pathkeys(root, index,
|
||||||
ForwardScanDirection);
|
ForwardScanDirection);
|
||||||
index_is_ordered = (index_pathkeys != NIL);
|
index_is_ordered = (index_pathkeys != NIL);
|
||||||
useful_pathkeys = truncate_useless_pathkeys(root, rel,
|
useful_pathkeys = truncate_useless_pathkeys(root, rel,
|
||||||
|
@ -173,7 +168,7 @@ create_index_paths(Query *root, RelOptInfo *rel)
|
||||||
useful_pathkeys != NIL ||
|
useful_pathkeys != NIL ||
|
||||||
index->indpred != NIL)
|
index->indpred != NIL)
|
||||||
add_path(rel, (Path *)
|
add_path(rel, (Path *)
|
||||||
create_index_path(root, rel, index,
|
create_index_path(root, index,
|
||||||
restrictclauses,
|
restrictclauses,
|
||||||
useful_pathkeys,
|
useful_pathkeys,
|
||||||
index_is_ordered ?
|
index_is_ordered ?
|
||||||
|
@ -187,13 +182,13 @@ create_index_paths(Query *root, RelOptInfo *rel)
|
||||||
*/
|
*/
|
||||||
if (index_is_ordered)
|
if (index_is_ordered)
|
||||||
{
|
{
|
||||||
index_pathkeys = build_index_pathkeys(root, rel, index,
|
index_pathkeys = build_index_pathkeys(root, index,
|
||||||
BackwardScanDirection);
|
BackwardScanDirection);
|
||||||
useful_pathkeys = truncate_useless_pathkeys(root, rel,
|
useful_pathkeys = truncate_useless_pathkeys(root, rel,
|
||||||
index_pathkeys);
|
index_pathkeys);
|
||||||
if (useful_pathkeys != NIL)
|
if (useful_pathkeys != NIL)
|
||||||
add_path(rel, (Path *)
|
add_path(rel, (Path *)
|
||||||
create_index_path(root, rel, index,
|
create_index_path(root, index,
|
||||||
restrictclauses,
|
restrictclauses,
|
||||||
useful_pathkeys,
|
useful_pathkeys,
|
||||||
BackwardScanDirection));
|
BackwardScanDirection));
|
||||||
|
@ -207,7 +202,7 @@ create_index_paths(Query *root, RelOptInfo *rel)
|
||||||
* joining purposes. We compute both per-index and
|
* joining purposes. We compute both per-index and
|
||||||
* overall-for-relation sets.
|
* overall-for-relation sets.
|
||||||
*/
|
*/
|
||||||
join_outerrelids = indexable_outerrelids(rel, index);
|
join_outerrelids = indexable_outerrelids(index);
|
||||||
index->outer_relids = join_outerrelids;
|
index->outer_relids = join_outerrelids;
|
||||||
all_join_outerrelids = bms_add_members(all_join_outerrelids,
|
all_join_outerrelids = bms_add_members(all_join_outerrelids,
|
||||||
join_outerrelids);
|
join_outerrelids);
|
||||||
|
@ -226,9 +221,6 @@ create_index_paths(Query *root, RelOptInfo *rel)
|
||||||
* group_clauses_by_indexkey
|
* group_clauses_by_indexkey
|
||||||
* Find restriction clauses that can be used with an index.
|
* Find restriction clauses that can be used with an index.
|
||||||
*
|
*
|
||||||
* 'rel' is the node of the relation itself.
|
|
||||||
* 'index' is a index on 'rel'.
|
|
||||||
*
|
|
||||||
* Returns a list of sublists of RestrictInfo nodes for clauses that can be
|
* Returns a list of sublists of RestrictInfo nodes for clauses that can be
|
||||||
* used with this index. Each sublist contains clauses that can be used
|
* used with this index. Each sublist contains clauses that can be used
|
||||||
* with one index key (in no particular order); the top list is ordered by
|
* with one index key (in no particular order); the top list is ordered by
|
||||||
|
@ -243,10 +235,10 @@ create_index_paths(Query *root, RelOptInfo *rel)
|
||||||
* Therefore, there are no empty sublists in the result.
|
* Therefore, there are no empty sublists in the result.
|
||||||
*/
|
*/
|
||||||
static List *
|
static List *
|
||||||
group_clauses_by_indexkey(RelOptInfo *rel, IndexOptInfo *index)
|
group_clauses_by_indexkey(IndexOptInfo *index)
|
||||||
{
|
{
|
||||||
List *clausegroup_list = NIL;
|
List *clausegroup_list = NIL;
|
||||||
List *restrictinfo_list = rel->baserestrictinfo;
|
List *restrictinfo_list = index->rel->baserestrictinfo;
|
||||||
int indexcol = 0;
|
int indexcol = 0;
|
||||||
Oid *classes = index->classlist;
|
Oid *classes = index->classlist;
|
||||||
|
|
||||||
|
@ -263,8 +255,7 @@ group_clauses_by_indexkey(RelOptInfo *rel, IndexOptInfo *index)
|
||||||
{
|
{
|
||||||
RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
|
RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
|
||||||
|
|
||||||
if (match_clause_to_indexcol(rel,
|
if (match_clause_to_indexcol(index,
|
||||||
index,
|
|
||||||
indexcol,
|
indexcol,
|
||||||
curClass,
|
curClass,
|
||||||
rinfo))
|
rinfo))
|
||||||
|
@ -302,8 +293,7 @@ group_clauses_by_indexkey(RelOptInfo *rel, IndexOptInfo *index)
|
||||||
* will already have been generated for it.)
|
* will already have been generated for it.)
|
||||||
*/
|
*/
|
||||||
static List *
|
static List *
|
||||||
group_clauses_by_indexkey_for_join(Query *root,
|
group_clauses_by_indexkey_for_join(Query *root, IndexOptInfo *index,
|
||||||
RelOptInfo *rel, IndexOptInfo *index,
|
|
||||||
Relids outer_relids,
|
Relids outer_relids,
|
||||||
JoinType jointype, bool isouterjoin)
|
JoinType jointype, bool isouterjoin)
|
||||||
{
|
{
|
||||||
|
@ -327,7 +317,7 @@ group_clauses_by_indexkey_for_join(Query *root,
|
||||||
* to get rid of a non-join clause if it appears after a join
|
* to get rid of a non-join clause if it appears after a join
|
||||||
* clause it is redundant with.
|
* clause it is redundant with.
|
||||||
*/
|
*/
|
||||||
foreach(l, rel->baserestrictinfo)
|
foreach(l, index->rel->baserestrictinfo)
|
||||||
{
|
{
|
||||||
RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
|
RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
|
||||||
|
|
||||||
|
@ -335,8 +325,7 @@ group_clauses_by_indexkey_for_join(Query *root,
|
||||||
if (isouterjoin && rinfo->is_pushed_down)
|
if (isouterjoin && rinfo->is_pushed_down)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (match_clause_to_indexcol(rel,
|
if (match_clause_to_indexcol(index,
|
||||||
index,
|
|
||||||
indexcol,
|
indexcol,
|
||||||
curClass,
|
curClass,
|
||||||
rinfo))
|
rinfo))
|
||||||
|
@ -347,7 +336,7 @@ group_clauses_by_indexkey_for_join(Query *root,
|
||||||
numsources = (clausegroup != NIL) ? 1 : 0;
|
numsources = (clausegroup != NIL) ? 1 : 0;
|
||||||
|
|
||||||
/* Look for joinclauses that are usable with given outer_relids */
|
/* Look for joinclauses that are usable with given outer_relids */
|
||||||
foreach(l, rel->joininfo)
|
foreach(l, index->rel->joininfo)
|
||||||
{
|
{
|
||||||
JoinInfo *joininfo = (JoinInfo *) lfirst(l);
|
JoinInfo *joininfo = (JoinInfo *) lfirst(l);
|
||||||
bool jfoundhere = false;
|
bool jfoundhere = false;
|
||||||
|
@ -364,8 +353,7 @@ group_clauses_by_indexkey_for_join(Query *root,
|
||||||
if (isouterjoin && rinfo->is_pushed_down)
|
if (isouterjoin && rinfo->is_pushed_down)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (match_join_clause_to_indexcol(rel,
|
if (match_join_clause_to_indexcol(index,
|
||||||
index,
|
|
||||||
indexcol,
|
indexcol,
|
||||||
curClass,
|
curClass,
|
||||||
rinfo))
|
rinfo))
|
||||||
|
@ -434,9 +422,7 @@ group_clauses_by_indexkey_for_join(Query *root,
|
||||||
* restriction clause as qpquals. FIXME someday.
|
* restriction clause as qpquals. FIXME someday.
|
||||||
*/
|
*/
|
||||||
List *
|
List *
|
||||||
group_clauses_by_indexkey_for_or(RelOptInfo *rel,
|
group_clauses_by_indexkey_for_or(IndexOptInfo *index, Expr *orsubclause)
|
||||||
IndexOptInfo *index,
|
|
||||||
Expr *orsubclause)
|
|
||||||
{
|
{
|
||||||
List *clausegroup_list = NIL;
|
List *clausegroup_list = NIL;
|
||||||
bool matched = false;
|
bool matched = false;
|
||||||
|
@ -452,8 +438,7 @@ group_clauses_by_indexkey_for_or(RelOptInfo *rel,
|
||||||
/* Try to match the OR subclause to the index key */
|
/* Try to match the OR subclause to the index key */
|
||||||
if (IsA(orsubclause, RestrictInfo))
|
if (IsA(orsubclause, RestrictInfo))
|
||||||
{
|
{
|
||||||
if (match_clause_to_indexcol(rel, index,
|
if (match_clause_to_indexcol(index, indexcol, curClass,
|
||||||
indexcol, curClass,
|
|
||||||
(RestrictInfo *) orsubclause))
|
(RestrictInfo *) orsubclause))
|
||||||
{
|
{
|
||||||
clausegroup = lappend(clausegroup, orsubclause);
|
clausegroup = lappend(clausegroup, orsubclause);
|
||||||
|
@ -467,8 +452,7 @@ group_clauses_by_indexkey_for_or(RelOptInfo *rel,
|
||||||
RestrictInfo *subsubclause = (RestrictInfo *) lfirst(item);
|
RestrictInfo *subsubclause = (RestrictInfo *) lfirst(item);
|
||||||
|
|
||||||
if (IsA(subsubclause, RestrictInfo) &&
|
if (IsA(subsubclause, RestrictInfo) &&
|
||||||
match_clause_to_indexcol(rel, index,
|
match_clause_to_indexcol(index, indexcol, curClass,
|
||||||
indexcol, curClass,
|
|
||||||
subsubclause))
|
subsubclause))
|
||||||
{
|
{
|
||||||
clausegroup = lappend(clausegroup, subsubclause);
|
clausegroup = lappend(clausegroup, subsubclause);
|
||||||
|
@ -486,12 +470,11 @@ group_clauses_by_indexkey_for_or(RelOptInfo *rel,
|
||||||
*/
|
*/
|
||||||
if (clausegroup == NIL)
|
if (clausegroup == NIL)
|
||||||
{
|
{
|
||||||
foreach(item, rel->baserestrictinfo)
|
foreach(item, index->rel->baserestrictinfo)
|
||||||
{
|
{
|
||||||
RestrictInfo *rinfo = (RestrictInfo *) lfirst(item);
|
RestrictInfo *rinfo = (RestrictInfo *) lfirst(item);
|
||||||
|
|
||||||
if (match_clause_to_indexcol(rel, index,
|
if (match_clause_to_indexcol(index, indexcol, curClass,
|
||||||
indexcol, curClass,
|
|
||||||
rinfo))
|
rinfo))
|
||||||
clausegroup = lappend(clausegroup, rinfo);
|
clausegroup = lappend(clausegroup, rinfo);
|
||||||
}
|
}
|
||||||
|
@ -539,8 +522,7 @@ group_clauses_by_indexkey_for_or(RelOptInfo *rel,
|
||||||
* For boolean indexes, it is also possible to match the clause directly
|
* For boolean indexes, it is also possible to match the clause directly
|
||||||
* to the indexkey; or perhaps the clause is (NOT indexkey).
|
* to the indexkey; or perhaps the clause is (NOT indexkey).
|
||||||
*
|
*
|
||||||
* 'rel' is the relation of interest.
|
* 'index' is the index of interest.
|
||||||
* 'index' is an index on 'rel'.
|
|
||||||
* 'indexcol' is a column number of 'index' (counting from 0).
|
* 'indexcol' is a column number of 'index' (counting from 0).
|
||||||
* 'opclass' is the corresponding operator class.
|
* 'opclass' is the corresponding operator class.
|
||||||
* 'rinfo' is the clause to be tested (as a RestrictInfo node).
|
* 'rinfo' is the clause to be tested (as a RestrictInfo node).
|
||||||
|
@ -551,8 +533,7 @@ group_clauses_by_indexkey_for_or(RelOptInfo *rel,
|
||||||
* responsibility of higher-level routines to cope with those.
|
* responsibility of higher-level routines to cope with those.
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool
|
||||||
match_clause_to_indexcol(RelOptInfo *rel,
|
match_clause_to_indexcol(IndexOptInfo *index,
|
||||||
IndexOptInfo *index,
|
|
||||||
int indexcol,
|
int indexcol,
|
||||||
Oid opclass,
|
Oid opclass,
|
||||||
RestrictInfo *rinfo)
|
RestrictInfo *rinfo)
|
||||||
|
@ -564,8 +545,7 @@ match_clause_to_indexcol(RelOptInfo *rel,
|
||||||
/* First check for boolean-index cases. */
|
/* First check for boolean-index cases. */
|
||||||
if (IsBooleanOpclass(opclass))
|
if (IsBooleanOpclass(opclass))
|
||||||
{
|
{
|
||||||
if (match_boolean_index_clause((Node *) clause,
|
if (match_boolean_index_clause((Node *) clause, indexcol, index))
|
||||||
indexcol, rel, index))
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -582,7 +562,7 @@ match_clause_to_indexcol(RelOptInfo *rel,
|
||||||
* (constant operator indexkey). Anything that is a "pseudo constant"
|
* (constant operator indexkey). Anything that is a "pseudo constant"
|
||||||
* expression will do.
|
* expression will do.
|
||||||
*/
|
*/
|
||||||
if (match_index_to_operand(leftop, indexcol, rel, index) &&
|
if (match_index_to_operand(leftop, indexcol, index) &&
|
||||||
is_pseudo_constant_clause_relids(rightop, rinfo->right_relids))
|
is_pseudo_constant_clause_relids(rightop, rinfo->right_relids))
|
||||||
{
|
{
|
||||||
if (is_indexable_operator(clause, opclass, true))
|
if (is_indexable_operator(clause, opclass, true))
|
||||||
|
@ -597,7 +577,7 @@ match_clause_to_indexcol(RelOptInfo *rel,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (match_index_to_operand(rightop, indexcol, rel, index) &&
|
if (match_index_to_operand(rightop, indexcol, index) &&
|
||||||
is_pseudo_constant_clause_relids(leftop, rinfo->left_relids))
|
is_pseudo_constant_clause_relids(leftop, rinfo->left_relids))
|
||||||
{
|
{
|
||||||
if (is_indexable_operator(clause, opclass, false))
|
if (is_indexable_operator(clause, opclass, false))
|
||||||
|
@ -638,8 +618,7 @@ match_clause_to_indexcol(RelOptInfo *rel,
|
||||||
* expressions like (a.f1 OP (b.f2 OP a.f3)); that's not processable by
|
* expressions like (a.f1 OP (b.f2 OP a.f3)); that's not processable by
|
||||||
* an indexscan nestloop join, whereas (a.f1 OP (b.f2 OP c.f3)) is.
|
* an indexscan nestloop join, whereas (a.f1 OP (b.f2 OP c.f3)) is.
|
||||||
*
|
*
|
||||||
* 'rel' is the relation of interest.
|
* 'index' is the index of interest.
|
||||||
* 'index' is an index on 'rel'.
|
|
||||||
* 'indexcol' is a column number of 'index' (counting from 0).
|
* 'indexcol' is a column number of 'index' (counting from 0).
|
||||||
* 'opclass' is the corresponding operator class.
|
* 'opclass' is the corresponding operator class.
|
||||||
* 'rinfo' is the clause to be tested (as a RestrictInfo node).
|
* 'rinfo' is the clause to be tested (as a RestrictInfo node).
|
||||||
|
@ -650,8 +629,7 @@ match_clause_to_indexcol(RelOptInfo *rel,
|
||||||
* responsibility of higher-level routines to cope with those.
|
* responsibility of higher-level routines to cope with those.
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool
|
||||||
match_join_clause_to_indexcol(RelOptInfo *rel,
|
match_join_clause_to_indexcol(IndexOptInfo *index,
|
||||||
IndexOptInfo *index,
|
|
||||||
int indexcol,
|
int indexcol,
|
||||||
Oid opclass,
|
Oid opclass,
|
||||||
RestrictInfo *rinfo)
|
RestrictInfo *rinfo)
|
||||||
|
@ -674,25 +652,25 @@ match_join_clause_to_indexcol(RelOptInfo *rel,
|
||||||
* none of the indexed relation's vars and contains no volatile
|
* none of the indexed relation's vars and contains no volatile
|
||||||
* functions.
|
* functions.
|
||||||
*/
|
*/
|
||||||
if (match_index_to_operand(leftop, indexcol, rel, index))
|
if (match_index_to_operand(leftop, indexcol, index))
|
||||||
{
|
{
|
||||||
Relids othervarnos = rinfo->right_relids;
|
Relids othervarnos = rinfo->right_relids;
|
||||||
bool isIndexable;
|
bool isIndexable;
|
||||||
|
|
||||||
isIndexable =
|
isIndexable =
|
||||||
!bms_overlap(rel->relids, othervarnos) &&
|
!bms_overlap(index->rel->relids, othervarnos) &&
|
||||||
!contain_volatile_functions(rightop) &&
|
!contain_volatile_functions(rightop) &&
|
||||||
is_indexable_operator(clause, opclass, true);
|
is_indexable_operator(clause, opclass, true);
|
||||||
return isIndexable;
|
return isIndexable;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (match_index_to_operand(rightop, indexcol, rel, index))
|
if (match_index_to_operand(rightop, indexcol, index))
|
||||||
{
|
{
|
||||||
Relids othervarnos = rinfo->left_relids;
|
Relids othervarnos = rinfo->left_relids;
|
||||||
bool isIndexable;
|
bool isIndexable;
|
||||||
|
|
||||||
isIndexable =
|
isIndexable =
|
||||||
!bms_overlap(rel->relids, othervarnos) &&
|
!bms_overlap(index->rel->relids, othervarnos) &&
|
||||||
!contain_volatile_functions(leftop) &&
|
!contain_volatile_functions(leftop) &&
|
||||||
is_indexable_operator(clause, opclass, false);
|
is_indexable_operator(clause, opclass, false);
|
||||||
return isIndexable;
|
return isIndexable;
|
||||||
|
@ -1423,16 +1401,14 @@ pred_test_simple_clause(Expr *predicate, Node *clause)
|
||||||
* indexable_outerrelids
|
* indexable_outerrelids
|
||||||
* Finds all other relids that participate in any indexable join clause
|
* Finds all other relids that participate in any indexable join clause
|
||||||
* for the specified index. Returns a set of relids.
|
* for the specified index. Returns a set of relids.
|
||||||
*
|
|
||||||
* 'rel' is the relation for which 'index' is defined
|
|
||||||
*/
|
*/
|
||||||
static Relids
|
static Relids
|
||||||
indexable_outerrelids(RelOptInfo *rel, IndexOptInfo *index)
|
indexable_outerrelids(IndexOptInfo *index)
|
||||||
{
|
{
|
||||||
Relids outer_relids = NULL;
|
Relids outer_relids = NULL;
|
||||||
ListCell *l;
|
ListCell *l;
|
||||||
|
|
||||||
foreach(l, rel->joininfo)
|
foreach(l, index->rel->joininfo)
|
||||||
{
|
{
|
||||||
JoinInfo *joininfo = (JoinInfo *) lfirst(l);
|
JoinInfo *joininfo = (JoinInfo *) lfirst(l);
|
||||||
bool match_found = false;
|
bool match_found = false;
|
||||||
|
@ -1455,8 +1431,7 @@ indexable_outerrelids(RelOptInfo *rel, IndexOptInfo *index)
|
||||||
{
|
{
|
||||||
Oid curClass = classes[0];
|
Oid curClass = classes[0];
|
||||||
|
|
||||||
if (match_join_clause_to_indexcol(rel,
|
if (match_join_clause_to_indexcol(index,
|
||||||
index,
|
|
||||||
indexcol,
|
indexcol,
|
||||||
curClass,
|
curClass,
|
||||||
rinfo))
|
rinfo))
|
||||||
|
@ -1614,7 +1589,6 @@ best_inner_indexscan(Query *root, RelOptInfo *rel,
|
||||||
|
|
||||||
/* find useful clauses for this index and outerjoin set */
|
/* find useful clauses for this index and outerjoin set */
|
||||||
clausegroups = group_clauses_by_indexkey_for_join(root,
|
clausegroups = group_clauses_by_indexkey_for_join(root,
|
||||||
rel,
|
|
||||||
index,
|
index,
|
||||||
index_outer_relids,
|
index_outer_relids,
|
||||||
jointype,
|
jointype,
|
||||||
|
@ -1622,8 +1596,7 @@ best_inner_indexscan(Query *root, RelOptInfo *rel,
|
||||||
if (clausegroups)
|
if (clausegroups)
|
||||||
{
|
{
|
||||||
/* make the path */
|
/* make the path */
|
||||||
path = make_innerjoin_index_path(root, rel, index,
|
path = make_innerjoin_index_path(root, index, clausegroups);
|
||||||
clausegroups);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Cache the result --- whether positive or negative */
|
/* Cache the result --- whether positive or negative */
|
||||||
|
@ -1661,15 +1634,16 @@ best_inner_indexscan(Query *root, RelOptInfo *rel,
|
||||||
* Create an index path node for a path to be used as an inner
|
* Create an index path node for a path to be used as an inner
|
||||||
* relation in a nestloop join.
|
* relation in a nestloop join.
|
||||||
*
|
*
|
||||||
* 'rel' is the relation for which 'index' is defined
|
* 'index' is the index of interest
|
||||||
* 'clausegroups' is a list of lists of RestrictInfos that can use 'index'
|
* 'clausegroups' is a list of lists of RestrictInfos that can use 'index'
|
||||||
*/
|
*/
|
||||||
static Path *
|
static Path *
|
||||||
make_innerjoin_index_path(Query *root,
|
make_innerjoin_index_path(Query *root,
|
||||||
RelOptInfo *rel, IndexOptInfo *index,
|
IndexOptInfo *index,
|
||||||
List *clausegroups)
|
List *clausegroups)
|
||||||
{
|
{
|
||||||
IndexPath *pathnode = makeNode(IndexPath);
|
IndexPath *pathnode = makeNode(IndexPath);
|
||||||
|
RelOptInfo *rel = index->rel;
|
||||||
List *indexquals,
|
List *indexquals,
|
||||||
*allclauses;
|
*allclauses;
|
||||||
|
|
||||||
|
@ -1686,7 +1660,7 @@ make_innerjoin_index_path(Query *root,
|
||||||
pathnode->path.pathkeys = NIL;
|
pathnode->path.pathkeys = NIL;
|
||||||
|
|
||||||
/* Convert clauses to indexquals the executor can handle */
|
/* Convert clauses to indexquals the executor can handle */
|
||||||
indexquals = expand_indexqual_conditions(rel, index, clausegroups);
|
indexquals = expand_indexqual_conditions(index, clausegroups);
|
||||||
|
|
||||||
/* Flatten the clausegroups list to produce indexclauses list */
|
/* Flatten the clausegroups list to produce indexclauses list */
|
||||||
allclauses = flatten_clausegroups_list(clausegroups);
|
allclauses = flatten_clausegroups_list(clausegroups);
|
||||||
|
@ -1729,7 +1703,7 @@ make_innerjoin_index_path(Query *root,
|
||||||
/* Like costsize.c, force estimate to be at least one row */
|
/* Like costsize.c, force estimate to be at least one row */
|
||||||
pathnode->rows = clamp_row_est(pathnode->rows);
|
pathnode->rows = clamp_row_est(pathnode->rows);
|
||||||
|
|
||||||
cost_index(&pathnode->path, root, rel, index, indexquals, true);
|
cost_index(&pathnode->path, root, index, indexquals, true);
|
||||||
|
|
||||||
return (Path *) pathnode;
|
return (Path *) pathnode;
|
||||||
}
|
}
|
||||||
|
@ -1798,13 +1772,11 @@ make_expr_from_indexclauses(List *indexclauses)
|
||||||
*
|
*
|
||||||
* operand: the nodetree to be compared to the index
|
* operand: the nodetree to be compared to the index
|
||||||
* indexcol: the column number of the index (counting from 0)
|
* indexcol: the column number of the index (counting from 0)
|
||||||
* rel: the parent relation
|
|
||||||
* index: the index of interest
|
* index: the index of interest
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool
|
||||||
match_index_to_operand(Node *operand,
|
match_index_to_operand(Node *operand,
|
||||||
int indexcol,
|
int indexcol,
|
||||||
RelOptInfo *rel,
|
|
||||||
IndexOptInfo *index)
|
IndexOptInfo *index)
|
||||||
{
|
{
|
||||||
int indkey;
|
int indkey;
|
||||||
|
@ -1825,7 +1797,7 @@ match_index_to_operand(Node *operand,
|
||||||
* Simple index column; operand must be a matching Var.
|
* Simple index column; operand must be a matching Var.
|
||||||
*/
|
*/
|
||||||
if (operand && IsA(operand, Var) &&
|
if (operand && IsA(operand, Var) &&
|
||||||
rel->relid == ((Var *) operand)->varno &&
|
index->rel->relid == ((Var *) operand)->varno &&
|
||||||
indkey == ((Var *) operand)->varattno)
|
indkey == ((Var *) operand)->varattno)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1933,17 +1905,16 @@ match_index_to_operand(Node *operand,
|
||||||
static bool
|
static bool
|
||||||
match_boolean_index_clause(Node *clause,
|
match_boolean_index_clause(Node *clause,
|
||||||
int indexcol,
|
int indexcol,
|
||||||
RelOptInfo *rel,
|
|
||||||
IndexOptInfo *index)
|
IndexOptInfo *index)
|
||||||
{
|
{
|
||||||
/* Direct match? */
|
/* Direct match? */
|
||||||
if (match_index_to_operand(clause, indexcol, rel, index))
|
if (match_index_to_operand(clause, indexcol, index))
|
||||||
return true;
|
return true;
|
||||||
/* NOT clause? */
|
/* NOT clause? */
|
||||||
if (not_clause(clause))
|
if (not_clause(clause))
|
||||||
{
|
{
|
||||||
if (match_index_to_operand((Node *) get_notclausearg((Expr *) clause),
|
if (match_index_to_operand((Node *) get_notclausearg((Expr *) clause),
|
||||||
indexcol, rel, index))
|
indexcol, index))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
@ -1958,7 +1929,7 @@ match_boolean_index_clause(Node *clause,
|
||||||
if (btest->booltesttype == IS_TRUE ||
|
if (btest->booltesttype == IS_TRUE ||
|
||||||
btest->booltesttype == IS_FALSE)
|
btest->booltesttype == IS_FALSE)
|
||||||
if (match_index_to_operand((Node *) btest->arg,
|
if (match_index_to_operand((Node *) btest->arg,
|
||||||
indexcol, rel, index))
|
indexcol, index))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -2135,7 +2106,7 @@ match_special_index_operator(Expr *clause, Oid opclass,
|
||||||
* someday --- tgl 7/00)
|
* someday --- tgl 7/00)
|
||||||
*/
|
*/
|
||||||
List *
|
List *
|
||||||
expand_indexqual_conditions(RelOptInfo *rel, IndexOptInfo *index, List *clausegroups)
|
expand_indexqual_conditions(IndexOptInfo *index, List *clausegroups)
|
||||||
{
|
{
|
||||||
List *resultquals = NIL;
|
List *resultquals = NIL;
|
||||||
ListCell *clausegroup_item;
|
ListCell *clausegroup_item;
|
||||||
|
@ -2162,7 +2133,6 @@ expand_indexqual_conditions(RelOptInfo *rel, IndexOptInfo *index, List *clausegr
|
||||||
|
|
||||||
boolqual = expand_boolean_index_clause((Node *) rinfo->clause,
|
boolqual = expand_boolean_index_clause((Node *) rinfo->clause,
|
||||||
indexcol,
|
indexcol,
|
||||||
rel,
|
|
||||||
index);
|
index);
|
||||||
if (boolqual)
|
if (boolqual)
|
||||||
{
|
{
|
||||||
|
@ -2199,11 +2169,10 @@ expand_indexqual_conditions(RelOptInfo *rel, IndexOptInfo *index, List *clausegr
|
||||||
static Expr *
|
static Expr *
|
||||||
expand_boolean_index_clause(Node *clause,
|
expand_boolean_index_clause(Node *clause,
|
||||||
int indexcol,
|
int indexcol,
|
||||||
RelOptInfo *rel,
|
|
||||||
IndexOptInfo *index)
|
IndexOptInfo *index)
|
||||||
{
|
{
|
||||||
/* Direct match? */
|
/* Direct match? */
|
||||||
if (match_index_to_operand(clause, indexcol, rel, index))
|
if (match_index_to_operand(clause, indexcol, index))
|
||||||
{
|
{
|
||||||
/* convert to indexkey = TRUE */
|
/* convert to indexkey = TRUE */
|
||||||
return make_opclause(BooleanEqualOperator, BOOLOID, false,
|
return make_opclause(BooleanEqualOperator, BOOLOID, false,
|
||||||
|
@ -2216,7 +2185,7 @@ expand_boolean_index_clause(Node *clause,
|
||||||
Node *arg = (Node *) get_notclausearg((Expr *) clause);
|
Node *arg = (Node *) get_notclausearg((Expr *) clause);
|
||||||
|
|
||||||
/* It must have matched the indexkey */
|
/* It must have matched the indexkey */
|
||||||
Assert(match_index_to_operand(arg, indexcol, rel, index));
|
Assert(match_index_to_operand(arg, indexcol, index));
|
||||||
/* convert to indexkey = FALSE */
|
/* convert to indexkey = FALSE */
|
||||||
return make_opclause(BooleanEqualOperator, BOOLOID, false,
|
return make_opclause(BooleanEqualOperator, BOOLOID, false,
|
||||||
(Expr *) arg,
|
(Expr *) arg,
|
||||||
|
@ -2228,7 +2197,7 @@ expand_boolean_index_clause(Node *clause,
|
||||||
Node *arg = (Node *) btest->arg;
|
Node *arg = (Node *) btest->arg;
|
||||||
|
|
||||||
/* It must have matched the indexkey */
|
/* It must have matched the indexkey */
|
||||||
Assert(match_index_to_operand(arg, indexcol, rel, index));
|
Assert(match_index_to_operand(arg, indexcol, index));
|
||||||
if (btest->booltesttype == IS_TRUE)
|
if (btest->booltesttype == IS_TRUE)
|
||||||
{
|
{
|
||||||
/* convert to indexkey = TRUE */
|
/* convert to indexkey = TRUE */
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/optimizer/path/orindxpath.c,v 1.66 2005/03/26 23:29:17 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/optimizer/path/orindxpath.c,v 1.67 2005/03/27 06:29:36 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -383,7 +383,7 @@ best_or_subclause_index(Query *root,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Collect index clauses usable with this index */
|
/* Collect index clauses usable with this index */
|
||||||
indexclauses = group_clauses_by_indexkey_for_or(rel, index, subclause);
|
indexclauses = group_clauses_by_indexkey_for_or(index, subclause);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Ignore index if it doesn't match the subclause at all; except
|
* Ignore index if it doesn't match the subclause at all; except
|
||||||
|
@ -398,9 +398,9 @@ best_or_subclause_index(Query *root,
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Convert clauses to indexquals the executor can handle */
|
/* Convert clauses to indexquals the executor can handle */
|
||||||
indexquals = expand_indexqual_conditions(rel, index, indexclauses);
|
indexquals = expand_indexqual_conditions(index, indexclauses);
|
||||||
|
|
||||||
cost_index(&subclause_path, root, rel, index, indexquals, false);
|
cost_index(&subclause_path, root, index, indexquals, false);
|
||||||
|
|
||||||
if (!found || subclause_path.total_cost < *retTotalCost)
|
if (!found || subclause_path.total_cost < *retTotalCost)
|
||||||
{
|
{
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/optimizer/path/pathkeys.c,v 1.64 2005/01/23 02:21:26 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/optimizer/path/pathkeys.c,v 1.65 2005/03/27 06:29:36 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -648,7 +648,6 @@ get_cheapest_fractional_path_for_pathkeys(List *paths,
|
||||||
*/
|
*/
|
||||||
List *
|
List *
|
||||||
build_index_pathkeys(Query *root,
|
build_index_pathkeys(Query *root,
|
||||||
RelOptInfo *rel,
|
|
||||||
IndexOptInfo *index,
|
IndexOptInfo *index,
|
||||||
ScanDirection scandir)
|
ScanDirection scandir)
|
||||||
{
|
{
|
||||||
|
@ -675,7 +674,8 @@ build_index_pathkeys(Query *root,
|
||||||
if (*indexkeys != 0)
|
if (*indexkeys != 0)
|
||||||
{
|
{
|
||||||
/* simple index column */
|
/* simple index column */
|
||||||
indexkey = (Node *) find_indexkey_var(root, rel, *indexkeys);
|
indexkey = (Node *) find_indexkey_var(root, index->rel,
|
||||||
|
*indexkeys);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.176 2005/03/10 23:21:22 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.177 2005/03/27 06:29:38 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -65,16 +65,13 @@ static void fix_indxqual_references(List *indexquals, IndexPath *index_path,
|
||||||
List **indxstrategy,
|
List **indxstrategy,
|
||||||
List **indxsubtype,
|
List **indxsubtype,
|
||||||
List **indxlossy);
|
List **indxlossy);
|
||||||
static void fix_indxqual_sublist(List *indexqual,
|
static void fix_indxqual_sublist(List *indexqual, IndexOptInfo *index,
|
||||||
Relids baserelids, int baserelid,
|
|
||||||
IndexOptInfo *index,
|
|
||||||
List **fixed_quals,
|
List **fixed_quals,
|
||||||
List **strategy,
|
List **strategy,
|
||||||
List **subtype,
|
List **subtype,
|
||||||
List **lossy);
|
List **lossy);
|
||||||
static Node *fix_indxqual_operand(Node *node, int baserelid,
|
static Node *fix_indxqual_operand(Node *node, IndexOptInfo *index,
|
||||||
IndexOptInfo *index,
|
Oid *opclass);
|
||||||
Oid *opclass);
|
|
||||||
static List *get_switched_clauses(List *clauses, Relids outerrelids);
|
static List *get_switched_clauses(List *clauses, Relids outerrelids);
|
||||||
static List *order_qual_clauses(Query *root, List *clauses);
|
static List *order_qual_clauses(Query *root, List *clauses);
|
||||||
static void copy_path_costsize(Plan *dest, Path *src);
|
static void copy_path_costsize(Plan *dest, Path *src);
|
||||||
|
@ -1179,8 +1176,6 @@ fix_indxqual_references(List *indexquals, IndexPath *index_path,
|
||||||
List **indxsubtype,
|
List **indxsubtype,
|
||||||
List **indxlossy)
|
List **indxlossy)
|
||||||
{
|
{
|
||||||
Relids baserelids = index_path->path.parent->relids;
|
|
||||||
int baserelid = index_path->path.parent->relid;
|
|
||||||
List *index_info = index_path->indexinfo;
|
List *index_info = index_path->indexinfo;
|
||||||
ListCell *iq,
|
ListCell *iq,
|
||||||
*ii;
|
*ii;
|
||||||
|
@ -1198,7 +1193,7 @@ fix_indxqual_references(List *indexquals, IndexPath *index_path,
|
||||||
List *subtype;
|
List *subtype;
|
||||||
List *lossy;
|
List *lossy;
|
||||||
|
|
||||||
fix_indxqual_sublist(indexqual, baserelids, baserelid, index,
|
fix_indxqual_sublist(indexqual, index,
|
||||||
&fixed_qual, &strategy, &subtype, &lossy);
|
&fixed_qual, &strategy, &subtype, &lossy);
|
||||||
*fixed_indexquals = lappend(*fixed_indexquals, fixed_qual);
|
*fixed_indexquals = lappend(*fixed_indexquals, fixed_qual);
|
||||||
*indxstrategy = lappend(*indxstrategy, strategy);
|
*indxstrategy = lappend(*indxstrategy, strategy);
|
||||||
|
@ -1222,9 +1217,7 @@ fix_indxqual_references(List *indexquals, IndexPath *index_path,
|
||||||
* the integer list of lossiness flags (1/0)
|
* the integer list of lossiness flags (1/0)
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
fix_indxqual_sublist(List *indexqual,
|
fix_indxqual_sublist(List *indexqual, IndexOptInfo *index,
|
||||||
Relids baserelids, int baserelid,
|
|
||||||
IndexOptInfo *index,
|
|
||||||
List **fixed_quals,
|
List **fixed_quals,
|
||||||
List **strategy,
|
List **strategy,
|
||||||
List **subtype,
|
List **subtype,
|
||||||
|
@ -1265,7 +1258,7 @@ fix_indxqual_sublist(List *indexqual,
|
||||||
* the clause. The indexkey should be the side that refers to
|
* the clause. The indexkey should be the side that refers to
|
||||||
* (only) the base relation.
|
* (only) the base relation.
|
||||||
*/
|
*/
|
||||||
if (!bms_equal(rinfo->left_relids, baserelids))
|
if (!bms_equal(rinfo->left_relids, index->rel->relids))
|
||||||
CommuteClause(newclause);
|
CommuteClause(newclause);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1273,7 +1266,6 @@ fix_indxqual_sublist(List *indexqual,
|
||||||
* indexkey operand as needed, and get the index opclass.
|
* indexkey operand as needed, and get the index opclass.
|
||||||
*/
|
*/
|
||||||
linitial(newclause->args) = fix_indxqual_operand(linitial(newclause->args),
|
linitial(newclause->args) = fix_indxqual_operand(linitial(newclause->args),
|
||||||
baserelid,
|
|
||||||
index,
|
index,
|
||||||
&opclass);
|
&opclass);
|
||||||
|
|
||||||
|
@ -1295,8 +1287,7 @@ fix_indxqual_sublist(List *indexqual,
|
||||||
}
|
}
|
||||||
|
|
||||||
static Node *
|
static Node *
|
||||||
fix_indxqual_operand(Node *node, int baserelid, IndexOptInfo *index,
|
fix_indxqual_operand(Node *node, IndexOptInfo *index, Oid *opclass)
|
||||||
Oid *opclass)
|
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* We represent index keys by Var nodes having the varno of the base
|
* We represent index keys by Var nodes having the varno of the base
|
||||||
|
@ -1316,7 +1307,7 @@ fix_indxqual_operand(Node *node, int baserelid, IndexOptInfo *index,
|
||||||
node = (Node *) ((RelabelType *) node)->arg;
|
node = (Node *) ((RelabelType *) node)->arg;
|
||||||
|
|
||||||
if (IsA(node, Var) &&
|
if (IsA(node, Var) &&
|
||||||
((Var *) node)->varno == baserelid)
|
((Var *) node)->varno == index->rel->relid)
|
||||||
{
|
{
|
||||||
/* Try to match against simple index columns */
|
/* Try to match against simple index columns */
|
||||||
int varatt = ((Var *) node)->varattno;
|
int varatt = ((Var *) node)->varattno;
|
||||||
|
@ -1353,7 +1344,7 @@ fix_indxqual_operand(Node *node, int baserelid, IndexOptInfo *index,
|
||||||
if (equal(node, indexkey))
|
if (equal(node, indexkey))
|
||||||
{
|
{
|
||||||
/* Found a match */
|
/* Found a match */
|
||||||
result = makeVar(baserelid, pos + 1,
|
result = makeVar(index->rel->relid, pos + 1,
|
||||||
exprType(lfirst(indexpr_item)), -1,
|
exprType(lfirst(indexpr_item)), -1,
|
||||||
0);
|
0);
|
||||||
/* return the correct opclass, too */
|
/* return the correct opclass, too */
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/optimizer/util/pathnode.c,v 1.113 2005/03/26 23:29:18 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/optimizer/util/pathnode.c,v 1.114 2005/03/27 06:29:42 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -417,8 +417,7 @@ create_seqscan_path(Query *root, RelOptInfo *rel)
|
||||||
* create_index_path
|
* create_index_path
|
||||||
* Creates a path node for an index scan.
|
* Creates a path node for an index scan.
|
||||||
*
|
*
|
||||||
* 'rel' is the parent rel
|
* 'index' is a usable index.
|
||||||
* 'index' is an index on 'rel'
|
|
||||||
* 'restriction_clauses' is a list of lists of RestrictInfo nodes
|
* 'restriction_clauses' is a list of lists of RestrictInfo nodes
|
||||||
* to be used as index qual conditions in the scan.
|
* to be used as index qual conditions in the scan.
|
||||||
* 'pathkeys' describes the ordering of the path.
|
* 'pathkeys' describes the ordering of the path.
|
||||||
|
@ -430,7 +429,6 @@ create_seqscan_path(Query *root, RelOptInfo *rel)
|
||||||
*/
|
*/
|
||||||
IndexPath *
|
IndexPath *
|
||||||
create_index_path(Query *root,
|
create_index_path(Query *root,
|
||||||
RelOptInfo *rel,
|
|
||||||
IndexOptInfo *index,
|
IndexOptInfo *index,
|
||||||
List *restriction_clauses,
|
List *restriction_clauses,
|
||||||
List *pathkeys,
|
List *pathkeys,
|
||||||
|
@ -440,11 +438,11 @@ create_index_path(Query *root,
|
||||||
List *indexquals;
|
List *indexquals;
|
||||||
|
|
||||||
pathnode->path.pathtype = T_IndexScan;
|
pathnode->path.pathtype = T_IndexScan;
|
||||||
pathnode->path.parent = rel;
|
pathnode->path.parent = index->rel;
|
||||||
pathnode->path.pathkeys = pathkeys;
|
pathnode->path.pathkeys = pathkeys;
|
||||||
|
|
||||||
/* Convert clauses to indexquals the executor can handle */
|
/* Convert clauses to indexquals the executor can handle */
|
||||||
indexquals = expand_indexqual_conditions(rel, index, restriction_clauses);
|
indexquals = expand_indexqual_conditions(index, restriction_clauses);
|
||||||
|
|
||||||
/* Flatten the clause-groups list to produce indexclauses list */
|
/* Flatten the clause-groups list to produce indexclauses list */
|
||||||
restriction_clauses = flatten_clausegroups_list(restriction_clauses);
|
restriction_clauses = flatten_clausegroups_list(restriction_clauses);
|
||||||
|
@ -466,9 +464,9 @@ create_index_path(Query *root,
|
||||||
* The number of rows is the same as the parent rel's estimate, since
|
* The number of rows is the same as the parent rel's estimate, since
|
||||||
* this isn't a join inner indexscan.
|
* this isn't a join inner indexscan.
|
||||||
*/
|
*/
|
||||||
pathnode->rows = rel->rows;
|
pathnode->rows = index->rel->rows;
|
||||||
|
|
||||||
cost_index(&pathnode->path, root, rel, index, indexquals, false);
|
cost_index(&pathnode->path, root, index, indexquals, false);
|
||||||
|
|
||||||
return pathnode;
|
return pathnode;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/optimizer/util/plancat.c,v 1.101 2005/03/24 19:14:49 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/optimizer/util/plancat.c,v 1.102 2005/03/27 06:29:42 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -124,6 +124,7 @@ get_relation_info(Oid relationObjectId, RelOptInfo *rel)
|
||||||
info = makeNode(IndexOptInfo);
|
info = makeNode(IndexOptInfo);
|
||||||
|
|
||||||
info->indexoid = index->indexrelid;
|
info->indexoid = index->indexrelid;
|
||||||
|
info->rel = rel;
|
||||||
info->ncolumns = ncolumns = index->indnatts;
|
info->ncolumns = ncolumns = index->indnatts;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.103 2005/02/21 06:43:04 neilc Exp $
|
* $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.104 2005/03/27 06:29:45 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -253,6 +253,7 @@ typedef struct IndexOptInfo
|
||||||
NodeTag type;
|
NodeTag type;
|
||||||
|
|
||||||
Oid indexoid; /* OID of the index relation */
|
Oid indexoid; /* OID of the index relation */
|
||||||
|
RelOptInfo *rel; /* back-link to index's table */
|
||||||
|
|
||||||
/* statistics from pg_class */
|
/* statistics from pg_class */
|
||||||
BlockNumber pages; /* number of disk pages in index */
|
BlockNumber pages; /* number of disk pages in index */
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/optimizer/cost.h,v 1.62 2004/12/31 22:03:36 pgsql Exp $
|
* $PostgreSQL: pgsql/src/include/optimizer/cost.h,v 1.63 2005/03/27 06:29:49 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -50,10 +50,8 @@ extern bool enable_mergejoin;
|
||||||
extern bool enable_hashjoin;
|
extern bool enable_hashjoin;
|
||||||
|
|
||||||
extern double clamp_row_est(double nrows);
|
extern double clamp_row_est(double nrows);
|
||||||
extern void cost_seqscan(Path *path, Query *root,
|
extern void cost_seqscan(Path *path, Query *root, RelOptInfo *baserel);
|
||||||
RelOptInfo *baserel);
|
extern void cost_index(Path *path, Query *root, IndexOptInfo *index,
|
||||||
extern void cost_index(Path *path, Query *root,
|
|
||||||
RelOptInfo *baserel, IndexOptInfo *index,
|
|
||||||
List *indexQuals, bool is_injoin);
|
List *indexQuals, bool is_injoin);
|
||||||
extern void cost_tidscan(Path *path, Query *root,
|
extern void cost_tidscan(Path *path, Query *root,
|
||||||
RelOptInfo *baserel, List *tideval);
|
RelOptInfo *baserel, List *tideval);
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/optimizer/pathnode.h,v 1.56 2004/12/31 22:03:36 pgsql Exp $
|
* $PostgreSQL: pgsql/src/include/optimizer/pathnode.h,v 1.57 2005/03/27 06:29:49 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -28,7 +28,7 @@ extern void set_cheapest(RelOptInfo *parent_rel);
|
||||||
extern void add_path(RelOptInfo *parent_rel, Path *new_path);
|
extern void add_path(RelOptInfo *parent_rel, Path *new_path);
|
||||||
|
|
||||||
extern Path *create_seqscan_path(Query *root, RelOptInfo *rel);
|
extern Path *create_seqscan_path(Query *root, RelOptInfo *rel);
|
||||||
extern IndexPath *create_index_path(Query *root, RelOptInfo *rel,
|
extern IndexPath *create_index_path(Query *root,
|
||||||
IndexOptInfo *index,
|
IndexOptInfo *index,
|
||||||
List *restriction_clauses,
|
List *restriction_clauses,
|
||||||
List *pathkeys,
|
List *pathkeys,
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/optimizer/paths.h,v 1.79 2005/03/26 23:29:20 tgl Exp $
|
* $PostgreSQL: pgsql/src/include/optimizer/paths.h,v 1.80 2005/03/27 06:29:49 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -38,11 +38,9 @@ extern void debug_print_rel(Query *root, RelOptInfo *rel);
|
||||||
extern void create_index_paths(Query *root, RelOptInfo *rel);
|
extern void create_index_paths(Query *root, RelOptInfo *rel);
|
||||||
extern Path *best_inner_indexscan(Query *root, RelOptInfo *rel,
|
extern Path *best_inner_indexscan(Query *root, RelOptInfo *rel,
|
||||||
Relids outer_relids, JoinType jointype);
|
Relids outer_relids, JoinType jointype);
|
||||||
extern List *group_clauses_by_indexkey_for_or(RelOptInfo *rel,
|
extern List *group_clauses_by_indexkey_for_or(IndexOptInfo *index,
|
||||||
IndexOptInfo *index,
|
|
||||||
Expr *orsubclause);
|
Expr *orsubclause);
|
||||||
extern List *expand_indexqual_conditions(RelOptInfo *rel,
|
extern List *expand_indexqual_conditions(IndexOptInfo *index,
|
||||||
IndexOptInfo *index,
|
|
||||||
List *clausegroups);
|
List *clausegroups);
|
||||||
extern void check_partial_indexes(Query *root, RelOptInfo *rel);
|
extern void check_partial_indexes(Query *root, RelOptInfo *rel);
|
||||||
extern bool pred_test(List *predicate_list, List *restrictinfo_list);
|
extern bool pred_test(List *predicate_list, List *restrictinfo_list);
|
||||||
|
@ -108,8 +106,7 @@ extern Path *get_cheapest_path_for_pathkeys(List *paths, List *pathkeys,
|
||||||
extern Path *get_cheapest_fractional_path_for_pathkeys(List *paths,
|
extern Path *get_cheapest_fractional_path_for_pathkeys(List *paths,
|
||||||
List *pathkeys,
|
List *pathkeys,
|
||||||
double fraction);
|
double fraction);
|
||||||
extern List *build_index_pathkeys(Query *root, RelOptInfo *rel,
|
extern List *build_index_pathkeys(Query *root, IndexOptInfo *index,
|
||||||
IndexOptInfo *index,
|
|
||||||
ScanDirection scandir);
|
ScanDirection scandir);
|
||||||
extern List *build_subquery_pathkeys(Query *root, RelOptInfo *rel,
|
extern List *build_subquery_pathkeys(Query *root, RelOptInfo *rel,
|
||||||
Query *subquery);
|
Query *subquery);
|
||||||
|
|
Loading…
Reference in New Issue