@@ -230,12 +230,17 @@ ProcessConfigFile(GucContext context)
230
230
* same reason, we don't attempt to validate the options' values here.
231
231
*
232
232
* In addition, the GUC_IS_IN_FILE flag is set on each existing GUC
233
- * variable mentioned in the file.
233
+ * variable mentioned in the file; and we detect duplicate entries in
234
+ * the file and mark the earlier occurrences as ignorable.
234
235
*/
235
236
for (item = head; item; item = item->next)
236
237
{
237
238
struct config_generic *record;
238
239
240
+ /* Ignore anything already marked as ignorable */
241
+ if (item->ignore )
242
+ continue ;
243
+
239
244
/*
240
245
* Try to find the variable; but do not create a custom placeholder
241
246
* if it's not there already.
@@ -244,7 +249,24 @@ ProcessConfigFile(GucContext context)
244
249
245
250
if (record)
246
251
{
247
- /* Found, so mark it as present in file */
252
+ /* If it's already marked, then this is a duplicate entry */
253
+ if (record->status & GUC_IS_IN_FILE)
254
+ {
255
+ /*
256
+ * Mark the earlier occurrence(s) as dead/ignorable. We could
257
+ * avoid the O(N^2) behavior here with some additional state,
258
+ * but it seems unlikely to be worth the trouble.
259
+ */
260
+ ConfigVariable *pitem;
261
+
262
+ for (pitem = head; pitem != item; pitem = pitem->next )
263
+ {
264
+ if (!pitem->ignore &&
265
+ strcmp (pitem->name , item->name ) == 0 )
266
+ pitem->ignore = true ;
267
+ }
268
+ }
269
+ /* Now mark it as present in file */
248
270
record->status |= GUC_IS_IN_FILE;
249
271
}
250
272
else if (strchr (item->name , GUC_QUALIFIER_SEPARATOR) == NULL )
@@ -352,6 +374,10 @@ ProcessConfigFile(GucContext context)
352
374
char *pre_value = NULL ;
353
375
int scres;
354
376
377
+ /* Ignore anything marked as ignorable */
378
+ if (item->ignore )
379
+ continue ;
380
+
355
381
/* In SIGHUP cases in the postmaster, we want to report changes */
356
382
if (context == PGC_SIGHUP && !IsUnderPostmaster)
357
383
{
@@ -557,19 +583,25 @@ GUC_flex_fatal(const char *msg)
557
583
* config_file: absolute or relative path name of the configuration file
558
584
* depth: recursion depth (should be 0 in the outermost call)
559
585
* elevel: error logging level to use
560
- * Output parameters:
586
+ * Input/ Output parameters:
561
587
* head_p, tail_p: head and tail of linked list of name/value pairs
562
588
*
563
- * *head_p and *tail_p must be initialized to NULL before calling the outer
564
- * recursion level. On exit, they contain a list of name-value pairs read
565
- * from the input file(s).
589
+ * *head_p and *tail_p must be initialized, either to NULL or valid pointers
590
+ * to a ConfigVariable list, before calling the outer recursion level. Any
591
+ * name-value pairs read from the input file(s) will be appended to the list .
566
592
*
567
593
* Returns TRUE if successful, FALSE if an error occurred. The error has
568
594
* already been ereport'd, it is only necessary for the caller to clean up
569
595
* its own state and release the ConfigVariable list.
570
596
*
571
597
* Note: if elevel >= ERROR then an error will not return control to the
572
598
* caller, so there is no need to check the return value in that case.
599
+ *
600
+ * Note: this function is used to parse not only postgresql.conf, but
601
+ * various other configuration files that use the same "name = value"
602
+ * syntax. Hence, do not do anything here or in the subsidiary routines
603
+ * ParseConfigFile/ParseConfigDirectory that assumes we are processing
604
+ * GUCs specifically.
573
605
*/
574
606
bool
575
607
ParseConfigFp (FILE *fp, const char *config_file, int depth, int elevel,
@@ -658,11 +690,10 @@ ParseConfigFp(FILE *fp, const char *config_file, int depth, int elevel,
658
690
* processed immediately.
659
691
*/
660
692
if (!ParseConfigDirectory (opt_value, config_file,
661
- depth + 1 , elevel,
662
- head_p, tail_p))
693
+ depth + 1 , elevel,
694
+ head_p, tail_p))
663
695
OK = false ;
664
696
yy_switch_to_buffer (lex_buffer);
665
- ConfigFileLineno = save_ConfigFileLineno;
666
697
pfree (opt_name);
667
698
pfree (opt_value);
668
699
}
@@ -702,6 +733,7 @@ ParseConfigFp(FILE *fp, const char *config_file, int depth, int elevel,
702
733
item->value = opt_value;
703
734
item->filename = pstrdup (config_file);
704
735
item->sourceline = ConfigFileLineno-1 ;
736
+ item->ignore = false ;
705
737
item->next = NULL ;
706
738
if (*head_p == NULL )
707
739
*head_p = item;
0 commit comments