8
8
*
9
9
*
10
10
* 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 $
12
12
*
13
13
*-------------------------------------------------------------------------
14
14
*/
@@ -44,24 +44,30 @@ typedef enum {
44
44
Prefix_None ,Prefix_Partial ,Prefix_Exact
45
45
}Prefix_Status ;
46
46
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 );
51
54
static bool match_or_subclause_to_indexkey (RelOptInfo * rel ,RelOptInfo * index ,
52
- int indexkey ,int xclass ,
55
+ int indexkey ,Oid opclass ,
53
56
Expr * clause );
54
57
static 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 );
56
60
static 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 );
58
64
static bool match_clause_to_indexkey (RelOptInfo * rel ,RelOptInfo * index ,
59
- int indexkey ,int xclass ,
65
+ int indexkey ,Oid opclass ,
60
66
Expr * 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 ,
62
68
bool indexkey_on_left );
63
69
static bool pred_test (List * predicate_list ,List * restrictinfo_list ,
64
- List * joininfo_list );
70
+ List * joininfo_list );
65
71
static bool one_pred_test (Expr * predicate ,List * restrictinfo_list );
66
72
static bool one_pred_clause_expr_test (Expr * predicate ,Node * clause );
67
73
static bool one_pred_clause_test (Expr * predicate ,Node * clause );
@@ -77,13 +83,16 @@ static bool useful_for_ordering(Query *root, RelOptInfo *rel,
77
83
RelOptInfo * index );
78
84
static bool match_index_to_operand (int indexkey ,Var * operand ,
79
85
RelOptInfo * 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 );
82
90
static Prefix_Status like_fixed_prefix (char * patt ,char * * prefix );
83
91
static Prefix_Status regex_fixed_prefix (char * patt ,bool case_insensitive ,
84
92
char * * prefix );
85
93
static List * prefix_quals (Var * leftop ,Oid expr_op ,
86
94
char * prefix ,Prefix_Status pstatus );
95
+ static Oid find_operator (const char * opname ,Oid datatype );
87
96
88
97
89
98
/*
@@ -255,7 +264,7 @@ static void
255
264
match_index_orclauses (RelOptInfo * rel ,
256
265
RelOptInfo * index ,
257
266
int indexkey ,
258
- int xclass ,
267
+ Oid opclass ,
259
268
List * restrictinfo_list )
260
269
{
261
270
List * i ;
@@ -272,7 +281,7 @@ match_index_orclauses(RelOptInfo *rel,
272
281
*/
273
282
restrictinfo -> subclauseindices =
274
283
match_index_orclause (rel ,index ,
275
- indexkey ,xclass ,
284
+ indexkey ,opclass ,
276
285
restrictinfo -> clause -> args ,
277
286
restrictinfo -> subclauseindices );
278
287
}
@@ -304,7 +313,7 @@ static List *
304
313
match_index_orclause (RelOptInfo * rel ,
305
314
RelOptInfo * index ,
306
315
int indexkey ,
307
- int xclass ,
316
+ Oid opclass ,
308
317
List * or_clauses ,
309
318
List * other_matching_indices )
310
319
{
@@ -330,7 +339,7 @@ match_index_orclause(RelOptInfo *rel,
330
339
{
331
340
Expr * clause = lfirst (clist );
332
341
333
- if (match_or_subclause_to_indexkey (rel ,index ,indexkey ,xclass ,
342
+ if (match_or_subclause_to_indexkey (rel ,index ,indexkey ,opclass ,
334
343
clause ))
335
344
{
336
345
/* OK to add this index to sublist for this subclause */
@@ -355,7 +364,7 @@ static bool
355
364
match_or_subclause_to_indexkey (RelOptInfo * rel ,
356
365
RelOptInfo * index ,
357
366
int indexkey ,
358
- int xclass ,
367
+ Oid opclass ,
359
368
Expr * clause )
360
369
{
361
370
if (and_clause ((Node * )clause ))
@@ -364,14 +373,14 @@ match_or_subclause_to_indexkey(RelOptInfo *rel,
364
373
365
374
foreach (item ,clause -> args )
366
375
{
367
- if (!match_clause_to_indexkey (rel ,index ,indexkey ,xclass ,
376
+ if (!match_clause_to_indexkey (rel ,index ,indexkey ,opclass ,
368
377
lfirst (item ), false))
369
378
return false;
370
379
}
371
380
return true;
372
381
}
373
382
else
374
- return match_clause_to_indexkey (rel ,index ,indexkey ,xclass ,
383
+ return match_clause_to_indexkey (rel ,index ,indexkey ,opclass ,
375
384
clause , false);
376
385
}
377
386
@@ -588,7 +597,7 @@ group_clauses_by_ikey_for_joins(RelOptInfo *rel,
588
597
* 'rel' is the relation of interest.
589
598
* 'index' is an index on 'rel'.
590
599
* 'indexkey' is a key of 'index'.
591
- * 'xclass ' is the corresponding operator class.
600
+ * 'opclass ' is the corresponding operator class.
592
601
* 'clause' is the clause to be tested.
593
602
* 'join' is true if we are considering this clause for joins.
594
603
*
@@ -601,7 +610,7 @@ static bool
601
610
match_clause_to_indexkey (RelOptInfo * rel ,
602
611
RelOptInfo * index ,
603
612
int indexkey ,
604
- int xclass ,
613
+ Oid opclass ,
605
614
Expr * clause ,
606
615
bool join )
607
616
{
@@ -627,26 +636,28 @@ match_clause_to_indexkey(RelOptInfo *rel,
627
636
if ((IsA (rightop ,Const )|| IsA (rightop ,Param ))&&
628
637
match_index_to_operand (indexkey ,leftop ,rel ,index ))
629
638
{
630
- if (indexable_operator (clause ,xclass ,index -> relam , true))
639
+ if (indexable_operator (clause ,opclass ,index -> relam , true))
631
640
return true;
632
641
/*
633
642
* If we didn't find a member of the index's opclass,
634
643
* see whether it is a "special" indexable operator.
635
644
*/
636
- if (match_special_index_operator (clause , true))
645
+ if (match_special_index_operator (clause ,opclass ,index -> relam ,
646
+ true))
637
647
return true;
638
648
return false;
639
649
}
640
650
if ((IsA (leftop ,Const )|| IsA (leftop ,Param ))&&
641
651
match_index_to_operand (indexkey ,rightop ,rel ,index ))
642
652
{
643
- if (indexable_operator (clause ,xclass ,index -> relam , false))
653
+ if (indexable_operator (clause ,opclass ,index -> relam , false))
644
654
return true;
645
655
/*
646
656
* If we didn't find a member of the index's opclass,
647
657
* see whether it is a "special" indexable operator.
648
658
*/
649
- if (match_special_index_operator (clause , false))
659
+ if (match_special_index_operator (clause ,opclass ,index -> relam ,
660
+ false))
650
661
return true;
651
662
return false;
652
663
}
@@ -666,7 +677,7 @@ match_clause_to_indexkey(RelOptInfo *rel,
666
677
isIndexable = !intMember (lfirsti (rel -> relids ),othervarnos );
667
678
freeList (othervarnos );
668
679
if (isIndexable &&
669
- indexable_operator (clause ,xclass ,index -> relam , true))
680
+ indexable_operator (clause ,opclass ,index -> relam , true))
670
681
return true;
671
682
}
672
683
else if (match_index_to_operand (indexkey ,rightop ,rel ,index ))
@@ -677,7 +688,7 @@ match_clause_to_indexkey(RelOptInfo *rel,
677
688
isIndexable = !intMember (lfirsti (rel -> relids ),othervarnos );
678
689
freeList (othervarnos );
679
690
if (isIndexable &&
680
- indexable_operator (clause ,xclass ,index -> relam , false))
691
+ indexable_operator (clause ,opclass ,index -> relam , false))
681
692
return true;
682
693
}
683
694
}
@@ -706,7 +717,7 @@ match_clause_to_indexkey(RelOptInfo *rel,
706
717
* a tad ugly...
707
718
*/
708
719
static bool
709
- indexable_operator (Expr * clause ,int xclass ,Oid relam ,
720
+ indexable_operator (Expr * clause ,Oid opclass ,Oid relam ,
710
721
bool indexkey_on_left )
711
722
{
712
723
Oid expr_op = ((Oper * )clause -> oper )-> opno ;
@@ -723,7 +734,7 @@ indexable_operator(Expr *clause, int xclass, Oid relam,
723
734
return false;
724
735
725
736
/* 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 ))
727
738
return true;
728
739
729
740
/*
@@ -766,7 +777,7 @@ indexable_operator(Expr *clause, int xclass, Oid relam,
766
777
if (commuted_op == InvalidOid )
767
778
return false;
768
779
769
- if (op_class (commuted_op ,xclass ,relam ))
780
+ if (op_class (commuted_op ,opclass ,relam ))
770
781
{
771
782
/*
772
783
* Success! Change the opclause to use the
@@ -1561,7 +1572,8 @@ function_index_operand(Expr *funcOpnd, RelOptInfo *rel, RelOptInfo *index)
1561
1572
* Return 'true' if we can do something with it anyway.
1562
1573
*/
1563
1574
static 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 )
1565
1577
{
1566
1578
bool isIndexable = false;
1567
1579
Var * leftop ,
@@ -1625,6 +1637,51 @@ match_special_index_operator(Expr *clause, bool indexkey_on_left)
1625
1637
break ;
1626
1638
}
1627
1639
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
+
1628
1685
return isIndexable ;
1629
1686
}
1630
1687
@@ -1848,7 +1905,7 @@ prefix_quals(Var *leftop, Oid expr_op,
1848
1905
{
1849
1906
List * result ;
1850
1907
Oid datatype ;
1851
- HeapTuple optup ;
1908
+ Oid oproid ;
1852
1909
void * conval ;
1853
1910
Const * con ;
1854
1911
Oper * op ;
@@ -1893,12 +1950,8 @@ prefix_quals(Var *leftop, Oid expr_op,
1893
1950
*/
1894
1951
if (pstatus == Prefix_Exact )
1895
1952
{
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 )
1902
1955
elog (ERROR ,"prefix_quals: no = operator for type %u" ,datatype );
1903
1956
/* Note: we cheat a little by assuming that textin() will do for
1904
1957
* bpchar and varchar constants too...
@@ -1908,7 +1961,7 @@ prefix_quals(Var *leftop, Oid expr_op,
1908
1961
con = makeConst (datatype , ((datatype == NAMEOID ) ?NAMEDATALEN :-1 ),
1909
1962
PointerGetDatum (conval ),
1910
1963
false, false, false, false);
1911
- op = makeOper (optup -> t_data -> t_oid ,InvalidOid ,BOOLOID ,0 ,NULL );
1964
+ op = makeOper (oproid ,InvalidOid ,BOOLOID ,0 ,NULL );
1912
1965
expr = make_opclause (op ,leftop , (Var * )con );
1913
1966
result = lcons (expr ,NIL );
1914
1967
return result ;
@@ -1919,19 +1972,15 @@ prefix_quals(Var *leftop, Oid expr_op,
1919
1972
*
1920
1973
* We can always say "x >= prefix".
1921
1974
*/
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 )
1928
1977
elog (ERROR ,"prefix_quals: no >= operator for type %u" ,datatype );
1929
1978
conval = (datatype == NAMEOID ) ?
1930
1979
(void * )namein (prefix ) : (void * )textin (prefix );
1931
1980
con = makeConst (datatype , ((datatype == NAMEOID ) ?NAMEDATALEN :-1 ),
1932
1981
PointerGetDatum (conval ),
1933
1982
false, false, false, false);
1934
- op = makeOper (optup -> t_data -> t_oid ,InvalidOid ,BOOLOID ,0 ,NULL );
1983
+ op = makeOper (oproid ,InvalidOid ,BOOLOID ,0 ,NULL );
1935
1984
expr = make_opclause (op ,leftop , (Var * )con );
1936
1985
result = lcons (expr ,NIL );
1937
1986
@@ -1947,22 +1996,34 @@ prefix_quals(Var *leftop, Oid expr_op,
1947
1996
prefix [prefixlen ]= '\377' ;
1948
1997
prefix [prefixlen + 1 ]= '\0' ;
1949
1998
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 )
1956
2001
elog (ERROR ,"prefix_quals: no <= operator for type %u" ,datatype );
1957
2002
conval = (datatype == NAMEOID ) ?
1958
2003
(void * )namein (prefix ) : (void * )textin (prefix );
1959
2004
con = makeConst (datatype , ((datatype == NAMEOID ) ?NAMEDATALEN :-1 ),
1960
2005
PointerGetDatum (conval ),
1961
2006
false, false, false, false);
1962
- op = makeOper (optup -> t_data -> t_oid ,InvalidOid ,BOOLOID ,0 ,NULL );
2007
+ op = makeOper (oproid ,InvalidOid ,BOOLOID ,0 ,NULL );
1963
2008
expr = make_opclause (op ,leftop , (Var * )con );
1964
2009
result = lappend (result ,expr );
1965
2010
#endif
1966
2011
1967
2012
return result ;
1968
2013
}
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
+ }