summaryrefslogtreecommitdiff
path: root/src/backend/optimizer/util
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2001-05-20 20:28:20 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2001-05-20 20:28:20 +0000
commitbe03eb25f34c9c95c400504ef76c8abe0081d09f (patch)
treeca3b081710826485bdaaad375b80e82f5a7fd611 /src/backend/optimizer/util
parent5d53389cfe5ecacadda12f3a777a642605278e49 (diff)
Modify optimizer data structures so that IndexOptInfo lists built for
create_index_paths are not immediately discarded, but are available for subsequent planner work. This allows avoiding redundant syscache lookups in several places. Change interface to operator selectivity estimation procedures to allow faster and more flexible estimation. Initdb forced due to change of pg_proc entries for selectivity functions!
Diffstat (limited to 'src/backend/optimizer/util')
-rw-r--r--src/backend/optimizer/util/clauses.c199
-rw-r--r--src/backend/optimizer/util/pathnode.c6
-rw-r--r--src/backend/optimizer/util/plancat.c151
-rw-r--r--src/backend/optimizer/util/relnode.c135
4 files changed, 215 insertions, 276 deletions
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index 8bd6ef6f68b..e0cc97e3a1d 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.84 2001/03/27 17:12:34 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.85 2001/05/20 20:28:19 tgl Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
@@ -46,7 +46,6 @@ static bool pull_subplans_walker(Node *node, List **listptr);
static bool check_subplans_for_ungrouped_vars_walker(Node *node,
Query *context);
static bool contain_noncachable_functions_walker(Node *node, void *context);
-static int is_single_func(Node *node);
static Node *eval_const_expressions_mutator(Node *node, void *context);
static Expr *simplify_op_or_func(Expr *expr, List *args);
@@ -797,202 +796,6 @@ NumRelids(Node *clause)
return result;
}
-/*
- * get_relattval
- * Extract information from a restriction or join clause for
- * selectivity estimation. The inputs are an expression
- * and a relation number (which can be 0 if we don't care which
- * relation is used; that'd normally be the case for restriction
- * clauses, where the caller already knows that only one relation
- * is referenced in the clause). The routine checks that the
- * expression is of the form (var op something) or (something op var)
- * where the var is an attribute of the specified relation, or
- * a function of a var of the specified relation. If so, it
- * returns the following info:
- * the found relation number (same as targetrelid unless that is 0)
- * the found var number (or InvalidAttrNumber if a function)
- * if the "something" is a constant, the value of the constant
- * flags indicating whether a constant was found, and on which side.
- * Default values are returned if the expression is too complicated,
- * specifically 0 for the relid and attno, 0 for the constant value.
- *
- * Note that negative attno values are *not* invalid, but represent
- * system attributes such as OID. It's sufficient to check for relid=0
- * to determine whether the routine succeeded.
- */
-void
-get_relattval(Node *clause,
- int targetrelid,
- int *relid,
- AttrNumber *attno,
- Datum *constval,
- int *flag)
-{
- Var *left,
- *right,
- *other;
- int funcvarno;
-
- /* Careful; the passed clause might not be a binary operator at all */
-
- if (!is_opclause(clause))
- goto default_results;
-
- left = get_leftop((Expr *) clause);
- right = get_rightop((Expr *) clause);
-
- if (!right)
- goto default_results;
-
- /* Ignore any binary-compatible relabeling */
-
- if (IsA(left, RelabelType))
- left = (Var *) ((RelabelType *) left)->arg;
- if (IsA(right, RelabelType))
- right = (Var *) ((RelabelType *) right)->arg;
-
- /* First look for the var or func */
-
- if (IsA(left, Var) &&
- (targetrelid == 0 || targetrelid == left->varno))
- {
- *relid = left->varno;
- *attno = left->varattno;
- *flag = SEL_RIGHT;
- }
- else if (IsA(right, Var) &&
- (targetrelid == 0 || targetrelid == right->varno))
- {
- *relid = right->varno;
- *attno = right->varattno;
- *flag = 0;
- }
- else if ((funcvarno = is_single_func((Node *) left)) != 0 &&
- (targetrelid == 0 || targetrelid == funcvarno))
- {
- *relid = funcvarno;
- *attno = InvalidAttrNumber;
- *flag = SEL_RIGHT;
- }
- else if ((funcvarno = is_single_func((Node *) right)) != 0 &&
- (targetrelid == 0 || targetrelid == funcvarno))
- {
- *relid = funcvarno;
- *attno = InvalidAttrNumber;
- *flag = 0;
- }
- else
- {
- /* Duh, it's too complicated for me... */
-default_results:
- *relid = 0;
- *attno = 0;
- *constval = 0;
- *flag = 0;
- return;
- }
-
- /* OK, we identified the var or func; now look at the other side */
-
- other = (*flag == 0) ? left : right;
-
- if (IsA(other, Const) &&
- !((Const *) other)->constisnull)
- {
- *constval = ((Const *) other)->constvalue;
- *flag |= SEL_CONSTANT;
- }
- else
- *constval = 0;
-}
-
-/*
- * is_single_func
- * If the given expression is a function of a single relation,
- * return the relation number; else return 0
- */
-static int
-is_single_func(Node *node)
-{
- if (is_funcclause(node))
- {
- List *varnos = pull_varnos(node);
-
- if (length(varnos) == 1)
- {
- int funcvarno = lfirsti(varnos);
-
- freeList(varnos);
- return funcvarno;
- }
- freeList(varnos);
- }
- return 0;
-}
-
-/*
- * get_rels_atts
- *
- * Returns the info
- * ( relid1 attno1 relid2 attno2 )
- * for a joinclause.
- *
- * If the clause is not of the form (var op var) or if any of the vars
- * refer to nested attributes, then zeroes are returned.
- */
-void
-get_rels_atts(Node *clause,
- int *relid1,
- AttrNumber *attno1,
- int *relid2,
- AttrNumber *attno2)
-{
- /* set default values */
- *relid1 = 0;
- *attno1 = 0;
- *relid2 = 0;
- *attno2 = 0;
-
- if (is_opclause(clause))
- {
- Var *left = get_leftop((Expr *) clause);
- Var *right = get_rightop((Expr *) clause);
-
- if (left && right)
- {
- int funcvarno;
-
- /* Ignore any binary-compatible relabeling */
- if (IsA(left, RelabelType))
- left = (Var *) ((RelabelType *) left)->arg;
- if (IsA(right, RelabelType))
- right = (Var *) ((RelabelType *) right)->arg;
-
- if (IsA(left, Var))
- {
- *relid1 = left->varno;
- *attno1 = left->varattno;
- }
- else if ((funcvarno = is_single_func((Node *) left)) != 0)
- {
- *relid1 = funcvarno;
- *attno1 = InvalidAttrNumber;
- }
-
- if (IsA(right, Var))
- {
- *relid2 = right->varno;
- *attno2 = right->varattno;
- }
- else if ((funcvarno = is_single_func((Node *) right)) != 0)
- {
- *relid2 = funcvarno;
- *attno2 = InvalidAttrNumber;
- }
- }
- }
-}
-
/*--------------------
* CommuteClause: commute a binary operator clause
*
diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c
index 407c132b4f7..801b328d817 100644
--- a/src/backend/optimizer/util/pathnode.c
+++ b/src/backend/optimizer/util/pathnode.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/util/pathnode.c,v 1.72 2001/05/07 00:43:22 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/util/pathnode.c,v 1.73 2001/05/20 20:28:19 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -346,9 +346,9 @@ create_index_path(Query *root,
/*
* We are making a pathnode for a single-scan indexscan; therefore,
- * both indexid and indexqual should be single-element lists.
+ * both indexinfo and indexqual should be single-element lists.
*/
- pathnode->indexid = makeListi1(index->indexoid);
+ pathnode->indexinfo = makeList1(index);
pathnode->indexqual = makeList1(indexquals);
pathnode->indexscandir = indexscandir;
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index ee3523553e8..749390a4d2d 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.65 2001/05/07 00:43:22 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.66 2001/05/20 20:28:19 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -23,9 +23,12 @@
#include "catalog/pg_amop.h"
#include "catalog/pg_inherits.h"
#include "catalog/pg_index.h"
+#include "optimizer/clauses.h"
#include "optimizer/plancat.h"
+#include "parser/parsetree.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
+#include "utils/lsyscache.h"
#include "utils/relcache.h"
#include "utils/syscache.h"
#include "catalog/catalog.h"
@@ -33,7 +36,7 @@
/*
- * relation_info -
+ * get_relation_info -
* Retrieves catalog information for a given relation.
* Given the Oid of the relation, return the following info:
* whether the relation has secondary indices
@@ -41,8 +44,8 @@
* number of tuples
*/
void
-relation_info(Oid relationObjectId,
- bool *hasindex, long *pages, double *tuples)
+get_relation_info(Oid relationObjectId,
+ bool *hasindex, long *pages, double *tuples)
{
HeapTuple relationTuple;
Form_pg_class relation;
@@ -51,16 +54,19 @@ relation_info(Oid relationObjectId,
ObjectIdGetDatum(relationObjectId),
0, 0, 0);
if (!HeapTupleIsValid(relationTuple))
- elog(ERROR, "relation_info: Relation %u not found",
+ elog(ERROR, "get_relation_info: Relation %u not found",
relationObjectId);
relation = (Form_pg_class) GETSTRUCT(relationTuple);
- if (IsIgnoringSystemIndexes() && IsSystemRelationName(NameStr(relation->relname)))
+ if (IsIgnoringSystemIndexes() &&
+ IsSystemRelationName(NameStr(relation->relname)))
*hasindex = false;
else
- *hasindex = (relation->relhasindex) ? true : false;
+ *hasindex = relation->relhasindex;
+
*pages = relation->relpages;
*tuples = relation->reltuples;
+
ReleaseSysCache(relationTuple);
}
@@ -110,8 +116,8 @@ find_secondary_indexes(Oid relationObjectId)
info = makeNode(IndexOptInfo);
/*
- * Need to make these arrays large enough to be sure there is a
- * terminating 0 at the end of each one.
+ * Need to make these arrays large enough to be sure there is
+ * room for a terminating 0 at the end of each one.
*/
info->classlist = (Oid *) palloc(sizeof(Oid) * (INDEX_MAX_KEYS + 1));
info->indexkeys = (int *) palloc(sizeof(int) * (INDEX_MAX_KEYS + 1));
@@ -131,14 +137,26 @@ find_secondary_indexes(Oid relationObjectId)
}
else
info->indpred = NIL;
+ info->unique = index->indisunique;
info->lossy = index->indislossy;
for (i = 0; i < INDEX_MAX_KEYS; i++)
- info->indexkeys[i] = index->indkey[i];
- info->indexkeys[INDEX_MAX_KEYS] = 0;
- for (i = 0; i < INDEX_MAX_KEYS; i++)
+ {
+ if (index->indclass[i] == (Oid) 0)
+ break;
info->classlist[i] = index->indclass[i];
- info->classlist[INDEX_MAX_KEYS] = (Oid) 0;
+ }
+ info->classlist[i] = (Oid) 0;
+ info->ncolumns = i;
+
+ for (i = 0; i < INDEX_MAX_KEYS; i++)
+ {
+ if (index->indkey[i] == 0)
+ break;
+ info->indexkeys[i] = index->indkey[i];
+ }
+ info->indexkeys[i] = 0;
+ info->nkeys = i;
/* Extract info from the relation descriptor for the index */
indexRelation = index_open(index->indexrelid);
@@ -156,7 +174,7 @@ find_secondary_indexes(Oid relationObjectId)
MemSet(info->ordering, 0, sizeof(Oid) * (INDEX_MAX_KEYS + 1));
if (amorderstrategy != 0)
{
- for (i = 0; i < INDEX_MAX_KEYS && index->indclass[i]; i++)
+ for (i = 0; i < info->ncolumns; i++)
{
HeapTuple amopTuple;
Form_pg_amop amop;
@@ -193,30 +211,34 @@ find_secondary_indexes(Oid relationObjectId)
/*
* restriction_selectivity
*
- * Returns the selectivity of a specified operator.
+ * Returns the selectivity of a specified restriction operator clause.
* This code executes registered procedures stored in the
* operator relation, by calling the function manager.
*
- * XXX The assumption in the selectivity procedures is that if the
- * relation OIDs or attribute numbers are 0, then the clause
- * isn't of the form (op var const).
+ * varRelid is either 0 or a rangetable index. See clause_selectivity()
+ * for details about its meaning.
*/
Selectivity
-restriction_selectivity(Oid functionObjectId,
- Oid operatorObjectId,
- Oid relationObjectId,
- AttrNumber attributeNumber,
- Datum constValue,
- int constFlag)
+restriction_selectivity(Query *root,
+ Oid operator,
+ List *args,
+ int varRelid)
{
+ RegProcedure oprrest = get_oprrest(operator);
float8 result;
- result = DatumGetFloat8(OidFunctionCall5(functionObjectId,
- ObjectIdGetDatum(operatorObjectId),
- ObjectIdGetDatum(relationObjectId),
- Int16GetDatum(attributeNumber),
- constValue,
- Int32GetDatum(constFlag)));
+ /*
+ * if the oprrest procedure is missing for whatever reason,
+ * use a selectivity of 0.5
+ */
+ if (!oprrest)
+ return (Selectivity) 0.5;
+
+ result = DatumGetFloat8(OidFunctionCall4(oprrest,
+ PointerGetDatum(root),
+ ObjectIdGetDatum(operator),
+ PointerGetDatum(args),
+ Int32GetDatum(varRelid)));
if (result < 0.0 || result > 1.0)
elog(ERROR, "restriction_selectivity: bad value %f", result);
@@ -227,29 +249,29 @@ restriction_selectivity(Oid functionObjectId,
/*
* join_selectivity
*
- * Returns the selectivity of an operator, given the join clause
- * information.
- *
- * XXX The assumption in the selectivity procedures is that if the
- * relation OIDs or attribute numbers are 0, then the clause
- * isn't of the form (op var var).
+ * Returns the selectivity of a specified join operator clause.
+ * This code executes registered procedures stored in the
+ * operator relation, by calling the function manager.
*/
Selectivity
-join_selectivity(Oid functionObjectId,
- Oid operatorObjectId,
- Oid relationObjectId1,
- AttrNumber attributeNumber1,
- Oid relationObjectId2,
- AttrNumber attributeNumber2)
+join_selectivity(Query *root,
+ Oid operator,
+ List *args)
{
+ RegProcedure oprjoin = get_oprjoin(operator);
float8 result;
- result = DatumGetFloat8(OidFunctionCall5(functionObjectId,
- ObjectIdGetDatum(operatorObjectId),
- ObjectIdGetDatum(relationObjectId1),
- Int16GetDatum(attributeNumber1),
- ObjectIdGetDatum(relationObjectId2),
- Int16GetDatum(attributeNumber2)));
+ /*
+ * if the oprjoin procedure is missing for whatever reason,
+ * use a selectivity of 0.5
+ */
+ if (!oprjoin)
+ return (Selectivity) 0.5;
+
+ result = DatumGetFloat8(OidFunctionCall3(oprjoin,
+ PointerGetDatum(root),
+ ObjectIdGetDatum(operator),
+ PointerGetDatum(args)));
if (result < 0.0 || result > 1.0)
elog(ERROR, "join_selectivity: bad value %f", result);
@@ -330,3 +352,36 @@ has_subclass(Oid relationId)
ReleaseSysCache(tuple);
return result;
}
+
+/*
+ * has_unique_index
+ *
+ * Detect whether there is a unique index on the specified attribute
+ * of the specified relation, thus allowing us to conclude that all
+ * the (non-null) values of the attribute are distinct.
+ */
+bool
+has_unique_index(RelOptInfo *rel, AttrNumber attno)
+{
+ List *ilist;
+
+ foreach(ilist, rel->indexlist)
+ {
+ IndexOptInfo *index = (IndexOptInfo *) lfirst(ilist);
+
+ /*
+ * Note: ignore functional, partial, or lossy indexes, since they
+ * don't allow us to conclude that all attr values are distinct.
+ * Also, a multicolumn unique index doesn't allow us to conclude
+ * that just the specified attr is unique.
+ */
+ if (index->unique &&
+ index->nkeys == 1 &&
+ index->indexkeys[0] == attno &&
+ index->indproc == InvalidOid &&
+ index->indpred == NIL &&
+ !index->lossy)
+ return true;
+ }
+ return false;
+}
diff --git a/src/backend/optimizer/util/relnode.c b/src/backend/optimizer/util/relnode.c
index b4764ab6f8c..86d923116a4 100644
--- a/src/backend/optimizer/util/relnode.c
+++ b/src/backend/optimizer/util/relnode.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/util/relnode.c,v 1.32 2001/02/16 00:03:08 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/util/relnode.c,v 1.33 2001/05/20 20:28:19 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -22,6 +22,7 @@
#include "parser/parsetree.h"
+static RelOptInfo *make_base_rel(Query *root, int relid);
static List *new_join_tlist(List *tlist, int first_resdomno);
static List *build_joinrel_restrictlist(RelOptInfo *joinrel,
RelOptInfo *outer_rel,
@@ -36,28 +37,35 @@ static void subbuild_joinrel_joinlist(RelOptInfo *joinrel,
/*
- * get_base_rel
+ * build_base_rel
* Returns relation entry corresponding to 'relid', creating a new one
* if necessary. This is for base relations.
*/
RelOptInfo *
-get_base_rel(Query *root, int relid)
+build_base_rel(Query *root, int relid)
{
- List *baserels;
+ List *rels;
RelOptInfo *rel;
- foreach(baserels, root->base_rel_list)
+ /* Already made? */
+ foreach(rels, root->base_rel_list)
{
- rel = (RelOptInfo *) lfirst(baserels);
+ rel = (RelOptInfo *) lfirst(rels);
- /*
- * We know length(rel->relids) == 1 for all members of
- * base_rel_list
- */
+ /* length(rel->relids) == 1 for all members of base_rel_list */
if (lfirsti(rel->relids) == relid)
return rel;
}
+ /* It should not exist as an "other" rel */
+ foreach(rels, root->other_rel_list)
+ {
+ rel = (RelOptInfo *) lfirst(rels);
+
+ if (lfirsti(rel->relids) == relid)
+ elog(ERROR, "build_base_rel: rel already exists as 'other' rel");
+ }
+
/* No existing RelOptInfo for this base rel, so make a new one */
rel = make_base_rel(root, relid);
@@ -68,16 +76,52 @@ get_base_rel(Query *root, int relid)
}
/*
+ * build_other_rel
+ * Returns relation entry corresponding to 'relid', creating a new one
+ * if necessary. This is for 'other' relations, which are just like
+ * base relations except that they live in a different list.
+ */
+RelOptInfo *
+build_other_rel(Query *root, int relid)
+{
+ List *rels;
+ RelOptInfo *rel;
+
+ /* Already made? */
+ foreach(rels, root->other_rel_list)
+ {
+ rel = (RelOptInfo *) lfirst(rels);
+
+ /* length(rel->relids) == 1 for all members of other_rel_list */
+ if (lfirsti(rel->relids) == relid)
+ return rel;
+ }
+
+ /* It should not exist as a base rel */
+ foreach(rels, root->base_rel_list)
+ {
+ rel = (RelOptInfo *) lfirst(rels);
+
+ if (lfirsti(rel->relids) == relid)
+ elog(ERROR, "build_other_rel: rel already exists as base rel");
+ }
+
+ /* No existing RelOptInfo for this other rel, so make a new one */
+ rel = make_base_rel(root, relid);
+
+ /* and add it to the list */
+ root->other_rel_list = lcons(rel, root->other_rel_list);
+
+ return rel;
+}
+
+/*
* make_base_rel
* Construct a base-relation RelOptInfo for the specified rangetable index.
*
- * This is split out of get_base_rel so that inheritance-tree processing can
- * construct baserel nodes for child tables. We need a RelOptInfo so we can
- * plan a suitable access path for each child table, but we do NOT want to
- * enter the child nodes into base_rel_list. In most contexts, get_base_rel
- * should be called instead.
+ * Common code for build_base_rel and build_other_rel.
*/
-RelOptInfo *
+static RelOptInfo *
make_base_rel(Query *root, int relid)
{
RelOptInfo *rel = makeNode(RelOptInfo);
@@ -92,7 +136,7 @@ make_base_rel(Query *root, int relid)
rel->cheapest_total_path = NULL;
rel->pruneable = true;
rel->issubquery = false;
- rel->indexed = false;
+ rel->indexlist = NIL;
rel->pages = 0;
rel->tuples = 0;
rel->subplan = NULL;
@@ -108,8 +152,12 @@ make_base_rel(Query *root, int relid)
if (relationObjectId != InvalidOid)
{
/* Plain relation --- retrieve statistics from the system catalogs */
- relation_info(relationObjectId,
- &rel->indexed, &rel->pages, &rel->tuples);
+ bool indexed;
+
+ get_relation_info(relationObjectId,
+ &indexed, &rel->pages, &rel->tuples);
+ if (indexed)
+ rel->indexlist = find_secondary_indexes(relationObjectId);
}
else
{
@@ -121,12 +169,45 @@ make_base_rel(Query *root, int relid)
}
/*
+ * find_base_rel
+ * Find a base or other relation entry, which must already exist
+ * (since we'd have no idea which list to add it to).
+ */
+RelOptInfo *
+find_base_rel(Query *root, int relid)
+{
+ List *rels;
+ RelOptInfo *rel;
+
+ foreach(rels, root->base_rel_list)
+ {
+ rel = (RelOptInfo *) lfirst(rels);
+
+ /* length(rel->relids) == 1 for all members of base_rel_list */
+ if (lfirsti(rel->relids) == relid)
+ return rel;
+ }
+
+ foreach(rels, root->other_rel_list)
+ {
+ rel = (RelOptInfo *) lfirst(rels);
+
+ if (lfirsti(rel->relids) == relid)
+ return rel;
+ }
+
+ elog(ERROR, "find_base_rel: no relation entry for relid %d", relid);
+
+ return NULL; /* keep compiler quiet */
+}
+
+/*
* find_join_rel
* Returns relation entry corresponding to 'relids' (a list of RT indexes),
* or NULL if none exists. This is for join relations.
*
* Note: there is probably no good reason for this to be called from
- * anywhere except get_join_rel, but keep it as a separate routine
+ * anywhere except build_join_rel, but keep it as a separate routine
* just in case.
*/
static RelOptInfo *
@@ -146,7 +227,7 @@ find_join_rel(Query *root, Relids relids)
}
/*
- * get_join_rel
+ * build_join_rel
* Returns relation entry corresponding to the union of two given rels,
* creating a new relation entry if none already exists.
*
@@ -161,11 +242,11 @@ find_join_rel(Query *root, Relids relids)
* duplicated calculation of the restrictlist...
*/
RelOptInfo *
-get_join_rel(Query *root,
- RelOptInfo *outer_rel,
- RelOptInfo *inner_rel,
- JoinType jointype,
- List **restrictlist_ptr)
+build_join_rel(Query *root,
+ RelOptInfo *outer_rel,
+ RelOptInfo *inner_rel,
+ JoinType jointype,
+ List **restrictlist_ptr)
{
List *joinrelids;
RelOptInfo *joinrel;
@@ -212,7 +293,7 @@ get_join_rel(Query *root,
joinrel->cheapest_total_path = NULL;
joinrel->pruneable = true;
joinrel->issubquery = false;
- joinrel->indexed = false;
+ joinrel->indexlist = NIL;
joinrel->pages = 0;
joinrel->tuples = 0;
joinrel->subplan = NULL;