aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/init/postinit.c
diff options
context:
space:
mode:
authorPeter Eisentraut <peter@eisentraut.org>2022-02-14 08:09:04 +0100
committerPeter Eisentraut <peter@eisentraut.org>2022-02-14 08:27:26 +0100
commit37851a8b83d3d57ca48736093b10aa5f3bc0c177 (patch)
tree5da6f597063d9579937e80aaf66d92c50ef73029 /src/backend/utils/init/postinit.c
parent9898c5e03c40c133a9a01d8b2b36cb7c990b30d5 (diff)
downloadpostgresql-37851a8b83d3d57ca48736093b10aa5f3bc0c177.tar.gz
postgresql-37851a8b83d3d57ca48736093b10aa5f3bc0c177.zip
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 <rjuju123@gmail.com> Discussion: https://www.postgresql.org/message-id/flat/f0ff3190-29a3-5b39-a179-fa32eee57db6%40enterprisedb.com
Diffstat (limited to 'src/backend/utils/init/postinit.c')
-rw-r--r--src/backend/utils/init/postinit.c34
1 files changed, 34 insertions, 0 deletions
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);