diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index 0ee6974f1c..8754f2f89b 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -23859,6 +23859,43 @@ SELECT currval(pg_get_serial_sequence('sometable', 'id')); + + + + pg_settings_get_flags + + pg_settings_get_flags ( guc text ) + text[] + + + Returns an array of the flags associated with the given GUC, or + NULL if it does not exist. The result is + an empty array if the GUC exists but there are no flags to show. + Only the most useful flags are exposed, as of the following: + + + EXPLAIN: parameters included in + EXPLAIN (SETTINGS) commands. + + + NO_SHOW_ALL: parameters excluded from + SHOW ALL commands. + + + NO_RESET_ALL: parameters excluded from + RESET ALL commands. + + + NOT_IN_SAMPLE: parameters not included in + postgresql.conf by default. + + + RUNTIME_COMPUTED: runtime-computed parameters. + + + + + diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index 4c94f09c64..b3fd42e0f1 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -9634,6 +9634,45 @@ GetConfigOptionByName(const char *name, const char **varname, bool missing_ok) return _ShowOption(record, true); } +/* + * Return some of the flags associated to the specified GUC in the shape of + * a text array, and NULL if it does not exist. An empty array is returned + * if the GUC exists without any meaningful flags to show. + */ +Datum +pg_settings_get_flags(PG_FUNCTION_ARGS) +{ +#define MAX_GUC_FLAGS 5 + char *varname = TextDatumGetCString(PG_GETARG_DATUM(0)); + struct config_generic *record; + int cnt = 0; + Datum flags[MAX_GUC_FLAGS]; + ArrayType *a; + + record = find_option(varname, false, true, ERROR); + + /* return NULL if no such variable */ + if (record == NULL) + PG_RETURN_NULL(); + + if (record->flags & GUC_EXPLAIN) + flags[cnt++] = CStringGetTextDatum("EXPLAIN"); + if (record->flags & GUC_NO_RESET_ALL) + flags[cnt++] = CStringGetTextDatum("NO_RESET_ALL"); + if (record->flags & GUC_NO_SHOW_ALL) + flags[cnt++] = CStringGetTextDatum("NO_SHOW_ALL"); + if (record->flags & GUC_NOT_IN_SAMPLE) + flags[cnt++] = CStringGetTextDatum("NOT_IN_SAMPLE"); + if (record->flags & GUC_RUNTIME_COMPUTED) + flags[cnt++] = CStringGetTextDatum("RUNTIME_COMPUTED"); + + Assert(cnt <= MAX_GUC_FLAGS); + + /* Returns the record as Datum */ + a = construct_array(flags, cnt, TEXTOID, -1, false, TYPALIGN_INT); + PG_RETURN_ARRAYTYPE_P(a); +} + /* * Return GUC variable value by variable number; optionally return canonical * form of name. Return value is palloc'd. diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index 656b6c8f00..6487bf9c0a 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 202201271 +#define CATALOG_VERSION_NO 202201311 #endif diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat index 0859dc81ca..7024dbe10a 100644 --- a/src/include/catalog/pg_proc.dat +++ b/src/include/catalog/pg_proc.dat @@ -6096,6 +6096,11 @@ proargmodes => '{o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}', proargnames => '{name,setting,unit,category,short_desc,extra_desc,context,vartype,source,min_val,max_val,enumvals,boot_val,reset_val,sourcefile,sourceline,pending_restart}', prosrc => 'show_all_settings' }, + +{ oid => '8921', descr => 'return flags for specified GUC', + proname => 'pg_settings_get_flags', provolatile => 's', prorettype => '_text', + proargtypes => 'text', prosrc => 'pg_settings_get_flags' }, + { oid => '3329', descr => 'show config file settings', proname => 'pg_show_all_file_settings', prorows => '1000', proretset => 't', provolatile => 'v', prorettype => 'record', proargtypes => '', diff --git a/src/test/regress/expected/guc.out b/src/test/regress/expected/guc.out index 59da91ff04..75b6bfbf11 100644 --- a/src/test/regress/expected/guc.out +++ b/src/test/regress/expected/guc.out @@ -813,3 +813,86 @@ set default_with_oids to f; -- Should not allow to set it to true. set default_with_oids to t; ERROR: tables declared WITH OIDS are not supported +-- Test GUC categories and flag patterns +SELECT pg_settings_get_flags(NULL); + pg_settings_get_flags +----------------------- + +(1 row) + +SELECT pg_settings_get_flags('does_not_exist'); + pg_settings_get_flags +----------------------- + +(1 row) + +CREATE TABLE tab_settings_flags AS SELECT name, category, + 'EXPLAIN' = ANY(flags) AS explain, + 'NO_RESET_ALL' = ANY(flags) AS no_reset_all, + 'NO_SHOW_ALL' = ANY(flags) AS no_show_all, + 'NOT_IN_SAMPLE' = ANY(flags) AS not_in_sample, + 'RUNTIME_COMPUTED' = ANY(flags) AS runtime_computed + FROM pg_show_all_settings() AS psas, + pg_settings_get_flags(psas.name) AS flags; +-- Developer GUCs should be flagged with GUC_NOT_IN_SAMPLE: +SELECT name FROM tab_settings_flags + WHERE category = 'Developer Options' AND NOT not_in_sample + ORDER BY 1; + name +------ +(0 rows) + +-- Most query-tuning GUCs are flagged as valid for EXPLAIN. +-- default_statistics_target is an exception. +SELECT name FROM tab_settings_flags + WHERE category ~ '^Query Tuning' AND NOT explain + ORDER BY 1; + name +--------------------------- + default_statistics_target +(1 row) + +-- Runtime-computed GUCs should be part of the preset category. +SELECT name FROM tab_settings_flags + WHERE NOT category = 'Preset Options' AND runtime_computed + ORDER BY 1; + name +------ +(0 rows) + +-- Preset GUCs are flagged as NOT_IN_SAMPLE. +SELECT name FROM tab_settings_flags + WHERE category = 'Preset Options' AND NOT not_in_sample + ORDER BY 1; + name +------ +(0 rows) + +-- NO_SHOW_ALL implies NO_RESET_ALL, and vice-versa. +SELECT name FROM tab_settings_flags + WHERE no_show_all AND NOT no_reset_all + ORDER BY 1; + name +------ +(0 rows) + +-- Exceptions are transaction_*. +SELECT name FROM tab_settings_flags + WHERE NOT no_show_all AND no_reset_all + ORDER BY 1; + name +------------------------ + transaction_deferrable + transaction_isolation + transaction_read_only +(3 rows) + +-- NO_SHOW_ALL implies NOT_IN_SAMPLE. +SELECT name FROM tab_settings_flags + WHERE no_show_all AND NOT not_in_sample + ORDER BY 1; + name +------ +(0 rows) + +DROP TABLE tab_settings_flags; diff --git a/src/test/regress/sql/guc.sql b/src/test/regress/sql/guc.sql index c39c11388d..3e2819449c 100644 --- a/src/test/regress/sql/guc.sql +++ b/src/test/regress/sql/guc.sql @@ -311,3 +311,46 @@ reset check_function_bodies; set default_with_oids to f; -- Should not allow to set it to true. set default_with_oids to t; + +-- Test GUC categories and flag patterns +SELECT pg_settings_get_flags(NULL); +SELECT pg_settings_get_flags('does_not_exist'); +CREATE TABLE tab_settings_flags AS SELECT name, category, + 'EXPLAIN' = ANY(flags) AS explain, + 'NO_RESET_ALL' = ANY(flags) AS no_reset_all, + 'NO_SHOW_ALL' = ANY(flags) AS no_show_all, + 'NOT_IN_SAMPLE' = ANY(flags) AS not_in_sample, + 'RUNTIME_COMPUTED' = ANY(flags) AS runtime_computed + FROM pg_show_all_settings() AS psas, + pg_settings_get_flags(psas.name) AS flags; + +-- Developer GUCs should be flagged with GUC_NOT_IN_SAMPLE: +SELECT name FROM tab_settings_flags + WHERE category = 'Developer Options' AND NOT not_in_sample + ORDER BY 1; +-- Most query-tuning GUCs are flagged as valid for EXPLAIN. +-- default_statistics_target is an exception. +SELECT name FROM tab_settings_flags + WHERE category ~ '^Query Tuning' AND NOT explain + ORDER BY 1; +-- Runtime-computed GUCs should be part of the preset category. +SELECT name FROM tab_settings_flags + WHERE NOT category = 'Preset Options' AND runtime_computed + ORDER BY 1; +-- Preset GUCs are flagged as NOT_IN_SAMPLE. +SELECT name FROM tab_settings_flags + WHERE category = 'Preset Options' AND NOT not_in_sample + ORDER BY 1; +-- NO_SHOW_ALL implies NO_RESET_ALL, and vice-versa. +SELECT name FROM tab_settings_flags + WHERE no_show_all AND NOT no_reset_all + ORDER BY 1; +-- Exceptions are transaction_*. +SELECT name FROM tab_settings_flags + WHERE NOT no_show_all AND no_reset_all + ORDER BY 1; +-- NO_SHOW_ALL implies NOT_IN_SAMPLE. +SELECT name FROM tab_settings_flags + WHERE no_show_all AND NOT not_in_sample + ORDER BY 1; +DROP TABLE tab_settings_flags;