diff --git a/test/core/database/mysql_grid_types_test.dart b/test/core/database/mysql_grid_types_test.dart index c3911da8..7f885e76 100644 --- a/test/core/database/mysql_grid_types_test.dart +++ b/test/core/database/mysql_grid_types_test.dart @@ -147,4 +147,86 @@ void main() { expect(identical(res1, res2), isTrue); }); }); + + group('mysqlColumnHoldsRawBytes', () { + const binary = mysqlCharsetBinary; + const utf8mb4 = 255; + + test('numbers, dates, JSON, ENUM and SET are text even with charset 63', + () { + // The server reports charset 63 for every non-string column; read as + // bytes, an INT 10 showed as 0x3130 in the grid. + for (final type in [ + mysqlColumnTypeTiny, + mysqlColumnTypeShort, + mysqlColumnTypeLong, + mysqlColumnTypeLongLong, + mysqlColumnTypeInt24, + mysqlColumnTypeNewDecimal, + mysqlColumnTypeFloat, + mysqlColumnTypeDouble, + mysqlColumnTypeDate, + mysqlColumnTypeTime, + mysqlColumnTypeDateTime, + mysqlColumnTypeTimestamp, + mysqlColumnTypeYear, + 0xf5, // JSON + mysqlColumnTypeEnum, + mysqlColumnTypeSet, + ]) { + expect( + mysqlColumnHoldsRawBytes(columnType: type, charset: binary), + isFalse, + reason: 'type 0x${type.toRadixString(16)}', + ); + } + }); + + test('BINARY, VARBINARY and BLOB (charset 63) are bytes', () { + for (final type in [ + mysqlColumnTypeString, + mysqlColumnTypeVarString, + mysqlColumnTypeVarChar, + mysqlColumnTypeTinyBlob, + mysqlColumnTypeBlob, + mysqlColumnTypeMediumBlob, + mysqlColumnTypeLongBlob, + ]) { + expect( + mysqlColumnHoldsRawBytes(columnType: type, charset: binary), + isTrue, + reason: 'type 0x${type.toRadixString(16)}', + ); + } + }); + + test('CHAR, VARCHAR and TEXT with a text charset are text', () { + for (final type in [ + mysqlColumnTypeString, + mysqlColumnTypeVarString, + mysqlColumnTypeBlob, // TEXT is a BLOB type + mysqlColumnTypeMediumBlob, + mysqlColumnTypeLongBlob, + ]) { + expect( + mysqlColumnHoldsRawBytes(columnType: type, charset: utf8mb4), + isFalse, + reason: 'type 0x${type.toRadixString(16)}', + ); + } + }); + + test('BIT and GEOMETRY are always bytes', () { + expect( + mysqlColumnHoldsRawBytes( + columnType: mysqlColumnTypeBit, charset: binary), + isTrue, + ); + expect( + mysqlColumnHoldsRawBytes( + columnType: mysqlColumnTypeGeometry, charset: binary), + isTrue, + ); + }); + }); } diff --git a/third_party/mysql_client/lib/src/mysql_protocol/mysql_column_type.dart b/third_party/mysql_client/lib/src/mysql_protocol/mysql_column_type.dart index 9fcae8c9..65e63d25 100644 --- a/third_party/mysql_client/lib/src/mysql_protocol/mysql_column_type.dart +++ b/third_party/mysql_client/lib/src/mysql_protocol/mysql_column_type.dart @@ -42,16 +42,23 @@ bool mysqlColumnHoldsRawBytes({ required int columnType, required int charset, }) { - if (charset == mysqlCharsetBinary) { - return true; - } switch (columnType) { case mysqlColumnTypeBit: + case mysqlColumnTypeGeometry: + return true; + // A string or BLOB column holds bytes only with the binary character set + // (BINARY, VARBINARY, BLOB); TEXT is a BLOB type with a text character set. + case mysqlColumnTypeVarChar: + case mysqlColumnTypeVarString: + case mysqlColumnTypeString: case mysqlColumnTypeTinyBlob: case mysqlColumnTypeMediumBlob: case mysqlColumnTypeLongBlob: case mysqlColumnTypeBlob: - return true; + return charset == mysqlCharsetBinary; + // Numbers, dates, JSON, ENUM / SET: the server reports charset 63 for + // every non-string column, so it says nothing about bytes here. Taken as + // bytes, an INT 10 showed as 0x3130 in the grid. default: return false; }