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

Commit9321d2f

Browse files
committed
Fix collation handling for foreign keys
Allowing foreign keys where the referenced and the referencing columnshave collations with different notions of equality is problematic.This can only happen when using nondeterministic collations, forexample, if the referencing column is case-insensitive and thereferenced column is not, or vice versa. It does not happen if bothcollations are deterministic.To show one example: CREATE COLLATION case_insensitive (provider = icu, deterministic = false, locale = 'und-u-ks-level2'); CREATE TABLE pktable (x text COLLATE "C" PRIMARY KEY); CREATE TABLE fktable (x text COLLATE case_insensitive REFERENCES pktable ON UPDATE CASCADE ON DELETE CASCADE); INSERT INTO pktable VALUES ('A'), ('a'); INSERT INTO fktable VALUES ('A'); BEGIN; DELETE FROM pktable WHERE x = 'a'; TABLE fktable; ROLLBACK; BEGIN; DELETE FROM pktable WHERE x = 'A'; TABLE fktable; ROLLBACK;Both of these DELETE statements delete the one row from fktable. Sothis means that one row from fktable references two rows in pktable,which should not happen. (That's why a primary key or uniqueconstraint is required on pktable.)When nondeterministic collations were implemented, the SQL standardavailable to yours truly said that referential integrity checks shouldbe performed with the collation of the referenced column, and sothat's how we implemented it. But this turned out to be a mistake inthe SQL standard, for the same reasons as above, that was later(SQL:2016) fixed to require both collations to be the same. So that'swhat we are aiming for here.We don't have to be quite so strict. We can allow differentcollations if they are both deterministic. This is also good forbackward compatibility.So the new rule is that the collations either have to be the same orboth deterministic. Or in other words, if one of them isnondeterministic, then both have to be the same.Users upgrading from before that have affected setups will need tomake changes to their schemas (i.e., change one or both collations inaffected foreign-key relationships) before the upgrade will succeed.Some of the nice test cases for the previous situation incollate.icu.utf8.sql are now obsolete. They are changed to just checkthe error checking of the new rule. Note that collate.sql alreadycontained a test for foreign keys with different deterministiccollations.A bunch of code in ri_triggers.c that added a COLLATE clause toenforce the referenced column's collation can be removed, because bothcolumns now have to have the same notion of equality, so it doesn'tmatter which one to use.Reported-by: Paul Jungwirth <pj@illuminatedcomputing.com>Reviewed-by: Jian He <jian.universality@gmail.com>Discussion:https://www.postgresql.org/message-id/flat/78d824e0-b21e-480d-a252-e4b84bc2c24b@illuminatedcomputing.com
1 parent90bcc7c commit9321d2f

File tree

5 files changed

+105
-178
lines changed

5 files changed

+105
-178
lines changed

‎doc/src/sgml/ref/create_table.sgml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1205,6 +1205,13 @@ WITH ( MODULUS <replaceable class="parameter">numeric_literal</replaceable>, REM
12051205
must have its final column marked <literal>WITHOUT OVERLAPS</literal>.
12061206
</para>
12071207

1208+
<para>
1209+
For each pair of referencing and referenced column, if they are of a
1210+
collatable data type, then the collations must either be both
1211+
deterministic or else both the same. This ensures that both columns
1212+
have a consistent notion of equality.
1213+
</para>
1214+
12081215
<para>
12091216
The user
12101217
must have <literal>REFERENCES</literal> permission on the referenced

‎src/backend/commands/tablecmds.c

Lines changed: 68 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -398,10 +398,10 @@ static ObjectAddress ATExecValidateConstraint(List **wqueue,
398398
Relation rel, char *constrName,
399399
bool recurse, bool recursing, LOCKMODE lockmode);
400400
static inttransformColumnNameList(Oid relId, List *colList,
401-
int16 *attnums, Oid *atttypids);
401+
int16 *attnums, Oid *atttypids, Oid *attcollids);
402402
static inttransformFkeyGetPrimaryKey(Relation pkrel, Oid *indexOid,
403403
List **attnamelist,
404-
int16 *attnums, Oid *atttypids,
404+
int16 *attnums, Oid *atttypids, Oid *attcollids,
405405
Oid *opclasses, bool *pk_has_without_overlaps);
406406
static OidtransformFkeyCheckAttrs(Relation pkrel,
407407
int numattrs, int16 *attnums,
@@ -9705,6 +9705,8 @@ ATAddForeignKeyConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
97059705
int16fkattnum[INDEX_MAX_KEYS] = {0};
97069706
Oidpktypoid[INDEX_MAX_KEYS] = {0};
97079707
Oidfktypoid[INDEX_MAX_KEYS] = {0};
9708+
Oidpkcolloid[INDEX_MAX_KEYS] = {0};
9709+
Oidfkcolloid[INDEX_MAX_KEYS] = {0};
97089710
Oidopclasses[INDEX_MAX_KEYS] = {0};
97099711
Oidpfeqoperators[INDEX_MAX_KEYS] = {0};
97109712
Oidppeqoperators[INDEX_MAX_KEYS] = {0};
@@ -9801,11 +9803,11 @@ ATAddForeignKeyConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
98019803

98029804
/*
98039805
* Look up the referencing attributes to make sure they exist, and record
9804-
* their attnums and type OIDs.
9806+
* their attnums and typeand collationOIDs.
98059807
*/
98069808
numfks = transformColumnNameList(RelationGetRelid(rel),
98079809
fkconstraint->fk_attrs,
9808-
fkattnum, fktypoid);
9810+
fkattnum, fktypoid, fkcolloid);
98099811
with_period = fkconstraint->fk_with_period || fkconstraint->pk_with_period;
98109812
if (with_period && !fkconstraint->fk_with_period)
98119813
ereport(ERROR,
@@ -9814,7 +9816,7 @@ ATAddForeignKeyConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
98149816

98159817
numfkdelsetcols = transformColumnNameList(RelationGetRelid(rel),
98169818
fkconstraint->fk_del_set_cols,
9817-
fkdelsetcols, NULL);
9819+
fkdelsetcols, NULL, NULL);
98189820
validateFkOnDeleteSetColumns(numfks, fkattnum,
98199821
numfkdelsetcols, fkdelsetcols,
98209822
fkconstraint->fk_del_set_cols);
@@ -9823,13 +9825,14 @@ ATAddForeignKeyConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
98239825
* If the attribute list for the referenced table was omitted, lookup the
98249826
* definition of the primary key and use it. Otherwise, validate the
98259827
* supplied attribute list. In either case, discover the index OID and
9826-
* index opclasses, and the attnums and type OIDs of the attributes.
9828+
* index opclasses, and the attnums and type and collation OIDs of the
9829+
* attributes.
98279830
*/
98289831
if (fkconstraint->pk_attrs == NIL)
98299832
{
98309833
numpks = transformFkeyGetPrimaryKey(pkrel, &indexOid,
98319834
&fkconstraint->pk_attrs,
9832-
pkattnum, pktypoid,
9835+
pkattnum, pktypoid, pkcolloid,
98339836
opclasses, &pk_has_without_overlaps);
98349837

98359838
/* If the primary key uses WITHOUT OVERLAPS, the fk must use PERIOD */
@@ -9842,7 +9845,7 @@ ATAddForeignKeyConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
98429845
{
98439846
numpks = transformColumnNameList(RelationGetRelid(pkrel),
98449847
fkconstraint->pk_attrs,
9845-
pkattnum, pktypoid);
9848+
pkattnum, pktypoid, pkcolloid);
98469849

98479850
/* Since we got pk_attrs, one should be a period. */
98489851
if (with_period && !fkconstraint->pk_with_period)
@@ -9944,6 +9947,8 @@ ATAddForeignKeyConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
99449947
Oidpktype = pktypoid[i];
99459948
Oidfktype = fktypoid[i];
99469949
Oidfktyped;
9950+
Oidpkcoll = pkcolloid[i];
9951+
Oidfkcoll = fkcolloid[i];
99479952
HeapTuplecla_ht;
99489953
Form_pg_opclass cla_tup;
99499954
Oidamid;
@@ -10086,6 +10091,41 @@ ATAddForeignKeyConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
1008610091
format_type_be(fktype),
1008710092
format_type_be(pktype))));
1008810093

10094+
/*
10095+
* This shouldn't be possible, but better check to make sure we have a
10096+
* consistent state for the check below.
10097+
*/
10098+
if ((OidIsValid(pkcoll) && !OidIsValid(fkcoll)) || (!OidIsValid(pkcoll) && OidIsValid(fkcoll)))
10099+
elog(ERROR, "key columns are not both collatable");
10100+
10101+
if (OidIsValid(pkcoll) && OidIsValid(fkcoll))
10102+
{
10103+
boolpkcolldet;
10104+
boolfkcolldet;
10105+
10106+
pkcolldet = get_collation_isdeterministic(pkcoll);
10107+
fkcolldet = get_collation_isdeterministic(fkcoll);
10108+
10109+
/*
10110+
* SQL requires that both collations are the same. This is
10111+
* because we need a consistent notion of equality on both
10112+
* columns. We relax this by allowing different collations if
10113+
* they are both deterministic. (This is also for backward
10114+
* compatibility, because PostgreSQL has always allowed this.)
10115+
*/
10116+
if ((!pkcolldet || !fkcolldet) && pkcoll != fkcoll)
10117+
ereport(ERROR,
10118+
(errcode(ERRCODE_COLLATION_MISMATCH),
10119+
errmsg("foreign key constraint \"%s\" cannot be implemented", fkconstraint->conname),
10120+
errdetail("Key columns \"%s\" of the referencing table and \"%s\" of the referenced table "
10121+
"have incompatible collations: \"%s\" and \"%s\". "
10122+
"If either collation is nondeterministic, then both collations have to be the same.",
10123+
strVal(list_nth(fkconstraint->fk_attrs, i)),
10124+
strVal(list_nth(fkconstraint->pk_attrs, i)),
10125+
get_collation_name(fkcoll),
10126+
get_collation_name(pkcoll))));
10127+
}
10128+
1008910129
if (old_check_ok)
1009010130
{
1009110131
/*
@@ -10106,6 +10146,8 @@ ATAddForeignKeyConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
1010610146
CoercionPathType new_pathtype;
1010710147
Oidold_castfunc;
1010810148
Oidnew_castfunc;
10149+
Oidold_fkcoll;
10150+
Oidnew_fkcoll;
1010910151
Form_pg_attribute attr = TupleDescAttr(tab->oldDesc,
1011010152
fkattnum[i] - 1);
1011110153

@@ -10121,6 +10163,9 @@ ATAddForeignKeyConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
1012110163
new_pathtype = findFkeyCast(pfeqop_right, new_fktype,
1012210164
&new_castfunc);
1012310165

10166+
old_fkcoll = attr->attcollation;
10167+
new_fkcoll = fkcoll;
10168+
1012410169
/*
1012510170
* Upon a change to the cast from the FK column to its pfeqop
1012610171
* operand, revalidate the constraint. For this evaluation, a
@@ -10144,9 +10189,10 @@ ATAddForeignKeyConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
1014410189
* turn conform to the domain. Consequently, we need not treat
1014510190
* domains specially here.
1014610191
*
10147-
* Since we require that all collations share the same notion of
10148-
* equality (which they do, because texteq reduces to bitwise
10149-
* equality), we don't compare collation here.
10192+
* If the collation changes, revalidation is required, unless both
10193+
* collations are deterministic, because those share the same
10194+
* notion of equality (because texteq reduces to bitwise
10195+
* equality).
1015010196
*
1015110197
* We need not directly consider the PK type. It's necessarily
1015210198
* binary coercible to the opcintype of the unique index column,
@@ -10156,7 +10202,9 @@ ATAddForeignKeyConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
1015610202
old_check_ok = (new_pathtype == old_pathtype &&
1015710203
new_castfunc == old_castfunc &&
1015810204
(!IsPolymorphicType(pfeqop_right) ||
10159-
new_fktype == old_fktype));
10205+
new_fktype == old_fktype) &&
10206+
(new_fkcoll == old_fkcoll ||
10207+
(get_collation_isdeterministic(old_fkcoll) && get_collation_isdeterministic(new_fkcoll))));
1016010208
}
1016110209

1016210210
pfeqoperators[i] = pfeqop;
@@ -12092,7 +12140,8 @@ ATExecValidateConstraint(List **wqueue, Relation rel, char *constrName,
1209212140
/*
1209312141
* transformColumnNameList - transform list of column names
1209412142
*
12095-
* Lookup each name and return its attnum and, optionally, type OID
12143+
* Lookup each name and return its attnum and, optionally, type and collation
12144+
* OIDs
1209612145
*
1209712146
* Note: the name of this function suggests that it's general-purpose,
1209812147
* but actually it's only used to look up names appearing in foreign-key
@@ -12101,7 +12150,7 @@ ATExecValidateConstraint(List **wqueue, Relation rel, char *constrName,
1210112150
*/
1210212151
static int
1210312152
transformColumnNameList(Oid relId, List *colList,
12104-
int16 *attnums, Oid *atttypids)
12153+
int16 *attnums, Oid *atttypids, Oid *attcollids)
1210512154
{
1210612155
ListCell *l;
1210712156
intattnum;
@@ -12132,6 +12181,8 @@ transformColumnNameList(Oid relId, List *colList,
1213212181
attnums[attnum] = attform->attnum;
1213312182
if (atttypids != NULL)
1213412183
atttypids[attnum] = attform->atttypid;
12184+
if (attcollids != NULL)
12185+
attcollids[attnum] = attform->attcollation;
1213512186
ReleaseSysCache(atttuple);
1213612187
attnum++;
1213712188
}
@@ -12142,7 +12193,7 @@ transformColumnNameList(Oid relId, List *colList,
1214212193
/*
1214312194
* transformFkeyGetPrimaryKey -
1214412195
*
12145-
*Look up the names, attnums, andtypes of the primary key attributes
12196+
*Look up the names, attnums,types,andcollations of the primary key attributes
1214612197
*for the pkrel. Also return the index OID and index opclasses of the
1214712198
*index supporting the primary key. Also return whether the index has
1214812199
*WITHOUT OVERLAPS.
@@ -12155,7 +12206,7 @@ transformColumnNameList(Oid relId, List *colList,
1215512206
static int
1215612207
transformFkeyGetPrimaryKey(Relation pkrel, Oid *indexOid,
1215712208
List **attnamelist,
12158-
int16 *attnums, Oid *atttypids,
12209+
int16 *attnums, Oid *atttypids, Oid *attcollids,
1215912210
Oid *opclasses, bool *pk_has_without_overlaps)
1216012211
{
1216112212
List *indexoidlist;
@@ -12229,6 +12280,7 @@ transformFkeyGetPrimaryKey(Relation pkrel, Oid *indexOid,
1222912280

1223012281
attnums[i] = pkattno;
1223112282
atttypids[i] = attnumTypeId(pkrel, pkattno);
12283+
attcollids[i] = attnumCollationId(pkrel, pkattno);
1223212284
opclasses[i] = indclass->values[i];
1223312285
*attnamelist = lappend(*attnamelist,
1223412286
makeString(pstrdup(NameStr(*attnumAttName(pkrel, pkattno)))));

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

Lines changed: 19 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ static void ri_BuildQueryKey(RI_QueryKey *key,
207207
int32constr_queryno);
208208
staticboolri_KeysEqual(Relationrel,TupleTableSlot*oldslot,TupleTableSlot*newslot,
209209
constRI_ConstraintInfo*riinfo,boolrel_is_pk);
210-
staticboolri_CompareWithCast(Oideq_opr,Oidtypeid,
210+
staticboolri_CompareWithCast(Oideq_opr,Oidtypeid,Oidcollid,
211211
Datumlhs,Datumrhs);
212212

213213
staticvoidri_InitHashTables(void);
@@ -776,8 +776,6 @@ ri_restrict(TriggerData *trigdata, bool is_no_action)
776776
{
777777
Oidpk_type=RIAttType(pk_rel,riinfo->pk_attnums[i]);
778778
Oidfk_type=RIAttType(fk_rel,riinfo->fk_attnums[i]);
779-
Oidpk_coll=RIAttCollation(pk_rel,riinfo->pk_attnums[i]);
780-
Oidfk_coll=RIAttCollation(fk_rel,riinfo->fk_attnums[i]);
781779

782780
quoteOneName(attname,
783781
RIAttName(fk_rel,riinfo->fk_attnums[i]));
@@ -786,8 +784,6 @@ ri_restrict(TriggerData *trigdata, bool is_no_action)
786784
paramname,pk_type,
787785
riinfo->pf_eq_oprs[i],
788786
attname,fk_type);
789-
if (pk_coll!=fk_coll&& !get_collation_isdeterministic(pk_coll))
790-
ri_GenerateQualCollation(&querybuf,pk_coll);
791787
querysep="AND";
792788
queryoids[i]=pk_type;
793789
}
@@ -881,8 +877,6 @@ RI_FKey_cascade_del(PG_FUNCTION_ARGS)
881877
{
882878
Oidpk_type=RIAttType(pk_rel,riinfo->pk_attnums[i]);
883879
Oidfk_type=RIAttType(fk_rel,riinfo->fk_attnums[i]);
884-
Oidpk_coll=RIAttCollation(pk_rel,riinfo->pk_attnums[i]);
885-
Oidfk_coll=RIAttCollation(fk_rel,riinfo->fk_attnums[i]);
886880

887881
quoteOneName(attname,
888882
RIAttName(fk_rel,riinfo->fk_attnums[i]));
@@ -891,8 +885,6 @@ RI_FKey_cascade_del(PG_FUNCTION_ARGS)
891885
paramname,pk_type,
892886
riinfo->pf_eq_oprs[i],
893887
attname,fk_type);
894-
if (pk_coll!=fk_coll&& !get_collation_isdeterministic(pk_coll))
895-
ri_GenerateQualCollation(&querybuf,pk_coll);
896888
querysep="AND";
897889
queryoids[i]=pk_type;
898890
}
@@ -996,8 +988,6 @@ RI_FKey_cascade_upd(PG_FUNCTION_ARGS)
996988
{
997989
Oidpk_type=RIAttType(pk_rel,riinfo->pk_attnums[i]);
998990
Oidfk_type=RIAttType(fk_rel,riinfo->fk_attnums[i]);
999-
Oidpk_coll=RIAttCollation(pk_rel,riinfo->pk_attnums[i]);
1000-
Oidfk_coll=RIAttCollation(fk_rel,riinfo->fk_attnums[i]);
1001991

1002992
quoteOneName(attname,
1003993
RIAttName(fk_rel,riinfo->fk_attnums[i]));
@@ -1009,8 +999,6 @@ RI_FKey_cascade_upd(PG_FUNCTION_ARGS)
1009999
paramname,pk_type,
10101000
riinfo->pf_eq_oprs[i],
10111001
attname,fk_type);
1012-
if (pk_coll!=fk_coll&& !get_collation_isdeterministic(pk_coll))
1013-
ri_GenerateQualCollation(&querybuf,pk_coll);
10141002
querysep=",";
10151003
qualsep="AND";
10161004
queryoids[i]=pk_type;
@@ -1232,8 +1220,6 @@ ri_set(TriggerData *trigdata, bool is_set_null, int tgkind)
12321220
{
12331221
Oidpk_type=RIAttType(pk_rel,riinfo->pk_attnums[i]);
12341222
Oidfk_type=RIAttType(fk_rel,riinfo->fk_attnums[i]);
1235-
Oidpk_coll=RIAttCollation(pk_rel,riinfo->pk_attnums[i]);
1236-
Oidfk_coll=RIAttCollation(fk_rel,riinfo->fk_attnums[i]);
12371223

12381224
quoteOneName(attname,
12391225
RIAttName(fk_rel,riinfo->fk_attnums[i]));
@@ -1243,8 +1229,6 @@ ri_set(TriggerData *trigdata, bool is_set_null, int tgkind)
12431229
paramname,pk_type,
12441230
riinfo->pf_eq_oprs[i],
12451231
attname,fk_type);
1246-
if (pk_coll!=fk_coll&& !get_collation_isdeterministic(pk_coll))
1247-
ri_GenerateQualCollation(&querybuf,pk_coll);
12481232
qualsep="AND";
12491233
queryoids[i]=pk_type;
12501234
}
@@ -1998,19 +1982,17 @@ ri_GenerateQual(StringInfo buf,
19981982
/*
19991983
* ri_GenerateQualCollation --- add a COLLATE spec to a WHERE clause
20001984
*
2001-
* At present, we intentionally do not use this function for RI queries that
2002-
* compare a variable to a $n parameter. Since parameter symbols always have
2003-
* default collation, the effect will be to use the variable's collation.
2004-
* Now that is only strictly correct when testing the referenced column, since
2005-
* the SQL standard specifies that RI comparisons should use the referenced
2006-
* column's collation. However, so long as all collations have the same
2007-
* notion of equality (which they do, because texteq reduces to bitwise
2008-
* equality), there's no visible semantic impact from using the referencing
2009-
* column's collation when testing it, and this is a good thing to do because
2010-
* it lets us use a normal index on the referencing column. However, we do
2011-
* have to use this function when directly comparing the referencing and
2012-
* referenced columns, if they are of different collations; else the parser
2013-
* will fail to resolve the collation to use.
1985+
* We only have to use this function when directly comparing the referencing
1986+
* and referenced columns, if they are of different collations; else the
1987+
* parser will fail to resolve the collation to use. We don't need to use
1988+
* this function for RI queries that compare a variable to a $n parameter.
1989+
* Since parameter symbols always have default collation, the effect will be
1990+
* to use the variable's collation.
1991+
*
1992+
* Note that we require that the collations of the referencing and the
1993+
* referenced column have the same notion of equality: Either they have to
1994+
* both be deterministic or else they both have to be the same. (See also
1995+
* ATAddForeignKeyConstraint().)
20141996
*/
20151997
staticvoid
20161998
ri_GenerateQualCollation(StringInfobuf,Oidcollation)
@@ -2952,7 +2934,7 @@ ri_KeysEqual(Relation rel, TupleTableSlot *oldslot, TupleTableSlot *newslot,
29522934
* operator. Changes that compare equal will still satisfy the
29532935
* constraint after the update.
29542936
*/
2955-
if (!ri_CompareWithCast(eq_opr,RIAttType(rel,attnums[i]),
2937+
if (!ri_CompareWithCast(eq_opr,RIAttType(rel,attnums[i]),RIAttCollation(rel,attnums[i]),
29562938
newvalue,oldvalue))
29572939
return false;
29582940
}
@@ -2968,11 +2950,12 @@ ri_KeysEqual(Relation rel, TupleTableSlot *oldslot, TupleTableSlot *newslot,
29682950
* Call the appropriate comparison operator for two values.
29692951
* Normally this is equality, but for the PERIOD part of foreign keys
29702952
* it is ContainedBy, so the order of lhs vs rhs is significant.
2953+
* See below for how the collation is applied.
29712954
*
29722955
* NB: we have already checked that neither value is null.
29732956
*/
29742957
staticbool
2975-
ri_CompareWithCast(Oideq_opr,Oidtypeid,
2958+
ri_CompareWithCast(Oideq_opr,Oidtypeid,Oidcollid,
29762959
Datumlhs,Datumrhs)
29772960
{
29782961
RI_CompareHashEntry*entry=ri_HashCompareOp(eq_opr,typeid);
@@ -2998,19 +2981,17 @@ ri_CompareWithCast(Oid eq_opr, Oid typeid,
29982981
* on the other side of a foreign-key constraint. Therefore, the
29992982
* comparison here would need to be done with the collation of the *other*
30002983
* table. For simplicity (e.g., we might not even have the other table
3001-
* open), we'lljustusethe default collation here, which could lead to
3002-
*some false negatives. All this would break if we ever allow
3003-
*database-wide collations to be nondeterministic.
2984+
* open), we'll useour own collation. This is fine because we require
2985+
*that both collations have the same notion of equality (either they are
2986+
*both deterministic or else they are both the same).
30042987
*
30052988
* With range/multirangetypes, the collation of the base type is stored as
30062989
* part of the rangetype (pg_range.rngcollation), and always used, so
30072990
* there is no danger of inconsistency even using a non-equals operator.
30082991
* But if we support arbitrary types with PERIOD, we should perhaps just
30092992
* always force a re-check.
30102993
*/
3011-
returnDatumGetBool(FunctionCall2Coll(&entry->eq_opr_finfo,
3012-
DEFAULT_COLLATION_OID,
3013-
lhs,rhs));
2994+
returnDatumGetBool(FunctionCall2Coll(&entry->eq_opr_finfo,collid,lhs,rhs));
30142995
}
30152996

30162997
/*

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp