aboutsummaryrefslogtreecommitdiff
path: root/contrib/xml2/xpath.c
diff options
context:
space:
mode:
authorMichael Paquier <michael@paquier.xyz>2022-03-08 10:12:22 +0900
committerMichael Paquier <michael@paquier.xyz>2022-03-08 10:12:22 +0900
commit5b81703787bfc1e6072c8e37125eba0c5598b807 (patch)
tree64fa53f8604641fc8ba17da54cf2b127b5016dac /contrib/xml2/xpath.c
parentd5ed9da41d96988d905b49bebb273a9b2d6e2915 (diff)
downloadpostgresql-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.c72
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.