parseBinaryColumnData function
Implementation
Tuple2<dynamic, int> parseBinaryColumnData(
int columnType,
ByteData data,
Uint8List buffer,
int startOffset,
int flags,
) {
switch (columnType) {
case mysqlColumnTypeTiny: // 1 byte
{
final value = data.getInt8(startOffset);
return Tuple2(value.toString(), 1);
}
case mysqlColumnTypeShort: // 2 bytes
{
final value = data.getInt16(startOffset, Endian.little);
return Tuple2(value.toString(), 2);
}
case mysqlColumnTypeLong: // 4 bytes
case mysqlColumnTypeInt24: // also 4 bytes as per MySQL binary protocol
{
final value = data.getInt32(startOffset, Endian.little);
return Tuple2(value.toString(), 4);
}
case mysqlColumnTypeLongLong: // 8 bytes
{
final value = data.getInt64(startOffset, Endian.little);
return Tuple2(value.toString(), 8);
}
case mysqlColumnTypeFloat: // 4 bytes
{
final value = data.getFloat32(startOffset, Endian.little);
return Tuple2(value.toString(), 4);
}
case mysqlColumnTypeDouble: // 8 bytes
{
final value = data.getFloat64(startOffset, Endian.little);
return Tuple2(value.toString(), 8);
}
case mysqlColumnTypeNull:
return Tuple2(null, 0);
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 isBinary = (flags & 0x80) != 0;
if (isBinary) {
final lengthEncoded = buffer.getLengthEncodedBytes(startOffset);
return Tuple2(lengthEncoded.item1, lengthEncoded.item2);
} else {
final result = buffer.getUtf8LengthEncodedString(startOffset);
return Tuple2(result.item1, result.item2);
}
}
case mysqlColumnTypeYear:
{
final yearValue = data.getUint16(startOffset, Endian.little);
return Tuple2(yearValue.toString(), 2);
}
case mysqlColumnTypeJson:
{
final lengthEncoded = buffer.getLengthEncodedBytes(startOffset);
final jsonBytes = lengthEncoded.item1;
final bytesConsumed = lengthEncoded.item2;
try {
final jsonString = utf8.decode(jsonBytes);
final jsonObject = jsonDecode(jsonString);
return Tuple2(jsonObject, bytesConsumed);
} catch (e) {
return Tuple2(utf8.decode(jsonBytes), bytesConsumed);
}
}
}
throw MySQLProtocolException(
"Can not parse binary column data: column type $columnType is not implemented",
);
}