= ANY with an AND/OR item omits parentheses, returning wrong results
Los mantenedores suelen responder en 1 día
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 2/5
- Tiempo estimado
- 1-3 horas
- Aptitud para principiantes
- 82/100
- Tipo de issue
- Error
- Claridad
- Bien especificado
- Estado de actividad
- Activo
- Stack tecnológico
- csharp, postgresql
- Área
- backend-api-design, database
Línea de trabajo
Empieza en src/EFCore.PG/Query/Internal/NpgsqlQuerySqlGenerator.cs, en la implementación de VisitArrayAny alrededor de la línea 890, y luego revisa el tratamiento de precedencia existente y sus pruebas. Reproduce el problema con la consulta Contains proporcionada y verifica que el SQL generado agrupe la expresión AND antes de = ANY; añade o actualiza una prueba de regresión para confirmar que la consulta devuelve las filas esperadas.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
VisitArrayAny writes the item without parentheses. When the item is an AND/OR expression, = binds tighter than AND, so Postgres applies = ANY to the last operand only. The query runs without error and returns the wrong rows.
bool[] availability = [false];
var unavailable = db.Products
.Where(p => availability.Contains(p.IsListed && p.InStock));
| SQL | Result | |
|---|---|---|
| Expected | WHERE (p."IsListed" AND p."InStock") = ANY (@availability) |
Banana, Cherry, Date |
| Actual | WHERE p."IsListed" AND p."InStock" = ANY (@availability) |
Banana |
Seed: Apple listed and in stock, Banana listed and out of stock, Cherry not listed and in stock, Date neither.
Full repro
using Microsoft.EntityFrameworkCore;
await using var db = new ShopContext();
await db.Database.EnsureDeletedAsync();
await db.Database.EnsureCreatedAsync();
db.Products.AddRange(
new Product { Name = "Apple", IsListed = true, InStock = true },
new Product { Name = "Banana", IsListed = true, InStock = false },
new Product { Name = "Cherry", IsListed = false, InStock = true },
new Product { Name = "Date", IsListed = false, InStock = false });
await db.SaveChangesAsync();
bool[] availability = [false];
var query = db.Products
.Where(p => availability.Contains(p.IsListed && p.InStock))
.Select(p => p.Name);
Console.WriteLine(query.ToQueryString());
Console.WriteLine(string.Join(", ", await query.ToListAsync()));
public class ShopContext : DbContext
{
public DbSet<Product> Products => Set<Product>();
protected override void OnConfiguring(DbContextOptionsBuilder options)
=> options.UseNpgsql("Host=localhost;Username=postgres;Password=postgres;Database=any_repro");
}
public class Product
{
public int Id { get; set; }
public string Name { get; set; } = "";
public bool IsListed { get; set; }
public bool InStock { get; set; }
}
Cause: NpgsqlQuerySqlGenerator.cs#L890 calls Visit(expression.Item) with no precedence check. The precedence table already ranks PgAnyExpression at 800 and AndAlso/OrElse at 500 (L1636).
Suggested fix, the same pattern as npgsql/npgsql#3927:
var requiresParentheses = RequiresParentheses(expression, expression.Item);
if (requiresParentheses)
{
Sql.Append("(");
}
Visit(expression.Item);
if (requiresParentheses)
{
Sql.Append(")");
}
Workaround: with a single picked value, filter on the expression or its negation (p.IsListed && p.InStock or !(p.IsListed && p.InStock)) in place of Contains.
Npgsql.EntityFrameworkCore.PostgreSQL 10.0.3, PostgreSQL 17. Happy to send a PR if that helps.
- Lenguaje dominante
- C#
- Estrellas
- 1.8k
- Forks
- 268
- Merge medio
- 2 h 35 min
- PR fusionados (30 d)
- 136
Preparar el entorno
Este proyecto no incluye contenedor de desarrollo, Dockerfile ni guía de contribución, así que la configuración corre por tu cuenta: empieza por su README y consulta nuestra guía para la primera contribución para los pasos generales.
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de npgsql/efcore.pg
-
NTS: the M ordinate is dropped from geometry SQL literals and from geometries stored in JSONPosiblemente ocupada @Ahmed7991 la tomó hace 5 días. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 85/100
npgsql/efcore.pg#4093 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
`TimeSpan`/`Duration` component members: negative values are floored, and intervals computed in SQL are read field by fieldPosiblemente ocupada @jeremy-morren la tomó hace 11 días. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 70/100
Los mantenedores suelen responder en 1 día
-
Numeric storage parameters are formatted with the current culture, so migrations emit 0,01 instead of 0.01Posiblemente ocupada @Sorbitol la tomó hace 12 días. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 30/100
Los mantenedores suelen responder en 1 día
-
`Contains` on a JSON primitive collection compares JSON text, so `DateTime` and `TimeOnly` items never matchPosiblemente ocupada @Mr444-dev la tomó hace 7 días. Abierto
Dificultad 4/5 3-5 días Aptitud para principiantes 45/100
npgsql/efcore.pg#4099 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
Array translations: chained `Skip`/`Take` return an empty array, `int.MaxValue` bounds overflow, and `Intersect().Any()` ignores NULL elementsQuizá libre de nuevo Un pull request para esta issue se cerró sin fusionarse. Abierto
Dificultad 4/5 3-5 días Aptitud para principiantes 30/100
Los mantenedores suelen responder en 1 día
Todos los issues de npgsql/efcore.pg
Issues similares
-
Issue-Bug Needs-Triage
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
Los mantenedores suelen responder en 2 días
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 66/100
JiaFeiMiao-K-Cat/DiscImageStudio#281 ·
Los mantenedores suelen responder en 1 día
-
area/access-management Frontend onboarding candidate :handshake:
Dificultad 2/5 1-3 horas Aptitud para principiantes 65/100
Altinn/altinn-auth#4941 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
aws/aws-sdk-net#4586 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
Kryptos-FR/MarkView.Avalonia#269 · 1 reacción ·
Los mantenedores suelen responder en 1 día