static void report_corruption(HeapCheckContext *ctx, char *msg);
static void report_toast_corruption(HeapCheckContext *ctx,
ToastedAttribute *ta, char *msg);
-static TupleDesc verify_heapam_tupdesc(void);
static FullTransactionId FullTransactionIdFromXidAndCtx(TransactionId xid,
const HeapCheckContext *ctx);
static void update_cached_xid_range(HeapCheckContext *ctx);
verify_heapam(PG_FUNCTION_ARGS)
{
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
- MemoryContext old_context;
- bool random_access;
HeapCheckContext ctx;
Buffer vmbuffer = InvalidBuffer;
Oid relid;
BlockNumber nblocks;
const char *skip;
- /* 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")));
-
/* Check supplied arguments */
if (PG_ARGISNULL(0))
ereport(ERROR,
*/
ctx.attnum = -1;
- /* The tupdesc and tuplestore must be created in ecxt_per_query_memory */
- old_context = MemoryContextSwitchTo(rsinfo->econtext->ecxt_per_query_memory);
- random_access = (rsinfo->allowedModes & SFRM_Materialize_Random) != 0;
- ctx.tupdesc = verify_heapam_tupdesc();
- ctx.tupstore = tuplestore_begin_heap(random_access, false, work_mem);
- rsinfo->returnMode = SFRM_Materialize;
- rsinfo->setResult = ctx.tupstore;
- rsinfo->setDesc = ctx.tupdesc;
- MemoryContextSwitchTo(old_context);
+ /* Construct the tuplestore and tuple descriptor */
+ SetSingleFuncCall(fcinfo, 0);
+ ctx.tupdesc = rsinfo->setDesc;
+ ctx.tupstore = rsinfo->setResult;
/* Open relation, check relkind and access method */
ctx.rel = relation_open(relid, AccessShareLock);
ctx->is_corrupt = true;
}
-/*
- * Construct the TupleDesc used to report messages about corruptions found
- * while scanning the heap.
- */
-static TupleDesc
-verify_heapam_tupdesc(void)
-{
- TupleDesc tupdesc;
- AttrNumber a = 0;
-
- tupdesc = CreateTemplateTupleDesc(HEAPCHECK_RELATION_COLS);
- TupleDescInitEntry(tupdesc, ++a, "blkno", INT8OID, -1, 0);
- TupleDescInitEntry(tupdesc, ++a, "offnum", INT4OID, -1, 0);
- TupleDescInitEntry(tupdesc, ++a, "attnum", INT4OID, -1, 0);
- TupleDescInitEntry(tupdesc, ++a, "msg", TEXTOID, -1, 0);
- Assert(a == HEAPCHECK_RELATION_COLS);
-
- return BlessTupleDesc(tupdesc);
-}
-
/*
* Check for tuple header corruption.
*
PGconn *conn;
PGnotify *notify;
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
- TupleDesc tupdesc;
- Tuplestorestate *tupstore;
- MemoryContext per_query_ctx;
- MemoryContext oldcontext;
-
- prepTuplestoreResult(fcinfo);
dblink_init();
if (PG_NARGS() == 1)
else
conn = pconn->conn;
- /* create the tuplestore in per-query memory */
- per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
- oldcontext = MemoryContextSwitchTo(per_query_ctx);
-
- tupdesc = CreateTemplateTupleDesc(DBLINK_NOTIFY_COLS);
- TupleDescInitEntry(tupdesc, (AttrNumber) 1, "notify_name",
- TEXTOID, -1, 0);
- TupleDescInitEntry(tupdesc, (AttrNumber) 2, "be_pid",
- INT4OID, -1, 0);
- TupleDescInitEntry(tupdesc, (AttrNumber) 3, "extra",
- TEXTOID, -1, 0);
-
- tupstore = tuplestore_begin_heap(true, false, work_mem);
- rsinfo->setResult = tupstore;
- rsinfo->setDesc = tupdesc;
-
- MemoryContextSwitchTo(oldcontext);
+ SetSingleFuncCall(fcinfo, 0);
PQconsumeInput(conn);
while ((notify = PQnotifies(conn)) != NULL)
else
nulls[2] = true;
- tuplestore_putvalues(tupstore, tupdesc, values, nulls);
+ tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
PQfreemem(notify);
PQconsumeInput(conn);
bytea *raw_page = PG_GETARG_BYTEA_P(0);
Oid indexRelid = PG_GETARG_OID(1);
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
- TupleDesc tupdesc;
- MemoryContext oldcontext;
- Tuplestorestate *tupstore;
Relation indexRel;
brin_column_state **columns;
BrinDesc *bdesc;
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser to use raw page functions")));
- /* 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 */
- 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);
+ SetSingleFuncCall(fcinfo, 0);
indexRel = index_open(indexRelid, AccessShareLock);
bdesc = brin_build_desc(indexRel);
int att = attno - 1;
values[0] = UInt16GetDatum(offset);
- switch (TupleDescAttr(tupdesc, 1)->atttypid)
+ switch (TupleDescAttr(rsinfo->setDesc, 1)->atttypid)
{
case INT8OID:
values[1] = Int64GetDatum((int64) dtup->bt_blkno);
}
}
- tuplestore_putvalues(tupstore, tupdesc, values, nulls);
+ tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
/*
* If the item was unused, jump straight to the next one; otherwise,
{
bytea *raw_page = PG_GETARG_BYTEA_P(0);
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
- bool randomAccess;
- TupleDesc tupdesc;
- Tuplestorestate *tupstore;
- MemoryContext oldcontext;
Page page;
OffsetNumber offset;
OffsetNumber maxoff = InvalidOffsetNumber;
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser to use raw page functions")));
- /* 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);
page = get_page_from_raw(raw_page);
values[3] = BoolGetDatum(ItemIdIsDead(id));
values[4] = PointerGetDatum(tuple_bytea);
- tuplestore_putvalues(tupstore, tupdesc, values, nulls);
+ tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
}
return (Datum) 0;
bytea *raw_page = PG_GETARG_BYTEA_P(0);
Oid indexRelid = PG_GETARG_OID(1);
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
- bool randomAccess;
Relation indexRel;
- TupleDesc tupdesc;
- Tuplestorestate *tupstore;
- MemoryContext oldcontext;
Page page;
OffsetNumber offset;
OffsetNumber maxoff = InvalidOffsetNumber;
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser to use raw page functions")));
- /* 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);
/* Open the relation */
indexRel = index_open(indexRelid, AccessShareLock);
nulls[4] = true;
}
- tuplestore_putvalues(tupstore, tupdesc, values, nulls);
+ tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
}
relation_close(indexRel, AccessShareLock);
bool showtext)
{
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
- TupleDesc tupdesc;
- Tuplestorestate *tupstore;
- MemoryContext per_query_ctx;
- MemoryContext oldcontext;
Oid userid = GetUserId();
bool is_allowed_role = false;
char *qbuffer = NULL;
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("pg_stat_statements must be loaded via shared_preload_libraries")));
- /* 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")));
-
- /* 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 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");
+ SetSingleFuncCall(fcinfo, 0);
/*
* Check we have the expected number of output arguments. Aside from
* being a good safety check, we need a kluge here to detect API version
* 1.1, which was wedged into the code in an ill-considered way.
*/
- switch (tupdesc->natts)
+ switch (rsinfo->setDesc->natts)
{
case PG_STAT_STATEMENTS_COLS_V1_0:
if (api_version != PGSS_V1_0)
elog(ERROR, "incorrect number of output arguments");
}
- tupstore = tuplestore_begin_heap(true, false, work_mem);
- rsinfo->returnMode = SFRM_Materialize;
- rsinfo->setResult = tupstore;
- rsinfo->setDesc = tupdesc;
-
- MemoryContextSwitchTo(oldcontext);
-
/*
* We'd like to load the query text file (if needed) while not holding any
* lock on pgss->lock. In the worst case we'll have to do this again
api_version == PGSS_V1_9 ? PG_STAT_STATEMENTS_COLS_V1_9 :
-1 /* fail if you forget to update this assert */ ));
- tuplestore_putvalues(tupstore, tupdesc, values, nulls);
+ tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
}
LWLockRelease(pgss->lock);
{
text *relname = PG_GETARG_TEXT_PP(0);
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
- bool randomAccess;
- TupleDesc tupdesc;
- Tuplestorestate *tupstore;
AttInMetadata *attinmeta;
Relation rel;
RangeVar *relrv;
TableScanDesc scan;
HeapScanDesc hscan;
HeapTuple tuple;
- MemoryContext oldcontext;
AclResult aclresult;
char **values;
- /* 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);
/* Access the table */
relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname));
scan = table_beginscan(rel, GetActiveSnapshot(), 0, NULL);
hscan = (HeapScanDesc) scan;
- attinmeta = TupleDescGetAttInMetadata(tupdesc);
+ attinmeta = TupleDescGetAttInMetadata(rsinfo->setDesc);
- values = (char **) palloc(tupdesc->natts * sizeof(char *));
+ values = (char **) palloc(rsinfo->setDesc->natts * sizeof(char *));
while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
{
/* build a tuple */
tuple = BuildTupleFromCStrings(attinmeta, values);
- tuplestore_puttuple(tupstore, tuple);
+ tuplestore_puttuple(rsinfo->setResult, tuple);
}
else
{
{
#define POSTGRES_FDW_GET_CONNECTIONS_COLS 2
ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
- TupleDesc tupdesc;
- Tuplestorestate *tupstore;
- MemoryContext per_query_ctx;
- MemoryContext oldcontext;
HASH_SEQ_STATUS scan;
ConnCacheEntry *entry;
- /* 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);
/* If cache doesn't exist, we return no records */
if (!ConnectionHash)
values[1] = BoolGetDatum(!entry->invalidated);
- tuplestore_putvalues(tupstore, tupdesc, values, nulls);
+ tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
}
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;
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")));
* 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.
*/
numpaths = 0;
pos = xpathset;
- while (numpaths < (ret_tupdesc->natts - 1))
+ while (numpaths < (rsinfo->setDesc->natts - 1))
{
xpaths[numpaths++] = (xmlChar *) pos;
pos = strstr(pos, pathsep);
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
xmlXPathObjectPtr res;
xmlChar *resstr;
xmlXPathCompExprPtr comppath;
+ HeapTuple ret_tuple;
/* Extract the row data as C Strings */
spi_tuple = tuptable->vals[i];
* 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 */
{
/* 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
if (had_values)
{
ret_tuple = BuildTupleFromCStrings(attinmeta, values);
- tuplestore_puttuple(tupstore, ret_tuple);
+ tuplestore_puttuple(rsinfo->setResult, ret_tuple);
heap_freetuple(ret_tuple);
}
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.