Allow binary-compatible indices to be considered when checking for valid
indices for restriction clauses containing a constant. Note that if an index does not match directly (usually because the types on both side of the clause don't match), and if a binary-compatible index is identified, then the operator function will be replaced by a new one. Should not be a problem, but be sure that if types are listed as being binary compatible (in parse_coerce.h) then the comparison functions are also binary-compatible, giving equivalent results.
This commit is contained in:
parent
94f42ed389
commit
6912beea70
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.28 1998/08/11 19:32:37 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.29 1998/08/14 16:13:07 thomas Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -39,6 +39,9 @@
|
|||||||
#include "optimizer/pathnode.h"
|
#include "optimizer/pathnode.h"
|
||||||
#include "optimizer/xfunc.h"
|
#include "optimizer/xfunc.h"
|
||||||
#include "parser/parsetree.h" /* for getrelid() */
|
#include "parser/parsetree.h" /* for getrelid() */
|
||||||
|
#include "parser/parse_expr.h" /* for exprType() */
|
||||||
|
#include "parser/parse_oper.h" /* for oprid() and oper() */
|
||||||
|
#include "parser/parse_coerce.h" /* for IS_BINARY_COMPATIBLE() */
|
||||||
#include "utils/lsyscache.h"
|
#include "utils/lsyscache.h"
|
||||||
|
|
||||||
|
|
||||||
@ -80,8 +83,7 @@ static List *add_index_paths(List *indexpaths, List *new_indexpaths);
|
|||||||
static bool function_index_operand(Expr *funcOpnd, RelOptInfo *rel, RelOptInfo *index);
|
static bool function_index_operand(Expr *funcOpnd, RelOptInfo *rel, RelOptInfo *index);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/* find_index_paths()
|
||||||
* find-index-paths--
|
|
||||||
* Finds all possible index paths by determining which indices in the
|
* Finds all possible index paths by determining which indices in the
|
||||||
* list 'indices' are usable.
|
* list 'indices' are usable.
|
||||||
*
|
*
|
||||||
@ -120,16 +122,16 @@ find_index_paths(Query *root,
|
|||||||
List *joinpaths = NIL;
|
List *joinpaths = NIL;
|
||||||
List *retval = NIL;
|
List *retval = NIL;
|
||||||
List *ilist;
|
List *ilist;
|
||||||
|
|
||||||
foreach(ilist, indices)
|
foreach(ilist, indices)
|
||||||
{
|
{
|
||||||
index = (RelOptInfo *) lfirst(ilist);
|
index = (RelOptInfo *) lfirst(ilist);
|
||||||
|
|
||||||
/* If this is a partial index, return if it fails the predicate test */
|
/* If this is a partial index, return if it fails the predicate test */
|
||||||
if (index->indpred != NIL)
|
if (index->indpred != NIL)
|
||||||
if (!pred_test(index->indpred, clauseinfo_list, joininfo_list))
|
if (!pred_test(index->indpred, clauseinfo_list, joininfo_list))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 1. Try matching the index against subclauses of an 'or' clause.
|
* 1. Try matching the index against subclauses of an 'or' clause.
|
||||||
* The fields of the clauseinfo nodes are marked with lists of the
|
* The fields of the clauseinfo nodes are marked with lists of the
|
||||||
@ -143,7 +145,7 @@ find_index_paths(Query *root,
|
|||||||
index->indexkeys[0],
|
index->indexkeys[0],
|
||||||
index->classlist[0],
|
index->classlist[0],
|
||||||
clauseinfo_list);
|
clauseinfo_list);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 2. If the keys of this index match any of the available restriction
|
* 2. If the keys of this index match any of the available restriction
|
||||||
* clauses, then create pathnodes corresponding to each group of
|
* clauses, then create pathnodes corresponding to each group of
|
||||||
@ -154,7 +156,7 @@ find_index_paths(Query *root,
|
|||||||
index->indexkeys,
|
index->indexkeys,
|
||||||
index->classlist,
|
index->classlist,
|
||||||
clauseinfo_list);
|
clauseinfo_list);
|
||||||
|
|
||||||
scanpaths = NIL;
|
scanpaths = NIL;
|
||||||
if (scanclausegroups != NIL)
|
if (scanclausegroups != NIL)
|
||||||
scanpaths = create_index_paths(root,
|
scanpaths = create_index_paths(root,
|
||||||
@ -162,7 +164,7 @@ find_index_paths(Query *root,
|
|||||||
index,
|
index,
|
||||||
scanclausegroups,
|
scanclausegroups,
|
||||||
false);
|
false);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 3. If this index can be used with any join clause, then create
|
* 3. If this index can be used with any join clause, then create
|
||||||
* pathnodes for each group of usable clauses. An index can be used
|
* pathnodes for each group of usable clauses. An index can be used
|
||||||
@ -172,7 +174,7 @@ find_index_paths(Query *root,
|
|||||||
*/
|
*/
|
||||||
joinclausegroups = indexable_joinclauses(rel, index, joininfo_list, clauseinfo_list);
|
joinclausegroups = indexable_joinclauses(rel, index, joininfo_list, clauseinfo_list);
|
||||||
joinpaths = NIL;
|
joinpaths = NIL;
|
||||||
|
|
||||||
if (joinclausegroups != NIL)
|
if (joinclausegroups != NIL)
|
||||||
{
|
{
|
||||||
List *new_join_paths = create_index_paths(root, rel,
|
List *new_join_paths = create_index_paths(root, rel,
|
||||||
@ -180,11 +182,11 @@ find_index_paths(Query *root,
|
|||||||
joinclausegroups,
|
joinclausegroups,
|
||||||
true);
|
true);
|
||||||
List *innerjoin_paths = index_innerjoin(root, rel, joinclausegroups, index);
|
List *innerjoin_paths = index_innerjoin(root, rel, joinclausegroups, index);
|
||||||
|
|
||||||
rel->innerjoin = nconc(rel->innerjoin, innerjoin_paths);
|
rel->innerjoin = nconc(rel->innerjoin, innerjoin_paths);
|
||||||
joinpaths = new_join_paths;
|
joinpaths = new_join_paths;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Some sanity checks to make sure that the indexpath is valid.
|
* Some sanity checks to make sure that the indexpath is valid.
|
||||||
*/
|
*/
|
||||||
@ -193,7 +195,7 @@ find_index_paths(Query *root,
|
|||||||
if (scanpaths != NULL)
|
if (scanpaths != NULL)
|
||||||
retval = add_index_paths(scanpaths, retval);
|
retval = add_index_paths(scanpaths, retval);
|
||||||
}
|
}
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -252,8 +254,7 @@ match_index_orclauses(RelOptInfo *rel,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* match_index_to_operand()
|
||||||
* match_index_operand--
|
|
||||||
* Generalize test for a match between an existing index's key
|
* Generalize test for a match between an existing index's key
|
||||||
* and the operand on the rhs of a restriction clause. Now check
|
* and the operand on the rhs of a restriction clause. Now check
|
||||||
* for functional indices as well.
|
* for functional indices as well.
|
||||||
@ -264,17 +265,22 @@ match_index_to_operand(int indexkey,
|
|||||||
RelOptInfo *rel,
|
RelOptInfo *rel,
|
||||||
RelOptInfo *index)
|
RelOptInfo *index)
|
||||||
{
|
{
|
||||||
|
bool result;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Normal index.
|
* Normal index.
|
||||||
*/
|
*/
|
||||||
if (index->indproc == InvalidOid)
|
if (index->indproc == InvalidOid)
|
||||||
return match_indexkey_operand(indexkey, (Var *) operand, rel);
|
{
|
||||||
|
result = match_indexkey_operand(indexkey, (Var *) operand, rel);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* functional index check
|
* functional index check
|
||||||
*/
|
*/
|
||||||
return (function_index_operand(operand, rel, index));
|
result = function_index_operand(operand, rel, index);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -320,7 +326,7 @@ match_index_orclause(RelOptInfo *rel,
|
|||||||
else matching_indices = other_matching_indices;
|
else matching_indices = other_matching_indices;
|
||||||
|
|
||||||
index_list = matching_indices;
|
index_list = matching_indices;
|
||||||
|
|
||||||
foreach(clist, or_clauses)
|
foreach(clist, or_clauses)
|
||||||
{
|
{
|
||||||
clause = lfirst(clist);
|
clause = lfirst(clist);
|
||||||
@ -555,8 +561,7 @@ group_clauses_by_ikey_for_joins(RelOptInfo *rel,
|
|||||||
* - vadim 01/22/97
|
* - vadim 01/22/97
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/* match_clause_to_indexkey()
|
||||||
* match_clause_to-indexkey--
|
|
||||||
* Finds the first of a relation's available restriction clauses that
|
* Finds the first of a relation's available restriction clauses that
|
||||||
* matches a key of an index.
|
* matches a key of an index.
|
||||||
*
|
*
|
||||||
@ -609,11 +614,56 @@ match_clause_to_indexkey(RelOptInfo *rel,
|
|||||||
(rightop && IsA(rightop, Param)))
|
(rightop && IsA(rightop, Param)))
|
||||||
{
|
{
|
||||||
restrict_op = ((Oper *) ((Expr *) clause)->oper)->opno;
|
restrict_op = ((Oper *) ((Expr *) clause)->oper)->opno;
|
||||||
|
|
||||||
isIndexable = (op_class(restrict_op, xclass, index->relam) &&
|
isIndexable = (op_class(restrict_op, xclass, index->relam) &&
|
||||||
IndexScanableOperand(leftop,
|
IndexScanableOperand(leftop,
|
||||||
|
indexkey,
|
||||||
|
rel,
|
||||||
|
index));
|
||||||
|
|
||||||
|
#ifndef IGNORE_BINARY_COMPATIBLE_INDICES
|
||||||
|
/* Didn't find an index?
|
||||||
|
* Then maybe we can find another binary-compatible index instead...
|
||||||
|
* thomas 1998-08-14
|
||||||
|
*/
|
||||||
|
if (! isIndexable)
|
||||||
|
{
|
||||||
|
Oid ltype;
|
||||||
|
Oid rtype;
|
||||||
|
|
||||||
|
ltype = exprType((Node *)leftop);
|
||||||
|
rtype = exprType((Node *)rightop);
|
||||||
|
|
||||||
|
/* make sure we have two different binary-compatible types... */
|
||||||
|
if ((ltype != rtype)
|
||||||
|
&& IS_BINARY_COMPATIBLE(ltype, rtype))
|
||||||
|
{
|
||||||
|
char *opname;
|
||||||
|
Operator newop;
|
||||||
|
|
||||||
|
opname = get_opname(restrict_op);
|
||||||
|
newop = oper(opname, ltype, ltype, TRUE);
|
||||||
|
|
||||||
|
/* actually have a different operator to try? */
|
||||||
|
if (HeapTupleIsValid(newop) && (oprid(newop) != restrict_op))
|
||||||
|
{
|
||||||
|
restrict_op = oprid(newop);
|
||||||
|
|
||||||
|
isIndexable =
|
||||||
|
(op_class(restrict_op, xclass, index->relam) &&
|
||||||
|
IndexScanableOperand(leftop,
|
||||||
indexkey,
|
indexkey,
|
||||||
rel,
|
rel,
|
||||||
index));
|
index));
|
||||||
|
|
||||||
|
if (isIndexable)
|
||||||
|
{
|
||||||
|
((Oper *) ((Expr *) clause)->oper)->opno = restrict_op;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -625,13 +675,54 @@ match_clause_to_indexkey(RelOptInfo *rel,
|
|||||||
restrict_op =
|
restrict_op =
|
||||||
get_commutator(((Oper *) ((Expr *) clause)->oper)->opno);
|
get_commutator(((Oper *) ((Expr *) clause)->oper)->opno);
|
||||||
|
|
||||||
if ((restrict_op != InvalidOid) &&
|
isIndexable = ((restrict_op != InvalidOid) &&
|
||||||
op_class(restrict_op, xclass, index->relam) &&
|
op_class(restrict_op, xclass, index->relam) &&
|
||||||
IndexScanableOperand(rightop,
|
IndexScanableOperand(rightop,
|
||||||
indexkey, rel, index))
|
indexkey, rel, index));
|
||||||
{
|
|
||||||
isIndexable = true;
|
|
||||||
|
|
||||||
|
#ifndef IGNORE_BINARY_COMPATIBLE_INDICES
|
||||||
|
if (! isIndexable)
|
||||||
|
{
|
||||||
|
Oid ltype;
|
||||||
|
Oid rtype;
|
||||||
|
|
||||||
|
ltype = exprType((Node *)leftop);
|
||||||
|
rtype = exprType((Node *)rightop);
|
||||||
|
|
||||||
|
if ((ltype != rtype)
|
||||||
|
&& IS_BINARY_COMPATIBLE(ltype, rtype))
|
||||||
|
{
|
||||||
|
char *opname;
|
||||||
|
Operator newop;
|
||||||
|
|
||||||
|
restrict_op = ((Oper *) ((Expr *) clause)->oper)->opno;
|
||||||
|
|
||||||
|
opname = get_opname(restrict_op);
|
||||||
|
newop = oper(opname, rtype, rtype, TRUE);
|
||||||
|
|
||||||
|
if (HeapTupleIsValid(newop) && (oprid(newop) != restrict_op))
|
||||||
|
{
|
||||||
|
restrict_op =
|
||||||
|
get_commutator(oprid(newop));
|
||||||
|
|
||||||
|
isIndexable = ((restrict_op != InvalidOid) &&
|
||||||
|
op_class(restrict_op, xclass, index->relam) &&
|
||||||
|
IndexScanableOperand(rightop,
|
||||||
|
indexkey,
|
||||||
|
rel,
|
||||||
|
index));
|
||||||
|
|
||||||
|
if (isIndexable)
|
||||||
|
{
|
||||||
|
((Oper *) ((Expr *) clause)->oper)->opno = oprid(newop);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (isIndexable)
|
||||||
|
{
|
||||||
/*
|
/*
|
||||||
* In place list modification. (op const var/func) -> (op
|
* In place list modification. (op const var/func) -> (op
|
||||||
* var/func const)
|
* var/func const)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user