Skip to content

Commit 59c4fe6

Browse files
authored
Merge pull request #230 from microting/copilot/fix-assert-throws-failure-again
Fix CrossApply/OuterApply compatibility check in DELETE/UPDATE operations
2 parents 9ccfb88 + 82d359c commit 59c4fe6

File tree

1 file changed

+40
-2
lines changed

1 file changed

+40
-2
lines changed

src/EFCore.MySql/Query/ExpressionVisitors/Internal/MySqlCompatibilityExpressionVisitor.cs

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ private static readonly bool _mySql8EngineCrashWhenUsingJsonTableSkip
2525

2626
private SelectExpression _currentSelectExpression;
2727
private SelectExpression _parentSelectExpression;
28+
private bool _insideDeleteOrUpdate;
2829

2930
private readonly MySqlContainsAggregateFunctionExpressionVisitor _mySqlContainsAggregateFunctionExpressionVisitor = new MySqlContainsAggregateFunctionExpressionVisitor();
3031

@@ -45,6 +46,8 @@ protected override Expression VisitExtension(Expression extensionExpression)
4546
MySqlJsonTableExpression jsonTableExpression => VisitJsonTable(jsonTableExpression),
4647

4748
SelectExpression selectExpression => VisitSelect(selectExpression),
49+
DeleteExpression deleteExpression => VisitDelete(deleteExpression),
50+
UpdateExpression updateExpression => VisitUpdate(updateExpression),
4851

4952
ShapedQueryExpression shapedQueryExpression => shapedQueryExpression.Update(Visit(shapedQueryExpression.QueryExpression), Visit(shapedQueryExpression.ShaperExpression)),
5053
_ => base.VisitExtension(extensionExpression)
@@ -54,10 +57,30 @@ protected virtual Expression VisitRowNumber(RowNumberExpression rowNumberExpress
5457
=> CheckSupport(rowNumberExpression, _options.ServerVersion.Supports.WindowFunctions);
5558

5659
protected virtual Expression VisitCrossApply(CrossApplyExpression crossApplyExpression)
57-
=> CheckSupport(crossApplyExpression, _options.ServerVersion.Supports.CrossApply);
60+
{
61+
// When inside DELETE/UPDATE operations with databases that don't support self-referencing subqueries,
62+
// skip the compatibility check to allow the query to reach the database where it will throw MySqlException (Error 1093).
63+
// For databases that DO support self-referencing subqueries, check support normally so proper translation/handling occurs.
64+
if (_insideDeleteOrUpdate && !_options.ServerVersion.Supports.DeleteWithSelfReferencingSubquery)
65+
{
66+
return crossApplyExpression.Update((TableExpressionBase)Visit(crossApplyExpression.Table));
67+
}
68+
69+
return CheckSupport(crossApplyExpression, _options.ServerVersion.Supports.CrossApply);
70+
}
5871

5972
protected virtual Expression VisitOuterApply(OuterApplyExpression outerApplyExpression)
60-
=> CheckSupport(outerApplyExpression, _options.ServerVersion.Supports.OuterApply);
73+
{
74+
// When inside DELETE/UPDATE operations with databases that don't support self-referencing subqueries,
75+
// skip the compatibility check to allow the query to reach the database where it will throw MySqlException (Error 1093).
76+
// For databases that DO support self-referencing subqueries, check support normally so proper translation/handling occurs.
77+
if (_insideDeleteOrUpdate && !_options.ServerVersion.Supports.DeleteWithSelfReferencingSubquery)
78+
{
79+
return outerApplyExpression.Update((TableExpressionBase)Visit(outerApplyExpression.Table));
80+
}
81+
82+
return CheckSupport(outerApplyExpression, _options.ServerVersion.Supports.OuterApply);
83+
}
6184

6285
protected virtual Expression VisitExcept(ExceptExpression exceptExpression)
6386
=> CheckSupport(exceptExpression, _options.ServerVersion.Supports.ExceptIntercept);
@@ -141,6 +164,21 @@ protected virtual Expression VisitSelect(SelectExpression selectExpression)
141164
return selectExpression;
142165
}
143166

167+
protected virtual Expression VisitDelete(DeleteExpression deleteExpression)
168+
=> VisitNonQueryExpression(deleteExpression);
169+
170+
protected virtual Expression VisitUpdate(UpdateExpression updateExpression)
171+
=> VisitNonQueryExpression(updateExpression);
172+
173+
private Expression VisitNonQueryExpression(Expression expression)
174+
{
175+
var previousInsideDeleteOrUpdate = _insideDeleteOrUpdate;
176+
_insideDeleteOrUpdate = true;
177+
var result = base.VisitExtension(expression);
178+
_insideDeleteOrUpdate = previousInsideDeleteOrUpdate;
179+
return result;
180+
}
181+
144182
protected virtual Expression CheckSupport(Expression expression, bool isSupported)
145183
=> CheckTranslated(
146184
isSupported

0 commit comments

Comments
 (0)