diff options
author | Michael Paquier <michael@paquier.xyz> | 2022-02-24 16:11:34 +0900 |
---|---|---|
committer | Michael Paquier <michael@paquier.xyz> | 2022-02-24 16:11:34 +0900 |
commit | fcc28178c6943d7df72b484a87fdb7e06d0c1079 (patch) | |
tree | 29d84d92aa610c56a1c1c1a4089d9e5fd201e0ba /src/backend/utils/misc/pg_config.c | |
parent | 04e706d4238f98a98e1c0b1a02db9d4280b96f04 (diff) |
Clean up and simplify code in a couple of set-returning functions
The following set-returning functions have their logic simplified, to be
more consistent with other in-core areas:
- pg_prepared_statement()'s tuple descriptor is now created with
get_call_result_type() instead of being created from scratch, saving
from some duplication with pg_proc.dat.
- show_all_file_settings(), similarly, now uses get_call_result_type()
to build its tuple descriptor instead of creating it from scratch.
- pg_options_to_table() made use of a static routine called only once.
This commit removes this internal routine to make the function easier to
follow.
- pg_config() was using a unique logic style, doing checks on the tuple
descriptor passed down in expectedDesc, but it has no need to do so.
This switches the function to use a tuplestore with a tuple descriptor
retrieved from get_call_result_type(), instead.
This simplifies an upcoming patch aimed at refactoring the way
tuplestores are created and checked in set-returning functions, this
change making sense as its own independent cleanup by shaving some
code.
Author: Melanie Plageman, Michael Paquier
Reviewed-by: Justin Pryzby
Discussion: https://postgr.es/m/CAAKRu_azyd1Z3W_r7Ou4sorTjRCs+PxeHw1CWJeXKofkE6TuZg@mail.gmail.com
Diffstat (limited to 'src/backend/utils/misc/pg_config.c')
-rw-r--r-- | src/backend/utils/misc/pg_config.c | 65 |
1 files changed, 17 insertions, 48 deletions
diff --git a/src/backend/utils/misc/pg_config.c b/src/backend/utils/misc/pg_config.c index 2dc875ebfbb..e646a419106 100644 --- a/src/backend/utils/misc/pg_config.c +++ b/src/backend/utils/misc/pg_config.c @@ -26,14 +26,10 @@ 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 */ @@ -41,65 +37,38 @@ pg_config(PG_FUNCTION_ARGS) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("set-valued function called in context that cannot accept a set"))); - if (!(rsinfo->allowedModes & SFRM_Materialize) || - rsinfo->expectedDesc == NULL) + if (!(rsinfo->allowedModes & SFRM_Materialize)) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), 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); + if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) + elog(ERROR, "return type must be a row type"); - /* get the requested return tuple description */ - tupdesc = CreateTupleDescCopy(rsinfo->expectedDesc); + /* Build tuplestore to hold the result rows */ + oldcontext = MemoryContextSwitchTo(rsinfo->econtext->ecxt_per_query_memory); - /* - * Check to make sure we have a reasonable tuple descriptor - */ - if (tupdesc->natts != 2 || - TupleDescAttr(tupdesc, 0)->atttypid != TEXTOID || - TupleDescAttr(tupdesc, 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 */ + tupstore = tuplestore_begin_heap(true, false, work_mem); rsinfo->returnMode = SFRM_Materialize; + rsinfo->setResult = tupstore; + rsinfo->setDesc = tupdesc; - /* initialize our tuplestore */ - tupstore = tuplestore_begin_heap(true, false, work_mem); + MemoryContextSwitchTo(oldcontext); 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); - } + Datum values[2]; + bool nulls[2]; - /* - * no longer need the tuple descriptor reference created by - * TupleDescGetAttInMetadata() - */ - ReleaseTupleDesc(tupdesc); + memset(values, 0, sizeof(values)); + memset(nulls, 0, sizeof(nulls)); - rsinfo->setResult = tupstore; + values[0] = CStringGetTextDatum(configdata[i].name); + values[1] = CStringGetTextDatum(configdata[i].setting); - /* - * 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); + tuplestore_putvalues(tupstore, tupdesc, values, nulls); + } return (Datum) 0; } |