Add new system view, pg_config
Move and refactor the underlying code for the pg_config client application to src/common in support of sharing it with a new system information SRF called pg_config() which makes the same information available via SQL. Additionally wrap the SRF with a new system view, as called pg_config. Patch by me with extensive input and review by Michael Paquier and additional review by Alvaro Herrera.
This commit is contained in:
parent
f1f5ec1efa
commit
a5c43b8869
@ -7349,6 +7349,11 @@
|
||||
<entry>available versions of extensions</entry>
|
||||
</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>
|
||||
@ -7609,6 +7614,53 @@
|
||||
</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 <productname>PostgreSQL</>. It is intended, for example, to
|
||||
be used by software packages that want to interface to
|
||||
<productname>PostgreSQL</> to facilitate finding the required header
|
||||
files and libraries. It provides the same basic information as the
|
||||
<xref linkend="app-pgconfig"> <productname>PostgreSQL</> Client
|
||||
Application.
|
||||
</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>
|
||||
|
||||
|
@ -433,6 +433,12 @@ CREATE VIEW pg_timezone_abbrevs AS
|
||||
CREATE VIEW pg_timezone_names AS
|
||||
SELECT * FROM pg_timezone_names();
|
||||
|
||||
CREATE VIEW pg_config AS
|
||||
SELECT * FROM pg_config();
|
||||
|
||||
REVOKE ALL on pg_config FROM PUBLIC;
|
||||
REVOKE EXECUTE ON FUNCTION pg_config() FROM PUBLIC;
|
||||
|
||||
-- Statistics views
|
||||
|
||||
CREATE VIEW pg_stat_all_tables AS
|
||||
|
@ -14,8 +14,8 @@ include $(top_builddir)/src/Makefile.global
|
||||
|
||||
override CPPFLAGS := -I. -I$(srcdir) $(CPPFLAGS)
|
||||
|
||||
OBJS = guc.o help_config.o pg_rusage.o ps_status.o rls.o \
|
||||
sampling.o superuser.o timeout.o tzparser.o
|
||||
OBJS = guc.o help_config.o pg_config.o pg_rusage.o \
|
||||
ps_status.o rls.o sampling.o superuser.o timeout.o tzparser.o
|
||||
|
||||
# This location might depend on the installation directories. Therefore
|
||||
# we can't subsitute it into pg_config.h.
|
||||
|
103
src/backend/utils/misc/pg_config.c
Normal file
103
src/backend/utils/misc/pg_config.c
Normal file
@ -0,0 +1,103 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* pg_config.c
|
||||
* Expose same output as pg_config except as an SRF
|
||||
*
|
||||
* Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* src/backend/utils/misc/pg_config.c
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "postgres.h"
|
||||
|
||||
#include "funcapi.h"
|
||||
#include "miscadmin.h"
|
||||
#include "catalog/pg_type.h"
|
||||
#include "common/config_info.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/elog.h"
|
||||
#include "port.h"
|
||||
|
||||
Datum
|
||||
pg_config(PG_FUNCTION_ARGS)
|
||||
{
|
||||
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
|
||||
Tuplestorestate *tupstore;
|
||||
HeapTuple tuple;
|
||||
TupleDesc tupdesc;
|
||||
AttInMetadata *attinmeta;
|
||||
MemoryContext per_query_ctx;
|
||||
MemoryContext oldcontext;
|
||||
ConfigData *configdata;
|
||||
size_t configdata_len;
|
||||
char *values[2];
|
||||
int i = 0;
|
||||
|
||||
/* check to see if caller supports us returning a tuplestore */
|
||||
if (!rsinfo || !(rsinfo->allowedModes & SFRM_Materialize))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("materialize mode required, but it is not "
|
||||
"allowed in this context")));
|
||||
|
||||
per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
|
||||
oldcontext = MemoryContextSwitchTo(per_query_ctx);
|
||||
|
||||
/* get the requested return tuple description */
|
||||
tupdesc = CreateTupleDescCopy(rsinfo->expectedDesc);
|
||||
|
||||
/*
|
||||
* Check to make sure we have a reasonable tuple descriptor
|
||||
*/
|
||||
if (tupdesc->natts != 2 ||
|
||||
tupdesc->attrs[0]->atttypid != TEXTOID ||
|
||||
tupdesc->attrs[1]->atttypid != TEXTOID)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_SYNTAX_ERROR),
|
||||
errmsg("query-specified return tuple and "
|
||||
"function return type are not compatible")));
|
||||
|
||||
/* OK to use it */
|
||||
attinmeta = TupleDescGetAttInMetadata(tupdesc);
|
||||
|
||||
/* let the caller know we're sending back a tuplestore */
|
||||
rsinfo->returnMode = SFRM_Materialize;
|
||||
|
||||
/* initialize our tuplestore */
|
||||
tupstore = tuplestore_begin_heap(true, false, work_mem);
|
||||
|
||||
configdata = get_configdata(my_exec_path, &configdata_len);
|
||||
for (i = 0; i < configdata_len; i++)
|
||||
{
|
||||
values[0] = configdata[i].name;
|
||||
values[1] = configdata[i].setting;
|
||||
|
||||
tuple = BuildTupleFromCStrings(attinmeta, values);
|
||||
tuplestore_puttuple(tupstore, tuple);
|
||||
}
|
||||
|
||||
/*
|
||||
* no longer need the tuple descriptor reference created by
|
||||
* TupleDescGetAttInMetadata()
|
||||
*/
|
||||
ReleaseTupleDesc(tupdesc);
|
||||
|
||||
tuplestore_donestoring(tupstore);
|
||||
rsinfo->setResult = tupstore;
|
||||
|
||||
/*
|
||||
* SFRM_Materialize mode expects us to return a NULL Datum. The actual
|
||||
* tuples are in our tuplestore and passed back through
|
||||
* rsinfo->setResult. rsinfo->setDesc is set to the tuple description
|
||||
* that we actually used to build our tuples with, so the caller can
|
||||
* verify we did what it was expecting.
|
||||
*/
|
||||
rsinfo->setDesc = tupdesc;
|
||||
MemoryContextSwitchTo(oldcontext);
|
||||
|
||||
return (Datum) 0;
|
||||
}
|
@ -17,20 +17,6 @@ include $(top_builddir)/src/Makefile.global
|
||||
|
||||
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
|
||||
|
@ -25,363 +25,9 @@
|
||||
#include "postgres_fe.h"
|
||||
|
||||
#include "port.h"
|
||||
#include "common/config_info.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
|
||||
@ -391,33 +37,33 @@ show_version(bool all)
|
||||
typedef struct
|
||||
{
|
||||
const char *switchname;
|
||||
void (*show_func) (bool all);
|
||||
const char *configname;
|
||||
} 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},
|
||||
{"--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}
|
||||
};
|
||||
|
||||
@ -466,22 +112,27 @@ advice(void)
|
||||
}
|
||||
|
||||
static void
|
||||
show_all(void)
|
||||
show_item(const char *configname,
|
||||
ConfigData *configdata,
|
||||
size_t configdata_len)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; info_items[i].switchname != NULL; i++)
|
||||
for (i = 0; i < configdata_len; i++)
|
||||
{
|
||||
(*info_items[i].show_func) (true);
|
||||
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;
|
||||
int ret;
|
||||
|
||||
set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_config"));
|
||||
|
||||
@ -497,28 +148,30 @@ main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
ret = find_my_exec(argv[0], mypath);
|
||||
|
||||
if (ret)
|
||||
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)
|
||||
{
|
||||
show_all();
|
||||
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)
|
||||
{
|
||||
(*info_items[j].show_func) (false);
|
||||
show_item(info_items[j].configname,
|
||||
configdata, configdata_len);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -23,8 +23,21 @@ include $(top_builddir)/src/Makefile.global
|
||||
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
|
||||
# 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 = config_info.o 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
|
||||
|
||||
|
206
src/common/config_info.c
Normal file
206
src/common/config_info.c
Normal file
@ -0,0 +1,206 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* config_info.c
|
||||
* Common code for pg_config output
|
||||
*
|
||||
*
|
||||
* Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* src/common/config_info.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;
|
||||
}
|
@ -53,6 +53,6 @@
|
||||
*/
|
||||
|
||||
/* yyyymmddN */
|
||||
#define CATALOG_VERSION_NO 201602071
|
||||
#define CATALOG_VERSION_NO 201602171
|
||||
|
||||
#endif
|
||||
|
@ -5208,6 +5208,10 @@ DESCR("row security for current context active on table by table oid");
|
||||
DATA(insert OID = 3299 ( row_security_active PGNSP PGUID 12 1 0 0 0 f f f f t f s s 1 0 16 "25" _null_ _null_ _null_ _null_ _null_ row_security_active_name _null_ _null_ _null_ ));
|
||||
DESCR("row security for current context active on table by table name");
|
||||
|
||||
/* 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
|
||||
* of a function is dependent *only* on the values of its explicit arguments,
|
||||
|
21
src/include/common/config_info.h
Normal file
21
src/include/common/config_info.h
Normal file
@ -0,0 +1,21 @@
|
||||
/*
|
||||
* config_info.h
|
||||
* Common code for pg_config output
|
||||
*
|
||||
* Copyright (c) 2016, PostgreSQL Global Development Group
|
||||
*
|
||||
* src/include/common/config_info.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 */
|
@ -42,6 +42,7 @@ extern void join_path_components(char *ret_path,
|
||||
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);
|
||||
|
@ -1147,6 +1147,9 @@ extern Datum set_config_by_name(PG_FUNCTION_ARGS);
|
||||
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);
|
||||
|
@ -171,6 +171,36 @@ make_native_path(char *filename)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
|
@ -1305,6 +1305,9 @@ pg_available_extensions| SELECT e.name,
|
||||
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,
|
||||
|
@ -106,8 +106,8 @@ sub mkvcbuild
|
||||
}
|
||||
|
||||
our @pgcommonallfiles = qw(
|
||||
exec.c pg_lzcompress.c pgfnames.c psprintf.c relpath.c rmtree.c
|
||||
string.c username.c wait_error.c);
|
||||
config_info.c 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
|
||||
|
Loading…
x
Reference in New Issue
Block a user