Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 853c175

Browse files
committed
Be more wary in initdb's creation of platform-dependent collations.
Discard any collation aliases that match the built-in pg_collation entries (ie, "default", "C", "POSIX"). Such aliases would be refused by a CREATE COLLATION command, but since initdb is injecting them via a simple INSERT, it has to make the corresponding check for itself. Per Martin Pitt's report of funny behavior in a machine that had a bogus "C.UTF-8" locale. Also, use E'' syntax for the output of escape_quotes, as per its header comment.
1 parent 5059cf6 commit 853c175

File tree

1 file changed

+16
-9
lines changed

1 file changed

+16
-9
lines changed

src/bin/initdb/initdb.c

+16-9
Original file line numberDiff line numberDiff line change
@@ -1595,6 +1595,7 @@ setup_collation(void)
15951595
size_t len;
15961596
int enc;
15971597
bool skip;
1598+
char *quoted_locale;
15981599
char alias[NAMEDATALEN];
15991600

16001601
len = strlen(localebuf);
@@ -1645,38 +1646,44 @@ setup_collation(void)
16451646

16461647
count++;
16471648

1648-
PG_CMD_PRINTF2("INSERT INTO tmp_pg_collation (locale, encoding) VALUES ('%s', %d);\n",
1649-
escape_quotes(localebuf), enc);
1649+
quoted_locale = escape_quotes(localebuf);
1650+
1651+
PG_CMD_PRINTF3("INSERT INTO tmp_pg_collation VALUES (E'%s', E'%s', %d);\n",
1652+
quoted_locale, quoted_locale, enc);
16501653

16511654
/*
16521655
* Generate aliases such as "en_US" in addition to "en_US.utf8" for
16531656
* ease of use. Note that collation names are unique per encoding
16541657
* only, so this doesn't clash with "en_US" for LATIN1, say.
16551658
*/
16561659
if (normalize_locale_name(alias, localebuf))
1657-
PG_CMD_PRINTF3("INSERT INTO tmp_pg_collation (collname, locale, encoding) VALUES ('%s', '%s', %d);\n",
1658-
escape_quotes(alias), escape_quotes(localebuf), enc);
1660+
PG_CMD_PRINTF3("INSERT INTO tmp_pg_collation VALUES (E'%s', E'%s', %d);\n",
1661+
escape_quotes(alias), quoted_locale, enc);
16591662
}
16601663

16611664
/* Add an SQL-standard name */
1662-
PG_CMD_PRINTF1("INSERT INTO tmp_pg_collation (collname, locale, encoding) VALUES ('ucs_basic', 'C', %d);\n", PG_UTF8);
1665+
PG_CMD_PRINTF1("INSERT INTO tmp_pg_collation VALUES ('ucs_basic', 'C', %d);\n", PG_UTF8);
16631666

16641667
/*
16651668
* When copying collations to the final location, eliminate aliases that
16661669
* conflict with an existing locale name for the same encoding. For
16671670
* example, "br_FR.iso88591" is normalized to "br_FR", both for encoding
16681671
* LATIN1. But the unnormalized locale "br_FR" already exists for LATIN1.
1669-
* Prefer the collation that matches the OS locale name, else the first
1672+
* Prefer the alias that matches the OS locale name, else the first locale
16701673
* name by sort order (arbitrary choice to be deterministic).
1674+
*
1675+
* Also, eliminate any aliases that conflict with pg_collation's
1676+
* hard-wired entries for "C" etc.
16711677
*/
16721678
PG_CMD_PUTS("INSERT INTO pg_collation (collname, collnamespace, collowner, collencoding, collcollate, collctype) "
1673-
" SELECT DISTINCT ON (final_collname, collnamespace, encoding)"
1674-
" COALESCE(collname, locale) AS final_collname, "
1679+
" SELECT DISTINCT ON (collname, encoding)"
1680+
" collname, "
16751681
" (SELECT oid FROM pg_namespace WHERE nspname = 'pg_catalog') AS collnamespace, "
16761682
" (SELECT relowner FROM pg_class WHERE relname = 'pg_collation') AS collowner, "
16771683
" encoding, locale, locale "
16781684
" FROM tmp_pg_collation"
1679-
" ORDER BY final_collname, collnamespace, encoding, (collname = locale) DESC, locale;\n");
1685+
" WHERE NOT EXISTS (SELECT 1 FROM pg_collation WHERE collname = tmp_pg_collation.collname)"
1686+
" ORDER BY collname, encoding, (collname = locale) DESC, locale;\n");
16801687

16811688
pclose(locale_a_handle);
16821689
PG_CMD_CLOSE;

0 commit comments

Comments
 (0)