Introduce pg_settings_get_flags() to find flags associated to a GUC
authorMichael Paquier <[email protected]>
Sun, 30 Jan 2022 23:56:41 +0000 (08:56 +0900)
committerMichael Paquier <[email protected]>
Sun, 30 Jan 2022 23:56:41 +0000 (08:56 +0900)
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[email protected]

doc/src/sgml/func.sgml
src/backend/utils/misc/guc.c
src/include/catalog/catversion.h
src/include/catalog/pg_proc.dat
src/test/regress/expected/guc.out
src/test/regress/sql/guc.sql

index 0ee6974f1c6466927219bf618547419afb4a0149..8754f2f89b61b14209d780632d3c956e7c48bfad 100644 (file)
@@ -23859,6 +23859,43 @@ SELECT currval(pg_get_serial_sequence('sometable', 'id'));
        </para></entry>
       </row>
 
+      <row>
+       <entry role="func_table_entry"><para role="func_signature">
+        <indexterm>
+         <primary>pg_settings_get_flags</primary>
+        </indexterm>
+        <function>pg_settings_get_flags</function> ( <parameter>guc</parameter> <type>text</type> )
+        <returnvalue>text[]</returnvalue>
+       </para>
+       <para>
+        Returns an array of the flags associated with the given GUC, or
+        <literal>NULL</literal> 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:
+        <simplelist>
+         <member>
+          <literal>EXPLAIN</literal>: parameters included in
+          <command>EXPLAIN (SETTINGS)</command> commands.
+         </member>
+         <member>
+          <literal>NO_SHOW_ALL</literal>: parameters excluded from
+          <command>SHOW ALL</command> commands.
+         </member>
+         <member>
+          <literal>NO_RESET_ALL</literal>: parameters excluded from
+          <command>RESET ALL</command> commands.
+         </member>
+         <member>
+          <literal>NOT_IN_SAMPLE</literal>: parameters not included in
+          <filename>postgresql.conf</filename> by default.
+         </member>
+         <member>
+          <literal>RUNTIME_COMPUTED</literal>: runtime-computed parameters.
+         </member>
+        </simplelist>
+       </para></entry>
+      </row>
+      
       <row>
        <entry role="func_table_entry"><para role="func_signature">
         <indexterm>
index 4c94f09c645132d918827fd0a3eee56b5e5bf0bf..b3fd42e0f185eca184071fdd5902b654a7b1f302 100644 (file)
@@ -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.
index 656b6c8f00e4895bacfab1df27ccd713d4f2d3e0..6487bf9c0a0638a0d5205bc8a5ba608847d6addb 100644 (file)
@@ -53,6 +53,6 @@
  */
 
 /*                                                     yyyymmddN */
-#define CATALOG_VERSION_NO     202201271
+#define CATALOG_VERSION_NO     202201311
 
 #endif
index 0859dc81cac843082536be666928c00e79cc54b3..7024dbe10a2144e30b87a1885a7c9d17dfd55ede 100644 (file)
   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 => '',
index 59da91ff04de6854dbc549e2d6b76ab0ac79f4c7..75b6bfbf116ae8d7de77b2aa13da597e871ec03f 100644 (file)
@@ -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;
index c39c11388d51f9d54952107bfe1b44aa9a7bc378..3e2819449c26e31eef945c79c0a77207f9752f69 100644 (file)
@@ -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;