diff --git a/src/EFCore.Sqlite.Core/Query/Internal/SqliteQuerySqlGenerator.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteQuerySqlGenerator.cs index 26c92c1f900..1f2c182b1ad 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/SqliteQuerySqlGenerator.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteQuerySqlGenerator.cs @@ -14,6 +14,195 @@ namespace Microsoft.EntityFrameworkCore.Sqlite.Query.Internal; /// public class SqliteQuerySqlGenerator(QuerySqlGeneratorDependencies dependencies) : QuerySqlGenerator(dependencies) { + private string? _updateTargetAlias; + private string? _updateTargetTableName; + private string? _updateTargetSchema; + + /// + /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to + /// the same compatibility standards as public APIs. It may be changed or removed without notice in + /// any release. You should only use it directly in your code with extreme caution and knowing that + /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// + protected override Expression VisitUpdate(UpdateExpression updateExpression) + { + var selectExpression = updateExpression.SelectExpression; + + if (selectExpression.Tables.Count > 1 + && selectExpression is + { + Offset: null, + Limit: null, + Having: null, + Orderings: [], + GroupBy: [], + Projection: [], + } + && (!ReferenceEquals(selectExpression.Tables[0], updateExpression.Table) + || selectExpression.Tables[1] is InnerJoinExpression + || selectExpression.Tables[1] is CrossJoinExpression)) + { + // SQLite doesn't support referencing the UPDATE target table (by alias or name) in JOIN ON clauses + // within the FROM clause. To work around this, we: + // 1. Don't alias the UPDATE target table + // 2. Replace column references to the target alias with the table name (via VisitColumn/VisitTable overrides) + // 3. Lift predicates from JOINs that reference the target table into the WHERE clause, + // emitting those tables as comma-separated instead of JOINed + _updateTargetAlias = updateExpression.Table.Alias; + _updateTargetTableName = updateExpression.Table.Name; + _updateTargetSchema = updateExpression.Table.Schema; + + try + { + Sql.Append("UPDATE "); + Visit(updateExpression.Table); + + Sql.AppendLine(); + Sql.Append("SET "); + + for (var i = 0; i < updateExpression.ColumnValueSetters.Count; i++) + { + if (i == 1) + { + Sql.IncrementIndent(); + } + + if (i > 0) + { + Sql.AppendLine(","); + } + + var (column, value) = updateExpression.ColumnValueSetters[i]; + + Sql.Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(column.Name)).Append(" = "); + Visit(value); + } + + if (updateExpression.ColumnValueSetters.Count > 1) + { + Sql.DecrementIndent(); + } + + var predicate = selectExpression.Predicate; + var firstTablePrinted = false; + Sql.AppendLine().Append("FROM "); + for (var i = 0; i < selectExpression.Tables.Count; i++) + { + var table = selectExpression.Tables[i]; + var joinExpression = table as JoinExpressionBase; + + if (updateExpression.Table.Alias == (joinExpression?.Table.Alias ?? table.Alias)) + { + LiftPredicate(table); + continue; + } + + if (firstTablePrinted) + { + // For joins whose ON predicate references the target table, lift the predicate to WHERE + // and emit just the table (comma-separated) instead of a JOIN + if (joinExpression is PredicateJoinExpressionBase predicateJoin + && ReferencesTargetTable(predicateJoin.JoinPredicate)) + { + Sql.Append(", "); + LiftPredicate(table); + Visit(joinExpression.Table); + } + else + { + Sql.AppendLine(); + Visit(table); + } + } + else + { + firstTablePrinted = true; + LiftPredicate(table); + table = joinExpression?.Table ?? table; + Visit(table); + } + } + + if (predicate != null) + { + Sql.AppendLine().Append("WHERE "); + Visit(predicate); + } + + return updateExpression; + + void LiftPredicate(TableExpressionBase joinTable) + { + if (joinTable is PredicateJoinExpressionBase predicateJoinExpression) + { + predicate = predicate == null + ? predicateJoinExpression.JoinPredicate + : new SqlBinaryExpression( + ExpressionType.AndAlso, + predicateJoinExpression.JoinPredicate, + predicate, + typeof(bool), + predicate.TypeMapping); + } + } + } + finally + { + _updateTargetAlias = null; + _updateTargetTableName = null; + _updateTargetSchema = null; + } + } + + return base.VisitUpdate(updateExpression); + } + + private bool ReferencesTargetTable(Expression expression) + => expression switch + { + ColumnExpression column => column.TableAlias == _updateTargetAlias, + SqlBinaryExpression binary => ReferencesTargetTable(binary.Left) || ReferencesTargetTable(binary.Right), + SqlUnaryExpression unary => ReferencesTargetTable(unary.Operand), + _ => false + }; + + /// + /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to + /// the same compatibility standards as public APIs. It may be changed or removed without notice in + /// any release. You should only use it directly in your code with extreme caution and knowing that + /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// + protected override Expression VisitTable(TableExpression tableExpression) + { + if (_updateTargetAlias is not null && tableExpression.Alias == _updateTargetAlias) + { + Sql.Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(tableExpression.Name, tableExpression.Schema)); + return tableExpression; + } + + return base.VisitTable(tableExpression); + } + + /// + /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to + /// the same compatibility standards as public APIs. It may be changed or removed without notice in + /// any release. You should only use it directly in your code with extreme caution and knowing that + /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// + protected override Expression VisitColumn(ColumnExpression columnExpression) + { + if (_updateTargetAlias is not null && columnExpression.TableAlias == _updateTargetAlias) + { + Sql + .Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(_updateTargetTableName!, _updateTargetSchema)) + .Append(".") + .Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(columnExpression.Name)); + return columnExpression; + } + + return base.VisitColumn(columnExpression); + } + /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to /// the same compatibility standards as public APIs. It may be changed or removed without notice in diff --git a/test/EFCore.Sqlite.FunctionalTests/BulkUpdates/Inheritance/TPTFiltersInheritanceBulkUpdatesSqliteTest.cs b/test/EFCore.Sqlite.FunctionalTests/BulkUpdates/Inheritance/TPTFiltersInheritanceBulkUpdatesSqliteTest.cs index 807c47f66ba..a8d8593db8d 100644 --- a/test/EFCore.Sqlite.FunctionalTests/BulkUpdates/Inheritance/TPTFiltersInheritanceBulkUpdatesSqliteTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/BulkUpdates/Inheritance/TPTFiltersInheritanceBulkUpdatesSqliteTest.cs @@ -1,8 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using Microsoft.Data.Sqlite; - namespace Microsoft.EntityFrameworkCore.BulkUpdates.Inheritance; #nullable disable @@ -102,20 +100,36 @@ public override async Task Update_base_type(bool async) """ @p='Animal' (Size = 6) -UPDATE "Animals" AS "a0" +UPDATE "Animals" SET "Name" = @p FROM ( SELECT "a"."Id" FROM "Animals" AS "a" WHERE "a"."CountryId" = 1 AND "a"."Name" = 'Great spotted kiwi' ) AS "s" -WHERE "a0"."Id" = "s"."Id" +WHERE "Animals"."Id" = "s"."Id" """); } - // #31402 - public override Task Update_base_type_with_OfType(bool async) - => Assert.ThrowsAsync(() => base.Update_base_property_on_derived_type(async)); + public override async Task Update_base_type_with_OfType(bool async) + { + await base.Update_base_type_with_OfType(async); + + AssertExecuteUpdateSql( + """ +@p='NewBird' (Size = 7) + +UPDATE "Animals" +SET "Name" = @p +FROM "Birds" AS "b", "Kiwi" AS "k0", ( + SELECT "a"."Id" + FROM "Animals" AS "a" + LEFT JOIN "Kiwi" AS "k" ON "a"."Id" = "k"."Id" + WHERE "a"."CountryId" = 1 AND "k"."Id" IS NOT NULL +) AS "s" +WHERE "Animals"."Id" = "s"."Id" AND "Animals"."Id" = "k0"."Id" AND "Animals"."Id" = "b"."Id" +"""); + } public override async Task Update_where_hierarchy_subquery(bool async) { @@ -124,9 +138,20 @@ public override async Task Update_where_hierarchy_subquery(bool async) AssertExecuteUpdateSql(); } - // #31402 - public override Task Update_base_property_on_derived_type(bool async) - => Assert.ThrowsAsync(() => base.Update_base_property_on_derived_type(async)); + public override async Task Update_base_property_on_derived_type(bool async) + { + await base.Update_base_property_on_derived_type(async); + + AssertExecuteUpdateSql( + """ +@p='SomeOtherKiwi' (Size = 13) + +UPDATE "Animals" +SET "Name" = @p +FROM "Birds" AS "b", "Kiwi" AS "k" +WHERE "Animals"."Id" = "k"."Id" AND "Animals"."Id" = "b"."Id" AND "Animals"."CountryId" = 1 +"""); + } public override async Task Update_derived_property_on_derived_type(bool async) { @@ -136,11 +161,11 @@ public override async Task Update_derived_property_on_derived_type(bool async) """ @p='0' -UPDATE "Kiwi" AS "k" +UPDATE "Kiwi" SET "FoundOn" = @p FROM "Animals" AS "a" INNER JOIN "Birds" AS "b" ON "a"."Id" = "b"."Id" -WHERE "a"."Id" = "k"."Id" AND "a"."CountryId" = 1 +WHERE "a"."Id" = "Kiwi"."Id" AND "a"."CountryId" = 1 """); } diff --git a/test/EFCore.Sqlite.FunctionalTests/BulkUpdates/Inheritance/TPTInheritanceBulkUpdatesSqliteTest.cs b/test/EFCore.Sqlite.FunctionalTests/BulkUpdates/Inheritance/TPTInheritanceBulkUpdatesSqliteTest.cs index c466179c165..b1000c42e6c 100644 --- a/test/EFCore.Sqlite.FunctionalTests/BulkUpdates/Inheritance/TPTInheritanceBulkUpdatesSqliteTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/BulkUpdates/Inheritance/TPTInheritanceBulkUpdatesSqliteTest.cs @@ -1,8 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using Microsoft.Data.Sqlite; - namespace Microsoft.EntityFrameworkCore.BulkUpdates.Inheritance; #nullable disable @@ -87,20 +85,36 @@ public override async Task Update_base_type(bool async) """ @p='Animal' (Size = 6) -UPDATE "Animals" AS "a0" +UPDATE "Animals" SET "Name" = @p FROM ( SELECT "a"."Id" FROM "Animals" AS "a" WHERE "a"."Name" = 'Great spotted kiwi' ) AS "s" -WHERE "a0"."Id" = "s"."Id" +WHERE "Animals"."Id" = "s"."Id" """); } - // #31402 - public override Task Update_base_type_with_OfType(bool async) - => Assert.ThrowsAsync(() => base.Update_base_property_on_derived_type(async)); + public override async Task Update_base_type_with_OfType(bool async) + { + await base.Update_base_type_with_OfType(async); + + AssertExecuteUpdateSql( + """ +@p='NewBird' (Size = 7) + +UPDATE "Animals" +SET "Name" = @p +FROM "Birds" AS "b", "Kiwi" AS "k0", ( + SELECT "a"."Id" + FROM "Animals" AS "a" + LEFT JOIN "Kiwi" AS "k" ON "a"."Id" = "k"."Id" + WHERE "k"."Id" IS NOT NULL +) AS "s" +WHERE "Animals"."Id" = "s"."Id" AND "Animals"."Id" = "k0"."Id" AND "Animals"."Id" = "b"."Id" +"""); + } public override async Task Update_where_hierarchy_subquery(bool async) { @@ -109,9 +123,20 @@ public override async Task Update_where_hierarchy_subquery(bool async) AssertExecuteUpdateSql(); } - // #31402 - public override Task Update_base_property_on_derived_type(bool async) - => Assert.ThrowsAsync(() => base.Update_base_property_on_derived_type(async)); + public override async Task Update_base_property_on_derived_type(bool async) + { + await base.Update_base_property_on_derived_type(async); + + AssertExecuteUpdateSql( + """ +@p='SomeOtherKiwi' (Size = 13) + +UPDATE "Animals" +SET "Name" = @p +FROM "Birds" AS "b", "Kiwi" AS "k" +WHERE "Animals"."Id" = "k"."Id" AND "Animals"."Id" = "b"."Id" +"""); + } public override async Task Update_derived_property_on_derived_type(bool async) { @@ -121,11 +146,11 @@ public override async Task Update_derived_property_on_derived_type(bool async) """ @p='0' -UPDATE "Kiwi" AS "k" +UPDATE "Kiwi" SET "FoundOn" = @p FROM "Animals" AS "a" INNER JOIN "Birds" AS "b" ON "a"."Id" = "b"."Id" -WHERE "a"."Id" = "k"."Id" +WHERE "a"."Id" = "Kiwi"."Id" """); } @@ -186,10 +211,10 @@ public override async Task Update_with_interface_in_property_expression(bool asy """ @p='0' -UPDATE "Coke" AS "c" +UPDATE "Coke" SET "SugarGrams" = @p FROM "Drinks" AS "d" -WHERE "d"."Id" = "c"."Id" +WHERE "d"."Id" = "Coke"."Id" """); } @@ -201,10 +226,10 @@ public override async Task Update_with_interface_in_EF_Property_in_property_expr """ @p='0' -UPDATE "Coke" AS "c" +UPDATE "Coke" SET "SugarGrams" = @p FROM "Drinks" AS "d" -WHERE "d"."Id" = "c"."Id" +WHERE "d"."Id" = "Coke"."Id" """); } diff --git a/test/EFCore.Sqlite.FunctionalTests/BulkUpdates/NonSharedModelBulkUpdatesSqliteTest.cs b/test/EFCore.Sqlite.FunctionalTests/BulkUpdates/NonSharedModelBulkUpdatesSqliteTest.cs index d3c2d8e9b60..d6c07682f5c 100644 --- a/test/EFCore.Sqlite.FunctionalTests/BulkUpdates/NonSharedModelBulkUpdatesSqliteTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/BulkUpdates/NonSharedModelBulkUpdatesSqliteTest.cs @@ -67,10 +67,10 @@ public override async Task Replace_ColumnExpression_in_column_setter(bool async) """ @p='SomeValue' (Size = 9) -UPDATE "OwnedCollection" AS "o0" +UPDATE "OwnedCollection" SET "Value" = @p FROM "Owner" AS "o" -WHERE "o"."Id" = "o0"."OwnerId" +WHERE "o"."Id" = "OwnedCollection"."OwnerId" """); } @@ -106,10 +106,10 @@ public override async Task Update_non_owned_property_on_entity_with_owned_in_joi """ @p='NewValue' (Size = 8) -UPDATE "Owner" AS "o" +UPDATE "Owner" SET "Title" = @p FROM "Owner" AS "o0" -WHERE "o"."Id" = "o0"."Id" +WHERE "Owner"."Id" = "o0"."Id" """); } @@ -142,11 +142,11 @@ public override async Task Update_non_main_table_in_entity_with_entity_splitting AssertSql( """ -UPDATE "BlogsPart1" AS "b0" -SET "Title" = CAST("b0"."Rating" AS TEXT), - "Rating" = length("b0"."Title") +UPDATE "BlogsPart1" +SET "Title" = CAST("BlogsPart1"."Rating" AS TEXT), + "Rating" = length("BlogsPart1"."Title") FROM "Blogs" AS "b" -WHERE "b"."Id" = "b0"."Id" +WHERE "b"."Id" = "BlogsPart1"."Id" """); } diff --git a/test/EFCore.Sqlite.FunctionalTests/BulkUpdates/NorthwindBulkUpdatesSqliteTest.cs b/test/EFCore.Sqlite.FunctionalTests/BulkUpdates/NorthwindBulkUpdatesSqliteTest.cs index e72e6c1d147..b739323bcd2 100644 --- a/test/EFCore.Sqlite.FunctionalTests/BulkUpdates/NorthwindBulkUpdatesSqliteTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/BulkUpdates/NorthwindBulkUpdatesSqliteTest.cs @@ -781,7 +781,7 @@ public override async Task Update_Where_Skip_set_constant(bool async) @p1='Updated' (Size = 7) @p='4' -UPDATE "Customers" AS "c0" +UPDATE "Customers" SET "ContactName" = @p1 FROM ( SELECT "c"."CustomerID" @@ -789,7 +789,7 @@ public override async Task Update_Where_Skip_set_constant(bool async) WHERE "c"."CustomerID" LIKE 'F%' LIMIT -1 OFFSET @p ) AS "c1" -WHERE "c0"."CustomerID" = "c1"."CustomerID" +WHERE "Customers"."CustomerID" = "c1"."CustomerID" """); } @@ -802,7 +802,7 @@ public override async Task Update_Where_Take_set_constant(bool async) @p1='Updated' (Size = 7) @p='4' -UPDATE "Customers" AS "c0" +UPDATE "Customers" SET "ContactName" = @p1 FROM ( SELECT "c"."CustomerID" @@ -810,7 +810,7 @@ public override async Task Update_Where_Take_set_constant(bool async) WHERE "c"."CustomerID" LIKE 'F%' LIMIT @p ) AS "c1" -WHERE "c0"."CustomerID" = "c1"."CustomerID" +WHERE "Customers"."CustomerID" = "c1"."CustomerID" """); } @@ -824,7 +824,7 @@ public override async Task Update_Where_Skip_Take_set_constant(bool async) @p1='4' @p='2' -UPDATE "Customers" AS "c0" +UPDATE "Customers" SET "ContactName" = @p2 FROM ( SELECT "c"."CustomerID" @@ -832,7 +832,7 @@ public override async Task Update_Where_Skip_Take_set_constant(bool async) WHERE "c"."CustomerID" LIKE 'F%' LIMIT @p1 OFFSET @p ) AS "c1" -WHERE "c0"."CustomerID" = "c1"."CustomerID" +WHERE "Customers"."CustomerID" = "c1"."CustomerID" """); } @@ -844,14 +844,14 @@ public override async Task Update_Where_OrderBy_set_constant(bool async) """ @p='Updated' (Size = 7) -UPDATE "Customers" AS "c0" +UPDATE "Customers" SET "ContactName" = @p FROM ( SELECT "c"."CustomerID" FROM "Customers" AS "c" WHERE "c"."CustomerID" LIKE 'F%' ) AS "c1" -WHERE "c0"."CustomerID" = "c1"."CustomerID" +WHERE "Customers"."CustomerID" = "c1"."CustomerID" """); } @@ -864,7 +864,7 @@ public override async Task Update_Where_OrderBy_Skip_set_constant(bool async) @p1='Updated' (Size = 7) @p='4' -UPDATE "Customers" AS "c0" +UPDATE "Customers" SET "ContactName" = @p1 FROM ( SELECT "c"."CustomerID" @@ -873,7 +873,7 @@ public override async Task Update_Where_OrderBy_Skip_set_constant(bool async) ORDER BY "c"."City" LIMIT -1 OFFSET @p ) AS "c1" -WHERE "c0"."CustomerID" = "c1"."CustomerID" +WHERE "Customers"."CustomerID" = "c1"."CustomerID" """); } @@ -886,7 +886,7 @@ public override async Task Update_Where_OrderBy_Take_set_constant(bool async) @p1='Updated' (Size = 7) @p='4' -UPDATE "Customers" AS "c0" +UPDATE "Customers" SET "ContactName" = @p1 FROM ( SELECT "c"."CustomerID" @@ -895,7 +895,7 @@ public override async Task Update_Where_OrderBy_Take_set_constant(bool async) ORDER BY "c"."City" LIMIT @p ) AS "c1" -WHERE "c0"."CustomerID" = "c1"."CustomerID" +WHERE "Customers"."CustomerID" = "c1"."CustomerID" """); } @@ -909,7 +909,7 @@ public override async Task Update_Where_OrderBy_Skip_Take_set_constant(bool asyn @p1='4' @p='2' -UPDATE "Customers" AS "c0" +UPDATE "Customers" SET "ContactName" = @p2 FROM ( SELECT "c"."CustomerID" @@ -918,7 +918,7 @@ public override async Task Update_Where_OrderBy_Skip_Take_set_constant(bool asyn ORDER BY "c"."City" LIMIT @p1 OFFSET @p ) AS "c1" -WHERE "c0"."CustomerID" = "c1"."CustomerID" +WHERE "Customers"."CustomerID" = "c1"."CustomerID" """); } @@ -932,7 +932,7 @@ public override async Task Update_Where_OrderBy_Skip_Take_Skip_Take_set_constant @p1='6' @p='2' -UPDATE "Customers" AS "c1" +UPDATE "Customers" SET "ContactName" = @p4 FROM ( SELECT "c0"."CustomerID" @@ -946,7 +946,7 @@ LIMIT @p1 OFFSET @p ORDER BY "c0"."City" LIMIT @p OFFSET @p ) AS "c2" -WHERE "c1"."CustomerID" = "c2"."CustomerID" +WHERE "Customers"."CustomerID" = "c2"."CustomerID" """); } @@ -1031,14 +1031,14 @@ public override async Task Update_Where_Distinct_set_constant(bool async) """ @p='Updated' (Size = 7) -UPDATE "Customers" AS "c0" +UPDATE "Customers" SET "ContactName" = @p FROM ( SELECT DISTINCT "c"."CustomerID", "c"."Address", "c"."City", "c"."CompanyName", "c"."ContactName", "c"."ContactTitle", "c"."Country", "c"."Fax", "c"."Phone", "c"."PostalCode", "c"."Region" FROM "Customers" AS "c" WHERE "c"."CustomerID" LIKE 'F%' ) AS "c1" -WHERE "c0"."CustomerID" = "c1"."CustomerID" +WHERE "Customers"."CustomerID" = "c1"."CustomerID" """); } @@ -1048,7 +1048,7 @@ public override async Task Update_Where_using_navigation_set_null(bool async) AssertExecuteUpdateSql( """ -UPDATE "Orders" AS "o0" +UPDATE "Orders" SET "OrderDate" = NULL FROM ( SELECT "o"."OrderID" @@ -1056,7 +1056,7 @@ public override async Task Update_Where_using_navigation_set_null(bool async) LEFT JOIN "Customers" AS "c" ON "o"."CustomerID" = "c"."CustomerID" WHERE "c"."City" = 'Seattle' ) AS "s" -WHERE "o0"."OrderID" = "s"."OrderID" +WHERE "Orders"."OrderID" = "s"."OrderID" """); } @@ -1068,11 +1068,11 @@ public override async Task Update_Where_using_navigation_2_set_constant(bool asy """ @p='1' -UPDATE "Order Details" AS "o" +UPDATE "Order Details" SET "Quantity" = CAST(@p AS INTEGER) FROM "Orders" AS "o0" LEFT JOIN "Customers" AS "c" ON "o0"."CustomerID" = "c"."CustomerID" -WHERE "o"."OrderID" = "o0"."OrderID" AND "c"."City" = 'Seattle' +WHERE "Order Details"."OrderID" = "o0"."OrderID" AND "c"."City" = 'Seattle' """); } @@ -1082,10 +1082,10 @@ public override async Task Update_Where_SelectMany_set_null(bool async) AssertExecuteUpdateSql( """ -UPDATE "Orders" AS "o" +UPDATE "Orders" SET "OrderDate" = NULL FROM "Customers" AS "c" -WHERE "c"."CustomerID" = "o"."CustomerID" AND "c"."CustomerID" LIKE 'F%' +WHERE "c"."CustomerID" = "Orders"."CustomerID" AND "c"."CustomerID" LIKE 'F%' """); } @@ -1205,7 +1205,7 @@ public override async Task Update_Union_set_constant(bool async) """ @p='Updated' (Size = 7) -UPDATE "Customers" AS "c1" +UPDATE "Customers" SET "ContactName" = @p FROM ( SELECT "c"."CustomerID", "c"."Address", "c"."City", "c"."CompanyName", "c"."ContactName", "c"."ContactTitle", "c"."Country", "c"."Fax", "c"."Phone", "c"."PostalCode", "c"."Region" @@ -1216,7 +1216,7 @@ public override async Task Update_Union_set_constant(bool async) FROM "Customers" AS "c0" WHERE "c0"."CustomerID" LIKE 'A%' ) AS "u" -WHERE "c1"."CustomerID" = "u"."CustomerID" +WHERE "Customers"."CustomerID" = "u"."CustomerID" """); } @@ -1228,7 +1228,7 @@ public override async Task Update_Concat_set_constant(bool async) """ @p='Updated' (Size = 7) -UPDATE "Customers" AS "c1" +UPDATE "Customers" SET "ContactName" = @p FROM ( SELECT "c"."CustomerID" @@ -1239,7 +1239,7 @@ UNION ALL FROM "Customers" AS "c0" WHERE "c0"."CustomerID" LIKE 'A%' ) AS "u" -WHERE "c1"."CustomerID" = "u"."CustomerID" +WHERE "Customers"."CustomerID" = "u"."CustomerID" """); } @@ -1251,7 +1251,7 @@ public override async Task Update_Except_set_constant(bool async) """ @p='Updated' (Size = 7) -UPDATE "Customers" AS "c1" +UPDATE "Customers" SET "ContactName" = @p FROM ( SELECT "c"."CustomerID", "c"."Address", "c"."City", "c"."CompanyName", "c"."ContactName", "c"."ContactTitle", "c"."Country", "c"."Fax", "c"."Phone", "c"."PostalCode", "c"."Region" @@ -1262,7 +1262,7 @@ public override async Task Update_Except_set_constant(bool async) FROM "Customers" AS "c0" WHERE "c0"."CustomerID" LIKE 'A%' ) AS "e" -WHERE "c1"."CustomerID" = "e"."CustomerID" +WHERE "Customers"."CustomerID" = "e"."CustomerID" """); } @@ -1274,7 +1274,7 @@ public override async Task Update_Intersect_set_constant(bool async) """ @p='Updated' (Size = 7) -UPDATE "Customers" AS "c1" +UPDATE "Customers" SET "ContactName" = @p FROM ( SELECT "c"."CustomerID", "c"."Address", "c"."City", "c"."CompanyName", "c"."ContactName", "c"."ContactTitle", "c"."Country", "c"."Fax", "c"."Phone", "c"."PostalCode", "c"."Region" @@ -1285,7 +1285,7 @@ public override async Task Update_Intersect_set_constant(bool async) FROM "Customers" AS "c0" WHERE "c0"."CustomerID" LIKE 'A%' ) AS "i" -WHERE "c1"."CustomerID" = "i"."CustomerID" +WHERE "Customers"."CustomerID" = "i"."CustomerID" """); } @@ -1297,14 +1297,14 @@ public override async Task Update_with_join_set_constant(bool async) """ @p='Updated' (Size = 7) -UPDATE "Customers" AS "c" +UPDATE "Customers" SET "ContactName" = @p FROM ( SELECT "o"."CustomerID" FROM "Orders" AS "o" WHERE "o"."OrderID" < 10300 ) AS "o0" -WHERE "c"."CustomerID" = "o0"."CustomerID" AND "c"."CustomerID" LIKE 'F%' +WHERE "Customers"."CustomerID" = "o0"."CustomerID" AND "Customers"."CustomerID" LIKE 'F%' """); } @@ -1316,7 +1316,7 @@ public override async Task Update_with_LeftJoin(bool async) """ @p='Updated' (Size = 7) -UPDATE "Customers" AS "c0" +UPDATE "Customers" SET "ContactName" = @p FROM ( SELECT "c"."CustomerID" @@ -1328,7 +1328,7 @@ LEFT JOIN ( ) AS "o0" ON "c"."CustomerID" = "o0"."CustomerID" WHERE "c"."CustomerID" LIKE 'F%' ) AS "s" -WHERE "c0"."CustomerID" = "s"."CustomerID" +WHERE "Customers"."CustomerID" = "s"."CustomerID" """); } @@ -1340,7 +1340,7 @@ public override async Task Update_with_LeftJoin_via_flattened_GroupJoin(bool asy """ @p='Updated' (Size = 7) -UPDATE "Customers" AS "c0" +UPDATE "Customers" SET "ContactName" = @p FROM ( SELECT "c"."CustomerID" @@ -1352,7 +1352,7 @@ LEFT JOIN ( ) AS "o0" ON "c"."CustomerID" = "o0"."CustomerID" WHERE "c"."CustomerID" LIKE 'F%' ) AS "s" -WHERE "c0"."CustomerID" = "s"."CustomerID" +WHERE "Customers"."CustomerID" = "s"."CustomerID" """); } @@ -1364,7 +1364,7 @@ public override async Task Update_with_RightJoin(bool async) """ @p='2020-01-01T00:00:00.0000000Z' (Nullable = true) (DbType = DateTime) -UPDATE "Orders" AS "o0" +UPDATE "Orders" SET "OrderDate" = @p FROM ( SELECT "o"."OrderID" @@ -1376,7 +1376,7 @@ RIGHT JOIN ( ) AS "c0" ON "o"."CustomerID" = "c0"."CustomerID" WHERE "o"."OrderID" < 10300 ) AS "s" -WHERE "o0"."OrderID" = "s"."OrderID" +WHERE "Orders"."OrderID" = "s"."OrderID" """); } @@ -1388,14 +1388,14 @@ public override async Task Update_with_cross_join_set_constant(bool async) """ @p='Updated' (Size = 7) -UPDATE "Customers" AS "c" +UPDATE "Customers" SET "ContactName" = @p FROM ( SELECT 1 FROM "Orders" AS "o" WHERE "o"."OrderID" < 10300 ) AS "o0" -WHERE "c"."CustomerID" LIKE 'F%' +WHERE "Customers"."CustomerID" LIKE 'F%' """); } @@ -1416,7 +1416,7 @@ public override async Task Update_with_cross_join_left_join_set_constant(bool as AssertExecuteUpdateSql( """ -UPDATE "Customers" AS "c" +UPDATE "Customers" SET "ContactName" = 'Updated' FROM ( SELECT "c0"."CustomerID", "c0"."Address", "c0"."City", "c0"."CompanyName", "c0"."ContactName", "c0"."ContactTitle", "c0"."Country", "c0"."Fax", "c0"."Phone", "c0"."PostalCode", "c0"."Region" @@ -1427,8 +1427,8 @@ LEFT JOIN ( SELECT "o"."OrderID", "o"."CustomerID", "o"."EmployeeID", "o"."OrderDate" FROM "Orders" AS "o" WHERE "o"."OrderID" < 10300 -) AS "t0" ON "c"."CustomerID" = "t0"."CustomerID" -WHERE "c"."CustomerID" LIKE 'F%' +) AS "t0" ON "Customers"."CustomerID" = "t0"."CustomerID" +WHERE "Customers"."CustomerID" LIKE 'F%' """); } @@ -1457,7 +1457,7 @@ public override async Task Update_Where_SelectMany_subquery_set_null(bool async) AssertExecuteUpdateSql( """ -UPDATE "Orders" AS "o1" +UPDATE "Orders" SET "OrderDate" = NULL FROM ( SELECT "o0"."OrderID" @@ -1469,7 +1469,7 @@ WHERE CAST(strftime('%Y', "o"."OrderDate") AS INTEGER) = 1997 ) AS "o0" ON "c"."CustomerID" = "o0"."CustomerID" WHERE "c"."CustomerID" LIKE 'F%' ) AS "s" -WHERE "o1"."OrderID" = "s"."OrderID" +WHERE "Orders"."OrderID" = "s"."OrderID" """); } @@ -1496,14 +1496,14 @@ public override async Task Update_Where_Join_set_property_from_joined_table(bool AssertExecuteUpdateSql( """ -UPDATE "Customers" AS "c" +UPDATE "Customers" SET "City" = "c1"."City" FROM ( SELECT "c0"."City" FROM "Customers" AS "c0" WHERE "c0"."CustomerID" = 'ALFKI' ) AS "c1" -WHERE "c"."CustomerID" LIKE 'F%' +WHERE "Customers"."CustomerID" LIKE 'F%' """); } @@ -1545,7 +1545,7 @@ public override async Task Update_with_PK_pushdown_and_join_and_multiple_setters @p='1' @p2='10' -UPDATE "Order Details" AS "o2" +UPDATE "Order Details" SET "Quantity" = CAST(@p AS INTEGER), "UnitPrice" = @p2 FROM ( @@ -1559,7 +1559,7 @@ ORDER BY "o"."OrderID" INNER JOIN "Orders" AS "o0" ON "o1"."OrderID" = "o0"."OrderID" WHERE "o0"."CustomerID" = 'ALFKI' ) AS "s" -WHERE "o2"."OrderID" = "s"."OrderID" AND "o2"."ProductID" = "s"."ProductID" +WHERE "Order Details"."OrderID" = "s"."OrderID" AND "Order Details"."ProductID" = "s"."ProductID" """); }