On 01/20/2016 08:08 PM, Michael Paquier wrote: > On Wed, Jan 20, 2016 at 2:32 AM, Joe Conway <m...@joeconway.com> wrote: >> The only things I know of still lacking is: >> 1) Documentation
Done and included in the attached. >> 2) Decision on REVOKE ... FROM PUBLIC > > Yep, regarding 2) I am the only one actually making noise to protect > this information by default, against at least 2 committers :) I plan to commit this way -- if the decision is made to remove the two REVOKEs it can always be done later, but I see no problem with it. > +typedef struct configdata > +{ > + char *name; > + char *setting; > +} configdata; > For a better analogy to ControlFileData, this could be renamed ConfigData? Well I was already using ConfigData as the variable name, but after some review it seems better your way, so I made the struct ConfigData and the variable configdata. > The point of the move to src/common is to remove the duplication in > src/bin/pg_config/Makefile. check > All the files in src/common should begin their include declarations with that: > #ifndef FRONTEND > #include "postgres.h" > #else > #include "postgres_fe.h" > #endif check > +configdata * > +get_configdata(char *my_exec_path, size_t *configdata_len) > +{ > It may be good to mention that the result is palloc'd and that caller > may need to free it if necessary. It does not matter in the two code > paths of this patch, but it may matter for other users calling that. check I believe this takes care of all open issues with this, so I plan to commit it as attached in a day or two. Thanks for your reviews and comments! Joe -- Crunchy Data - http://crunchydata.com PostgreSQL Support for Secure Enterprises Consulting, Training, & Open Source Development
diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml index 412c845..6c50f79 100644 *** a/doc/src/sgml/catalogs.sgml --- b/doc/src/sgml/catalogs.sgml *************** *** 7350,7355 **** --- 7350,7360 ---- </row> <row> + <entry><link linkend="view-pg-config"><structname>pg_config</structname></link></entry> + <entry>compile-time configuration parameters</entry> + </row> + + <row> <entry><link linkend="view-pg-cursors"><structname>pg_cursors</structname></link></entry> <entry>open cursors</entry> </row> *************** *** 7609,7614 **** --- 7614,7667 ---- </para> </sect1> + <sect1 id="view-pg-config"> + <title><structname>pg_config</structname></title> + + <indexterm zone="view-pg-config"> + <primary>pg_config</primary> + </indexterm> + + <para> + The view <structname>pg_config</structname> describes the + compile-time configuration parameters of the currently installed + version of PostgreSQL. It is intended, for example, to be used by + software packages that want to interface to PostgreSQL to facilitate + finding the required header files and libraries. It provides the same + basic information as the <xref linkend="app-pgconfig"> PostgreSQL Client + Application. There is a System Information Function + (<xref linkend="functions-info">) called <function>pg_config</function> + which underlies this view. + </para> + + <table> + <title><structname>pg_config</> Columns</title> + <tgroup cols="3"> + <thead> + <row> + <entry>Name</entry> + <entry>Type</entry> + <entry>Description</entry> + </row> + </thead> + + <tbody> + <row> + <entry><structfield>name</structfield></entry> + <entry><type>text</type></entry> + <entry>The parameter name</entry> + </row> + + <row> + <entry><structfield>setting</structfield></entry> + <entry><type>text</type></entry> + <entry>The parameter value</entry> + </row> + </tbody> + </tgroup> + </table> + + </sect1> + <sect1 id="view-pg-cursors"> <title><structname>pg_cursors</structname></title> diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index f9eea76..29c36d2 100644 *** a/doc/src/sgml/func.sgml --- b/doc/src/sgml/func.sgml *************** SELECT * FROM pg_ls_dir('.') WITH ORDINA *** 15003,15008 **** --- 15003,15014 ---- </row> <row> + <entry><literal><function>pg_config()</function></literal></entry> + <entry><type>setof record</type></entry> + <entry>get list of compile-time configure variable names and their values</entry> + </row> + + <row> <entry><literal><function>pg_is_other_temp_schema(<type>oid</type>)</function></literal></entry> <entry><type>boolean</type></entry> <entry>is schema another session's temporary schema?</entry> *************** SET search_path TO <replaceable>schema</ *** 15245,15250 **** --- 15251,15273 ---- </para> <indexterm> + <primary>pg_config</primary> + </indexterm> + + <para> + <function>pg_config</function> returns a set of records describing the + compile-time configuration parameters of the currently installed + version of PostgreSQL. It is intended, for example, to be used by + software packages that want to interface to PostgreSQL to facilitate + finding the required header files and libraries. The + <structfield>name</> column contains the parameter name. + The <structfield>setting</> column contains the parameter value. It + provides the same basic information as the + <xref linkend="app-pgconfig"> PostgreSQL Client Application. There + is also a <xref linkend="view-pg-config"> system view. + </para> + + <indexterm> <primary>version</primary> </indexterm> 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 ...a74e97d . *** 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/Makefile b/src/bin/pg_config/Makefile index 812c4a1..26fbaad 100644 *** a/src/bin/pg_config/Makefile --- b/src/bin/pg_config/Makefile *************** include $(top_builddir)/src/Makefile.glo *** 17,36 **** OBJS= pg_config.o $(WIN32RES) - # 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)\"" - all: pg_config pg_config: $(OBJS) | submake-libpgport --- 17,22 ---- diff --git a/src/bin/pg_config/pg_config.c b/src/bin/pg_config/pg_config.c index 4b14294..23c0495 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..ab183cf 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 *************** libpgcommon_srv.a: $(OBJS_SRV) *** 61,67 **** # a hack that might fail someday if there is a *_srv.o without a # corresponding *.o, but it works for now. %_srv.o: %.c %.o ! $(CC) $(CFLAGS) $(subst -DFRONTEND,, $(CPPFLAGS)) -c $< -o $@ $(OBJS_SRV): | submake-errcodes --- 74,80 ---- # a hack that might fail someday if there is a *_srv.o without a # corresponding *.o, but it works for now. %_srv.o: %.c %.o ! $(CC) $(CFLAGS) $(subst -DFRONTEND ,, $(CPPFLAGS)) -c $< -o $@ $(OBJS_SRV): | submake-errcodes diff --git a/src/common/config_info.c b/src/common/config_info.c index ...1e3c6db . *** a/src/common/config_info.c --- b/src/common/config_info.c *************** *** 0 **** --- 1,206 ---- + /*------------------------------------------------------------------------- + * + * config_info.c + * Common code for pg_config output + * + * + * Portions Copyright (c) 1996-2015, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * src/common/controldata_utils.c + * + *------------------------------------------------------------------------- + */ + + #ifndef FRONTEND + #include "postgres.h" + #else + #include "postgres_fe.h" + #endif + + #include "miscadmin.h" + #include "common/config_info.h" + + static size_t configdata_names_len(void); + + static const char *const configdata_names[] = + { + "BINDIR", + "DOCDIR", + "HTMLDIR", + "INCLUDEDIR", + "PKGINCLUDEDIR", + "INCLUDEDIR-SERVER", + "LIBDIR", + "PKGLIBDIR", + "LOCALEDIR", + "MANDIR", + "SHAREDIR", + "SYSCONFDIR", + "PGXS", + "CONFIGURE", + "CC", + "CPPFLAGS", + "CFLAGS", + "CFLAGS_SL", + "LDFLAGS", + "LDFLAGS_EX", + "LDFLAGS_SL", + "LIBS", + "VERSION", + NULL + }; + + static size_t + configdata_names_len(void) + { + size_t i = 0; + + while (configdata_names[i]) + i++; + + return i; + } + + /* + * get_configdata(char *my_exec_path, size_t *configdata_len) + * + * Get configure-time constants. The caller is responsible + * for pfreeing the result. + */ + ConfigData * + get_configdata(char *my_exec_path, size_t *configdata_len) + { + ConfigData *configdata; + char path[MAXPGPATH]; + char *lastsep; + int i; + + *configdata_len = configdata_names_len(); + configdata = palloc(*configdata_len * sizeof(ConfigData)); + + /* + * initialize configdata names + * + * These better be in sync with the settings manually + * defined below. + */ + for (i = 0; i < *configdata_len; i++) + configdata[i].name = pstrdup(configdata_names[i]); + + strcpy(path, my_exec_path); + lastsep = strrchr(path, '/'); + if (lastsep) + *lastsep = '\0'; + cleanup_path(path); + configdata[0].setting = pstrdup(path); + + get_doc_path(my_exec_path, path); + cleanup_path(path); + configdata[1].setting = pstrdup(path); + + get_html_path(my_exec_path, path); + cleanup_path(path); + configdata[2].setting = pstrdup(path); + + get_include_path(my_exec_path, path); + cleanup_path(path); + configdata[3].setting = pstrdup(path); + + get_pkginclude_path(my_exec_path, path); + cleanup_path(path); + configdata[4].setting = pstrdup(path); + + get_includeserver_path(my_exec_path, path); + cleanup_path(path); + configdata[5].setting = pstrdup(path); + + get_lib_path(my_exec_path, path); + cleanup_path(path); + configdata[6].setting = pstrdup(path); + + get_pkglib_path(my_exec_path, path); + cleanup_path(path); + configdata[7].setting = pstrdup(path); + + get_locale_path(my_exec_path, path); + cleanup_path(path); + configdata[8].setting = pstrdup(path); + + get_man_path(my_exec_path, path); + cleanup_path(path); + configdata[9].setting = pstrdup(path); + + get_share_path(my_exec_path, path); + cleanup_path(path); + configdata[10].setting = pstrdup(path); + + get_etc_path(my_exec_path, path); + cleanup_path(path); + configdata[11].setting = pstrdup(path); + + get_pkglib_path(my_exec_path, path); + strlcat(path, "/pgxs/src/makefiles/pgxs.mk", sizeof(path)); + cleanup_path(path); + configdata[12].setting = pstrdup(path); + + #ifdef VAL_CONFIGURE + configdata[13].setting = pstrdup(VAL_CONFIGURE); + #else + configdata[13].setting = pstrdup(_("not recorded")); + #endif + + #ifdef VAL_CC + configdata[14].setting = pstrdup(VAL_CC); + #else + configdata[14].setting = pstrdup(_("not recorded")); + #endif + + #ifdef VAL_CPPFLAGS + configdata[15].setting = pstrdup(VAL_CPPFLAGS); + #else + configdata[15].setting = pstrdup(_("not recorded")); + #endif + + #ifdef VAL_CFLAGS + configdata[16].setting = pstrdup(VAL_CFLAGS); + #else + configdata[16].setting = pstrdup(_("not recorded")); + #endif + + #ifdef VAL_CFLAGS_SL + configdata[17].setting = pstrdup(VAL_CFLAGS_SL); + #else + configdata[17].setting = pstrdup(_("not recorded")); + #endif + + #ifdef VAL_LDFLAGS + configdata[18].setting = pstrdup(VAL_LDFLAGS); + #else + configdata[18].setting = pstrdup(_("not recorded")); + #endif + + #ifdef VAL_LDFLAGS_EX + configdata[19].setting = pstrdup(VAL_LDFLAGS_EX); + #else + configdata[19].setting = pstrdup(_("not recorded")); + #endif + + #ifdef VAL_LDFLAGS_SL + configdata[20].setting = pstrdup(VAL_LDFLAGS_SL); + #else + configdata[20].setting = pstrdup(_("not recorded")); + #endif + + #ifdef VAL_LIBS + configdata[21].setting = pstrdup(VAL_LIBS); + #else + configdata[21].setting = pstrdup(_("not recorded")); + #endif + + configdata[22].setting = pstrdup("PostgreSQL " PG_VERSION); + + return configdata; + } diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index 1c0ef9a..f4c9572 100644 *** a/src/include/catalog/pg_proc.h --- b/src/include/catalog/pg_proc.h *************** DESCR("get an individual replication ori *** 5202,5207 **** --- 5202,5210 ---- 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/common/config_info.h b/src/include/common/config_info.h index ...488fcf1 . *** a/src/include/common/config_info.h --- b/src/include/common/config_info.h *************** *** 0 **** --- 1,21 ---- + /* + * controldata_utils.h + * Common code for pg_controldata output + * + * Copyright (c) 2016, PostgreSQL Global Development Group + * + * src/include/common/controldata_utils.h + */ + #ifndef COMMON_CONFIG_INFO_H + #define COMMON_CONFIG_INFO_H + + typedef struct ConfigData + { + char *name; + char *setting; + } ConfigData; + + extern ConfigData *get_configdata(char *my_exec_path, + size_t *configdata_len); + + #endif /* COMMON_CONFIG_INFO_H */ 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 affcc01..a784de9 100644 *** a/src/include/utils/builtins.h --- b/src/include/utils/builtins.h *************** extern Datum set_config_by_name(PG_FUNCT *** 1147,1152 **** --- 1147,1155 ---- 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 2bdba2d..81bc5c9 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, diff --git a/src/tools/msvc/Mkvcbuild.pm b/src/tools/msvc/Mkvcbuild.pm index 1dba7d9..cc0dcb3 100644 *** a/src/tools/msvc/Mkvcbuild.pm --- b/src/tools/msvc/Mkvcbuild.pm *************** sub mkvcbuild *** 106,113 **** } our @pgcommonallfiles = qw( ! exec.c pg_lzcompress.c pgfnames.c psprintf.c relpath.c rmtree.c ! string.c username.c wait_error.c); our @pgcommonfrontendfiles = ( @pgcommonallfiles, qw(fe_memutils.c --- 106,113 ---- } our @pgcommonallfiles = qw( ! exec.c config_info.c pg_lzcompress.c pgfnames.c psprintf.c ! relpath.c rmtree.c string.c username.c wait_error.c); our @pgcommonfrontendfiles = ( @pgcommonallfiles, qw(fe_memutils.c
signature.asc
Description: OpenPGP digital signature