@ -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_tupd esc - > 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_tupd esc - > natts * sizeof ( char * ) ) ;
xpaths = ( xmlChar * * ) palloc ( ret_tupd esc - > 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_tupd esc - > natts - 1 ) )
while ( numpaths < ( rsinfo - > setD esc - > 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_tupd esc - > natts ; j + + )
for ( j = 0 ; j < rsinfo - > setD esc - > 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 .