// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Threading.Tasks; using EntityFrameworkCore.Jet.FunctionalTests.TestUtilities; using EntityFrameworkCore.Jet.Infrastructure; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.Internal; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.TestUtilities; using Xunit; using Xunit.Abstractions; namespace EntityFrameworkCore.Jet.FunctionalTests.Query; // ReSharper disable InconsistentNaming public class PrecompiledSqlPregenerationQueryJetTest( PrecompiledSqlPregenerationQueryJetTest.PrecompiledSqlPregenerationQueryJetFixture fixture, ITestOutputHelper testOutputHelper) : PrecompiledSqlPregenerationQueryRelationalTestBase(fixture, testOutputHelper), IClassFixture { protected override bool AlwaysPrintGeneratedSources => false; public override async Task No_parameters() { await base.No_parameters(); AssertSql( """ SELECT `b`.`Id`, `b`.`Name` FROM `Blogs` AS `b` WHERE `b`.`Name` = 'foo' """); } public override async Task Non_nullable_value_type() { await base.Non_nullable_value_type(); AssertSql( """ @id='8' SELECT `b`.`Id`, `b`.`Name` FROM `Blogs` AS `b` WHERE `b`.`Id` = @id """); } public override async Task Nullable_value_type() { await base.Nullable_value_type(); AssertSql( """ @id='8' (Nullable = true) SELECT `b`.`Id`, `b`.`Name` FROM `Blogs` AS `b` WHERE `b`.`Id` = @id """); } public override async Task Nullable_reference_type() { await base.Nullable_reference_type(); AssertSql( """ @name='bar' (Size = 255) SELECT `b`.`Id`, `b`.`Name` FROM `Blogs` AS `b` WHERE `b`.`Name` = @name """); } public override async Task Non_nullable_reference_type() { await base.Non_nullable_reference_type(); AssertSql( """ @name='bar' (Nullable = false) (Size = 255) SELECT `b`.`Id`, `b`.`Name` FROM `Blogs` AS `b` WHERE `b`.`Name` = @name """); } public override async Task Nullable_and_non_nullable_value_types() { await base.Nullable_and_non_nullable_value_types(); AssertSql( """ @id1='8' (Nullable = true) @id2='9' SELECT `b`.`Id`, `b`.`Name` FROM `Blogs` AS `b` WHERE `b`.`Id` = @id1 OR `b`.`Id` = @id2 """); } public override async Task Two_nullable_reference_types() { await base.Two_nullable_reference_types(); AssertSql( """ @name1='foo' (Size = 255) @name2='bar' (Size = 255) SELECT `b`.`Id`, `b`.`Name` FROM `Blogs` AS `b` WHERE `b`.`Name` = @name1 OR `b`.`Name` = @name2 """); } public override async Task Two_non_nullable_reference_types() { await base.Two_non_nullable_reference_types(); AssertSql( """ @name1='foo' (Nullable = false) (Size = 255) @name2='bar' (Nullable = false) (Size = 255) SELECT `b`.`Id`, `b`.`Name` FROM `Blogs` AS `b` WHERE `b`.`Name` = @name1 OR `b`.`Name` = @name2 """); } public override async Task Nullable_and_non_nullable_reference_types() { await base.Nullable_and_non_nullable_reference_types(); AssertSql( """ @name1='foo' (Size = 255) @name2='bar' (Nullable = false) (Size = 255) SELECT `b`.`Id`, `b`.`Name` FROM `Blogs` AS `b` WHERE `b`.`Name` = @name1 OR `b`.`Name` = @name2 """); } public override async Task Too_many_nullable_parameters_prevent_pregeneration() { await base.Too_many_nullable_parameters_prevent_pregeneration(); AssertSql( """ @name1='foo' (Size = 255) @name2='bar' (Size = 255) @name3='baz' (Size = 255) @name4='baq' (Size = 255) SELECT `b`.`Id`, `b`.`Name` FROM `Blogs` AS `b` WHERE `b`.`Name` = @name1 OR `b`.`Name` = @name2 OR `b`.`Name` = @name3 OR `b`.`Name` = @name4 """); } public override async Task Many_non_nullable_parameters_do_not_prevent_pregeneration() { await base.Many_non_nullable_parameters_do_not_prevent_pregeneration(); AssertSql( """ @name1='foo' (Nullable = false) (Size = 255) @name2='bar' (Nullable = false) (Size = 255) @name3='baz' (Nullable = false) (Size = 255) @name4='baq' (Nullable = false) (Size = 255) SELECT `b`.`Id`, `b`.`Name` FROM `Blogs` AS `b` WHERE `b`.`Name` = @name1 OR `b`.`Name` = @name2 OR `b`.`Name` = @name3 OR `b`.`Name` = @name4 """); } #region Tests for the different querying enumerables public override async Task Include_single_query() { await base.Include_single_query(); AssertSql( """ SELECT `b`.`Id`, `b`.`Name`, `p`.`Id`, `p`.`BlogId`, `p`.`Title` FROM `Blogs` AS `b` LEFT JOIN `Post` AS `p` ON `b`.`Id` = `p`.`BlogId` ORDER BY `b`.`Id` """); } public override async Task Include_split_query() { await base.Include_split_query(); AssertSql( """ SELECT `b`.`Id`, `b`.`Name` FROM `Blogs` AS `b` ORDER BY `b`.`Id` """, // """ SELECT `p`.`Id`, `p`.`BlogId`, `p`.`Title`, `b`.`Id` FROM `Blogs` AS `b` INNER JOIN `Post` AS `p` ON `b`.`Id` = `p`.`BlogId` ORDER BY `b`.`Id` """); } public override async Task Final_GroupBy() { await base.Final_GroupBy(); AssertSql( """ SELECT `b`.`Name`, `b`.`Id` FROM `Blogs` AS `b` ORDER BY `b`.`Name` """); } #endregion Tests for the different querying enumerables [ConditionalFact] public virtual async Task Do_not_cache_is_respected() { // The "do not cache" flag in the 2nd part of the query pipeline is turned on in provider-specific situations, so we test it // here in SQL Server; note that SQL Server compatibility mode is set low to trigger this. await Test( """ string[] names = ["foo", "bar"]; var blogs = await context.Blogs.Where(b => names.Contains(b.Name)).ToListAsync(); """, interceptorCodeAsserter: code => Assert.Contains(nameof(RelationalCommandCache), code)); AssertSql( """ @names1='foo' (Size = 255) @names2='bar' (Size = 255) SELECT `b`.`Id`, `b`.`Name` FROM `Blogs` AS `b` WHERE `b`.`Name` IN (@names1, @names2) """); } public class PrecompiledSqlPregenerationQueryJetFixture : PrecompiledSqlPregenerationQueryRelationalFixture { protected override ITestStoreFactory TestStoreFactory => JetTestStoreFactory.Instance; /*public override DbContextOptionsBuilder AddOptions(DbContextOptionsBuilder builder) { builder = base.AddOptions(builder); // TODO: Figure out if there's a nice way to continue using the retrying strategy var jetOptionsBuilder = new JetDbContextOptionsBuilder(builder); jetOptionsBuilder .ExecutionStrategy(d => new NonRetryingExecutionStrategy(d)); return builder; }*/ public override PrecompiledQueryTestHelpers PrecompiledQueryTestHelpers => JetPrecompiledQueryTestHelpers.Instance; } }