aboutsummaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
authorJoe Conway <mail@joeconway.com>2016-02-17 09:12:06 -0800
committerJoe Conway <mail@joeconway.com>2016-02-17 09:12:06 -0800
commita5c43b886942e96ec5c745041f2d6a50c3205147 (patch)
treeb7d1967286366131bc65d34457fb0ba91ec710b8 /src/backend
parentf1f5ec1efafe74ca45e24e0bf3371b1d6985c8ee (diff)
downloadpostgresql-a5c43b886942e96ec5c745041f2d6a50c3205147.tar.gz
postgresql-a5c43b886942e96ec5c745041f2d6a50c3205147.zip
Add new system view, pg_config
Move and refactor the underlying code for the pg_config client application to src/common in support of sharing it with a new system information SRF called pg_config() which makes the same information available via SQL. Additionally wrap the SRF with a new system view, as called pg_config. Patch by me with extensive input and review by Michael Paquier and additional review by Alvaro Herrera.
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/catalog/system_views.sql6
-rw-r--r--src/backend/utils/misc/Makefile4
-rw-r--r--src/backend/utils/misc/pg_config.c103
3 files changed, 111 insertions, 2 deletions
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index 923fe589d5e..abf9a7007c5 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -433,6 +433,12 @@ CREATE VIEW pg_timezone_abbrevs AS
CREATE VIEW pg_timezone_names AS
SELECT * FROM pg_timezone_names();
+CREATE VIEW pg_config AS
+ SELECT * FROM pg_config();
+
+REVOKE ALL on pg_config FROM PUBLIC;
+REVOKE EXECUTE ON FUNCTION pg_config() FROM PUBLIC;
+
-- Statistics views
CREATE VIEW pg_stat_all_tables AS
diff --git a/src/backend/utils/misc/Makefile b/src/backend/utils/misc/Makefile
index 788910157de..a0c82c17438 100644
--- a/src/backend/utils/misc/Makefile
+++ b/src/backend/utils/misc/Makefile
@@ -14,8 +14,8 @@ include $(top_builddir)/src/Makefile.global
override CPPFLAGS := -I. -I$(srcdir) $(CPPFLAGS)
-OBJS = guc.o help_config.o pg_rusage.o ps_status.o rls.o \
- sampling.o superuser.o timeout.o tzparser.o
+OBJS = guc.o help_config.o pg_config.o pg_rusage.o \
+ ps_status.o rls.o sampling.o superuser.o timeout.o tzparser.o
# This location might depend on the installation directories. Therefore
# we can't subsitute it into pg_config.h.
diff --git a/src/backend/utils/misc/pg_config.c b/src/backend/utils/misc/pg_config.c
new file mode 100644
index 00000000000..3d6b9f27c08
--- /dev/null
+++ b/src/backend/utils/misc/pg_config.c
@@ -0,0 +1,103 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_config.c
+ * Expose same output as pg_config except as an SRF
+ *
+ * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/backend/utils/misc/pg_config.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#include "funcapi.h"
+#include "miscadmin.h"
+#include "catalog/pg_type.h"
+#include "common/config_info.h"
+#include "utils/builtins.h"
+#include "utils/elog.h"
+#include "port.h"
+
+Datum
+pg_config(PG_FUNCTION_ARGS)
+{
+ ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
+ Tuplestorestate *tupstore;
+ HeapTuple tuple;
+ TupleDesc tupdesc;
+ AttInMetadata *attinmeta;
+ MemoryContext per_query_ctx;
+ MemoryContext oldcontext;
+ ConfigData *configdata;
+ size_t configdata_len;
+ char *values[2];
+ int i = 0;
+
+ /* check to see if caller supports us returning a tuplestore */
+ if (!rsinfo || !(rsinfo->allowedModes & SFRM_Materialize))
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("materialize mode required, but it is not "
+ "allowed in this context")));
+
+ per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
+ oldcontext = MemoryContextSwitchTo(per_query_ctx);
+
+ /* get the requested return tuple description */
+ tupdesc = CreateTupleDescCopy(rsinfo->expectedDesc);
+
+ /*
+ * Check to make sure we have a reasonable tuple descriptor
+ */
+ if (tupdesc->natts != 2 ||
+ tupdesc->attrs[0]->atttypid != TEXTOID ||
+ tupdesc->attrs[1]->atttypid != TEXTOID)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("query-specified return tuple and "
+ "function return type are not compatible")));
+
+ /* OK to use it */
+ attinmeta = TupleDescGetAttInMetadata(tupdesc);
+
+ /* let the caller know we're sending back a tuplestore */
+ rsinfo->returnMode = SFRM_Materialize;
+
+ /* initialize our tuplestore */
+ tupstore = tuplestore_begin_heap(true, false, work_mem);
+
+ configdata = get_configdata(my_exec_path, &configdata_len);
+ for (i = 0; i < configdata_len; i++)
+ {
+ values[0] = configdata[i].name;
+ values[1] = configdata[i].setting;
+
+ tuple = BuildTupleFromCStrings(attinmeta, values);
+ tuplestore_puttuple(tupstore, tuple);
+ }
+
+ /*
+ * no longer need the tuple descriptor reference created by
+ * TupleDescGetAttInMetadata()
+ */
+ ReleaseTupleDesc(tupdesc);
+
+ tuplestore_donestoring(tupstore);
+ rsinfo->setResult = tupstore;
+
+ /*
+ * SFRM_Materialize mode expects us to return a NULL Datum. The actual
+ * tuples are in our tuplestore and passed back through
+ * rsinfo->setResult. rsinfo->setDesc is set to the tuple description
+ * that we actually used to build our tuples with, so the caller can
+ * verify we did what it was expecting.
+ */
+ rsinfo->setDesc = tupdesc;
+ MemoryContextSwitchTo(oldcontext);
+
+ return (Datum) 0;
+}