parseBinaryColumnData function
Função auxiliar para analisar dados de coluna em formato binário.
columnType
: O tipo da coluna (valor inteiro representando o tipo MySQL).
data
: Um ByteData que fornece acesso aos bytes do buffer.
buffer
: O Uint8List original contendo os dados.
startOffset
: A posição inicial no buffer para leitura.
Retorna uma Tuple2
contendo:
- item1: O valor lido da coluna (geralmente convertido para string ou, em casos binários, um Uint8List).
- item2: O número de bytes consumidos durante a leitura.
Caso o tipo da coluna não seja implementado, lança MySQLProtocolException.
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;
// Lê o número de bytes (pode ser 0, 4, 7 ou 11)
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;
// Lê o número de bytes (pode ser 0, 8 ou 12)
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:
{
// Dados textuais length-encoded
final result = buffer.getUtf8LengthEncodedString(startOffset);
return Tuple2(result.item1, result.item2);
}
case mysqlColumnTypeDecimal:
case mysqlColumnTypeNewDecimal:
{
final lengthEncoded = buffer.getLengthEncodedBytes(startOffset);
// Converte ASCII para string, p. ex. "99.99"
final strValue = String.fromCharCodes(lengthEncoded.item1);
return Tuple2(strValue, lengthEncoded.item2);
}
case mysqlColumnTypeLongBlob:
case mysqlColumnTypeMediumBlob:
case mysqlColumnTypeBlob:
case mysqlColumnTypeTinyBlob:
case mysqlColumnTypeGeometry:
case mysqlColumnTypeBit:
{
// Para dados binários, retorna os bytes crus
final lengthEncoded = buffer.getLengthEncodedBytes(startOffset);
return Tuple2(lengthEncoded.item1, lengthEncoded.item2);
}
case mysqlColumnTypeYear:
{
// Lê 2 bytes para YEAR
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",
);
}