Re: initdb's -c option behaves wrong way? - Mailing list pgsql-hackers

From Tom Lane
Subject Re: initdb's -c option behaves wrong way?
Date
Msg-id 2629788.1705682037@sss.pgh.pa.us
Whole thread Raw
In response to Re: initdb's -c option behaves wrong way?  (Daniel Gustafsson <daniel@yesql.se>)
Responses Re: initdb's -c option behaves wrong way?
List pgsql-hackers
Daniel Gustafsson <daniel@yesql.se> writes:
> I'll give some more time for opinions, then I'll go ahead with one of the
> patches with a backpatch to v16.

OK, I take back my previous complaint that just using strncasecmp
would be enough --- I was misremembering how the code worked, and
you're right that it would use the spelling from the command line
rather than that from the file.

However, the v3 patch is flat broken.  You can't assume you have
found a match until you've verified that whitespace and '='
appear next --- otherwise, you'll be fooled by a guc_name that
is a prefix of one that appears in the file.  I think the simplest
change that does it correctly is as attached.

Now, since I was the one who wrote the existing code, I freely
concede that I may have too high an opinion of its readability.
Maybe some larger refactoring is appropriate.  But I didn't
find that what you'd done improved the readability.  I'd still
rather keep the newline-assembly code together as much as possible.
Maybe we should do the search part before we build any of newline?

            regards, tom lane

diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c
index ac409b0006..6a620c9d5f 100644
--- a/src/bin/initdb/initdb.c
+++ b/src/bin/initdb/initdb.c
@@ -484,6 +484,7 @@ replace_guc_value(char **lines, const char *guc_name, const char *guc_value,
     for (i = 0; lines[i]; i++)
     {
         const char *where;
+        const char *namestart;

         /*
          * Look for a line assigning to guc_name.  Typically it will be
@@ -494,15 +495,19 @@ replace_guc_value(char **lines, const char *guc_name, const char *guc_value,
         where = lines[i];
         while (*where == '#' || isspace((unsigned char) *where))
             where++;
-        if (strncmp(where, guc_name, namelen) != 0)
+        if (strncasecmp(where, guc_name, namelen) != 0)
             continue;
+        namestart = where;
         where += namelen;
         while (isspace((unsigned char) *where))
             where++;
         if (*where != '=')
             continue;

-        /* found it -- append the original comment if any */
+        /* found it -- let's use the canonical casing shown in the file */
+        memcpy(&newline->data[mark_as_comment ? 1 : 0], namestart, namelen);
+
+        /* now append the original comment if any */
         where = strrchr(where, '#');
         if (where)
         {
diff --git a/src/bin/initdb/t/001_initdb.pl b/src/bin/initdb/t/001_initdb.pl
index 03376cc0f7..413a5eca67 100644
--- a/src/bin/initdb/t/001_initdb.pl
+++ b/src/bin/initdb/t/001_initdb.pl
@@ -199,4 +199,17 @@ command_fails(
 command_fails([ 'initdb', '--no-sync', '--set', 'foo=bar', "$tempdir/dataX" ],
     'fails for invalid --set option');

+# Make sure multiple invocations of -c parameters are added case insensitive
+command_ok(
+    [
+        'initdb', '-cwork_mem=128', '-cWork_Mem=256', '-cWORK_MEM=512',
+        "$tempdir/dataY"
+    ],
+    'multiple -c options with different case');
+
+my $conf = slurp_file("$tempdir/dataY/postgresql.conf");
+ok($conf !~ qr/^WORK_MEM = /m, "WORK_MEM should not be configured");
+ok($conf !~ qr/^Work_Mem = /m, "Work_Mem should not be configured");
+ok($conf =~ qr/^work_mem = 512/m, "work_mem should be in config");
+
 done_testing();

pgsql-hackers by date:

Previous
From: Konstantin Knizhnik
Date:
Subject: Re: index prefetching
Next
From: Heikki Linnakangas
Date:
Subject: Re: Change GUC hashtable to use simplehash?