本文整理汇总了C++中CreateTupleDescCopy函数的典型用法代码示例。如果您正苦于以下问题:C++ CreateTupleDescCopy函数的具体用法?C++ CreateTupleDescCopy怎么用?C++ CreateTupleDescCopy使用的例子?那么恭喜您, 这里精选的函数代码示例或许可以为您提供帮助。
在下文中一共展示了CreateTupleDescCopy函数的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: ExecInitDML
/**
* Init nodeDML, which initializes the insert TupleTableSlot.
* */
DMLState*
ExecInitDML(DML *node, EState *estate, int eflags)
{
/* check for unsupported flags */
Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK | EXEC_FLAG_REWIND)));
DMLState *dmlstate = makeNode(DMLState);
dmlstate->ps.plan = (Plan *)node;
dmlstate->ps.state = estate;
ExecInitResultTupleSlot(estate, &dmlstate->ps);
dmlstate->ps.targetlist = (List *)
ExecInitExpr((Expr *) node->plan.targetlist,
(PlanState *) dmlstate);
Plan *outerPlan = outerPlan(node);
outerPlanState(dmlstate) = ExecInitNode(outerPlan, estate, eflags);
ExecAssignResultTypeFromTL(&dmlstate->ps);
/* Create expression evaluation context. This will be used for projections */
ExecAssignExprContext(estate, &dmlstate->ps);
/*
* Create projection info from the child tuple descriptor and our target list
* Projection will be placed in the ResultSlot
*/
TupleTableSlot *childResultSlot = outerPlanState(dmlstate)->ps_ResultTupleSlot;
ExecAssignProjectionInfo(&dmlstate->ps, childResultSlot->tts_tupleDescriptor);
/*
* Initialize slot to insert/delete using output relation descriptor.
*/
dmlstate->cleanedUpSlot = ExecInitExtraTupleSlot(estate);
/*
* Both input and output of the junk filter include dropped attributes, so
* the junk filter doesn't need to do anything special there about them
*/
TupleDesc cleanTupType = CreateTupleDescCopy(dmlstate->ps.state->es_result_relation_info->ri_RelationDesc->rd_att);
dmlstate->junkfilter = ExecInitJunkFilter(node->plan.targetlist,
cleanTupType,
dmlstate->cleanedUpSlot);
if (estate->es_instrument)
{
dmlstate->ps.cdbexplainbuf = makeStringInfo();
/* Request a callback at end of query. */
dmlstate->ps.cdbexplainfun = ExecDMLExplainEnd;
}
initGpmonPktForDML((Plan *)node, &dmlstate->ps.gpmon_pkt, estate);
return dmlstate;
}
示例2: CheckerInit
void
CheckerInit(Checker *checker, Relation rel, TupleChecker *tchecker)
{
TupleDesc desc;
checker->tchecker = tchecker;
/*
* When specify ENCODING, we check the input data encoding.
* Convert encoding if the client and server encodings are different.
*/
checker->db_encoding = GetDatabaseEncoding();
if (checker->encoding != -1 &&
(checker->encoding != PG_SQL_ASCII ||
checker->db_encoding != PG_SQL_ASCII))
checker->check_encoding = true;
if (!rel)
return;
/* When specify CHECK_CONSTRAINTS, we check the constraints */
desc = RelationGetDescr(rel);
if (desc->constr &&
(checker->check_constraints || desc->constr->has_not_null))
{
if (checker->check_constraints)
checker->has_constraints = true;
if (desc->constr->has_not_null)
checker->has_not_null = true;
checker->resultRelInfo = makeNode(ResultRelInfo);
checker->resultRelInfo->ri_RangeTableIndex = 1; /* dummy */
checker->resultRelInfo->ri_RelationDesc = rel;
checker->resultRelInfo->ri_TrigDesc = NULL; /* TRIGGER is not supported */
checker->resultRelInfo->ri_TrigInstrument = NULL;
}
if (checker->has_constraints)
{
checker->estate = CreateExecutorState();
checker->estate->es_result_relations = checker->resultRelInfo;
checker->estate->es_num_result_relations = 1;
checker->estate->es_result_relation_info = checker->resultRelInfo;
/* Set up a tuple slot too */
checker->slot = MakeSingleTupleTableSlot(desc);
}
if (!checker->has_constraints && checker->has_not_null)
{
int i;
checker->desc = CreateTupleDescCopy(desc);
for (i = 0; i < desc->natts; i++)
checker->desc->attrs[i]->attnotnull = desc->attrs[i]->attnotnull;
}
}
示例3: deflist_to_tuplestore
/*
* deflist_to_tuplestore - Helper function to convert DefElem list to
* tuplestore usable in SRF.
*/
static void
deflist_to_tuplestore(ReturnSetInfo *rsinfo, List *options)
{
ListCell *cell;
TupleDesc tupdesc;
Tuplestorestate *tupstore;
Datum values[2];
bool nulls[2];
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")));
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;
foreach(cell, options)
{
DefElem *def = lfirst(cell);
values[0] = CStringGetTextDatum(def->defname);
nulls[0] = false;
if (def->arg)
{
values[1] = CStringGetTextDatum(((Value *) (def->arg))->val.str);
nulls[1] = false;
}
else
{
values[1] = (Datum) 0;
nulls[1] = true;
}
tuplestore_putvalues(tupstore, tupdesc, values, nulls);
}
示例4: RelationNameGetTupleDesc
/*
* RelationNameGetTupleDesc
*
* Given a (possibly qualified) relation name, build a TupleDesc.
*
* Note: while this works as advertised, it's seldom the best way to
* build a tupdesc for a function's result type. It's kept around
* only for backwards compatibility with existing user-written code.
*/
TupleDesc
RelationNameGetTupleDesc(const char *relname)
{
RangeVar *relvar;
Relation rel;
TupleDesc tupdesc;
List *relname_list;
/* Open relation and copy the tuple description */
relname_list = stringToQualifiedNameList(relname);
relvar = makeRangeVarFromNameList(relname_list);
rel = relation_openrv(relvar, AccessShareLock);
tupdesc = CreateTupleDescCopy(RelationGetDescr(rel));
relation_close(rel, AccessShareLock);
return tupdesc;
}
示例5: copy_heap
Relation
copy_heap(Oid OIDOldHeap)
{
char NewName[NAMEDATALEN];
TupleDesc OldHeapDesc, tupdesc;
Oid OIDNewHeap;
Relation NewHeap, OldHeap;
/*
* Create a new heap relation with a temporary name, which has the
* same tuple description as the old one.
*/
sprintf(NewName,"temp_%x", OIDOldHeap);
OldHeap= heap_open(OIDOldHeap);
OldHeapDesc= RelationGetTupleDescriptor(OldHeap);
/*
* Need to make a copy of the tuple descriptor, heap_create modifies
* it.
*/
tupdesc = CreateTupleDescCopy(OldHeapDesc);
OIDNewHeap=heap_create(NewName,
NULL,
OldHeap->rd_rel->relarch,
OldHeap->rd_rel->relsmgr,
tupdesc);
if (!OidIsValid(OIDNewHeap))
elog(WARN,"clusterheap: cannot create temporary heap relation\n");
NewHeap=heap_open(OIDNewHeap);
heap_close(NewHeap);
heap_close(OldHeap);
return NewHeap;
}
示例6: setup_firstcall
static void
setup_firstcall(FunctionCallInfo fcinfo, FuncCallContext *funcctx, Oid prsid)
{
TupleDesc tupdesc;
MemoryContext oldcontext;
TypeStorage *st;
WParserInfo *prs = findprs(prsid);
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
st = (TypeStorage *) palloc(sizeof(TypeStorage));
st->cur = 0;
st->list = (LexDescr *) DatumGetPointer(
OidFunctionCall1(prs->lextype, PointerGetDatum(prs->prs))
);
funcctx->user_fctx = (void *) st;
if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
elog(ERROR, "return type must be a row type");
tupdesc = CreateTupleDescCopy(tupdesc);
funcctx->attinmeta = TupleDescGetAttInMetadata(tupdesc);
MemoryContextSwitchTo(oldcontext);
}
示例7: CopyExprStateList
void DMLUtils::PrepareAbstractJoinPlanState(AbstractJoinPlanState *j_plan_state,
const JoinState &j_state) {
// Copy join type
j_plan_state->jointype = j_state.jointype;
// Copy join qual expr states
j_plan_state->joinqual = CopyExprStateList(j_state.joinqual);
// Copy ps qual
j_plan_state->qual = CopyExprStateList(j_state.ps.qual);
// Copy target list
j_plan_state->targetlist = CopyExprStateList(j_state.ps.targetlist);
// Copy tuple desc
auto tup_desc = j_state.ps.ps_ResultTupleSlot->tts_tupleDescriptor;
j_plan_state->tts_tupleDescriptor = CreateTupleDescCopy(tup_desc);
// Construct projection info
j_plan_state->ps_ProjInfo =
BuildProjectInfo(j_state.ps.ps_ProjInfo, tup_desc->natts);
}
示例8: producerStartupReceiver
/*
* Prepare to receive tuples from executor.
*/
static void
producerStartupReceiver(DestReceiver *self, int operation, TupleDesc typeinfo)
{
ProducerState *myState = (ProducerState *) self;
if (ActivePortal)
{
/* Normally ExecutorContext is current here. However we should better
* create local producer storage in the Portal's context: producer
* may keep pushing records to consumers after executor is destroyed.
*/
MemoryContext savecontext;
savecontext = MemoryContextSwitchTo(PortalGetHeapMemory(ActivePortal));
myState->typeinfo = CreateTupleDescCopy(typeinfo);
MemoryContextSwitchTo(savecontext);
}
else
myState->typeinfo = typeinfo;
if (myState->consumer)
(*myState->consumer->rStartup) (myState->consumer, operation, typeinfo);
}
示例9: spi_dest_startup
/*
* spi_dest_startup
* Initialize to receive tuples from Executor into SPITupleTable
* of current SPI procedure
*/
void
spi_dest_startup(DestReceiver *self, int operation, TupleDesc typeinfo)
{
SPITupleTable *tuptable;
MemoryContext oldcxt;
MemoryContext tuptabcxt;
/*
* When called by Executor _SPI_curid expected to be equal to
* _SPI_connected
*/
if (_SPI_curid != _SPI_connected || _SPI_connected < 0)
elog(ERROR, "improper call to spi_dest_startup");
if (_SPI_current != &(_SPI_stack[_SPI_curid]))
elog(ERROR, "SPI stack corrupted");
if (_SPI_current->tuptable != NULL)
elog(ERROR, "improper call to spi_dest_startup");
oldcxt = _SPI_procmem(); /* switch to procedure memory context */
tuptabcxt = AllocSetContextCreate(CurrentMemoryContext,
"SPI TupTable",
ALLOCSET_DEFAULT_MINSIZE,
ALLOCSET_DEFAULT_INITSIZE,
ALLOCSET_DEFAULT_MAXSIZE);
MemoryContextSwitchTo(tuptabcxt);
_SPI_current->tuptable = tuptable = (SPITupleTable *)
palloc(sizeof(SPITupleTable));
tuptable->tuptabcxt = tuptabcxt;
tuptable->alloced = tuptable->free = 128;
tuptable->vals = (HeapTuple *) palloc(tuptable->alloced * sizeof(HeapTuple));
tuptable->tupdesc = CreateTupleDescCopy(typeinfo);
MemoryContextSwitchTo(oldcxt);
}
示例10: PersistHoldablePortal
/*
* PersistHoldablePortal
*
* Prepare the specified Portal for access outside of the current
* transaction. When this function returns, all future accesses to the
* portal must be done via the Tuplestore (not by invoking the
* executor).
*/
void
PersistHoldablePortal(Portal portal)
{
QueryDesc *queryDesc = PortalGetQueryDesc(portal);
Portal saveActivePortal;
ResourceOwner saveResourceOwner;
MemoryContext savePortalContext;
MemoryContext oldcxt;
/*
* If we're preserving a holdable portal, we had better be inside the
* transaction that originally created it.
*/
Assert(portal->createSubid != InvalidSubTransactionId);
Assert(queryDesc != NULL);
/*
* Caller must have created the tuplestore already.
*/
Assert(portal->holdContext != NULL);
Assert(portal->holdStore != NULL);
/*
* Before closing down the executor, we must copy the tupdesc into
* long-term memory, since it was created in executor memory.
*/
oldcxt = MemoryContextSwitchTo(portal->holdContext);
portal->tupDesc = CreateTupleDescCopy(portal->tupDesc);
MemoryContextSwitchTo(oldcxt);
/*
* Check for improper portal use, and mark portal active.
*/
if (portal->status != PORTAL_READY)
ereport(ERROR,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("portal \"%s\" cannot be run", portal->name)));
portal->status = PORTAL_ACTIVE;
/*
* Set up global portal context pointers.
*/
saveActivePortal = ActivePortal;
saveResourceOwner = CurrentResourceOwner;
savePortalContext = PortalContext;
PG_TRY();
{
ActivePortal = portal;
CurrentResourceOwner = portal->resowner;
PortalContext = PortalGetHeapMemory(portal);
MemoryContextSwitchTo(PortalContext);
PushActiveSnapshot(queryDesc->snapshot);
/*
* Rewind the executor: we need to store the entire result set in the
* tuplestore, so that subsequent backward FETCHs can be processed.
*/
ExecutorRewind(queryDesc);
/*
* Change the destination to output to the tuplestore. Note we tell
* the tuplestore receiver to detoast all data passed through it.
*/
queryDesc->dest = CreateDestReceiver(DestTuplestore);
SetTuplestoreDestReceiverParams(queryDesc->dest,
portal->holdStore,
portal->holdContext,
true);
/* Fetch the result set into the tuplestore */
ExecutorRun(queryDesc, ForwardScanDirection, 0L);
(*queryDesc->dest->rDestroy) (queryDesc->dest);
queryDesc->dest = NULL;
/*
* Now shut down the inner executor.
*/
portal->queryDesc = NULL; /* prevent double shutdown */
/* we do not need AfterTriggerEndQuery() here */
ExecutorEnd(queryDesc);
FreeQueryDesc(queryDesc);
/*
* Set the position in the result set: ideally, this could be
* implemented by just skipping straight to the tuple # that we need
* to be at, but the tuplestore API doesn't support that. So we start
* at the beginning of the tuplestore and iterate through it until we
//.........这里部分代码省略.........
示例11: pgstattuple_real
/*
* pgstattuple_real
*
* The real work occurs here
*/
static Datum
pgstattuple_real(Relation rel, FunctionCallInfo fcinfo)
{
HeapScanDesc scan;
HeapTuple tuple;
BlockNumber nblocks;
BlockNumber block = 0; /* next block to count free space in */
BlockNumber tupblock;
Buffer buffer;
uint64 table_len;
uint64 tuple_len = 0;
uint64 dead_tuple_len = 0;
uint64 tuple_count = 0;
uint64 dead_tuple_count = 0;
double tuple_percent;
double dead_tuple_percent;
uint64 free_space = 0; /* free/reusable space in bytes */
double free_percent; /* free/reusable space in % */
TupleDesc tupdesc;
AttInMetadata *attinmeta;
char **values;
int i;
Datum result;
/* 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");
/* make sure we have a persistent copy of the tupdesc */
tupdesc = CreateTupleDescCopy(tupdesc);
/*
* Generate attribute metadata needed later to produce tuples from raw C
* strings
*/
attinmeta = TupleDescGetAttInMetadata(tupdesc);
scan = heap_beginscan(rel, SnapshotAny, 0, NULL);
nblocks = scan->rs_nblocks; /* # blocks to be scanned */
/* scan the relation */
while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
{
/* must hold a buffer lock to call HeapTupleSatisfiesNow */
LockBuffer(scan->rs_cbuf, BUFFER_LOCK_SHARE);
if (HeapTupleSatisfiesNow(tuple->t_data, scan->rs_cbuf))
{
tuple_len += tuple->t_len;
tuple_count++;
}
else
{
dead_tuple_len += tuple->t_len;
dead_tuple_count++;
}
LockBuffer(scan->rs_cbuf, BUFFER_LOCK_UNLOCK);
/*
* To avoid physically reading the table twice, try to do the
* free-space scan in parallel with the heap scan. However,
* heap_getnext may find no tuples on a given page, so we cannot
* simply examine the pages returned by the heap scan.
*/
tupblock = BlockIdGetBlockNumber(&tuple->t_self.ip_blkid);
while (block <= tupblock)
{
buffer = ReadBuffer(rel, block);
LockBuffer(buffer, BUFFER_LOCK_SHARE);
free_space += PageGetFreeSpace((Page) BufferGetPage(buffer));
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
ReleaseBuffer(buffer);
block++;
}
}
heap_endscan(scan);
while (block < nblocks)
{
buffer = ReadBuffer(rel, block);
free_space += PageGetFreeSpace((Page) BufferGetPage(buffer));
ReleaseBuffer(buffer);
block++;
}
heap_close(rel, AccessShareLock);
table_len = (uint64) nblocks *BLCKSZ;
if (nblocks == 0)
{
tuple_percent = 0.0;
//.........这里部分代码省略.........
示例12: UpdateMotionLayerNode
/*
* Initialize a single motion node. This is called by the executor when a
* motion node in the plan tree is being initialized.
*
* This function is called from: ExecInitMotion()
*/
void
UpdateMotionLayerNode(MotionLayerState *mlStates, int16 motNodeID, bool preserveOrder, TupleDesc tupDesc, uint64 operatorMemKB)
{
MemoryContext oldCtxt;
MotionNodeEntry *pEntry;
AssertArg(tupDesc != NULL);
/*
* Switch to the Motion Layer's memory-context, so that the motion node
* can be reset later.
*/
oldCtxt = MemoryContextSwitchTo(mlStates->motion_layer_mctx);
if (motNodeID > mlStates->mneCount)
{
AddMotionLayerNode(mlStates, motNodeID);
}
pEntry = &mlStates->mnEntries[motNodeID - 1];
if (!pEntry->valid)
{
/*
* we'll just set this to 0. later, ml_ipc will call
* setExpectedReceivers() to set this if we are a "Receiving"
* motion node.
*/
pEntry->num_senders = 0;
}
pEntry->motion_node_id = motNodeID;
pEntry->valid = true;
/* Finish up initialization of the motion node entry. */
pEntry->preserve_order = preserveOrder;
pEntry->tuple_desc = CreateTupleDescCopy(tupDesc);
InitSerTupInfo(pEntry->tuple_desc, &pEntry->ser_tup_info);
pEntry->memKB = operatorMemKB;
if (!preserveOrder)
{
Assert(pEntry->memKB > 0);
/* Create a tuple-store for the motion node's incoming tuples. */
pEntry->ready_tuples = htfifo_create(pEntry->memKB);
}
else
pEntry->ready_tuples = NULL;
pEntry->num_stream_ends_recvd = 0;
/* Initialize statistics counters. */
pEntry->stat_total_chunks_sent = 0;
pEntry->stat_total_bytes_sent = 0;
pEntry->stat_tuple_bytes_sent = 0;
pEntry->stat_total_sends = 0;
pEntry->stat_total_recvs = 0;
pEntry->stat_tuples_available = 0;
pEntry->stat_tuples_available_hwm = 0;
pEntry->stat_total_chunks_recvd = 0;
pEntry->stat_total_bytes_recvd = 0;
pEntry->stat_tuple_bytes_recvd = 0;
pEntry->sel_rd_wait = 0;
pEntry->sel_wr_wait = 0;
pEntry->cleanedUp = false;
pEntry->stopped = false;
pEntry->moreNetWork = true;
/* All done! Go back to caller memory-context. */
MemoryContextSwitchTo(oldCtxt);
}
示例13: each_worker
static inline Datum
each_worker(PG_FUNCTION_ARGS, bool as_text)
{
text *json = PG_GETARG_TEXT_P(0);
JsonLexContext *lex = makeJsonLexContext(json, true);
JsonSemAction sem;
ReturnSetInfo *rsi;
MemoryContext old_cxt;
TupleDesc tupdesc;
EachState state;
state = palloc0(sizeof(eachState));
sem = palloc0(sizeof(jsonSemAction));
rsi = (ReturnSetInfo *) fcinfo->resultinfo;
if (!rsi || !IsA(rsi, ReturnSetInfo) ||
(rsi->allowedModes & SFRM_Materialize) == 0 ||
rsi->expectedDesc == NULL)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("set-valued function called in context that "
"cannot accept a set")));
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,
false, work_mem);
MemoryContextSwitchTo(old_cxt);
sem->semstate = (void *) state;
sem->array_start = each_array_start;
sem->scalar = each_scalar;
sem->object_field_start = each_object_field_start;
sem->object_field_end = each_object_field_end;
state->normalize_results = as_text;
state->next_scalar = false;
state->lex = lex;
state->tmp_cxt = AllocSetContextCreate(CurrentMemoryContext,
"json_each temporary cxt",
ALLOCSET_DEFAULT_MINSIZE,
ALLOCSET_DEFAULT_INITSIZE,
ALLOCSET_DEFAULT_MAXSIZE);
pg_parse_json(lex, sem);
rsi->setResult = state->tuple_store;
rsi->setDesc = state->ret_tdesc;
PG_RETURN_NULL();
}
示例14: json_populate_recordset
/*
* SQL function json_populate_recordset
*
* set fields in a set of records from the argument json,
* which must be an array of objects.
*
* similar to json_populate_record, but the tuple-building code
* is pushed down into the semantic action handlers so it's done
* per object in the array.
*/
Datum
json_populate_recordset(PG_FUNCTION_ARGS)
{
Oid argtype = get_fn_expr_argtype(fcinfo->flinfo, 0);
text *json = PG_GETARG_TEXT_P(1);
bool use_json_as_text = PG_GETARG_BOOL(2);
ReturnSetInfo *rsi;
MemoryContext old_cxt;
Oid tupType;
int32 tupTypmod;
HeapTupleHeader rec;
TupleDesc tupdesc;
RecordIOData *my_extra;
int ncolumns;
JsonLexContext *lex;
JsonSemAction sem;
PopulateRecordsetState state;
if (!type_is_rowtype(argtype))
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("first argument must be a rowtype")));
rsi = (ReturnSetInfo *) fcinfo->resultinfo;
if (!rsi || !IsA(rsi, ReturnSetInfo) ||
(rsi->allowedModes & SFRM_Materialize) == 0 ||
rsi->expectedDesc == NULL)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("set-valued function called in context that "
"cannot accept a set")));
rsi->returnMode = SFRM_Materialize;
/*
* get the tupdesc from the result set info - it must be a record type
* because we already checked that arg1 is a record type.
*/
(void) get_call_result_type(fcinfo, NULL, &tupdesc);
state = palloc0(sizeof(populateRecordsetState));
sem = palloc0(sizeof(jsonSemAction));
/* 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,
false, work_mem);
MemoryContextSwitchTo(old_cxt);
/* if the json is null send back an empty set */
if (PG_ARGISNULL(1))
PG_RETURN_NULL();
if (PG_ARGISNULL(0))
rec = NULL;
else
rec = PG_GETARG_HEAPTUPLEHEADER(0);
tupType = tupdesc->tdtypeid;
tupTypmod = tupdesc->tdtypmod;
ncolumns = tupdesc->natts;
lex = makeJsonLexContext(json, true);
/*
* We arrange to look up the needed I/O info just once per series of
* calls, assuming the record type doesn't change underneath us.
*/
my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;
if (my_extra == NULL ||
my_extra->ncolumns != ncolumns)
{
fcinfo->flinfo->fn_extra =
MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
sizeof(RecordIOData) - sizeof(ColumnIOData)
+ ncolumns * sizeof(ColumnIOData));
my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;
my_extra->record_type = InvalidOid;
my_extra->record_typmod = 0;
}
if (my_extra->record_type != tupType ||
//.........这里部分代码省略.........
示例15: xpath_table
Datum
xpath_table(PG_FUNCTION_ARGS)
{
/* Function parameters */
char *pkeyfield = text_to_cstring(PG_GETARG_TEXT_PP(0));
char *xmlfield = text_to_cstring(PG_GETARG_TEXT_PP(1));
char *relname = text_to_cstring(PG_GETARG_TEXT_PP(2));
char *xpathset = text_to_cstring(PG_GETARG_TEXT_PP(3));
char *condition = text_to_cstring(PG_GETARG_TEXT_PP(4));
/* SPI (input tuple) support */
SPITupleTable *tuptable;
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;
char *pos;
const char *pathsep = "|";
int numpaths;
int ret;
int proc;
int i;
int j;
int rownr; /* For issuing multiple rows from one original
* document */
bool had_values; /* To determine end of nodeset results */
StringInfoData query_buf;
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);
/* must have at least one output column (for the pkey) */
if (ret_tupdesc->natts < 1)
ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR),
errmsg("xpath_table must have at least one output column")));
/*
* At the moment we assume that the returned attributes make sense for the
* XPath specififed (i.e. we trust the caller). It's not fatal if they get
* it wrong - the input function for the column type will raise an error
* if the path result can't be converted into the correct binary
* representation.
*/
attinmeta = TupleDescGetAttInMetadata(ret_tupdesc);
/* Set return mode and allocate value space. */
rsinfo->returnMode = SFRM_Materialize;
//.........这里部分代码省略.........