parseColumnarV2ToRowBuffer function

ParsedRowBuffer parseColumnarV2ToRowBuffer(
  1. Uint8List data
)

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,
  );
}