88 *
99 *
1010 * IDENTIFICATION
11- * $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.73 1999/11/22 17:56:07 momjian Exp $
11+ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.74 1999/12/31 03:41:03 tgl Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
@@ -44,24 +44,30 @@ typedef enum {
4444Prefix_None ,Prefix_Partial ,Prefix_Exact
4545}Prefix_Status ;
4646
47- static void match_index_orclauses (RelOptInfo * rel ,RelOptInfo * index ,int indexkey ,
48- int xclass ,List * restrictinfo_list );
49- static List * match_index_orclause (RelOptInfo * rel ,RelOptInfo * index ,int indexkey ,
50- int xclass ,List * or_clauses ,List * other_matching_indices );
47+ static void match_index_orclauses (RelOptInfo * rel ,RelOptInfo * index ,
48+ int indexkey ,Oid opclass ,
49+ List * restrictinfo_list );
50+ static List * match_index_orclause (RelOptInfo * rel ,RelOptInfo * index ,
51+ int indexkey ,Oid opclass ,
52+ List * or_clauses ,
53+ List * other_matching_indices );
5154static bool match_or_subclause_to_indexkey (RelOptInfo * rel ,RelOptInfo * index ,
52- int indexkey ,int xclass ,
55+ int indexkey ,Oid opclass ,
5356Expr * clause );
5457static List * group_clauses_by_indexkey (RelOptInfo * rel ,RelOptInfo * index ,
55- int * indexkeys ,Oid * classes ,List * restrictinfo_list );
58+ int * indexkeys ,Oid * classes ,
59+ List * restrictinfo_list );
5660static List * group_clauses_by_ikey_for_joins (RelOptInfo * rel ,RelOptInfo * index ,
57- int * indexkeys ,Oid * classes ,List * join_cinfo_list ,List * restr_cinfo_list );
61+ int * indexkeys ,Oid * classes ,
62+ List * join_cinfo_list ,
63+ List * restr_cinfo_list );
5864static bool match_clause_to_indexkey (RelOptInfo * rel ,RelOptInfo * index ,
59- int indexkey ,int xclass ,
65+ int indexkey ,Oid opclass ,
6066Expr * clause ,bool join );
61- static bool indexable_operator (Expr * clause ,int xclass ,Oid relam ,
67+ static bool indexable_operator (Expr * clause ,Oid opclass ,Oid relam ,
6268bool indexkey_on_left );
6369static bool pred_test (List * predicate_list ,List * restrictinfo_list ,
64- List * joininfo_list );
70+ List * joininfo_list );
6571static bool one_pred_test (Expr * predicate ,List * restrictinfo_list );
6672static bool one_pred_clause_expr_test (Expr * predicate ,Node * clause );
6773static bool one_pred_clause_test (Expr * predicate ,Node * clause );
@@ -77,13 +83,16 @@ static bool useful_for_ordering(Query *root, RelOptInfo *rel,
7783RelOptInfo * index );
7884static bool match_index_to_operand (int indexkey ,Var * operand ,
7985RelOptInfo * rel ,RelOptInfo * index );
80- static bool function_index_operand (Expr * funcOpnd ,RelOptInfo * rel ,RelOptInfo * index );
81- static bool match_special_index_operator (Expr * clause ,bool indexkey_on_left );
86+ static bool function_index_operand (Expr * funcOpnd ,RelOptInfo * rel ,
87+ RelOptInfo * index );
88+ static bool match_special_index_operator (Expr * clause ,Oid opclass ,Oid relam ,
89+ bool indexkey_on_left );
8290static Prefix_Status like_fixed_prefix (char * patt ,char * * prefix );
8391static Prefix_Status regex_fixed_prefix (char * patt ,bool case_insensitive ,
8492char * * prefix );
8593static List * prefix_quals (Var * leftop ,Oid expr_op ,
8694char * prefix ,Prefix_Status pstatus );
95+ static Oid find_operator (const char * opname ,Oid datatype );
8796
8897
8998/*
@@ -255,7 +264,7 @@ static void
255264match_index_orclauses (RelOptInfo * rel ,
256265RelOptInfo * index ,
257266int indexkey ,
258- int xclass ,
267+ Oid opclass ,
259268List * restrictinfo_list )
260269{
261270List * i ;
@@ -272,7 +281,7 @@ match_index_orclauses(RelOptInfo *rel,
272281 */
273282restrictinfo -> subclauseindices =
274283match_index_orclause (rel ,index ,
275- indexkey ,xclass ,
284+ indexkey ,opclass ,
276285restrictinfo -> clause -> args ,
277286restrictinfo -> subclauseindices );
278287}
@@ -304,7 +313,7 @@ static List *
304313match_index_orclause (RelOptInfo * rel ,
305314RelOptInfo * index ,
306315int indexkey ,
307- int xclass ,
316+ Oid opclass ,
308317List * or_clauses ,
309318List * other_matching_indices )
310319{
@@ -330,7 +339,7 @@ match_index_orclause(RelOptInfo *rel,
330339{
331340Expr * clause = lfirst (clist );
332341
333- if (match_or_subclause_to_indexkey (rel ,index ,indexkey ,xclass ,
342+ if (match_or_subclause_to_indexkey (rel ,index ,indexkey ,opclass ,
334343clause ))
335344{
336345/* OK to add this index to sublist for this subclause */
@@ -355,7 +364,7 @@ static bool
355364match_or_subclause_to_indexkey (RelOptInfo * rel ,
356365RelOptInfo * index ,
357366int indexkey ,
358- int xclass ,
367+ Oid opclass ,
359368Expr * clause )
360369{
361370if (and_clause ((Node * )clause ))
@@ -364,14 +373,14 @@ match_or_subclause_to_indexkey(RelOptInfo *rel,
364373
365374foreach (item ,clause -> args )
366375{
367- if (!match_clause_to_indexkey (rel ,index ,indexkey ,xclass ,
376+ if (!match_clause_to_indexkey (rel ,index ,indexkey ,opclass ,
368377lfirst (item ), false))
369378return false;
370379}
371380return true;
372381}
373382else
374- return match_clause_to_indexkey (rel ,index ,indexkey ,xclass ,
383+ return match_clause_to_indexkey (rel ,index ,indexkey ,opclass ,
375384clause , false);
376385}
377386
@@ -588,7 +597,7 @@ group_clauses_by_ikey_for_joins(RelOptInfo *rel,
588597 * 'rel' is the relation of interest.
589598 * 'index' is an index on 'rel'.
590599 * 'indexkey' is a key of 'index'.
591- * 'xclass ' is the corresponding operator class.
600+ * 'opclass ' is the corresponding operator class.
592601 * 'clause' is the clause to be tested.
593602 * 'join' is true if we are considering this clause for joins.
594603 *
@@ -601,7 +610,7 @@ static bool
601610match_clause_to_indexkey (RelOptInfo * rel ,
602611RelOptInfo * index ,
603612int indexkey ,
604- int xclass ,
613+ Oid opclass ,
605614Expr * clause ,
606615bool join )
607616{
@@ -627,26 +636,28 @@ match_clause_to_indexkey(RelOptInfo *rel,
627636if ((IsA (rightop ,Const )|| IsA (rightop ,Param ))&&
628637match_index_to_operand (indexkey ,leftop ,rel ,index ))
629638{
630- if (indexable_operator (clause ,xclass ,index -> relam , true))
639+ if (indexable_operator (clause ,opclass ,index -> relam , true))
631640return true;
632641/*
633642 * If we didn't find a member of the index's opclass,
634643 * see whether it is a "special" indexable operator.
635644 */
636- if (match_special_index_operator (clause , true))
645+ if (match_special_index_operator (clause ,opclass ,index -> relam ,
646+ true))
637647return true;
638648return false;
639649}
640650if ((IsA (leftop ,Const )|| IsA (leftop ,Param ))&&
641651match_index_to_operand (indexkey ,rightop ,rel ,index ))
642652{
643- if (indexable_operator (clause ,xclass ,index -> relam , false))
653+ if (indexable_operator (clause ,opclass ,index -> relam , false))
644654return true;
645655/*
646656 * If we didn't find a member of the index's opclass,
647657 * see whether it is a "special" indexable operator.
648658 */
649- if (match_special_index_operator (clause , false))
659+ if (match_special_index_operator (clause ,opclass ,index -> relam ,
660+ false))
650661return true;
651662return false;
652663}
@@ -666,7 +677,7 @@ match_clause_to_indexkey(RelOptInfo *rel,
666677isIndexable = !intMember (lfirsti (rel -> relids ),othervarnos );
667678freeList (othervarnos );
668679if (isIndexable &&
669- indexable_operator (clause ,xclass ,index -> relam , true))
680+ indexable_operator (clause ,opclass ,index -> relam , true))
670681return true;
671682}
672683else if (match_index_to_operand (indexkey ,rightop ,rel ,index ))
@@ -677,7 +688,7 @@ match_clause_to_indexkey(RelOptInfo *rel,
677688isIndexable = !intMember (lfirsti (rel -> relids ),othervarnos );
678689freeList (othervarnos );
679690if (isIndexable &&
680- indexable_operator (clause ,xclass ,index -> relam , false))
691+ indexable_operator (clause ,opclass ,index -> relam , false))
681692return true;
682693}
683694}
@@ -706,7 +717,7 @@ match_clause_to_indexkey(RelOptInfo *rel,
706717 * a tad ugly...
707718 */
708719static bool
709- indexable_operator (Expr * clause ,int xclass ,Oid relam ,
720+ indexable_operator (Expr * clause ,Oid opclass ,Oid relam ,
710721bool indexkey_on_left )
711722{
712723Oid expr_op = ((Oper * )clause -> oper )-> opno ;
@@ -723,7 +734,7 @@ indexable_operator(Expr *clause, int xclass, Oid relam,
723734return false;
724735
725736/* Done if the (commuted) operator is a member of the index's AM */
726- if (op_class (commuted_op ,xclass ,relam ))
737+ if (op_class (commuted_op ,opclass ,relam ))
727738return true;
728739
729740/*
@@ -766,7 +777,7 @@ indexable_operator(Expr *clause, int xclass, Oid relam,
766777if (commuted_op == InvalidOid )
767778return false;
768779
769- if (op_class (commuted_op ,xclass ,relam ))
780+ if (op_class (commuted_op ,opclass ,relam ))
770781{
771782/*
772783 * Success! Change the opclause to use the
@@ -1561,7 +1572,8 @@ function_index_operand(Expr *funcOpnd, RelOptInfo *rel, RelOptInfo *index)
15611572 * Return 'true' if we can do something with it anyway.
15621573 */
15631574static bool
1564- match_special_index_operator (Expr * clause ,bool indexkey_on_left )
1575+ match_special_index_operator (Expr * clause ,Oid opclass ,Oid relam ,
1576+ bool indexkey_on_left )
15651577{
15661578bool isIndexable = false;
15671579Var * leftop ,
@@ -1625,6 +1637,51 @@ match_special_index_operator(Expr *clause, bool indexkey_on_left)
16251637break ;
16261638}
16271639
1640+ /* done if the expression doesn't look indexable */
1641+ if (!isIndexable )
1642+ return false;
1643+
1644+ /*
1645+ * Must also check that index's opclass supports the operators we will
1646+ * want to apply. (A hash index, for example, will not support ">=".)
1647+ * We cheat a little by not checking for availability of "=" ... any
1648+ * index type should support "=", methinks.
1649+ */
1650+ switch (expr_op )
1651+ {
1652+ case OID_TEXT_LIKE_OP :
1653+ case OID_TEXT_REGEXEQ_OP :
1654+ case OID_TEXT_ICREGEXEQ_OP :
1655+ if (!op_class (find_operator (">=" ,TEXTOID ),opclass ,relam )||
1656+ !op_class (find_operator ("<=" ,TEXTOID ),opclass ,relam ))
1657+ isIndexable = false;
1658+ break ;
1659+
1660+ case OID_BPCHAR_LIKE_OP :
1661+ case OID_BPCHAR_REGEXEQ_OP :
1662+ case OID_BPCHAR_ICREGEXEQ_OP :
1663+ if (!op_class (find_operator (">=" ,BPCHAROID ),opclass ,relam )||
1664+ !op_class (find_operator ("<=" ,BPCHAROID ),opclass ,relam ))
1665+ isIndexable = false;
1666+ break ;
1667+
1668+ case OID_VARCHAR_LIKE_OP :
1669+ case OID_VARCHAR_REGEXEQ_OP :
1670+ case OID_VARCHAR_ICREGEXEQ_OP :
1671+ if (!op_class (find_operator (">=" ,VARCHAROID ),opclass ,relam )||
1672+ !op_class (find_operator ("<=" ,VARCHAROID ),opclass ,relam ))
1673+ isIndexable = false;
1674+ break ;
1675+
1676+ case OID_NAME_LIKE_OP :
1677+ case OID_NAME_REGEXEQ_OP :
1678+ case OID_NAME_ICREGEXEQ_OP :
1679+ if (!op_class (find_operator (">=" ,NAMEOID ),opclass ,relam )||
1680+ !op_class (find_operator ("<=" ,NAMEOID ),opclass ,relam ))
1681+ isIndexable = false;
1682+ break ;
1683+ }
1684+
16281685return isIndexable ;
16291686}
16301687
@@ -1848,7 +1905,7 @@ prefix_quals(Var *leftop, Oid expr_op,
18481905{
18491906List * result ;
18501907Oid datatype ;
1851- HeapTuple optup ;
1908+ Oid oproid ;
18521909void * conval ;
18531910Const * con ;
18541911Oper * op ;
@@ -1893,12 +1950,8 @@ prefix_quals(Var *leftop, Oid expr_op,
18931950 */
18941951if (pstatus == Prefix_Exact )
18951952{
1896- optup = SearchSysCacheTuple (OPERNAME ,
1897- PointerGetDatum ("=" ),
1898- ObjectIdGetDatum (datatype ),
1899- ObjectIdGetDatum (datatype ),
1900- CharGetDatum ('b' ));
1901- if (!HeapTupleIsValid (optup ))
1953+ oproid = find_operator ("=" ,datatype );
1954+ if (oproid == InvalidOid )
19021955elog (ERROR ,"prefix_quals: no = operator for type %u" ,datatype );
19031956/* Note: we cheat a little by assuming that textin() will do for
19041957 * bpchar and varchar constants too...
@@ -1908,7 +1961,7 @@ prefix_quals(Var *leftop, Oid expr_op,
19081961con = makeConst (datatype , ((datatype == NAMEOID ) ?NAMEDATALEN :-1 ),
19091962PointerGetDatum (conval ),
19101963false, false, false, false);
1911- op = makeOper (optup -> t_data -> t_oid ,InvalidOid ,BOOLOID ,0 ,NULL );
1964+ op = makeOper (oproid ,InvalidOid ,BOOLOID ,0 ,NULL );
19121965expr = make_opclause (op ,leftop , (Var * )con );
19131966result = lcons (expr ,NIL );
19141967return result ;
@@ -1919,19 +1972,15 @@ prefix_quals(Var *leftop, Oid expr_op,
19191972 *
19201973 * We can always say "x >= prefix".
19211974 */
1922- optup = SearchSysCacheTuple (OPERNAME ,
1923- PointerGetDatum (">=" ),
1924- ObjectIdGetDatum (datatype ),
1925- ObjectIdGetDatum (datatype ),
1926- CharGetDatum ('b' ));
1927- if (!HeapTupleIsValid (optup ))
1975+ oproid = find_operator (">=" ,datatype );
1976+ if (oproid == InvalidOid )
19281977elog (ERROR ,"prefix_quals: no >= operator for type %u" ,datatype );
19291978conval = (datatype == NAMEOID ) ?
19301979(void * )namein (prefix ) : (void * )textin (prefix );
19311980con = makeConst (datatype , ((datatype == NAMEOID ) ?NAMEDATALEN :-1 ),
19321981PointerGetDatum (conval ),
19331982false, false, false, false);
1934- op = makeOper (optup -> t_data -> t_oid ,InvalidOid ,BOOLOID ,0 ,NULL );
1983+ op = makeOper (oproid ,InvalidOid ,BOOLOID ,0 ,NULL );
19351984expr = make_opclause (op ,leftop , (Var * )con );
19361985result = lcons (expr ,NIL );
19371986
@@ -1947,22 +1996,34 @@ prefix_quals(Var *leftop, Oid expr_op,
19471996prefix [prefixlen ]= '\377' ;
19481997prefix [prefixlen + 1 ]= '\0' ;
19491998
1950- optup = SearchSysCacheTuple (OPERNAME ,
1951- PointerGetDatum ("<=" ),
1952- ObjectIdGetDatum (datatype ),
1953- ObjectIdGetDatum (datatype ),
1954- CharGetDatum ('b' ));
1955- if (!HeapTupleIsValid (optup ))
1999+ oproid = find_operator ("<=" ,datatype );
2000+ if (oproid == InvalidOid )
19562001elog (ERROR ,"prefix_quals: no <= operator for type %u" ,datatype );
19572002conval = (datatype == NAMEOID ) ?
19582003(void * )namein (prefix ) : (void * )textin (prefix );
19592004con = makeConst (datatype , ((datatype == NAMEOID ) ?NAMEDATALEN :-1 ),
19602005PointerGetDatum (conval ),
19612006false, false, false, false);
1962- op = makeOper (optup -> t_data -> t_oid ,InvalidOid ,BOOLOID ,0 ,NULL );
2007+ op = makeOper (oproid ,InvalidOid ,BOOLOID ,0 ,NULL );
19632008expr = make_opclause (op ,leftop , (Var * )con );
19642009result = lappend (result ,expr );
19652010#endif
19662011
19672012return result ;
19682013}
2014+
2015+ /* See if there is a binary op of the given name for the given datatype */
2016+ static Oid
2017+ find_operator (const char * opname ,Oid datatype )
2018+ {
2019+ HeapTuple optup ;
2020+
2021+ optup = SearchSysCacheTuple (OPERNAME ,
2022+ PointerGetDatum (opname ),
2023+ ObjectIdGetDatum (datatype ),
2024+ ObjectIdGetDatum (datatype ),
2025+ CharGetDatum ('b' ));
2026+ if (!HeapTupleIsValid (optup ))
2027+ return InvalidOid ;
2028+ return optup -> t_data -> t_oid ;
2029+ }