Fixed unexpected data beyond EOF error - fixes #29

This commit is contained in:
Andrew Kane
2022-07-31 20:48:15 -07:00
parent df3dc151d5
commit 51fe8aff02
3 changed files with 67 additions and 19 deletions

View File

@@ -1,3 +1,7 @@
## 0.2.7 (unreleased)
- Fixed `unexpected data beyond EOF` error
## 0.2.6 (2022-05-22)
- Improved performance of index creation for Postgres < 12

View File

@@ -53,18 +53,6 @@ FindInsertPage(Relation rel, Datum *values, BlockNumber *insertPage, ListInfo *
}
}
/*
* Prepare to insert an index tuple
*/
static void
LoadInsertPage(Relation index, Buffer *buf, Page *page, GenericXLogState **state, BlockNumber insertPage)
{
*buf = ReadBuffer(index, insertPage);
LockBuffer(*buf, BUFFER_LOCK_EXCLUSIVE);
*state = GenericXLogStart(index);
*page = GenericXLogRegisterBuffer(*state, *buf, 0);
}
/*
* Insert a tuple into the index
*/
@@ -87,11 +75,18 @@ InsertTuple(Relation rel, IndexTuple itup, Relation heapRel, Datum *values)
itemsz = MAXALIGN(IndexTupleSize(itup));
Assert(itemsz <= BLCKSZ - MAXALIGN(SizeOfPageHeaderData) - MAXALIGN(sizeof(IvfflatPageOpaqueData)));
LoadInsertPage(rel, &buf, &page, &state, insertPage);
/* Find a page to insert the item */
while (PageGetFreeSpace(page) < itemsz)
for (;;)
{
buf = ReadBuffer(rel, insertPage);
LockBuffer(buf, BUFFER_LOCK_EXCLUSIVE);
state = GenericXLogStart(rel);
page = GenericXLogRegisterBuffer(state, buf, 0);
if (PageGetFreeSpace(page) >= itemsz)
break;
insertPage = IvfflatPageGetOpaque(page)->nextblkno;
if (BlockNumberIsValid(insertPage))
@@ -99,15 +94,31 @@ InsertTuple(Relation rel, IndexTuple itup, Relation heapRel, Datum *values)
/* Move to next page */
GenericXLogAbort(state);
UnlockReleaseBuffer(buf);
LoadInsertPage(rel, &buf, &page, &state, insertPage);
}
else
{
/* Add a new page */
IvfflatAppendPage(rel, &buf, &page, &state, MAIN_FORKNUM);
Buffer newbuf = IvfflatNewBuffer(rel, MAIN_FORKNUM);
Page newpage = GenericXLogRegisterBuffer(state, buf, GENERIC_XLOG_FULL_IMAGE);
insertPage = BufferGetBlockNumber(buf);
insertPage = BufferGetBlockNumber(newbuf);
/* Update previous buffer */
IvfflatPageGetOpaque(page)->nextblkno = insertPage;
/* Init page */
PageInit(newpage, BufferGetPageSize(newbuf), sizeof(IvfflatPageOpaqueData));
IvfflatPageGetOpaque(newpage)->nextblkno = InvalidBlockNumber;
IvfflatPageGetOpaque(newpage)->page_id = IVFFLAT_PAGE_ID;
/* Commit */
MarkBufferDirty(buf);
MarkBufferDirty(newbuf);
GenericXLogFinish(state);
/* Unlock */
UnlockReleaseBuffer(buf);
UnlockReleaseBuffer(newbuf);
}
}

33
test/t/007_inserts.pl Normal file
View File

@@ -0,0 +1,33 @@
use strict;
use warnings;
use PostgresNode;
use TestLib;
use Test::More tests => 3;
# Initialize node
my $node = get_new_node('node');
$node->init;
$node->start;
# Create table and index
$node->safe_psql("postgres", "CREATE EXTENSION vector;");
$node->safe_psql("postgres", "CREATE TABLE tst (v vector(768));");
$node->safe_psql("postgres",
"INSERT INTO tst SELECT (SELECT array_agg(random()) FROM generate_series(1, 768)) FROM generate_series(1, 10000) i;"
);
$node->safe_psql("postgres", "CREATE INDEX ON tst USING ivfflat (v);");
$node->pgbench(
"--no-vacuum --client=5 --transactions=100",
0,
[qr{actually processed}],
[qr{^$}],
"concurrent INSERTs",
{
"007_concurrent" => q(
BEGIN;
INSERT INTO tst SELECT (SELECT array_agg(random()) FROM generate_series(1, 768)) FROM generate_series(1, 10) i;
COMMIT;
),
}
);