Hello. I noticed that -c option of initdb behaves in an unexpected manner. Identical variable names with variations in letter casing are treated as distinct variables.
$ initdb -cwork_mem=100 -cWORK_MEM=1000 -cWork_mem=2000 ... $ grep -i 'work_mem ' $PGDATA/postgresql.conf work_mem = 100 # min 64kB #maintenance_work_mem = 64MB # min 1MB #autovacuum_work_mem = -1 # min 1MB, or -1 to use maintenance_work_mem #logical_decoding_work_mem = 64MB # min 64kB WORK_MEM = 1000 Work_mem = 2000 The original intention was apparently to overwrite the existing line. Furthermore, I surmise that preserving the original letter casing is preferable. Attached is a patch to address this issue. To retrieve the variable name from the existing line, the code is slightly restructured. Alternatively, should we just down-case the provided variable names? regards. -- Kyotaro Horiguchi NTT Open Source Software Center
diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c index 0c6f5ceb0a..04419840f4 100644 --- a/src/bin/initdb/initdb.c +++ b/src/bin/initdb/initdb.c @@ -470,20 +470,14 @@ replace_guc_value(char **lines, const char *guc_name, const char *guc_value, int namelen = strlen(guc_name); PQExpBuffer newline = createPQExpBuffer(); int i; + const char *where; + const char *pname; - /* prepare the replacement line, except for possible comment and newline */ if (mark_as_comment) appendPQExpBufferChar(newline, '#'); - appendPQExpBuffer(newline, "%s = ", guc_name); - if (guc_value_requires_quotes(guc_value)) - appendPQExpBuffer(newline, "'%s'", escape_quotes(guc_value)); - else - appendPQExpBufferStr(newline, guc_value); for (i = 0; lines[i]; i++) { - const char *where; - /* * Look for a line assigning to guc_name. Typically it will be * preceded by '#', but that might not be the case if a -c switch @@ -493,15 +487,32 @@ 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; + + pname = where; where += namelen; while (isspace((unsigned char) *where)) where++; - if (*where != '=') - continue; - /* found it -- append the original comment if any */ + /* assume there's only one match */ + if (*where == '=') + break; + } + + if (lines[i]) + { + /* found it, rewrite the line preserving the original comment if any */ + appendPQExpBuffer(newline, "%.*s = ", namelen, pname); + if (guc_value_requires_quotes(guc_value)) + appendPQExpBuffer(newline, "'%s'", escape_quotes(guc_value)); + else + appendPQExpBufferStr(newline, guc_value); + + /* + * completed body of line, now continue with potential indentation and + * comment + */ where = strrchr(where, '#'); if (where) { @@ -548,16 +559,19 @@ replace_guc_value(char **lines, const char *guc_name, const char *guc_value, free(lines[i]); lines[i] = newline->data; - - break; /* assume there's only one match */ } - - if (lines[i] == NULL) + else { /* * No match, so append a new entry. (We rely on the bootstrap server * to complain if it's not a valid GUC name.) */ + appendPQExpBuffer(newline, "%s = ", guc_name); + if (guc_value_requires_quotes(guc_value)) + appendPQExpBuffer(newline, "'%s'", escape_quotes(guc_value)); + else + appendPQExpBufferStr(newline, guc_value); + appendPQExpBufferChar(newline, '\n'); lines = pg_realloc_array(lines, char *, i + 2); lines[i++] = newline->data;