On 01/18/2016 08:51 PM, Michael Paquier wrote:
> On Tue, Jan 19, 2016 at 1:49 PM, Michael Paquier
>> +       }
>> +
>> +       /*
>> +        * no longer need the tuple descriptor reference created by
>> The patch has some whitespaces.

I take it you mean a line with only whitespace? Fixed.


>> +REVOKE ALL on pg_config FROM PUBLIC;
>> +REVOKE EXECUTE ON FUNCTION pg_config() FROM PUBLIC;
>> I guess that this portion is still under debate :)


Left in for the moment.

>> make[1]: Nothing to be done for `all'.
>> make -C ../backend submake-errcodes
>> make[2]: *** No rule to make target `config_info.o', needed by
>> `libpgcommon.a'.  Stop.
>> make[2]: *** Waiting for unfinished jobs....
>> The patch is visibly forgetting to include config_info.c, which should
>> be part of src/common.


Confounded git! ;-)
Fixed.


>>  /*
>> + * 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)
>> +{
>> Perhaps this refactoring would be useful as a separate patch?


It doesn't seem worth doing on its own, and it is required by the rest
of this patch. I'd say keep it here, but I'll break it out if you think
it important enough.


> You need as well to update @pgcommonallfiles in Mkvcbuild.pm or the
> compilation with MSVC is going to fail.

Good catch -- done.

The only things I know of still lacking is:
1) Documentation
2) Decision on REVOKE ... FROM PUBLIC

I'm assuming by the lack of complainants that there is enough support
for the feature (conceptually at least) that it is worthwhile for me to
write the docs. Will do that over the next couple of days or so.

Thanks for the code reviews!

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 ...d86460e .
*** 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/common/config_info.c b/src/common/config_info.c
index ...96f0e7b .
*** a/src/common/config_info.c
--- b/src/common/config_info.c
***************
*** 0 ****
--- 1,196 ----
+ /*-------------------------------------------------------------------------
+  *
+  * 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
+  *
+  *-------------------------------------------------------------------------
+  */
+ 
+ #include "postgres.h"
+ 
+ #include "miscadmin.h"
+ #include "common/config_info.h"
+ 
+ static size_t ConfigDataNames_len(void);
+ 
+ static const char *const ConfigDataNames[] =
+ {
+ 	"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
+ ConfigDataNames_len(void)
+ {
+ 	size_t	i = 0;
+ 
+ 	while (ConfigDataNames[i])
+ 		i++;
+ 
+ 	return i;
+ }
+ 
+ configdata *
+ get_configdata(char *my_exec_path, size_t *configdata_len)
+ {
+ 	configdata	   *ConfigData;
+ 	char			path[MAXPGPATH];
+ 	char		   *lastsep;
+ 	int				i;
+ 
+ 	*configdata_len = ConfigDataNames_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(ConfigDataNames[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 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/common/config_info.h b/src/include/common/config_info.h
index ...762b66f .
*** 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 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,
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

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to