Optimizer drops parentheses for `NOT (<date> = DATE_TRUNC(...))`, changing query results
I maintainer di solito rispondono entro 1 giorno
Valutazione
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Idoneità per principianti
- 28/100
Direzione di ricerca
Start in the optimizer's simplify rules: simplify_parens and simplify_datetrunc in sqlglot/optimizer/simplify.py, plus _parenthesize_nested_connector, which the reporter blames for deciding parens are unnecessary because expression.parent is still the Paren being unwrapped. Reproduce with the DuckDB snippet in the issue, then follow the rule ordering where sort_comparison moves DATE_TRUNC left before the NOT is pushed in. Done looks like the optimized query returning the same 4 rows as the original and a new test under tests/fixtures/optimizer covering NOT with the literal on either side, for = and <>. Note a pull request (#9108) is already open against this, so coordinate before starting.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
The simplifier rewrites NOT (DATE '2024-01-03' = DATE_TRUNC('day', x)) into
NOT x < ... AND x >= .... Because the AND isn't parenthesized, NOT only applies to the
first comparison, so the optimized query returns different rows. It only happens when the
literal is on the left side; NOT (DATE_TRUNC('day', x) = DATE '2024-01-03') is fine.
Reproduced on main (b294f7fa8) with DuckDB 1.5.6:
import duckdb
import sqlglot
from sqlglot.optimizer import optimize
con = duckdb.connect()
con.execute("CREATE TABLE t AS SELECT DATE '2024-01-01' + CAST(i AS INT) AS x FROM range(5) r(i)")
sql = "SELECT COUNT(*) FROM t WHERE NOT (DATE '2024-01-03' = DATE_TRUNC('day', x))"
optimized = optimize(sqlglot.parse_one(sql, read="duckdb"), schema={"t": {"x": "DATE"}}, dialect="duckdb").sql("duckdb")
print(optimized)
print("original: ", con.execute(sql).fetchone()[0])
print("optimized:", con.execute(optimized).fetchone()[0])
Output:
SELECT COUNT(*) AS "_col_0" FROM "t" AS "t" WHERE NOT "t"."x" < CAST('2024-01-04' AS DATE) AND "t"."x" >= CAST('2024-01-03' AS DATE)
original: 4
optimized: 2
Expected: "t"."x" < CAST('2024-01-03' AS DATE) OR "t"."x" >= CAST('2024-01-04' AS DATE), i.e. 4 rows.
It happens for every unit (year, quarter, month, week, day, hour) and for <> as well.
Cause, as far as I can tell: the reversed comparison is only rewritten after sort_comparison
moves DATE_TRUNC to the left. When the enclosing Paren is processed, simplify_parens unwraps
it and then simplify_datetrunc runs in the same step, but expression.parent is still the
Paren being removed, so _parenthesize_nested_connector decides no parens are needed.
I found this by comparing query results in DuckDB before and after optimize(); I used Claude
to help with the testing and investigation. I have a small fix with tests and can open a PR.
- Lingua principale
- Python
- Stelle
- 9.8k
- Fork
- 1.4k
- Merge medio
- 13h 19m
- PR unite (30g)
- 243
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Nessun modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di tobymao/sqlglot
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 70/100
I maintainer di solito rispondono entro 1 giorno
-
SQLite: CAST(x AS JSON) is generated verbatim, which SQLite evaluates as a numeric castForse già presa @Gowthamsuryagolla l’ha presa oggi. Aperta
Difficoltà 3/5 Mezza giornata Idoneità per principianti 32/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 4/5 3-5 giorni Idoneità per principianti 30/100
I maintainer di solito rispondono entro 1 giorno
-
BigQuery: region-qualified INFORMATION_SCHEMA reference is rewritten across transpile passes, gaining an invented aliasForse già presa @ansh-rohilla l’ha presa oggi. Aperta
Difficoltà 4/5 3-5 giorni Idoneità per principianti 28/100
I maintainer di solito rispondono entro 1 giorno
-
DATE_ADD/DATE_SUB with a single argument raises AttributeError (BigQuery, MySQL, Doris, StarRocks)Forse già presa @akchhayasharma l’ha presa oggi. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 42/100
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di tobymao/sqlglot
Issue simili
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 75/100
alltheplaces/alltheplaces#20570 · 2 commenti ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 74/100
I maintainer di solito rispondono entro 1 giorno
-
area:ci bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 85/100
catincloud-labs/dagster-dex#206 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
number_to_words raises ValueError with threshold= for ordinals ("12th") and comma-grouped strings ("1,000")Forse già presa @hemtilva l’ha presa oggi. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 74/100
I maintainer di solito rispondono entro 1 giorno
-
providers security
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
agentbreeder/agentbreeder#1031 ·
I maintainer di solito rispondono entro 1 giorno