From d10e41d4238e7dcd23968230939c0c59cbcb41c2 Mon Sep 17 00:00:00 2001 From: Michael Paquier Date: Mon, 31 Jan 2022 08:56:41 +0900 Subject: [PATCH] Introduce pg_settings_get_flags() to find flags associated to a GUC The most meaningful flags are shown, which are the ones useful for the user and for automating and extending the set of tests supported currently by check_guc. This script may actually be removed in the future, but we are not completely sure yet if and how we want to support the remaining sanity checks performed there, that are now integrated in the main regression test suite as of this commit. Thanks also to Peter Eisentraut and Kyotaro Horiguchi for the discussion. Bump catalog version. Author: Justin Pryzby Discussion: https://postgr.es/m/20211129030833.GJ17618@telsasoft.com --- doc/src/sgml/func.sgml | 37 ++++++++++++++ src/backend/utils/misc/guc.c | 39 +++++++++++++++ src/include/catalog/catversion.h | 2 +- src/include/catalog/pg_proc.dat | 5 ++ src/test/regress/expected/guc.out | 83 +++++++++++++++++++++++++++++++ src/test/regress/sql/guc.sql | 43 ++++++++++++++++ 6 files changed, 208 insertions(+), 1 deletion(-) 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; -- 2.30.2