On Wed, Dec 18, 2019 at 11:02 PM Thomas Munro <thomas.mu...@gmail.com> wrote: > On Tue, Dec 17, 2019 at 1:40 AM Juan José Santamaría Flecha > <juanjo.santama...@gmail.com> wrote: > > This is a resume to illustrate an issue with locale = 'C': > > > > postgres=# CREATE COLLATION c_test (locale = 'C'); > > CREATE COLLATION > > postgres=# select collname, collprovider, collencoding, collcollate, > > collctype, collversion from pg_collation ; > > collname | collprovider | collencoding | collcollate | > > collctype | collversion > > ------------------------+--------------+--------------+------------------+------------------+------------- > > default | d | -1 | | > > | <NULL> > > C | c | -1 | C | > > C | <NULL> > > POSIX | c | -1 | POSIX | > > POSIX | <NULL> > > ucs_basic | c | 6 | C | > > C | <NULL> > > und-x-icu | i | -1 | und | > > und | 153.97 > > [... resumed ...] > > c_test | c | 6 | C | > > C | > > (757 rows) > > > > Shouldn't it be NULL?
Done in this new 0002 patch (untested). 0001 removes the comment that individual collations can't have a NULL version, reports NULL for Linux/glibc collations like C.UTF-8 by stripping the suffix and comparing with C and POSIX as suggested by Peter E.
From 95f35fcbc61354c984193293f70e8ee8a944df91 Mon Sep 17 00:00:00 2001 From: Thomas Munro <thomas.mu...@gmail.com> Date: Mon, 23 Mar 2020 12:48:59 +1300 Subject: [PATCH v3 1/2] Allow NULL version for individual collations. Remove the documented restriction that collation providers must either return NULL for all collations or non-NULL for all collations. Use NULL for glibc collations like "C.UTF-8", which might otherwise lead future proposed commits to force unnecessary index rebuilds. Reviewed-by: Peter Eisentraut <peter.eisentr...@2ndquadrant.com> Discussion: https://postgr.es/m/CA%2BhUKGJvqup3s%2BJowVTcacZADO6dOhfdBmvOPHLS3KXUJu41Jw%40mail.gmail.com --- src/backend/utils/adt/pg_locale.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/backend/utils/adt/pg_locale.c b/src/backend/utils/adt/pg_locale.c index 64fd3ae18a..b42122f9ce 100644 --- a/src/backend/utils/adt/pg_locale.c +++ b/src/backend/utils/adt/pg_locale.c @@ -1505,10 +1505,6 @@ pg_newlocale_from_collation(Oid collid) /* * Get provider-specific collation version string for the given collation from * the operating system/library. - * - * A particular provider must always either return a non-NULL string or return - * NULL (if it doesn't support versions). It must not return NULL for some - * collcollate and not NULL for others. */ char * get_collation_actual_version(char collprovider, const char *collcollate) @@ -1540,6 +1536,23 @@ get_collation_actual_version(char collprovider, const char *collcollate) if (collprovider == COLLPROVIDER_LIBC) { #if defined(__GLIBC__) + char *copy = pstrdup(collcollate); + char *copy_suffix = strstr(copy, "."); + bool need_version = true; + + /* + * Check for names like C.UTF-8 by chopping off the encoding suffix on + * our temporary copy, so we can skip the version. + */ + if (copy_suffix) + *copy_suffix = '\0'; + if (pg_strcasecmp("c", copy) == 0 || + pg_strcasecmp("posix", copy) == 0) + need_version = false; + pfree(copy); + if (!need_version) + return NULL; + /* Use the glibc version because we don't have anything better. */ collversion = pstrdup(gnu_get_libc_version()); #endif -- 2.20.1
From 953148ccfcb28856db70fe0cb4a99b9f2a08a0ce Mon Sep 17 00:00:00 2001 From: Thomas Munro <thomas.mu...@gmail.com> Date: Fri, 8 Nov 2019 12:01:05 +1300 Subject: [PATCH v3 2/2] Add collation versions for Windows. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On Vista and later, use GetNLSVersionEx() to request collation version information. Reviewed-by: Juan José Santamaría Flecha <juanjo.santama...@gmail.com> Discussion: https://postgr.es/m/CA%2BhUKGJvqup3s%2BJowVTcacZADO6dOhfdBmvOPHLS3KXUJu41Jw%40mail.gmail.com --- src/backend/utils/adt/pg_locale.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/backend/utils/adt/pg_locale.c b/src/backend/utils/adt/pg_locale.c index b42122f9ce..2562eb5416 100644 --- a/src/backend/utils/adt/pg_locale.c +++ b/src/backend/utils/adt/pg_locale.c @@ -1555,6 +1555,33 @@ get_collation_actual_version(char collprovider, const char *collcollate) /* Use the glibc version because we don't have anything better. */ collversion = pstrdup(gnu_get_libc_version()); +#elif defined(WIN32) && _WIN32_WINNT >= 0x0600 + /* + * If we are targeting Windows Vista and above, we can ask for a name + * given a collation name (earlier versions required a location code + * that we don't have). + */ + NLSVERSIONINFOEX version = {sizeof(NLSVERSIONINFOEX)}; + WCHAR wide_collcollate[LOCALE_NAME_MAX_LENGTH]; + + /* These would be invalid arguments, but have no version. */ + if (pg_strcasecmp("c", collcollate) == 0 || + pg_strcasecmp("posix", collcollate) == 0) + return NULL; + + /* For all other names, ask the OS. */ + MultiByteToWideChar(CP_ACP, 0, collcollate, -1, wide_collcollate, + LOCALE_NAME_MAX_LENGTH); + if (!GetNLSVersionEx(COMPARE_STRING, wide_collcollate, &version)) + ereport(ERROR, + (errmsg("could not get collation version for locale \"%s\": error code %lu", + collcollate, + GetLastError()))); + collversion = psprintf("%d.%d,%d.%d", + (version.dwNLSVersion >> 8) & 0xFFFF, + version.dwNLSVersion & 0xFF, + (version.dwDefinedVersion >> 8) & 0xFFFF, + version.dwDefinedVersion & 0xFF); #endif } -- 2.20.1