static void
transform_receive(TupleTableSlot *slot, DestReceiver *self)
{
	TransformState *t = (TransformState *) self;
	MemoryContext old = MemoryContextSwitchTo(ContQueryBatchContext);

	if (t->tg_rel == NULL)
		t->tg_rel = heap_open(t->cont_query->matrelid, AccessShareLock);

	if (t->cont_query->tgfn != PIPELINE_STREAM_INSERT_OID)
	{
		TriggerData *cxt = (TriggerData *) t->trig_fcinfo->context;

		Assert(t->trig_fcinfo);

		cxt->tg_relation = t->tg_rel;
		cxt->tg_trigtuple = ExecCopySlotTuple(slot);

		FunctionCallInvoke(t->trig_fcinfo);

		heap_freetuple(cxt->tg_trigtuple);
		cxt->tg_trigtuple = NULL;
	}
	else
	{
		if (t->tups == NULL)
		{
			Assert(t->nmaxtups == 0);
			Assert(t->ntups == 0);

			t->nmaxtups = continuous_query_batch_size / 8;
			t->tups = palloc(sizeof(HeapTuple) * t->nmaxtups);
		}

		if (t->ntups == t->nmaxtups)
		{
			t->nmaxtups *= 2;
			t->tups = repalloc(t->tups, sizeof(HeapTuple) * t->nmaxtups);
		}

		t->tups[t->ntups] = ExecCopySlotTuple(slot);
		t->ntups++;

		if (synchronous_stream_insert && t->acks == NULL)
			t->acks = InsertBatchAckCreate(t->cont_exec->yielded_msgs, &t->nacks);
	}

	MemoryContextSwitchTo(old);
}
Example #2
0
jobject TupleTable_createFromSlot(TupleTableSlot* tts)
{
	HeapTuple tuple;
	jobject tupdesc;
	jobjectArray tuples;
	MemoryContext curr;

	if(tts == 0)
		return 0;

	curr = MemoryContextSwitchTo(JavaMemoryContext);

#if (PGSQL_MAJOR_VER == 8 && PGSQL_MINOR_VER == 0)
	tupdesc = TupleDesc_internalCreate(tts->ttc_tupleDescriptor);
	tuple   = heap_copytuple(tts->val);
#else
	tupdesc = TupleDesc_internalCreate(tts->tts_tupleDescriptor);
	tuple   = ExecCopySlotTuple(tts);
#endif
	tuples  = Tuple_createArray(&tuple, 1, false);

	MemoryContextSwitchTo(curr);

	return JNI_newObject(s_TupleTable_class, s_TupleTable_init, tupdesc, tuples);
}
Example #3
0
/* --------------------------------
 *		ExecCopySlot
 *			Copy the source slot's contents into the destination slot.
 *
 *		The destination acquires a private copy that will not go away
 *		if the source is cleared.
 *
 *		The caller must ensure the slots have compatible tupdescs.
 * --------------------------------
 */
TupleTableSlot *
ExecCopySlot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
{
	HeapTuple	newTuple;
	MemoryContext oldContext;

	/*
	 * There might be ways to optimize this when the source is virtual, but
	 * for now just always build a physical copy.  Make sure it is in the
	 * right context.
	 */
	oldContext = MemoryContextSwitchTo(dstslot->tts_mcxt);
	newTuple = ExecCopySlotTuple(srcslot);
	MemoryContextSwitchTo(oldContext);

	return ExecStoreTuple(newTuple, dstslot, InvalidBuffer, true);
}
Example #4
0
static void
combiner_receive(TupleTableSlot *slot, DestReceiver *self)
{
	CombinerState *c = (CombinerState *) self;
	MemoryContext old = MemoryContextSwitchTo(ContQueryBatchContext);
	tagged_ref_t *ref;
	uint32 shard_hash;
	bool received = false;

	if (!c->cont_query)
		c->cont_query = c->cont_exec->curr_query->query;

	Assert(c->cont_query->type == CONT_VIEW);

	ref = palloc(sizeof(tagged_ref_t));
	ref->ptr = ExecCopySlotTuple(slot);

	/* Shard by groups or name if no grouping. */
	if (c->hash_fcinfo)
	{
		ref->tag = slot_hash_group(slot, c->hashfn, c->hash_fcinfo);
		shard_hash = slot_hash_group_skip_attr(slot, c->cont_query->sw_attno, c->hashfn, c->hash_fcinfo);
	}
	else
	{
		ref->tag = c->name_hash;
		shard_hash = c->name_hash;
	}

	if (CombinerReceiveHook)
		received = CombinerReceiveHook(c->cont_query, shard_hash, ref->tag, ref->ptr);

	if (!received)
	{
		int i = get_combiner_for_shard_hash(shard_hash);
		c->tups_per_combiner[i] = lappend(c->tups_per_combiner[i], ref);
	}

	MemoryContextSwitchTo(old);
}
Example #5
0
/* --------------------------------
 *		ExecMaterializeSlot
 *			Force a slot into the "materialized" state.
 *
 *		This causes the slot's tuple to be a local copy not dependent on
 *		any external storage.  A pointer to the contained tuple is returned.
 *
 *		A typical use for this operation is to prepare a computed tuple
 *		for being stored on disk.  The original data may or may not be
 *		virtual, but in any case we need a private copy for heap_insert
 *		to scribble on.
 * --------------------------------
 */
HeapTuple
ExecMaterializeSlot(TupleTableSlot *slot)
{
	HeapTuple	newTuple;
	MemoryContext oldContext;

	/*
	 * sanity checks
	 */
	Assert(slot != NULL);
	Assert(!slot->tts_isempty);

	/*
	 * If we have a physical tuple, and it's locally palloc'd, we have nothing
	 * to do.
	 */
	if (slot->tts_tuple && slot->tts_shouldFree)
		return slot->tts_tuple;

	/*
	 * Otherwise, copy or build a tuple, and then store it as the new slot
	 * value.  (Note: tts_nvalid will be reset to zero here.  There are cases
	 * in which this could be optimized but it's probably not worth worrying
	 * about.)
	 *
	 * We may be called in a context that is shorter-lived than the tuple
	 * slot, but we have to ensure that the materialized tuple will survive
	 * anyway.
	 */
	oldContext = MemoryContextSwitchTo(slot->tts_mcxt);
	newTuple = ExecCopySlotTuple(slot);
	MemoryContextSwitchTo(oldContext);

	ExecStoreTuple(newTuple, slot, InvalidBuffer, true);

	return slot->tts_tuple;
}
Example #6
0
/*
 * ExecSetOp for non-hashed case
 */
static TupleTableSlot *
setop_retrieve_direct(SetOpState *setopstate)
{
	SetOp	   *node = (SetOp *) setopstate->ps.plan;
	PlanState  *outerPlan;
	SetOpStatePerGroup pergroup;
	TupleTableSlot *outerslot;
	TupleTableSlot *resultTupleSlot;

	/*
	 * get state info from node
	 */
	outerPlan = outerPlanState(setopstate);
	pergroup = setopstate->pergroup;
	resultTupleSlot = setopstate->ps.ps_ResultTupleSlot;

	/*
	 * We loop retrieving groups until we find one we should return
	 */
	while (!setopstate->setop_done)
	{
		/*
		 * If we don't already have the first tuple of the new group, fetch it
		 * from the outer plan.
		 */
		if (setopstate->grp_firstTuple == NULL)
		{
			outerslot = ExecProcNode(outerPlan);
			if (!TupIsNull(outerslot))
			{
				/* Make a copy of the first input tuple */
				setopstate->grp_firstTuple = ExecCopySlotTuple(outerslot);
			}
			else
			{
				/* outer plan produced no tuples at all */
				setopstate->setop_done = true;
				return NULL;
			}
		}

		/*
		 * Store the copied first input tuple in the tuple table slot reserved
		 * for it.  The tuple will be deleted when it is cleared from the
		 * slot.
		 */
		ExecStoreTuple(setopstate->grp_firstTuple,
					   resultTupleSlot,
					   InvalidBuffer,
					   true);
		setopstate->grp_firstTuple = NULL;		/* don't keep two pointers */

		/* Initialize working state for a new input tuple group */
		initialize_counts(pergroup);

		/* Count the first input tuple */
		advance_counts(pergroup,
					   fetch_tuple_flag(setopstate, resultTupleSlot));

		/*
		 * Scan the outer plan until we exhaust it or cross a group boundary.
		 */
		for (;;)
		{
			outerslot = ExecProcNode(outerPlan);
			if (TupIsNull(outerslot))
			{
				/* no more outer-plan tuples available */
				setopstate->setop_done = true;
				break;
			}

			/*
			 * Check whether we've crossed a group boundary.
			 */
			if (!execTuplesMatch(resultTupleSlot,
								 outerslot,
								 node->numCols, node->dupColIdx,
								 setopstate->eqfunctions,
								 setopstate->tempContext))
			{
				/*
				 * Save the first input tuple of the next group.
				 */
				setopstate->grp_firstTuple = ExecCopySlotTuple(outerslot);
				break;
			}

			/* Still in same group, so count this tuple */
			advance_counts(pergroup,
						   fetch_tuple_flag(setopstate, outerslot));
		}

		/*
		 * Done scanning input tuple group.  See if we should emit any copies
		 * of result tuple, and if so return the first copy.
		 */
		set_output_count(setopstate, pergroup);

		if (setopstate->numOutput > 0)
		{
			setopstate->numOutput--;
			return resultTupleSlot;
		}
	}

	/* No more groups */
	ExecClearTuple(resultTupleSlot);
	return NULL;
}