Yaoxuan Wu created SPARK-60152:
----------------------------------

             Summary: ORC filter pushdown drops rows with a TIMESTAMP before 
1582-10-15
                 Key: SPARK-60152
                 URL: https://issues.apache.org/jira/browse/SPARK-60152
             Project: Spark
          Issue Type: Bug
          Components: SQL
    Affects Versions: 4.1.1, 4.2.0, 3.5.8, 4.0.0, 5.0.0
            Reporter: Yaoxuan Wu


{code:java}
import tempfile
from pyspark.sql import SparkSession
spark = SparkSession.builder.config("spark.sql.session.timeZone", 
"UTC").getOrCreate()
path = tempfile.mkdtemp()
spark.sql("SELECT TIMESTAMP'0001-01-02 00:00:00' AS 
t").write.mode("overwrite").orc(path)
spark.read.orc(path).createOrReplaceTempView("o")spark.sql("SELECT cast(t AS 
STRING) FROM o").collect()
# [Row(t='0001-01-02 00:00:00')]: the value round-tripsspark.sql("SELECT 
count(*) FROM o WHERE t = TIMESTAMP'0001-01-02 00:00:00'").first()[0]
# expected:    1
# Spark 4.2.0: 0
spark.sql("SELECT count(*) FROM o WHERE t <= TIMESTAMP'0001-01-02 
00:00:00'").first()[0]
# expected:    1
# Spark 4.2.0: 0
spark.sql("SELECT count(*) FROM o WHERE t >= TIMESTAMP'0001-01-02 
00:00:00'").first()[0]
# 1 {code}
With {{spark.sql.orc.filterPushdown=false}} all three return 1. Same on 3.5.8, 
4.0.0, 4.1.1, 4.2.0 and master, with the JVM time zone UTC or 
America/Los_Angeles, and with the vectorized reader on or off.
||Value||Predicates that return 0 rows||
|TIMESTAMP '0001-01-02 00:00:00'|{{{}={}}}, {{<=}}|
|TIMESTAMP '1500-01-01 00:00:00'|{{{}={}}}, {{>=}}|
|TIMESTAMP '1582-10-14 23:00:00'|{{=}}|
|TIMESTAMP '1582-10-16 00:00:00', DATE '0001-01-02', TIMESTAMP_NTZ '0001-01-02 
00:00:00'|none|

*Cause* (checked with the ORC Java API through py4j):
 * Spark writes TIMESTAMP values rebased to the hybrid Julian/Gregorian 
calendar ({{{}OrcSerializer{}}} uses {{{}DateTimeUtils.toJavaTimestamp{}}}), 
and builds the pushed literal the same way 
({{{}OrcFilters.castLiteralValue{}}}). The literal's {{getTime()}} equals the 
file statistics' {{{}getMinimum().getTime(){}}}.
 * ORC's row-group pruning, {{{}RecordReaderImpl.evaluatePredicateProto{}}}, 
reads the statistics with {{{}ColumnStatisticsImpl.deserialize(null, 
statsProto, writerUsedProlepticGregorian, true){}}}. The {{true}} converts 
min/max to the proleptic Gregorian calendar (2 days later in year 1, 9 days 
earlier in 1500). The hybrid literal is then outside [min, max].
 * Reading the file with ORC directly and the same SearchArgument: Spark's 
hybrid literal reads 0 rows, a proleptic literal ({{{}new Timestamp(micros / 
1000){}}}) reads 1 row. ORC 1.9.8 and 2.3.0 behave the same.
 * DATE works because ORC compares dates as local dates. TIMESTAMP_NTZ is 
pushed as a long.

A fix on the Spark side could push TIMESTAMP literals without the hybrid 
rebase, or skip pushdown for literals before 1582-10-15.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

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

Reply via email to