diff options
author | Michael Paquier <michael@paquier.xyz> | 2022-03-08 10:12:22 +0900 |
---|---|---|
committer | Michael Paquier <michael@paquier.xyz> | 2022-03-08 10:12:22 +0900 |
commit | 5b81703787bfc1e6072c8e37125eba0c5598b807 (patch) | |
tree | 64fa53f8604641fc8ba17da54cf2b127b5016dac /contrib/xml2/xpath.c | |
parent | d5ed9da41d96988d905b49bebb273a9b2d6e2915 (diff) | |
download | postgresql-5b81703787bfc1e6072c8e37125eba0c5598b807.tar.gz postgresql-5b81703787bfc1e6072c8e37125eba0c5598b807.zip |
Simplify SRFs using materialize mode in contrib/ modules
9e98583 introduced a helper to centralize building their needed state
(tuplestore, tuple descriptors, etc.), checking for any errors. This
commit updates all places of contrib/ that can be switched to use
SetSingleFuncCall() as a drop-in replacement, resulting in the removal
of a lot of boilerplate code in all the modules updated by this commit.
Per analysis, some places remain as they are:
- pg_logdir_ls() in adminpack/ uses historically TYPEFUNC_RECORD as
return type, and I suspect that changing it may cause issues at run-time
with some of its past versions, down to 1.0.
- dblink/ uses a wrapper function doing exactly the work of
SetSingleFuncCall(). Here the switch should be possible, but rather
invasive so it does not seem the extra backpatch maintenance cost.
- tablefunc/, similarly, uses multiple helper functions with portions of
SetSingleFuncCall() spread across the code paths of this module.
Author: Melanie Plageman
Discussion: https://postgr.es/m/CAAKRu_bvDPJoL9mH6eYwvBpPtTGQwbDzfJbCM-OjkSZDu5yTPg@mail.gmail.com
Diffstat (limited to 'contrib/xml2/xpath.c')
-rw-r--r-- | contrib/xml2/xpath.c | 72 |
1 files changed, 10 insertions, 62 deletions
diff --git a/contrib/xml2/xpath.c b/contrib/xml2/xpath.c index a2e5fb54e20..b8ee757674d 100644 --- a/contrib/xml2/xpath.c +++ b/contrib/xml2/xpath.c @@ -491,15 +491,9 @@ xpath_table(PG_FUNCTION_ARGS) HeapTuple spi_tuple; TupleDesc spi_tupdesc; - /* Output tuple (tuplestore) support */ - Tuplestorestate *tupstore = NULL; - TupleDesc ret_tupdesc; - HeapTuple ret_tuple; ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo; AttInMetadata *attinmeta; - MemoryContext per_query_ctx; - MemoryContext oldcontext; char **values; xmlChar **xpaths; @@ -517,48 +511,10 @@ xpath_table(PG_FUNCTION_ARGS) PgXmlErrorContext *xmlerrcxt; volatile xmlDocPtr doctree = NULL; - /* We only have a valid tuple description in table function mode */ - if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo)) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("set-valued function called in context that cannot accept a set"))); - if (rsinfo->expectedDesc == NULL) - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("xpath_table must be called as a table function"))); - - /* - * We want to materialise because it means that we don't have to carry - * libxml2 parser state between invocations of this function - */ - if (!(rsinfo->allowedModes & SFRM_Materialize)) - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("xpath_table requires Materialize mode, but it is not " - "allowed in this context"))); - - /* - * The tuplestore must exist in a higher context than this function call - * (per_query_ctx is used) - */ - per_query_ctx = rsinfo->econtext->ecxt_per_query_memory; - oldcontext = MemoryContextSwitchTo(per_query_ctx); - - /* - * Create the tuplestore - work_mem is the max in-memory size before a - * file is created on disk to hold it. - */ - tupstore = - tuplestore_begin_heap(rsinfo->allowedModes & SFRM_Materialize_Random, - false, work_mem); - - MemoryContextSwitchTo(oldcontext); - - /* get the requested return tuple description */ - ret_tupdesc = CreateTupleDescCopy(rsinfo->expectedDesc); + SetSingleFuncCall(fcinfo, SRF_SINGLE_USE_EXPECTED); /* must have at least one output column (for the pkey) */ - if (ret_tupdesc->natts < 1) + if (rsinfo->setDesc->natts < 1) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("xpath_table must have at least one output column"))); @@ -571,14 +527,10 @@ xpath_table(PG_FUNCTION_ARGS) * representation. */ - attinmeta = TupleDescGetAttInMetadata(ret_tupdesc); - - /* Set return mode and allocate value space. */ - rsinfo->returnMode = SFRM_Materialize; - rsinfo->setDesc = ret_tupdesc; + attinmeta = TupleDescGetAttInMetadata(rsinfo->setDesc); - values = (char **) palloc(ret_tupdesc->natts * sizeof(char *)); - xpaths = (xmlChar **) palloc(ret_tupdesc->natts * sizeof(xmlChar *)); + values = (char **) palloc(rsinfo->setDesc->natts * sizeof(char *)); + xpaths = (xmlChar **) palloc(rsinfo->setDesc->natts * sizeof(xmlChar *)); /* * Split XPaths. xpathset is a writable CString. @@ -587,7 +539,7 @@ xpath_table(PG_FUNCTION_ARGS) */ numpaths = 0; pos = xpathset; - while (numpaths < (ret_tupdesc->natts - 1)) + while (numpaths < (rsinfo->setDesc->natts - 1)) { xpaths[numpaths++] = (xmlChar *) pos; pos = strstr(pos, pathsep); @@ -621,9 +573,6 @@ xpath_table(PG_FUNCTION_ARGS) tuptable = SPI_tuptable; spi_tupdesc = tuptable->tupdesc; - /* Switch out of SPI context */ - MemoryContextSwitchTo(oldcontext); - /* * Check that SPI returned correct result. If you put a comma into one of * the function parameters, this will catch it when the SPI query returns @@ -655,6 +604,7 @@ xpath_table(PG_FUNCTION_ARGS) xmlXPathObjectPtr res; xmlChar *resstr; xmlXPathCompExprPtr comppath; + HeapTuple ret_tuple; /* Extract the row data as C Strings */ spi_tuple = tuptable->vals[i]; @@ -666,7 +616,7 @@ xpath_table(PG_FUNCTION_ARGS) * return NULL in all columns. Note that this also means that * spare columns will be NULL. */ - for (j = 0; j < ret_tupdesc->natts; j++) + for (j = 0; j < rsinfo->setDesc->natts; j++) values[j] = NULL; /* Insert primary key */ @@ -682,7 +632,7 @@ xpath_table(PG_FUNCTION_ARGS) { /* not well-formed, so output all-NULL tuple */ ret_tuple = BuildTupleFromCStrings(attinmeta, values); - tuplestore_puttuple(tupstore, ret_tuple); + tuplestore_puttuple(rsinfo->setResult, ret_tuple); heap_freetuple(ret_tuple); } else @@ -749,7 +699,7 @@ xpath_table(PG_FUNCTION_ARGS) if (had_values) { ret_tuple = BuildTupleFromCStrings(attinmeta, values); - tuplestore_puttuple(tupstore, ret_tuple); + tuplestore_puttuple(rsinfo->setResult, ret_tuple); heap_freetuple(ret_tuple); } @@ -785,8 +735,6 @@ xpath_table(PG_FUNCTION_ARGS) SPI_finish(); - 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. |