From 77a5576306b7c35800dd3fd1c42ddf98ee1e60ee Mon Sep 17 00:00:00 2001 From: Julien Rouhaud Date: Wed, 11 Dec 2019 13:54:32 +0100 Subject: [PATCH 6/6] Add a new ALTER INDEX name DEPENDS ON COLLATION name CURRENT VERSION This command allows privileged users to specifify that the currently installed collation library version, for a specific collation, is binary compatible with the one that was installed when the specified index was built for the last time. Author: Julien Rouhaud Reviewed-by: Discussion: https://postgr.es/m/CAEepm%3D0uEQCpfq_%2BLYFBdArCe4Ot98t1aR4eYiYTe%3DyavQygiQ%40mail.gmail.com --- doc/src/sgml/ref/alter_index.sgml | 13 ++ src/backend/commands/tablecmds.c | 20 ++- src/backend/parser/gram.y | 9 ++ src/bin/psql/tab-complete.c | 26 +++- src/include/nodes/parsenodes.h | 5 +- .../regress/expected/collate.icu.utf8.out | 147 ++++++++++-------- src/test/regress/sql/collate.icu.utf8.sql | 47 +++--- 7 files changed, 175 insertions(+), 92 deletions(-) diff --git a/doc/src/sgml/ref/alter_index.sgml b/doc/src/sgml/ref/alter_index.sgml index 6d34dbb74e..f4a4333ab1 100644 --- a/doc/src/sgml/ref/alter_index.sgml +++ b/doc/src/sgml/ref/alter_index.sgml @@ -25,6 +25,7 @@ ALTER INDEX [ IF EXISTS ] name RENA ALTER INDEX [ IF EXISTS ] name SET TABLESPACE tablespace_name ALTER INDEX name ATTACH PARTITION index_name ALTER INDEX name DEPENDS ON EXTENSION extension_name +ALTER INDEX name DEPENDS ON COLLATION collation_name CURRENT VERSION ALTER INDEX [ IF EXISTS ] name SET ( storage_parameter = value [, ... ] ) ALTER INDEX [ IF EXISTS ] name RESET ( storage_parameter [, ... ] ) ALTER INDEX [ IF EXISTS ] name ALTER [ COLUMN ] column_number @@ -109,6 +110,18 @@ ALTER INDEX ALL IN TABLESPACE name + + DEPENDS ON COLLATION + + + This form update the index existing dependency on a specific collation, + to specificy the the currently installed collation version is compatible + with the version used the last time the index was built. Be aware that + an incorrect use of this form can hide a corruption on the index. + + + + SET ( storage_parameter = value [, ... ] ) diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index b3cf5641fd..31ab4f5ad4 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -93,6 +93,7 @@ #include "utils/lsyscache.h" #include "utils/memutils.h" #include "utils/partcache.h" +#include "utils/pg_locale.h" #include "utils/relcache.h" #include "utils/ruleutils.h" #include "utils/snapmgr.h" @@ -4054,7 +4055,7 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd, break; case AT_DependsOnCollationVersion: /* DEPENDS ON COLLATION ... * [UNKNOWN VERSION | VERSION ...] */ - if (!IsBinaryUpgrade) + if (!IsBinaryUpgrade && cmd->version) ereport(ERROR, (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM), (errmsg("command can only be called when server is in binary upgrade mode")))); @@ -17319,8 +17320,9 @@ index_force_collation_version(const ObjectAddress *otherObject, /* Execute an ALTER INDEX ... ALTER COLLATION DEPENDS ON ... * - * A version has to be provided. If the caller wants to notify that the - * collation version to depend on is unknown, an empty string is passed. + * If the caller wants to notify that the collation version to depend on is + * unknown, an empty string is passed. If the collation's current version has + * to be used, then NULL is passed. */ static void ATExecDependsOnCollationVersion(Relation rel, List *coll, char *version) @@ -17328,14 +17330,20 @@ ATExecDependsOnCollationVersion(Relation rel, List *coll, char *version) ObjectAddress object; NewCollationVersionDependency forced_dependency; - Assert(version); - if (coll == NIL) forced_dependency.oid = InvalidOid; else forced_dependency.oid = get_collation_oid(coll, false); - forced_dependency.version = version; + if (version) + forced_dependency.version = version; + else + { + /* Retrieve the current version for the CURRENT VERSION case. */ + Assert(OidIsValid(forced_dependency.oid)); + forced_dependency.version = + get_collation_version_for_oid(forced_dependency.oid); + } object.classId = RelationRelationId; object.objectId = rel->rd_id; diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 1437123540..cb8c4f6b05 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -2596,6 +2596,15 @@ alter_table_cmd: n->version = ""; $$ = (Node *)n; } + /* ALTER INDEX DEPENDS ON COLLATION ... CURRENT VERSION */ + | DEPENDS ON COLLATION any_name CURRENT_P VERSION_P + { + AlterTableCmd *n = makeNode(AlterTableCmd); + n->subtype = AT_DependsOnCollationVersion; + n->object = $4; + n->version = NULL; + $$ = (Node *)n; + } | alter_generic_options { AlterTableCmd *n = makeNode(AlterTableCmd); diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c index dc03fbde13..e1b56b8fed 100644 --- a/src/bin/psql/tab-complete.c +++ b/src/bin/psql/tab-complete.c @@ -45,6 +45,7 @@ #include "catalog/pg_am_d.h" #include "catalog/pg_class_d.h" +#include "catalog/pg_collation_d.h" #include "common.h" #include "libpq-fe.h" #include "pqexpbuffer.h" @@ -807,6 +808,20 @@ static const SchemaQuery Query_for_list_of_statistics = { " (SELECT tgrelid FROM pg_catalog.pg_trigger "\ " WHERE pg_catalog.quote_ident(tgname)='%s')" +/* the silly-looking length condition is just to eat up the current word */ +#define Query_for_list_of_colls_for_one_index \ +" SELECT DISTINCT pg_catalog.quote_ident(coll.collname) " \ +" FROM pg_catalog.pg_depend d, pg_catalog.pg_collation coll, " \ +" pg_catalog.pg_class c" \ +" WHERE (%d = pg_catalog.length('%s'))" \ +" AND d.refclassid = " CppAsString2(CollationRelationId) \ +" AND d.refobjid = coll.oid " \ +" AND d.classid = " CppAsString2(RelationRelationId) \ +" AND d.objid = c.oid " \ +" AND c.relkind = " CppAsString2(RELKIND_INDEX) \ +" AND pg_catalog.pg_table_is_visible(c.oid) " \ +" AND c.relname = '%s'" + #define Query_for_list_of_ts_configurations \ "SELECT pg_catalog.quote_ident(cfgname) FROM pg_catalog.pg_ts_config "\ " WHERE substring(pg_catalog.quote_ident(cfgname),1,%d)='%s'" @@ -1697,7 +1712,7 @@ psql_completion(const char *text, int start, int end) /* ALTER INDEX */ else if (Matches("ALTER", "INDEX", MatchAny)) COMPLETE_WITH("ALTER COLUMN", "OWNER TO", "RENAME TO", "SET", - "RESET", "ATTACH PARTITION"); + "RESET", "ATTACH PARTITION", "DEPENDS ON COLLATION"); else if (Matches("ALTER", "INDEX", MatchAny, "ATTACH")) COMPLETE_WITH("PARTITION"); else if (Matches("ALTER", "INDEX", MatchAny, "ATTACH", "PARTITION")) @@ -1743,6 +1758,15 @@ psql_completion(const char *text, int start, int end) "buffering =", /* GiST */ "pages_per_range =", "autosummarize =" /* BRIN */ ); + /* ALTER INDEX DEPENDS ON COLLATION */ + else if (Matches("ALTER", "INDEX", MatchAny, "DEPENDS", "ON", "COLLATION")) + { + completion_info_charp = prev4_wd; + COMPLETE_WITH_QUERY(Query_for_list_of_colls_for_one_index); + } + /* ALTER INDEX DEPENDS ON COLLATION */ + else if (Matches("ALTER", "INDEX", MatchAny, "DEPENDS", "ON", "COLLATION", MatchAny)) + COMPLETE_WITH("CURRENT VERSION"); /* ALTER LANGUAGE */ else if (Matches("ALTER", "LANGUAGE", MatchAny)) diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index b36824ddfe..a418d43352 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -1864,7 +1864,10 @@ typedef struct AlterTableCmd /* one subcommand of an ALTER TABLE */ List *object; /* collation to act on if it's a collation */ int16 num; /* attribute number for columns referenced by * number */ - char *version; /* version reference for collation dependency */ + char *version; /* version reference for collation dependency. + * An empty string is used to represent an + * unknown version, and a NULL pointer is used + * to represent the current version */ RoleSpec *newowner; Node *def; /* definition of new column, index, * constraint, or parent table */ diff --git a/src/test/regress/expected/collate.icu.utf8.out b/src/test/regress/expected/collate.icu.utf8.out index 6a218d7954..b35c200b24 100644 --- a/src/test/regress/expected/collate.icu.utf8.out +++ b/src/test/regress/expected/collate.icu.utf8.out @@ -1923,26 +1923,26 @@ CREATE TABLE collate_test ( myrange_en_fr_ga myrange_en_fr_ga, mood mood ); -CREATE INDEX idx01_t_en_fr__d_es ON collate_test (t_en_fr, d_es); -CREATE INDEX idx02_d_en_fr ON collate_test (d_en_fr); -CREATE INDEX idx03_t_en_fr_ga ON collate_test (t_en_fr_ga); -CREATE INDEX idx04_d_en_fr_ga ON collate_test (d_en_fr_ga); -CREATE INDEX idx05_d_en_fr_ga_arr ON collate_test (d_en_fr_ga_arr); -CREATE INDEX idx06_d_en_fr_ga ON collate_test(id) WHERE (d_en_fr_ga).en_fr.fr = 'foo'; -CREATE INDEX idx07_d_en_fr_ga ON collate_test(id) WHERE (d_en_fr_ga).ga = 'foo'; -CREATE INDEX idx08_d_en_fr_ga ON collate_test(id) WHERE (t_en_fr_ga) = ('foo', 'bar', 'baz'); -CREATE INDEX idx09_d_en_fr_ga ON collate_test(id) WHERE (d_en_fr_ga) = ('foo', 'bar', 'baz'); -CREATE INDEX idx10_d_en_fr_ga_es ON collate_test(id) WHERE (d_en_fr_ga) = ('foo', 'bar', 'baz' COLLATE "es-x-icu"); -CREATE INDEX idx11_d_es ON collate_test(id) WHERE (d_es) = ('foo'); -CREATE INDEX idx12_custom ON collate_test(id) WHERE ('foo', 'bar')::d_custom = ('foo', 'bar' collate custom)::d_custom; -CREATE INDEX idx13_custom ON collate_test(id) WHERE ('foo' collate custom, 'bar')::d_custom = ('foo', 'bar')::d_custom; -CREATE INDEX idx14_myrange ON collate_test(myrange); -CREATE INDEX idx15_myrange_en_fr_ga ON collate_test USING gist (myrange_en_fr_ga); -CREATE INDEX idx16_mood ON collate_test(id) WHERE mood > 'ok' collate "fr-x-icu"; +CREATE INDEX icuidx01_t_en_fr__d_es ON collate_test (t_en_fr, d_es); +CREATE INDEX icuidx02_d_en_fr ON collate_test (d_en_fr); +CREATE INDEX icuidx03_t_en_fr_ga ON collate_test (t_en_fr_ga); +CREATE INDEX icuidx04_d_en_fr_ga ON collate_test (d_en_fr_ga); +CREATE INDEX icuidx05_d_en_fr_ga_arr ON collate_test (d_en_fr_ga_arr); +CREATE INDEX icuidx06_d_en_fr_ga ON collate_test(id) WHERE (d_en_fr_ga).en_fr.fr = 'foo'; +CREATE INDEX icuidx07_d_en_fr_ga ON collate_test(id) WHERE (d_en_fr_ga).ga = 'foo'; +CREATE INDEX icuidx08_d_en_fr_ga ON collate_test(id) WHERE (t_en_fr_ga) = ('foo', 'bar', 'baz'); +CREATE INDEX icuidx09_d_en_fr_ga ON collate_test(id) WHERE (d_en_fr_ga) = ('foo', 'bar', 'baz'); +CREATE INDEX icuidx10_d_en_fr_ga_es ON collate_test(id) WHERE (d_en_fr_ga) = ('foo', 'bar', 'baz' COLLATE "es-x-icu"); +CREATE INDEX icuidx11_d_es ON collate_test(id) WHERE (d_es) = ('foo'); +CREATE INDEX icuidx12_custom ON collate_test(id) WHERE ('foo', 'bar')::d_custom = ('foo', 'bar' collate custom)::d_custom; +CREATE INDEX icuidx13_custom ON collate_test(id) WHERE ('foo' collate custom, 'bar')::d_custom = ('foo', 'bar')::d_custom; +CREATE INDEX icuidx14_myrange ON collate_test(myrange); +CREATE INDEX icuidx15_myrange_en_fr_ga ON collate_test USING gist (myrange_en_fr_ga); +CREATE INDEX icuidx16_mood ON collate_test(id) WHERE mood > 'ok' collate "fr-x-icu"; CREATE TABLE collate_part(id integer, val text COLLATE "en-x-icu") PARTITION BY range(id); CREATE TABLE collate_part_0 PARTITION OF collate_part FOR VALUES FROM (0) TO (1); CREATE TABLE collate_part_1 PARTITION OF collate_part FOR VALUES FROM (1) TO (1000000); -CREATE INDEX idx16_part ON collate_part_1 (val); +CREATE INDEX icuidx17_part ON collate_part_1 (val); -- version of default (and libc) collation is only tracked on glibc systems SELECT objid::regclass, refobjid::regcollation, CASE @@ -1953,59 +1953,59 @@ FROM pg_depend d LEFT JOIN pg_class c ON c.oid = d.objid WHERE refclassid = 'pg_collation'::regclass AND coalesce(relkind, 'i') = 'i' -AND relname LIKE 'idx%' +AND relname LIKE 'icuidx%' ORDER BY 1, 2; - objid | refobjid | version -------------------------+------------+-------------- - idx01_t_en_fr__d_es | "en-x-icu" | some version - idx01_t_en_fr__d_es | "es-x-icu" | some version - idx01_t_en_fr__d_es | "fr-x-icu" | some version - idx02_d_en_fr | "en-x-icu" | some version - idx02_d_en_fr | "fr-x-icu" | some version - idx03_t_en_fr_ga | "en-x-icu" | some version - idx03_t_en_fr_ga | "fr-x-icu" | some version - idx03_t_en_fr_ga | "ga-x-icu" | some version - idx04_d_en_fr_ga | "en-x-icu" | some version - idx04_d_en_fr_ga | "fr-x-icu" | some version - idx04_d_en_fr_ga | "ga-x-icu" | some version - idx05_d_en_fr_ga_arr | "en-x-icu" | some version - idx05_d_en_fr_ga_arr | "fr-x-icu" | some version - idx05_d_en_fr_ga_arr | "ga-x-icu" | some version - idx06_d_en_fr_ga | "default" | no version - idx06_d_en_fr_ga | "en-x-icu" | some version - idx06_d_en_fr_ga | "fr-x-icu" | some version - idx06_d_en_fr_ga | "ga-x-icu" | some version - idx07_d_en_fr_ga | "default" | no version - idx07_d_en_fr_ga | "en-x-icu" | some version - idx07_d_en_fr_ga | "fr-x-icu" | some version - idx07_d_en_fr_ga | "ga-x-icu" | some version - idx08_d_en_fr_ga | "en-x-icu" | some version - idx08_d_en_fr_ga | "fr-x-icu" | some version - idx08_d_en_fr_ga | "ga-x-icu" | some version - idx09_d_en_fr_ga | "en-x-icu" | some version - idx09_d_en_fr_ga | "fr-x-icu" | some version - idx09_d_en_fr_ga | "ga-x-icu" | some version - idx10_d_en_fr_ga_es | "en-x-icu" | some version - idx10_d_en_fr_ga_es | "es-x-icu" | some version - idx10_d_en_fr_ga_es | "fr-x-icu" | some version - idx10_d_en_fr_ga_es | "ga-x-icu" | some version - idx11_d_es | "default" | no version - idx11_d_es | "es-x-icu" | some version - idx12_custom | "default" | no version - idx12_custom | custom | some version - idx13_custom | "default" | no version - idx13_custom | custom | some version - idx14_myrange | "default" | no version - idx15_myrange_en_fr_ga | "en-x-icu" | some version - idx15_myrange_en_fr_ga | "fr-x-icu" | some version - idx15_myrange_en_fr_ga | "ga-x-icu" | some version - idx16_mood | "fr-x-icu" | some version - idx16_part | "en-x-icu" | some version + objid | refobjid | version +---------------------------+------------+-------------- + icuidx01_t_en_fr__d_es | "en-x-icu" | some version + icuidx01_t_en_fr__d_es | "es-x-icu" | some version + icuidx01_t_en_fr__d_es | "fr-x-icu" | some version + icuidx02_d_en_fr | "en-x-icu" | some version + icuidx02_d_en_fr | "fr-x-icu" | some version + icuidx03_t_en_fr_ga | "en-x-icu" | some version + icuidx03_t_en_fr_ga | "fr-x-icu" | some version + icuidx03_t_en_fr_ga | "ga-x-icu" | some version + icuidx04_d_en_fr_ga | "en-x-icu" | some version + icuidx04_d_en_fr_ga | "fr-x-icu" | some version + icuidx04_d_en_fr_ga | "ga-x-icu" | some version + icuidx05_d_en_fr_ga_arr | "en-x-icu" | some version + icuidx05_d_en_fr_ga_arr | "fr-x-icu" | some version + icuidx05_d_en_fr_ga_arr | "ga-x-icu" | some version + icuidx06_d_en_fr_ga | "default" | no version + icuidx06_d_en_fr_ga | "en-x-icu" | some version + icuidx06_d_en_fr_ga | "fr-x-icu" | some version + icuidx06_d_en_fr_ga | "ga-x-icu" | some version + icuidx07_d_en_fr_ga | "default" | no version + icuidx07_d_en_fr_ga | "en-x-icu" | some version + icuidx07_d_en_fr_ga | "fr-x-icu" | some version + icuidx07_d_en_fr_ga | "ga-x-icu" | some version + icuidx08_d_en_fr_ga | "en-x-icu" | some version + icuidx08_d_en_fr_ga | "fr-x-icu" | some version + icuidx08_d_en_fr_ga | "ga-x-icu" | some version + icuidx09_d_en_fr_ga | "en-x-icu" | some version + icuidx09_d_en_fr_ga | "fr-x-icu" | some version + icuidx09_d_en_fr_ga | "ga-x-icu" | some version + icuidx10_d_en_fr_ga_es | "en-x-icu" | some version + icuidx10_d_en_fr_ga_es | "es-x-icu" | some version + icuidx10_d_en_fr_ga_es | "fr-x-icu" | some version + icuidx10_d_en_fr_ga_es | "ga-x-icu" | some version + icuidx11_d_es | "default" | no version + icuidx11_d_es | "es-x-icu" | some version + icuidx12_custom | "default" | no version + icuidx12_custom | custom | some version + icuidx13_custom | "default" | no version + icuidx13_custom | custom | some version + icuidx14_myrange | "default" | no version + icuidx15_myrange_en_fr_ga | "en-x-icu" | some version + icuidx15_myrange_en_fr_ga | "fr-x-icu" | some version + icuidx15_myrange_en_fr_ga | "ga-x-icu" | some version + icuidx16_mood | "fr-x-icu" | some version + icuidx17_part | "en-x-icu" | some version (44 rows) UPDATE pg_depend SET refobjversion = 'not a version' WHERE refclassid = 'pg_collation'::regclass -AND objid::regclass::text LIKE 'idx%' +AND objid::regclass::text LIKE 'icuidx%' AND refobjversion IS NOT NULL; REINDEX TABLE collate_test; REINDEX TABLE collate_part_0; @@ -2015,6 +2015,23 @@ SELECT objid::regclass FROM pg_depend WHERE refobjversion = 'not a version'; ------- (0 rows) +-- Test ALTER INDEX name DEPENDS ON COLLATION name CURRENT VERSION +UPDATE pg_depend SET refobjversion = 'not a version' +WHERE refclassid = 'pg_collation'::regclass +AND objid::regclass::text = 'icuidx17_part' +AND refobjversion IS NOT NULL; +SELECT objid::regclass FROM pg_depend WHERE refobjversion = 'not a version'; + objid +--------------- + icuidx17_part +(1 row) + +ALTER INDEX icuidx17_part DEPENDS ON COLLATION "en-x-icu" CURRENT VERSION; +SELECT objid::regclass FROM pg_depend WHERE refobjversion = 'not a version'; + objid +------- +(0 rows) + -- cleanup RESET search_path; SET client_min_messages TO warning; diff --git a/src/test/regress/sql/collate.icu.utf8.sql b/src/test/regress/sql/collate.icu.utf8.sql index e870594b5b..885470c7ba 100644 --- a/src/test/regress/sql/collate.icu.utf8.sql +++ b/src/test/regress/sql/collate.icu.utf8.sql @@ -747,27 +747,27 @@ CREATE TABLE collate_test ( mood mood ); -CREATE INDEX idx01_t_en_fr__d_es ON collate_test (t_en_fr, d_es); -CREATE INDEX idx02_d_en_fr ON collate_test (d_en_fr); -CREATE INDEX idx03_t_en_fr_ga ON collate_test (t_en_fr_ga); -CREATE INDEX idx04_d_en_fr_ga ON collate_test (d_en_fr_ga); -CREATE INDEX idx05_d_en_fr_ga_arr ON collate_test (d_en_fr_ga_arr); -CREATE INDEX idx06_d_en_fr_ga ON collate_test(id) WHERE (d_en_fr_ga).en_fr.fr = 'foo'; -CREATE INDEX idx07_d_en_fr_ga ON collate_test(id) WHERE (d_en_fr_ga).ga = 'foo'; -CREATE INDEX idx08_d_en_fr_ga ON collate_test(id) WHERE (t_en_fr_ga) = ('foo', 'bar', 'baz'); -CREATE INDEX idx09_d_en_fr_ga ON collate_test(id) WHERE (d_en_fr_ga) = ('foo', 'bar', 'baz'); -CREATE INDEX idx10_d_en_fr_ga_es ON collate_test(id) WHERE (d_en_fr_ga) = ('foo', 'bar', 'baz' COLLATE "es-x-icu"); -CREATE INDEX idx11_d_es ON collate_test(id) WHERE (d_es) = ('foo'); -CREATE INDEX idx12_custom ON collate_test(id) WHERE ('foo', 'bar')::d_custom = ('foo', 'bar' collate custom)::d_custom; -CREATE INDEX idx13_custom ON collate_test(id) WHERE ('foo' collate custom, 'bar')::d_custom = ('foo', 'bar')::d_custom; -CREATE INDEX idx14_myrange ON collate_test(myrange); -CREATE INDEX idx15_myrange_en_fr_ga ON collate_test USING gist (myrange_en_fr_ga); -CREATE INDEX idx16_mood ON collate_test(id) WHERE mood > 'ok' collate "fr-x-icu"; +CREATE INDEX icuidx01_t_en_fr__d_es ON collate_test (t_en_fr, d_es); +CREATE INDEX icuidx02_d_en_fr ON collate_test (d_en_fr); +CREATE INDEX icuidx03_t_en_fr_ga ON collate_test (t_en_fr_ga); +CREATE INDEX icuidx04_d_en_fr_ga ON collate_test (d_en_fr_ga); +CREATE INDEX icuidx05_d_en_fr_ga_arr ON collate_test (d_en_fr_ga_arr); +CREATE INDEX icuidx06_d_en_fr_ga ON collate_test(id) WHERE (d_en_fr_ga).en_fr.fr = 'foo'; +CREATE INDEX icuidx07_d_en_fr_ga ON collate_test(id) WHERE (d_en_fr_ga).ga = 'foo'; +CREATE INDEX icuidx08_d_en_fr_ga ON collate_test(id) WHERE (t_en_fr_ga) = ('foo', 'bar', 'baz'); +CREATE INDEX icuidx09_d_en_fr_ga ON collate_test(id) WHERE (d_en_fr_ga) = ('foo', 'bar', 'baz'); +CREATE INDEX icuidx10_d_en_fr_ga_es ON collate_test(id) WHERE (d_en_fr_ga) = ('foo', 'bar', 'baz' COLLATE "es-x-icu"); +CREATE INDEX icuidx11_d_es ON collate_test(id) WHERE (d_es) = ('foo'); +CREATE INDEX icuidx12_custom ON collate_test(id) WHERE ('foo', 'bar')::d_custom = ('foo', 'bar' collate custom)::d_custom; +CREATE INDEX icuidx13_custom ON collate_test(id) WHERE ('foo' collate custom, 'bar')::d_custom = ('foo', 'bar')::d_custom; +CREATE INDEX icuidx14_myrange ON collate_test(myrange); +CREATE INDEX icuidx15_myrange_en_fr_ga ON collate_test USING gist (myrange_en_fr_ga); +CREATE INDEX icuidx16_mood ON collate_test(id) WHERE mood > 'ok' collate "fr-x-icu"; CREATE TABLE collate_part(id integer, val text COLLATE "en-x-icu") PARTITION BY range(id); CREATE TABLE collate_part_0 PARTITION OF collate_part FOR VALUES FROM (0) TO (1); CREATE TABLE collate_part_1 PARTITION OF collate_part FOR VALUES FROM (1) TO (1000000); -CREATE INDEX idx16_part ON collate_part_1 (val); +CREATE INDEX icuidx17_part ON collate_part_1 (val); -- version of default (and libc) collation is only tracked on glibc systems SELECT objid::regclass, refobjid::regcollation, @@ -779,12 +779,12 @@ FROM pg_depend d LEFT JOIN pg_class c ON c.oid = d.objid WHERE refclassid = 'pg_collation'::regclass AND coalesce(relkind, 'i') = 'i' -AND relname LIKE 'idx%' +AND relname LIKE 'icuidx%' ORDER BY 1, 2; UPDATE pg_depend SET refobjversion = 'not a version' WHERE refclassid = 'pg_collation'::regclass -AND objid::regclass::text LIKE 'idx%' +AND objid::regclass::text LIKE 'icuidx%' AND refobjversion IS NOT NULL; REINDEX TABLE collate_test; @@ -793,6 +793,15 @@ REINDEX TABLE collate_part_1; SELECT objid::regclass FROM pg_depend WHERE refobjversion = 'not a version'; +-- Test ALTER INDEX name DEPENDS ON COLLATION name CURRENT VERSION +UPDATE pg_depend SET refobjversion = 'not a version' +WHERE refclassid = 'pg_collation'::regclass +AND objid::regclass::text = 'icuidx17_part' +AND refobjversion IS NOT NULL; +SELECT objid::regclass FROM pg_depend WHERE refobjversion = 'not a version'; +ALTER INDEX icuidx17_part DEPENDS ON COLLATION "en-x-icu" CURRENT VERSION; +SELECT objid::regclass FROM pg_depend WHERE refobjversion = 'not a version'; + -- cleanup RESET search_path; SET client_min_messages TO warning; -- 2.20.1