insert method
Implementation
Future<TupleLocation> insert({
required Map<String, dynamic> values,
required int xmin, // creating txnId
int rowId = 0, // 0 = auto-assign
}) async {
if (rowId <= 0) {
rowId = _nextRowId;
}
if (rowId >= _nextRowId) _nextRowId = rowId + 1;
final header = MvccTupleHeader(xmin: xmin, xmax: 0, rowId: rowId);
final tuple = TupleCodec.encode(
schema: schema,
values: values,
header: header,
);
if (tuple.length > PageConst.pageSize - PageConst.headerSize - PageConst.slotSize) {
throw TupleTooBigException(
tuple.length, PageConst.pageSize - PageConst.headerSize - PageConst.slotSize);
}
// Ensure root page exists
if (meta.rootPageId < 0) {
meta.rootPageId = await _allocatePage();
}
// Find a page with enough space
TupleLocation? loc;
for (final pid in await _allPageIds()) {
final page = await _getPage(pid);
final slotIdx = page.insertTuple(tuple);
if (slotIdx >= 0) {
await _putPage(page);
loc = TupleLocation(pid, slotIdx);
break;
}
}
// No existing page had space — allocate new page
if (loc == null) {
// Link new page to end of chain
final allIds = await _allPageIds();
final lastId = allIds.isNotEmpty ? allIds.last : meta.rootPageId;
final newPid = await _allocatePage();
// Update last page's next pointer
final lastPage = await _getPage(lastId);
lastPage.setNextPage(newPid);
await _putPage(lastPage);
// Insert into new page
final newPage = await _getPage(newPid);
final slotIdx = newPage.insertTuple(tuple);
await _putPage(newPage);
loc = TupleLocation(newPid, slotIdx);
}
meta.rowCount++;
return loc;
}