pg_event_trigger_dropped_objects(PG_FUNCTION_ARGS)
{
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
- TupleDesc tupdesc;
- Tuplestorestate *tupstore;
- MemoryContext per_query_ctx;
- MemoryContext oldcontext;
slist_iter iter;
/*
errmsg("%s can only be called in a sql_drop event trigger function",
"pg_event_trigger_dropped_objects()")));
- /* check to see if caller supports us returning a tuplestore */
- 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->allowedModes & SFRM_Materialize))
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("materialize mode required, but it is not allowed in this context")));
-
- /* Build a tuple descriptor for our result type */
- if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
- elog(ERROR, "return type must be a row type");
-
/* Build tuplestore to hold the result rows */
- per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
- oldcontext = MemoryContextSwitchTo(per_query_ctx);
-
- tupstore = tuplestore_begin_heap(true, false, work_mem);
- rsinfo->returnMode = SFRM_Materialize;
- rsinfo->setResult = tupstore;
- rsinfo->setDesc = tupdesc;
-
- MemoryContextSwitchTo(oldcontext);
+ SetSingleFuncCall(fcinfo, 0);
slist_foreach(iter, &(currentEventTriggerState->SQLDropList))
{
nulls[i++] = true;
}
- tuplestore_putvalues(tupstore, tupdesc, values, nulls);
+ tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
+ values, nulls);
}
return (Datum) 0;
pg_event_trigger_ddl_commands(PG_FUNCTION_ARGS)
{
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
- TupleDesc tupdesc;
- Tuplestorestate *tupstore;
- MemoryContext per_query_ctx;
- MemoryContext oldcontext;
ListCell *lc;
/*
errmsg("%s can only be called in an event trigger function",
"pg_event_trigger_ddl_commands()")));
- /* check to see if caller supports us returning a tuplestore */
- 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->allowedModes & SFRM_Materialize))
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("materialize mode required, but it is not allowed in this context")));
-
- /* Build a tuple descriptor for our result type */
- if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
- elog(ERROR, "return type must be a row type");
-
/* Build tuplestore to hold the result rows */
- per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
- oldcontext = MemoryContextSwitchTo(per_query_ctx);
-
- tupstore = tuplestore_begin_heap(true, false, work_mem);
- rsinfo->returnMode = SFRM_Materialize;
- rsinfo->setResult = tupstore;
- rsinfo->setDesc = tupdesc;
-
- MemoryContextSwitchTo(oldcontext);
+ SetSingleFuncCall(fcinfo, 0);
foreach(lc, currentEventTriggerState->commandList)
{
break;
}
- tuplestore_putvalues(tupstore, tupdesc, values, nulls);
+ tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
+ values, nulls);
}
PG_RETURN_VOID();
pg_available_extensions(PG_FUNCTION_ARGS)
{
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
- TupleDesc tupdesc;
- Tuplestorestate *tupstore;
- MemoryContext per_query_ctx;
- MemoryContext oldcontext;
char *location;
DIR *dir;
struct dirent *de;
- /* check to see if caller supports us returning a tuplestore */
- 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->allowedModes & SFRM_Materialize))
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("materialize mode required, but it is not allowed in this context")));
-
- /* Build a tuple descriptor for our result type */
- if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
- elog(ERROR, "return type must be a row type");
-
/* Build tuplestore to hold the result rows */
- per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
- oldcontext = MemoryContextSwitchTo(per_query_ctx);
-
- tupstore = tuplestore_begin_heap(true, false, work_mem);
- rsinfo->returnMode = SFRM_Materialize;
- rsinfo->setResult = tupstore;
- rsinfo->setDesc = tupdesc;
-
- MemoryContextSwitchTo(oldcontext);
+ SetSingleFuncCall(fcinfo, 0);
location = get_extension_control_directory();
dir = AllocateDir(location);
else
values[2] = CStringGetTextDatum(control->comment);
- tuplestore_putvalues(tupstore, tupdesc, values, nulls);
+ tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
+ values, nulls);
}
FreeDir(dir);
pg_available_extension_versions(PG_FUNCTION_ARGS)
{
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
- TupleDesc tupdesc;
- Tuplestorestate *tupstore;
- MemoryContext per_query_ctx;
- MemoryContext oldcontext;
char *location;
DIR *dir;
struct dirent *de;
- /* check to see if caller supports us returning a tuplestore */
- 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->allowedModes & SFRM_Materialize))
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("materialize mode required, but it is not allowed in this context")));
-
- /* Build a tuple descriptor for our result type */
- if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
- elog(ERROR, "return type must be a row type");
-
/* Build tuplestore to hold the result rows */
- per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
- oldcontext = MemoryContextSwitchTo(per_query_ctx);
-
- tupstore = tuplestore_begin_heap(true, false, work_mem);
- rsinfo->returnMode = SFRM_Materialize;
- rsinfo->setResult = tupstore;
- rsinfo->setDesc = tupdesc;
-
- MemoryContextSwitchTo(oldcontext);
+ SetSingleFuncCall(fcinfo, 0);
location = get_extension_control_directory();
dir = AllocateDir(location);
control = read_extension_control_file(extname);
/* scan extension's script directory for install scripts */
- get_available_versions_for_extension(control, tupstore, tupdesc);
+ get_available_versions_for_extension(control, rsinfo->setResult,
+ rsinfo->setDesc);
}
FreeDir(dir);
{
Name extname = PG_GETARG_NAME(0);
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
- TupleDesc tupdesc;
- Tuplestorestate *tupstore;
- MemoryContext per_query_ctx;
- MemoryContext oldcontext;
List *evi_list;
ExtensionControlFile *control;
ListCell *lc1;
/* Check extension name validity before any filesystem access */
check_valid_extension_name(NameStr(*extname));
- /* check to see if caller supports us returning a tuplestore */
- 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->allowedModes & SFRM_Materialize))
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("materialize mode required, but it is not allowed in this context")));
-
- /* Build a tuple descriptor for our result type */
- if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
- elog(ERROR, "return type must be a row type");
-
/* Build tuplestore to hold the result rows */
- per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
- oldcontext = MemoryContextSwitchTo(per_query_ctx);
-
- tupstore = tuplestore_begin_heap(true, false, work_mem);
- rsinfo->returnMode = SFRM_Materialize;
- rsinfo->setResult = tupstore;
- rsinfo->setDesc = tupdesc;
-
- MemoryContextSwitchTo(oldcontext);
+ SetSingleFuncCall(fcinfo, 0);
/* Read the extension's control file */
control = read_extension_control_file(NameStr(*extname));
pfree(pathbuf.data);
}
- tuplestore_putvalues(tupstore, tupdesc, values, nulls);
+ tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
+ values, nulls);
}
}
pg_prepared_statement(PG_FUNCTION_ARGS)
{
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
- TupleDesc tupdesc;
- Tuplestorestate *tupstore;
- MemoryContext per_query_ctx;
- MemoryContext oldcontext;
-
- /* check to see if caller supports us returning a tuplestore */
- 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->allowedModes & SFRM_Materialize))
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("materialize mode required, but it is not allowed in this context")));
-
- if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
- elog(ERROR, "return type must be a row type");
-
- /* need to build tuplestore in query context */
- per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
- oldcontext = MemoryContextSwitchTo(per_query_ctx);
/*
* We put all the tuples into a tuplestore in one scan of the hashtable.
* This avoids any issue of the hashtable possibly changing between calls.
*/
- tupstore =
- tuplestore_begin_heap(rsinfo->allowedModes & SFRM_Materialize_Random,
- false, work_mem);
- rsinfo->returnMode = SFRM_Materialize;
- rsinfo->setResult = tupstore;
- rsinfo->setDesc = tupdesc;
-
- /* generate junk in short-term context */
- MemoryContextSwitchTo(oldcontext);
+ SetSingleFuncCall(fcinfo, 0);
/* hash table might be uninitialized */
if (prepared_queries)
values[5] = Int64GetDatumFast(prep_stmt->plansource->num_generic_plans);
values[6] = Int64GetDatumFast(prep_stmt->plansource->num_custom_plans);
- tuplestore_putvalues(tupstore, tupdesc, values, nulls);
+ tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
+ values, nulls);
}
}
#include "catalog/pg_user_mapping.h"
#include "foreign/fdwapi.h"
#include "foreign/foreign.h"
+#include "funcapi.h"
#include "lib/stringinfo.h"
#include "miscadmin.h"
#include "utils/builtins.h"
ListCell *cell;
List *options;
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
- TupleDesc tupdesc;
- Tuplestorestate *tupstore;
- MemoryContext per_query_ctx;
- MemoryContext oldcontext;
-
- /* check to see if caller supports us returning a tuplestore */
- 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->allowedModes & SFRM_Materialize) ||
- rsinfo->expectedDesc == NULL)
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("materialize mode required, but it is not allowed in this context")));
options = untransformRelOptions(array);
rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
- per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
- oldcontext = MemoryContextSwitchTo(per_query_ctx);
-
- /*
- * Now prepare the result set.
- */
- tupdesc = CreateTupleDescCopy(rsinfo->expectedDesc);
- tupstore = tuplestore_begin_heap(true, false, work_mem);
- rsinfo->returnMode = SFRM_Materialize;
- rsinfo->setResult = tupstore;
- rsinfo->setDesc = tupdesc;
-
- MemoryContextSwitchTo(oldcontext);
+ /* prepare the result set */
+ SetSingleFuncCall(fcinfo, SRF_SINGLE_USE_EXPECTED);
foreach(cell, options)
{
values[1] = (Datum) 0;
nulls[1] = true;
}
- tuplestore_putvalues(tupstore, tupdesc, values, nulls);
+ tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
+ values, nulls);
}
return (Datum) 0;
if (parsedline->auth_method == uaCert)
{
/*
- * For auth method cert, client certificate validation is mandatory, and it implies
- * the level of verify-full.
+ * For auth method cert, client certificate validation is mandatory,
+ * and it implies the level of verify-full.
*/
parsedline->clientcert = clientCertFull;
}
Datum
pg_hba_file_rules(PG_FUNCTION_ARGS)
{
- Tuplestorestate *tuple_store;
- TupleDesc tupdesc;
- MemoryContext old_cxt;
ReturnSetInfo *rsi;
/*
- * We must use the Materialize mode to be safe against HBA file changes
- * while the cursor is open. It's also more efficient than having to look
- * up our current position in the parsed list every time.
+ * Build tuplestore to hold the result rows. We must use the Materialize
+ * mode to be safe against HBA file changes while the cursor is open.
+ * It's also more efficient than having to look up our current position in
+ * the parsed list every time.
*/
- rsi = (ReturnSetInfo *) fcinfo->resultinfo;
-
- /* Check to see if caller supports us returning a tuplestore */
- if (rsi == NULL || !IsA(rsi, ReturnSetInfo))
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("set-valued function called in context that cannot accept a set")));
- if (!(rsi->allowedModes & SFRM_Materialize))
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("materialize mode required, but it is not allowed in this context")));
-
- rsi->returnMode = SFRM_Materialize;
-
- /* Build a tuple descriptor for our result type */
- if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
- elog(ERROR, "return type must be a row type");
-
- /* Build tuplestore to hold the result rows */
- old_cxt = MemoryContextSwitchTo(rsi->econtext->ecxt_per_query_memory);
-
- tuple_store =
- tuplestore_begin_heap(rsi->allowedModes & SFRM_Materialize_Random,
- false, work_mem);
- rsi->setDesc = tupdesc;
- rsi->setResult = tuple_store;
-
- MemoryContextSwitchTo(old_cxt);
+ SetSingleFuncCall(fcinfo, 0);
/* Fill the tuplestore */
- fill_hba_view(tuple_store, tupdesc);
+ rsi = (ReturnSetInfo *) fcinfo->resultinfo;
+ fill_hba_view(rsi->setResult, rsi->setDesc);
PG_RETURN_NULL();
}
Oid subid = PG_ARGISNULL(0) ? InvalidOid : PG_GETARG_OID(0);
int i;
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
- TupleDesc tupdesc;
- Tuplestorestate *tupstore;
- MemoryContext per_query_ctx;
- MemoryContext oldcontext;
- /* check to see if caller supports us returning a tuplestore */
- 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->allowedModes & SFRM_Materialize))
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("materialize mode required, but it is not allowed in this context")));
-
- /* Build a tuple descriptor for our result type */
- if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
- elog(ERROR, "return type must be a row type");
-
- per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
- oldcontext = MemoryContextSwitchTo(per_query_ctx);
-
- tupstore = tuplestore_begin_heap(true, false, work_mem);
- rsinfo->returnMode = SFRM_Materialize;
- rsinfo->setResult = tupstore;
- rsinfo->setDesc = tupdesc;
-
- MemoryContextSwitchTo(oldcontext);
+ SetSingleFuncCall(fcinfo, 0);
/* Make sure we get consistent view of the workers. */
LWLockAcquire(LogicalRepWorkerLock, LW_SHARED);
else
values[7] = TimestampTzGetDatum(worker.reply_time);
- tuplestore_putvalues(tupstore, tupdesc, values, nulls);
+ tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
+ values, nulls);
/*
* If only a single subscription was requested, and we found it,
errmsg("options array must not be null")));
arr = PG_GETARG_ARRAYTYPE_P(3);
- /* check to see if caller supports us returning a tuplestore */
- 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->allowedModes & SFRM_Materialize))
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("materialize mode required, but it is not allowed in this context")));
-
/* state to write output to */
p = palloc0(sizeof(DecodingOutputState));
p->binary_output = binary;
- /* Build a tuple descriptor for our result type */
- if (get_call_result_type(fcinfo, NULL, &p->tupdesc) != TYPEFUNC_COMPOSITE)
- elog(ERROR, "return type must be a row type");
-
per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
oldcontext = MemoryContextSwitchTo(per_query_ctx);
}
}
- p->tupstore = tuplestore_begin_heap(true, false, work_mem);
- rsinfo->returnMode = SFRM_Materialize;
- rsinfo->setResult = p->tupstore;
- rsinfo->setDesc = p->tupdesc;
+ SetSingleFuncCall(fcinfo, 0);
+ p->tupstore = rsinfo->setResult;
+ p->tupdesc = rsinfo->setDesc;
/*
* Compute the current end-of-wal.
pg_show_replication_origin_status(PG_FUNCTION_ARGS)
{
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
- TupleDesc tupdesc;
- Tuplestorestate *tupstore;
- MemoryContext per_query_ctx;
- MemoryContext oldcontext;
int i;
#define REPLICATION_ORIGIN_PROGRESS_COLS 4
/* we want to return 0 rows if slot is set to zero */
replorigin_check_prerequisites(false, true);
- 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->allowedModes & SFRM_Materialize))
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("materialize mode required, but it is not allowed in this context")));
- if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
- elog(ERROR, "return type must be a row type");
-
- if (tupdesc->natts != REPLICATION_ORIGIN_PROGRESS_COLS)
- elog(ERROR, "wrong function definition");
-
- per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
- oldcontext = MemoryContextSwitchTo(per_query_ctx);
-
- tupstore = tuplestore_begin_heap(true, false, work_mem);
- rsinfo->returnMode = SFRM_Materialize;
- rsinfo->setResult = tupstore;
- rsinfo->setDesc = tupdesc;
-
- MemoryContextSwitchTo(oldcontext);
-
+ SetSingleFuncCall(fcinfo, 0);
/* prevent slots from being concurrently dropped */
LWLockAcquire(ReplicationOriginLock, LW_SHARED);
LWLockRelease(&state->lock);
- tuplestore_putvalues(tupstore, tupdesc, values, nulls);
+ tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
+ values, nulls);
}
LWLockRelease(ReplicationOriginLock);
{
#define PG_GET_REPLICATION_SLOTS_COLS 14
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
- TupleDesc tupdesc;
- Tuplestorestate *tupstore;
- MemoryContext per_query_ctx;
- MemoryContext oldcontext;
XLogRecPtr currlsn;
int slotno;
- /* check to see if caller supports us returning a tuplestore */
- 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->allowedModes & SFRM_Materialize))
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("materialize mode required, but it is not allowed in this context")));
-
- /* Build a tuple descriptor for our result type */
- if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
- elog(ERROR, "return type must be a row type");
-
/*
* We don't require any special permission to see this function's data
* because nothing should be sensitive. The most critical being the slot
* name, which shouldn't contain anything particularly sensitive.
*/
- per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
- oldcontext = MemoryContextSwitchTo(per_query_ctx);
-
- tupstore = tuplestore_begin_heap(true, false, work_mem);
- rsinfo->returnMode = SFRM_Materialize;
- rsinfo->setResult = tupstore;
- rsinfo->setDesc = tupdesc;
-
- MemoryContextSwitchTo(oldcontext);
+ SetSingleFuncCall(fcinfo, 0);
currlsn = GetXLogWriteRecPtr();
Assert(i == PG_GET_REPLICATION_SLOTS_COLS);
- tuplestore_putvalues(tupstore, tupdesc, values, nulls);
+ tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
+ values, nulls);
}
LWLockRelease(ReplicationSlotControlLock);
{
#define PG_STAT_GET_WAL_SENDERS_COLS 12
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
- TupleDesc tupdesc;
- Tuplestorestate *tupstore;
- MemoryContext per_query_ctx;
- MemoryContext oldcontext;
SyncRepStandbyData *sync_standbys;
int num_standbys;
int i;
- /* check to see if caller supports us returning a tuplestore */
- 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->allowedModes & SFRM_Materialize))
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("materialize mode required, but it is not allowed in this context")));
-
- /* Build a tuple descriptor for our result type */
- if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
- elog(ERROR, "return type must be a row type");
-
- per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
- oldcontext = MemoryContextSwitchTo(per_query_ctx);
-
- tupstore = tuplestore_begin_heap(true, false, work_mem);
- rsinfo->returnMode = SFRM_Materialize;
- rsinfo->setResult = tupstore;
- rsinfo->setDesc = tupdesc;
-
- MemoryContextSwitchTo(oldcontext);
+ SetSingleFuncCall(fcinfo, 0);
/*
* Get the currently active synchronous standbys. This could be out of
values[11] = TimestampTzGetDatum(replyTime);
}
- tuplestore_putvalues(tupstore, tupdesc, values, nulls);
+ tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
+ values, nulls);
}
return (Datum) 0;
{
#define PG_GET_SHMEM_SIZES_COLS 4
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
- TupleDesc tupdesc;
- Tuplestorestate *tupstore;
- MemoryContext per_query_ctx;
- MemoryContext oldcontext;
HASH_SEQ_STATUS hstat;
ShmemIndexEnt *ent;
Size named_allocated = 0;
Datum values[PG_GET_SHMEM_SIZES_COLS];
bool nulls[PG_GET_SHMEM_SIZES_COLS];
- /* check to see if caller supports us returning a tuplestore */
- 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->allowedModes & SFRM_Materialize))
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("materialize mode required, but it is not allowed in this context")));
-
- /* Build a tuple descriptor for our result type */
- if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
- elog(ERROR, "return type must be a row type");
-
- per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
- oldcontext = MemoryContextSwitchTo(per_query_ctx);
-
- tupstore = tuplestore_begin_heap(true, false, work_mem);
- rsinfo->returnMode = SFRM_Materialize;
- rsinfo->setResult = tupstore;
- rsinfo->setDesc = tupdesc;
-
- MemoryContextSwitchTo(oldcontext);
+ SetSingleFuncCall(fcinfo, 0);
LWLockAcquire(ShmemIndexLock, LW_SHARED);
values[3] = Int64GetDatum(ent->allocated_size);
named_allocated += ent->allocated_size;
- tuplestore_putvalues(tupstore, tupdesc, values, nulls);
+ tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
+ values, nulls);
}
/* output shared memory allocated but not counted via the shmem index */
nulls[1] = true;
values[2] = Int64GetDatum(ShmemSegHdr->freeoffset - named_allocated);
values[3] = values[2];
- tuplestore_putvalues(tupstore, tupdesc, values, nulls);
+ tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
/* output as-of-yet unused shared memory */
nulls[0] = true;
nulls[1] = false;
values[2] = Int64GetDatum(ShmemSegHdr->totalsize - ShmemSegHdr->freeoffset);
values[3] = values[2];
- tuplestore_putvalues(tupstore, tupdesc, values, nulls);
+ tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
LWLockRelease(ShmemIndexLock);
pg_timezone_names(PG_FUNCTION_ARGS)
{
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
- bool randomAccess;
- TupleDesc tupdesc;
- Tuplestorestate *tupstore;
pg_tzenum *tzenum;
pg_tz *tz;
Datum values[4];
const char *tzn;
Interval *resInterval;
struct pg_tm itm;
- MemoryContext oldcontext;
- /* check to see if caller supports us returning a tuplestore */
- 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->allowedModes & SFRM_Materialize))
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("materialize mode required, but it is not allowed in this context")));
-
- /* The tupdesc and tuplestore must be created in ecxt_per_query_memory */
- oldcontext = MemoryContextSwitchTo(rsinfo->econtext->ecxt_per_query_memory);
-
- if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
- elog(ERROR, "return type must be a row type");
-
- randomAccess = (rsinfo->allowedModes & SFRM_Materialize_Random) != 0;
- tupstore = tuplestore_begin_heap(randomAccess, false, work_mem);
- rsinfo->returnMode = SFRM_Materialize;
- rsinfo->setResult = tupstore;
- rsinfo->setDesc = tupdesc;
-
- MemoryContextSwitchTo(oldcontext);
+ SetSingleFuncCall(fcinfo, 0);
/* initialize timezone scanning code */
tzenum = pg_tzenumerate_start();
values[3] = BoolGetDatum(tm.tm_isdst > 0);
- tuplestore_putvalues(tupstore, tupdesc, values, nulls);
+ tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
}
pg_tzenumerate_end(tzenum);
char *location;
bool missing_ok = false;
bool include_dot_dirs = false;
- bool randomAccess;
- TupleDesc tupdesc;
- Tuplestorestate *tupstore;
DIR *dirdesc;
struct dirent *de;
- MemoryContext oldcontext;
location = convert_and_check_filename(PG_GETARG_TEXT_PP(0));
include_dot_dirs = PG_GETARG_BOOL(2);
}
- /* check to see if caller supports us returning a tuplestore */
- 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->allowedModes & SFRM_Materialize))
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("materialize mode required, but it is not allowed in this context")));
-
- /* The tupdesc and tuplestore must be created in ecxt_per_query_memory */
- oldcontext = MemoryContextSwitchTo(rsinfo->econtext->ecxt_per_query_memory);
-
- tupdesc = CreateTemplateTupleDesc(1);
- TupleDescInitEntry(tupdesc, (AttrNumber) 1, "pg_ls_dir", TEXTOID, -1, 0);
-
- randomAccess = (rsinfo->allowedModes & SFRM_Materialize_Random) != 0;
- tupstore = tuplestore_begin_heap(randomAccess, false, work_mem);
- rsinfo->returnMode = SFRM_Materialize;
- rsinfo->setResult = tupstore;
- rsinfo->setDesc = tupdesc;
-
- MemoryContextSwitchTo(oldcontext);
+ SetSingleFuncCall(fcinfo, SRF_SINGLE_USE_EXPECTED);
dirdesc = AllocateDir(location);
if (!dirdesc)
values[0] = CStringGetTextDatum(de->d_name);
nulls[0] = false;
- tuplestore_putvalues(tupstore, tupdesc, values, nulls);
+ tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
+ values, nulls);
}
FreeDir(dirdesc);
pg_ls_dir_files(FunctionCallInfo fcinfo, const char *dir, bool missing_ok)
{
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
- bool randomAccess;
- TupleDesc tupdesc;
- Tuplestorestate *tupstore;
DIR *dirdesc;
struct dirent *de;
- MemoryContext oldcontext;
-
- /* check to see if caller supports us returning a tuplestore */
- 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->allowedModes & SFRM_Materialize))
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("materialize mode required, but it is not allowed in this context")));
-
- /* The tupdesc and tuplestore must be created in ecxt_per_query_memory */
- oldcontext = MemoryContextSwitchTo(rsinfo->econtext->ecxt_per_query_memory);
-
- if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
- elog(ERROR, "return type must be a row type");
-
- randomAccess = (rsinfo->allowedModes & SFRM_Materialize_Random) != 0;
- tupstore = tuplestore_begin_heap(randomAccess, false, work_mem);
- rsinfo->returnMode = SFRM_Materialize;
- rsinfo->setResult = tupstore;
- rsinfo->setDesc = tupdesc;
- MemoryContextSwitchTo(oldcontext);
+ SetSingleFuncCall(fcinfo, 0);
/*
* Now walk the directory. Note that we must do this within a single SRF
values[2] = TimestampTzGetDatum(time_t_to_timestamptz(attrib.st_mtime));
memset(nulls, 0, sizeof(nulls));
- tuplestore_putvalues(tupstore, tupdesc, values, nulls);
+ tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
}
FreeDir(dirdesc);
{
Jsonb *jb = PG_GETARG_JSONB_P(0);
ReturnSetInfo *rsi;
- Tuplestorestate *tuple_store;
- TupleDesc tupdesc;
- TupleDesc ret_tdesc;
MemoryContext old_cxt,
tmp_cxt;
bool skipNested = false;
funcname)));
rsi = (ReturnSetInfo *) fcinfo->resultinfo;
-
- if (!rsi || !IsA(rsi, ReturnSetInfo))
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("set-valued function called in context that cannot accept a set")));
- if (!(rsi->allowedModes & SFRM_Materialize))
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("materialize mode required, but it is not allowed in this context")));
-
- rsi->returnMode = SFRM_Materialize;
-
- if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
- elog(ERROR, "return type must be a row type");
-
- old_cxt = MemoryContextSwitchTo(rsi->econtext->ecxt_per_query_memory);
-
- ret_tdesc = CreateTupleDescCopy(tupdesc);
- BlessTupleDesc(ret_tdesc);
- tuple_store =
- tuplestore_begin_heap(rsi->allowedModes & SFRM_Materialize_Random,
- false, work_mem);
-
- MemoryContextSwitchTo(old_cxt);
+ SetSingleFuncCall(fcinfo, SRF_SINGLE_BLESS);
tmp_cxt = AllocSetContextCreate(CurrentMemoryContext,
"jsonb_each temporary cxt",
if (r == WJB_KEY)
{
text *key;
- HeapTuple tuple;
Datum values[2];
bool nulls[2] = {false, false};
values[1] = PointerGetDatum(val);
}
- tuple = heap_form_tuple(ret_tdesc, values, nulls);
-
- tuplestore_puttuple(tuple_store, tuple);
+ tuplestore_putvalues(rsi->setResult, rsi->setDesc, values, nulls);
/* clean up and switch back */
MemoryContextSwitchTo(old_cxt);
MemoryContextDelete(tmp_cxt);
- rsi->setResult = tuple_store;
- rsi->setDesc = ret_tdesc;
-
PG_RETURN_NULL();
}
JsonLexContext *lex;
JsonSemAction *sem;
ReturnSetInfo *rsi;
- MemoryContext old_cxt;
- TupleDesc tupdesc;
EachState *state;
lex = makeJsonLexContext(json, true);
rsi = (ReturnSetInfo *) fcinfo->resultinfo;
- if (!rsi || !IsA(rsi, ReturnSetInfo))
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("set-valued function called in context that cannot accept a set")));
-
- if (!(rsi->allowedModes & SFRM_Materialize))
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("materialize mode required, but it is not allowed in this context")));
-
- rsi->returnMode = SFRM_Materialize;
-
- (void) get_call_result_type(fcinfo, NULL, &tupdesc);
-
- /* make these in a sufficiently long-lived memory context */
- old_cxt = MemoryContextSwitchTo(rsi->econtext->ecxt_per_query_memory);
-
- state->ret_tdesc = CreateTupleDescCopy(tupdesc);
- BlessTupleDesc(state->ret_tdesc);
- state->tuple_store =
- tuplestore_begin_heap(rsi->allowedModes & SFRM_Materialize_Random,
- false, work_mem);
-
- MemoryContextSwitchTo(old_cxt);
+ SetSingleFuncCall(fcinfo, SRF_SINGLE_BLESS);
+ state->tuple_store = rsi->setResult;
+ state->ret_tdesc = rsi->setDesc;
sem->semstate = (void *) state;
sem->array_start = each_array_start;
MemoryContextDelete(state->tmp_cxt);
- rsi->setResult = state->tuple_store;
- rsi->setDesc = state->ret_tdesc;
-
PG_RETURN_NULL();
}
{
Jsonb *jb = PG_GETARG_JSONB_P(0);
ReturnSetInfo *rsi;
- Tuplestorestate *tuple_store;
- TupleDesc tupdesc;
- TupleDesc ret_tdesc;
MemoryContext old_cxt,
tmp_cxt;
bool skipNested = false;
rsi = (ReturnSetInfo *) fcinfo->resultinfo;
- if (!rsi || !IsA(rsi, ReturnSetInfo))
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("set-valued function called in context that cannot accept a set")));
-
- if (!(rsi->allowedModes & SFRM_Materialize) ||
- rsi->expectedDesc == NULL)
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("materialize mode required, but it is not allowed in this context")));
-
- rsi->returnMode = SFRM_Materialize;
-
- /* it's a simple type, so don't use get_call_result_type() */
- tupdesc = rsi->expectedDesc;
-
- old_cxt = MemoryContextSwitchTo(rsi->econtext->ecxt_per_query_memory);
-
- ret_tdesc = CreateTupleDescCopy(tupdesc);
- BlessTupleDesc(ret_tdesc);
- tuple_store =
- tuplestore_begin_heap(rsi->allowedModes & SFRM_Materialize_Random,
- false, work_mem);
-
- MemoryContextSwitchTo(old_cxt);
+ SetSingleFuncCall(fcinfo,
+ SRF_SINGLE_USE_EXPECTED | SRF_SINGLE_BLESS);
tmp_cxt = AllocSetContextCreate(CurrentMemoryContext,
"jsonb_array_elements temporary cxt",
if (r == WJB_ELEM)
{
- HeapTuple tuple;
Datum values[1];
bool nulls[1] = {false};
values[0] = PointerGetDatum(val);
}
- tuple = heap_form_tuple(ret_tdesc, values, nulls);
-
- tuplestore_puttuple(tuple_store, tuple);
+ tuplestore_putvalues(rsi->setResult, rsi->setDesc, values, nulls);
/* clean up and switch back */
MemoryContextSwitchTo(old_cxt);
MemoryContextDelete(tmp_cxt);
- rsi->setResult = tuple_store;
- rsi->setDesc = ret_tdesc;
-
PG_RETURN_NULL();
}
JsonLexContext *lex = makeJsonLexContext(json, as_text);
JsonSemAction *sem;
ReturnSetInfo *rsi;
- MemoryContext old_cxt;
- TupleDesc tupdesc;
ElementsState *state;
state = palloc0(sizeof(ElementsState));
sem = palloc0(sizeof(JsonSemAction));
+ SetSingleFuncCall(fcinfo, SRF_SINGLE_USE_EXPECTED | SRF_SINGLE_BLESS);
rsi = (ReturnSetInfo *) fcinfo->resultinfo;
-
- if (!rsi || !IsA(rsi, ReturnSetInfo))
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("set-valued function called in context that cannot accept a set")));
-
- if (!(rsi->allowedModes & SFRM_Materialize) ||
- rsi->expectedDesc == NULL)
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("materialize mode required, but it is not allowed in this context")));
-
- rsi->returnMode = SFRM_Materialize;
-
- /* it's a simple type, so don't use get_call_result_type() */
- tupdesc = rsi->expectedDesc;
-
- /* make these in a sufficiently long-lived memory context */
- old_cxt = MemoryContextSwitchTo(rsi->econtext->ecxt_per_query_memory);
-
- state->ret_tdesc = CreateTupleDescCopy(tupdesc);
- BlessTupleDesc(state->ret_tdesc);
- state->tuple_store =
- tuplestore_begin_heap(rsi->allowedModes & SFRM_Materialize_Random,
- false, work_mem);
-
- MemoryContextSwitchTo(old_cxt);
+ state->tuple_store = rsi->setResult;
+ state->ret_tdesc = rsi->setDesc;
sem->semstate = (void *) state;
sem->object_start = elements_object_start;
MemoryContextDelete(state->tmp_cxt);
- rsi->setResult = state->tuple_store;
- rsi->setDesc = state->ret_tdesc;
-
PG_RETURN_NULL();
}
pg_get_backend_memory_contexts(PG_FUNCTION_ARGS)
{
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
- TupleDesc tupdesc;
- Tuplestorestate *tupstore;
- MemoryContext per_query_ctx;
- MemoryContext oldcontext;
-
- /* check to see if caller supports us returning a tuplestore */
- 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->allowedModes & SFRM_Materialize))
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("materialize mode required, but it is not allowed in this context")));
-
- /* Build a tuple descriptor for our result type */
- if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
- elog(ERROR, "return type must be a row type");
-
- per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
- oldcontext = MemoryContextSwitchTo(per_query_ctx);
-
- tupstore = tuplestore_begin_heap(true, false, work_mem);
- rsinfo->returnMode = SFRM_Materialize;
- rsinfo->setResult = tupstore;
- rsinfo->setDesc = tupdesc;
-
- MemoryContextSwitchTo(oldcontext);
-
- PutMemoryContextsStatsTupleStore(tupstore, tupdesc,
+
+ SetSingleFuncCall(fcinfo, 0);
+ PutMemoryContextsStatsTupleStore(rsinfo->setResult, rsinfo->setDesc,
TopMemoryContext, NULL, 0);
return (Datum) 0;
{
Oid tablespaceOid = PG_GETARG_OID(0);
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
- bool randomAccess;
- TupleDesc tupdesc;
- Tuplestorestate *tupstore;
char *location;
DIR *dirdesc;
struct dirent *de;
- MemoryContext oldcontext;
- /* check to see if caller supports us returning a tuplestore */
- 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->allowedModes & SFRM_Materialize))
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("materialize mode required, but it is not allowed in this context")));
-
- /* The tupdesc and tuplestore must be created in ecxt_per_query_memory */
- oldcontext = MemoryContextSwitchTo(rsinfo->econtext->ecxt_per_query_memory);
-
- tupdesc = CreateTemplateTupleDesc(1);
- TupleDescInitEntry(tupdesc, (AttrNumber) 1, "pg_tablespace_databases",
- OIDOID, -1, 0);
-
- randomAccess = (rsinfo->allowedModes & SFRM_Materialize_Random) != 0;
- tupstore = tuplestore_begin_heap(randomAccess, false, work_mem);
-
- rsinfo->returnMode = SFRM_Materialize;
- rsinfo->setResult = tupstore;
- rsinfo->setDesc = tupdesc;
-
- MemoryContextSwitchTo(oldcontext);
+ SetSingleFuncCall(fcinfo, SRF_SINGLE_USE_EXPECTED);
if (tablespaceOid == GLOBALTABLESPACE_OID)
{
values[0] = ObjectIdGetDatum(datOid);
nulls[0] = false;
- tuplestore_putvalues(tupstore, tupdesc, values, nulls);
+ tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
+ values, nulls);
}
FreeDir(dirdesc);
int curr_backend;
char *cmd = text_to_cstring(PG_GETARG_TEXT_PP(0));
ProgressCommandType cmdtype;
- TupleDesc tupdesc;
- Tuplestorestate *tupstore;
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
- MemoryContext per_query_ctx;
- MemoryContext oldcontext;
-
- /* check to see if caller supports us returning a tuplestore */
- 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->allowedModes & SFRM_Materialize))
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("materialize mode required, but it is not allowed in this context")));
-
- /* Build a tuple descriptor for our result type */
- if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
- elog(ERROR, "return type must be a row type");
/* Translate command name into command type code. */
if (pg_strcasecmp(cmd, "VACUUM") == 0)
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("invalid command name: \"%s\"", cmd)));
- per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
- oldcontext = MemoryContextSwitchTo(per_query_ctx);
-
- tupstore = tuplestore_begin_heap(true, false, work_mem);
- rsinfo->returnMode = SFRM_Materialize;
- rsinfo->setResult = tupstore;
- rsinfo->setDesc = tupdesc;
- MemoryContextSwitchTo(oldcontext);
+ SetSingleFuncCall(fcinfo, 0);
/* 1-based index */
for (curr_backend = 1; curr_backend <= num_backends; curr_backend++)
nulls[i + 3] = true;
}
- tuplestore_putvalues(tupstore, tupdesc, values, nulls);
+ tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
}
return (Datum) 0;
int curr_backend;
int pid = PG_ARGISNULL(0) ? -1 : PG_GETARG_INT32(0);
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
- TupleDesc tupdesc;
- Tuplestorestate *tupstore;
- MemoryContext per_query_ctx;
- MemoryContext oldcontext;
-
- /* check to see if caller supports us returning a tuplestore */
- 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->allowedModes & SFRM_Materialize))
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("materialize mode required, but it is not allowed in this context")));
- /* Build a tuple descriptor for our result type */
- if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
- elog(ERROR, "return type must be a row type");
-
- per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
- oldcontext = MemoryContextSwitchTo(per_query_ctx);
-
- tupstore = tuplestore_begin_heap(true, false, work_mem);
- rsinfo->returnMode = SFRM_Materialize;
- rsinfo->setResult = tupstore;
- rsinfo->setDesc = tupdesc;
-
- MemoryContextSwitchTo(oldcontext);
+ SetSingleFuncCall(fcinfo, 0);
/* 1-based index */
for (curr_backend = 1; curr_backend <= num_backends; curr_backend++)
nulls[5] = false;
values[5] = CStringGetTextDatum("");
- tuplestore_putvalues(tupstore, tupdesc, values, nulls);
+ tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
continue;
}
nulls[29] = true;
}
- tuplestore_putvalues(tupstore, tupdesc, values, nulls);
+ tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
/* If only a single backend was requested, and we found it, break. */
if (pid != -1)
{
#define PG_STAT_GET_SLRU_COLS 9
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
- TupleDesc tupdesc;
- Tuplestorestate *tupstore;
- MemoryContext per_query_ctx;
- MemoryContext oldcontext;
int i;
PgStat_SLRUStats *stats;
- /* check to see if caller supports us returning a tuplestore */
- 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->allowedModes & SFRM_Materialize))
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("materialize mode required, but it is not allowed in this context")));
-
- /* Build a tuple descriptor for our result type */
- if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
- elog(ERROR, "return type must be a row type");
-
- per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
- oldcontext = MemoryContextSwitchTo(per_query_ctx);
-
- tupstore = tuplestore_begin_heap(true, false, work_mem);
- rsinfo->returnMode = SFRM_Materialize;
- rsinfo->setResult = tupstore;
- rsinfo->setDesc = tupdesc;
-
- MemoryContextSwitchTo(oldcontext);
+ SetSingleFuncCall(fcinfo, 0);
/* request SLRU stats from the stat collector */
stats = pgstat_fetch_slru();
values[7] = Int64GetDatum(stat.truncate);
values[8] = TimestampTzGetDatum(stat.stat_reset_timestamp);
- tuplestore_putvalues(tupstore, tupdesc, values, nulls);
+ tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
}
return (Datum) 0;
#include "common/hashfn.h"
#include "common/int.h"
#include "common/unicode_norm.h"
+#include "funcapi.h"
#include "lib/hyperloglog.h"
#include "libpq/pqformat.h"
#include "miscadmin.h"
{
ReturnSetInfo *rsi = (ReturnSetInfo *) fcinfo->resultinfo;
SplitTextOutputData tstate;
- MemoryContext old_cxt;
-
- /* check to see if caller supports us returning a tuplestore */
- if (rsi == NULL || !IsA(rsi, ReturnSetInfo))
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("set-valued function called in context that cannot accept a set")));
- if (!(rsi->allowedModes & SFRM_Materialize) ||
- rsi->expectedDesc == NULL)
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("materialize mode required, but it is not allowed in this context")));
-
- /* OK, prepare tuplestore in per-query memory */
- old_cxt = MemoryContextSwitchTo(rsi->econtext->ecxt_per_query_memory);
tstate.astate = NULL;
- tstate.tupdesc = CreateTupleDescCopy(rsi->expectedDesc);
- tstate.tupstore = tuplestore_begin_heap(true, false, work_mem);
-
- MemoryContextSwitchTo(old_cxt);
+ SetSingleFuncCall(fcinfo, SRF_SINGLE_USE_EXPECTED);
+ tstate.tupstore = rsi->setResult;
+ tstate.tupdesc = rsi->setDesc;
(void) split_text(fcinfo, &tstate);
- rsi->returnMode = SFRM_Materialize;
- rsi->setResult = tstate.tupstore;
- rsi->setDesc = tstate.tupdesc;
-
return (Datum) 0;
}
in other contexts the expectedDesc field will be NULL. The function need
not pay attention to expectedDesc, but it may be useful in special cases.
+SetSingleFuncCall() is a helper function able to setup the function's
+ReturnSetInfo for a single call, filling in the Tuplestore and the
+TupleDesc with the proper configuration for Materialize mode.
+
There is no support for functions accepting sets; instead, the function will
be called multiple times, once for each element of the input set.
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
#include "funcapi.h"
+#include "miscadmin.h"
#include "nodes/nodeFuncs.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/regproc.h"
#include "utils/rel.h"
#include "utils/syscache.h"
+#include "utils/tuplestore.h"
#include "utils/typcache.h"
static TypeFuncClass get_type_func_class(Oid typid, Oid *base_typeid);
+/*
+ * SetSingleFuncCall
+ *
+ * Helper function to build the state of a set-returning function used
+ * in the context of a single call with materialize mode. This code
+ * includes sanity checks on ReturnSetInfo, creates the Tuplestore and
+ * the TupleDesc used with the function and stores them into the
+ * function's ReturnSetInfo.
+ *
+ * "flags" can be set to SRF_SINGLE_USE_EXPECTED, to use the tuple
+ * descriptor coming from expectedDesc, which is the tuple descriptor
+ * expected by the caller. SRF_SINGLE_BLESS can be set to complete the
+ * information associated to the tuple descriptor, which is necessary
+ * in some cases where the tuple descriptor comes from a transient
+ * RECORD datatype.
+ */
+void
+SetSingleFuncCall(FunctionCallInfo fcinfo, bits32 flags)
+{
+ bool random_access;
+ ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
+ Tuplestorestate *tupstore;
+ MemoryContext old_context,
+ per_query_ctx;
+ TupleDesc stored_tupdesc;
+
+ /* check to see if caller supports returning a tuplestore */
+ 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->allowedModes & SFRM_Materialize) ||
+ ((flags & SRF_SINGLE_USE_EXPECTED) != 0 && rsinfo->expectedDesc == NULL))
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("materialize mode required, but it is not allowed in this context")));
+
+ /*
+ * Store the tuplestore and the tuple descriptor in ReturnSetInfo. This
+ * must be done in the per-query memory context.
+ */
+ per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
+ old_context = MemoryContextSwitchTo(per_query_ctx);
+
+ /* build a tuple descriptor for our result type */
+ if ((flags & SRF_SINGLE_USE_EXPECTED) != 0)
+ stored_tupdesc = CreateTupleDescCopy(rsinfo->expectedDesc);
+ else
+ {
+ if (get_call_result_type(fcinfo, NULL, &stored_tupdesc) != TYPEFUNC_COMPOSITE)
+ elog(ERROR, "return type must be a row type");
+ }
+
+ /* If requested, bless the tuple descriptor */
+ if ((flags & SRF_SINGLE_BLESS) != 0)
+ BlessTupleDesc(stored_tupdesc);
+
+ random_access = (rsinfo->allowedModes & SFRM_Materialize_Random) != 0;
+
+ tupstore = tuplestore_begin_heap(random_access, false, work_mem);
+ rsinfo->returnMode = SFRM_Materialize;
+ rsinfo->setResult = tupstore;
+ rsinfo->setDesc = stored_tupdesc;
+ MemoryContextSwitchTo(old_context);
+}
+
+
/*
* init_MultiFuncCall
* Create an empty FuncCallContext data structure
{
#define NUM_PG_FILE_SETTINGS_ATTS 7
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
- TupleDesc tupdesc;
- Tuplestorestate *tupstore;
ConfigVariable *conf;
int seqno;
- MemoryContext per_query_ctx;
- MemoryContext oldcontext;
-
- /* Check to see if caller supports us returning a tuplestore */
- 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->allowedModes & SFRM_Materialize))
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("materialize mode required, but it is not allowed in this context")));
-
- if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
- elog(ERROR, "return type must be a row type");
/* Scan the config files using current context as workspace */
conf = ProcessConfigFileInternal(PGC_SIGHUP, false, DEBUG3);
- /* Switch into long-lived context to construct returned data structures */
- per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
- oldcontext = MemoryContextSwitchTo(per_query_ctx);
-
/* Build a tuplestore to return our results in */
- tupstore = tuplestore_begin_heap(true, false, work_mem);
- rsinfo->returnMode = SFRM_Materialize;
- rsinfo->setResult = tupstore;
- rsinfo->setDesc = tupdesc;
-
- /* The rest can be done in short-lived context */
- MemoryContextSwitchTo(oldcontext);
+ SetSingleFuncCall(fcinfo, 0);
/* Process the results and create a tuplestore */
for (seqno = 1; conf != NULL; conf = conf->next, seqno++)
nulls[6] = true;
/* shove row into tuplestore */
- tuplestore_putvalues(tupstore, tupdesc, values, nulls);
+ tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
}
return (Datum) 0;
pg_config(PG_FUNCTION_ARGS)
{
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
- Tuplestorestate *tupstore;
- TupleDesc tupdesc;
- MemoryContext oldcontext;
ConfigData *configdata;
size_t configdata_len;
int i = 0;
- /* check to see if caller supports us returning a tuplestore */
- 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->allowedModes & SFRM_Materialize))
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("materialize mode required, but it is not allowed in this context")));
-
- if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
- elog(ERROR, "return type must be a row type");
-
- /* Build tuplestore to hold the result rows */
- oldcontext = MemoryContextSwitchTo(rsinfo->econtext->ecxt_per_query_memory);
-
- tupstore = tuplestore_begin_heap(true, false, work_mem);
- rsinfo->returnMode = SFRM_Materialize;
- rsinfo->setResult = tupstore;
- rsinfo->setDesc = tupdesc;
-
- MemoryContextSwitchTo(oldcontext);
+ /* initialize our tuplestore */
+ SetSingleFuncCall(fcinfo, 0);
configdata = get_configdata(my_exec_path, &configdata_len);
for (i = 0; i < configdata_len; i++)
values[0] = CStringGetTextDatum(configdata[i].name);
values[1] = CStringGetTextDatum(configdata[i].setting);
- tuplestore_putvalues(tupstore, tupdesc, values, nulls);
+ tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
}
return (Datum) 0;
pg_cursor(PG_FUNCTION_ARGS)
{
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
- TupleDesc tupdesc;
- Tuplestorestate *tupstore;
- MemoryContext per_query_ctx;
- MemoryContext oldcontext;
HASH_SEQ_STATUS hash_seq;
PortalHashEnt *hentry;
- /* check to see if caller supports us returning a tuplestore */
- 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->allowedModes & SFRM_Materialize))
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("materialize mode required, but it is not allowed in this context")));
-
- /* need to build tuplestore in query 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");
-
/*
* We put all the tuples into a tuplestore in one scan of the hashtable.
* This avoids any issue of the hashtable possibly changing between calls.
*/
- tupstore =
- tuplestore_begin_heap(rsinfo->allowedModes & SFRM_Materialize_Random,
- false, work_mem);
- rsinfo->returnMode = SFRM_Materialize;
- rsinfo->setResult = tupstore;
- rsinfo->setDesc = tupdesc;
-
- /* generate junk in short-term context */
- MemoryContextSwitchTo(oldcontext);
+ SetSingleFuncCall(fcinfo, 0);
hash_seq_init(&hash_seq, PortalHashTable);
while ((hentry = hash_seq_search(&hash_seq)) != NULL)
values[4] = BoolGetDatum(portal->cursorOptions & CURSOR_OPT_SCROLL);
values[5] = TimestampTzGetDatum(portal->creation_time);
- tuplestore_putvalues(tupstore, tupdesc, values, nulls);
+ tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
}
- rsinfo->returnMode = SFRM_Materialize;
- rsinfo->setResult = tupstore;
- rsinfo->setDesc = tupdesc;
-
return (Datum) 0;
}
* memory allocated in multi_call_memory_ctx, but holding file descriptors or
* other non-memory resources open across calls is a bug. SRFs that need
* such resources should not use these macros, but instead populate a
- * tuplestore during a single call, and return that using SFRM_Materialize
- * mode (see fmgr/README). Alternatively, set up a callback to release
- * resources at query shutdown, using RegisterExprContextCallback().
+ * tuplestore during a single call, as set up by SetSingleFuncCall() (see
+ * fmgr/README). Alternatively, set up a callback to release resources
+ * at query shutdown, using RegisterExprContextCallback().
*
*----------
*/
/* from funcapi.c */
+
+/* flag bits for SetSingleFuncCall() */
+#define SRF_SINGLE_USE_EXPECTED 0x01 /* use expectedDesc as tupdesc */
+#define SRF_SINGLE_BLESS 0x02 /* validate tuple for SRF */
+extern void SetSingleFuncCall(FunctionCallInfo fcinfo, bits32 flags);
+
extern FuncCallContext *init_MultiFuncCall(PG_FUNCTION_ARGS);
extern FuncCallContext *per_MultiFuncCall(PG_FUNCTION_ARGS);
extern void end_MultiFuncCall(PG_FUNCTION_ARGS, FuncCallContext *funcctx);