From 37851a8b83d3d57ca48736093b10aa5f3bc0c177 Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Mon, 14 Feb 2022 08:09:04 +0100 Subject: Database-level collation version tracking This adds to database objects the same version tracking that collation objects have. There is a new pg_database column datcollversion that stores the version, a new function pg_database_collation_actual_version() to get the version from the operating system, and a new subcommand ALTER DATABASE ... REFRESH COLLATION VERSION. This was not originally added together with pg_collation.collversion, since originally version tracking was only supported for ICU, and ICU on a database-level is not currently supported. But we now have version tracking for glibc (since PG13), FreeBSD (since PG14), and Windows (since PG13), so this is useful to have now. Reviewed-by: Julien Rouhaud Discussion: https://www.postgresql.org/message-id/flat/f0ff3190-29a3-5b39-a179-fa32eee57db6%40enterprisedb.com --- src/backend/utils/init/postinit.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'src/backend/utils/init/postinit.c') diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c index ca53912f151..02207a5b6f8 100644 --- a/src/backend/utils/init/postinit.c +++ b/src/backend/utils/init/postinit.c @@ -32,6 +32,7 @@ #include "catalog/catalog.h" #include "catalog/namespace.h" #include "catalog/pg_authid.h" +#include "catalog/pg_collation.h" #include "catalog/pg_database.h" #include "catalog/pg_db_role_setting.h" #include "catalog/pg_tablespace.h" @@ -418,6 +419,39 @@ CheckMyDatabase(const char *name, bool am_superuser, bool override_allow_connect " which is not recognized by setlocale().", ctype), errhint("Recreate the database with another locale or install the missing locale."))); + /* + * Check collation version. See similar code in + * pg_newlocale_from_collation(). Note that here we warn instead of error + * in any case, so that we don't prevent connecting. + */ + datum = SysCacheGetAttr(DATABASEOID, tup, Anum_pg_database_datcollversion, + &isnull); + if (!isnull) + { + char *actual_versionstr; + char *collversionstr; + + collversionstr = TextDatumGetCString(datum); + + actual_versionstr = get_collation_actual_version(COLLPROVIDER_LIBC, collate); + if (!actual_versionstr) + ereport(WARNING, + (errmsg("database \"%s\" has no actual collation version, but a version was recorded", + name))); + + if (strcmp(actual_versionstr, collversionstr) != 0) + ereport(WARNING, + (errmsg("database \"%s\" has a collation version mismatch", + name), + errdetail("The database was created using collation version %s, " + "but the operating system provides version %s.", + collversionstr, actual_versionstr), + errhint("Rebuild all objects in this database that use the default collation and run " + "ALTER DATABASE %s REFRESH COLLATION VERSION, " + "or build PostgreSQL with the right library version.", + quote_identifier(name)))); + } + /* Make the locale settings visible as GUC variables, too */ SetConfigOption("lc_collate", collate, PGC_INTERNAL, PGC_S_OVERRIDE); SetConfigOption("lc_ctype", ctype, PGC_INTERNAL, PGC_S_OVERRIDE); -- cgit v1.2.3