From 1904912824a577cb87beea5d271285e1f045eae8 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. --- doc/src/sgml/ref/alter_index.sgml | 13 +++++++++++++ src/backend/commands/tablecmds.c | 14 ++++++++++++-- src/backend/parser/gram.y | 9 +++++++++ src/bin/psql/tab-complete.c | 26 +++++++++++++++++++++++++- src/include/nodes/parsenodes.h | 5 ++++- 5 files changed, 63 insertions(+), 4 deletions(-) diff --git a/doc/src/sgml/ref/alter_index.sgml b/doc/src/sgml/ref/alter_index.sgml index 6d34dbb74e..db5ade29d1 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 EXTENSION + + + 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 67d1fd5732..5a7da64f95 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -92,6 +92,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" @@ -3973,7 +3974,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")))); @@ -16767,7 +16768,16 @@ ATExecDependsOnCollationVersion(Relation rel, List *coll, char *version) forced_dependency.oid = InvalidOid; else forced_dependency.oid = get_collation_oid(coll, false); - strncpy(NameStr(forced_dependency.version), version, sizeof(NameData)); + + if (version) + strncpy(NameStr(forced_dependency.version), version, sizeof(NameData)); + else + { + /* Retrieve the current version for the CURRENT VERSION case. */ + Assert(OidIsValid(forced_dependency.oid)); + get_collation_version_for_oid(forced_dependency.oid, + &forced_dependency.version); + } object.classId = RelationRelationId; object.objectId = rel->rd_id; diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 4f53737e66..4d09f7bdac 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -2567,6 +2567,15 @@ alter_table_cmd: n->version = ""; $$ = (Node *)n; } + /* ALTER INDEX DEPENDS ON ANY COLLATION UNKNOWN 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 df26826993..e869f3fc47 100644 --- a/src/bin/psql/tab-complete.c +++ b/src/bin/psql/tab-complete.c @@ -44,6 +44,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" @@ -792,6 +793,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'" @@ -1643,7 +1658,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")) @@ -1689,6 +1704,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 4e559fea09..c16d633ed8 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -1844,7 +1844,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 */ -- 2.20.1