From 247e7647f598d541775a77057df15fd32651566a Mon Sep 17 00:00:00 2001 From: Alexander Korotkov Date: Tue, 12 Nov 2024 01:44:20 +0200 Subject: [PATCH] Fix arrays comparison in CompareOpclassOptions() The current code calls array_eq() and does not provide FmgrInfo. This commit provides initialization of FmgrInfo and uses C collation as the safe option for text comparison because we don't know anything about the semantics of opclass options. Backpatch to 13, where opclass options were introduced. Reported-by: Nicolas Maus Discussion: https://postgr.es/m/18692-72ea398df3ec6712%40postgresql.org Backpatch-through: 13 --- contrib/pg_trgm/expected/pg_trgm.out | 3 +++ contrib/pg_trgm/sql/pg_trgm.sql | 4 ++++ src/backend/commands/indexcmds.c | 11 +++++++++-- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/contrib/pg_trgm/expected/pg_trgm.out b/contrib/pg_trgm/expected/pg_trgm.out index 20141ce7f3d..8b5dcf90d18 100644 --- a/contrib/pg_trgm/expected/pg_trgm.out +++ b/contrib/pg_trgm/expected/pg_trgm.out @@ -2372,6 +2372,9 @@ ERROR: value 2025 out of bounds for option "siglen" DETAIL: Valid values are between "1" and "2024". create index trgm_idx on test_trgm using gist (t gist_trgm_ops(siglen=2024)); set enable_seqscan=off; +-- check index compatibility handling when opclass option is specified +alter table test_trgm alter column t type varchar(768); +alter table test_trgm alter column t type text; select t,similarity(t,'qwertyu0988') as sml from test_trgm where t % 'qwertyu0988' order by sml desc, t; t | sml -------------+---------- diff --git a/contrib/pg_trgm/sql/pg_trgm.sql b/contrib/pg_trgm/sql/pg_trgm.sql index 6a9da24d5a7..340c9891899 100644 --- a/contrib/pg_trgm/sql/pg_trgm.sql +++ b/contrib/pg_trgm/sql/pg_trgm.sql @@ -52,6 +52,10 @@ create index trgm_idx on test_trgm using gist (t gist_trgm_ops(siglen=2025)); create index trgm_idx on test_trgm using gist (t gist_trgm_ops(siglen=2024)); set enable_seqscan=off; +-- check index compatibility handling when opclass option is specified +alter table test_trgm alter column t type varchar(768); +alter table test_trgm alter column t type text; + select t,similarity(t,'qwertyu0988') as sml from test_trgm where t % 'qwertyu0988' order by sml desc, t; select t,similarity(t,'gwertyu0988') as sml from test_trgm where t % 'gwertyu0988' order by sml desc, t; select t,similarity(t,'gwertyu1988') as sml from test_trgm where t % 'gwertyu1988' order by sml desc, t; diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c index 99c536891a7..c2904cdb1a7 100644 --- a/src/backend/commands/indexcmds.c +++ b/src/backend/commands/indexcmds.c @@ -26,6 +26,7 @@ #include "catalog/index.h" #include "catalog/indexing.h" #include "catalog/pg_am.h" +#include "catalog/pg_collation.h" #include "catalog/pg_constraint.h" #include "catalog/pg_inherits.h" #include "catalog/pg_opclass.h" @@ -349,10 +350,12 @@ static bool CompareOpclassOptions(Datum *opts1, Datum *opts2, int natts) { int i; + FmgrInfo fm; if (!opts1 && !opts2) return true; + fmgr_info(F_ARRAY_EQ, &fm); for (i = 0; i < natts; i++) { Datum opt1 = opts1 ? opts1[i] : (Datum) 0; @@ -368,8 +371,12 @@ CompareOpclassOptions(Datum *opts1, Datum *opts2, int natts) else if (opt2 == (Datum) 0) return false; - /* Compare non-NULL text[] datums. */ - if (!DatumGetBool(DirectFunctionCall2(array_eq, opt1, opt2))) + /* + * Compare non-NULL text[] datums. Use C collation to enforce binary + * equivalence of texts, because we don't know anything about the + * semantics of opclass options. + */ + if (!DatumGetBool(FunctionCall2Coll(&fm, C_COLLATION_OID, opt1, opt2))) return false; }