Commit 6cb1c023 authored by Tom Lane's avatar Tom Lane

Rewrite OR indexscan processing to be more flexible. We can now for the

first time generate an OR indexscan for a two-column index when the WHERE
condition is like 'col1 = foo AND (col2 = bar OR col2 = baz)' --- before,
the OR had to be on the first column of the index or we'd not notice the
possibility of using it.  Some progress towards extracting OR indexscans
from subclauses of an OR that references multiple relations, too, although
this code is #ifdef'd out because it needs more work.
parent 037e2fcf
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,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/nodes/copyfuncs.c,v 1.270 2003/12/30 23:53:14 tgl Exp $ * $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.271 2004/01/04 00:07:32 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1172,7 +1172,7 @@ _copyRestrictInfo(RestrictInfo *from) ...@@ -1172,7 +1172,7 @@ _copyRestrictInfo(RestrictInfo *from)
COPY_SCALAR_FIELD(canjoin); COPY_SCALAR_FIELD(canjoin);
COPY_BITMAPSET_FIELD(left_relids); COPY_BITMAPSET_FIELD(left_relids);
COPY_BITMAPSET_FIELD(right_relids); COPY_BITMAPSET_FIELD(right_relids);
COPY_NODE_FIELD(subclauseindices); /* XXX probably bad */ COPY_NODE_FIELD(orclause);
COPY_SCALAR_FIELD(eval_cost); COPY_SCALAR_FIELD(eval_cost);
COPY_SCALAR_FIELD(this_selec); COPY_SCALAR_FIELD(this_selec);
COPY_SCALAR_FIELD(mergejoinoperator); COPY_SCALAR_FIELD(mergejoinoperator);
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.223 2003/12/30 23:53:14 tgl Exp $ * $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.224 2004/01/04 00:07:32 tgl Exp $
* *
* NOTES * NOTES
* Every node type that can appear in stored rules' parsetrees *must* * Every node type that can appear in stored rules' parsetrees *must*
...@@ -1077,7 +1077,7 @@ _outRestrictInfo(StringInfo str, RestrictInfo *node) ...@@ -1077,7 +1077,7 @@ _outRestrictInfo(StringInfo str, RestrictInfo *node)
WRITE_BOOL_FIELD(canjoin); WRITE_BOOL_FIELD(canjoin);
WRITE_BITMAPSET_FIELD(left_relids); WRITE_BITMAPSET_FIELD(left_relids);
WRITE_BITMAPSET_FIELD(right_relids); WRITE_BITMAPSET_FIELD(right_relids);
WRITE_NODE_FIELD(subclauseindices); WRITE_NODE_FIELD(orclause);
WRITE_OID_FIELD(mergejoinoperator); WRITE_OID_FIELD(mergejoinoperator);
WRITE_OID_FIELD(left_sortop); WRITE_OID_FIELD(left_sortop);
WRITE_OID_FIELD(right_sortop); WRITE_OID_FIELD(right_sortop);
......
This diff is collapsed.
This diff is collapsed.
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/plan/initsplan.c,v 1.94 2003/12/30 23:53:14 tgl Exp $ * $PostgreSQL: pgsql/src/backend/optimizer/plan/initsplan.c,v 1.95 2004/01/04 00:07:32 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include "optimizer/pathnode.h" #include "optimizer/pathnode.h"
#include "optimizer/paths.h" #include "optimizer/paths.h"
#include "optimizer/planmain.h" #include "optimizer/planmain.h"
#include "optimizer/restrictinfo.h"
#include "optimizer/tlist.h" #include "optimizer/tlist.h"
#include "optimizer/var.h" #include "optimizer/var.h"
#include "parser/parsetree.h" #include "parser/parsetree.h"
...@@ -373,31 +374,11 @@ distribute_qual_to_rels(Query *root, Node *clause, ...@@ -373,31 +374,11 @@ distribute_qual_to_rels(Query *root, Node *clause,
Relids outerjoin_nonnullable, Relids outerjoin_nonnullable,
Relids qualscope) Relids qualscope)
{ {
RestrictInfo *restrictinfo = makeNode(RestrictInfo);
RelOptInfo *rel;
Relids relids; Relids relids;
List *vars; List *vars;
bool can_be_equijoin; bool can_be_equijoin;
RestrictInfo *restrictinfo;
restrictinfo->clause = (Expr *) clause; RelOptInfo *rel;
restrictinfo->canjoin = false; /* set below, if join clause */
restrictinfo->left_relids = NULL;
restrictinfo->right_relids = NULL;
restrictinfo->subclauseindices = NIL;
restrictinfo->eval_cost.startup = -1; /* not computed until
* needed */
restrictinfo->this_selec = -1; /* not computed until needed */
restrictinfo->mergejoinoperator = InvalidOid;
restrictinfo->left_sortop = InvalidOid;
restrictinfo->right_sortop = InvalidOid;
restrictinfo->left_pathkey = NIL; /* not computable yet */
restrictinfo->right_pathkey = NIL;
restrictinfo->left_mergescansel = -1; /* not computed until
* needed */
restrictinfo->right_mergescansel = -1;
restrictinfo->hashjoinoperator = InvalidOid;
restrictinfo->left_bucketsize = -1; /* not computed until needed */
restrictinfo->right_bucketsize = -1;
/* /*
* Retrieve all relids and vars contained within the clause. * Retrieve all relids and vars contained within the clause.
...@@ -508,18 +489,17 @@ distribute_qual_to_rels(Query *root, Node *clause, ...@@ -508,18 +489,17 @@ distribute_qual_to_rels(Query *root, Node *clause,
* same joinrel. A qual originating from WHERE is always considered * same joinrel. A qual originating from WHERE is always considered
* "pushed down". * "pushed down".
*/ */
restrictinfo->ispusheddown = ispusheddown || !bms_equal(relids, if (!ispusheddown)
qualscope); ispusheddown = !bms_equal(relids, qualscope);
/* /*
* If it's a binary opclause, set up left/right relids info. * Build the RestrictInfo node itself.
*/ */
if (is_opclause(clause) && length(((OpExpr *) clause)->args) == 2) restrictinfo = make_restrictinfo((Expr *) clause, ispusheddown);
{
restrictinfo->left_relids = pull_varnos(get_leftop((Expr *) clause));
restrictinfo->right_relids = pull_varnos(get_rightop((Expr *) clause));
}
/*
* Figure out where to attach it.
*/
switch (bms_membership(relids)) switch (bms_membership(relids))
{ {
case BMS_SINGLETON: case BMS_SINGLETON:
...@@ -553,7 +533,8 @@ distribute_qual_to_rels(Query *root, Node *clause, ...@@ -553,7 +533,8 @@ distribute_qual_to_rels(Query *root, Node *clause,
* into a join rel's restriction list.) * into a join rel's restriction list.)
*/ */
if (!isdeduced || if (!isdeduced ||
!qual_is_redundant(root, restrictinfo, rel->baserestrictinfo)) !qual_is_redundant(root, restrictinfo,
rel->baserestrictinfo))
{ {
/* Add clause to rel's restriction list */ /* Add clause to rel's restriction list */
rel->baserestrictinfo = lappend(rel->baserestrictinfo, rel->baserestrictinfo = lappend(rel->baserestrictinfo,
...@@ -564,23 +545,11 @@ distribute_qual_to_rels(Query *root, Node *clause, ...@@ -564,23 +545,11 @@ distribute_qual_to_rels(Query *root, Node *clause,
/* /*
* 'clause' is a join clause, since there is more than one rel * 'clause' is a join clause, since there is more than one rel
* in the relid set. Set additional RestrictInfo fields for * in the relid set.
* joining. First, does it look like a normal join clause,
* i.e., a binary operator relating expressions that come from
* distinct relations? If so we might be able to use it in a
* join algorithm.
*/ */
if (is_opclause(clause) && length(((OpExpr *) clause)->args) == 2)
{
if (!bms_is_empty(restrictinfo->left_relids) &&
!bms_is_empty(restrictinfo->right_relids) &&
!bms_overlap(restrictinfo->left_relids,
restrictinfo->right_relids))
restrictinfo->canjoin = true;
}
/* /*
* Now check for hash or mergejoinable operators. * Check for hash or mergejoinable operators.
* *
* We don't bother setting the hashjoin info if we're not going * We don't bother setting the hashjoin info if we're not going
* to need it. We do want to know about mergejoinable ops in * to need it. We do want to know about mergejoinable ops in
...@@ -624,7 +593,8 @@ distribute_qual_to_rels(Query *root, Node *clause, ...@@ -624,7 +593,8 @@ distribute_qual_to_rels(Query *root, Node *clause,
* equivalence for future use. (We can skip this for a deduced * equivalence for future use. (We can skip this for a deduced
* clause, since the keys are already known equivalent in that case.) * clause, since the keys are already known equivalent in that case.)
*/ */
if (can_be_equijoin && restrictinfo->mergejoinoperator != InvalidOid && if (can_be_equijoin &&
restrictinfo->mergejoinoperator != InvalidOid &&
!isdeduced) !isdeduced)
add_equijoined_keys(root, restrictinfo); add_equijoined_keys(root, restrictinfo);
} }
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/prep/prepunion.c,v 1.105 2003/11/29 19:51:51 pgsql Exp $ * $PostgreSQL: pgsql/src/backend/optimizer/prep/prepunion.c,v 1.106 2004/01/04 00:07:32 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -881,12 +881,9 @@ adjust_inherited_attrs_mutator(Node *node, ...@@ -881,12 +881,9 @@ adjust_inherited_attrs_mutator(Node *node,
newinfo->clause = (Expr *) newinfo->clause = (Expr *)
adjust_inherited_attrs_mutator((Node *) oldinfo->clause, context); adjust_inherited_attrs_mutator((Node *) oldinfo->clause, context);
/* /* and the modified version, if an OR clause */
* We do NOT want to copy the original subclauseindices list, newinfo->orclause = (Expr *)
* since the new rel will have different indices. The list will adjust_inherited_attrs_mutator((Node *) oldinfo->orclause, context);
* be rebuilt when needed during later planning.
*/
newinfo->subclauseindices = NIL;
/* /*
* Adjust left/right relid sets too. * Adjust left/right relid sets too.
...@@ -898,9 +895,13 @@ adjust_inherited_attrs_mutator(Node *node, ...@@ -898,9 +895,13 @@ adjust_inherited_attrs_mutator(Node *node,
context->old_rt_index, context->old_rt_index,
context->new_rt_index); context->new_rt_index);
newinfo->eval_cost.startup = -1; /* reset these too */ /*
* Reset cached derivative fields, since these might need to have
* different values when considering the child relation.
*/
newinfo->eval_cost.startup = -1;
newinfo->this_selec = -1; newinfo->this_selec = -1;
newinfo->left_pathkey = NIL; /* and these */ newinfo->left_pathkey = NIL;
newinfo->right_pathkey = NIL; newinfo->right_pathkey = NIL;
newinfo->left_mergescansel = -1; newinfo->left_mergescansel = -1;
newinfo->right_mergescansel = -1; newinfo->right_mergescansel = -1;
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/util/plancat.c,v 1.90 2003/11/29 19:51:51 pgsql Exp $ * $PostgreSQL: pgsql/src/backend/optimizer/util/plancat.c,v 1.91 2004/01/04 00:07:32 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -146,6 +146,7 @@ get_relation_info(Oid relationObjectId, RelOptInfo *rel) ...@@ -146,6 +146,7 @@ get_relation_info(Oid relationObjectId, RelOptInfo *rel)
ChangeVarNodes((Node *) info->indexprs, 1, varno, 0); ChangeVarNodes((Node *) info->indexprs, 1, varno, 0);
if (info->indpred && varno != 1) if (info->indpred && varno != 1)
ChangeVarNodes((Node *) info->indpred, 1, varno, 0); ChangeVarNodes((Node *) info->indpred, 1, varno, 0);
info->predOK = false; /* set later in indxpath.c */
info->unique = index->indisunique; info->unique = index->indisunique;
/* initialize cached join info to empty */ /* initialize cached join info to empty */
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/util/restrictinfo.c,v 1.21 2003/12/30 23:53:15 tgl Exp $ * $PostgreSQL: pgsql/src/backend/optimizer/util/restrictinfo.c,v 1.22 2004/01/04 00:07:32 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -20,12 +20,134 @@ ...@@ -20,12 +20,134 @@
#include "optimizer/var.h" #include "optimizer/var.h"
static Expr *make_sub_restrictinfos(Expr *clause, bool ispusheddown);
static bool join_clause_is_redundant(Query *root, static bool join_clause_is_redundant(Query *root,
RestrictInfo *rinfo, RestrictInfo *rinfo,
List *reference_list, List *reference_list,
JoinType jointype); JoinType jointype);
/*
* make_restrictinfo
*
* Build a RestrictInfo node containing the given subexpression.
*
* The ispusheddown flag must be supplied by the caller. We initialize
* fields that depend only on the given subexpression, leaving others that
* depend on context (or may never be needed at all) to be filled later.
*/
RestrictInfo *
make_restrictinfo(Expr *clause, bool ispusheddown)
{
RestrictInfo *restrictinfo = makeNode(RestrictInfo);
restrictinfo->clause = clause;
restrictinfo->ispusheddown = ispusheddown;
restrictinfo->canjoin = false; /* may get set below */
/*
* If it's a binary opclause, set up left/right relids info.
*/
if (is_opclause(clause) && length(((OpExpr *) clause)->args) == 2)
{
restrictinfo->left_relids = pull_varnos(get_leftop(clause));
restrictinfo->right_relids = pull_varnos(get_rightop(clause));
/*
* Does it look like a normal join clause, i.e., a binary operator
* relating expressions that come from distinct relations? If so
* we might be able to use it in a join algorithm. Note that this
* is a purely syntactic test that is made regardless of context.
*/
if (!bms_is_empty(restrictinfo->left_relids) &&
!bms_is_empty(restrictinfo->right_relids) &&
!bms_overlap(restrictinfo->left_relids,
restrictinfo->right_relids))
restrictinfo->canjoin = true;
}
else
{
/* Not a binary opclause, so mark both relid sets as empty */
restrictinfo->left_relids = NULL;
restrictinfo->right_relids = NULL;
}
/*
* If it's an OR clause, set up a modified copy with RestrictInfos
* inserted above each subclause of the top-level AND/OR structure.
*/
if (or_clause((Node *) clause))
{
restrictinfo->orclause = make_sub_restrictinfos(clause, ispusheddown);
}
else
{
/* Shouldn't be an AND clause, else flatten_andors messed up */
Assert(!and_clause((Node *) clause));
restrictinfo->orclause = NULL;
}
/*
* Fill in all the cacheable fields with "not yet set" markers.
* None of these will be computed until/unless needed. Note in
* particular that we don't mark a binary opclause as mergejoinable
* or hashjoinable here; that happens only if it appears in the right
* context (top level of a joinclause list).
*/
restrictinfo->eval_cost.startup = -1;
restrictinfo->this_selec = -1;
restrictinfo->mergejoinoperator = InvalidOid;
restrictinfo->left_sortop = InvalidOid;
restrictinfo->right_sortop = InvalidOid;
restrictinfo->left_pathkey = NIL;
restrictinfo->right_pathkey = NIL;
restrictinfo->left_mergescansel = -1;
restrictinfo->right_mergescansel = -1;
restrictinfo->hashjoinoperator = InvalidOid;
restrictinfo->left_bucketsize = -1;
restrictinfo->right_bucketsize = -1;
return restrictinfo;
}
/*
* Recursively insert sub-RestrictInfo nodes into a boolean expression.
*/
static Expr *
make_sub_restrictinfos(Expr *clause, bool ispusheddown)
{
if (or_clause((Node *) clause))
{
List *orlist = NIL;
List *temp;
foreach(temp, ((BoolExpr *) clause)->args)
orlist = lappend(orlist,
make_sub_restrictinfos(lfirst(temp),
ispusheddown));
return make_orclause(orlist);
}
else if (and_clause((Node *) clause))
{
List *andlist = NIL;
List *temp;
foreach(temp, ((BoolExpr *) clause)->args)
andlist = lappend(andlist,
make_sub_restrictinfos(lfirst(temp),
ispusheddown));
return make_andclause(andlist);
}
else
return (Expr *) make_restrictinfo(clause, ispusheddown);
}
/* /*
* restriction_is_or_clause * restriction_is_or_clause
* *
...@@ -34,8 +156,7 @@ static bool join_clause_is_redundant(Query *root, ...@@ -34,8 +156,7 @@ static bool join_clause_is_redundant(Query *root,
bool bool
restriction_is_or_clause(RestrictInfo *restrictinfo) restriction_is_or_clause(RestrictInfo *restrictinfo)
{ {
if (restrictinfo != NULL && if (restrictinfo->orclause != NULL)
or_clause((Node *) restrictinfo->clause))
return true; return true;
else else
return false; return false;
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2003, 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.88 2003/12/30 23:53:15 tgl Exp $ * $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.89 2004/01/04 00:07:32 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -271,6 +271,8 @@ typedef struct IndexOptInfo ...@@ -271,6 +271,8 @@ typedef struct IndexOptInfo
List *indexprs; /* expressions for non-simple index List *indexprs; /* expressions for non-simple index
* columns */ * columns */
List *indpred; /* predicate if a partial index, else NIL */ List *indpred; /* predicate if a partial index, else NIL */
bool predOK; /* true if predicate matches query */
bool unique; /* true if a unique index */ bool unique; /* true if a unique index */
/* cached info about inner indexscan paths for index */ /* cached info about inner indexscan paths for index */
...@@ -410,6 +412,8 @@ typedef struct AppendPath ...@@ -410,6 +412,8 @@ typedef struct AppendPath
* variable-free targetlist or to gate execution of a subplan with a * variable-free targetlist or to gate execution of a subplan with a
* one-time (variable-free) qual condition. Note that in the former case * one-time (variable-free) qual condition. Note that in the former case
* path.parent will be NULL; in the latter case it is copied from the subpath. * path.parent will be NULL; in the latter case it is copied from the subpath.
*
* Note that constantqual is a list of bare clauses, not RestrictInfos.
*/ */
typedef struct ResultPath typedef struct ResultPath
{ {
...@@ -478,9 +482,7 @@ typedef JoinPath NestPath; ...@@ -478,9 +482,7 @@ typedef JoinPath NestPath;
* A mergejoin path has these fields. * A mergejoin path has these fields.
* *
* path_mergeclauses lists the clauses (in the form of RestrictInfos) * path_mergeclauses lists the clauses (in the form of RestrictInfos)
* that will be used in the merge. (Before 7.0, this was a list of bare * that will be used in the merge.
* clause expressions, but we can save on list memory and cost_qual_eval
* work by leaving it in the form of a RestrictInfo list.)
* *
* Note that the mergeclauses are a subset of the parent relation's * Note that the mergeclauses are a subset of the parent relation's
* restriction-clause list. Any join clauses that are not mergejoinable * restriction-clause list. Any join clauses that are not mergejoinable
...@@ -586,6 +588,12 @@ typedef struct HashPath ...@@ -586,6 +588,12 @@ typedef struct HashPath
* qual-expression-evaluation code. (But we are still entitled to count * qual-expression-evaluation code. (But we are still entitled to count
* their selectivity when estimating the result tuple count, if we * their selectivity when estimating the result tuple count, if we
* can guess what it is...) * can guess what it is...)
*
* When the referenced clause is an OR clause, we generate a modified copy
* in which additional RestrictInfo nodes are inserted below the top-level
* OR/AND structure. This is a convenience for OR indexscan processing:
* indexquals taken from either the top level or an OR subclause will have
* associated RestrictInfo nodes.
*/ */
typedef struct RestrictInfo typedef struct RestrictInfo
...@@ -609,9 +617,8 @@ typedef struct RestrictInfo ...@@ -609,9 +617,8 @@ typedef struct RestrictInfo
Relids left_relids; /* relids in left side of clause */ Relids left_relids; /* relids in left side of clause */
Relids right_relids; /* relids in right side of clause */ Relids right_relids; /* relids in right side of clause */
/* only used if clause is an OR clause: */ /* This field is NULL unless clause is an OR clause: */
List *subclauseindices; /* indexes matching subclauses */ Expr *orclause; /* modified clause with RestrictInfos */
/* subclauseindices is a List of Lists of IndexOptInfos */
/* cache space for costs (currently only used for join clauses) */ /* cache space for costs (currently only used for join clauses) */
QualCost eval_cost; /* eval cost of clause; -1 if not yet set */ QualCost eval_cost; /* eval cost of clause; -1 if not yet set */
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2003, 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.70 2003/11/29 22:41:07 pgsql Exp $ * $PostgreSQL: pgsql/src/include/optimizer/paths.h,v 1.71 2004/01/04 00:07:32 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -38,7 +38,7 @@ extern void debug_print_rel(Query *root, RelOptInfo *rel); ...@@ -38,7 +38,7 @@ 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 *extract_or_indexqual_conditions(RelOptInfo *rel, extern List *group_clauses_by_indexkey_for_or(RelOptInfo *rel,
IndexOptInfo *index, IndexOptInfo *index,
Expr *orsubclause); Expr *orsubclause);
extern List *expand_indexqual_conditions(IndexOptInfo *index, extern List *expand_indexqual_conditions(IndexOptInfo *index,
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2003, 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/restrictinfo.h,v 1.20 2003/11/29 22:41:07 pgsql Exp $ * $PostgreSQL: pgsql/src/include/optimizer/restrictinfo.h,v 1.21 2004/01/04 00:07:32 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "nodes/relation.h" #include "nodes/relation.h"
extern RestrictInfo *make_restrictinfo(Expr *clause, bool ispusheddown);
extern bool restriction_is_or_clause(RestrictInfo *restrictinfo); extern bool restriction_is_or_clause(RestrictInfo *restrictinfo);
extern List *get_actual_clauses(List *restrictinfo_list); extern List *get_actual_clauses(List *restrictinfo_list);
extern void get_actual_join_clauses(List *restrictinfo_list, extern void get_actual_join_clauses(List *restrictinfo_list,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment