parseColumnarV2ToRowBuffer function
Implementation
ParsedRowBuffer parseColumnarV2ToRowBuffer(Uint8List data) {
if (data.length < BinaryProtocolConstants.headerSizeColumnarV2) {
throw const FormatException('Columnar v2: buffer too small');
}
final bd = ByteData.sublistView(data);
final colCount = bd.getUint16(8, _littleEndian);
final rowCount = bd.getUint32(10, _littleEndian);
final paySize = bd.getUint32(15, _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),
);
for (var c = 0; c < colCount; c++) {
if (off + 4 > end) {
throw const FormatException('Columnar v2: metadata truncated');
}
final odbcType = bd.getUint16(off, _littleEndian);
off += 2;
final nameLen = bd.getUint16(off, _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,
bd: bd,
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,
);
}