From d5ac14f9ccdda036358c9059d4a29836ebc0c440 Mon Sep 17 00:00:00 2001 From: Thomas Munro Date: Wed, 16 Oct 2019 16:51:40 +1300 Subject: [PATCH] Use libc version as a collation version on glibc systems. Using glibc's version string to detect potential collation definition changes is not 100% reliable, but it's better than nothing. Currently this affects only collations explicitly provided by "libc". More work will be needed to handle the default collation. Author: Thomas Munro, based on a suggestion from Christoph Berg Reviewed-by: Peter Eisentraut Discussion: https://postgr.es/m/4b76c6d4-ae5e-0dc6-7d0d-b5c796a07e34%402ndquadrant.com --- doc/src/sgml/ref/alter_collation.sgml | 10 ++++++++++ src/backend/utils/adt/pg_locale.c | 14 ++++++++++++-- src/bin/pg_dump/t/002_pg_dump.pl | 4 ++-- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/doc/src/sgml/ref/alter_collation.sgml b/doc/src/sgml/ref/alter_collation.sgml index b51b3a2564..4cfcb42251 100644 --- a/doc/src/sgml/ref/alter_collation.sgml +++ b/doc/src/sgml/ref/alter_collation.sgml @@ -129,6 +129,16 @@ HINT: Rebuild all objects affected by this collation and run ALTER COLLATION pg does not actually check whether all affected objects have been rebuilt correctly. + + When using collations provided by libc and + PostgreSQL was built with the GNU C library, the + C library's version is used as a collation version. Since collation + definitions typically change only with GNU C library releases, this provides + some defense against corruption, but it is not completely reliable. + + + Currently, there is no version tracking for the database default collation. + The following query can be used to identify all collations in the current diff --git a/src/backend/utils/adt/pg_locale.c b/src/backend/utils/adt/pg_locale.c index 2a076a3dfd..fcdbaae37b 100644 --- a/src/backend/utils/adt/pg_locale.c +++ b/src/backend/utils/adt/pg_locale.c @@ -70,6 +70,10 @@ #include #endif +#ifdef __GLIBC__ +#include +#endif + #ifdef WIN32 /* * This Windows file defines StrNCpy. We don't need it here, so we undefine @@ -1499,7 +1503,7 @@ pg_newlocale_from_collation(Oid collid) char * get_collation_actual_version(char collprovider, const char *collcollate) { - char *collversion; + char *collversion = NULL; #ifdef USE_ICU if (collprovider == COLLPROVIDER_ICU) @@ -1523,7 +1527,13 @@ get_collation_actual_version(char collprovider, const char *collcollate) } else #endif - collversion = NULL; + if (collprovider == COLLPROVIDER_LIBC) + { +#if defined(__GLIBC__) + /* Use the glibc version because we don't have anything better. */ + collversion = pstrdup(gnu_get_libc_version()); +#endif + } return collversion; } diff --git a/src/bin/pg_dump/t/002_pg_dump.pl b/src/bin/pg_dump/t/002_pg_dump.pl index 4712e3a958..1163420491 100644 --- a/src/bin/pg_dump/t/002_pg_dump.pl +++ b/src/bin/pg_dump/t/002_pg_dump.pl @@ -1376,8 +1376,8 @@ my %tests = ( 'CREATE COLLATION test0 FROM "C"' => { create_order => 76, create_sql => 'CREATE COLLATION test0 FROM "C";', - regexp => qr/^ - \QCREATE COLLATION public.test0 (provider = libc, locale = 'C');\E/xm, + regexp => + qr/CREATE COLLATION public.test0 \(provider = libc, locale = 'C'(, version = '[^']*')?\);/m, collation => 1, like => { %full_runs, section_pre_data => 1, }, }, -- 2.40.0