On 2019-06-06 21:52, Alvaro Herrera wrote:
> On 2019-Jun-06, FabrÃzio de Royes Mello wrote:
>
>>>> Cool... would be nice also add some test cases.
>>>
>>> Right. Any suggestions where to put them?
>>
>> Hmm... good question... I thought we already have some regression tests for
>> {CREATE|DROP} DATABASE but actually we don't... should we add a new one?
>
> I think pg_dump/t/002_pg_dump.pl might be a good place. Not the easiest
> program in the world to work with, admittedly.
Updated patch with test and expanded documentation.
--
Peter Eisentraut http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services
From 7ba4151235a32ebfd11bd80a5a01d9ef347d2c11 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <[email protected]>
Date: Sun, 23 Jun 2019 20:09:00 +0200
Subject: [PATCH v2] Add CREATE DATABASE LOCALE option
This sets both LC_COLLATE and LC_CTYPE with one option. Similar
behavior is already supported in initdb, CREATE COLLATION, and
createdb.
Discussion:
https://www.postgresql.org/message-id/flat/d9d5043a-dc70-da8a-0166-1e218e6e34d4%402ndquadrant.com
---
doc/src/sgml/ref/create_database.sgml | 25 +++++++++++++++++++++++--
src/backend/commands/dbcommands.c | 20 ++++++++++++++++++++
src/bin/pg_dump/pg_dump.c | 23 +++++++++++++++++------
src/bin/pg_dump/t/002_pg_dump.pl | 9 +++++++++
4 files changed, 69 insertions(+), 8 deletions(-)
diff --git a/doc/src/sgml/ref/create_database.sgml
b/doc/src/sgml/ref/create_database.sgml
index b2c9e241c2..4014f6703b 100644
--- a/doc/src/sgml/ref/create_database.sgml
+++ b/doc/src/sgml/ref/create_database.sgml
@@ -25,6 +25,7 @@
[ [ WITH ] [ OWNER [=] <replaceable
class="parameter">user_name</replaceable> ]
[ TEMPLATE [=] <replaceable
class="parameter">template</replaceable> ]
[ ENCODING [=] <replaceable
class="parameter">encoding</replaceable> ]
+ [ LOCALE [=] <replaceable class="parameter">locale</replaceable> ]
[ LC_COLLATE [=] <replaceable
class="parameter">lc_collate</replaceable> ]
[ LC_CTYPE [=] <replaceable
class="parameter">lc_ctype</replaceable> ]
[ TABLESPACE [=] <replaceable
class="parameter">tablespace_name</replaceable> ]
@@ -111,6 +112,26 @@ <title>Parameters</title>
</para>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><replaceable class="parameter">locale</replaceable></term>
+ <listitem>
+ <para>
+ This is a shortcut for setting <symbol>LC_COLLATE</symbol>
+ and <symbol>LC_CTYPE</symbol> at once. If you specify this,
+ you cannot specify either of those parameters.
+ </para>
+ <tip>
+ <para>
+ The other locale settings <xref linkend="guc-lc-messages"/>, <xref
+ linkend="guc-lc-monetary"/>, <xref linkend="guc-lc-numeric"/>, and
+ <xref linkend="guc-lc-time"/> are not fixed per database and are not
+ set by this command. If you want to make them the default for a
+ specific database, you can use <literal>ALTER DATABASE
+ ... SET</literal>.
+ </para>
+ </tip>
+ </listitem>
+ </varlistentry>
<varlistentry>
<term><replaceable class="parameter">lc_collate</replaceable></term>
<listitem>
@@ -287,7 +308,7 @@ <title>Examples</title>
To create a database <literal>music</literal> with a different locale:
<programlisting>
CREATE DATABASE music
- LC_COLLATE 'sv_SE.utf8' LC_CTYPE 'sv_SE.utf8'
+ LOCALE 'sv_SE.utf8'
TEMPLATE template0;
</programlisting>
In this example, the <literal>TEMPLATE template0</literal> clause is
required if
@@ -300,7 +321,7 @@ <title>Examples</title>
different character set encoding:
<programlisting>
CREATE DATABASE music2
- LC_COLLATE 'sv_SE.iso885915' LC_CTYPE 'sv_SE.iso885915'
+ LOCALE 'sv_SE.iso885915'
ENCODING LATIN9
TEMPLATE template0;
</programlisting>
diff --git a/src/backend/commands/dbcommands.c
b/src/backend/commands/dbcommands.c
index 15207bf75a..ac275f7e64 100644
--- a/src/backend/commands/dbcommands.c
+++ b/src/backend/commands/dbcommands.c
@@ -124,6 +124,7 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
DefElem *downer = NULL;
DefElem *dtemplate = NULL;
DefElem *dencoding = NULL;
+ DefElem *dlocale = NULL;
DefElem *dcollate = NULL;
DefElem *dctype = NULL;
DefElem *distemplate = NULL;
@@ -184,6 +185,15 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
parser_errposition(pstate,
defel->location)));
dencoding = defel;
}
+ else if (strcmp(defel->defname, "locale") == 0)
+ {
+ if (dlocale)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("conflicting or
redundant options"),
+ parser_errposition(pstate,
defel->location)));
+ dlocale = defel;
+ }
else if (strcmp(defel->defname, "lc_collate") == 0)
{
if (dcollate)
@@ -244,6 +254,11 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
parser_errposition(pstate,
defel->location)));
}
+ if (dlocale && (dcollate || dctype))
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("conflicting or redundant options")));
+
if (downer && downer->arg)
dbowner = defGetString(downer);
if (dtemplate && dtemplate->arg)
@@ -276,6 +291,11 @@ createdb(ParseState *pstate, const CreatedbStmt *stmt)
parser_errposition(pstate,
dencoding->location)));
}
}
+ if (dlocale && dlocale->arg)
+ {
+ dbcollate = defGetString(dlocale);
+ dbctype = defGetString(dlocale);
+ }
if (dcollate && dcollate->arg)
dbcollate = defGetString(dcollate);
if (dctype && dctype->arg)
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 8909a45d61..5cad9ed796 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -2812,15 +2812,26 @@ dumpDatabase(Archive *fout)
appendPQExpBufferStr(creaQry, " ENCODING = ");
appendStringLiteralAH(creaQry, encoding, fout);
}
- if (strlen(collate) > 0)
+ if (strcmp(collate, ctype) == 0)
{
- appendPQExpBufferStr(creaQry, " LC_COLLATE = ");
- appendStringLiteralAH(creaQry, collate, fout);
+ if (strlen(collate) > 0)
+ {
+ appendPQExpBufferStr(creaQry, " LOCALE = ");
+ appendStringLiteralAH(creaQry, collate, fout);
+ }
}
- if (strlen(ctype) > 0)
+ else
{
- appendPQExpBufferStr(creaQry, " LC_CTYPE = ");
- appendStringLiteralAH(creaQry, ctype, fout);
+ if (strlen(collate) > 0)
+ {
+ appendPQExpBufferStr(creaQry, " LC_COLLATE = ");
+ appendStringLiteralAH(creaQry, collate, fout);
+ }
+ if (strlen(ctype) > 0)
+ {
+ appendPQExpBufferStr(creaQry, " LC_CTYPE = ");
+ appendStringLiteralAH(creaQry, ctype, fout);
+ }
}
/*
diff --git a/src/bin/pg_dump/t/002_pg_dump.pl b/src/bin/pg_dump/t/002_pg_dump.pl
index c56bf00e4b..7cbccee103 100644
--- a/src/bin/pg_dump/t/002_pg_dump.pl
+++ b/src/bin/pg_dump/t/002_pg_dump.pl
@@ -1407,6 +1407,15 @@
like => { pg_dumpall_dbprivs => 1, },
},
+ "CREATE DATABASE dump_test2 LOCALE = 'C'" => {
+ create_order => 47,
+ create_sql => "CREATE DATABASE dump_test2 LOCALE = 'C'
TEMPLATE = template0;",
+ regexp => qr/^
+ \QCREATE DATABASE dump_test2 \E.*\QLOCALE = 'C';\E
+ /xm,
+ like => { pg_dumpall_dbprivs => 1, },
+ },
+
'CREATE EXTENSION ... plpgsql' => {
regexp => qr/^
\QCREATE EXTENSION IF NOT EXISTS plpgsql WITH SCHEMA
pg_catalog;\E
--
2.22.0