parseColumnarV2ToRowBuffer function
Implementation
ParsedRowBuffer parseColumnarV2ToRowBuffer(Uint8List data) {
if (data.length < BinaryProtocolConstants.headerSizeColumnarV2) {
throw const FormatException('Columnar v2: buffer too small');
}
final colCount = ByteData.sublistView(
data,
8,
10,
).getUint16(0, _littleEndian);
final rowCount = ByteData.sublistView(
data,
10,
14,
).getUint32(0, _littleEndian);
final paySize = ByteData.sublistView(
data,
15,
19,
).getUint32(0, _littleEndian);
if (data.length < BinaryProtocolConstants.headerSizeColumnarV2 + paySize) {
throw const FormatException('Columnar v2: truncated payload');
}
if (colCount > data.length || rowCount > data.length) {
throw FormatException(
'Columnar v2 header oversized: rows=$rowCount, cols=$colCount, '
'buffer=${data.length}',
);
}
if (colCount > 0 && rowCount > paySize) {
throw FormatException(
'Columnar v2 header inconsistent: rows=$rowCount cannot fit in '
'payload=$paySize',
);
}
if (colCount == 0) {
return ParsedRowBuffer(
columns: [],
rows: [],
rowCount: 0,
columnCount: 0,
);
}
var off = BinaryProtocolConstants.headerSizeColumnarV2;
final end = BinaryProtocolConstants.headerSizeColumnarV2 + paySize;
final columnMetas = <ColumnMetadata>[];
final rows = List<List<dynamic>>.generate(
rowCount,
(_) => List<dynamic>.filled(colCount, null),
growable: false,
);
for (var c = 0; c < colCount; c++) {
if (off + 4 > end) {
throw const FormatException('Columnar v2: metadata truncated');
}
final odbcType = ByteData.sublistView(
data,
off,
off + 2,
).getUint16(0, _littleEndian);
off += 2;
final nameLen = ByteData.sublistView(
data,
off,
off + 2,
).getUint16(0, _littleEndian);
off += 2;
if (off + nameLen > end) {
throw const FormatException('Columnar v2: name truncated');
}
final name = utf8.decode(
Uint8List.sublistView(data, off, off + nameLen),
allowMalformed: true,
);
off += nameLen;
columnMetas.add(ColumnMetadata(name: name, odbcType: odbcType));
if (off >= end) {
throw const FormatException('Columnar v2: missing column payload');
}
final isCompressed = data[off++];
final raw = _readColumnarColumnPayload(
data: data,
off: off,
end: end,
isCompressed: isCompressed,
);
off = raw.nextOffset;
fillColumnarRowsIntoRowBuffer(
odbcType: odbcType,
raw: raw.bytes,
columnIndex: c,
rows: rows,
);
}
if (off != end) {
throw const FormatException('Columnar v2: extra bytes in column payload');
}
return ParsedRowBuffer(
columns: columnMetas,
rows: rows,
rowCount: rowCount,
columnCount: colCount,
);
}