Exemplo n.º 1
0
/* --------------------------------
 *		ExecCopySlotHeadTupleTo
 * 			Copy heapTuple to a preallocated buffer.   Code adapted from ExecCopySlotTuple
 *
 * 			return the copied heaptule if there is enough space, or, if the memorycontext is
 *              not null, which the function will alloc enough space from the context.  One can
 *				test if the tuple is alloced (ret == dest)
 *
 *			return NULL and set *len to space need if there is not enough space and the mem context is null.
 *			return NULL if heap tuple is not valid, and set *len = 0.  See slot->tts_tuple case below.
 * -------------------------------
 */
HeapTuple ExecCopySlotHeapTupleTo(TupleTableSlot *slot, MemoryContext pctxt, char* dest, unsigned int *len)
{
	uint32 dumlen;
	HeapTuple tup = NULL;

	Assert(!TupIsNull(slot));
	Assert(slot->tts_tupleDescriptor);

	if(!len)
		len = &dumlen;
	
	if (slot->PRIVATE_tts_heaptuple)
	{
		tup = heaptuple_copy_to(slot->PRIVATE_tts_heaptuple, (HeapTuple) dest, len);

		if(tup || !pctxt)
			return tup;

		tup = (HeapTuple) ctxt_alloc(pctxt, *len);
		tup = heaptuple_copy_to(slot->PRIVATE_tts_heaptuple, tup, len);
		Assert(tup);

		return tup;
	}

	slot_getallattrs(slot);
	tup = heaptuple_form_to(slot->tts_tupleDescriptor, slot_get_values(slot), slot_get_isnull(slot), (HeapTuple) dest, len);

	if(tup || !pctxt)
		return tup;
	tup = (HeapTuple) ctxt_alloc(pctxt, *len);
	tup = heaptuple_form_to(slot->tts_tupleDescriptor, slot_get_values(slot), slot_get_isnull(slot), tup, len);
	Assert(tup);
	return tup;
}
Exemplo n.º 2
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)
{
	Assert(!TupIsNull(srcslot));

	ExecClearTuple(dstslot);
	TupClearIsEmpty(dstslot);

	/* heap tuple stuff */
	if(srcslot->PRIVATE_tts_heaptuple && !srcslot->PRIVATE_tts_memtuple) {

		uint32 tuplen = dstslot->PRIVATE_tts_htup_buf_len;
		HeapTuple htup = heaptuple_copy_to(srcslot->PRIVATE_tts_heaptuple, dstslot->PRIVATE_tts_htup_buf, &tuplen);

		if(!htup)
		{
			dstslot->PRIVATE_tts_htup_buf = MemoryContextAlloc(dstslot->tts_mcxt, tuplen);
			dstslot->PRIVATE_tts_htup_buf_len = tuplen;

			htup = heaptuple_copy_to(srcslot->PRIVATE_tts_heaptuple, dstslot->PRIVATE_tts_htup_buf, &tuplen);
		}

		Assert(htup);
		dstslot->PRIVATE_tts_heaptuple = htup;
		dstslot->PRIVATE_tts_nvalid = 0;
	}
	else
	{
		uint32 tuplen = dstslot->PRIVATE_tts_mtup_buf_len;
		MemTuple mtup;

		Assert(srcslot->tts_mt_bind != NULL && dstslot->tts_mt_bind != NULL);

		mtup = ExecCopySlotMemTupleTo(srcslot, NULL, dstslot->PRIVATE_tts_mtup_buf, &tuplen);
		if(!mtup)
		{
			dstslot->PRIVATE_tts_mtup_buf = MemoryContextAlloc(dstslot->tts_mcxt, tuplen);
			dstslot->PRIVATE_tts_mtup_buf_len = tuplen;

			mtup = ExecCopySlotMemTupleTo(srcslot, NULL, dstslot->PRIVATE_tts_mtup_buf, &tuplen);
		}

		Assert(mtup);
		dstslot->PRIVATE_tts_memtuple = mtup;
		dstslot->PRIVATE_tts_nvalid = 0;
	}

	return dstslot;
}
Exemplo n.º 3
0
static void *
copytup_heap(Tuplestorestate *state, TuplestorePos *pos, void *tup)
{
	if(!is_heaptuple_memtuple((HeapTuple) tup))
		return heaptuple_copy_to((HeapTuple) tup, NULL, NULL);

	return memtuple_copy_to((MemTuple) tup, NULL, NULL, NULL);
}
Exemplo n.º 4
0
static void *
copytup_heap(Tuplestorestate *state, void *tup)
{
	if (!is_memtuple((GenericTuple) tup))
		return heaptuple_copy_to((HeapTuple) tup, NULL, NULL);
	else
		return memtuple_copy_to((MemTuple) tup, NULL, NULL);
}
Exemplo n.º 5
0
/*
 * insert a tuple into in-memory heap table.
 */
void
InMemHeap_Insert(InMemHeapRelation relation, HeapTuple tup, int contentid)
{
    InMemHeapTuple inmemtup;

    MemoryContext oldmem = CurrentMemoryContext;
    Assert(NULL != relation && NULL != tup);
    Assert(GP_ROLE_EXECUTE == Gp_role || -1 == contentid);
    Assert(NULL != relation && NULL != tup);
    
    CurrentMemoryContext = relation->memcxt;

    if (relation->tupsize >= relation->tupmaxsize)
    {
        Assert(NULL != relation->tuples);
        relation->tuples = repalloc(relation->tuples,
                sizeof(InMemHeapTupleData) * relation->tupmaxsize * 2);
        relation->tupmaxsize *= 2;
    }

    inmemtup = &relation->tuples[relation->tupsize];

    inmemtup->contentid = contentid;
    inmemtup->flags = INMEM_HEAP_TUPLE_DISPATCHED;
    inmemtup->tuple = heaptuple_copy_to(tup, NULL, NULL);
    Assert(inmemtup->tuple != NULL);

    if (relation->hashIndex)
    {
        Oid key;
        bool isNull, found;

        key = DatumGetObjectId(
                heap_getattr(tup, relation->keyAttrno,
                        RelationGetDescr(relation->rel), &isNull));

        Insist(!isNull && "index key cannot be null");

        MemHeapHashIndexEntry *entry;
        entry = (MemHeapHashIndexEntry *) hash_search(relation->hashIndex, &key,
                HASH_ENTER, &found);

        if (!found)
        {
            entry->key = key;
            entry->values = NIL;
        }

        entry->values = lappend_int(entry->values, relation->tupsize);

        elog(DEBUG1, "add index %d key %d relation %s", relation->tupsize, key, relation->relname);
    }

    ++relation->tupsize;

    CurrentMemoryContext = oldmem;
}
Exemplo n.º 6
0
/*
 * update a tuple in in-memory heap table.
 *
 * if the target tuple already in the memory,
 * update it in-place with flag INMEM_HEAP_TUPLE_UPDATED.
 * else report an error.
 *
 * update should not change the otid of the old tuple,
 * since updated tuple should write back to the master and update there.
 */
void
InMemHeap_Update(InMemHeapRelation relation, ItemPointer otid,
        HeapTuple tup)
{
    int pos;
    HeapTuple target;
    MemoryContext oldmem = CurrentMemoryContext;

    Assert(ItemPointerIsValid(otid));

    pos = InMemHeap_Find(relation, otid);

    CurrentMemoryContext = relation->memcxt;

    /*
     * not found, report error
     */
    if (pos >= relation->tupsize)
    {
        ereport(ERROR,
                (errcode(ERRCODE_INTERNAL_ERROR),
                        errmsg("update a tuple which does not exist,"
                                " relname = %s, relid = %u", relation->rel->rd_rel->relname.data,
                                relation->relid)));
    }

    Insist(relation->hashIndex == NULL && "cannot handle index in in-memory heap when update");

    /*
     * already in table
     */
    Assert(relation->tuples[pos].flags == INMEM_HEAP_TUPLE_DISPATCHED
            || relation->tuples[pos].flags == INMEM_HEAP_TUPLE_UPDATED);
    relation->tuples[pos].flags = INMEM_HEAP_TUPLE_UPDATED;

    target = heaptuple_copy_to(tup, NULL, NULL );

    /*
     * do not modify original tuple header
     */
    ItemPointerCopy(&target->t_self, &relation->tuples[pos].tuple->t_self);

    Assert(ItemPointerEquals(&target->t_self, otid));

    memcpy(target->t_data, relation->tuples[pos].tuple->t_data,
            sizeof(HeapTupleHeaderData));

    CurrentMemoryContext = oldmem;

    pfree(relation->tuples[pos].tuple);
    relation->tuples[pos].tuple = target;
}
Exemplo n.º 7
0
Datum
caql_copy_to_in_memory_pg_class(PG_FUNCTION_ARGS)
{

	text *inText = PG_GETARG_TEXT_P(0);;
	char *inStr = text_to_cstring(inText);
	char kind = PG_GETARG_CHAR(1);

	StringInfoData buf;
	initStringInfo(&buf);

	/* create tuples for pg_class table */
	HeapTuple reltup = NULL;
	HeapTuple copytup = NULL;
	Form_pg_class relform;
	cqContext  *pcqCtx;
	cqContext  *pcqCtxInsert;

	pcqCtx = caql_beginscan(
			NULL,
			cql("SELECT * FROM pg_class "
				" WHERE relname = :1",
				CStringGetDatum((char *) inStr)));

	reltup = caql_getnext(pcqCtx);

	if (NULL == reltup)
	{
		appendStringInfo(&buf, "no tuples with relname=%s found!", inStr);
	}
	else
	{
	    copytup = heaptuple_copy_to(reltup, NULL, NULL);

		relform = (Form_pg_class) GETSTRUCT(copytup);
		relform->relkind = kind;
		appendStringInfo(&buf, "table pg_class, insert 1 line (relname %s, relkind %c)", NameStr(relform->relname), kind);

		/* insert */
		pcqCtxInsert = caql_beginscan(
				NULL,
				cql("INSERT INTO pg_class", NULL));
		caql_insert_inmem(pcqCtxInsert, copytup);
		caql_endscan(pcqCtxInsert);

		heap_freetuple(copytup);
	}

	caql_endscan(pcqCtx);

	PG_RETURN_TEXT_P(cstring_to_text(buf.data));
}
void PersistentStore_ReplaceTuple(
	PersistentStoreData 		*storeData,

	PersistentStoreSharedData 	*storeSharedData,

	ItemPointer 			persistentTid,
				/* TID of the stored tuple. */

	HeapTuple				tuple,

	Datum					*newValues,
	
	bool					*replaces,

	bool					flushToXLog)
				/* When true, the XLOG record for this change will be flushed to disk. */

{
	Relation	persistentRel;
	bool 		*nulls;
	HeapTuple	replacementTuple = NULL;
	XLogRecPtr 	xlogUpdateEndLoc;
	
#ifdef USE_ASSERT_CHECKING
	if (storeSharedData == NULL ||
		!PersistentStoreSharedData_EyecatcherIsValid(storeSharedData))
		elog(ERROR, "Persistent store shared-memory not valid");
#endif
	
	if (Debug_persistent_store_print)
		elog(PersistentStore_DebugPrintLevel(), 
			 "PersistentStore_ReplaceTuple: Going to replace set of columns in tuple at TID %s ('%s', shared data %p)",
			 ItemPointerToString(persistentTid),
			 storeData->tableName,
			 storeSharedData);

	persistentRel = (*storeData->openRel)();

	/*
	 * In order to keep the tuples the exact same size to enable direct reuse of
	 * free tuples, we do not use NULLs.
	 */
	nulls = (bool*)palloc0(storeData->numAttributes * sizeof(bool));
		
	/*
	 * Modify the tuple.
	 */
	replacementTuple = heap_modify_tuple(tuple, persistentRel->rd_att, 
										 newValues, nulls, replaces);

	replacementTuple->t_self = *persistentTid;
		
	frozen_heap_inplace_update(persistentRel, replacementTuple);

	/*
	 * Return the XLOG location of the UPDATE tuple's XLOG record.
	 */
	xlogUpdateEndLoc = XLogLastInsertEndLoc();

	heap_freetuple(replacementTuple);
	pfree(nulls);

	if (Debug_persistent_store_print)
	{
		Datum 			*readValues;
		bool			*readNulls;
		HeapTupleData 	readTuple;
		Buffer			buffer;
		HeapTuple		readTupleCopy;
		
		elog(PersistentStore_DebugPrintLevel(), 
			 "PersistentStore_ReplaceTuple: Replaced set of columns in tuple at TID %s ('%s')",
			 ItemPointerToString(persistentTid),
			 storeData->tableName);
		
		readValues = (Datum*)palloc(storeData->numAttributes * sizeof(Datum));
		readNulls = (bool*)palloc(storeData->numAttributes * sizeof(bool));

		readTuple.t_self = *persistentTid;
		
		if (!heap_fetch(persistentRel, SnapshotAny,
						&readTuple, &buffer, false, NULL))
		{
			elog(ERROR, "Failed to fetch persistent tuple at %s ('%s')",
				 ItemPointerToString(&readTuple.t_self),
				 storeData->tableName);
		}
		
		
		readTupleCopy = heaptuple_copy_to(&readTuple, NULL, NULL);
		
		ReleaseBuffer(buffer);
		
		heap_deform_tuple(readTupleCopy, persistentRel->rd_att, readValues, readNulls);
		
		(*storeData->printTupleCallback)(
									PersistentStore_DebugPrintLevel(),
									"STORE REPLACED TUPLE",
									persistentTid,
									readValues);

		heap_freetuple(readTupleCopy);
		pfree(readValues);
		pfree(readNulls);
	}

	(*storeData->closeRel)(persistentRel);
	
	if (flushToXLog)
	{
		XLogFlush(xlogUpdateEndLoc);
		XLogRecPtr_Zero(&nowaitXLogEndLoc);
	}
	else
		nowaitXLogEndLoc = xlogUpdateEndLoc;
}
HeapTuple PersistentStore_GetScanTupleCopy(
	PersistentStoreScan			*storeScan)
{
	return heaptuple_copy_to(storeScan->tuple, NULL, NULL);
}
void PersistentStore_ReadTuple(
	PersistentStoreData 		*storeData,

	PersistentStoreSharedData 	*storeSharedData,

	ItemPointer					readTid,

	Datum						*values,

	HeapTuple					*tupleCopy)
{
	Relation	persistentRel;

	HeapTupleData 	tuple;
	Buffer			buffer;

	bool *nulls;
	
#ifdef USE_ASSERT_CHECKING
	if (storeSharedData == NULL ||
		!PersistentStoreSharedData_EyecatcherIsValid(storeSharedData))
		elog(ERROR, "Persistent store shared-memory not valid");
#endif
	
	if (Debug_persistent_store_print)
		elog(PersistentStore_DebugPrintLevel(), 
			 "PersistentStore_ReadTuple: Going to read tuple at TID %s ('%s', shared data %p)",
			 ItemPointerToString(readTid),
			 storeData->tableName,
			 storeSharedData);

	if (PersistentStore_IsZeroTid(readTid))
		elog(ERROR, "TID for fetch persistent tuple is invalid (0,0) ('%s')",
			 storeData->tableName);

	// UNDONE: I think the InRecovery test only applies to physical Master Mirroring on Standby.
	/* Only test this outside of recovery scenarios */
	if (!InRecovery 
		&& 
		(PersistentStore_IsZeroTid(&storeSharedData->maxTid)
		 ||
		 ItemPointerCompare(
						readTid,
						&storeSharedData->maxTid) == 1 // Greater-than.
		))
	{
		elog(ERROR, "TID %s for fetch persistent tuple is greater than the last known TID %s ('%s')",
			 ItemPointerToString(readTid),
			 ItemPointerToString2(&storeSharedData->maxTid),
			 storeData->tableName);
	}
	
	persistentRel = (*storeData->openRel)();

	tuple.t_self = *readTid;

	if (!heap_fetch(persistentRel, SnapshotAny,
					&tuple, &buffer, false, NULL))
	{
		elog(ERROR, "Failed to fetch persistent tuple at %s (maximum known TID %s, '%s')",
			 ItemPointerToString(&tuple.t_self),
			 ItemPointerToString2(&storeSharedData->maxTid),
			 storeData->tableName);
	}

	
	*tupleCopy = heaptuple_copy_to(&tuple, NULL, NULL);

	ReleaseBuffer(buffer);
	
	/*
	 * In order to keep the tuples the exact same size to enable direct reuse of
	 * free tuples, we do not use NULLs.
	 */
	nulls = (bool*)palloc(storeData->numAttributes * sizeof(bool));

	heap_deform_tuple(*tupleCopy, persistentRel->rd_att, values, nulls);

	(*storeData->closeRel)(persistentRel);
	
	if (Debug_persistent_store_print)
	{
		elog(PersistentStore_DebugPrintLevel(), 
			 "PersistentStore_ReadTuple: Successfully read tuple at TID %s ('%s')",
			 ItemPointerToString(readTid),
			 storeData->tableName);

		(*storeData->printTupleCallback)(
									PersistentStore_DebugPrintLevel(),
									"STORE READ TUPLE",
									readTid,
									values);
	}

	pfree(nulls);
}
Exemplo n.º 11
0
void PersistentStore_ReadTuple(
	PersistentStoreData 		*storeData,
	PersistentStoreSharedData 	*storeSharedData,
	ItemPointer					readTid,
	Datum						*values,
	HeapTuple					*tupleCopy)
{
	Relation	persistentRel;

	HeapTupleData 	tuple;
	Buffer			buffer;

	bool *nulls;
	
#ifdef USE_ASSERT_CHECKING
	if (storeSharedData == NULL ||
		!PersistentStoreSharedData_EyecatcherIsValid(storeSharedData))
		elog(ERROR, "Persistent store shared-memory not valid");
#endif
	
	if (Debug_persistent_store_print)
		elog(PersistentStore_DebugPrintLevel(), 
			 "PersistentStore_ReadTuple: Going to read tuple at TID %s ('%s', shared data %p)",
			 ItemPointerToString(readTid),
			 storeData->tableName,
			 storeSharedData);

	if (PersistentStore_IsZeroTid(readTid))
		elog(ERROR, "TID for fetch persistent tuple is invalid (0,0) ('%s')",
			 storeData->tableName);

	persistentRel = (*storeData->openRel)();

	tuple.t_self = *readTid;

	if (heap_fetch(persistentRel, SnapshotAny,
					&tuple, &buffer, false, NULL))
	{
		*tupleCopy = heaptuple_copy_to(&tuple, NULL, NULL);
		ReleaseBuffer(buffer);
		/*
		 * In order to keep the tuples the exact same size to enable direct reuse of
		 * free tuples, we do not use NULLs.
		 */
		nulls = (bool*)palloc(storeData->numAttributes * sizeof(bool));

		heap_deform_tuple(*tupleCopy, persistentRel->rd_att, values, nulls);

		(*storeData->closeRel)(persistentRel);
	
		if (Debug_persistent_store_print)
		{
			elog(PersistentStore_DebugPrintLevel(),
				 "PersistentStore_ReadTuple: Successfully read tuple at TID %s ('%s')",
				 ItemPointerToString(readTid),
				 storeData->tableName);

			(*storeData->printTupleCallback)(
				PersistentStore_DebugPrintLevel(),
				"STORE READ TUPLE",
				readTid,
				values);
		}

		pfree(nulls);
	}
	else
	{
		*tupleCopy = NULL;
	}
}