parseWithOutputs static method
Parses a full buffer into rows/columns and optional OUT1 outputs.
Supports v1 row-major, v2 columnar, optional OUT1 trailer, optional
RC1\0 ref-cursor trailer (each sub-message is a full v1 buffer).
Implementation
static ParsedQueryMessage parseWithOutputs(Uint8List data) {
if (data.length < 6) {
throw const FormatException('Buffer too small for version');
}
final readMagic = ByteData.sublistView(
data,
0,
4,
).getUint32(0, _littleEndian);
if (readMagic != magic) {
throw FormatException(
'Invalid magic number: 0x${readMagic.toRadixString(16)}',
);
}
final version = ByteData.sublistView(
data,
4,
6,
).getUint16(0, _littleEndian);
late final ParsedRowBuffer buffer;
late final int mainEnd;
if (version == protocolVersionRowMajor) {
if (data.length < headerSizeV1) {
throw const FormatException('Buffer too small for header');
}
mainEnd = messageLengthFromHeader(data);
if (data.length < mainEnd) {
throw const FormatException('Buffer too small for payload');
}
buffer = _parseRowMajorV1(Uint8List.sublistView(data, 0, mainEnd));
} else if (version == protocolVersionColumnarV2) {
if (data.length < headerSizeColumnarV2) {
throw const FormatException('Buffer too small for columnar v2 header');
}
final payloadSize =
ByteData.sublistView(data, 15, 19).getUint32(0, _littleEndian);
mainEnd = headerSizeColumnarV2 + payloadSize;
if (data.length < mainEnd) {
throw const FormatException('Buffer too small for columnar payload');
}
buffer = _parseColumnarV2(Uint8List.sublistView(data, 0, mainEnd));
} else {
throw FormatException('Unsupported protocol version: $version');
}
var off = mainEnd;
final outputs = <ParamValue>[];
off = _parseOut1IfPresent(
data: data,
start: off,
outputs: outputs,
);
final refCursors = <ParsedRowBuffer>[];
off = _parseRc1IfPresent(
data: data,
start: off,
out: refCursors,
);
if (off < data.length) {
if (data.length - off >= 4) {
final peek = ByteData.sublistView(
data,
off,
off + 4,
).getUint32(0, _littleEndian);
if (peek == outputFooterMagic || peek == refCursorFooterMagic) {
throw const FormatException(
'Buffer too small for complete OUT1 or RC1 trailer',
);
}
}
}
return ParsedQueryMessage(
rowBuffer: buffer,
outputParamValues: outputs,
refCursorRowBuffers: refCursors,
);
}