]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Allow binary-compatible indices to be considered when checking for valid
authorThomas G. Lockhart <lockhart@fourpalms.org>
Fri, 14 Aug 1998 16:13:07 +0000 (16:13 +0000)
committerThomas G. Lockhart <lockhart@fourpalms.org>
Fri, 14 Aug 1998 16:13:07 +0000 (16:13 +0000)
 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.

src/backend/optimizer/path/indxpath.c

index 2932f82b7ecd1310bc164c36b2d730924d09570e..41583a1c1c6b54a8c017770f30e33c6697554612 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * 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/xfunc.h"
 #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"
 
 
@@ -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);
 
 
-/*
- * find-index-paths--
+/* find_index_paths()
  *       Finds all possible index paths by determining which indices in the
  *       list 'indices' are usable.
  *
@@ -120,16 +122,16 @@ find_index_paths(Query *root,
        List       *joinpaths = NIL;
        List       *retval = NIL;
        List       *ilist;
-       
+
        foreach(ilist, indices)
        {
                index = (RelOptInfo *) lfirst(ilist);
-       
+
                /* If this is a partial index, return if it fails the predicate test */
                if (index->indpred != NIL)
                        if (!pred_test(index->indpred, clauseinfo_list, joininfo_list))
                                continue;
-       
+
                /*
                 * 1. Try matching the index against subclauses of an 'or' clause.
                 * 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->classlist[0],
                                                                  clauseinfo_list);
-       
+
                /*
                 * 2. If the keys of this index match any of the available restriction
                 * clauses, then create pathnodes corresponding to each group of
@@ -154,7 +156,7 @@ find_index_paths(Query *root,
                                                                                                         index->indexkeys,
                                                                                                         index->classlist,
                                                                                                         clauseinfo_list);
-       
+
                scanpaths = NIL;
                if (scanclausegroups != NIL)
                        scanpaths = create_index_paths(root,
@@ -162,7 +164,7 @@ find_index_paths(Query *root,
                                                                                   index,
                                                                                   scanclausegroups,
                                                                                   false);
-       
+
                /*
                 * 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
@@ -172,7 +174,7 @@ find_index_paths(Query *root,
                 */
                joinclausegroups = indexable_joinclauses(rel, index, joininfo_list, clauseinfo_list);
                joinpaths = NIL;
-       
+
                if (joinclausegroups != NIL)
                {
                        List       *new_join_paths = create_index_paths(root, rel,
@@ -180,11 +182,11 @@ find_index_paths(Query *root,
                                                                                                                        joinclausegroups,
                                                                                                                        true);
                        List       *innerjoin_paths = index_innerjoin(root, rel, joinclausegroups, index);
-       
+
                        rel->innerjoin = nconc(rel->innerjoin, innerjoin_paths);
                        joinpaths = new_join_paths;
                }
-       
+
                /*
                 * Some sanity checks to make sure that the indexpath is valid.
                 */
@@ -193,7 +195,7 @@ find_index_paths(Query *root,
                if (scanpaths != NULL)
                        retval = add_index_paths(scanpaths, retval);
        }
-       
+
        return retval;
 
 }
@@ -252,8 +254,7 @@ match_index_orclauses(RelOptInfo *rel,
        }
 }
 
-/*
- * match_index_operand--
+/* match_index_to_operand()
  *       Generalize test for a match between an existing index's key
  *       and the operand on the rhs of a restriction clause.  Now check
  *       for functional indices as well.
@@ -264,17 +265,22 @@ match_index_to_operand(int indexkey,
                                           RelOptInfo *rel,
                                           RelOptInfo *index)
 {
+       bool    result;
 
        /*
         * Normal index.
         */
        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
         */
-       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;
 
        index_list = matching_indices;
-       
+
        foreach(clist, or_clauses)
        {
                clause = lfirst(clist);
@@ -555,8 +561,7 @@ group_clauses_by_ikey_for_joins(RelOptInfo *rel,
  * - vadim 01/22/97
  */
 
-/*
- * match_clause_to-indexkey--
+/* match_clause_to_indexkey()
  *       Finds the first of a relation's available restriction clauses that
  *       matches a key of an index.
  *
@@ -609,11 +614,56 @@ match_clause_to_indexkey(RelOptInfo *rel,
                        (rightop && IsA(rightop, Param)))
                {
                        restrict_op = ((Oper *) ((Expr *) clause)->oper)->opno;
+
                        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,
                                                                                                  rel,
                                                                                                  index));
+
+                                               if (isIndexable)
+                                               {
+                                                       ((Oper *) ((Expr *) clause)->oper)->opno = restrict_op;
+                                               }
+                                       }
+                               }
+                       }
+#endif
                }
 
                /*
@@ -625,13 +675,54 @@ match_clause_to_indexkey(RelOptInfo *rel,
                        restrict_op =
                                get_commutator(((Oper *) ((Expr *) clause)->oper)->opno);
 
-                       if ((restrict_op != InvalidOid) &&
+                       isIndexable = ((restrict_op != InvalidOid) &&
                                op_class(restrict_op, xclass, index->relam) &&
                                IndexScanableOperand(rightop,
-                                                                        indexkey, rel, index))
+                                                                        indexkey, rel, index));
+
+#ifndef IGNORE_BINARY_COMPATIBLE_INDICES
+                       if (! isIndexable)
                        {
-                               isIndexable = true;
+                               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
                                 * var/func const)