From 89e0d52a93c4eea088407e4d125ccbf9dcc6fb8d Mon Sep 17 00:00:00 2001 From: Shay Rojansky Date: Fri, 10 Jul 2026 10:22:09 +0200 Subject: [PATCH] Fix GIN index detection for views Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- ...yableMethodTranslatingExpressionVisitor.cs | 12 +++++------ ...aredPrimitiveCollectionsQueryNpgsqlTest.cs | 21 +++++++++++++++++++ 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/EFCore.PG/Query/Internal/NpgsqlQueryableMethodTranslatingExpressionVisitor.cs b/src/EFCore.PG/Query/Internal/NpgsqlQueryableMethodTranslatingExpressionVisitor.cs index a20f17e02f..f6f38ca53b 100644 --- a/src/EFCore.PG/Query/Internal/NpgsqlQueryableMethodTranslatingExpressionVisitor.cs +++ b/src/EFCore.PG/Query/Internal/NpgsqlQueryableMethodTranslatingExpressionVisitor.cs @@ -703,12 +703,12 @@ protected override ShapedQueryExpression TransformJsonQueryToTable(JsonQueryExpr return array switch { // For array columns which have a GIN index, we translate to array containment (with @>) which uses that index. - ColumnExpression { Column: IColumn column } - when column.Table.Indexes - .Any(i => - i.Columns.Count > 0 - && i.Columns[0] == column - && i.MappedIndexes.Any(mi => mi.GetMethod()?.Equals("GIN", StringComparison.OrdinalIgnoreCase) == true)) + ColumnExpression { Column: IColumnBase column } + when column.PropertyMappings.Any( + m => m.Property.GetContainingIndexes().Any( + i => i.Properties.Count > 0 + && i.Properties[0] == m.Property + && i.GetMethod()?.Equals("GIN", StringComparison.OrdinalIgnoreCase) == true)) => BuildSimplifiedShapedQuery( source, _sqlExpressionFactory.Contains( diff --git a/test/EFCore.PG.FunctionalTests/Query/NonSharedPrimitiveCollectionsQueryNpgsqlTest.cs b/test/EFCore.PG.FunctionalTests/Query/NonSharedPrimitiveCollectionsQueryNpgsqlTest.cs index 5ea8bc4860..278c5cbf0c 100644 --- a/test/EFCore.PG.FunctionalTests/Query/NonSharedPrimitiveCollectionsQueryNpgsqlTest.cs +++ b/test/EFCore.PG.FunctionalTests/Query/NonSharedPrimitiveCollectionsQueryNpgsqlTest.cs @@ -135,6 +135,27 @@ LIMIT 2 """); } + [ConditionalFact] + public virtual async Task View_column_collection_Contains_with_GIN_index_uses_containment() + { + var contextFactory = await InitializeAsync( + onModelCreating: mb => mb.Entity() + .ToView("TestView") + .HasIndex(e => e.Ints) + .HasMethod("GIN"), + onConfiguring: b => b.ConfigureWarnings(w => w.Ignore(RelationalEventId.AllIndexPropertiesNotToMappedToAnyTable))); + + await using var context = contextFactory.CreateContext(); + + Assert.Equal( + """ +SELECT t."Id", t."Ints" +FROM "TestView" AS t +WHERE t."Ints" @> ARRAY[4]::integer[] +""", + context.Set().Where(c => c.Ints!.Contains(4)).ToQueryString()); + } + [ConditionalFact] public virtual async Task Column_collection_Contains_with_btree_index_does_not_use_containment() {