Skip to content

arrayColumn.Contains(element) translates into element = ANY(arrayColumn) in version 10 #3862

Description

@sskalex

Hello! I believe I've encountered a regression while upgrading Npgsql.EntityFrameworkCore.PostgreSQL from 9.0.4 to 10.0.2.

arrayColumn.Contains(element) used to translate into [arrayColumn @> ARRAY[element]] as stated in docs.
But now it translates into element = ANY(arrayColumn). This can be critical since element = ANY(arrayColumn) operator is not supported by GIN index. Now my query seq scans the table.

Minimal repro code
using Microsoft.EntityFrameworkCore;
using Npgsql;

var dataSource = new NpgsqlDataSourceBuilder("Host=localhost")
    .Build();

var options = new DbContextOptionsBuilder<TestContext>()
    .UseNpgsql(dataSource)
    .EnableSensitiveDataLogging()
    .Options;

await using var ctx = new TestContext(options);

var query = ctx.Items.Where(i => i.Names.Contains("Test"));

Console.WriteLine(query.ToQueryString());

public class TestContext : DbContext
{
    public TestContext(DbContextOptions<TestContext> options) : base(options)
    {
    }

    public DbSet<Item> Items => Set<Item>();
}

public class Item
{
    public int Id { get; set; }

    public string[] Names { get; set; } = Array.Empty<string>();

    public int[] Numbers { get; set; } = Array.Empty<int>();
}

This repro code produces:

SELECT i."Id", i."Names", i."Numbers"
FROM "Items" AS i
WHERE 'Test' = ANY (i."Names")

I've tested various expressions and I can't make it produce @> as it used to before. All variations produce WHERE 'Test' = ANY (i."Names"). To name a few I've tried:

  • var query = ctx.Items.Where(i => i.Names.AsEnumerable().Contains("Test"));
  • var query = ctx.Items.Where(i => i.Names.ToList().Contains("Test"));
  • var query = ctx.Items.Where(i => i.Names.Any(n => n == "test"));

With Npgsql.EntityFrameworkCore.PostgreSQL 9.0.4 all those variations translate to:

SELECT i."Id", i."Names", i."Numbers"
FROM "Items" AS i
WHERE i."Names" @> ARRAY['test']::text[]

This query is supported by GIN index and I believe it is the correct translation.

P.S. - this feels related to a C# 14 breaking change of overload resolution with span parameters. That was my original thought but adding AsEnumerable() or downgrading to C# 10 didn't help. Maybe this change somehow affected the library itself but I am probably very wrong here.

Environment

Component Version
.NET 10.0
C# 14 (also fails on 10)
Microsoft.EntityFrameworkCore 10.0.9
Npgsql.EntityFrameworkCore.PostgreSQL 10.0.2

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions