Try to detect oversize tuple before corrupting relation, instead of
after...
This commit is contained in:
parent
66dbcd47ed
commit
8a7f31a7d8
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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;
|
ItemId itemId;
|
||||||
Item item;
|
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.
|
* 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.
|
* transactions with XactLockTable.
|
||||||
*/
|
*/
|
||||||
if (!relation->rd_myxactonly)
|
if (!relation->rd_myxactonly)
|
||||||
@ -122,17 +132,17 @@ RelationPutHeapTupleAtEnd(Relation relation, HeapTuple tuple)
|
|||||||
* relation. A good optimization would be to get this to actually
|
* relation. A good optimization would be to get this to actually
|
||||||
* work properly.
|
* work properly.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
lastblock = RelationGetNumberOfBlocks(relation);
|
lastblock = RelationGetNumberOfBlocks(relation);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the last existing page --- may need to create the first one
|
||||||
|
* if this is a virgin relation.
|
||||||
|
*/
|
||||||
if (lastblock == 0)
|
if (lastblock == 0)
|
||||||
{
|
{
|
||||||
|
/* what exactly is this all about??? */
|
||||||
buffer = ReadBuffer(relation, lastblock);
|
buffer = ReadBuffer(relation, lastblock);
|
||||||
pageHeader = (Page) BufferGetPage(buffer);
|
pageHeader = (Page) BufferGetPage(buffer);
|
||||||
|
|
||||||
/*
|
|
||||||
* There was IF instead of ASSERT here ?!
|
|
||||||
*/
|
|
||||||
Assert(PageIsNew((PageHeader) pageHeader));
|
Assert(PageIsNew((PageHeader) pageHeader));
|
||||||
buffer = ReleaseAndReadBuffer(buffer, relation, P_NEW);
|
buffer = ReleaseAndReadBuffer(buffer, relation, P_NEW);
|
||||||
pageHeader = (Page) BufferGetPage(buffer);
|
pageHeader = (Page) BufferGetPage(buffer);
|
||||||
@ -143,13 +153,10 @@ RelationPutHeapTupleAtEnd(Relation relation, HeapTuple tuple)
|
|||||||
|
|
||||||
LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
|
LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
|
||||||
pageHeader = (Page) BufferGetPage(buffer);
|
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
|
* Is there room on the last existing page?
|
||||||
* will do for a completely empty relation.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (len > PageGetFreeSpace(pageHeader))
|
if (len > PageGetFreeSpace(pageHeader))
|
||||||
{
|
{
|
||||||
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
|
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
|
||||||
@ -159,12 +166,18 @@ RelationPutHeapTupleAtEnd(Relation relation, HeapTuple tuple)
|
|||||||
PageInit(pageHeader, BufferGetPageSize(buffer), 0);
|
PageInit(pageHeader, BufferGetPageSize(buffer), 0);
|
||||||
|
|
||||||
if (len > PageGetFreeSpace(pageHeader))
|
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);
|
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)
|
if (!relation->rd_myxactonly)
|
||||||
UnlockPage(relation, 0, ExclusiveLock);
|
UnlockPage(relation, 0, ExclusiveLock);
|
||||||
|
|
||||||
@ -178,7 +191,7 @@ RelationPutHeapTupleAtEnd(Relation relation, HeapTuple tuple)
|
|||||||
|
|
||||||
ItemPointerSet(&((HeapTupleHeader) item)->t_ctid, lastblock, offnum);
|
ItemPointerSet(&((HeapTupleHeader) item)->t_ctid, lastblock, offnum);
|
||||||
|
|
||||||
/* return an accurate tuple */
|
/* return an accurate tuple self-pointer */
|
||||||
ItemPointerSet(&tuple->t_self, lastblock, offnum);
|
ItemPointerSet(&tuple->t_self, lastblock, offnum);
|
||||||
|
|
||||||
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
|
LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user