Try to detect oversize tuple before corrupting relation, instead of

after...
This commit is contained in:
Tom Lane 1999-11-29 04:34:55 +00:00
parent 66dbcd47ed
commit 8a7f31a7d8
1 changed files with 29 additions and 16 deletions

View File

@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Id: hio.c,v 1.26 1999/07/19 07:07:18 momjian Exp $
* $Id: hio.c,v 1.27 1999/11/29 04:34:55 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -107,10 +107,20 @@ RelationPutHeapTupleAtEnd(Relation relation, HeapTuple tuple)
ItemId itemId;
Item item;
len = (unsigned) MAXALIGN(tuple->t_len); /* be conservative */
/*
* Lock relation for extention. We can use LockPage here as long as in
* If we're gonna fail for oversize tuple, do it right away...
* this code should go away eventually.
*/
if (len > MaxTupleSize)
elog(ERROR, "Tuple is too big: size %d, max size %d",
len, MaxTupleSize);
/*
* Lock relation for extension. We can use LockPage here as long as in
* all other places we use page-level locking for indices only.
* Alternatevely, we could define pseudo-table as we do for
* Alternatively, we could define pseudo-table as we do for
* transactions with XactLockTable.
*/
if (!relation->rd_myxactonly)
@ -122,17 +132,17 @@ RelationPutHeapTupleAtEnd(Relation relation, HeapTuple tuple)
* relation. A good optimization would be to get this to actually
* work properly.
*/
lastblock = RelationGetNumberOfBlocks(relation);
/*
* Get the last existing page --- may need to create the first one
* if this is a virgin relation.
*/
if (lastblock == 0)
{
/* what exactly is this all about??? */
buffer = ReadBuffer(relation, lastblock);
pageHeader = (Page) BufferGetPage(buffer);
/*
* There was IF instead of ASSERT here ?!
*/
Assert(PageIsNew((PageHeader) pageHeader));
buffer = ReleaseAndReadBuffer(buffer, relation, P_NEW);
pageHeader = (Page) BufferGetPage(buffer);
@ -143,13 +153,10 @@ RelationPutHeapTupleAtEnd(Relation relation, HeapTuple tuple)
LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
pageHeader = (Page) BufferGetPage(buffer);
len = (unsigned) MAXALIGN(tuple->t_len); /* be conservative */
/*
* Note that this is true if the above returned a bogus page, which it
* will do for a completely empty relation.
* Is there room on the last existing page?
*/
if (len > PageGetFreeSpace(pageHeader))
{
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
@ -159,12 +166,18 @@ RelationPutHeapTupleAtEnd(Relation relation, HeapTuple tuple)
PageInit(pageHeader, BufferGetPageSize(buffer), 0);
if (len > PageGetFreeSpace(pageHeader))
{
/*
* BUG: by elog'ing here, we leave the new buffer locked and not
* marked dirty, which may result in an invalid page header
* being left on disk. But we should not get here given the
* test at the top of the routine, and the whole deal should
* go away when we implement tuple splitting anyway...
*/
elog(ERROR, "Tuple is too big: size %d", len);
}
}
if (len > MaxTupleSize)
elog(ERROR, "Tuple is too big: size %d, max size %d", len, MaxTupleSize);
if (!relation->rd_myxactonly)
UnlockPage(relation, 0, ExclusiveLock);
@ -178,7 +191,7 @@ RelationPutHeapTupleAtEnd(Relation relation, HeapTuple tuple)
ItemPointerSet(&((HeapTupleHeader) item)->t_ctid, lastblock, offnum);
/* return an accurate tuple */
/* return an accurate tuple self-pointer */
ItemPointerSet(&tuple->t_self, lastblock, offnum);
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);