postgresql/src/backend/utils/misc/pg_config.c

104 lines
2.9 KiB
C

/*-------------------------------------------------------------------------
*
* 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;
}