build method
Builds the binary data buffer for bulk insert.
Version BulkPayloadVersion.v2 is the default and preserves
variable-width binary values, including embedded NUL bytes. Use
BulkPayloadVersion.legacy only when talking to native engines that do
not understand the versioned BLK2 payload.
Uses a two-pass strategy: phase 1 pre-encodes variable-width payloads and computes the exact total byte count; phase 2 writes directly into a single pre-sized Uint8List.
Validates that table name, columns, and at least one row are present. Returns a Uint8List containing the serialized bulk insert data.
Throws StateError if table name is empty, no columns are defined, no rows have been added, or a non-nullable column contains null.
Implementation
Uint8List build({BulkPayloadVersion version = BulkPayloadVersion.v2}) {
if (_table.isEmpty) {
throw StateError('Table name required');
}
if (_columns.isEmpty) {
throw StateError('At least one column required');
}
if (_effectiveRowCount == 0) {
throw StateError('At least one row required');
}
// Keep a final nullability check because addRow stores row references.
// Caller code can still mutate rows after insertion.
if (!_usesColumnar) {
for (var c = 0; c < _columns.length; c++) {
final spec = _columns[c];
if (!spec.nullable) {
for (var r = 0; r < _rows.length; r++) {
final value = _rows[r][c];
if (value == null) {
_throwNullabilityError(spec.name, r + 1);
}
}
}
}
}
final cache = _prepareEncodeCache(version);
final out = Uint8List(cache.totalBytes);
final w = _WriteCursor(out);
if (version == BulkPayloadVersion.v2) {
w
..writeBytes(_bulkPayloadV2Magic)
..writeU16Le(_bulkPayloadV2Version)
..writeU16Le(_bulkPayloadV2Flags);
}
w
..writeU32Le(cache.tableBytes.length)
..writeBytes(cache.tableBytes)
..writeU32Le(_columns.length);
for (var i = 0; i < _columns.length; i++) {
final spec = _columns[i];
final nameBytes = cache.columnNameBytes[i];
w
..writeU32Le(nameBytes.length)
..writeBytes(nameBytes)
..writeByte(spec.tag)
..writeByte(spec.nullable ? 1 : 0)
..writeU32Le(spec.maxLen);
}
final rowCount = _effectiveRowCount;
w.writeU32Le(rowCount);
for (var c = 0; c < _columns.length; c++) {
_writeColumn(
w,
version,
_columns[c],
c,
rowCount,
cache.v2VariableCells[c],
_usesColumnar ? _columnarData[c] : null,
);
}
assert(
w.offset == cache.totalBytes,
'bulk payload write cursor ${w.offset} != ${cache.totalBytes}',
);
return out;
}