mirror of
https://github.com/pgvector/pgvector.git
synced 2026-07-15 00:56:54 +08:00
Fixed unexpected data beyond EOF error - fixes #29
This commit is contained in:
@@ -1,3 +1,7 @@
|
|||||||
|
## 0.2.7 (unreleased)
|
||||||
|
|
||||||
|
- Fixed `unexpected data beyond EOF` error
|
||||||
|
|
||||||
## 0.2.6 (2022-05-22)
|
## 0.2.6 (2022-05-22)
|
||||||
|
|
||||||
- Improved performance of index creation for Postgres < 12
|
- Improved performance of index creation for Postgres < 12
|
||||||
|
|||||||
@@ -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
|
* Insert a tuple into the index
|
||||||
*/
|
*/
|
||||||
@@ -87,11 +75,18 @@ InsertTuple(Relation rel, IndexTuple itup, Relation heapRel, Datum *values)
|
|||||||
itemsz = MAXALIGN(IndexTupleSize(itup));
|
itemsz = MAXALIGN(IndexTupleSize(itup));
|
||||||
Assert(itemsz <= BLCKSZ - MAXALIGN(SizeOfPageHeaderData) - MAXALIGN(sizeof(IvfflatPageOpaqueData)));
|
Assert(itemsz <= BLCKSZ - MAXALIGN(SizeOfPageHeaderData) - MAXALIGN(sizeof(IvfflatPageOpaqueData)));
|
||||||
|
|
||||||
LoadInsertPage(rel, &buf, &page, &state, insertPage);
|
|
||||||
|
|
||||||
/* Find a page to insert the item */
|
/* 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;
|
insertPage = IvfflatPageGetOpaque(page)->nextblkno;
|
||||||
|
|
||||||
if (BlockNumberIsValid(insertPage))
|
if (BlockNumberIsValid(insertPage))
|
||||||
@@ -99,15 +94,31 @@ InsertTuple(Relation rel, IndexTuple itup, Relation heapRel, Datum *values)
|
|||||||
/* Move to next page */
|
/* Move to next page */
|
||||||
GenericXLogAbort(state);
|
GenericXLogAbort(state);
|
||||||
UnlockReleaseBuffer(buf);
|
UnlockReleaseBuffer(buf);
|
||||||
|
|
||||||
LoadInsertPage(rel, &buf, &page, &state, insertPage);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Add a new page */
|
/* 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
33
test/t/007_inserts.pl
Normal 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;
|
||||||
|
),
|
||||||
|
}
|
||||||
|
);
|
||||||
Reference in New Issue
Block a user