Tom Lane wrote: > Alvaro Herrera <[EMAIL PROTECTED]> writes: > > Tom Lane wrote:
> > Hmm, I didn't recheck after Greg's patch, but in mine, it doesn't, > > because the location is saved as "reset location" and restored when the > > variable is reset. It worked fine in all cases I tested. > > Hmm. Actually, why is there a need to save and restore at all? There > can certainly never be more than one recorded config-file location per > variable. What about saying that each variable has one and only one > filename/linenumber, but whether these are relevant to the current value > is determined by whether the current value's source is S_FILE? Hmm, this does make the patch a lot simpler. Attached. (Magnus was visionary enough to put the correct test in the pg_settings definition.) I also dropped the change to set_config_option, and added a new routine to set the source file/line, as you suggested elsewhere. The only problem is that we now have two bsearch calls for each option set in a config file ... I don't want to change set_config_option just to be able to return the struct config_generic for this routine's sake ... Better ideas? Is this OK as is? I noticed some weird things when the config files contain errors, but I think it's outside this patch's scope. (I dropped the "default" stuff for now, as it doesn't seem that a consensus has been reached on that topic.) -- Alvaro Herrera http://www.CommandPrompt.com/ PostgreSQL Replication, Consulting, Custom Development, 24x7 support
Index: doc/src/sgml/catalogs.sgml =================================================================== RCS file: /home/alvherre/Code/cvs/pgsql/doc/src/sgml/catalogs.sgml,v retrieving revision 2.172 diff -c -p -r2.172 catalogs.sgml *** doc/src/sgml/catalogs.sgml 30 Jul 2008 17:05:04 -0000 2.172 --- doc/src/sgml/catalogs.sgml 9 Sep 2008 02:42:14 -0000 *************** *** 6414,6419 **** --- 6414,6433 ---- <entry>Allowed values in enum parameters (NULL for non-enum values)</entry> </row> + <row> + <entry><structfield>sourcefile</structfield></entry> + <entry><type>text</type></entry> + <entry>Input file the current value was set from (NULL for values set in + sources other than configuration files). Helpful when using + configuration include directives.</entry> + </row> + <row> + <entry><structfield>sourceline</structfield></entry> + <entry><type>text</type></entry> + <entry>Line number within the sourcefile the current value was set + from (NULL for values set in sources other than configuration files) + </entry> + </row> </tbody> </tgroup> </table> Index: src/backend/utils/misc/guc-file.l =================================================================== RCS file: /home/alvherre/Code/cvs/pgsql/src/backend/utils/misc/guc-file.l,v retrieving revision 1.56 diff -c -p -r1.56 guc-file.l *** src/backend/utils/misc/guc-file.l 22 Aug 2008 00:20:40 -0000 1.56 --- src/backend/utils/misc/guc-file.l 9 Sep 2008 02:09:28 -0000 *************** struct name_value_pair *** 39,44 **** --- 39,46 ---- { char *name; char *value; + char *filename; + int sourceline; struct name_value_pair *next; }; *************** ProcessConfigFile(GucContext context) *** 307,314 **** /* If we got here all the options checked out okay, so apply them. */ for (item = head; item; item = item->next) { ! set_config_option(item->name, item->value, context, ! PGC_S_FILE, GUC_ACTION_SET, true); } /* Remember when we last successfully loaded the config file. */ --- 309,320 ---- /* If we got here all the options checked out okay, so apply them. */ for (item = head; item; item = item->next) { ! if (set_config_option(item->name, item->value, context, ! PGC_S_FILE, GUC_ACTION_SET, true)) ! { ! set_config_sourcefile(item->name, item->filename, ! item->sourceline); ! } } /* Remember when we last successfully loaded the config file. */ *************** ParseConfigFile(const char *config_file, *** 483,488 **** --- 489,496 ---- pfree(item->value); item->name = opt_name; item->value = opt_value; + item->filename = pstrdup(config_file); + item->sourceline = ConfigFileLineno-1; } else { *************** ParseConfigFile(const char *config_file, *** 490,495 **** --- 498,505 ---- item = palloc(sizeof *item); item->name = opt_name; item->value = opt_value; + item->filename = pstrdup(config_file); + item->sourceline = ConfigFileLineno-1; item->next = *head_p; *head_p = item; if (*tail_p == NULL) *************** ParseConfigFile(const char *config_file, *** 502,507 **** --- 512,519 ---- item = palloc(sizeof *item); item->name = opt_name; item->value = opt_value; + item->filename = pstrdup(config_file); + item->sourceline = ConfigFileLineno-1; item->next = NULL; if (*head_p == NULL) *head_p = item; *************** free_name_value_list(struct name_value_p *** 553,558 **** --- 565,571 ---- pfree(item->name); pfree(item->value); + pfree(item->filename); pfree(item); item = next; } Index: src/backend/utils/misc/guc.c =================================================================== RCS file: /home/alvherre/Code/cvs/pgsql/src/backend/utils/misc/guc.c,v retrieving revision 1.470 diff -c -p -r1.470 guc.c *** src/backend/utils/misc/guc.c 25 Aug 2008 15:11:00 -0000 1.470 --- src/backend/utils/misc/guc.c 9 Sep 2008 02:24:27 -0000 *************** extern bool optimize_bounded_sort; *** 129,134 **** --- 129,136 ---- extern char *SSLCipherSuites; #endif + static void set_config_sourcefile(const char *name, char *sourcefile, + int sourceline); static const char *assign_log_destination(const char *value, bool doit, GucSource source); *************** InitializeGUCOptions(void) *** 3200,3205 **** --- 3202,3209 ---- gconf->reset_source = PGC_S_DEFAULT; gconf->source = PGC_S_DEFAULT; gconf->stack = NULL; + gconf->sourcefile = NULL; + gconf->sourceline = 0; switch (gconf->vartype) { *************** ResetAllOptions(void) *** 3541,3547 **** PGC_S_SESSION)) elog(ERROR, "failed to reset %s", conf->gen.name); *conf->variable = conf->reset_val; - conf->gen.source = conf->gen.reset_source; break; } case PGC_INT: --- 3545,3550 ---- *************** ResetAllOptions(void) *** 3553,3559 **** PGC_S_SESSION)) elog(ERROR, "failed to reset %s", conf->gen.name); *conf->variable = conf->reset_val; - conf->gen.source = conf->gen.reset_source; break; } case PGC_REAL: --- 3556,3561 ---- *************** ResetAllOptions(void) *** 3565,3571 **** PGC_S_SESSION)) elog(ERROR, "failed to reset %s", conf->gen.name); *conf->variable = conf->reset_val; - conf->gen.source = conf->gen.reset_source; break; } case PGC_STRING: --- 3567,3572 ---- *************** ResetAllOptions(void) *** 3594,3600 **** } set_string_field(conf, conf->variable, str); - conf->gen.source = conf->gen.reset_source; break; } case PGC_ENUM: --- 3595,3600 ---- *************** ResetAllOptions(void) *** 3606,3616 **** PGC_S_SESSION)) elog(ERROR, "failed to reset %s", conf->gen.name); *conf->variable = conf->reset_val; - conf->gen.source = conf->gen.reset_source; break; } } if (gconf->flags & GUC_REPORT) ReportGUCOption(gconf); } --- 3606,3617 ---- PGC_S_SESSION)) elog(ERROR, "failed to reset %s", conf->gen.name); *conf->variable = conf->reset_val; break; } } + gconf->source = gconf->reset_source; + if (gconf->flags & GUC_REPORT) ReportGUCOption(gconf); } *************** set_config_option(const char *name, cons *** 5108,5116 **** --- 5109,5146 ---- /* + * Set the fields for source file and line number the setting came from. + */ + static void + set_config_sourcefile(const char *name, char *sourcefile, int sourceline) + { + struct config_generic *record; + int elevel; + + /* + * To avoid cluttering the log, only the postmaster bleats loudly + * about problems with the config file. + */ + elevel = IsUnderPostmaster ? DEBUG3 : LOG; + + record = find_option(name, true, elevel); + /* should not happen */ + if (record == NULL) + elog(ERROR, "unrecognized configuration parameter \"%s\"", name); + + if (record->sourcefile) + free(record->sourcefile); + record->sourcefile = guc_strdup(elevel, sourcefile); + record->sourceline = sourceline; + } + + /* * Set a config option to the given value. See also set_config_option, * this is just the wrapper to be called from outside GUC. NB: this * is used only for non-transactional operations. + * + * Note: there is no support here for setting source file/line, as it + * is currently not needed. */ void SetConfigOption(const char *name, const char *value, *************** GetConfigOptionByNum(int varnum, const c *** 6144,6149 **** --- 6174,6192 ---- } break; } + + /* If the setting came from a config file, set the source location */ + if (conf->source == PGC_S_FILE) + { + values[12] = conf->sourcefile; + snprintf(buffer, sizeof(buffer), "%d", conf->sourceline); + values[13] = pstrdup(buffer); + } + else + { + values[12] = NULL; + values[13] = NULL; + } } /* *************** show_config_by_name(PG_FUNCTION_ARGS) *** 6179,6185 **** * show_all_settings - equiv to SHOW ALL command but implemented as * a Table Function. */ ! #define NUM_PG_SETTINGS_ATTS 12 Datum show_all_settings(PG_FUNCTION_ARGS) --- 6222,6228 ---- * show_all_settings - equiv to SHOW ALL command but implemented as * a Table Function. */ ! #define NUM_PG_SETTINGS_ATTS 14 Datum show_all_settings(PG_FUNCTION_ARGS) *************** show_all_settings(PG_FUNCTION_ARGS) *** 6231,6236 **** --- 6274,6283 ---- TEXTOID, -1, 0); TupleDescInitEntry(tupdesc, (AttrNumber) 12, "enumvals", TEXTOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 13, "sourcefile", + TEXTOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 14, "sourceline", + INT4OID, -1, 0); /* * Generate attribute metadata needed later to produce tuples from raw Index: src/include/catalog/pg_proc.h =================================================================== RCS file: /home/alvherre/Code/cvs/pgsql/src/include/catalog/pg_proc.h,v retrieving revision 1.513 diff -c -p -r1.513 pg_proc.h *** src/include/catalog/pg_proc.h 6 Sep 2008 00:01:24 -0000 1.513 --- src/include/catalog/pg_proc.h 9 Sep 2008 00:11:29 -0000 *************** DATA(insert OID = 2077 ( current_settin *** 3159,3165 **** DESCR("SHOW X as a function"); DATA(insert OID = 2078 ( set_config PGNSP PGUID 12 1 0 0 f f f f v 3 25 "25 25 16" _null_ _null_ _null_ set_config_by_name _null_ _null_ _null_ )); DESCR("SET X as a function"); ! DATA(insert OID = 2084 ( pg_show_all_settings PGNSP PGUID 12 1 1000 0 f f t t s 0 2249 "" "{25,25,25,25,25,25,25,25,25,25,25,25}" "{o,o,o,o,o,o,o,o,o,o,o,o}" "{name,setting,unit,category,short_desc,extra_desc,context,vartype,source,min_val,max_val,enumvals}" show_all_settings _null_ _null_ _null_ )); DESCR("SHOW ALL as a function"); DATA(insert OID = 1371 ( pg_lock_status PGNSP PGUID 12 1 1000 0 f f t t v 0 2249 "" "{25,26,26,23,21,25,28,26,26,21,25,23,25,16}" "{o,o,o,o,o,o,o,o,o,o,o,o,o,o}" "{locktype,database,relation,page,tuple,virtualxid,transactionid,classid,objid,objsubid,virtualtransaction,pid,mode,granted}" pg_lock_status _null_ _null_ _null_ )); DESCR("view system lock information"); --- 3159,3165 ---- DESCR("SHOW X as a function"); DATA(insert OID = 2078 ( set_config PGNSP PGUID 12 1 0 0 f f f f v 3 25 "25 25 16" _null_ _null_ _null_ set_config_by_name _null_ _null_ _null_ )); DESCR("SET X as a function"); ! DATA(insert OID = 2084 ( pg_show_all_settings PGNSP PGUID 12 1 1000 0 f f t t s 0 2249 "" "{25,25,25,25,25,25,25,25,25,25,25,25,25,23}" "{o,o,o,o,o,o,o,o,o,o,o,o,o,o}" "{name,setting,unit,category,short_desc,extra_desc,context,vartype,source,min_val,max_val,enumvals,sourcefile,sourceline}" show_all_settings _null_ _null_ _null_ )); DESCR("SHOW ALL as a function"); DATA(insert OID = 1371 ( pg_lock_status PGNSP PGUID 12 1 1000 0 f f t t v 0 2249 "" "{25,26,26,23,21,25,28,26,26,21,25,23,25,16}" "{o,o,o,o,o,o,o,o,o,o,o,o,o,o}" "{locktype,database,relation,page,tuple,virtualxid,transactionid,classid,objid,objsubid,virtualtransaction,pid,mode,granted}" pg_lock_status _null_ _null_ _null_ )); DESCR("view system lock information"); Index: src/include/utils/guc_tables.h =================================================================== RCS file: /home/alvherre/Code/cvs/pgsql/src/include/utils/guc_tables.h,v retrieving revision 1.41 diff -c -p -r1.41 guc_tables.h *** src/include/utils/guc_tables.h 17 Mar 2008 17:45:09 -0000 1.41 --- src/include/utils/guc_tables.h 9 Sep 2008 00:23:27 -0000 *************** struct config_generic *** 126,131 **** --- 126,133 ---- GucSource reset_source; /* source of the reset_value */ GucSource source; /* source of the current actual value */ GucStack *stack; /* stacked prior values */ + char *sourcefile; /* file this settings is from (NULL if not file) */ + int sourceline; /* line in source file */ }; /* bit values in flags field */ Index: src/test/regress/expected/rules.out =================================================================== RCS file: /home/alvherre/Code/cvs/pgsql/src/test/regress/expected/rules.out,v retrieving revision 1.141 diff -c -p -r1.141 rules.out *** src/test/regress/expected/rules.out 25 Aug 2008 11:18:43 -0000 1.141 --- src/test/regress/expected/rules.out 9 Sep 2008 00:11:29 -0000 *************** SELECT viewname, definition FROM pg_view *** 1287,1293 **** pg_prepared_xacts | SELECT p.transaction, p.gid, p.prepared, u.rolname AS owner, d.datname AS database FROM ((pg_prepared_xact() p(transaction, gid, prepared, ownerid, dbid) LEFT JOIN pg_authid u ON ((p.ownerid = u.oid))) LEFT JOIN pg_database d ON ((p.dbid = d.oid))); pg_roles | SELECT pg_authid.rolname, pg_authid.rolsuper, pg_authid.rolinherit, pg_authid.rolcreaterole, pg_authid.rolcreatedb, pg_authid.rolcatupdate, pg_authid.rolcanlogin, pg_authid.rolconnlimit, '********'::text AS rolpassword, pg_authid.rolvaliduntil, pg_authid.rolconfig, pg_authid.oid FROM pg_authid; pg_rules | SELECT n.nspname AS schemaname, c.relname AS tablename, r.rulename, pg_get_ruledef(r.oid) AS definition FROM ((pg_rewrite r JOIN pg_class c ON ((c.oid = r.ev_class))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) WHERE (r.rulename <> '_RETURN'::name); ! pg_settings | SELECT a.name, a.setting, a.unit, a.category, a.short_desc, a.extra_desc, a.context, a.vartype, a.source, a.min_val, a.max_val, a.enumvals FROM pg_show_all_settings() a(name, setting, unit, category, short_desc, extra_desc, context, vartype, source, min_val, max_val, enumvals); pg_shadow | SELECT pg_authid.rolname AS usename, pg_authid.oid AS usesysid, pg_authid.rolcreatedb AS usecreatedb, pg_authid.rolsuper AS usesuper, pg_authid.rolcatupdate AS usecatupd, pg_authid.rolpassword AS passwd, (pg_authid.rolvaliduntil)::abstime AS valuntil, pg_authid.rolconfig AS useconfig FROM pg_authid WHERE pg_authid.rolcanlogin; pg_stat_activity | SELECT s.datid, d.datname, s.procpid, s.usesysid, u.rolname AS usename, s.current_query, s.waiting, s.xact_start, s.query_start, s.backend_start, s.client_addr, s.client_port FROM pg_database d, pg_stat_get_activity(NULL::integer) s(datid, procpid, usesysid, current_query, waiting, xact_start, query_start, backend_start, client_addr, client_port), pg_authid u WHERE ((s.datid = d.oid) AND (s.usesysid = u.oid)); pg_stat_all_indexes | SELECT c.oid AS relid, i.oid AS indexrelid, n.nspname AS schemaname, c.relname, i.relname AS indexrelname, pg_stat_get_numscans(i.oid) AS idx_scan, pg_stat_get_tuples_returned(i.oid) AS idx_tup_read, pg_stat_get_tuples_fetched(i.oid) AS idx_tup_fetch FROM (((pg_class c JOIN pg_index x ON ((c.oid = x.indrelid))) JOIN pg_class i ON ((i.oid = x.indexrelid))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) WHERE (c.relkind = ANY (ARRAY['r'::"char", 't'::"char"])); --- 1287,1293 ---- pg_prepared_xacts | SELECT p.transaction, p.gid, p.prepared, u.rolname AS owner, d.datname AS database FROM ((pg_prepared_xact() p(transaction, gid, prepared, ownerid, dbid) LEFT JOIN pg_authid u ON ((p.ownerid = u.oid))) LEFT JOIN pg_database d ON ((p.dbid = d.oid))); pg_roles | SELECT pg_authid.rolname, pg_authid.rolsuper, pg_authid.rolinherit, pg_authid.rolcreaterole, pg_authid.rolcreatedb, pg_authid.rolcatupdate, pg_authid.rolcanlogin, pg_authid.rolconnlimit, '********'::text AS rolpassword, pg_authid.rolvaliduntil, pg_authid.rolconfig, pg_authid.oid FROM pg_authid; pg_rules | SELECT n.nspname AS schemaname, c.relname AS tablename, r.rulename, pg_get_ruledef(r.oid) AS definition FROM ((pg_rewrite r JOIN pg_class c ON ((c.oid = r.ev_class))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) WHERE (r.rulename <> '_RETURN'::name); ! pg_settings | SELECT a.name, a.setting, a.unit, a.category, a.short_desc, a.extra_desc, a.context, a.vartype, a.source, a.min_val, a.max_val, a.enumvals, a.sourcefile, a.sourceline FROM pg_show_all_settings() a(name, setting, unit, category, short_desc, extra_desc, context, vartype, source, min_val, max_val, enumvals, sourcefile, sourceline); pg_shadow | SELECT pg_authid.rolname AS usename, pg_authid.oid AS usesysid, pg_authid.rolcreatedb AS usecreatedb, pg_authid.rolsuper AS usesuper, pg_authid.rolcatupdate AS usecatupd, pg_authid.rolpassword AS passwd, (pg_authid.rolvaliduntil)::abstime AS valuntil, pg_authid.rolconfig AS useconfig FROM pg_authid WHERE pg_authid.rolcanlogin; pg_stat_activity | SELECT s.datid, d.datname, s.procpid, s.usesysid, u.rolname AS usename, s.current_query, s.waiting, s.xact_start, s.query_start, s.backend_start, s.client_addr, s.client_port FROM pg_database d, pg_stat_get_activity(NULL::integer) s(datid, procpid, usesysid, current_query, waiting, xact_start, query_start, backend_start, client_addr, client_port), pg_authid u WHERE ((s.datid = d.oid) AND (s.usesysid = u.oid)); pg_stat_all_indexes | SELECT c.oid AS relid, i.oid AS indexrelid, n.nspname AS schemaname, c.relname, i.relname AS indexrelname, pg_stat_get_numscans(i.oid) AS idx_scan, pg_stat_get_tuples_returned(i.oid) AS idx_tup_read, pg_stat_get_tuples_fetched(i.oid) AS idx_tup_fetch FROM (((pg_class c JOIN pg_index x ON ((c.oid = x.indrelid))) JOIN pg_class i ON ((i.oid = x.indexrelid))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) WHERE (c.relkind = ANY (ARRAY['r'::"char", 't'::"char"]));
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers