Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 69f1d5f

Browse files
committed
Clean up minor collation issues in indxpath.c.
Get rid of bogus collation test in match_special_index_operator (even for ILIKE, the pattern match operator's collation doesn't matter here, and even if it did the test was testing the wrong thing). Fix broken looping logic in expand_indexqual_rowcompare. Add collation check in match_clause_to_ordering_op. Make naming and argument ordering more consistent; improve comments.
1 parent 466dac8 commit 69f1d5f

File tree

1 file changed

+61
-42
lines changed

1 file changed

+61
-42
lines changed

src/backend/optimizer/path/indxpath.c

+61-42
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
#include "catalog/pg_opfamily.h"
2525
#include "catalog/pg_type.h"
2626
#include "nodes/makefuncs.h"
27-
#include "nodes/nodeFuncs.h"
2827
#include "optimizer/clauses.h"
2928
#include "optimizer/cost.h"
3029
#include "optimizer/pathnode.h"
@@ -101,6 +100,7 @@ static bool is_indexable_operator(Oid expr_op, Oid opfamily,
101100
static bool match_rowcompare_to_indexcol(IndexOptInfo *index,
102101
int indexcol,
103102
Oid opfamily,
103+
Oid idxcollation,
104104
RowCompareExpr *clause,
105105
Relids outer_relids);
106106
static List *match_index_to_pathkeys(IndexOptInfo *index, List *pathkeys);
@@ -113,11 +113,13 @@ static List *find_clauses_for_join(PlannerInfo *root, RelOptInfo *rel,
113113
Relids outer_relids, bool isouterjoin);
114114
static bool match_boolean_index_clause(Node *clause, int indexcol,
115115
IndexOptInfo *index);
116-
static bool match_special_index_operator(Expr *clause, Oid idxcolcollation, Oid opfamily,
116+
static bool match_special_index_operator(Expr *clause,
117+
Oid opfamily, Oid idxcollation,
117118
bool indexkey_on_left);
118119
static Expr *expand_boolean_index_clause(Node *clause, int indexcol,
119120
IndexOptInfo *index);
120-
static List *expand_indexqual_opclause(RestrictInfo *rinfo, Oid opfamily, Oid collation);
121+
static List *expand_indexqual_opclause(RestrictInfo *rinfo,
122+
Oid opfamily, Oid idxcollation);
121123
static RestrictInfo *expand_indexqual_rowcompare(RestrictInfo *rinfo,
122124
IndexOptInfo *index,
123125
int indexcol);
@@ -1158,7 +1160,7 @@ group_clauses_by_indexkey(IndexOptInfo *index,
11581160
* operator for this column, or is a "special" operator as recognized
11591161
* by match_special_index_operator();
11601162
* and
1161-
* (3) must match the collation of the index.
1163+
* (3) must match the collation of the index, if collation is relevant.
11621164
*
11631165
* Our definition of "const" is pretty liberal: we allow Vars belonging
11641166
* to the caller-specified outer_relids relations (which had better not
@@ -1215,7 +1217,7 @@ match_clause_to_indexcol(IndexOptInfo *index,
12151217
{
12161218
Expr *clause = rinfo->clause;
12171219
Oid opfamily = index->opfamily[indexcol];
1218-
Oid collation = index->indexcollations[indexcol];
1220+
Oid idxcollation = index->indexcollations[indexcol];
12191221
Node *leftop,
12201222
*rightop;
12211223
Relids left_relids;
@@ -1276,7 +1278,8 @@ match_clause_to_indexcol(IndexOptInfo *index,
12761278
}
12771279
else if (clause && IsA(clause, RowCompareExpr))
12781280
{
1279-
return match_rowcompare_to_indexcol(index, indexcol, opfamily,
1281+
return match_rowcompare_to_indexcol(index, indexcol,
1282+
opfamily, idxcollation,
12801283
(RowCompareExpr *) clause,
12811284
outer_relids);
12821285
}
@@ -1300,7 +1303,7 @@ match_clause_to_indexcol(IndexOptInfo *index,
13001303
bms_is_subset(right_relids, outer_relids) &&
13011304
!contain_volatile_functions(rightop))
13021305
{
1303-
if (collation == expr_coll &&
1306+
if (idxcollation == expr_coll &&
13041307
is_indexable_operator(expr_op, opfamily, true))
13051308
return true;
13061309

@@ -1309,7 +1312,7 @@ match_clause_to_indexcol(IndexOptInfo *index,
13091312
* is a "special" indexable operator.
13101313
*/
13111314
if (plain_op &&
1312-
match_special_index_operator(clause, collation, opfamily, true))
1315+
match_special_index_operator(clause, opfamily, idxcollation, true))
13131316
return true;
13141317
return false;
13151318
}
@@ -1319,15 +1322,15 @@ match_clause_to_indexcol(IndexOptInfo *index,
13191322
bms_is_subset(left_relids, outer_relids) &&
13201323
!contain_volatile_functions(leftop))
13211324
{
1322-
if (collation == expr_coll &&
1325+
if (idxcollation == expr_coll &&
13231326
is_indexable_operator(expr_op, opfamily, false))
13241327
return true;
13251328

13261329
/*
13271330
* If we didn't find a member of the index's opfamily, see whether it
13281331
* is a "special" indexable operator.
13291332
*/
1330-
if (match_special_index_operator(clause, collation, opfamily, false))
1333+
if (match_special_index_operator(clause, opfamily, idxcollation, false))
13311334
return true;
13321335
return false;
13331336
}
@@ -1367,12 +1370,14 @@ static bool
13671370
match_rowcompare_to_indexcol(IndexOptInfo *index,
13681371
int indexcol,
13691372
Oid opfamily,
1373+
Oid idxcollation,
13701374
RowCompareExpr *clause,
13711375
Relids outer_relids)
13721376
{
13731377
Node *leftop,
13741378
*rightop;
13751379
Oid expr_op;
1380+
Oid expr_coll;
13761381

13771382
/* Forget it if we're not dealing with a btree index */
13781383
if (index->relam != BTREE_AM_OID)
@@ -1391,6 +1396,11 @@ match_rowcompare_to_indexcol(IndexOptInfo *index,
13911396
leftop = (Node *) linitial(clause->largs);
13921397
rightop = (Node *) linitial(clause->rargs);
13931398
expr_op = linitial_oid(clause->opnos);
1399+
expr_coll = linitial_oid(clause->inputcollids);
1400+
1401+
/* Collations must match */
1402+
if (expr_coll != idxcollation)
1403+
return false;
13941404

13951405
/*
13961406
* These syntactic tests are the same as in match_clause_to_indexcol()
@@ -1413,9 +1423,6 @@ match_rowcompare_to_indexcol(IndexOptInfo *index,
14131423
else
14141424
return false;
14151425

1416-
if (index->indexcollations[indexcol] != linitial_oid(clause->inputcollids))
1417-
return false;
1418-
14191426
/* We're good if the operator is the right type of opfamily member */
14201427
switch (get_op_opfamily_strategy(expr_op, opfamily))
14211428
{
@@ -1525,6 +1532,12 @@ match_index_to_pathkeys(IndexOptInfo *index, List *pathkeys)
15251532
* 'clause' is the ordering expression to be tested.
15261533
* 'pk_opfamily' is the btree opfamily describing the required sort order.
15271534
*
1535+
* Note that we currently do not consider the collation of the ordering
1536+
* operator's result. In practical cases the result type will be numeric
1537+
* and thus have no collation, and it's not very clear what to match to
1538+
* if it did have a collation. The index's collation should match the
1539+
* ordering operator's input collation, not its result.
1540+
*
15281541
* If successful, return 'clause' as-is if the indexkey is on the left,
15291542
* otherwise a commuted copy of 'clause'. If no match, return NULL.
15301543
*/
@@ -1535,9 +1548,11 @@ match_clause_to_ordering_op(IndexOptInfo *index,
15351548
Oid pk_opfamily)
15361549
{
15371550
Oid opfamily = index->opfamily[indexcol];
1551+
Oid idxcollation = index->indexcollations[indexcol];
15381552
Node *leftop,
15391553
*rightop;
15401554
Oid expr_op;
1555+
Oid expr_coll;
15411556
Oid sortfamily;
15421557
bool commuted;
15431558

@@ -1551,6 +1566,13 @@ match_clause_to_ordering_op(IndexOptInfo *index,
15511566
if (!leftop || !rightop)
15521567
return NULL;
15531568
expr_op = ((OpExpr *) clause)->opno;
1569+
expr_coll = ((OpExpr *) clause)->inputcollid;
1570+
1571+
/*
1572+
* We can forget the whole thing right away if wrong collation.
1573+
*/
1574+
if (expr_coll != idxcollation)
1575+
return NULL;
15541576

15551577
/*
15561578
* Check for clauses of the form: (indexkey operator constant) or
@@ -2175,6 +2197,12 @@ relation_has_unique_index_for(PlannerInfo *root, RelOptInfo *rel,
21752197
if (!list_member_oid(rinfo->mergeopfamilies, ind->opfamily[c]))
21762198
continue;
21772199

2200+
/*
2201+
* XXX at some point we may need to check collations here
2202+
* too. For the moment we assume all collations reduce to
2203+
* the same notion of equality.
2204+
*/
2205+
21782206
/* OK, see if the condition operand matches the index key */
21792207
if (rinfo->outer_is_left)
21802208
rexpr = get_rightop(rinfo->clause);
@@ -2235,6 +2263,9 @@ flatten_clausegroups_list(List *clausegroups)
22352263
* operand: the nodetree to be compared to the index
22362264
* indexcol: the column number of the index (counting from 0)
22372265
* index: the index of interest
2266+
*
2267+
* Note that we aren't interested in collations here; the caller must check
2268+
* for a collation match, if it's dealing with an operator where that matters.
22382269
*/
22392270
bool
22402271
match_index_to_operand(Node *operand,
@@ -2409,7 +2440,7 @@ match_boolean_index_clause(Node *clause,
24092440
* Return 'true' if we can do something with it anyway.
24102441
*/
24112442
static bool
2412-
match_special_index_operator(Expr *clause, Oid idxcolcollation, Oid opfamily,
2443+
match_special_index_operator(Expr *clause, Oid opfamily, Oid idxcollation,
24132444
bool indexkey_on_left)
24142445
{
24152446
bool isIndexable = false;
@@ -2513,7 +2544,10 @@ match_special_index_operator(Expr *clause, Oid idxcolcollation, Oid opfamily,
25132544
*
25142545
* The non-pattern opclasses will not sort the way we need in most non-C
25152546
* locales. We can use such an index anyway for an exact match (simple
2516-
* equality), but not for prefix-match cases.
2547+
* equality), but not for prefix-match cases. Note that we are looking
2548+
* at the index's collation, not the expression's collation -- this test
2549+
* is not dependent on the LIKE/regex operator's collation (which would
2550+
* only affect case folding behavior of ILIKE, anyway).
25172551
*/
25182552
switch (expr_op)
25192553
{
@@ -2524,7 +2558,7 @@ match_special_index_operator(Expr *clause, Oid idxcolcollation, Oid opfamily,
25242558
isIndexable =
25252559
(opfamily == TEXT_PATTERN_BTREE_FAM_OID) ||
25262560
(opfamily == TEXT_BTREE_FAM_OID &&
2527-
(pstatus == Pattern_Prefix_Exact || lc_collate_is_c(idxcolcollation)));
2561+
(pstatus == Pattern_Prefix_Exact || lc_collate_is_c(idxcollation)));
25282562
break;
25292563

25302564
case OID_BPCHAR_LIKE_OP:
@@ -2534,7 +2568,7 @@ match_special_index_operator(Expr *clause, Oid idxcolcollation, Oid opfamily,
25342568
isIndexable =
25352569
(opfamily == BPCHAR_PATTERN_BTREE_FAM_OID) ||
25362570
(opfamily == BPCHAR_BTREE_FAM_OID &&
2537-
(pstatus == Pattern_Prefix_Exact || lc_collate_is_c(idxcolcollation)));
2571+
(pstatus == Pattern_Prefix_Exact || lc_collate_is_c(idxcollation)));
25382572
break;
25392573

25402574
case OID_NAME_LIKE_OP:
@@ -2555,25 +2589,6 @@ match_special_index_operator(Expr *clause, Oid idxcolcollation, Oid opfamily,
25552589
break;
25562590
}
25572591

2558-
if (!isIndexable)
2559-
return false;
2560-
2561-
/*
2562-
* For case-insensitive matching, we also need to check that the
2563-
* collations match.
2564-
*/
2565-
switch (expr_op)
2566-
{
2567-
case OID_TEXT_ICLIKE_OP:
2568-
case OID_TEXT_ICREGEXEQ_OP:
2569-
case OID_BPCHAR_ICLIKE_OP:
2570-
case OID_BPCHAR_ICREGEXEQ_OP:
2571-
case OID_NAME_ICLIKE_OP:
2572-
case OID_NAME_ICREGEXEQ_OP:
2573-
isIndexable = (idxcolcollation == exprCollation((Node *) clause));
2574-
break;
2575-
}
2576-
25772592
return isIndexable;
25782593
}
25792594

@@ -2747,7 +2762,7 @@ expand_boolean_index_clause(Node *clause,
27472762
* expand special cases that were accepted by match_special_index_operator().
27482763
*/
27492764
static List *
2750-
expand_indexqual_opclause(RestrictInfo *rinfo, Oid opfamily, Oid collation)
2765+
expand_indexqual_opclause(RestrictInfo *rinfo, Oid opfamily, Oid idxcollation)
27512766
{
27522767
Expr *clause = rinfo->clause;
27532768

@@ -2778,7 +2793,7 @@ expand_indexqual_opclause(RestrictInfo *rinfo, Oid opfamily, Oid collation)
27782793
{
27792794
pstatus = pattern_fixed_prefix(patt, Pattern_Type_Like,
27802795
&prefix, &rest);
2781-
return prefix_quals(leftop, opfamily, collation, prefix, pstatus);
2796+
return prefix_quals(leftop, opfamily, idxcollation, prefix, pstatus);
27822797
}
27832798
break;
27842799

@@ -2790,7 +2805,7 @@ expand_indexqual_opclause(RestrictInfo *rinfo, Oid opfamily, Oid collation)
27902805
/* the right-hand const is type text for all of these */
27912806
pstatus = pattern_fixed_prefix(patt, Pattern_Type_Like_IC,
27922807
&prefix, &rest);
2793-
return prefix_quals(leftop, opfamily, collation, prefix, pstatus);
2808+
return prefix_quals(leftop, opfamily, idxcollation, prefix, pstatus);
27942809
}
27952810
break;
27962811

@@ -2802,7 +2817,7 @@ expand_indexqual_opclause(RestrictInfo *rinfo, Oid opfamily, Oid collation)
28022817
/* the right-hand const is type text for all of these */
28032818
pstatus = pattern_fixed_prefix(patt, Pattern_Type_Regex,
28042819
&prefix, &rest);
2805-
return prefix_quals(leftop, opfamily, collation, prefix, pstatus);
2820+
return prefix_quals(leftop, opfamily, idxcollation, prefix, pstatus);
28062821
}
28072822
break;
28082823

@@ -2814,7 +2829,7 @@ expand_indexqual_opclause(RestrictInfo *rinfo, Oid opfamily, Oid collation)
28142829
/* the right-hand const is type text for all of these */
28152830
pstatus = pattern_fixed_prefix(patt, Pattern_Type_Regex_IC,
28162831
&prefix, &rest);
2817-
return prefix_quals(leftop, opfamily, collation, prefix, pstatus);
2832+
return prefix_quals(leftop, opfamily, idxcollation, prefix, pstatus);
28182833
}
28192834
break;
28202835

@@ -2965,6 +2980,7 @@ expand_indexqual_rowcompare(RestrictInfo *rinfo,
29652980
largs_cell = lnext(largs_cell);
29662981
rargs_cell = lnext(rargs_cell);
29672982
opnos_cell = lnext(opnos_cell);
2983+
collids_cell = lnext(collids_cell);
29682984
}
29692985

29702986
/* Return clause as-is if it's all usable as index quals */
@@ -3158,7 +3174,10 @@ prefix_quals(Node *leftop, Oid opfamily, Oid collation,
31583174

31593175
/*-------
31603176
* If we can create a string larger than the prefix, we can say
3161-
* "x < greaterstr".
3177+
* "x < greaterstr". NB: we rely on make_greater_string() to generate
3178+
* a guaranteed-greater string, not just a probably-greater string.
3179+
* In general this is only guaranteed in C locale, so we'd better be
3180+
* using a C-locale index collation.
31623181
*-------
31633182
*/
31643183
oproid = get_opfamily_member(opfamily, datatype, datatype,

0 commit comments

Comments
 (0)