I propose this patch to add a LOCALE option to CREATE DATABASE.  This
sets both LC_COLLATE and LC_CTYPE with one option.  Similar behavior is
already supported in initdb, CREATE COLLATION, and createdb.

With collation providers other than libc, having separate lc_collate and
lc_ctype settings is not necessarily applicable, so this is also
preparation for such future functionality.

-- 
Peter Eisentraut              http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services
From 5f64d10944b272a5b636d7b0033a0a6a3d28998b Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <pe...@eisentraut.org>
Date: Tue, 4 Jun 2019 14:45:00 +0200
Subject: [PATCH] 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.
---
 doc/src/sgml/ref/create_database.sgml | 15 +++++++++++++--
 src/backend/commands/dbcommands.c     | 20 ++++++++++++++++++++
 src/bin/pg_dump/pg_dump.c             | 23 +++++++++++++++++------
 3 files changed, 50 insertions(+), 8 deletions(-)

diff --git a/doc/src/sgml/ref/create_database.sgml 
b/doc/src/sgml/ref/create_database.sgml
index b2c9e241c2..c5b7af5cf7 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,16 @@ <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>
+      </listitem>
+     </varlistentry>
      <varlistentry>
       <term><replaceable class="parameter">lc_collate</replaceable></term>
       <listitem>
@@ -287,7 +298,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 +311,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 9f59cc74ee..ba34677787 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);
+               }
        }
 
        /*
-- 
2.21.0

Reply via email to