diff --git a/src/EFCore.MySql/Infrastructure/MariaDbServerVersion.cs b/src/EFCore.MySql/Infrastructure/MariaDbServerVersion.cs index 871dd1cc4..4ca435139 100644 --- a/src/EFCore.MySql/Infrastructure/MariaDbServerVersion.cs +++ b/src/EFCore.MySql/Infrastructure/MariaDbServerVersion.cs @@ -99,6 +99,7 @@ internal MariaDbServerVersionSupport([NotNull] ServerVersion serverVersion) public override bool WhereSubqueryReferencesOuterQuery => false; public override bool FieldReferenceInTableValueConstructor => false; public override bool CollationCharacterSetApplicabilityWithFullCollationNameColumn => ServerVersion.Version >= new Version(10, 10, 1); + public override bool DeleteWithSelfReferencingSubquery => ServerVersion.Version >= new Version(11, 0, 0); // MariaDB 11+ supports DELETE with self-referencing subqueries public override bool JsonTableImplementationStable => false; public override bool JsonTableImplementationWithoutMariaDbBugs => false; diff --git a/src/EFCore.MySql/Infrastructure/MySqlServerVersion.cs b/src/EFCore.MySql/Infrastructure/MySqlServerVersion.cs index 6d73ead8d..8015d35d2 100644 --- a/src/EFCore.MySql/Infrastructure/MySqlServerVersion.cs +++ b/src/EFCore.MySql/Infrastructure/MySqlServerVersion.cs @@ -101,6 +101,7 @@ internal MySqlServerVersionSupport([NotNull] ServerVersion serverVersion) public override bool WhereSubqueryReferencesOuterQuery => false; public override bool FieldReferenceInTableValueConstructor => true; public override bool CollationCharacterSetApplicabilityWithFullCollationNameColumn => false; + public override bool DeleteWithSelfReferencingSubquery => false; // MySQL does not support DELETE with self-referencing subqueries (Error 1093) public override bool JsonTableImplementationStable => false; public override bool JsonTableImplementationWithoutMySqlBugs => false; // Other non-fatal bugs regarding JSON_TABLE. diff --git a/src/EFCore.MySql/Infrastructure/ServerVersionSupport.cs b/src/EFCore.MySql/Infrastructure/ServerVersionSupport.cs index dc0b72a8c..ba3e96627 100644 --- a/src/EFCore.MySql/Infrastructure/ServerVersionSupport.cs +++ b/src/EFCore.MySql/Infrastructure/ServerVersionSupport.cs @@ -97,6 +97,7 @@ public virtual bool PropertyOrVersion(string propertyNameOrServerVersion) public virtual bool WhereSubqueryReferencesOuterQuery => false; public virtual bool FieldReferenceInTableValueConstructor => false; public virtual bool CollationCharacterSetApplicabilityWithFullCollationNameColumn => false; + public virtual bool DeleteWithSelfReferencingSubquery => false; public virtual bool JsonTableImplementationStable => JsonTable; public virtual bool JsonTableImplementationWithoutMySqlBugs => JsonTable; diff --git a/test/EFCore.MySql.FunctionalTests/BulkUpdates/NorthwindBulkUpdatesMySqlTest.cs b/test/EFCore.MySql.FunctionalTests/BulkUpdates/NorthwindBulkUpdatesMySqlTest.cs index 69e040360..a19a811dd 100644 --- a/test/EFCore.MySql.FunctionalTests/BulkUpdates/NorthwindBulkUpdatesMySqlTest.cs +++ b/test/EFCore.MySql.FunctionalTests/BulkUpdates/NorthwindBulkUpdatesMySqlTest.cs @@ -554,9 +554,39 @@ LIMIT @p0 OFFSET @p public override async Task Delete_with_LeftJoin(bool async) { - await base.Delete_with_LeftJoin(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_with_LeftJoin(async)); - AssertSql( + AssertSql( +""" +@p0='100' +@p='0' + +DELETE `o` +FROM `Order Details` AS `o` +WHERE EXISTS ( + SELECT 1 + FROM `Order Details` AS `o0` + LEFT JOIN ( + SELECT `o2`.`OrderID` + FROM `Orders` AS `o2` + WHERE `o2`.`OrderID` < 10300 + ORDER BY `o2`.`OrderID` + LIMIT @p0 OFFSET @p + ) AS `o1` ON `o0`.`OrderID` = `o1`.`OrderID` + WHERE (`o0`.`OrderID` < 10276) AND ((`o0`.`OrderID` = `o`.`OrderID`) AND (`o0`.`ProductID` = `o`.`ProductID`))) +"""); + } + else + { + // Works as expected in MariaDB 11+. + await base.Delete_with_LeftJoin(async); + + AssertSql( """ @p0='100' @p='0' @@ -575,6 +605,7 @@ LIMIT @p0 OFFSET @p ) AS `o1` ON `o0`.`OrderID` = `o1`.`OrderID` WHERE (`o0`.`OrderID` < 10276) AND ((`o0`.`OrderID` = `o`.`OrderID`) AND (`o0`.`ProductID` = `o`.`ProductID`))) """); + } } public override async Task Delete_with_cross_join(bool async) @@ -989,7 +1020,7 @@ await Assert.ThrowsAsync( } else { - // Works as expected in MariaDB. + // Works as expected in MariaDB (all versions). await base.Update_Where_GroupBy_First_set_constant_3(async); AssertExecuteUpdateSql( @@ -1555,7 +1586,18 @@ public override async Task Update_with_two_inner_joins(bool async) public override async Task Delete_with_LeftJoin_via_flattened_GroupJoin(bool async) { - await base.Delete_with_LeftJoin_via_flattened_GroupJoin(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_with_LeftJoin_via_flattened_GroupJoin(async)); + } + else + { + // Works as expected in MariaDB 11+. + await base.Delete_with_LeftJoin_via_flattened_GroupJoin(async); + } // Note: SQL validation skipped - actual SQL needs to be captured from test run } diff --git a/test/EFCore.MySql.FunctionalTests/BulkUpdates/TPHFiltersInheritanceBulkUpdatesMySqlTest.cs b/test/EFCore.MySql.FunctionalTests/BulkUpdates/TPHFiltersInheritanceBulkUpdatesMySqlTest.cs index 14597daf7..1e01d160e 100644 --- a/test/EFCore.MySql.FunctionalTests/BulkUpdates/TPHFiltersInheritanceBulkUpdatesMySqlTest.cs +++ b/test/EFCore.MySql.FunctionalTests/BulkUpdates/TPHFiltersInheritanceBulkUpdatesMySqlTest.cs @@ -94,8 +94,7 @@ public override async Task Delete_GroupBy_Where_Select_First_2(bool async) public override async Task Delete_GroupBy_Where_Select_First_3(bool async) { - if (AppConfig.ServerVersion.Type == ServerType.MariaDb && - AppConfig.ServerVersion.Version >= new Version(11, 1)) + if (AppConfig.ServerVersion.Supports.DeleteWithSelfReferencingSubquery) { await base.Delete_GroupBy_Where_Select_First_3(async); @@ -118,7 +117,7 @@ HAVING COUNT(*) < 3 } else { - // Not supported by MySQL: + // Not supported by MySQL and older MariaDB versions: // Error Code: 1093. You can't specify target table 'c' for update in FROM clause await Assert.ThrowsAsync( () => base.Delete_GroupBy_Where_Select_First_3(async));