@@ -38,6 +38,45 @@ public override ResultSetMapping AppendInsertOperation(
3838 ? AppendInsertReturningOperation ( commandStringBuilder , command , commandPosition , out requiresTransaction )
3939 : base . AppendInsertOperation ( commandStringBuilder , command , commandPosition , out requiresTransaction ) ;
4040
41+ /// <summary>
42+ /// Appends SQL for inserting a row to the commands being built, via an INSERT containing a RETURNING clause
43+ /// to retrieve any database-generated values.
44+ /// </summary>
45+ /// <param name="commandStringBuilder">The builder to which the SQL should be appended.</param>
46+ /// <param name="command">The command that represents the insert operation.</param>
47+ /// <param name="commandPosition">The ordinal of this command in the batch.</param>
48+ /// <param name="requiresTransaction">Returns whether the SQL appended must be executed in a transaction to work correctly.</param>
49+ /// <returns>The <see cref="ResultSetMapping" /> for the command.</returns>
50+ public override ResultSetMapping AppendInsertReturningOperation (
51+ StringBuilder commandStringBuilder ,
52+ IReadOnlyModificationCommand command ,
53+ int commandPosition ,
54+ out bool requiresTransaction )
55+ {
56+ var name = command . TableName ;
57+ var schema = command . Schema ;
58+ var operations = command . ColumnModifications ;
59+
60+ var writeOperations = operations . Where ( o => o . IsWrite ) . ToList ( ) ;
61+ var readOperations = operations . Where ( o => o . IsRead ) . ToList ( ) ;
62+
63+ AppendInsertCommandHeader ( commandStringBuilder , name , schema , writeOperations ) ;
64+ AppendValuesHeader ( commandStringBuilder , writeOperations ) ;
65+ AppendValues ( commandStringBuilder , name , schema , writeOperations ) ;
66+
67+ // MySQL supports RETURNING clause starting from version 8.0.21
68+ if ( _options . ServerVersion . Supports . Returning && readOperations . Count > 0 )
69+ {
70+ AppendReturningClause ( commandStringBuilder , readOperations ) ;
71+ }
72+
73+ commandStringBuilder . AppendLine ( SqlGenerationHelper . StatementTerminator ) ;
74+
75+ requiresTransaction = false ;
76+
77+ return readOperations . Count > 0 ? ResultSetMapping . LastInResultSet : ResultSetMapping . NoResults ;
78+ }
79+
4180 public virtual ResultSetMapping AppendBulkInsertOperation (
4281 StringBuilder commandStringBuilder ,
4382 IReadOnlyList < IReadOnlyModificationCommand > modificationCommands ,
@@ -137,6 +176,58 @@ protected override void AppendValues(
137176 }
138177 }
139178
179+ public override ResultSetMapping AppendUpdateOperation (
180+ StringBuilder commandStringBuilder ,
181+ IReadOnlyModificationCommand command ,
182+ int commandPosition ,
183+ out bool requiresTransaction )
184+ => _options . ServerVersion . Supports . Returning
185+ ? AppendUpdateReturningOperation ( commandStringBuilder , command , commandPosition , out requiresTransaction )
186+ : base . AppendUpdateOperation ( commandStringBuilder , command , commandPosition , out requiresTransaction ) ;
187+
188+ /// <summary>
189+ /// Appends SQL for updating a row to the commands being built, via an UPDATE containing a RETURNING clause
190+ /// to retrieve any database-generated values or for concurrency checking.
191+ /// </summary>
192+ /// <param name="commandStringBuilder">The builder to which the SQL should be appended.</param>
193+ /// <param name="command">The command that represents the update operation.</param>
194+ /// <param name="commandPosition">The ordinal of this command in the batch.</param>
195+ /// <param name="requiresTransaction">Returns whether the SQL appended must be executed in a transaction to work correctly.</param>
196+ /// <returns>The <see cref="ResultSetMapping" /> for the command.</returns>
197+ protected override ResultSetMapping AppendUpdateReturningOperation (
198+ StringBuilder commandStringBuilder ,
199+ IReadOnlyModificationCommand command ,
200+ int commandPosition ,
201+ out bool requiresTransaction )
202+ {
203+ var name = command . TableName ;
204+ var schema = command . Schema ;
205+ var operations = command . ColumnModifications ;
206+
207+ var writeOperations = operations . Where ( o => o . IsWrite ) . ToList ( ) ;
208+ var conditionOperations = operations . Where ( o => o . IsCondition ) . ToList ( ) ;
209+ var readOperations = operations . Where ( o => o . IsRead ) . ToList ( ) ;
210+
211+ requiresTransaction = false ;
212+
213+ var anyReadOperations = readOperations . Count > 0 ;
214+
215+ AppendUpdateCommandHeader ( commandStringBuilder , name , schema , writeOperations ) ;
216+ AppendWhereClause ( commandStringBuilder , conditionOperations ) ;
217+
218+ // MySQL supports RETURNING clause starting from version 8.0.21
219+ if ( _options . ServerVersion . Supports . Returning )
220+ {
221+ AppendReturningClause ( commandStringBuilder , readOperations , anyReadOperations ? null : "1" ) ;
222+ }
223+
224+ commandStringBuilder . AppendLine ( SqlGenerationHelper . StatementTerminator ) ;
225+
226+ return anyReadOperations
227+ ? ResultSetMapping . LastInResultSet
228+ : ResultSetMapping . LastInResultSet | ResultSetMapping . ResultSetWithRowsAffectedOnly ;
229+ }
230+
140231 public override ResultSetMapping AppendDeleteOperation ( StringBuilder commandStringBuilder ,
141232 IReadOnlyModificationCommand command ,
142233 int commandPosition ,
@@ -145,6 +236,41 @@ public override ResultSetMapping AppendDeleteOperation(StringBuilder commandStri
145236 ? AppendDeleteReturningOperation ( commandStringBuilder , command , commandPosition , out requiresTransaction )
146237 : base . AppendDeleteOperation ( commandStringBuilder , command , commandPosition , out requiresTransaction ) ;
147238
239+ /// <summary>
240+ /// Appends SQL for deleting a row to the commands being built, via a DELETE containing a RETURNING clause
241+ /// for concurrency checking.
242+ /// </summary>
243+ /// <param name="commandStringBuilder">The builder to which the SQL should be appended.</param>
244+ /// <param name="command">The command that represents the delete operation.</param>
245+ /// <param name="commandPosition">The ordinal of this command in the batch.</param>
246+ /// <param name="requiresTransaction">Returns whether the SQL appended must be executed in a transaction to work correctly.</param>
247+ /// <returns>The <see cref="ResultSetMapping" /> for the command.</returns>
248+ protected override ResultSetMapping AppendDeleteReturningOperation (
249+ StringBuilder commandStringBuilder ,
250+ IReadOnlyModificationCommand command ,
251+ int commandPosition ,
252+ out bool requiresTransaction )
253+ {
254+ var name = command . TableName ;
255+ var schema = command . Schema ;
256+ var conditionOperations = command . ColumnModifications . Where ( o => o . IsCondition ) . ToList ( ) ;
257+
258+ requiresTransaction = false ;
259+
260+ AppendDeleteCommandHeader ( commandStringBuilder , name , schema ) ;
261+ AppendWhereClause ( commandStringBuilder , conditionOperations ) ;
262+
263+ // MySQL supports RETURNING clause starting from version 8.0.21
264+ if ( _options . ServerVersion . Supports . Returning )
265+ {
266+ AppendReturningClause ( commandStringBuilder , [ ] , "1" ) ;
267+ }
268+
269+ commandStringBuilder . AppendLine ( SqlGenerationHelper . StatementTerminator ) ;
270+
271+ return ResultSetMapping . LastInResultSet | ResultSetMapping . ResultSetWithRowsAffectedOnly ;
272+ }
273+
148274 protected override ResultSetMapping AppendSelectAffectedCountCommand ( StringBuilder commandStringBuilder , string name , string schema , int commandPosition )
149275 {
150276 commandStringBuilder
0 commit comments