Add CREATE DATABASE LOCALE option
authorPeter Eisentraut
Tue, 23 Jul 2019 12:40:42 +0000 (14:40 +0200)
committerPeter Eisentraut
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
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 name
     [ [ WITH ] [ OWNER [=] user_name ]
            [ TEMPLATE [=] template ]
            [ ENCODING [=] encoding ]
+           [ LOCALE [=] locale ]
            [ LC_COLLATE [=] lc_collate ]
            [ LC_CTYPE [=] lc_ctype ]
            [ TABLESPACE [=] tablespace_name ]
@@ -111,6 +112,26 @@ CREATE DATABASE name
        
       
      
+     
+      locale
+      
+       
+        This is a shortcut for setting LC_COLLATE
+        and LC_CTYPE at once.  If you specify this,
+        you cannot specify either of those parameters.
+       
+       
+        
+         The other locale settings 
+         linkend="guc-lc-monetary"/>, , and
+          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 ALTER DATABASE
+         ... SET.
+        
+       
+      
+     
      
       lc_collate
       
@@ -287,7 +308,7 @@ CREATE DATABASE sales OWNER salesapp TABLESPACE salesspace;
    To create a database music with a different locale:
 
 CREATE DATABASE music
-    LC_COLLATE 'sv_SE.utf8' LC_CTYPE 'sv_SE.utf8'
+    LOCALE 'sv_SE.utf8'
     TEMPLATE template0;
 
     In this example, the TEMPLATE template0 clause is required if
@@ -300,7 +321,7 @@ CREATE DATABASE music
    different character set encoding:
 
 CREATE DATABASE music2
-    LC_COLLATE 'sv_SE.iso885915' LC_CTYPE 'sv_SE.iso885915'
+    LOCALE 'sv_SE.iso885915'
     ENCODING LATIN9
     TEMPLATE template0;
 
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