On 01/18/2016 04:16 PM, Joe Conway wrote: > Please see the attached. Duplication removed.
Actually please see this version instead. Joe -- Crunchy Data - http://crunchydata.com PostgreSQL Support for Secure Enterprises Consulting, Training, & Open Source Development
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql index 923fe58..abf9a70 100644 *** a/src/backend/catalog/system_views.sql --- b/src/backend/catalog/system_views.sql *************** CREATE VIEW pg_timezone_abbrevs AS *** 433,438 **** --- 433,444 ---- 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 7889101..a0c82c1 100644 *** a/src/backend/utils/misc/Makefile --- b/src/backend/utils/misc/Makefile *************** include $(top_builddir)/src/Makefile.glo *** 14,21 **** 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 # This location might depend on the installation directories. Therefore # we can't subsitute it into pg_config.h. --- 14,21 ---- override CPPFLAGS := -I. -I$(srcdir) $(CPPFLAGS) ! 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 index ...05ee67b . *** a/src/backend/utils/misc/pg_config.c --- b/src/backend/utils/misc/pg_config.c *************** *** 0 **** --- 1,102 ---- + /*------------------------------------------------------------------------- + * + * pg_config.c + * Expose same output as pg_config except as an SRF + * + * Portions Copyright (c) 1996-2015, 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; + } diff --git a/src/bin/pg_config/pg_config.c b/src/bin/pg_config/pg_config.c index 4b14294..963a244 100644 *** a/src/bin/pg_config/pg_config.c --- b/src/bin/pg_config/pg_config.c *************** *** 25,387 **** #include "postgres_fe.h" #include "port.h" static const char *progname; - static char mypath[MAXPGPATH]; - - - /* - * This function cleans up the paths for use with either cmd.exe or Msys - * on Windows. We need them to use filenames without spaces, for which a - * short filename is the safest equivalent, eg: - * C:/Progra~1/ - */ - static void - cleanup_path(char *path) - { - #ifdef WIN32 - char *ptr; - - /* - * GetShortPathName() will fail if the path does not exist, or short names - * are disabled on this file system. In both cases, we just return the - * original path. This is particularly useful for --sysconfdir, which - * might not exist. - */ - GetShortPathName(path, path, MAXPGPATH - 1); - - /* Replace '\' with '/' */ - for (ptr = path; *ptr; ptr++) - { - if (*ptr == '\\') - *ptr = '/'; - } - #endif - } - - - /* - * For each piece of information known to pg_config, we define a subroutine - * to print it. This is probably overkill, but it avoids code duplication - * and accidentally omitting items from the "all" display. - */ - - static void - show_bindir(bool all) - { - char path[MAXPGPATH]; - char *lastsep; - - if (all) - printf("BINDIR = "); - /* assume we are located in the bindir */ - strcpy(path, mypath); - lastsep = strrchr(path, '/'); - - if (lastsep) - *lastsep = '\0'; - - cleanup_path(path); - printf("%s\n", path); - } - - static void - show_docdir(bool all) - { - char path[MAXPGPATH]; - - if (all) - printf("DOCDIR = "); - get_doc_path(mypath, path); - cleanup_path(path); - printf("%s\n", path); - } - - static void - show_htmldir(bool all) - { - char path[MAXPGPATH]; - - if (all) - printf("HTMLDIR = "); - get_html_path(mypath, path); - cleanup_path(path); - printf("%s\n", path); - } - - static void - show_includedir(bool all) - { - char path[MAXPGPATH]; - - if (all) - printf("INCLUDEDIR = "); - get_include_path(mypath, path); - cleanup_path(path); - printf("%s\n", path); - } - - static void - show_pkgincludedir(bool all) - { - char path[MAXPGPATH]; - - if (all) - printf("PKGINCLUDEDIR = "); - get_pkginclude_path(mypath, path); - cleanup_path(path); - printf("%s\n", path); - } - - static void - show_includedir_server(bool all) - { - char path[MAXPGPATH]; - - if (all) - printf("INCLUDEDIR-SERVER = "); - get_includeserver_path(mypath, path); - cleanup_path(path); - printf("%s\n", path); - } - - static void - show_libdir(bool all) - { - char path[MAXPGPATH]; - - if (all) - printf("LIBDIR = "); - get_lib_path(mypath, path); - cleanup_path(path); - printf("%s\n", path); - } - - static void - show_pkglibdir(bool all) - { - char path[MAXPGPATH]; - - if (all) - printf("PKGLIBDIR = "); - get_pkglib_path(mypath, path); - cleanup_path(path); - printf("%s\n", path); - } - - static void - show_localedir(bool all) - { - char path[MAXPGPATH]; - - if (all) - printf("LOCALEDIR = "); - get_locale_path(mypath, path); - cleanup_path(path); - printf("%s\n", path); - } - - static void - show_mandir(bool all) - { - char path[MAXPGPATH]; - - if (all) - printf("MANDIR = "); - get_man_path(mypath, path); - cleanup_path(path); - printf("%s\n", path); - } - - static void - show_sharedir(bool all) - { - char path[MAXPGPATH]; - - if (all) - printf("SHAREDIR = "); - get_share_path(mypath, path); - cleanup_path(path); - printf("%s\n", path); - } - - static void - show_sysconfdir(bool all) - { - char path[MAXPGPATH]; - - if (all) - printf("SYSCONFDIR = "); - get_etc_path(mypath, path); - cleanup_path(path); - printf("%s\n", path); - } - - static void - show_pgxs(bool all) - { - char path[MAXPGPATH]; - - if (all) - printf("PGXS = "); - get_pkglib_path(mypath, path); - strlcat(path, "/pgxs/src/makefiles/pgxs.mk", sizeof(path)); - cleanup_path(path); - printf("%s\n", path); - } - - static void - show_configure(bool all) - { - #ifdef VAL_CONFIGURE - if (all) - printf("CONFIGURE = "); - printf("%s\n", VAL_CONFIGURE); - #else - if (!all) - { - fprintf(stderr, _("not recorded\n")); - exit(1); - } - #endif - } - - static void - show_cc(bool all) - { - #ifdef VAL_CC - if (all) - printf("CC = "); - printf("%s\n", VAL_CC); - #else - if (!all) - { - fprintf(stderr, _("not recorded\n")); - exit(1); - } - #endif - } - - static void - show_cppflags(bool all) - { - #ifdef VAL_CPPFLAGS - if (all) - printf("CPPFLAGS = "); - printf("%s\n", VAL_CPPFLAGS); - #else - if (!all) - { - fprintf(stderr, _("not recorded\n")); - exit(1); - } - #endif - } - - static void - show_cflags(bool all) - { - #ifdef VAL_CFLAGS - if (all) - printf("CFLAGS = "); - printf("%s\n", VAL_CFLAGS); - #else - if (!all) - { - fprintf(stderr, _("not recorded\n")); - exit(1); - } - #endif - } - - static void - show_cflags_sl(bool all) - { - #ifdef VAL_CFLAGS_SL - if (all) - printf("CFLAGS_SL = "); - printf("%s\n", VAL_CFLAGS_SL); - #else - if (!all) - { - fprintf(stderr, _("not recorded\n")); - exit(1); - } - #endif - } - - static void - show_ldflags(bool all) - { - #ifdef VAL_LDFLAGS - if (all) - printf("LDFLAGS = "); - printf("%s\n", VAL_LDFLAGS); - #else - if (!all) - { - fprintf(stderr, _("not recorded\n")); - exit(1); - } - #endif - } - - static void - show_ldflags_ex(bool all) - { - #ifdef VAL_LDFLAGS_EX - if (all) - printf("LDFLAGS_EX = "); - printf("%s\n", VAL_LDFLAGS_EX); - #else - if (!all) - { - fprintf(stderr, _("not recorded\n")); - exit(1); - } - #endif - } - - static void - show_ldflags_sl(bool all) - { - #ifdef VAL_LDFLAGS_SL - if (all) - printf("LDFLAGS_SL = "); - printf("%s\n", VAL_LDFLAGS_SL); - #else - if (!all) - { - fprintf(stderr, _("not recorded\n")); - exit(1); - } - #endif - } - - static void - show_libs(bool all) - { - #ifdef VAL_LIBS - if (all) - printf("LIBS = "); - printf("%s\n", VAL_LIBS); - #else - if (!all) - { - fprintf(stderr, _("not recorded\n")); - exit(1); - } - #endif - } - - static void - show_version(bool all) - { - if (all) - printf("VERSION = "); - printf("PostgreSQL " PG_VERSION "\n"); - } - /* * Table of known information items --- 25,33 ---- #include "postgres_fe.h" #include "port.h" + #include "common/config_info.h" static const char *progname; /* * Table of known information items *************** show_version(bool all) *** 391,423 **** typedef struct { const char *switchname; ! void (*show_func) (bool all); } InfoItem; static const InfoItem info_items[] = { ! {"--bindir", show_bindir}, ! {"--docdir", show_docdir}, ! {"--htmldir", show_htmldir}, ! {"--includedir", show_includedir}, ! {"--pkgincludedir", show_pkgincludedir}, ! {"--includedir-server", show_includedir_server}, ! {"--libdir", show_libdir}, ! {"--pkglibdir", show_pkglibdir}, ! {"--localedir", show_localedir}, ! {"--mandir", show_mandir}, ! {"--sharedir", show_sharedir}, ! {"--sysconfdir", show_sysconfdir}, ! {"--pgxs", show_pgxs}, ! {"--configure", show_configure}, ! {"--cc", show_cc}, ! {"--cppflags", show_cppflags}, ! {"--cflags", show_cflags}, ! {"--cflags_sl", show_cflags_sl}, ! {"--ldflags", show_ldflags}, ! {"--ldflags_ex", show_ldflags_ex}, ! {"--ldflags_sl", show_ldflags_sl}, ! {"--libs", show_libs}, ! {"--version", show_version}, {NULL, NULL} }; --- 37,69 ---- typedef struct { const char *switchname; ! const char *configname; } InfoItem; static const InfoItem info_items[] = { ! {"--bindir", "BINDIR"}, ! {"--docdir", "DOCDIR"}, ! {"--htmldir", "HTMLDIR"}, ! {"--includedir", "INCLUDEDIR"}, ! {"--pkgincludedir", "PKGINCLUDEDIR"}, ! {"--includedir-server", "INCLUDEDIR-SERVER"}, ! {"--libdir", "LIBDIR"}, ! {"--pkglibdir", "PKGLIBDIR"}, ! {"--localedir", "LOCALEDIR"}, ! {"--mandir", "MANDIR"}, ! {"--sharedir", "SHAREDIR"}, ! {"--sysconfdir", "SYSCONFDIR"}, ! {"--pgxs", "PGXS"}, ! {"--configure", "CONFIGURE"}, ! {"--cc", "CC"}, ! {"--cppflags", "CPPFLAGS"}, ! {"--cflags", "CFLAGS"}, ! {"--cflags_sl", "CFLAGS_SL"}, ! {"--ldflags", "LDFLAGS"}, ! {"--ldflags_ex", "LDFLAGS_EX"}, ! {"--ldflags_sl", "LDFLAGS_SL"}, ! {"--libs", "LIBS"}, ! {"--version", "VERSION"}, {NULL, NULL} }; *************** advice(void) *** 466,487 **** } static void ! show_all(void) { int i; ! for (i = 0; info_items[i].switchname != NULL; i++) { ! (*info_items[i].show_func) (true); } } int main(int argc, char **argv) { int i; int j; - int ret; set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_config")); --- 112,138 ---- } static void ! show_item(const char *configname, ! configdata *ConfigData, ! size_t configdata_len) { int i; ! for (i = 0; i < configdata_len; i++) { ! if (strcmp(configname, ConfigData[i].name) == 0) ! printf("%s = %s\n", ConfigData[i].name, ConfigData[i].setting); } } int main(int argc, char **argv) { + configdata *ConfigData; + size_t configdata_len; + char my_exec_path[MAXPGPATH]; int i; int j; set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_config")); *************** main(int argc, char **argv) *** 497,524 **** } } ! ret = find_my_exec(argv[0], mypath); ! ! if (ret) { fprintf(stderr, _("%s: could not find own program executable\n"), progname); exit(1); } /* no arguments -> print everything */ if (argc < 2) { ! show_all(); exit(0); } for (i = 1; i < argc; i++) { for (j = 0; info_items[j].switchname != NULL; j++) { if (strcmp(argv[i], info_items[j].switchname) == 0) { ! (*info_items[j].show_func) (false); break; } } --- 148,177 ---- } } ! if (find_my_exec(argv[0], my_exec_path) < 0) { fprintf(stderr, _("%s: could not find own program executable\n"), progname); exit(1); } + ConfigData = get_configdata(my_exec_path, &configdata_len); /* no arguments -> print everything */ if (argc < 2) { ! for (i = 0; i < configdata_len; i++) ! printf("%s = %s\n", ConfigData[i].name, ConfigData[i].setting); exit(0); } + /* otherwise print requested items */ for (i = 1; i < argc; i++) { for (j = 0; info_items[j].switchname != NULL; j++) { if (strcmp(argv[i], info_items[j].switchname) == 0) { ! show_item(info_items[j].configname, ! ConfigData, configdata_len); break; } } diff --git a/src/common/Makefile b/src/common/Makefile index c47445e..0cbee41 100644 *** a/src/common/Makefile --- b/src/common/Makefile *************** include $(top_builddir)/src/Makefile.glo *** 23,30 **** override CPPFLAGS := -DFRONTEND $(CPPFLAGS) LIBS += $(PTHREAD_LIBS) ! OBJS_COMMON = exec.o pg_lzcompress.o pgfnames.o psprintf.o relpath.o \ ! rmtree.o string.o username.o wait_error.o OBJS_FRONTEND = $(OBJS_COMMON) fe_memutils.o restricted_token.o --- 23,43 ---- override CPPFLAGS := -DFRONTEND $(CPPFLAGS) LIBS += $(PTHREAD_LIBS) ! # don't include subdirectory-path-dependent -I and -L switches ! STD_CPPFLAGS := $(filter-out -I$(top_srcdir)/src/include -I$(top_builddir)/src/include,$(CPPFLAGS)) ! STD_LDFLAGS := $(filter-out -L$(top_builddir)/src/port,$(LDFLAGS)) ! override CPPFLAGS += -DVAL_CONFIGURE="\"$(configure_args)\"" ! override CPPFLAGS += -DVAL_CC="\"$(CC)\"" ! override CPPFLAGS += -DVAL_CPPFLAGS="\"$(STD_CPPFLAGS)\"" ! override CPPFLAGS += -DVAL_CFLAGS="\"$(CFLAGS)\"" ! override CPPFLAGS += -DVAL_CFLAGS_SL="\"$(CFLAGS_SL)\"" ! override CPPFLAGS += -DVAL_LDFLAGS="\"$(STD_LDFLAGS)\"" ! override CPPFLAGS += -DVAL_LDFLAGS_EX="\"$(LDFLAGS_EX)\"" ! override CPPFLAGS += -DVAL_LDFLAGS_SL="\"$(LDFLAGS_SL)\"" ! override CPPFLAGS += -DVAL_LIBS="\"$(LIBS)\"" ! ! OBJS_COMMON = exec.o config_info.o pg_lzcompress.o pgfnames.o psprintf.o \ ! relpath.o rmtree.o string.o username.o wait_error.o OBJS_FRONTEND = $(OBJS_COMMON) fe_memutils.o restricted_token.o diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index 3df5ac5..ffc8096 100644 *** a/src/include/catalog/pg_proc.h --- b/src/include/catalog/pg_proc.h *************** DESCR("get an individual replication ori *** 5186,5191 **** --- 5186,5194 ---- DATA(insert OID = 6014 ( pg_show_replication_origin_status PGNSP PGUID 12 1 100 0 0 f f f f f t v r 0 0 2249 "" "{26,25,3220,3220}" "{o,o,o,o}" "{local_id, external_id, remote_lsn, local_lsn}" _null_ _null_ pg_show_replication_origin_status _null_ _null_ _null_ )); DESCR("get progress for all replication origins"); + /* pg_config */ + DATA(insert OID = 3400 ( pg_config PGNSP PGUID 12 1 23 0 0 f f f f t t i r 0 0 2249 "" "{25,25}" "{o,o}" "{name,setting}" _null_ _null_ pg_config _null_ _null_ _null_ )); + DESCR("pg_config binary as a function"); /* * Symbolic values for provolatile column: these indicate whether the result diff --git a/src/include/port.h b/src/include/port.h index 9fc79f4..cb13dd8 100644 *** a/src/include/port.h --- b/src/include/port.h *************** extern void join_path_components(char *r *** 42,47 **** --- 42,48 ---- const char *head, const char *tail); extern void canonicalize_path(char *path); extern void make_native_path(char *path); + extern void cleanup_path(char *path); extern bool path_contains_parent_reference(const char *path); extern bool path_is_relative_and_below_cwd(const char *path); extern bool path_is_prefix_of_path(const char *path1, const char *path2); diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h index 477fde1..aa713c1 100644 *** a/src/include/utils/builtins.h --- b/src/include/utils/builtins.h *************** extern Datum set_config_by_name(PG_FUNCT *** 1126,1131 **** --- 1126,1134 ---- extern Datum show_all_settings(PG_FUNCTION_ARGS); extern Datum show_all_file_settings(PG_FUNCTION_ARGS); + /* pg_config.c */ + extern Datum pg_config(PG_FUNCTION_ARGS); + /* rls.c */ extern Datum row_security_active(PG_FUNCTION_ARGS); extern Datum row_security_active_name(PG_FUNCTION_ARGS); diff --git a/src/port/path.c b/src/port/path.c index a418f93..5c9de0c 100644 *** a/src/port/path.c --- b/src/port/path.c *************** make_native_path(char *filename) *** 172,177 **** --- 172,207 ---- /* + * This function cleans up the paths for use with either cmd.exe or Msys + * on Windows. We need them to use filenames without spaces, for which a + * short filename is the safest equivalent, eg: + * C:/Progra~1/ + */ + void + cleanup_path(char *path) + { + #ifdef WIN32 + char *ptr; + + /* + * GetShortPathName() will fail if the path does not exist, or short names + * are disabled on this file system. In both cases, we just return the + * original path. This is particularly useful for --sysconfdir, which + * might not exist. + */ + GetShortPathName(path, path, MAXPGPATH - 1); + + /* Replace '\' with '/' */ + for (ptr = path; *ptr; ptr++) + { + if (*ptr == '\\') + *ptr = '/'; + } + #endif + } + + + /* * join_path_components - join two path components, inserting a slash * * We omit the slash if either given component is empty. diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out index 28b061f..4c84411 100644 *** a/src/test/regress/expected/rules.out --- b/src/test/regress/expected/rules.out *************** pg_available_extensions| SELECT e.name, *** 1305,1310 **** --- 1305,1313 ---- e.comment FROM (pg_available_extensions() e(name, default_version, comment) LEFT JOIN pg_extension x ON ((e.name = x.extname))); + pg_config| SELECT pg_config.name, + pg_config.setting + FROM pg_config() pg_config(name, setting); pg_cursors| SELECT c.name, c.statement, c.is_holdable,
signature.asc
Description: OpenPGP digital signature