aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2017-01-18 13:44:19 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2017-01-18 13:44:19 -0500
commit0333a7340054c3356940759b1ab2391eed572171 (patch)
tree3e933bb72245e00d2d990868da9a9e3f84a79b0b /src
parent215b43cdc8d6b4a1700886a39df1ee735cb0274d (diff)
downloadpostgresql-0333a7340054c3356940759b1ab2391eed572171.tar.gz
postgresql-0333a7340054c3356940759b1ab2391eed572171.zip
Avoid conflicts with collation aliases generated by stripping.
This resulted in failures depending on the order of "locale -a" output. The original coding in initdb sorted the results, but that should be unnecessary as long as "locale -a" doesn't print duplicate names. The original entries will then all be non-dups, and while we might generate duplicate aliases by stripping, they should be for different encodings and thus not conflict. Even if the latter assumption fails somehow, it won't be fatal because we're using if_not_exists mode for the aliases. Discussion: https://postgr.es/m/26116.1484751196%40sss.pgh.pa.us
Diffstat (limited to 'src')
-rw-r--r--src/backend/commands/collationcmds.c36
1 files changed, 26 insertions, 10 deletions
diff --git a/src/backend/commands/collationcmds.c b/src/backend/commands/collationcmds.c
index 5cb3e2bb282..71b21bf0d20 100644
--- a/src/backend/commands/collationcmds.c
+++ b/src/backend/commands/collationcmds.c
@@ -224,11 +224,17 @@ pg_import_system_collations(PG_FUNCTION_ARGS)
{
#if defined(HAVE_LOCALE_T) && !defined(WIN32)
bool if_not_exists = PG_GETARG_BOOL(0);
- Oid nspid = PG_GETARG_OID(1);
+ Oid nspid = PG_GETARG_OID(1);
FILE *locale_a_handle;
char localebuf[NAMEDATALEN]; /* we assume ASCII so this is fine */
int count = 0;
+ List *aliaslist = NIL;
+ List *localelist = NIL;
+ List *enclist = NIL;
+ ListCell *lca,
+ *lcl,
+ *lce;
#endif
if (!superuser())
@@ -306,26 +312,36 @@ pg_import_system_collations(PG_FUNCTION_ARGS)
* ease of use. Note that collation names are unique per encoding
* only, so this doesn't clash with "en_US" for LATIN1, say.
*
- * This always runs in "if not exists" mode, to skip aliases that
- * conflict with an existing locale name for the same encoding. For
- * example, "br_FR.iso88591" is normalized to "br_FR", both for
- * encoding LATIN1. But the unnormalized locale "br_FR" already
- * exists for LATIN1.
+ * However, it might conflict with a name we'll see later in the
+ * "locale -a" output. So save up the aliases and try to add them
+ * after we've read all the output.
*/
if (normalize_locale_name(alias, localebuf))
{
- CollationCreate(alias, nspid, GetUserId(), enc,
- localebuf, localebuf, true);
- CommandCounterIncrement();
+ aliaslist = lappend(aliaslist, pstrdup(alias));
+ localelist = lappend(localelist, pstrdup(localebuf));
+ enclist = lappend_int(enclist, enc);
}
}
ClosePipeStream(locale_a_handle);
+ /* Now try to add any aliases we created */
+ forthree(lca, aliaslist, lcl, localelist, lce, enclist)
+ {
+ char *alias = (char *) lfirst(lca);
+ char *locale = (char *) lfirst(lcl);
+ int enc = lfirst_int(lce);
+
+ CollationCreate(alias, nspid, GetUserId(), enc,
+ locale, locale, true);
+ CommandCounterIncrement();
+ }
+
if (count == 0)
ereport(ERROR,
(errmsg("no usable system locales were found")));
-#endif /* not HAVE_LOCALE_T && not WIN32 */
+#endif /* not HAVE_LOCALE_T && not WIN32 */
PG_RETURN_VOID();
}