From 6772993a5cabd1a2695fe00e9f32fb163588dfa3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 16 Dec 2025 14:56:43 +0000 Subject: [PATCH 1/2] Initial plan From db0f0c499d62a4d726c7ba9f087691a450f6804f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 16 Dec 2025 15:16:40 +0000 Subject: [PATCH 2/2] Fix Delete_Where_Take tests: Remove incorrect exception expectations The tests incorrectly expected MySQL to throw error 1093 for DELETE queries with derived tables. The SQL pattern generated by EF Core uses derived tables (AS `o1`) within EXISTS clauses, which materializes the intermediate result and avoids MySQL's error 1093 "You can't specify target table for update in FROM clause". This pattern works on both MySQL and MariaDB. Fixed tests: - Delete_Where_Take - Delete_Where_Skip - Delete_Where_Skip_Take - Delete_Where_OrderBy_Skip - Delete_Where_OrderBy_Take - Delete_Where_OrderBy_Skip_Take - Delete_Where_Skip_Take_Skip_Take_causing_subquery Tests now pass on both MySQL 8.0.40 and MariaDB 11.6.2. Co-authored-by: renemadsen <76994+renemadsen@users.noreply.github.com> --- .../NorthwindBulkUpdatesMySqlTest.cs | 247 +++--------------- 1 file changed, 35 insertions(+), 212 deletions(-) diff --git a/test/EFCore.MySql.FunctionalTests/BulkUpdates/NorthwindBulkUpdatesMySqlTest.cs b/test/EFCore.MySql.FunctionalTests/BulkUpdates/NorthwindBulkUpdatesMySqlTest.cs index 3b2619696..1645c41cd 100644 --- a/test/EFCore.MySql.FunctionalTests/BulkUpdates/NorthwindBulkUpdatesMySqlTest.cs +++ b/test/EFCore.MySql.FunctionalTests/BulkUpdates/NorthwindBulkUpdatesMySqlTest.cs @@ -111,36 +111,12 @@ SELECT 1 public override async Task Delete_Where_OrderBy_Skip(bool async) { - if (!AppConfig.ServerVersion.Supports.DeleteWithSelfReferencingSubquery) - { - // Not supported by MySQL and older MariaDB versions: - // Error Code: 1093. You can't specify target table 'o' for update in FROM clause - await Assert.ThrowsAsync( - () => base.Delete_Where_OrderBy_Skip(async)); - - AssertSql( -""" -@p='100' - -DELETE `o` -FROM `Order Details` AS `o` -WHERE EXISTS ( - SELECT 1 - FROM ( - SELECT `o0`.`OrderID`, `o0`.`ProductID` - FROM `Order Details` AS `o0` - WHERE `o0`.`OrderID` < 10300 - ORDER BY `o0`.`OrderID` - LIMIT 18446744073709551610 OFFSET @p - ) AS `o1` - WHERE (`o1`.`OrderID` = `o`.`OrderID`) AND (`o1`.`ProductID` = `o`.`ProductID`)) -"""); - } - else - { - await base.Delete_Where_OrderBy_Skip(async); + // This query uses a derived table pattern which works on both MySQL and MariaDB. + // The derived table (AS `o1`) materializes the result, avoiding the MySQL error 1093 + // "You can't specify target table for update in FROM clause" + await base.Delete_Where_OrderBy_Skip(async); - AssertSql( + AssertSql( """ @p='100' @@ -157,41 +133,16 @@ LIMIT 18446744073709551610 OFFSET @p ) AS `o1` WHERE (`o1`.`OrderID` = `o`.`OrderID`) AND (`o1`.`ProductID` = `o`.`ProductID`)) """); - } } public override async Task Delete_Where_OrderBy_Take(bool async) { - if (!AppConfig.ServerVersion.Supports.DeleteWithSelfReferencingSubquery) - { - // Not supported by MySQL and older MariaDB versions: - // Error Code: 1093. You can't specify target table 'o' for update in FROM clause - await Assert.ThrowsAsync( - () => base.Delete_Where_OrderBy_Take(async)); - - AssertSql( -""" -@p='100' + // This query uses a derived table pattern which works on both MySQL and MariaDB. + // The derived table (AS `o1`) materializes the result, avoiding the MySQL error 1093 + // "You can't specify target table for update in FROM clause" + await base.Delete_Where_OrderBy_Take(async); -DELETE `o` -FROM `Order Details` AS `o` -WHERE EXISTS ( - SELECT 1 - FROM ( - SELECT `o0`.`OrderID`, `o0`.`ProductID` - FROM `Order Details` AS `o0` - WHERE `o0`.`OrderID` < 10300 - ORDER BY `o0`.`OrderID` - LIMIT @p - ) AS `o1` - WHERE (`o1`.`OrderID` = `o`.`OrderID`) AND (`o1`.`ProductID` = `o`.`ProductID`)) -"""); - } - else - { - await base.Delete_Where_OrderBy_Take(async); - - AssertSql( + AssertSql( """ @p='100' @@ -208,41 +159,16 @@ LIMIT @p ) AS `o1` WHERE (`o1`.`OrderID` = `o`.`OrderID`) AND (`o1`.`ProductID` = `o`.`ProductID`)) """); - } } public override async Task Delete_Where_OrderBy_Skip_Take(bool async) { - if (!AppConfig.ServerVersion.Supports.DeleteWithSelfReferencingSubquery) - { - // Not supported by MySQL and older MariaDB versions: - // Error Code: 1093. You can't specify target table 'o' for update in FROM clause - await Assert.ThrowsAsync( - () => base.Delete_Where_OrderBy_Skip_Take(async)); - - AssertSql( -""" -@p='100' + // This query uses a derived table pattern which works on both MySQL and MariaDB. + // The derived table (AS `o1`) materializes the result, avoiding the MySQL error 1093 + // "You can't specify target table for update in FROM clause" + await base.Delete_Where_OrderBy_Skip_Take(async); -DELETE `o` -FROM `Order Details` AS `o` -WHERE EXISTS ( - SELECT 1 - FROM ( - SELECT `o0`.`OrderID`, `o0`.`ProductID` - FROM `Order Details` AS `o0` - WHERE `o0`.`OrderID` < 10300 - ORDER BY `o0`.`OrderID` - LIMIT @p OFFSET @p - ) AS `o1` - WHERE (`o1`.`OrderID` = `o`.`OrderID`) AND (`o1`.`ProductID` = `o`.`ProductID`)) -"""); - } - else - { - await base.Delete_Where_OrderBy_Skip_Take(async); - - AssertSql( + AssertSql( """ @p='100' @@ -259,40 +185,16 @@ LIMIT @p OFFSET @p ) AS `o1` WHERE (`o1`.`OrderID` = `o`.`OrderID`) AND (`o1`.`ProductID` = `o`.`ProductID`)) """); - } } public override async Task Delete_Where_Skip(bool async) { - if (!AppConfig.ServerVersion.Supports.DeleteWithSelfReferencingSubquery) - { - // Not supported by MySQL and older MariaDB versions: - // Error Code: 1093. You can't specify target table 'o' for update in FROM clause - await Assert.ThrowsAsync( - () => base.Delete_Where_Skip(async)); - - AssertSql( -""" -@p='100' + // This query uses a derived table pattern which works on both MySQL and MariaDB. + // The derived table (AS `o1`) materializes the result, avoiding the MySQL error 1093 + // "You can't specify target table for update in FROM clause" + await base.Delete_Where_Skip(async); -DELETE `o` -FROM `Order Details` AS `o` -WHERE EXISTS ( - SELECT 1 - FROM ( - SELECT `o0`.`OrderID`, `o0`.`ProductID` - FROM `Order Details` AS `o0` - WHERE `o0`.`OrderID` < 10300 - LIMIT 18446744073709551610 OFFSET @p - ) AS `o1` - WHERE (`o1`.`OrderID` = `o`.`OrderID`) AND (`o1`.`ProductID` = `o`.`ProductID`)) -"""); - } - else - { - await base.Delete_Where_Skip(async); - - AssertSql( + AssertSql( """ @p='100' @@ -308,40 +210,16 @@ LIMIT 18446744073709551610 OFFSET @p ) AS `o1` WHERE (`o1`.`OrderID` = `o`.`OrderID`) AND (`o1`.`ProductID` = `o`.`ProductID`)) """); - } } public override async Task Delete_Where_Take(bool async) { - if (!AppConfig.ServerVersion.Supports.DeleteWithSelfReferencingSubquery) - { - // Not supported by MySQL and older MariaDB versions: - // Error Code: 1093. You can't specify target table 'o' for update in FROM clause - await Assert.ThrowsAsync( - () => base.Delete_Where_Take(async)); + // This query uses a derived table pattern which works on both MySQL and MariaDB. + // The derived table (AS `o1`) materializes the result, avoiding the MySQL error 1093 + // "You can't specify target table for update in FROM clause" + await base.Delete_Where_Take(async); - AssertSql( -""" -@p='100' - -DELETE `o` -FROM `Order Details` AS `o` -WHERE EXISTS ( - SELECT 1 - FROM ( - SELECT `o0`.`OrderID`, `o0`.`ProductID` - FROM `Order Details` AS `o0` - WHERE `o0`.`OrderID` < 10300 - LIMIT @p - ) AS `o1` - WHERE (`o1`.`OrderID` = `o`.`OrderID`) AND (`o1`.`ProductID` = `o`.`ProductID`)) -"""); - } - else - { - await base.Delete_Where_Take(async); - - AssertSql( + AssertSql( """ @p='100' @@ -357,40 +235,16 @@ LIMIT @p ) AS `o1` WHERE (`o1`.`OrderID` = `o`.`OrderID`) AND (`o1`.`ProductID` = `o`.`ProductID`)) """); - } } public override async Task Delete_Where_Skip_Take(bool async) { - if (!AppConfig.ServerVersion.Supports.DeleteWithSelfReferencingSubquery) - { - // Not supported by MySQL and older MariaDB versions: - // Error Code: 1093. You can't specify target table 'o' for update in FROM clause - await Assert.ThrowsAsync( - () => base.Delete_Where_Skip_Take(async)); - - AssertSql( -""" -@p='100' - -DELETE `o` -FROM `Order Details` AS `o` -WHERE EXISTS ( - SELECT 1 - FROM ( - SELECT `o0`.`OrderID`, `o0`.`ProductID` - FROM `Order Details` AS `o0` - WHERE `o0`.`OrderID` < 10300 - LIMIT @p OFFSET @p - ) AS `o1` - WHERE (`o1`.`OrderID` = `o`.`OrderID`) AND (`o1`.`ProductID` = `o`.`ProductID`)) -"""); - } - else - { - await base.Delete_Where_Skip_Take(async); + // This query uses a derived table pattern which works on both MySQL and MariaDB. + // The derived table (AS `o1`) materializes the result, avoiding the MySQL error 1093 + // "You can't specify target table for update in FROM clause" + await base.Delete_Where_Skip_Take(async); - AssertSql( + AssertSql( """ @p='100' @@ -406,7 +260,6 @@ LIMIT @p OFFSET @p ) AS `o1` WHERE (`o1`.`OrderID` = `o`.`OrderID`) AND (`o1`.`ProductID` = `o`.`ProductID`)) """); - } } public override async Task Delete_Where_predicate_with_GroupBy_aggregate(bool async) @@ -468,41 +321,12 @@ public override async Task Delete_GroupBy_Where_Select_2(bool async) public override async Task Delete_Where_Skip_Take_Skip_Take_causing_subquery(bool async) { - if (!AppConfig.ServerVersion.Supports.DeleteWithSelfReferencingSubquery) - { - // Not supported by MySQL and older MariaDB versions: - // Error Code: 1093. You can't specify target table 'o' for update in FROM clause - await Assert.ThrowsAsync( - () => base.Delete_Where_Skip_Take_Skip_Take_causing_subquery(async)); + // This query uses a derived table pattern which works on both MySQL and MariaDB. + // The derived table (AS `o2`) materializes the result, avoiding the MySQL error 1093 + // "You can't specify target table for update in FROM clause" + await base.Delete_Where_Skip_Take_Skip_Take_causing_subquery(async); - AssertSql( -""" -@p='100' -@p2='5' -@p1='20' - -DELETE `o` -FROM `Order Details` AS `o` -WHERE EXISTS ( - SELECT 1 - FROM ( - SELECT `o0`.`OrderID`, `o0`.`ProductID` - FROM ( - SELECT `o1`.`OrderID`, `o1`.`ProductID` - FROM `Order Details` AS `o1` - WHERE `o1`.`OrderID` < 10300 - LIMIT @p OFFSET @p - ) AS `o0` - LIMIT @p2 OFFSET @p1 - ) AS `o2` - WHERE (`o2`.`OrderID` = `o`.`OrderID`) AND (`o2`.`ProductID` = `o`.`ProductID`)) -"""); - } - else - { - await base.Delete_Where_Skip_Take_Skip_Take_causing_subquery(async); - - AssertSql( + AssertSql( """ @p='100' @p2='5' @@ -524,7 +348,6 @@ LIMIT @p2 OFFSET @p1 ) AS `o2` WHERE (`o2`.`OrderID` = `o`.`OrderID`) AND (`o2`.`ProductID` = `o`.`ProductID`)) """); - } } public override async Task Delete_Where_Distinct(bool async)