aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/plan/createplan.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/plan/createplan.c')
-rw-r--r--src/backend/optimizer/plan/createplan.c133
1 files changed, 48 insertions, 85 deletions
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index 2d264c46881..81e7fec0427 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.105 2001/05/07 00:43:20 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.106 2001/05/20 20:28:18 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -18,7 +18,6 @@
#include <sys/types.h>
-#include "catalog/pg_index.h"
#include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h"
#include "optimizer/clauses.h"
@@ -27,6 +26,7 @@
#include "optimizer/planmain.h"
#include "optimizer/restrictinfo.h"
#include "optimizer/tlist.h"
+#include "optimizer/var.h"
#include "parser/parse_expr.h"
#include "utils/lsyscache.h"
#include "utils/syscache.h"
@@ -56,11 +56,11 @@ static HashJoin *create_hashjoin_plan(HashPath *best_path, List *tlist,
Plan *outer_plan, List *outer_tlist,
Plan *inner_plan, List *inner_tlist);
static List *fix_indxqual_references(List *indexquals, IndexPath *index_path);
-static List *fix_indxqual_sublist(List *indexqual, int baserelid, Oid relam,
- Form_pg_index index);
+static List *fix_indxqual_sublist(List *indexqual, int baserelid,
+ IndexOptInfo *index);
static Node *fix_indxqual_operand(Node *node, int baserelid,
- Form_pg_index index,
- Oid *opclass);
+ IndexOptInfo *index,
+ Oid *opclass);
static List *switch_outer(List *clauses);
static void copy_path_costsize(Plan *dest, Path *src);
static void copy_plan_costsize(Plan *dest, Plan *src);
@@ -365,7 +365,7 @@ create_seqscan_plan(Path *best_path, List *tlist, List *scan_clauses)
* The indexqual of the path contains a sublist of implicitly-ANDed qual
* conditions for each scan of the index(es); if there is more than one
* scan then the retrieved tuple sets are ORed together. The indexqual
- * and indexid lists must have the same length, ie, the number of scans
+ * and indexinfo lists must have the same length, ie, the number of scans
* that will occur. Note it is possible for a qual condition sublist
* to be empty --- then no index restrictions will be applied during that
* scan.
@@ -380,9 +380,10 @@ create_indexscan_plan(Query *root,
Index baserelid;
List *qpqual;
List *fixed_indxqual;
- List *ixid;
+ List *indexids;
+ List *ixinfo;
IndexScan *scan_plan;
- bool lossy = false;
+ bool lossy;
/* there should be exactly one base rel involved... */
Assert(length(best_path->path.parent->relids) == 1);
@@ -390,25 +391,18 @@ create_indexscan_plan(Query *root,
baserelid = lfirsti(best_path->path.parent->relids);
- /* check to see if any of the indices are lossy */
- foreach(ixid, best_path->indexid)
+ /*
+ * Build list of index OIDs, and check to see if any of the indices
+ * are lossy.
+ */
+ indexids = NIL;
+ lossy = false;
+ foreach(ixinfo, best_path->indexinfo)
{
- HeapTuple indexTuple;
- Form_pg_index index;
-
- indexTuple = SearchSysCache(INDEXRELID,
- ObjectIdGetDatum(lfirsti(ixid)),
- 0, 0, 0);
- if (!HeapTupleIsValid(indexTuple))
- elog(ERROR, "create_plan: index %u not found", lfirsti(ixid));
- index = (Form_pg_index) GETSTRUCT(indexTuple);
- if (index->indislossy)
- {
- lossy = true;
- ReleaseSysCache(indexTuple);
- break;
- }
- ReleaseSysCache(indexTuple);
+ IndexOptInfo *index = (IndexOptInfo *) lfirst(ixinfo);
+
+ indexids = lappendi(indexids, index->indexoid);
+ lossy |= index->lossy;
}
/*
@@ -471,7 +465,7 @@ create_indexscan_plan(Query *root,
scan_plan = make_indexscan(tlist,
qpqual,
baserelid,
- best_path->indexid,
+ indexids,
fixed_indxqual,
indxqual,
best_path->indexscandir);
@@ -895,45 +889,19 @@ fix_indxqual_references(List *indexquals, IndexPath *index_path)
{
List *fixed_quals = NIL;
int baserelid = lfirsti(index_path->path.parent->relids);
- List *indexids = index_path->indexid;
+ List *ixinfo = index_path->indexinfo;
List *i;
foreach(i, indexquals)
{
List *indexqual = lfirst(i);
- Oid indexid = lfirsti(indexids);
- HeapTuple indexTuple;
- Oid relam;
- Form_pg_index index;
-
- /* Get the relam from the index's pg_class entry */
- indexTuple = SearchSysCache(RELOID,
- ObjectIdGetDatum(indexid),
- 0, 0, 0);
- if (!HeapTupleIsValid(indexTuple))
- elog(ERROR, "fix_indxqual_references: index %u not found in pg_class",
- indexid);
- relam = ((Form_pg_class) GETSTRUCT(indexTuple))->relam;
- ReleaseSysCache(indexTuple);
-
- /* Need the index's pg_index entry for other stuff */
- indexTuple = SearchSysCache(INDEXRELID,
- ObjectIdGetDatum(indexid),
- 0, 0, 0);
- if (!HeapTupleIsValid(indexTuple))
- elog(ERROR, "fix_indxqual_references: index %u not found in pg_index",
- indexid);
- index = (Form_pg_index) GETSTRUCT(indexTuple);
+ IndexOptInfo *index = (IndexOptInfo *) lfirst(ixinfo);
fixed_quals = lappend(fixed_quals,
fix_indxqual_sublist(indexqual,
baserelid,
- relam,
index));
-
- ReleaseSysCache(indexTuple);
-
- indexids = lnext(indexids);
+ ixinfo = lnext(ixinfo);
}
return fixed_quals;
}
@@ -946,8 +914,7 @@ fix_indxqual_references(List *indexquals, IndexPath *index_path)
* of the clause.) Also change the operator if necessary.
*/
static List *
-fix_indxqual_sublist(List *indexqual, int baserelid, Oid relam,
- Form_pg_index index)
+fix_indxqual_sublist(List *indexqual, int baserelid, IndexOptInfo *index)
{
List *fixed_qual = NIL;
List *i;
@@ -955,27 +922,15 @@ fix_indxqual_sublist(List *indexqual, int baserelid, Oid relam,
foreach(i, indexqual)
{
Expr *clause = (Expr *) lfirst(i);
- int relid;
- AttrNumber attno;
- Datum constval;
- int flag;
Expr *newclause;
+ List *leftvarnos;
Oid opclass,
newopno;
- if (!is_opclause((Node *) clause) ||
- length(clause->args) != 2)
+ if (!is_opclause((Node *) clause) || length(clause->args) != 2)
elog(ERROR, "fix_indxqual_sublist: indexqual clause is not binary opclause");
/*
- * Which side is the indexkey on?
- *
- * get_relattval sets flag&SEL_RIGHT if the indexkey is on the LEFT.
- */
- get_relattval((Node *) clause, baserelid,
- &relid, &attno, &constval, &flag);
-
- /*
* Make a copy that will become the fixed clause.
*
* We used to try to do a shallow copy here, but that fails if there
@@ -984,9 +939,15 @@ fix_indxqual_sublist(List *indexqual, int baserelid, Oid relam,
*/
newclause = (Expr *) copyObject((Node *) clause);
- /* If the indexkey is on the right, commute the clause. */
- if ((flag & SEL_RIGHT) == 0)
+ /*
+ * Check to see if the indexkey is on the right; if so, commute
+ * the clause. The indexkey should be the side that refers to
+ * (only) the base relation.
+ */
+ leftvarnos = pull_varnos((Node *) lfirst(newclause->args));
+ if (length(leftvarnos) != 1 || lfirsti(leftvarnos) != baserelid)
CommuteClause(newclause);
+ freeList(leftvarnos);
/*
* Now, determine which index attribute this is, change the
@@ -1002,7 +963,7 @@ fix_indxqual_sublist(List *indexqual, int baserelid, Oid relam,
* is merely binary-compatible with the index. This shouldn't
* fail, since indxpath.c found it before...
*/
- newopno = indexable_operator(newclause, opclass, relam, true);
+ newopno = indexable_operator(newclause, opclass, index->relam, true);
if (newopno == InvalidOid)
elog(ERROR, "fix_indxqual_sublist: failed to find substitute op");
((Oper *) newclause->oper)->opno = newopno;
@@ -1013,7 +974,7 @@ fix_indxqual_sublist(List *indexqual, int baserelid, Oid relam,
}
static Node *
-fix_indxqual_operand(Node *node, int baserelid, Form_pg_index index,
+fix_indxqual_operand(Node *node, int baserelid, IndexOptInfo *index,
Oid *opclass)
{
@@ -1033,27 +994,29 @@ fix_indxqual_operand(Node *node, int baserelid, Form_pg_index index,
if (IsA(node, Var))
{
/* If it's a var, find which index key position it occupies */
+ Assert(index->indproc == InvalidOid);
+
if (((Var *) node)->varno == baserelid)
{
int varatt = ((Var *) node)->varattno;
int pos;
- for (pos = 0; pos < INDEX_MAX_KEYS; pos++)
+ for (pos = 0; pos < index->nkeys; pos++)
{
- if (index->indkey[pos] == varatt)
+ if (index->indexkeys[pos] == varatt)
{
Node *newnode = copyObject(node);
((Var *) newnode)->varattno = pos + 1;
/* return the correct opclass, too */
- *opclass = index->indclass[pos];
+ *opclass = index->classlist[pos];
return newnode;
}
}
}
/*
- * Oops, this Var isn't the indexkey!
+ * Oops, this Var isn't an indexkey!
*/
elog(ERROR, "fix_indxqual_operand: var is not index attribute");
}
@@ -1063,11 +1026,11 @@ fix_indxqual_operand(Node *node, int baserelid, Form_pg_index index,
* Since we currently only support single-column functional indexes,
* the returned varattno must be 1.
*/
+ Assert(index->indproc != InvalidOid);
+ Assert(is_funcclause(node)); /* not a very thorough check, but easy */
- Assert(is_funcclause(node));/* not a very thorough check, but easy */
-
- /* indclass[0] is the only class of a functional index */
- *opclass = index->indclass[0];
+ /* classlist[0] is the only class of a functional index */
+ *opclass = index->classlist[0];
return (Node *) makeVar(baserelid, 1, exprType(node), -1, 0);
}