44 *
55 * Copyright (c) 2000-2007, PostgreSQL Global Development Group
66 *
7- * $PostgreSQL: pgsql/src/backend/utils/misc/guc-file.l,v 1.47 2007/02/10 14:58:55 petere Exp $
7+ * $PostgreSQL: pgsql/src/backend/utils/misc/guc-file.l,v 1.48 2007/03/12 22:09:27 petere Exp $
88 */
99
1010%{
@@ -54,6 +54,8 @@ static bool ParseConfigFile(const char *config_file, const char *calling_file,
5454static void free_name_value_list (struct name_value_pair * list);
5555static char *GUC_scanstr (const char *s);
5656
57+ static char *custom_variable_classes_backup;
58+
5759%}
5860
5961%option 8bit
@@ -116,6 +118,10 @@ ProcessConfigFile(GucContext context)
116118{
117119 int elevel;
118120 struct name_value_pair *item, *head, *tail;
121+ int i;
122+ bool *in_conffile = NULL;
123+ const char *var;
124+ bool success = false;
119125
120126 Assert(context == PGC_POSTMASTER || context == PGC_SIGHUP);
121127
@@ -132,6 +138,18 @@ ProcessConfigFile(GucContext context)
132138
133139 head = tail = NULL;
134140
141+ /*
142+ * We do not know whether we will read the configuration file
143+ * without error. If we encounter an error we have to restore the
144+ * previous value of the custom_variable_classes variable for
145+ * consistency. Therefore we have to save its value.
146+ */
147+ var = GetConfigOption("custom_variable_classes");
148+ if (var)
149+ custom_variable_classes_backup = pstrdup(var);
150+ set_config_option("custom_variable_classes", NULL, context,
151+ PGC_S_DEFAULT, false, true);
152+
135153 if (!ParseConfigFile(ConfigFileName, NULL,
136154 0, context, elevel,
137155 &head, &tail))
@@ -140,20 +158,198 @@ ProcessConfigFile(GucContext context)
140158 /* Check if all options are valid */
141159 for (item = head; item; item = item->next)
142160 {
161+ char *sep = strchr(item->name, GUC_QUALIFIER_SEPARATOR);
162+ if (sep && !is_custom_class(item->name, sep - item->name))
163+ {
164+ ereport(elevel,
165+ (errcode(ERRCODE_UNDEFINED_OBJECT),
166+ errmsg("unrecognized configuration parameter \" %s\" ",
167+ item->name)));
168+ goto cleanup_list;
169+ }
170+
143171 if (!set_config_option(item->name, item->value, context,
144172 PGC_S_FILE, false, false))
145173 goto cleanup_list;
146174 }
147175
148- /* If we got here all the options checked out okay, so apply them. */
176+
177+ /*
178+ * Mark all variables as not showing up in the config file. The
179+ * allocation has to take place after ParseConfigFile() since this
180+ * function can change num_guc_variables due to custom variables.
181+ * It would be easier to add a new field or status bit to struct
182+ * conf_generic, but that way we would expose internal information
183+ * that is just needed here in the following few lines. The price
184+ * to pay for this separation are a few more loops over the set of
185+ * configuration options, but those are expected to be rather few
186+ * and we only have to pay the cost at SIGHUP. We initialize
187+ * in_conffile only here because set_config_option() makes
188+ * guc_variables grow with custom variables.
189+ */
190+ in_conffile = guc_malloc(elevel, num_guc_variables * sizeof(bool));
191+ if (!in_conffile)
192+ goto cleanup_list;
193+ for (i = 0; i < num_guc_variables; i++)
194+ in_conffile[i] = false;
195+
149196 for (item = head; item; item = item->next)
150197 {
198+ /*
199+ * After set_config_option() the variable name item->name is
200+ * known to exist.
201+ */
202+ Assert(guc_get_index(item->name) >= 0);
203+ in_conffile[guc_get_index(item->name)] = true;
204+ }
205+
206+ for (i = 0; i < num_guc_variables; i++)
207+ {
208+ struct config_generic *gconf = guc_variables[i];
209+ if (!in_conffile[i] && strchr(gconf->name, GUC_QUALIFIER_SEPARATOR))
210+ {
211+ /* handle custom variables here */
212+ int j;
213+
214+ /*
215+ * guc_delete_variable will re-sort the array of
216+ * configuration options and decrease num_guc_variables by
217+ * one.
218+ */
219+ guc_delete_custom_variable(gconf->name);
220+
221+ /*
222+ * Since the array is always sorted we just have to shift
223+ * all boolean values after position i by one position to
224+ * the left.
225+ */
226+ for (j = i; j < num_guc_variables; j++)
227+ in_conffile[j] = in_conffile[j+1];
228+
229+ /*
230+ * Decrease the loop variable to re-test the entry at the
231+ * current position that is now a different one.
232+ */
233+ i--;
234+
235+ continue;
236+ }
237+ else if (!in_conffile[i] && gconf->source == PGC_S_FILE)
238+ {
239+ if (gconf->context < PGC_SIGHUP)
240+ ereport(elevel,
241+ (errcode(ERRCODE_CANT_CHANGE_RUNTIME_PARAM),
242+ errmsg("parameter \" %s\" cannot be changed after server start; configuration file change ignored",
243+ gconf->name)));
244+ else
245+ {
246+ /* prepare */
247+ GucStack *stack;
248+ if (gconf->reset_source == PGC_S_FILE)
249+ gconf->reset_source = PGC_S_DEFAULT;
250+ for (stack = gconf->stack; stack; stack = stack->prev)
251+ if (stack->source == PGC_S_FILE)
252+ stack->source = PGC_S_DEFAULT;
253+ /* apply the default */
254+ set_config_option(gconf->name, NULL, context,
255+ PGC_S_DEFAULT, false, true);
256+ }
257+ }
258+ else if (!in_conffile[i] && gconf->reset_source == PGC_S_FILE)
259+ {
260+ /*------
261+ * Change the reset_val to default_val. Here' s an
262+ * example: In the configuration file we have
263+ *
264+ * seq_page_cost = 3.00
265+ *
266+ * Now we execute in a session
267+ *
268+ * SET seq_page_cost TO 4.00 ;
269+ *
270+ * Then we remove this option from the configuration file
271+ * and send SIGHUP. Now when you execute
272+ *
273+ * RESET seq_page_cost;
274+ *
275+ * it should fall back to 1.00 (the default value for
276+ * seq_page_cost) and not to 3.00 (which is the current
277+ * reset_val).
278+ */
279+
280+ switch (gconf->vartype)
281+ {
282+ case PGC_BOOL:
283+ {
284+ struct config_bool *conf;
285+ conf = (struct config_bool *) gconf;
286+ conf->reset_val = conf->boot_val ;
287+ break ;
288+ }
289+ case PGC_INT:
290+ {
291+ struct config_int *conf;
292+ conf = (struct config_int *) gconf;
293+ conf->reset_val = conf->boot_val ;
294+ break ;
295+ }
296+ case PGC_REAL:
297+ {
298+ struct config_real *conf;
299+ conf = (struct config_real *) gconf;
300+ conf->reset_val = conf->boot_val ;
301+ break ;
302+ }
303+ case PGC_STRING:
304+ {
305+ struct config_string *conf;
306+ conf = (struct config_string *) gconf;
307+ /*
308+ * We can cast away the const here because we
309+ * won't free the address. It is protected by
310+ * set_string_field() and string_field_used().
311+ */
312+ conf->reset_val = (char *) conf->boot_val ;
313+ break ;
314+ }
315+ }
316+ }
317+ }
318+
319+ /* If we got here all the options checked out okay, so apply them. */
320+ for (item = head; item; item = item->next)
151321 set_config_option (item->name, item->value, context,
152322 PGC_S_FILE, false , true );
153- }
323+
324+ /*
325+ * Reset variables to the value of environment variables
326+ * (PGC_S_ENV_VAR overrules PGC_S_FILE). PGPORT is ignored,
327+ * because it cannot be changed without restart.
328+ */
329+ var = getenv(" PGDATESTYLE" );
330+ if (var != NULL )
331+ set_config_option (" datestyle" , var, context,
332+ PGC_S_ENV_VAR, false , true );
333+
334+ var = getenv(" PGCLIENTENCODING" );
335+ if (var != NULL )
336+ set_config_option (" client_encoding" , var, context,
337+ PGC_S_ENV_VAR, false , true );
338+
339+ success = true ;
154340
155341 cleanup_list:
342+ free (in_conffile);
156343 free_name_value_list (head);
344+ if (!success)
345+ set_config_option (" custom_variable_classes" ,
346+ custom_variable_classes_backup,
347+ context, PGC_S_FILE, false , true );
348+ if (custom_variable_classes_backup)
349+ {
350+ pfree (custom_variable_classes_backup);
351+ custom_variable_classes_backup = NULL ;
352+ }
157353}
158354
159355
@@ -312,14 +508,14 @@ ParseConfigFile(const char *config_file, const char *calling_file,
312508 {
313509 pfree (opt_name);
314510 pfree (opt_value);
315- /* we assume error message was logged already */
511+
512+ /* We assume the error message was logged already. */
316513 OK = false ;
317514 goto cleanup_exit;
318515 }
319- pfree (opt_name);
320- pfree (opt_value);
321516 }
322- else
517+
518+ if (pg_strcasecmp (opt_name, " include" ) != 0 )
323519 {
324520 /* append to list */
325521 struct name_value_pair *item;
0 commit comments