src/backend/replication/logical/reorderbuffer.c
static void
ReorderBufferToastAppendChunk(ReorderBuffer *rb, ReorderBufferTXN *txn,
							  Relation relation, ReorderBufferChange *change)
{
	ReorderBufferToastEnt *ent;
	ReorderBufferTupleBuf *newtup;
	bool		found;
	int32		chunksize;
	bool		isnull;
	Pointer		chunk;
	TupleDesc	desc = RelationGetDescr(relation);
	Oid			chunk_id;
	int32		chunk_seq;

	if (txn->toast_hash == NULL)
		ReorderBufferToastInitHash(rb, txn);

	Assert(IsToastRelation(relation));

	newtup = change->data.tp.newtuple;
	chunk_id = DatumGetObjectId(fastgetattr(&newtup->tuple, 1, desc, &isnull));
	Assert(!isnull);
	chunk_seq = DatumGetInt32(fastgetattr(&newtup->tuple, 2, desc, &isnull));
	Assert(!isnull);

	ent = (ReorderBufferToastEnt *)
		hash_search(txn->toast_hash,
					(void *) &chunk_id,
					HASH_ENTER,
					&found);

	if (!found)
	{
		Assert(ent->chunk_id == chunk_id);
		ent->num_chunks = 0;
		ent->last_chunk_seq = 0;
		ent->size = 0;
		ent->reconstructed = NULL;
		dlist_init(&ent->chunks);

		if (chunk_seq != 0)
			elog(ERROR, "got sequence entry %d for toast chunk %u instead of seq 0",
				 chunk_seq, chunk_id);
	}
	else if (found && chunk_seq != ent->last_chunk_seq + 1)
		elog(ERROR, "got sequence entry %d for toast chunk %u instead of seq %d",
			 chunk_seq, chunk_id, ent->last_chunk_seq + 1);

	chunk = DatumGetPointer(fastgetattr(&newtup->tuple, 3, desc, &isnull));
	Assert(!isnull);

	/* calculate size so we can allocate the right size at once later */
	if (!VARATT_IS_EXTENDED(chunk))
		chunksize = VARSIZE(chunk) - VARHDRSZ;
	else if (VARATT_IS_SHORT(chunk))
		/* could happen due to heap_form_tuple doing its thing */
		chunksize = VARSIZE_SHORT(chunk) - VARHDRSZ_SHORT;
	else
		elog(ERROR, "unexpected type of toast chunk");

	ent->size += chunksize;
	ent->last_chunk_seq = chunk_seq;
	ent->num_chunks++;
	dlist_push_tail(&ent->chunks, &change->node);
}
/*
 * Per toast-chunk handling for toast reconstruction
 *
 * Appends a toast chunk so we can reconstruct it when the tuple "owning" the
 * toasted Datum comes along.
 */
Per toast-chunk handling for toast reconstruction
Appends a toast chunk so we can reconstruct it when the tuple "owning" the
toasted Datum comes along.
Per toast - chunk handling for toast reconstruction Appends a toast chunk so we can reconstruct it when the tuple " owning " the toasted Datum comes along .
static void
ReorderBufferToastAppendChunk(ReorderBuffer *rb, ReorderBufferTXN *txn,
							  Relation relation, ReorderBufferChange *change)
{
	ReorderBufferToastEnt *ent;
	ReorderBufferTupleBuf *newtup;
	bool		found;
	int32		chunksize;
	bool		isnull;
	Pointer		chunk;
	TupleDesc	desc = RelationGetDescr(relation);
	Oid			chunk_id;
	int32		chunk_seq;
	if (txn->toast_hash == NULL)
		ReorderBufferToastInitHash(rb, txn);
	Assert(IsToastRelation(relation));
	newtup = change->data.tp.newtuple;
	chunk_id = DatumGetObjectId(fastgetattr(&newtup->tuple, 1, desc, &isnull));
	Assert(!isnull);
	chunk_seq = DatumGetInt32(fastgetattr(&newtup->tuple, 2, desc, &isnull));
	Assert(!isnull);
	ent = (ReorderBufferToastEnt *)
		hash_search(txn->toast_hash,
					(void *) &chunk_id,
					HASH_ENTER,
					&found);
	if (!found)
	{
		Assert(ent->chunk_id == chunk_id);
		ent->num_chunks = 0;
		ent->last_chunk_seq = 0;
		ent->size = 0;
		ent->reconstructed = NULL;
		dlist_init(&ent->chunks);
		if (chunk_seq != 0)
			elog(ERROR, "got sequence entry %d for toast chunk %u instead of seq 0",
				 chunk_seq, chunk_id);
	}
	else if (found && chunk_seq != ent->last_chunk_seq + 1)
		elog(ERROR, "got sequence entry %d for toast chunk %u instead of seq %d",
			 chunk_seq, chunk_id, ent->last_chunk_seq + 1);
	chunk = DatumGetPointer(fastgetattr(&newtup->tuple, 3, desc, &isnull));
	Assert(!isnull);
	if (!VARATT_IS_EXTENDED(chunk))
		chunksize = VARSIZE(chunk) - VARHDRSZ;
	else if (VARATT_IS_SHORT(chunk))
		chunksize = VARSIZE_SHORT(chunk) - VARHDRSZ_SHORT;
	else
		elog(ERROR, "unexpected type of toast chunk");
	ent->size += chunksize;
	ent->last_chunk_seq = chunk_seq;
	ent->num_chunks++;
	dlist_push_tail(&ent->chunks, &change->node);
}
static void ReorderBufferToastAppendChunk ( ReorderBuffer * rb , ReorderBufferTXN * txn , Relation relation , ReorderBufferChange * change ) { ReorderBufferToastEnt * ent ; ReorderBufferTupleBuf * newtup ; bool found ; int32 chunksize ; bool isnull ; Pointer chunk ; TupleDesc desc = RelationGetDescr ( relation ) ; Oid chunk_id ; int32 chunk_seq ; if ( txn -> toast_hash == NULL ) ReorderBufferToastInitHash ( rb , txn ) ; Assert ( IsToastRelation ( relation ) ) ; newtup = change -> data . tp . newtuple ; chunk_id = DatumGetObjectId ( fastgetattr ( & newtup -> tuple , 1 , desc , & isnull ) ) ; Assert ( ! isnull ) ; chunk_seq = DatumGetInt32 ( fastgetattr ( & newtup -> tuple , 2 , desc , & isnull ) ) ; Assert ( ! isnull ) ; ent = ( ReorderBufferToastEnt * ) hash_search ( txn -> toast_hash , ( void * ) & chunk_id , HASH_ENTER , & found ) ; if ( ! found ) { Assert ( ent -> chunk_id == chunk_id ) ; ent -> num_chunks = 0 ; ent -> last_chunk_seq = 0 ; ent -> size = 0 ; ent -> reconstructed = NULL ; dlist_init ( & ent -> chunks ) ; if ( chunk_seq != 0 ) elog ( ERROR , " " , chunk_seq , chunk_id ) ; } else if ( found && chunk_seq != ent -> last_chunk_seq + 1 ) elog ( ERROR , " " , chunk_seq , chunk_id , ent -> last_chunk_seq + 1 ) ; chunk = DatumGetPointer ( fastgetattr ( & newtup -> tuple , 3 , desc , & isnull ) ) ; Assert ( ! isnull ) ; if ( ! VARATT_IS_EXTENDED ( chunk ) ) chunksize = VARSIZE ( chunk ) - VARHDRSZ ; else if ( VARATT_IS_SHORT ( chunk ) ) chunksize = VARSIZE_SHORT ( chunk ) - VARHDRSZ_SHORT ; else elog ( ERROR , " " ) ; ent -> size += chunksize ; ent -> last_chunk_seq = chunk_seq ; ent -> num_chunks ++ ; dlist_push_tail ( & ent -> chunks , & change -> node ) ; }
Per toast-chunk handling for toast reconstruction
 Appends a toast chunk so we can reconstruct it when the tuple "owning" the
 toasted Datum comes along.
Per toast - chunk handling for toast reconstruction Appends a toast chunk so we can reconstruct it when the tuple " owning " the toasted Datum comes along .
/* calculate size so we can allocate the right size at once later */ /* could happen due to heap_form_tuple doing its thing */