diff --git a/src/EFCore.Jet/Query/Sql/Internal/JetQuerySqlGenerator.cs b/src/EFCore.Jet/Query/Sql/Internal/JetQuerySqlGenerator.cs index 80731af..4b2e672 100644 --- a/src/EFCore.Jet/Query/Sql/Internal/JetQuerySqlGenerator.cs +++ b/src/EFCore.Jet/Query/Sql/Internal/JetQuerySqlGenerator.cs @@ -751,6 +751,71 @@ namespace EntityFrameworkCore.Jet.Query.Sql.Internal return crossJoinExpression; } + private Expression VisitRowValuePrivate(RowValueExpression rowValueExpression, IReadOnlyList columnNames) + { + var values = rowValueExpression.Values; + var count = values.Count; + for (var i = 0; i < count; i++) + { + if (i > 0) + { + Sql.Append(", "); + } + + Visit(values[i]); + Sql.Append(" AS "); + Sql.Append(_sqlGenerationHelper.DelimitIdentifier(columnNames[i])); + } + + return rowValueExpression; + } + + /// + /// 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 VisitValues(ValuesExpression valuesExpression) + { + base.VisitValues(valuesExpression); + + return valuesExpression; + } + + /// + /// 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 void GenerateValues(ValuesExpression valuesExpression) + { + if (valuesExpression.RowValues.Count == 0) + { + throw new InvalidOperationException(RelationalStrings.EmptyCollectionNotSupportedAsInlineQueryRoot); + } + + var rowValues = valuesExpression.RowValues; + + for (var i = 0; i < rowValues.Count; i++) + { + Sql.Append("SELECT "); + + VisitRowValuePrivate(valuesExpression.RowValues[i], valuesExpression.ColumnNames); + GeneratePseudoFromClause(); + var alias = valuesExpression.Alias; + Sql.Append(" AS "); + Sql.Append(_sqlGenerationHelper.DelimitIdentifier(alias + "_" + i)); + if (i != rowValues.Count - 1) + { + Sql.AppendLine(); + Sql.AppendLine("UNION"); + } + } + } + + /// Generates the TOP part of the SELECT statement, /// The select expression. protected override void GenerateTop(SelectExpression selectExpression) diff --git a/test/EFCore.Jet.FunctionalTests/GreenTests/ace_2010_odbc_x86.txt b/test/EFCore.Jet.FunctionalTests/GreenTests/ace_2010_odbc_x86.txt index 37ca3f8..a5cbdb3 100644 --- a/test/EFCore.Jet.FunctionalTests/GreenTests/ace_2010_odbc_x86.txt +++ b/test/EFCore.Jet.FunctionalTests/GreenTests/ace_2010_odbc_x86.txt @@ -15226,6 +15226,12 @@ EntityFrameworkCore.Jet.FunctionalTests.Query.PrimitiveCollectionsQueryJetTest.I EntityFrameworkCore.Jet.FunctionalTests.Query.PrimitiveCollectionsQueryJetTest.Inline_collection_Contains_with_two_values(async: True) EntityFrameworkCore.Jet.FunctionalTests.Query.PrimitiveCollectionsQueryJetTest.Inline_collection_Contains_with_zero_values(async: False) EntityFrameworkCore.Jet.FunctionalTests.Query.PrimitiveCollectionsQueryJetTest.Inline_collection_Contains_with_zero_values(async: True) +EntityFrameworkCore.Jet.FunctionalTests.Query.PrimitiveCollectionsQueryJetTest.Inline_collection_Count_with_one_value(async: False) +EntityFrameworkCore.Jet.FunctionalTests.Query.PrimitiveCollectionsQueryJetTest.Inline_collection_Count_with_one_value(async: True) +EntityFrameworkCore.Jet.FunctionalTests.Query.PrimitiveCollectionsQueryJetTest.Inline_collection_Count_with_three_values(async: False) +EntityFrameworkCore.Jet.FunctionalTests.Query.PrimitiveCollectionsQueryJetTest.Inline_collection_Count_with_three_values(async: True) +EntityFrameworkCore.Jet.FunctionalTests.Query.PrimitiveCollectionsQueryJetTest.Inline_collection_Count_with_two_values(async: False) +EntityFrameworkCore.Jet.FunctionalTests.Query.PrimitiveCollectionsQueryJetTest.Inline_collection_Count_with_two_values(async: True) EntityFrameworkCore.Jet.FunctionalTests.Query.PrimitiveCollectionsQueryJetTest.Inline_collection_Count_with_zero_values(async: False) EntityFrameworkCore.Jet.FunctionalTests.Query.PrimitiveCollectionsQueryJetTest.Inline_collection_Count_with_zero_values(async: True) EntityFrameworkCore.Jet.FunctionalTests.Query.PrimitiveCollectionsQueryJetTest.Inline_collection_Except_column_collection(async: False) diff --git a/test/EFCore.Jet.FunctionalTests/GreenTests/ace_2010_oledb_x86.txt b/test/EFCore.Jet.FunctionalTests/GreenTests/ace_2010_oledb_x86.txt index d73fc74..f3badd0 100644 --- a/test/EFCore.Jet.FunctionalTests/GreenTests/ace_2010_oledb_x86.txt +++ b/test/EFCore.Jet.FunctionalTests/GreenTests/ace_2010_oledb_x86.txt @@ -16390,6 +16390,12 @@ EntityFrameworkCore.Jet.FunctionalTests.Query.PrimitiveCollectionsQueryJetTest.I EntityFrameworkCore.Jet.FunctionalTests.Query.PrimitiveCollectionsQueryJetTest.Inline_collection_Contains_with_two_values(async: True) EntityFrameworkCore.Jet.FunctionalTests.Query.PrimitiveCollectionsQueryJetTest.Inline_collection_Contains_with_zero_values(async: False) EntityFrameworkCore.Jet.FunctionalTests.Query.PrimitiveCollectionsQueryJetTest.Inline_collection_Contains_with_zero_values(async: True) +EntityFrameworkCore.Jet.FunctionalTests.Query.PrimitiveCollectionsQueryJetTest.Inline_collection_Count_with_one_value(async: False) +EntityFrameworkCore.Jet.FunctionalTests.Query.PrimitiveCollectionsQueryJetTest.Inline_collection_Count_with_one_value(async: True) +EntityFrameworkCore.Jet.FunctionalTests.Query.PrimitiveCollectionsQueryJetTest.Inline_collection_Count_with_three_values(async: False) +EntityFrameworkCore.Jet.FunctionalTests.Query.PrimitiveCollectionsQueryJetTest.Inline_collection_Count_with_three_values(async: True) +EntityFrameworkCore.Jet.FunctionalTests.Query.PrimitiveCollectionsQueryJetTest.Inline_collection_Count_with_two_values(async: False) +EntityFrameworkCore.Jet.FunctionalTests.Query.PrimitiveCollectionsQueryJetTest.Inline_collection_Count_with_two_values(async: True) EntityFrameworkCore.Jet.FunctionalTests.Query.PrimitiveCollectionsQueryJetTest.Inline_collection_Count_with_zero_values(async: False) EntityFrameworkCore.Jet.FunctionalTests.Query.PrimitiveCollectionsQueryJetTest.Inline_collection_Count_with_zero_values(async: True) EntityFrameworkCore.Jet.FunctionalTests.Query.PrimitiveCollectionsQueryJetTest.Inline_collection_Except_column_collection(async: False) diff --git a/test/EFCore.Jet.FunctionalTests/Query/PrimitiveCollectionsQueryJetTest.cs b/test/EFCore.Jet.FunctionalTests/Query/PrimitiveCollectionsQueryJetTest.cs index 0fc237c..a70c0c3 100644 --- a/test/EFCore.Jet.FunctionalTests/Query/PrimitiveCollectionsQueryJetTest.cs +++ b/test/EFCore.Jet.FunctionalTests/Query/PrimitiveCollectionsQueryJetTest.cs @@ -77,13 +77,14 @@ WHERE `p`.`NullableInt` IS NULL OR `p`.`NullableInt` = 999 await base.Inline_collection_Count_with_one_value(async); AssertSql( -""" -SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings] -FROM [PrimitiveCollectionsEntity] AS [p] + """ +SELECT `p`.`Id`, `p`.`Bool`, `p`.`Bools`, `p`.`DateTime`, `p`.`DateTimes`, `p`.`Enum`, `p`.`Enums`, `p`.`Int`, `p`.`Ints`, `p`.`NullableInt`, `p`.`NullableInts`, `p`.`NullableString`, `p`.`NullableStrings`, `p`.`String`, `p`.`Strings` +FROM `PrimitiveCollectionsEntity` AS `p` WHERE ( SELECT COUNT(*) - FROM (VALUES (CAST(2 AS int))) AS [v]([Value]) - WHERE [v].[Value] > [p].[Id]) = 1 + FROM (SELECT CLNG(2) AS `Value` + FROM (SELECT COUNT(*) FROM `#Dual`) AS `v_0`) AS `v` + WHERE `v`.`Value` > `p`.`Id`) = 1 """); } @@ -92,13 +93,17 @@ WHERE ( await base.Inline_collection_Count_with_two_values(async); AssertSql( -""" -SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings] -FROM [PrimitiveCollectionsEntity] AS [p] + """ +SELECT `p`.`Id`, `p`.`Bool`, `p`.`Bools`, `p`.`DateTime`, `p`.`DateTimes`, `p`.`Enum`, `p`.`Enums`, `p`.`Int`, `p`.`Ints`, `p`.`NullableInt`, `p`.`NullableInts`, `p`.`NullableString`, `p`.`NullableStrings`, `p`.`String`, `p`.`Strings` +FROM `PrimitiveCollectionsEntity` AS `p` WHERE ( SELECT COUNT(*) - FROM (VALUES (CAST(2 AS int)), (999)) AS [v]([Value]) - WHERE [v].[Value] > [p].[Id]) = 1 + FROM (SELECT CLNG(2) AS `Value` + FROM (SELECT COUNT(*) FROM `#Dual`) AS `v_0` + UNION + SELECT 999 AS `Value` + FROM (SELECT COUNT(*) FROM `#Dual`) AS `v_1`) AS `v` + WHERE `v`.`Value` > `p`.`Id`) = 1 """); } @@ -107,13 +112,20 @@ WHERE ( await base.Inline_collection_Count_with_three_values(async); AssertSql( -""" -SELECT [p].[Id], [p].[Bool], [p].[Bools], [p].[DateTime], [p].[DateTimes], [p].[Enum], [p].[Enums], [p].[Int], [p].[Ints], [p].[NullableInt], [p].[NullableInts], [p].[NullableString], [p].[NullableStrings], [p].[String], [p].[Strings] -FROM [PrimitiveCollectionsEntity] AS [p] + """ +SELECT `p`.`Id`, `p`.`Bool`, `p`.`Bools`, `p`.`DateTime`, `p`.`DateTimes`, `p`.`Enum`, `p`.`Enums`, `p`.`Int`, `p`.`Ints`, `p`.`NullableInt`, `p`.`NullableInts`, `p`.`NullableString`, `p`.`NullableStrings`, `p`.`String`, `p`.`Strings` +FROM `PrimitiveCollectionsEntity` AS `p` WHERE ( SELECT COUNT(*) - FROM (VALUES (CAST(2 AS int)), (999), (1000)) AS [v]([Value]) - WHERE [v].[Value] > [p].[Id]) = 2 + FROM (SELECT CLNG(2) AS `Value` + FROM (SELECT COUNT(*) FROM `#Dual`) AS `v_0` + UNION + SELECT 999 AS `Value` + FROM (SELECT COUNT(*) FROM `#Dual`) AS `v_1` + UNION + SELECT 1000 AS `Value` + FROM (SELECT COUNT(*) FROM `#Dual`) AS `v_2`) AS `v` + WHERE `v`.`Value` > `p`.`Id`) = 2 """); }