parseBinaryColumnData function

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

Implementation

Tuple2<dynamic, 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;
        final numOfBytes = data.getUint8(startOffset);
        startOffset += 1;

        // Quando numOfBytes == 0, MySQL envia datas/timestamps '0000-00-00 00:00:00'
        if (numOfBytes == 0) {
          return Tuple2("0000-00-00 00:00:00", 1);
        }

        var year = 0, month = 0, day = 0;
        var hour = 0, minute = 0, second = 0, 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()
          ..write('$year-')
          ..write('${month.toString().padLeft(2, '0')}-')
          ..write('${day.toString().padLeft(2, '0')} ')
          ..write('${hour.toString().padLeft(2, '0')}:')
          ..write('${minute.toString().padLeft(2, '0')}:')
          ..write(second.toString().padLeft(2, '0'));

        if (numOfBytes >= 11) {
          result.write('.$microSecond');
        }

        final consumed = startOffset - initialOffset;
        return Tuple2(result.toString(), consumed);
      }

    case mysqlColumnTypeTime:
    case mysqlColumnTypeTime2:
      {
        final initialOffset = startOffset;
        final numOfBytes = data.getUint8(startOffset);
        startOffset += 1;

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

        var isNegative = false;
        var days = 0, hours = 0, minutes = 0, seconds = 0, 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 timeResult = StringBuffer();
        if (isNegative) {
          timeResult.write("-");
        }
        timeResult.write('${hours.toString().padLeft(2, '0')}:');
        timeResult.write('${minutes.toString().padLeft(2, '0')}:');
        timeResult.write(seconds.toString().padLeft(2, '0'));

        if (numOfBytes >= 12) {
          timeResult.write('.${microSecond.toString()}');
        }

        final consumed = startOffset - initialOffset;
        return Tuple2(timeResult.toString(), consumed);
      }

    case mysqlColumnTypeString:
    case mysqlColumnTypeVarString:
    case mysqlColumnTypeVarChar:
    case mysqlColumnTypeEnum:
    case mysqlColumnTypeSet:
      {
        final result = buffer.getUtf8LengthEncodedString(startOffset);
        return Tuple2(result.item1, result.item2);
      }

    case mysqlColumnTypeDecimal:
    case mysqlColumnTypeNewDecimal:
      {
        final lengthEncoded = buffer.getLengthEncodedBytes(startOffset);
        final strValue = String.fromCharCodes(lengthEncoded.item1);
        return Tuple2(strValue, lengthEncoded.item2);
      }

    case mysqlColumnTypeLongBlob:
    case mysqlColumnTypeMediumBlob:
    case mysqlColumnTypeBlob:
    case mysqlColumnTypeTinyBlob:
    case mysqlColumnTypeGeometry:
    case mysqlColumnTypeBit:
      {
        final lengthEncoded = buffer.getLengthEncodedBytes(startOffset);
        return Tuple2(lengthEncoded.item1, lengthEncoded.item2);
      }

    case mysqlColumnTypeYear:
      {
        final yearValue = data.getUint16(startOffset, Endian.little);
        return Tuple2(yearValue.toString(), 2);
      }
  }

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