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 ----
+ pg_config
+ compile-time configuration parameters
+
+
+ pg_cursorsopen cursors
***************
*** 7609,7614 ****
--- 7614,7667 ----
+
+ pg_config
+
+
+ pg_config
+
+
+
+ The view pg_config 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 PostgreSQL Client
+ Application. There is a System Information Function
+ () called pg_config
+ which underlies this view.
+
+
+
+ pg_config> Columns
+
+
+
+ Name
+ Type
+ Description
+
+
+
+
+
+ name
+ text
+ The parameter name
+
+
+
+ setting
+ text
+ The parameter value
+
+
+
+
+
+
+
pg_cursors
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 ----
+ pg_config()
+ setof record
+ get list of compile-time configure variable names and their values
+
+
+ pg_is_other_temp_schema(oid)booleanis schema another session's temporary schema?
*************** SET search_path TO schema
*** 15245,15250 ****
--- 15251,15273 ----
+ pg_config
+
+
+
+ pg_config 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
+ name> column contains the parameter name.
+ The setting> column contains the parameter value. It
+ provides the same basic information as the
+ PostgreSQL Client Application. There
+ is also a system view.
+
+
+ version
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