Thanks to visit codestin.com
Credit goes to github.com

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

Lines changed: 61 additions & 42 deletions
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)