1fanwang opened a new pull request, #25140:
URL: https://github.com/apache/datafusion/pull/25140

   ## Which issue does this PR close?
   
   - Closes #25135.
   
   ## Rationale for this change
   
   `EXTRACT(YEAR FROM ts) < 9999` matches no rows on a nanosecond timestamp
   column, and the comparison itself evaluates to NULL:
   
   ```sql
   SELECT EXTRACT(YEAR FROM ts), EXTRACT(YEAR FROM ts) < 9999 FROM t;
   -- 2020 NULL
   -- 1995 NULL
   ```
   
   The comparison is rewritten into a range over the timestamp column, which 
needs
   midnight on January 1 of the bound year. January 1 of 9999 is outside the
   nanosecond range, and that conversion returns nothing. The result was 
wrapped as
   a NULL scalar and used as the bound anyway, so every row compared against 
NULL.
   A wrong non-zero count is reachable too, since `OR` over two such predicates
   returns 1 instead of 2.
   
   ## What changes are included in this PR?
   
   Building the bound now reports that no bound exists when midnight has no
   representation in the target unit, so the original predicate is kept. The 
same
   path also covers a time zone that skips midnight on that date, such as Lima 
in
   1990 and 1994.
   
   ## What is the testing strategy for this PR?
   
   `datafusion/sqllogictest/test_files/datetime/date_part.slt` gains cases for 
the
   out-of-range bound in `WHERE`, in a projection and across `OR`, plus a bound
   inside the nanosecond range to confirm that rewriting still happens.
   
   <details><summary>Reproducer, before and after</summary>
   
   ```sql
   CREATE VIEW t AS SELECT * FROM (VALUES
     ('2020-06-01T12:00:00'::timestamp),
     ('1995-06-01T12:00:00'::timestamp)) s(ts);
   SELECT count(*) FROM t WHERE EXTRACT(YEAR FROM ts) < 9999;
   SELECT count(*) FROM t WHERE EXTRACT(YEAR FROM ts) >= 1000 OR EXTRACT(YEAR 
FROM ts) = 2020;
   SELECT EXTRACT(YEAR FROM ts), EXTRACT(YEAR FROM ts) < 9999 FROM t;
   SELECT count(*) FROM t WHERE EXTRACT(YEAR FROM ts) <= 2262;
   SELECT count(*) FROM t WHERE EXTRACT(YEAR FROM ts) >= 1678;
   ```
   
   | query | before | after |
   |---|---|---|
   | `< 9999` | 0 | 2 |
   | `>= 1000 OR = 2020` | 1 | 2 |
   | projection comparison | NULL, NULL | true, true |
   | `<= 2262` | 0 | 2 |
   | `>= 1678` | 2 | 2 |
   
   </details>
   
   ## Are there any user-facing changes?
   
   Yes. `EXTRACT` comparisons against a year whose January 1 is unrepresentable 
now
   return the correct rows instead of NULL. No API change.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to