From 637d5c3a90b99be773d87961a8ac2a33314ddb09 Mon Sep 17 00:00:00 2001 From: Bradley Grainger Date: Thu, 17 Apr 2025 11:49:30 -0700 Subject: [PATCH 1/2] Add test to reproduce bug. Signed-off-by: Bradley Grainger --- tests/IntegrationTests/DataTypes.cs | 6 ++++++ tests/IntegrationTests/DataTypesFixture.cs | 16 +++++++++------- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/tests/IntegrationTests/DataTypes.cs b/tests/IntegrationTests/DataTypes.cs index b03650cbd..6d5b1e170 100644 --- a/tests/IntegrationTests/DataTypes.cs +++ b/tests/IntegrationTests/DataTypes.cs @@ -329,6 +329,8 @@ public void QueryDecimal(string column, object[] expected) [InlineData("latin1", new[] { null, "", "ASCII", "Lãtïñ", c_251ByteString })] [InlineData("latin1bin", new[] { null, "", "ASCII", "Lãtïñ", c_251ByteString })] [InlineData("cp1251", new[] { null, "", "ASCII", "АБВГабвг", c_251ByteString })] + [InlineData("nonguid_utf8", new[] { null, "", "ASCII", "Ũńıċōđĕ", "This string has 36 characters in it." })] + [InlineData("nonguid_latin1", new[] { null, "", "ASCII", "Lãtïñ", "This string has 36 characters in it." })] public void QueryString(string column, string[] expected) { DoQuery("strings", column, "VARCHAR", expected, reader => reader.GetString(0)); @@ -1328,6 +1330,8 @@ public void GetSchemaTableAfterNextResult() [InlineData("cp1251", "datatypes_strings", MySqlDbType.VarChar, "VARCHAR", 300, typeof(string), "N", -1, 0)] [InlineData("guid", "datatypes_strings", MySqlDbType.Guid, "CHAR(36)", 36, typeof(Guid), "N", -1, 0)] [InlineData("guidbin", "datatypes_strings", MySqlDbType.Guid, "CHAR(36)", 36, typeof(Guid), "N", -1, 0)] + [InlineData("nonguid_utf8", "datatypes_strings", MySqlDbType.VarChar, "VARCHAR", 36, typeof(string), "N", -1, 0)] + [InlineData("nonguid_latin1", "datatypes_strings", MySqlDbType.VarChar, "VARCHAR", 36, typeof(string), "N", -1, 0)] [InlineData("Date", "datatypes_times", MySqlDbType.Date, "DATE", 10, typeof(DateTime), "N", -1, 0)] [InlineData("DateTime", "datatypes_times", MySqlDbType.DateTime, "DATETIME", 26, typeof(DateTime), "N", -1, 6)] [InlineData("Timestamp", "datatypes_times", MySqlDbType.Timestamp, "TIMESTAMP", 26, typeof(DateTime), "N", -1, 6)] @@ -1420,6 +1424,8 @@ public void GetColumnSchema(string column, string table, MySqlDbType mySqlDbType [InlineData("BigDecimal", "datatypes_reals", MySqlDbType.NewDecimal, "DECIMAL(50,30)", typeof(decimal), 3, null)] [InlineData("utf8", "datatypes_strings", MySqlDbType.VarChar, "VARCHAR(300)", typeof(string), 3, "ASCII")] [InlineData("latin1", "datatypes_strings", MySqlDbType.VarChar, "VARCHAR(300)", typeof(string), 3, "ASCII")] + [InlineData("nonguid_utf8", "datatypes_strings", MySqlDbType.VarChar, "VARCHAR(36)", typeof(string), 3, "ASCII")] + [InlineData("nonguid_latin1", "datatypes_strings", MySqlDbType.VarChar, "VARCHAR(36)", typeof(string), 3, "ASCII")] [InlineData("Date", "datatypes_times", MySqlDbType.Date, "DATE", typeof(DateTime), 2, null)] [InlineData("DateTime", "datatypes_times", MySqlDbType.DateTime, "DATETIME", typeof(DateTime), 2, null)] [InlineData("Timestamp", "datatypes_times", MySqlDbType.Timestamp, "TIMESTAMP", typeof(DateTime), 2, null)] diff --git a/tests/IntegrationTests/DataTypesFixture.cs b/tests/IntegrationTests/DataTypesFixture.cs index f9ad28a38..471e519a8 100644 --- a/tests/IntegrationTests/DataTypesFixture.cs +++ b/tests/IntegrationTests/DataTypesFixture.cs @@ -121,21 +121,23 @@ latin1 varchar(300) character set 'latin1' null, latin1bin varchar(300) character set latin1 collate latin1_bin null, cp1251 varchar(300) character set 'cp1251' null, guid char(36) null, - guidbin char(36) binary null + guidbin char(36) binary null, + nonguid_utf8 varchar(36) character set 'utf8mb4' null, + nonguid_latin1 varchar(36) character set 'latin1' null ); -insert into datatypes_strings(utf8, utf8bin, latin1, latin1bin, cp1251, guid, guidbin) +insert into datatypes_strings(utf8, utf8bin, latin1, latin1bin, cp1251, guid, guidbin, nonguid_utf8, nonguid_latin1) values - (null, null, null, null, null, null, null), - ('', '', '', '', '', '00000000-0000-0000-0000-000000000000', '00000000-0000-0000-0000-000000000000'), - ('ASCII', 'ASCII', 'ASCII', 'ASCII', 'ASCII', '00000000-0000-0000-c000-000000000046', '00000000-0000-0000-c000-000000000046'), - ('Ũńıċōđĕ', 'Ũńıċōđĕ', 'Lãtïñ', 'Lãtïñ', 'АБВГабвг', 'fd24a0e8-c3f2-4821-a456-35da2dc4bb8f', 'fd24a0e8-c3f2-4821-a456-35da2dc4bb8f'), + (null, null, null, null, null, null, null, null, null), + ('', '', '', '', '', '00000000-0000-0000-0000-000000000000', '00000000-0000-0000-0000-000000000000', '', ''), + ('ASCII', 'ASCII', 'ASCII', 'ASCII', 'ASCII', '00000000-0000-0000-c000-000000000046', '00000000-0000-0000-c000-000000000046', 'ASCII', 'ASCII'), + ('Ũńıċōđĕ', 'Ũńıċōđĕ', 'Lãtïñ', 'Lãtïñ', 'АБВГабвг', 'fd24a0e8-c3f2-4821-a456-35da2dc4bb8f', 'fd24a0e8-c3f2-4821-a456-35da2dc4bb8f', 'Ũńıċōđĕ', 'Lãtïñ'), ('This string has exactly 251 characters in it. The encoded length is stored as 0xFC 0xFB 0x00. 0xFB (i.e., 251) is the sentinel byte indicating ""this field is null"". Incorrectly interpreting the (decoded) length as the sentinel byte would corrupt data.', 'This string has exactly 251 characters in it. The encoded length is stored as 0xFC 0xFB 0x00. 0xFB (i.e., 251) is the sentinel byte indicating ""this field is null"". Incorrectly interpreting the (decoded) length as the sentinel byte would corrupt data.', 'This string has exactly 251 characters in it. The encoded length is stored as 0xFC 0xFB 0x00. 0xFB (i.e., 251) is the sentinel byte indicating ""this field is null"". Incorrectly interpreting the (decoded) length as the sentinel byte would corrupt data.', 'This string has exactly 251 characters in it. The encoded length is stored as 0xFC 0xFB 0x00. 0xFB (i.e., 251) is the sentinel byte indicating ""this field is null"". Incorrectly interpreting the (decoded) length as the sentinel byte would corrupt data.', 'This string has exactly 251 characters in it. The encoded length is stored as 0xFC 0xFB 0x00. 0xFB (i.e., 251) is the sentinel byte indicating ""this field is null"". Incorrectly interpreting the (decoded) length as the sentinel byte would corrupt data.', - '6a0e0a40-6228-11d3-a996-0050041896c8', '6a0e0a40-6228-11d3-a996-0050041896c8'); + '6a0e0a40-6228-11d3-a996-0050041896c8', '6a0e0a40-6228-11d3-a996-0050041896c8', 'This string has 36 characters in it.', 'This string has 36 characters in it.'); drop table if exists datatypes_blobs; create table datatypes_blobs( From 3dca6b1878a342b4c29fdb0a5ba47f8fbb353cf2 Mon Sep 17 00:00:00 2001 From: Bradley Grainger Date: Thu, 17 Apr 2025 11:53:29 -0700 Subject: [PATCH 2/2] Only treat CHAR(n) columns as Guids. Fixes #1565 This reverts a change in #1546 that was introduced to fix #1528. However, none of the integration tests fail locally when reverting this change, so it's not clear why it was necessary. Signed-off-by: Bradley Grainger --- src/MySqlConnector/ColumnReaders/ColumnReader.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/MySqlConnector/ColumnReaders/ColumnReader.cs b/src/MySqlConnector/ColumnReaders/ColumnReader.cs index ec6d1c85d..86ba9145f 100644 --- a/src/MySqlConnector/ColumnReaders/ColumnReader.cs +++ b/src/MySqlConnector/ColumnReaders/ColumnReader.cs @@ -45,13 +45,13 @@ public static ColumnReader Create(bool isBinary, ColumnDefinitionPayload columnD return BitColumnReader.Instance; case ColumnType.String: - case ColumnType.VarString: if (connection.GuidFormat == MySqlGuidFormat.Char36 && columnDefinition.ColumnLength / ProtocolUtility.GetBytesPerCharacter(columnDefinition.CharacterSet) == 36) return GuidChar36ColumnReader.Instance; if (connection.GuidFormat == MySqlGuidFormat.Char32 && columnDefinition.ColumnLength / ProtocolUtility.GetBytesPerCharacter(columnDefinition.CharacterSet) == 32) return GuidChar32ColumnReader.Instance; - goto case ColumnType.VarChar; + goto case ColumnType.VarString; + case ColumnType.VarString: case ColumnType.VarChar: case ColumnType.TinyBlob: case ColumnType.Blob: