mirror of https://github.com/postgres/postgres
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.pull/10/merge
parent
f1f5ec1efa
commit
a5c43b8869
@ -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; |
||||
} |
@ -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; |
||||
} |
@ -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 */ |
Loading…
Reference in new issue