You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
ExtractANSIIntervalDays and the other interval field extractors have no serde, so date + <day interval column> and extract of an interval fall back #6193
Spark lowers extract(field FROM interval) and date_part('field', interval) to one of twelve ExtractIntervalPart subclasses. The ANSI types get ExtractANSIInterval{Years,Months,Days,Hours,Minutes,Seconds} and CalendarInterval gets ExtractInterval{Years,Months,Days,Hours,Minutes,Seconds}. None of them has a serde, so a projection that uses one falls back to Spark.
ExtractANSIIntervalDays also sits under ordinary date arithmetic. Spark rewrites date + <DAY-precision interval> to DateAdd(date, ExtractANSIIntervalDays(interval)), and the subtract form to DateAdd(date, UnaryMinus(ExtractANSIIntervalDays(interval))). That happens in Analyzer.ResolveBinaryArithmetic on 3.4 and 3.5, and in BinaryArithmeticWithDatetimeResolver on 4.0 and later. DateAdd is native, but its argument is not. A literal such as date + INTERVAL '30' DAY is unaffected in practice, because ConstantFolding reduces ExtractANSIIntervalDays(literal) to an int. An interval column is affected, and the commonest one is date subtraction itself: d1 - d2 returns INTERVAL DAY in the default interval mode, so d + (d1 - d2) falls back.
It also limits testing. CometSqlFileTestSuite excludes ConstantFolding, so inside a SQL fixture even date + INTERVAL '1' DAY falls back, and that spelling can't be pinned by a fixture until this is fixed.
Reproduced on main at dd68a531c, default Spark 4.1 profile:
CREATETABLEt (d date, d1 date, d2 date, n int) USING parquet;
INSERT INTO t VALUES (date'2024-01-31', date'2024-03-15', date'2024-01-01', 5), (NULL, NULL, NULL, NULL);
SELECT d + (d1 - d2) FROM t; -- extractansiintervaldays is not supportedSELECT d - (d1 - d2) FROM t; -- extractansiintervaldays is not supportedSELECT extract(DAY FROM make_dt_interval(n, 1, 2, 3)) FROM t; -- extractansiintervaldays is not supportedSELECT date_part('HOUR', make_dt_interval(n, 1, 2, 3)) FROM t; -- extractansiintervalhours is not supportedSELECT extract(YEAR FROM make_ym_interval(n, 1)) FROM t; -- extractansiintervalyears is not supportedSELECT extract(DAY FROM make_interval(0, 0, 0, n)) FROM t; -- extractintervaldays is not supported
Each comment is the fallback reason Comet reports. The first two queries also need #5864, which adds the SubtractDates serde. On main the extractor is just the first unsupported node the serde reaches.
Describe the potential solution
All twelve are UnaryExpressions whose doGenCode is a single IntervalUtils.getX(child) call, returning IntegerType, ByteType or DecimalType(8, 6). The codegen dispatcher already reads all three interval types and writes all three result types, so each one needs only a CometCodegenDispatch registration in temporalExpressions, like CometMakeDTInterval. The classes and their result types are the same on 3.4.3, 3.5.9, 4.0.4, 4.1.3 and 4.2.0, so no shim is needed.
I checked that locally on #5864's head with the 4.1 profile. With all twelve registered as new CometCodegenDispatch[...], expect_dispatch passes and the answers match Spark for d + (d1 - d2), d - (d1 - d2), d +/- INTERVAL '<n>' DAY inside the harness, and extract of every field of all three interval types, over Parquet data with negative and NULL values.
The PR for this should:
Register the twelve extractors.
Add SQL fixtures with expect_dispatch(...) for each field, derived from Parquet columns. Cover negative values, NULLs, both the extract and date_part spellings, and date +/- (d1 - d2) and date +/- INTERVAL '<n>' DAY for the DateAdd rewrite.
Part of #5061, whose table of expressions not yet wired lists "extract / date_part of interval fields (ExtractANSIInterval*, ExtractInterval*)" as needing an issue. Found while reviewing #5864.
What is the problem the feature request solves?
Spark lowers
extract(field FROM interval)anddate_part('field', interval)to one of twelveExtractIntervalPartsubclasses. The ANSI types getExtractANSIInterval{Years,Months,Days,Hours,Minutes,Seconds}andCalendarIntervalgetsExtractInterval{Years,Months,Days,Hours,Minutes,Seconds}. None of them has a serde, so a projection that uses one falls back to Spark.ExtractANSIIntervalDaysalso sits under ordinary date arithmetic. Spark rewritesdate + <DAY-precision interval>toDateAdd(date, ExtractANSIIntervalDays(interval)), and the subtract form toDateAdd(date, UnaryMinus(ExtractANSIIntervalDays(interval))). That happens inAnalyzer.ResolveBinaryArithmeticon 3.4 and 3.5, and inBinaryArithmeticWithDatetimeResolveron 4.0 and later.DateAddis native, but its argument is not. A literal such asdate + INTERVAL '30' DAYis unaffected in practice, becauseConstantFoldingreducesExtractANSIIntervalDays(literal)to an int. An interval column is affected, and the commonest one is date subtraction itself:d1 - d2returnsINTERVAL DAYin the default interval mode, sod + (d1 - d2)falls back.It also limits testing.
CometSqlFileTestSuiteexcludesConstantFolding, so inside a SQL fixture evendate + INTERVAL '1' DAYfalls back, and that spelling can't be pinned by a fixture until this is fixed.Reproduced on
mainatdd68a531c, default Spark 4.1 profile:Each comment is the fallback reason Comet reports. The first two queries also need #5864, which adds the
SubtractDatesserde. Onmainthe extractor is just the first unsupported node the serde reaches.Describe the potential solution
All twelve are
UnaryExpressions whosedoGenCodeis a singleIntervalUtils.getX(child)call, returningIntegerType,ByteTypeorDecimalType(8, 6). The codegen dispatcher already reads all three interval types and writes all three result types, so each one needs only aCometCodegenDispatchregistration intemporalExpressions, likeCometMakeDTInterval. The classes and their result types are the same on 3.4.3, 3.5.9, 4.0.4, 4.1.3 and 4.2.0, so no shim is needed.I checked that locally on #5864's head with the 4.1 profile. With all twelve registered as
new CometCodegenDispatch[...],expect_dispatchpasses and the answers match Spark ford + (d1 - d2),d - (d1 - d2),d +/- INTERVAL '<n>' DAYinside the harness, andextractof every field of all three interval types, over Parquet data with negative and NULL values.The PR for this should:
expect_dispatch(...)for each field, derived from Parquet columns. Cover negative values, NULLs, both theextractanddate_partspellings, anddate +/- (d1 - d2)anddate +/- INTERVAL '<n>' DAYfor theDateAddrewrite.expressions.md. The+and-notes that feat: route date and timestamp interval arithmetic through codegen dispatch #5864 adds say a DAY-precision interval column on a date falls back becauseExtractANSIIntervalDayshas no serde. Theextract,date_partanddatepartrows carry no interval caveat at all today.Additional context
Part of #5061, whose table of expressions not yet wired lists "
extract/date_partof interval fields (ExtractANSIInterval*,ExtractInterval*)" as needing an issue. Found while reviewing #5864.