From 33794c8ac7949602706f795a571fbfbff87f5bb3 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 15 Nov 2025 12:21:21 +0000
Subject: [PATCH 1/5] Initial plan
From 2d2c8f494fa8eb22cf49663be43f2206571914d7 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 15 Nov 2025 12:32:25 +0000
Subject: [PATCH 2/5] Implement missing override methods for RETURNING
operations
Co-authored-by: renemadsen <76994+renemadsen@users.noreply.github.com>
---
.../Internal/MySqlUpdateSqlGenerator.cs | 126 ++++++++++++++++++
1 file changed, 126 insertions(+)
diff --git a/src/EFCore.MySql/Update/Internal/MySqlUpdateSqlGenerator.cs b/src/EFCore.MySql/Update/Internal/MySqlUpdateSqlGenerator.cs
index dfde995e5..6a36d4309 100644
--- a/src/EFCore.MySql/Update/Internal/MySqlUpdateSqlGenerator.cs
+++ b/src/EFCore.MySql/Update/Internal/MySqlUpdateSqlGenerator.cs
@@ -38,6 +38,45 @@ public override ResultSetMapping AppendInsertOperation(
? AppendInsertReturningOperation(commandStringBuilder, command, commandPosition, out requiresTransaction)
: base.AppendInsertOperation(commandStringBuilder, command, commandPosition, out requiresTransaction);
+ ///
+ /// Appends SQL for inserting a row to the commands being built, via an INSERT containing a RETURNING clause
+ /// to retrieve any database-generated values.
+ ///
+ /// The builder to which the SQL should be appended.
+ /// The command that represents the insert operation.
+ /// The ordinal of this command in the batch.
+ /// Returns whether the SQL appended must be executed in a transaction to work correctly.
+ /// The for the command.
+ protected virtual ResultSetMapping AppendInsertReturningOperation(
+ StringBuilder commandStringBuilder,
+ IReadOnlyModificationCommand command,
+ int commandPosition,
+ out bool requiresTransaction)
+ {
+ var name = command.TableName;
+ var schema = command.Schema;
+ var operations = command.ColumnModifications;
+
+ var writeOperations = operations.Where(o => o.IsWrite).ToList();
+ var readOperations = operations.Where(o => o.IsRead).ToList();
+
+ AppendInsertCommandHeader(commandStringBuilder, name, schema, writeOperations);
+ AppendValuesHeader(commandStringBuilder, writeOperations);
+ AppendValues(commandStringBuilder, name, schema, writeOperations);
+
+ // MySQL supports RETURNING clause starting from version 8.0.21
+ if (_options.ServerVersion.Supports.Returning && readOperations.Count > 0)
+ {
+ AppendReturningClause(commandStringBuilder, readOperations);
+ }
+
+ commandStringBuilder.AppendLine(SqlGenerationHelper.StatementTerminator);
+
+ requiresTransaction = false;
+
+ return readOperations.Count > 0 ? ResultSetMapping.LastInResultSet : ResultSetMapping.NoResults;
+ }
+
public virtual ResultSetMapping AppendBulkInsertOperation(
StringBuilder commandStringBuilder,
IReadOnlyList modificationCommands,
@@ -137,6 +176,58 @@ protected override void AppendValues(
}
}
+ public override ResultSetMapping AppendUpdateOperation(
+ StringBuilder commandStringBuilder,
+ IReadOnlyModificationCommand command,
+ int commandPosition,
+ out bool requiresTransaction)
+ => _options.ServerVersion.Supports.Returning
+ ? AppendUpdateReturningOperation(commandStringBuilder, command, commandPosition, out requiresTransaction)
+ : base.AppendUpdateOperation(commandStringBuilder, command, commandPosition, out requiresTransaction);
+
+ ///
+ /// Appends SQL for updating a row to the commands being built, via an UPDATE containing a RETURNING clause
+ /// to retrieve any database-generated values or for concurrency checking.
+ ///
+ /// The builder to which the SQL should be appended.
+ /// The command that represents the update operation.
+ /// The ordinal of this command in the batch.
+ /// Returns whether the SQL appended must be executed in a transaction to work correctly.
+ /// The for the command.
+ protected virtual ResultSetMapping AppendUpdateReturningOperation(
+ StringBuilder commandStringBuilder,
+ IReadOnlyModificationCommand command,
+ int commandPosition,
+ out bool requiresTransaction)
+ {
+ var name = command.TableName;
+ var schema = command.Schema;
+ var operations = command.ColumnModifications;
+
+ var writeOperations = operations.Where(o => o.IsWrite).ToList();
+ var conditionOperations = operations.Where(o => o.IsCondition).ToList();
+ var readOperations = operations.Where(o => o.IsRead).ToList();
+
+ requiresTransaction = false;
+
+ var anyReadOperations = readOperations.Count > 0;
+
+ AppendUpdateCommandHeader(commandStringBuilder, name, schema, writeOperations);
+ AppendWhereClause(commandStringBuilder, conditionOperations);
+
+ // MySQL supports RETURNING clause starting from version 8.0.21
+ if (_options.ServerVersion.Supports.Returning)
+ {
+ AppendReturningClause(commandStringBuilder, readOperations, anyReadOperations ? null : "1");
+ }
+
+ commandStringBuilder.AppendLine(SqlGenerationHelper.StatementTerminator);
+
+ return anyReadOperations
+ ? ResultSetMapping.LastInResultSet
+ : ResultSetMapping.LastInResultSet | ResultSetMapping.ResultSetWithRowsAffectedOnly;
+ }
+
public override ResultSetMapping AppendDeleteOperation(StringBuilder commandStringBuilder,
IReadOnlyModificationCommand command,
int commandPosition,
@@ -145,6 +236,41 @@ public override ResultSetMapping AppendDeleteOperation(StringBuilder commandStri
? AppendDeleteReturningOperation(commandStringBuilder, command, commandPosition, out requiresTransaction)
: base.AppendDeleteOperation(commandStringBuilder, command, commandPosition, out requiresTransaction);
+ ///
+ /// Appends SQL for deleting a row to the commands being built, via a DELETE containing a RETURNING clause
+ /// for concurrency checking.
+ ///
+ /// The builder to which the SQL should be appended.
+ /// The command that represents the delete operation.
+ /// The ordinal of this command in the batch.
+ /// Returns whether the SQL appended must be executed in a transaction to work correctly.
+ /// The for the command.
+ protected virtual ResultSetMapping AppendDeleteReturningOperation(
+ StringBuilder commandStringBuilder,
+ IReadOnlyModificationCommand command,
+ int commandPosition,
+ out bool requiresTransaction)
+ {
+ var name = command.TableName;
+ var schema = command.Schema;
+ var conditionOperations = command.ColumnModifications.Where(o => o.IsCondition).ToList();
+
+ requiresTransaction = false;
+
+ AppendDeleteCommandHeader(commandStringBuilder, name, schema);
+ AppendWhereClause(commandStringBuilder, conditionOperations);
+
+ // MySQL supports RETURNING clause starting from version 8.0.21
+ if (_options.ServerVersion.Supports.Returning)
+ {
+ AppendReturningClause(commandStringBuilder, [], "1");
+ }
+
+ commandStringBuilder.AppendLine(SqlGenerationHelper.StatementTerminator);
+
+ return ResultSetMapping.LastInResultSet | ResultSetMapping.ResultSetWithRowsAffectedOnly;
+ }
+
protected override ResultSetMapping AppendSelectAffectedCountCommand(StringBuilder commandStringBuilder, string name, string schema, int commandPosition)
{
commandStringBuilder
From eada307423c7f81dc2ed89df421c112424abfc11 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 15 Nov 2025 13:06:22 +0000
Subject: [PATCH 3/5] Fix: Change RETURNING methods from virtual to override
Co-authored-by: renemadsen <76994+renemadsen@users.noreply.github.com>
---
src/EFCore.MySql/Update/Internal/MySqlUpdateSqlGenerator.cs | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/EFCore.MySql/Update/Internal/MySqlUpdateSqlGenerator.cs b/src/EFCore.MySql/Update/Internal/MySqlUpdateSqlGenerator.cs
index 6a36d4309..bcecff38f 100644
--- a/src/EFCore.MySql/Update/Internal/MySqlUpdateSqlGenerator.cs
+++ b/src/EFCore.MySql/Update/Internal/MySqlUpdateSqlGenerator.cs
@@ -47,7 +47,7 @@ public override ResultSetMapping AppendInsertOperation(
/// The ordinal of this command in the batch.
/// Returns whether the SQL appended must be executed in a transaction to work correctly.
/// The for the command.
- protected virtual ResultSetMapping AppendInsertReturningOperation(
+ protected override ResultSetMapping AppendInsertReturningOperation(
StringBuilder commandStringBuilder,
IReadOnlyModificationCommand command,
int commandPosition,
@@ -194,7 +194,7 @@ public override ResultSetMapping AppendUpdateOperation(
/// The ordinal of this command in the batch.
/// Returns whether the SQL appended must be executed in a transaction to work correctly.
/// The for the command.
- protected virtual ResultSetMapping AppendUpdateReturningOperation(
+ protected override ResultSetMapping AppendUpdateReturningOperation(
StringBuilder commandStringBuilder,
IReadOnlyModificationCommand command,
int commandPosition,
@@ -245,7 +245,7 @@ public override ResultSetMapping AppendDeleteOperation(StringBuilder commandStri
/// The ordinal of this command in the batch.
/// Returns whether the SQL appended must be executed in a transaction to work correctly.
/// The for the command.
- protected virtual ResultSetMapping AppendDeleteReturningOperation(
+ protected override ResultSetMapping AppendDeleteReturningOperation(
StringBuilder commandStringBuilder,
IReadOnlyModificationCommand command,
int commandPosition,
From 326f46a528e7814fb1871edfe03e490f9436c767 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 15 Nov 2025 14:22:52 +0000
Subject: [PATCH 4/5] Fix: Change RETURNING methods to public override
Co-authored-by: renemadsen <76994+renemadsen@users.noreply.github.com>
---
src/EFCore.MySql/Update/Internal/MySqlUpdateSqlGenerator.cs | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/EFCore.MySql/Update/Internal/MySqlUpdateSqlGenerator.cs b/src/EFCore.MySql/Update/Internal/MySqlUpdateSqlGenerator.cs
index bcecff38f..56c7a1441 100644
--- a/src/EFCore.MySql/Update/Internal/MySqlUpdateSqlGenerator.cs
+++ b/src/EFCore.MySql/Update/Internal/MySqlUpdateSqlGenerator.cs
@@ -47,7 +47,7 @@ public override ResultSetMapping AppendInsertOperation(
/// The ordinal of this command in the batch.
/// Returns whether the SQL appended must be executed in a transaction to work correctly.
/// The for the command.
- protected override ResultSetMapping AppendInsertReturningOperation(
+ public override ResultSetMapping AppendInsertReturningOperation(
StringBuilder commandStringBuilder,
IReadOnlyModificationCommand command,
int commandPosition,
@@ -194,7 +194,7 @@ public override ResultSetMapping AppendUpdateOperation(
/// The ordinal of this command in the batch.
/// Returns whether the SQL appended must be executed in a transaction to work correctly.
/// The for the command.
- protected override ResultSetMapping AppendUpdateReturningOperation(
+ public override ResultSetMapping AppendUpdateReturningOperation(
StringBuilder commandStringBuilder,
IReadOnlyModificationCommand command,
int commandPosition,
@@ -245,7 +245,7 @@ public override ResultSetMapping AppendDeleteOperation(StringBuilder commandStri
/// The ordinal of this command in the batch.
/// Returns whether the SQL appended must be executed in a transaction to work correctly.
/// The for the command.
- protected override ResultSetMapping AppendDeleteReturningOperation(
+ public override ResultSetMapping AppendDeleteReturningOperation(
StringBuilder commandStringBuilder,
IReadOnlyModificationCommand command,
int commandPosition,
From c94cf7749890bc8e9bd143b4437bc707de97e2b0 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 15 Nov 2025 14:36:23 +0000
Subject: [PATCH 5/5] Fix: Use correct access modifiers for RETURNING methods
Co-authored-by: renemadsen <76994+renemadsen@users.noreply.github.com>
---
src/EFCore.MySql/Update/Internal/MySqlUpdateSqlGenerator.cs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/EFCore.MySql/Update/Internal/MySqlUpdateSqlGenerator.cs b/src/EFCore.MySql/Update/Internal/MySqlUpdateSqlGenerator.cs
index 56c7a1441..7f6f4cf3b 100644
--- a/src/EFCore.MySql/Update/Internal/MySqlUpdateSqlGenerator.cs
+++ b/src/EFCore.MySql/Update/Internal/MySqlUpdateSqlGenerator.cs
@@ -194,7 +194,7 @@ public override ResultSetMapping AppendUpdateOperation(
/// The ordinal of this command in the batch.
/// Returns whether the SQL appended must be executed in a transaction to work correctly.
/// The for the command.
- public override ResultSetMapping AppendUpdateReturningOperation(
+ protected override ResultSetMapping AppendUpdateReturningOperation(
StringBuilder commandStringBuilder,
IReadOnlyModificationCommand command,
int commandPosition,
@@ -245,7 +245,7 @@ public override ResultSetMapping AppendDeleteOperation(StringBuilder commandStri
/// The ordinal of this command in the batch.
/// Returns whether the SQL appended must be executed in a transaction to work correctly.
/// The for the command.
- public override ResultSetMapping AppendDeleteReturningOperation(
+ protected override ResultSetMapping AppendDeleteReturningOperation(
StringBuilder commandStringBuilder,
IReadOnlyModificationCommand command,
int commandPosition,