From 6afd72697d83ca9fdd37e87d516595a50a5e29f7 Mon Sep 17 00:00:00 2001 From: Shay Rojansky Date: Wed, 18 Feb 2026 08:10:35 +0100 Subject: [PATCH] Rename JsonExists to JsonPathExists Part of #31136 --- .../RelationalDbFunctionsExtensions.cs | 4 ++-- .../Query/SqlExpressions/SelectExpression.cs | 1 - .../Query/SqlNullabilityProcessor.cs | 2 +- ...qlServerSqlTranslatingExpressionVisitor.cs | 4 ++-- .../SqliteSqlTranslatingExpressionVisitor.cs | 4 ++-- .../JsonTranslationsRelationalTestBase.cs | 20 +++++++++---------- .../JsonTranslationsSqlServerTest.cs | 16 +++++++-------- .../JsonTranslationsSqliteTest.cs | 16 +++++++-------- 8 files changed, 33 insertions(+), 34 deletions(-) diff --git a/src/EFCore.Relational/Extensions/RelationalDbFunctionsExtensions.cs b/src/EFCore.Relational/Extensions/RelationalDbFunctionsExtensions.cs index 3eb33258d9d..2cea5107483 100644 --- a/src/EFCore.Relational/Extensions/RelationalDbFunctionsExtensions.cs +++ b/src/EFCore.Relational/Extensions/RelationalDbFunctionsExtensions.cs @@ -56,6 +56,6 @@ public static T Greatest(this DbFunctions _, [NotParameterized] params T[] va /// The instance. /// The JSON value to check. /// The JSON path to look for. - public static bool JsonExists(this DbFunctions _, object json, string path) - => throw new InvalidOperationException(CoreStrings.FunctionOnClient(nameof(JsonExists))); + public static bool JsonPathExists(this DbFunctions _, object json, string path) + => throw new InvalidOperationException(CoreStrings.FunctionOnClient(nameof(JsonPathExists))); } diff --git a/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs index 2e0b65f0236..2efcd67ecf8 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs @@ -2072,7 +2072,6 @@ private void ApplySetOperation( SelectExpression select2, bool distinct) { - // TODO: Introduce clone method? See issue#24460 var select1 = new SelectExpression( alias: null, tables: _tables.ToList(), groupBy: _groupBy.ToList(), projections: [], orderings: _orderings.ToList(), annotations: Annotations, sqlAliasManager: _sqlAliasManager) diff --git a/src/EFCore.Relational/Query/SqlNullabilityProcessor.cs b/src/EFCore.Relational/Query/SqlNullabilityProcessor.cs index bec7c0e3c29..bc9d68e21b1 100644 --- a/src/EFCore.Relational/Query/SqlNullabilityProcessor.cs +++ b/src/EFCore.Relational/Query/SqlNullabilityProcessor.cs @@ -1957,7 +1957,7 @@ protected virtual bool TryMakeNonNullable( var rewrittenCollectionTable = UpdateParameterCollection(collectionTable, rewrittenParameter); // We clone the select expression since Update below doesn't create a pure copy, mutating the original as well (because of - // TableReferenceExpression). TODO: Remove this after #31327. + // TableReferenceExpression). TODO: Remove this after SelectExpression becomes fully mutable (#32927). #pragma warning disable EF1001 rewrittenSelectExpression = selectExpression.Clone(); #pragma warning restore EF1001 diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerSqlTranslatingExpressionVisitor.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerSqlTranslatingExpressionVisitor.cs index c049b4c8bfe..7ed12888445 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerSqlTranslatingExpressionVisitor.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerSqlTranslatingExpressionVisitor.cs @@ -315,9 +315,9 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp typeof(int)); } - // We translate EF.Functions.JsonExists here and not in a method translator since we need to support JsonExists over + // We translate EF.Functions.JsonPathExists here and not in a method translator since we need to support JsonPathExists over // complex and owned JSON properties, which requires special handling. - case nameof(RelationalDbFunctionsExtensions.JsonExists) + case nameof(RelationalDbFunctionsExtensions.JsonPathExists) when declaringType == typeof(RelationalDbFunctionsExtensions) && @object is null && arguments is [_, var json, var path]: diff --git a/src/EFCore.Sqlite.Core/Query/Internal/SqliteSqlTranslatingExpressionVisitor.cs b/src/EFCore.Sqlite.Core/Query/Internal/SqliteSqlTranslatingExpressionVisitor.cs index 2001be61a61..c0d7e051604 100644 --- a/src/EFCore.Sqlite.Core/Query/Internal/SqliteSqlTranslatingExpressionVisitor.cs +++ b/src/EFCore.Sqlite.Core/Query/Internal/SqliteSqlTranslatingExpressionVisitor.cs @@ -236,9 +236,9 @@ when methodCallExpression.Object is not null method.Name is nameof(string.StartsWith)); } - // We translate EF.Functions.JsonExists here and not in a method translator since we need to support JsonExists over + // We translate EF.Functions.JsonPathExists here and not in a method translator since we need to support JsonPathExists over // complex and owned JSON properties, which requires special handling. - case nameof(RelationalDbFunctionsExtensions.JsonExists) + case nameof(RelationalDbFunctionsExtensions.JsonPathExists) when declaringType == typeof(RelationalDbFunctionsExtensions) && @object is null && arguments is [_, var json, var path]: diff --git a/test/EFCore.Relational.Specification.Tests/Query/Translations/JsonTranslationsRelationalTestBase.cs b/test/EFCore.Relational.Specification.Tests/Query/Translations/JsonTranslationsRelationalTestBase.cs index dfcc4c898e8..e937ebd5e79 100644 --- a/test/EFCore.Relational.Specification.Tests/Query/Translations/JsonTranslationsRelationalTestBase.cs +++ b/test/EFCore.Relational.Specification.Tests/Query/Translations/JsonTranslationsRelationalTestBase.cs @@ -7,32 +7,32 @@ namespace Microsoft.EntityFrameworkCore.Query.Translations; -// This test suite covers translations of JSON functions on EF.Functions (e.g. EF.Functions.JsonExists). +// This test suite covers translations of JSON functions on EF.Functions (e.g. EF.Functions.JsonPathExists). // It does not cover general, built-in JSON support via complex type mapping, etc. public abstract class JsonTranslationsRelationalTestBase(TFixture fixture) : QueryTestBase(fixture) where TFixture : JsonTranslationsRelationalTestBase.JsonTranslationsQueryFixtureBase, new() { [ConditionalFact] - public virtual Task JsonExists_on_scalar_string_column() + public virtual Task JsonPathExists_on_scalar_string_column() => AssertQuery( ss => ss.Set() - .Where(b => EF.Functions.JsonExists(b.JsonString, "$.OptionalInt")), + .Where(b => EF.Functions.JsonPathExists(b.JsonString, "$.OptionalInt")), ss => ss.Set() .Where(b => ((IDictionary)JsonNode.Parse(b.JsonString)!).ContainsKey("OptionalInt"))); [ConditionalFact] - public virtual Task JsonExists_on_complex_property() + public virtual Task JsonPathExists_on_complex_property() => AssertQuery( ss => ss.Set() - .Where(b => EF.Functions.JsonExists(b.JsonComplexType, "$.OptionalInt")), + .Where(b => EF.Functions.JsonPathExists(b.JsonComplexType, "$.OptionalInt")), ss => ss.Set() .Where(b => ((IDictionary)JsonNode.Parse(b.JsonString)!).ContainsKey("OptionalInt"))); [ConditionalFact] - public virtual Task JsonExists_on_owned_entity() + public virtual Task JsonPathExists_on_owned_entity() => AssertQuery( ss => ss.Set() - .Where(b => EF.Functions.JsonExists(b.JsonOwnedType, "$.OptionalInt")), + .Where(b => EF.Functions.JsonPathExists(b.JsonOwnedType, "$.OptionalInt")), ss => ss.Set() .Where(b => ((IDictionary)JsonNode.Parse(b.JsonString)!).ContainsKey("OptionalInt"))); @@ -103,12 +103,12 @@ protected override async Task SeedAsync(JsonTranslationsQueryContext context) await context.Database.ExecuteSqlRawAsync( $$""" - UPDATE {{table}} SET {{complexTypeColumn}} = {{RemoveJsonProperty(complexTypeColumn, "$.OptionalInt")}} WHERE {{idColumn}} = 4; - UPDATE {{table}} SET {{ownedColumn}} = {{RemoveJsonProperty(ownedColumn, "$.OptionalInt")}} WHERE {{idColumn}} = 4; + UPDATE {{table}} SET {{complexTypeColumn}} = {{RemoveJsonProperty(complexTypeColumn, "OptionalInt")}} WHERE {{idColumn}} = 4; + UPDATE {{table}} SET {{ownedColumn}} = {{RemoveJsonProperty(ownedColumn, "OptionalInt")}} WHERE {{idColumn}} = 4; """); } - protected abstract string RemoveJsonProperty(string column, string jsonPath); + protected abstract string RemoveJsonProperty(string column, string property); public virtual ISetSource GetExpectedData() => _expectedData ??= new JsonTranslationsData(); diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/Translations/JsonTranslationsSqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/Translations/JsonTranslationsSqlServerTest.cs index e594bda2113..408e4b8844d 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/Translations/JsonTranslationsSqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/Translations/JsonTranslationsSqlServerTest.cs @@ -15,9 +15,9 @@ public JsonTranslationsSqlServerTest(JsonTranslationsQuerySqlServerFixture fixtu } [ConditionalFact, SqlServerCondition(SqlServerCondition.SupportsFunctions2022)] - public override async Task JsonExists_on_scalar_string_column() + public override async Task JsonPathExists_on_scalar_string_column() { - await base.JsonExists_on_scalar_string_column(); + await base.JsonPathExists_on_scalar_string_column(); AssertSql( """ @@ -28,9 +28,9 @@ WHERE JSON_PATH_EXISTS([j].[JsonString], N'$.OptionalInt') = 1 } [ConditionalFact, SqlServerCondition(SqlServerCondition.SupportsFunctions2022)] - public override async Task JsonExists_on_complex_property() + public override async Task JsonPathExists_on_complex_property() { - await base.JsonExists_on_complex_property(); + await base.JsonPathExists_on_complex_property(); AssertSql( """ @@ -41,9 +41,9 @@ WHERE JSON_PATH_EXISTS([j].[JsonComplexType], N'$.OptionalInt') = 1 } [ConditionalFact, SqlServerCondition(SqlServerCondition.SupportsFunctions2022)] - public override async Task JsonExists_on_owned_entity() + public override async Task JsonPathExists_on_owned_entity() { - await base.JsonExists_on_owned_entity(); + await base.JsonPathExists_on_owned_entity(); AssertSql( """ @@ -133,8 +133,8 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con } } - protected override string RemoveJsonProperty(string column, string jsonPath) - => $"JSON_MODIFY({column}, '{jsonPath}', NULL)"; + protected override string RemoveJsonProperty(string column, string property) + => $"JSON_MODIFY({column}, '$.{property}', NULL)"; } [ConditionalFact] diff --git a/test/EFCore.Sqlite.FunctionalTests/Query/Translations/JsonTranslationsSqliteTest.cs b/test/EFCore.Sqlite.FunctionalTests/Query/Translations/JsonTranslationsSqliteTest.cs index f1c82ae2a8e..4ef55b7717c 100644 --- a/test/EFCore.Sqlite.FunctionalTests/Query/Translations/JsonTranslationsSqliteTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/Query/Translations/JsonTranslationsSqliteTest.cs @@ -13,9 +13,9 @@ public JsonTranslationsSqliteTest(JsonTranslationsQuerySqliteFixture fixture, IT } [ConditionalFact] - public override async Task JsonExists_on_scalar_string_column() + public override async Task JsonPathExists_on_scalar_string_column() { - await base.JsonExists_on_scalar_string_column(); + await base.JsonPathExists_on_scalar_string_column(); AssertSql( """ @@ -26,9 +26,9 @@ WHERE json_type("j"."JsonString", '$.OptionalInt') IS NOT NULL } [ConditionalFact] - public override async Task JsonExists_on_complex_property() + public override async Task JsonPathExists_on_complex_property() { - await base.JsonExists_on_complex_property(); + await base.JsonPathExists_on_complex_property(); AssertSql( """ @@ -39,9 +39,9 @@ WHERE json_type("j"."JsonComplexType", '$.OptionalInt') IS NOT NULL } [ConditionalFact] - public override async Task JsonExists_on_owned_entity() + public override async Task JsonPathExists_on_owned_entity() { - await base.JsonExists_on_owned_entity(); + await base.JsonPathExists_on_owned_entity(); AssertSql( """ @@ -56,8 +56,8 @@ public class JsonTranslationsQuerySqliteFixture : JsonTranslationsQueryFixtureBa protected override ITestStoreFactory TestStoreFactory => SqliteTestStoreFactory.Instance; - protected override string RemoveJsonProperty(string column, string jsonPath) - => $"json_remove({column}, '{jsonPath}')"; + protected override string RemoveJsonProperty(string column, string property) + => $"json_remove({column}, '$.{property}')"; } [ConditionalFact]