diff --git a/contrib/tsearch2/tsearch2.c b/contrib/tsearch2/tsearch2.c
index 143dabba407..4354c5b0904 100644
--- a/contrib/tsearch2/tsearch2.c
+++ b/contrib/tsearch2/tsearch2.c
@@ -363,7 +363,7 @@ tsa_tsearch2(PG_FUNCTION_ARGS)
tgargs[i + 1] = trigger->tgargs[i];
tgargs[1] = pstrdup(GetConfigOptionByName("default_text_search_config",
- NULL));
+ NULL, false));
tgargs_old = trigger->tgargs;
trigger->tgargs = tgargs;
trigger->tgnargs++;
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index 99923f46bca..76f77cb0fcf 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -16444,7 +16444,7 @@ SELECT collation for ('foo' COLLATE "de_DE");
current_setting
- current_setting(setting_name)
+ current_setting(setting_name [, missing_ok ])
text
get current value of setting
@@ -16492,6 +16492,11 @@ SELECT current_setting('datestyle');
ISO, MDY
(1 row)
+
+ If there is no setting named setting_name,
+ current_setting throws an error
+ unless missing_ok is supplied and is
+ true.
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 0356ecb4821..595a609989d 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -7131,7 +7131,7 @@ ExtractSetVariableArgs(VariableSetStmt *stmt)
case VAR_SET_VALUE:
return flatten_set_variable_args(stmt->name, stmt->args);
case VAR_SET_CURRENT:
- return GetConfigOptionByName(stmt->name, NULL);
+ return GetConfigOptionByName(stmt->name, NULL, false);
default:
return NULL;
}
@@ -7200,7 +7200,7 @@ set_config_by_name(PG_FUNCTION_ARGS)
true, 0, false);
/* get the new current value */
- new_value = GetConfigOptionByName(name, NULL);
+ new_value = GetConfigOptionByName(name, NULL, false);
/* Convert return string to text */
PG_RETURN_TEXT_P(cstring_to_text(new_value));
@@ -7627,7 +7627,7 @@ GetPGVariableResultDesc(const char *name)
const char *varname;
/* Get the canonical spelling of name */
- (void) GetConfigOptionByName(name, &varname);
+ (void) GetConfigOptionByName(name, &varname, false);
/* need a tuple descriptor representing a single TEXT column */
tupdesc = CreateTemplateTupleDesc(1, false);
@@ -7650,7 +7650,7 @@ ShowGUCConfigOption(const char *name, DestReceiver *dest)
char *value;
/* Get the value and canonical spelling of name */
- value = GetConfigOptionByName(name, &varname);
+ value = GetConfigOptionByName(name, &varname, false);
/* need a tuple descriptor representing a single TEXT column */
tupdesc = CreateTemplateTupleDesc(1, false);
@@ -7734,19 +7734,30 @@ ShowAllGUCConfig(DestReceiver *dest)
}
/*
- * Return GUC variable value by name; optionally return canonical
- * form of name. Return value is palloc'd.
+ * Return GUC variable value by name; optionally return canonical form of
+ * name. If the GUC is unset, then throw an error unless missing_ok is true,
+ * in which case return NULL. Return value is palloc'd (but *varname isn't).
*/
char *
-GetConfigOptionByName(const char *name, const char **varname)
+GetConfigOptionByName(const char *name, const char **varname, bool missing_ok)
{
struct config_generic *record;
record = find_option(name, false, ERROR);
if (record == NULL)
+ {
+ if (missing_ok)
+ {
+ if (varname)
+ *varname = NULL;
+ return NULL;
+ }
+
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("unrecognized configuration parameter \"%s\"", name)));
+ }
+
if ((record->flags & GUC_SUPERUSER_ONLY) && !superuser())
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
@@ -8033,14 +8044,34 @@ GetNumConfigOptions(void)
Datum
show_config_by_name(PG_FUNCTION_ARGS)
{
- char *varname;
+ char *varname = TextDatumGetCString(PG_GETARG_DATUM(0));
char *varval;
- /* Get the GUC variable name */
- varname = TextDatumGetCString(PG_GETARG_DATUM(0));
+ /* Get the value */
+ varval = GetConfigOptionByName(varname, NULL, false);
+
+ /* Convert to text */
+ PG_RETURN_TEXT_P(cstring_to_text(varval));
+}
+
+/*
+ * show_config_by_name_missing_ok - equiv to SHOW X command but implemented as
+ * a function. If X does not exist, suppress the error and just return NULL
+ * if missing_ok is TRUE.
+ */
+Datum
+show_config_by_name_missing_ok(PG_FUNCTION_ARGS)
+{
+ char *varname = TextDatumGetCString(PG_GETARG_DATUM(0));
+ bool missing_ok = PG_GETARG_BOOL(1);
+ char *varval;
/* Get the value */
- varval = GetConfigOptionByName(varname, NULL);
+ varval = GetConfigOptionByName(varname, NULL, missing_ok);
+
+ /* return NULL if no such variable */
+ if (varval == NULL)
+ PG_RETURN_NULL();
/* Convert to text */
PG_RETURN_TEXT_P(cstring_to_text(varval));
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index 965a53cbfda..44ce2b3a620 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -53,6 +53,6 @@
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 201506282
+#define CATALOG_VERSION_NO 201507021
#endif
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index be3a8fba1be..6fd1278d1b2 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -3067,6 +3067,8 @@ DESCR("convert bitstring to int8");
DATA(insert OID = 2077 ( current_setting PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 25 "25" _null_ _null_ _null_ _null_ _null_ show_config_by_name _null_ _null_ _null_ ));
DESCR("SHOW X as a function");
+DATA(insert OID = 3294 ( current_setting PGNSP PGUID 12 1 0 0 0 f f f f t f s 2 0 25 "25 16" _null_ _null_ _null_ _null_ _null_ show_config_by_name_missing_ok _null_ _null_ _null_ ));
+DESCR("SHOW X as a function, optionally no error for missing variable");
DATA(insert OID = 2078 ( set_config PGNSP PGUID 12 1 0 0 0 f f f f f f v 3 0 25 "25 25 16" _null_ _null_ _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 0 f f f f t t s 0 0 2249 "" "{25,25,25,25,25,25,25,25,25,25,25,1009,25,25,25,23,16}" "{o,o,o,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,boot_val,reset_val,sourcefile,sourceline,pending_restart}" _null_ _null_ show_all_settings _null_ _null_ _null_ ));
@@ -4866,8 +4868,8 @@ DESCR("GIN support");
DATA(insert OID = 3301 ( jsonb_concat PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 3802 "3802 3802" _null_ _null_ _null_ _null_ _null_ jsonb_concat _null_ _null_ _null_ ));
DATA(insert OID = 3302 ( jsonb_delete PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 3802 "3802 25" _null_ _null_ _null_ _null_ _null_ jsonb_delete _null_ _null_ _null_ ));
DATA(insert OID = 3303 ( jsonb_delete PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 3802 "3802 23" _null_ _null_ _null_ _null_ _null_ jsonb_delete_idx _null_ _null_ _null_ ));
-DATA(insert OID = 3304 ( jsonb_delete_path PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 3802 "3802 1009" _null_ _null_ _null_ _null_ _null_ jsonb_delete_path _null_ _null_ _null_ ));
-DATA(insert OID = 3305 ( jsonb_set PGNSP PGUID 12 1 0 0 0 f f f f t f i 4 0 3802 "3802 1009 3802 16" _null_ _null_ _null_ _null_ _null_ jsonb_set _null_ _null_ _null_ ));
+DATA(insert OID = 3304 ( jsonb_delete_path PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 3802 "3802 1009" _null_ _null_ _null_ _null_ _null_ jsonb_delete_path _null_ _null_ _null_ ));
+DATA(insert OID = 3305 ( jsonb_set PGNSP PGUID 12 1 0 0 0 f f f f t f i 4 0 3802 "3802 1009 3802 16" _null_ _null_ _null_ _null_ _null_ jsonb_set _null_ _null_ _null_ ));
DESCR("Set part of a jsonb");
DATA(insert OID = 3306 ( jsonb_pretty PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 25 "3802" _null_ _null_ _null_ _null_ _null_ jsonb_pretty _null_ _null_ _null_ ));
DESCR("Indented text from jsonb");
diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h
index 98556725c8e..fcb0bf0ce8e 100644
--- a/src/include/utils/builtins.h
+++ b/src/include/utils/builtins.h
@@ -1114,6 +1114,7 @@ extern Datum quote_nullable(PG_FUNCTION_ARGS);
/* guc.c */
extern Datum show_config_by_name(PG_FUNCTION_ARGS);
+extern Datum show_config_by_name_missing_ok(PG_FUNCTION_ARGS);
extern Datum set_config_by_name(PG_FUNCTION_ARGS);
extern Datum show_all_settings(PG_FUNCTION_ARGS);
extern Datum show_all_file_settings(PG_FUNCTION_ARGS);
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 49ec3840af3..dc167f9bb5c 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -365,7 +365,8 @@ extern int set_config_option(const char *name, const char *value,
GucAction action, bool changeVal, int elevel,
bool is_reload);
extern void AlterSystemSetConfigFile(AlterSystemStmt *setstmt);
-extern char *GetConfigOptionByName(const char *name, const char **varname);
+extern char *GetConfigOptionByName(const char *name, const char **varname,
+ bool missing_ok);
extern void GetConfigOptionByNum(int varnum, const char **values, bool *noshow);
extern int GetNumConfigOptions(void);
diff --git a/src/test/regress/expected/guc.out b/src/test/regress/expected/guc.out
index 4f0065cb7ef..fdb9b5cddaf 100644
--- a/src/test/regress/expected/guc.out
+++ b/src/test/regress/expected/guc.out
@@ -720,6 +720,37 @@ select myfunc(1), current_setting('work_mem');
2MB | 2MB
(1 row)
+-- check current_setting()'s behavior with invalid setting name
+select current_setting('nosuch.setting'); -- FAIL
+ERROR: unrecognized configuration parameter "nosuch.setting"
+select current_setting('nosuch.setting', false); -- FAIL
+ERROR: unrecognized configuration parameter "nosuch.setting"
+select current_setting('nosuch.setting', true) is null;
+ ?column?
+----------
+ t
+(1 row)
+
+-- after this, all three cases should yield 'nada'
+set nosuch.setting = 'nada';
+select current_setting('nosuch.setting');
+ current_setting
+-----------------
+ nada
+(1 row)
+
+select current_setting('nosuch.setting', false);
+ current_setting
+-----------------
+ nada
+(1 row)
+
+select current_setting('nosuch.setting', true);
+ current_setting
+-----------------
+ nada
+(1 row)
+
-- Normally, CREATE FUNCTION should complain about invalid values in
-- function SET options; but not if check_function_bodies is off,
-- because that creates ordering hazards for pg_dump
diff --git a/src/test/regress/sql/guc.sql b/src/test/regress/sql/guc.sql
index 3de8a6b55d6..6a062a0a5ba 100644
--- a/src/test/regress/sql/guc.sql
+++ b/src/test/regress/sql/guc.sql
@@ -258,6 +258,19 @@ select myfunc(0);
select current_setting('work_mem');
select myfunc(1), current_setting('work_mem');
+-- check current_setting()'s behavior with invalid setting name
+
+select current_setting('nosuch.setting'); -- FAIL
+select current_setting('nosuch.setting', false); -- FAIL
+select current_setting('nosuch.setting', true) is null;
+
+-- after this, all three cases should yield 'nada'
+set nosuch.setting = 'nada';
+
+select current_setting('nosuch.setting');
+select current_setting('nosuch.setting', false);
+select current_setting('nosuch.setting', true);
+
-- Normally, CREATE FUNCTION should complain about invalid values in
-- function SET options; but not if check_function_bodies is off,
-- because that creates ordering hazards for pg_dump