Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit2810396

Browse files
committed
Fix up handling of nondeterministic collations with pattern_ops opclasses.
text_pattern_ops and its siblings can't be used with nondeterministiccollations, because they use the text_eq operator which will not behaveas bitwise equality if applied with a nondeterministic collation. Theinitial implementation of that restriction was to insert a run-time testin the related comparison functions, but that is inefficient, may throwmisleading errors, and will throw errors in some cases that would work.It seems sufficient to just prevent the combination during CREATE INDEX,so do that instead.Lacking any better way to identify the opclasses involved, we need tohard-wire tests for them, which requires hand-assigned values for theirOIDs, which forces a catversion bump because they previously had OIDsthat would be assigned automatically. That's slightly annoying in thev12 branch, but fortunately we're not at rc1 yet, so just do it.Back-patch to v12 where nondeterministic collations were added.In passing, run make reformat-dat-files, which found some unrelatedwhitespace issues (slightly different ones in HEAD and v12).Peter Eisentraut, with small corrections by meDiscussion:https://postgr.es/m/22566.1568675619@sss.pgh.pa.us
1 parentdf4fbcd commit2810396

File tree

6 files changed

+66
-69
lines changed

6 files changed

+66
-69
lines changed

‎src/backend/catalog/index.c

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -762,6 +762,51 @@ index_create(Relation heapRelation,
762762
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
763763
errmsg("user-defined indexes on system catalog tables are not supported")));
764764

765+
/*
766+
* Btree text_pattern_ops uses text_eq as the equality operator, which is
767+
* fine as long as the collation is deterministic; text_eq then reduces to
768+
* bitwise equality and so it is semantically compatible with the other
769+
* operators and functions in that opclass. But with a nondeterministic
770+
* collation, text_eq could yield results that are incompatible with the
771+
* actual behavior of the index (which is determined by the opclass's
772+
* comparison function). We prevent such problems by refusing creation of
773+
* an index with that opclass and a nondeterministic collation.
774+
*
775+
* The same applies to varchar_pattern_ops and bpchar_pattern_ops. If we
776+
* find more cases, we might decide to create a real mechanism for marking
777+
* opclasses as incompatible with nondeterminism; but for now, this small
778+
* hack suffices.
779+
*
780+
* Another solution is to use a special operator, not text_eq, as the
781+
* equality opclass member; but that is undesirable because it would
782+
* prevent index usage in many queries that work fine today.
783+
*/
784+
for (i=0;i<indexInfo->ii_NumIndexKeyAttrs;i++)
785+
{
786+
Oidcollation=collationObjectId[i];
787+
Oidopclass=classObjectId[i];
788+
789+
if (collation)
790+
{
791+
if ((opclass==TEXT_BTREE_PATTERN_OPS_OID||
792+
opclass==VARCHAR_BTREE_PATTERN_OPS_OID||
793+
opclass==BPCHAR_BTREE_PATTERN_OPS_OID)&&
794+
!get_collation_isdeterministic(collation))
795+
{
796+
HeapTupleclasstup;
797+
798+
classtup=SearchSysCache1(CLAOID,ObjectIdGetDatum(opclass));
799+
if (!HeapTupleIsValid(classtup))
800+
elog(ERROR,"cache lookup failed for operator class %u",opclass);
801+
ereport(ERROR,
802+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
803+
errmsg("nondeterministic collations are not supported for operator class \"%s\"",
804+
NameStr(((Form_pg_opclass)GETSTRUCT(classtup))->opcname))));
805+
ReleaseSysCache(classtup);
806+
}
807+
}
808+
}
809+
765810
/*
766811
* Concurrent index build on a system catalog is unsafe because we tend to
767812
* release locks before committing in catalogs.

‎src/backend/utils/adt/varchar.c

Lines changed: 6 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1105,23 +1105,12 @@ hashbpcharextended(PG_FUNCTION_ARGS)
11051105
*/
11061106

11071107
staticint
1108-
internal_bpchar_pattern_compare(BpChar*arg1,BpChar*arg2,Oidcollid)
1108+
internal_bpchar_pattern_compare(BpChar*arg1,BpChar*arg2)
11091109
{
11101110
intresult;
11111111
intlen1,
11121112
len2;
11131113

1114-
check_collation_set(collid);
1115-
1116-
/*
1117-
* see internal_text_pattern_compare()
1118-
*/
1119-
if (!get_collation_isdeterministic(collid))
1120-
ereport(ERROR,
1121-
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1122-
errmsg("nondeterministic collations are not supported for operator class \"%s\"",
1123-
"bpchar_pattern_ops")));
1124-
11251114
len1=bcTruelen(arg1);
11261115
len2=bcTruelen(arg2);
11271116

@@ -1144,7 +1133,7 @@ bpchar_pattern_lt(PG_FUNCTION_ARGS)
11441133
BpChar*arg2=PG_GETARG_BPCHAR_PP(1);
11451134
intresult;
11461135

1147-
result=internal_bpchar_pattern_compare(arg1,arg2,PG_GET_COLLATION());
1136+
result=internal_bpchar_pattern_compare(arg1,arg2);
11481137

11491138
PG_FREE_IF_COPY(arg1,0);
11501139
PG_FREE_IF_COPY(arg2,1);
@@ -1160,7 +1149,7 @@ bpchar_pattern_le(PG_FUNCTION_ARGS)
11601149
BpChar*arg2=PG_GETARG_BPCHAR_PP(1);
11611150
intresult;
11621151

1163-
result=internal_bpchar_pattern_compare(arg1,arg2,PG_GET_COLLATION());
1152+
result=internal_bpchar_pattern_compare(arg1,arg2);
11641153

11651154
PG_FREE_IF_COPY(arg1,0);
11661155
PG_FREE_IF_COPY(arg2,1);
@@ -1176,7 +1165,7 @@ bpchar_pattern_ge(PG_FUNCTION_ARGS)
11761165
BpChar*arg2=PG_GETARG_BPCHAR_PP(1);
11771166
intresult;
11781167

1179-
result=internal_bpchar_pattern_compare(arg1,arg2,PG_GET_COLLATION());
1168+
result=internal_bpchar_pattern_compare(arg1,arg2);
11801169

11811170
PG_FREE_IF_COPY(arg1,0);
11821171
PG_FREE_IF_COPY(arg2,1);
@@ -1192,7 +1181,7 @@ bpchar_pattern_gt(PG_FUNCTION_ARGS)
11921181
BpChar*arg2=PG_GETARG_BPCHAR_PP(1);
11931182
intresult;
11941183

1195-
result=internal_bpchar_pattern_compare(arg1,arg2,PG_GET_COLLATION());
1184+
result=internal_bpchar_pattern_compare(arg1,arg2);
11961185

11971186
PG_FREE_IF_COPY(arg1,0);
11981187
PG_FREE_IF_COPY(arg2,1);
@@ -1208,7 +1197,7 @@ btbpchar_pattern_cmp(PG_FUNCTION_ARGS)
12081197
BpChar*arg2=PG_GETARG_BPCHAR_PP(1);
12091198
intresult;
12101199

1211-
result=internal_bpchar_pattern_compare(arg1,arg2,PG_GET_COLLATION());
1200+
result=internal_bpchar_pattern_compare(arg1,arg2);
12121201

12131202
PG_FREE_IF_COPY(arg1,0);
12141203
PG_FREE_IF_COPY(arg2,1);
@@ -1221,17 +1210,8 @@ Datum
12211210
btbpchar_pattern_sortsupport(PG_FUNCTION_ARGS)
12221211
{
12231212
SortSupportssup= (SortSupport)PG_GETARG_POINTER(0);
1224-
Oidcollid=ssup->ssup_collation;
12251213
MemoryContextoldcontext;
12261214

1227-
check_collation_set(collid);
1228-
1229-
if (!get_collation_isdeterministic(collid))
1230-
ereport(ERROR,
1231-
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1232-
errmsg("nondeterministic collations are not supported for operator class \"%s\"",
1233-
"bpchar_pattern_ops")));
1234-
12351215
oldcontext=MemoryContextSwitchTo(ssup->ssup_cxt);
12361216

12371217
/* Use generic string SortSupport, forcing "C" collation */

‎src/backend/utils/adt/varlena.c

Lines changed: 6 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2996,34 +2996,12 @@ textgename(PG_FUNCTION_ARGS)
29962996
*/
29972997

29982998
staticint
2999-
internal_text_pattern_compare(text*arg1,text*arg2,Oidcollid)
2999+
internal_text_pattern_compare(text*arg1,text*arg2)
30003000
{
30013001
intresult;
30023002
intlen1,
30033003
len2;
30043004

3005-
check_collation_set(collid);
3006-
3007-
/*
3008-
* XXX We cannot use a text_pattern_ops index for nondeterministic
3009-
* collations, because these operators intentionally ignore the collation.
3010-
* However, the planner has no way to know that, so it might choose such
3011-
* an index for an "=" clause, which would lead to wrong results. This
3012-
* check here doesn't prevent choosing the index, but it will at least
3013-
* error out if the index is chosen. A text_pattern_ops index on a column
3014-
* with nondeterministic collation is pretty useless anyway, since LIKE
3015-
* etc. won't work there either. A future possibility would be to
3016-
* annotate the operator class or its members in the catalog to avoid the
3017-
* index. Another alternative is to stay away from the *_pattern_ops
3018-
* operator classes and prefer creating LIKE-supporting indexes with
3019-
* COLLATE "C".
3020-
*/
3021-
if (!get_collation_isdeterministic(collid))
3022-
ereport(ERROR,
3023-
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3024-
errmsg("nondeterministic collations are not supported for operator class \"%s\"",
3025-
"text_pattern_ops")));
3026-
30273005
len1=VARSIZE_ANY_EXHDR(arg1);
30283006
len2=VARSIZE_ANY_EXHDR(arg2);
30293007

@@ -3046,7 +3024,7 @@ text_pattern_lt(PG_FUNCTION_ARGS)
30463024
text*arg2=PG_GETARG_TEXT_PP(1);
30473025
intresult;
30483026

3049-
result=internal_text_pattern_compare(arg1,arg2,PG_GET_COLLATION());
3027+
result=internal_text_pattern_compare(arg1,arg2);
30503028

30513029
PG_FREE_IF_COPY(arg1,0);
30523030
PG_FREE_IF_COPY(arg2,1);
@@ -3062,7 +3040,7 @@ text_pattern_le(PG_FUNCTION_ARGS)
30623040
text*arg2=PG_GETARG_TEXT_PP(1);
30633041
intresult;
30643042

3065-
result=internal_text_pattern_compare(arg1,arg2,PG_GET_COLLATION());
3043+
result=internal_text_pattern_compare(arg1,arg2);
30663044

30673045
PG_FREE_IF_COPY(arg1,0);
30683046
PG_FREE_IF_COPY(arg2,1);
@@ -3078,7 +3056,7 @@ text_pattern_ge(PG_FUNCTION_ARGS)
30783056
text*arg2=PG_GETARG_TEXT_PP(1);
30793057
intresult;
30803058

3081-
result=internal_text_pattern_compare(arg1,arg2,PG_GET_COLLATION());
3059+
result=internal_text_pattern_compare(arg1,arg2);
30823060

30833061
PG_FREE_IF_COPY(arg1,0);
30843062
PG_FREE_IF_COPY(arg2,1);
@@ -3094,7 +3072,7 @@ text_pattern_gt(PG_FUNCTION_ARGS)
30943072
text*arg2=PG_GETARG_TEXT_PP(1);
30953073
intresult;
30963074

3097-
result=internal_text_pattern_compare(arg1,arg2,PG_GET_COLLATION());
3075+
result=internal_text_pattern_compare(arg1,arg2);
30983076

30993077
PG_FREE_IF_COPY(arg1,0);
31003078
PG_FREE_IF_COPY(arg2,1);
@@ -3110,7 +3088,7 @@ bttext_pattern_cmp(PG_FUNCTION_ARGS)
31103088
text*arg2=PG_GETARG_TEXT_PP(1);
31113089
intresult;
31123090

3113-
result=internal_text_pattern_compare(arg1,arg2,PG_GET_COLLATION());
3091+
result=internal_text_pattern_compare(arg1,arg2);
31143092

31153093
PG_FREE_IF_COPY(arg1,0);
31163094
PG_FREE_IF_COPY(arg2,1);
@@ -3123,17 +3101,8 @@ Datum
31233101
bttext_pattern_sortsupport(PG_FUNCTION_ARGS)
31243102
{
31253103
SortSupportssup= (SortSupport)PG_GETARG_POINTER(0);
3126-
Oidcollid=ssup->ssup_collation;
31273104
MemoryContextoldcontext;
31283105

3129-
check_collation_set(collid);
3130-
3131-
if (!get_collation_isdeterministic(collid))
3132-
ereport(ERROR,
3133-
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
3134-
errmsg("nondeterministic collations are not supported for operator class \"%s\"",
3135-
"text_pattern_ops")));
3136-
31373106
oldcontext=MemoryContextSwitchTo(ssup->ssup_cxt);
31383107

31393108
/* Use generic string SortSupport, forcing "C" collation */

‎src/include/catalog/catversion.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,6 @@
5353
*/
5454

5555
/*yyyymmddN */
56-
#defineCATALOG_VERSION_NO201909071
56+
#defineCATALOG_VERSION_NO201909213
5757

5858
#endif

‎src/include/catalog/pg_opclass.dat

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -146,13 +146,16 @@
146146
opcfamily => 'btree/datetime_ops', opcintype => 'timestamp' },
147147
{ opcmethod => 'hash', opcname => 'timestamp_ops',
148148
opcfamily => 'hash/timestamp_ops', opcintype => 'timestamp' },
149-
{ opcmethod => 'btree', opcname => 'text_pattern_ops',
149+
{ oid => '4217', oid_symbol => 'TEXT_BTREE_PATTERN_OPS_OID',
150+
opcmethod => 'btree', opcname => 'text_pattern_ops',
150151
opcfamily => 'btree/text_pattern_ops', opcintype => 'text',
151152
opcdefault => 'f' },
152-
{ opcmethod => 'btree', opcname => 'varchar_pattern_ops',
153+
{ oid => '4218', oid_symbol => 'VARCHAR_BTREE_PATTERN_OPS_OID',
154+
opcmethod => 'btree', opcname => 'varchar_pattern_ops',
153155
opcfamily => 'btree/text_pattern_ops', opcintype => 'text',
154156
opcdefault => 'f' },
155-
{ opcmethod => 'btree', opcname => 'bpchar_pattern_ops',
157+
{ oid => '4219', oid_symbol => 'BPCHAR_BTREE_PATTERN_OPS_OID',
158+
opcmethod => 'btree', opcname => 'bpchar_pattern_ops',
156159
opcfamily => 'btree/bpchar_pattern_ops', opcintype => 'bpchar',
157160
opcdefault => 'f' },
158161
{ opcmethod => 'btree', opcname => 'money_ops', opcfamily => 'btree/money_ops',

‎src/include/catalog/pg_operator.dat

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -660,13 +660,13 @@
660660

661661
{ oid => '613', descr => 'distance between',
662662
oprname => '<->', oprleft => 'point', oprright => 'line',
663-
oprresult => 'float8', oprcom => '<->(line,point)',oprcode => 'dist_pl' },
663+
oprresult => 'float8', oprcom => '<->(line,point)',oprcode => 'dist_pl' },
664664
{ oid => '760', descr => 'distance between',
665665
oprname => '<->', oprleft => 'line', oprright => 'point',
666666
oprresult => 'float8', oprcom => '<->(point,line)', oprcode => 'dist_lp' },
667667
{ oid => '614', descr => 'distance between',
668668
oprname => '<->', oprleft => 'point', oprright => 'lseg',
669-
oprresult => 'float8', oprcom => '<->(lseg,point)',oprcode => 'dist_ps' },
669+
oprresult => 'float8', oprcom => '<->(lseg,point)',oprcode => 'dist_ps' },
670670
{ oid => '761', descr => 'distance between',
671671
oprname => '<->', oprleft => 'lseg', oprright => 'point',
672672
oprresult => 'float8', oprcom => '<->(point,lseg)', oprcode => 'dist_sp' },

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp