parseBinaryColumnData function

Tuple2<String, int> parseBinaryColumnData(
  1. int columnType,
  2. ByteData data,
  3. Uint8List buffer,
  4. int startOffset,
)

Implementation

Tuple2<String, int> parseBinaryColumnData(
  int columnType,
  ByteData data,
  Uint8List buffer,
  int startOffset,
) {
  switch (columnType) {
    case mysqlColumnTypeTiny:
      final value = data.getInt8(startOffset);
      return Tuple2(value.toString(), 1);
    case mysqlColumnTypeShort:
      final value = data.getInt16(startOffset, Endian.little);
      return Tuple2(value.toString(), 2);
    case mysqlColumnTypeLong:
    case mysqlColumnTypeInt24:
      final value = data.getInt32(startOffset, Endian.little);
      return Tuple2(value.toString(), 4);
    case mysqlColumnTypeLongLong:
      final value = data.getInt64(startOffset, Endian.little);
      return Tuple2(value.toString(), 8);
    case mysqlColumnTypeFloat:
      final value = data.getFloat32(startOffset, Endian.little);
      return Tuple2(value.toString(), 4);
    case mysqlColumnTypeDouble:
      final value = data.getFloat64(startOffset, Endian.little);
      return Tuple2(value.toString(), 8);
    case mysqlColumnTypeDate:
    case mysqlColumnTypeDateTime:
    case mysqlColumnTypeTimestamp:
      final initialOffset = startOffset;

      // read number of bytes (0, 4, 7, 11)
      final numOfBytes = data.getUint8(startOffset);
      startOffset += 1;

      if (numOfBytes == 0) {
        return Tuple2("0000-00-00 00:00:00", 1);
      }

      var year = 0;
      var month = 0;
      var day = 0;
      var hour = 0;
      var minute = 0;
      var second = 0;
      var microSecond = 0;

      if (numOfBytes >= 4) {
        year = data.getUint16(startOffset, Endian.little);
        startOffset += 2;

        month = data.getUint8(startOffset);
        startOffset += 1;

        day = data.getUint8(startOffset);
        startOffset += 1;
      }

      if (numOfBytes >= 7) {
        hour = data.getUint8(startOffset);
        startOffset += 1;

        minute = data.getUint8(startOffset);
        startOffset += 1;

        second = data.getUint8(startOffset);
        startOffset += 1;
      }

      if (numOfBytes >= 11) {
        microSecond = data.getUint32(startOffset, Endian.little);
        startOffset += 4;
      }

      final result = StringBuffer();
      result.write('$year-');
      result.write('${month.toString().padLeft(2, '0')}-');
      result.write('${day.toString().padLeft(2, '0')} ');
      result.write('${hour.toString().padLeft(2, '0')}:');
      result.write('${minute.toString().padLeft(2, '0')}:');
      result.write('${second.toString().padLeft(2, '0')}.');
      result.write(microSecond.toString());

      return Tuple2(result.toString(), startOffset - initialOffset);
    case mysqlColumnTypeTime:
      final initialOffset = startOffset;

      // read number of bytes (0, 8, 12)
      final numOfBytes = data.getUint8(startOffset);
      startOffset += 1;

      if (numOfBytes == 0) {
        return Tuple2("00:00:00", 1);
      }

      var isNegative = false;
      var days = 0;
      var hours = 0;
      var minutes = 0;
      var seconds = 0;
      var microSecond = 0;

      if (numOfBytes >= 8) {
        isNegative = data.getUint8(startOffset) > 0;
        startOffset += 1;

        days = data.getUint32(startOffset, Endian.little);
        startOffset += 4;

        hours = data.getUint8(startOffset);
        startOffset += 1;

        minutes = data.getUint8(startOffset);
        startOffset += 1;

        seconds = data.getUint8(startOffset);
        startOffset += 1;
      }

      if (numOfBytes >= 12) {
        microSecond = data.getUint32(startOffset, Endian.little);
        startOffset += 4;
      }

      hours += days * 24;

      final result = StringBuffer();
      if (isNegative) {
        result.write("-");
      }
      result.write('${hours.toString().padLeft(2, '0')}:');
      result.write('${minutes.toString().padLeft(2, '0')}:');
      result.write('${seconds.toString().padLeft(2, '0')}.');
      result.write(microSecond.toString());

      return Tuple2(result.toString(), startOffset - initialOffset);
    case mysqlColumnTypeString:
    case mysqlColumnTypeVarString:
    case mysqlColumnTypeVarChar:
    case mysqlColumnTypeEnum:
    case mysqlColumnTypeSet:
    case mysqlColumnTypeLongBlob:
    case mysqlColumnTypeMediumBlob:
    case mysqlColumnTypeBlob:
    case mysqlColumnTypeTinyBlob:
    case mysqlColumnTypeGeometry:
    case mysqlColumnTypeBit:
    case mysqlColumnTypeDecimal:
    case mysqlColumnTypeNewDecimal:
      return buffer.getUtf8LengthEncodedString(startOffset);
  }

  throw MySQLProtocolException(
    "Can not parse binary column data: column type $columnType is not implemented",
  );
}