From fa8d7839f8cd6def6012d9c0562540753caecd3c Mon Sep 17 00:00:00 2001 From: Shay Rojansky Date: Fri, 10 Jul 2026 10:14:43 +0200 Subject: [PATCH 1/2] Fix GIN index detection for views Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- ...yableMethodTranslatingExpressionVisitor.cs | 12 +++++------ .../PrimitiveCollectionsQueryNpgsqlTest.cs | 20 +++++++++++++++++++ 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/src/EFCore.PG/Query/Internal/NpgsqlQueryableMethodTranslatingExpressionVisitor.cs b/src/EFCore.PG/Query/Internal/NpgsqlQueryableMethodTranslatingExpressionVisitor.cs index ef8cf0f1a..c636dca5d 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/PrimitiveCollectionsQueryNpgsqlTest.cs b/test/EFCore.PG.FunctionalTests/Query/PrimitiveCollectionsQueryNpgsqlTest.cs index 229eb6b8b..a6c3314ce 100644 --- a/test/EFCore.PG.FunctionalTests/Query/PrimitiveCollectionsQueryNpgsqlTest.cs +++ b/test/EFCore.PG.FunctionalTests/Query/PrimitiveCollectionsQueryNpgsqlTest.cs @@ -2753,6 +2753,26 @@ LIMIT 2 """); } + [ConditionalFact] + public virtual async Task View_column_collection_Contains_with_GIN_index_uses_containment() + { + var contextFactory = await InitializeNonSharedTest( + onModelCreating: mb => mb.Entity() + .ToView("TestView") + .HasIndex(e => e.Ints) + .HasMethod("GIN")); + + await using var context = contextFactory.CreateDbContext(); + + 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() { From 68c01b239b76552d3f92f497709c691fbedb21c7 Mon Sep 17 00:00:00 2001 From: Shay Rojansky Date: Fri, 10 Jul 2026 10:17:35 +0200 Subject: [PATCH 2/2] Suppress view index validation in regression test Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .../Query/PrimitiveCollectionsQueryNpgsqlTest.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/EFCore.PG.FunctionalTests/Query/PrimitiveCollectionsQueryNpgsqlTest.cs b/test/EFCore.PG.FunctionalTests/Query/PrimitiveCollectionsQueryNpgsqlTest.cs index a6c3314ce..2a06de91d 100644 --- a/test/EFCore.PG.FunctionalTests/Query/PrimitiveCollectionsQueryNpgsqlTest.cs +++ b/test/EFCore.PG.FunctionalTests/Query/PrimitiveCollectionsQueryNpgsqlTest.cs @@ -2760,7 +2760,8 @@ public virtual async Task View_column_collection_Contains_with_GIN_index_uses_co onModelCreating: mb => mb.Entity() .ToView("TestView") .HasIndex(e => e.Ints) - .HasMethod("GIN")); + .HasMethod("GIN"), + onConfiguring: b => b.ConfigureWarnings(w => w.Ignore(RelationalEventId.AllIndexPropertiesNotMappedToAnyTable))); await using var context = contextFactory.CreateDbContext();