/* request an array of relevant settings */
gucs = get_explain_guc_options(&num);
- /* also bail out of there are no options */
- if (!num)
- return;
-
if (es->format != EXPLAIN_FORMAT_TEXT)
{
- int i;
-
ExplainOpenGroup("Settings", "Settings", true, es);
- for (i = 0; i < num; i++)
+ for (int i = 0; i < num; i++)
{
char *setting;
struct config_generic *conf = gucs[i];
}
else
{
- int i;
StringInfoData str;
+ /* In TEXT mode, print nothing if there are no options */
+ if (num <= 0)
+ return;
+
initStringInfo(&str);
- for (i = 0; i < num; i++)
+ for (int i = 0; i < num; i++)
{
char *setting;
struct config_generic *conf = gucs[i];
appendStringInfo(&str, "%s = NULL", conf->name);
}
- if (num > 0)
- ExplainPropertyText("Settings", str.data, es);
+ ExplainPropertyText("Settings", str.data, es);
}
}
/* Current number of variables contained in the vector */
static int num_guc_variables;
-/* Current number of variables marked with GUC_EXPLAIN */
-static int num_guc_explain_variables;
-
/* Vector capacity */
static int size_guc_variables;
{
int size_vars;
int num_vars = 0;
- int num_explain_vars = 0;
struct config_generic **guc_vars;
int i;
/* Rather than requiring vartype to be filled in by hand, do this: */
conf->gen.vartype = PGC_BOOL;
num_vars++;
-
- if (conf->gen.flags & GUC_EXPLAIN)
- num_explain_vars++;
}
for (i = 0; ConfigureNamesInt[i].gen.name; i++)
conf->gen.vartype = PGC_INT;
num_vars++;
-
- if (conf->gen.flags & GUC_EXPLAIN)
- num_explain_vars++;
}
for (i = 0; ConfigureNamesReal[i].gen.name; i++)
conf->gen.vartype = PGC_REAL;
num_vars++;
-
- if (conf->gen.flags & GUC_EXPLAIN)
- num_explain_vars++;
}
for (i = 0; ConfigureNamesString[i].gen.name; i++)
conf->gen.vartype = PGC_STRING;
num_vars++;
-
- if (conf->gen.flags & GUC_EXPLAIN)
- num_explain_vars++;
}
for (i = 0; ConfigureNamesEnum[i].gen.name; i++)
conf->gen.vartype = PGC_ENUM;
num_vars++;
-
- if (conf->gen.flags & GUC_EXPLAIN)
- num_explain_vars++;
}
/*
free(guc_variables);
guc_variables = guc_vars;
num_guc_variables = num_vars;
- num_guc_explain_variables = num_explain_vars;
size_guc_variables = size_vars;
qsort((void *) guc_variables, num_guc_variables,
sizeof(struct config_generic *), guc_var_compare);
}
/*
- * Returns an array of modified GUC options to show in EXPLAIN. Only options
- * related to query planning (marked with GUC_EXPLAIN), with values different
- * from built-in defaults.
+ * Return an array of modified GUC options to show in EXPLAIN.
+ *
+ * We only report options related to query planning (marked with GUC_EXPLAIN),
+ * with values different from their built-in defaults.
*/
struct config_generic **
get_explain_guc_options(int *num)
{
- int i;
struct config_generic **result;
*num = 0;
/*
- * Allocate enough space to fit all GUC_EXPLAIN options. We may not need
- * all the space, but there are fairly few such options so we don't waste
- * a lot of memory.
+ * While only a fraction of all the GUC variables are marked GUC_EXPLAIN,
+ * it doesn't seem worth dynamically resizing this array.
*/
- result = palloc(sizeof(struct config_generic *) * num_guc_explain_variables);
+ result = palloc(sizeof(struct config_generic *) * num_guc_variables);
- for (i = 0; i < num_guc_variables; i++)
+ for (int i = 0; i < num_guc_variables; i++)
{
bool modified;
struct config_generic *conf = guc_variables[i];
- /* return only options visible to the user */
+ /* return only parameters marked for inclusion in explain */
+ if (!(conf->flags & GUC_EXPLAIN))
+ continue;
+
+ /* return only options visible to the current user */
if ((conf->flags & GUC_NO_SHOW_ALL) ||
((conf->flags & GUC_SUPERUSER_ONLY) &&
!is_member_of_role(GetUserId(), DEFAULT_ROLE_READ_ALL_SETTINGS)))
continue;
- /* only parameters explicitly marked for inclusion in explain */
- if (!(conf->flags & GUC_EXPLAIN))
- continue;
-
- /* return only options that were modified (w.r.t. config file) */
+ /* return only options that are different from their boot values */
modified = false;
switch (conf->vartype)
elog(ERROR, "unexpected GUC type: %d", conf->vartype);
}
- /* skip GUC variables that match the built-in default */
if (!modified)
continue;
- /* assign to the values array */
+ /* OK, report it */
result[*num] = conf;
*num = *num + 1;
-
- Assert(*num <= num_guc_explain_variables);
}
return result;
select explain_filter('explain (analyze, buffers, format xml) select * from int8_tbl i8');
select explain_filter('explain (analyze, buffers, format yaml) select * from int8_tbl i8');
+-- SETTINGS option
+-- We have to ignore other settings that might be imposed by the environment,
+-- so printing the whole Settings field unfortunately won't do.
+
+begin;
+set local plan_cache_mode = force_generic_plan;
+select true as "OK"
+ from explain_filter('explain (settings) select * from int8_tbl i8') ln
+ where ln ~ '^ *Settings: .*plan_cache_mode = ''force_generic_plan''';
+select explain_filter_to_json('explain (settings, format json) select * from int8_tbl i8') #> '{0,Settings,plan_cache_mode}';
+rollback;
+
--
-- Test production of per-worker data
--