]> granicus.if.org Git - postgresql/commitdiff
Add CREATE DATABASE LOCALE option
authorPeter Eisentraut <peter@eisentraut.org>
Tue, 23 Jul 2019 12:40:42 +0000 (14:40 +0200)
committerPeter Eisentraut <peter@eisentraut.org>
Tue, 23 Jul 2019 12:47:24 +0000 (14:47 +0200)
This sets both LC_COLLATE and LC_CTYPE with one option.  Similar
behavior is already supported in initdb, CREATE COLLATION, and
createdb.

Reviewed-by: Fabien COELHO <coelho@cri.ensmp.fr>
Discussion: https://www.postgresql.org/message-id/flat/d9d5043a-dc70-da8a-0166-1e218e6e34d4%402ndquadrant.com

doc/src/sgml/ref/create_database.sgml
src/backend/commands/dbcommands.c
src/bin/pg_dump/pg_dump.c
src/bin/pg_dump/t/002_pg_dump.pl

index b2c9e241c2f1387f9e45da47feeb0f0a8e3067b0..4014f6703bbaeaeac8ebdc13dcd2f674c9088fcb 100644 (file)
@@ -25,6 +25,7 @@ CREATE DATABASE <replaceable class="parameter">name</replaceable>
     [ [ 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 @@ CREATE DATABASE <replaceable class="parameter">name</replaceable>
        </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 @@ CREATE DATABASE sales OWNER salesapp TABLESPACE salesspace;
    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 @@ CREATE DATABASE music
    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>
index 863f89f19d24189e2d183e28d1c00319e2ce4af2..fc1e1564a6188384355e1b3e6ce23efba7b1e106 100644 (file)
@@ -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,12 @@ 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"),
+                                errdetail("LOCALE cannot be specified together with LC_COLLATE or LC_CTYPE.")));
+
        if (downer && downer->arg)
                dbowner = defGetString(downer);
        if (dtemplate && dtemplate->arg)
@@ -276,6 +292,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)
index bbf44a18202547724daedcbbe36cd483b910b17b..8a3167224713b19cc98de94fc8719d08d0d3cd14 100644 (file)
@@ -2812,15 +2812,23 @@ dumpDatabase(Archive *fout)
                appendPQExpBufferStr(creaQry, " ENCODING = ");
                appendStringLiteralAH(creaQry, encoding, fout);
        }
-       if (strlen(collate) > 0)
+       if (strlen(collate) > 0 && strcmp(collate, ctype) == 0)
        {
-               appendPQExpBufferStr(creaQry, " LC_COLLATE = ");
+               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);
+               }
        }
 
        /*
index c56bf00e4b40e2b914b284d3ad682a06b03608bc..7cbccee103a7f270796b3c955979354299729567 100644 (file)
@@ -1407,6 +1407,15 @@ my %tests = (
                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