[2/2] services: postgresql: Add locale to configuration

Message ID 20161211211301.28403-2-mail@cbaines.net
State New
Headers

Commit Message

Christopher Baines Dec. 11, 2016, 9:13 p.m. UTC
  * gnu/services/postgresql.scm (<postgresql-configuration>): Add locale
  field.
  (postgresql-shepherd-service): Pass locale to initdb.
  (postgresql-service): Add locale default.
---
 gnu/services/databases.scm | 22 ++++++++++++++++++----
 1 file changed, 18 insertions(+), 4 deletions(-)
  

Comments

Ludovic Courtès Dec. 11, 2016, 11:14 p.m. UTC | #1
Hi!

Christopher Baines <mail@cbaines.net> skribis:

> * gnu/services/postgresql.scm (<postgresql-configuration>): Add locale
>   field.
>   (postgresql-shepherd-service): Pass locale to initdb.
>   (postgresql-service): Add locale default.

[...]

> +  (locale         postgresql-configuration-locale
> +                  (default "en_US.UTF-8"))

Note: this should use the “normalized codeset”, so “en_US.utf8”.

>           (let ((user (getpwnam "postgres"))
> -               (initdb (string-append #$postgresql "/bin/initdb")))
> +               (initdb (string-append #$postgresql "/bin/initdb"))
> +               (initdb-args
> +                (append
> +                 (if #$locale
> +                     (list (string-append "--locale=" #$locale))
> +                     '()))))
>             ;; Create db state directory.
>             (mkdir-p #$data-directory)
>             (chown #$data-directory (passwd:uid user) (passwd:gid user))
> @@ -103,14 +110,19 @@ host	all	all	::1/128 	trust"))
>                  (lambda ()
>                    (setgid (passwd:gid user))
>                    (setuid (passwd:uid user))
> -                  (primitive-exit (system* initdb "-D" #$data-directory)))
> +                  (primitive-exit
> +                   (apply system*
> +                          initdb
> +                          "-D"
> +                          #$data-directory
> +                          initdb-args)))
>                  (lambda ()
>                    (primitive-exit 1))))
>               (pid (waitpid pid))))))))

The effect of that is that ‘initdb’, but not ‘postgresql’ itself, would
run in a locale different from the system locale by default.

These two inconsistencies may be quite confusing.  WDYT?

Thanks,
Ludo’.
  
Christopher Baines Dec. 12, 2016, 6:53 a.m. UTC | #2
On 11/12/16 23:14, Ludovic Courtès wrote:
> Hi!
>
> Christopher Baines <mail@cbaines.net> skribis:
>
>> * gnu/services/postgresql.scm (<postgresql-configuration>): Add locale
>>   field.
>>   (postgresql-shepherd-service): Pass locale to initdb.
>>   (postgresql-service): Add locale default.
>
> [...]
>
>> +  (locale         postgresql-configuration-locale
>> +                  (default "en_US.UTF-8"))
>
> Note: this should use the “normalized codeset”, so “en_US.utf8”.
>
>>           (let ((user (getpwnam "postgres"))
>> -               (initdb (string-append #$postgresql "/bin/initdb")))
>> +               (initdb (string-append #$postgresql "/bin/initdb"))
>> +               (initdb-args
>> +                (append
>> +                 (if #$locale
>> +                     (list (string-append "--locale=" #$locale))
>> +                     '()))))
>>             ;; Create db state directory.
>>             (mkdir-p #$data-directory)
>>             (chown #$data-directory (passwd:uid user) (passwd:gid user))
>> @@ -103,14 +110,19 @@ host	all	all	::1/128 	trust"))
>>                  (lambda ()
>>                    (setgid (passwd:gid user))
>>                    (setuid (passwd:uid user))
>> -                  (primitive-exit (system* initdb "-D" #$data-directory)))
>> +                  (primitive-exit
>> +                   (apply system*
>> +                          initdb
>> +                          "-D"
>> +                          #$data-directory
>> +                          initdb-args)))
>>                  (lambda ()
>>                    (primitive-exit 1))))
>>               (pid (waitpid pid))))))))
>
> The effect of that is that ‘initdb’, but not ‘postgresql’ itself, would
> run in a locale different from the system locale by default.
>
> These two inconsistencies may be quite confusing.  WDYT?

I believe the locale passed to initdb sets "the default locale for the 
database cluster", so I'd imagine that there is no problems with running 
PostgreSQL (it seems to work for me). I think its good to support 
setting it explicitly, but it would also be good to use the system 
locale as a default.

I thought about trying to get the LANG from /etc/environment, or the 
<operating-system>, but I could not see an easy and elegant way to do 
either. By default, initdb will use the environment, its just that the 
environment during service activation contains no locale information.
  
Ludovic Courtès Dec. 13, 2016, 11:09 p.m. UTC | #3
Christopher Baines <mail@cbaines.net> skribis:

> On 11/12/16 23:14, Ludovic Courtès wrote:
>> Hi!
>>
>> Christopher Baines <mail@cbaines.net> skribis:
>>
>>> * gnu/services/postgresql.scm (<postgresql-configuration>): Add locale
>>>   field.
>>>   (postgresql-shepherd-service): Pass locale to initdb.
>>>   (postgresql-service): Add locale default.
>>
>> [...]
>>
>>> +  (locale         postgresql-configuration-locale
>>> +                  (default "en_US.UTF-8"))
>>
>> Note: this should use the “normalized codeset”, so “en_US.utf8”.
>>
>>>           (let ((user (getpwnam "postgres"))
>>> -               (initdb (string-append #$postgresql "/bin/initdb")))
>>> +               (initdb (string-append #$postgresql "/bin/initdb"))
>>> +               (initdb-args
>>> +                (append
>>> +                 (if #$locale
>>> +                     (list (string-append "--locale=" #$locale))
>>> +                     '()))))
>>>             ;; Create db state directory.
>>>             (mkdir-p #$data-directory)
>>>             (chown #$data-directory (passwd:uid user) (passwd:gid user))
>>> @@ -103,14 +110,19 @@ host	all	all	::1/128 	trust"))
>>>                  (lambda ()
>>>                    (setgid (passwd:gid user))
>>>                    (setuid (passwd:uid user))
>>> -                  (primitive-exit (system* initdb "-D" #$data-directory)))
>>> +                  (primitive-exit
>>> +                   (apply system*
>>> +                          initdb
>>> +                          "-D"
>>> +                          #$data-directory
>>> +                          initdb-args)))
>>>                  (lambda ()
>>>                    (primitive-exit 1))))
>>>               (pid (waitpid pid))))))))
>>
>> The effect of that is that ‘initdb’, but not ‘postgresql’ itself, would
>> run in a locale different from the system locale by default.
>>
>> These two inconsistencies may be quite confusing.  WDYT?
>
> I believe the locale passed to initdb sets "the default locale for the
> database cluster",

Oh, so it affects the initial format of the DB, right?  In that case,
you’re right of course.

> I thought about trying to get the LANG from /etc/environment, or the
> <operating-system>, but I could not see an easy and elegant way to do
> either. By default, initdb will use the environment, its just that the
> environment during service activation contains no locale information.

With 97bb1ab66519736afbdab57c230c3a9deef2fa05 there *is* locale data
available at least, right?

But yeah, there’s no easy way to retrieve the currently-configured system
locale, so let’s forget about it (maybe add an “XXX” comment next to
it.)

Could you send an updated patch with (1) the normalized codeset by
default (“en_US.utf8”), and (2) a guix.texi update mentioning the new
option?

Thanks in advance!

Ludo’.
  

Patch

diff --git a/gnu/services/databases.scm b/gnu/services/databases.scm
index 3850ba502..4b97afc37 100644
--- a/gnu/services/databases.scm
+++ b/gnu/services/databases.scm
@@ -50,6 +50,8 @@ 
                   (default postgresql))
   (port           postgresql-configuration-port
                   (default 5432))
+  (locale         postgresql-configuration-locale
+                  (default "en_US.UTF-8"))
   (config-file    postgresql-configuration-file)
   (data-directory postgresql-configuration-data-directory))
 
@@ -82,13 +84,18 @@  host	all	all	::1/128 	trust"))
 
 (define postgresql-activation
   (match-lambda
-    (($ <postgresql-configuration> postgresql port config-file data-directory)
+    (($ <postgresql-configuration> postgresql port locale config-file data-directory)
      #~(begin
          (use-modules (guix build utils)
                       (ice-9 match))
 
          (let ((user (getpwnam "postgres"))
-               (initdb (string-append #$postgresql "/bin/initdb")))
+               (initdb (string-append #$postgresql "/bin/initdb"))
+               (initdb-args
+                (append
+                 (if #$locale
+                     (list (string-append "--locale=" #$locale))
+                     '()))))
            ;; Create db state directory.
            (mkdir-p #$data-directory)
            (chown #$data-directory (passwd:uid user) (passwd:gid user))
@@ -103,14 +110,19 @@  host	all	all	::1/128 	trust"))
                 (lambda ()
                   (setgid (passwd:gid user))
                   (setuid (passwd:uid user))
-                  (primitive-exit (system* initdb "-D" #$data-directory)))
+                  (primitive-exit
+                   (apply system*
+                          initdb
+                          "-D"
+                          #$data-directory
+                          initdb-args)))
                 (lambda ()
                   (primitive-exit 1))))
              (pid (waitpid pid))))))))
 
 (define postgresql-shepherd-service
   (match-lambda
-    (($ <postgresql-configuration> postgresql port config-file data-directory)
+    (($ <postgresql-configuration> postgresql port locale config-file data-directory)
      (let* ((string-port (number->string port))
             (start-script
              ;; Wrapper script that switches to the 'postgres' user before
@@ -145,6 +157,7 @@  host	all	all	::1/128 	trust"))
 
 (define* (postgresql-service #:key (postgresql postgresql)
                              (port 5432)
+                             (locale "en_US.UTF-8")
                              (config-file %default-postgres-config)
                              (data-directory "/var/lib/postgresql/data"))
   "Return a service that runs @var{postgresql}, the PostgreSQL database server.
@@ -155,6 +168,7 @@  and stores the database cluster in @var{data-directory}."
            (postgresql-configuration
             (postgresql postgresql)
             (port port)
+            (locale locale)
             (config-file config-file)
             (data-directory data-directory))))