snmvaughan commented on code in PR #7171:
URL: https://github.com/apache/datafusion-comet/pull/7171#discussion_r4364406121


##########
docs/source/contributor-guide/expression-audits/conversion_funcs.md:
##########
@@ -27,6 +27,7 @@
 - Spark 3.5.8 (audited 2026-05-27): baseline. `Cast(child, dataType, 
timeZoneId, evalMode)`; eval modes are `LEGACY`, `ANSI`, `TRY`. The legacy 
`Cast.canCast` matrix and the `Cast.canAnsiCast` matrix decide acceptance per 
type pair. Comet routes via `CometCast` 
(`spark/src/main/scala/org/apache/comet/expressions/CometCast.scala`) using a 
per-source-type support matrix that returns `Compatible`, 
`Incompatible(reason)`, or `Unsupported(reason)`; literal children are 
short-circuited to `Compatible()` so `CometLiteral` validates them. The 
serialized `Cast` proto carries `datatype`, `evalMode`, `timezone` (default 
`UTC`), and `isSpark4Plus`; `allowIncompatible` is enforced only by the JVM 
planner and is not sent to the native cast kernel. The native side 
(`native/spark-expr/src/conversion_funcs/cast.rs`) implements explicit 
per-eval-mode branches for narrowing numeric casts that match Spark's overflow 
exceptions, and falls through to DataFusion `cast_with_options(safe = !ANSI)` 
for the r
 est.
 - Spark 4.0.1 (audited 2026-05-27): `VariantType` added; `StringType` literals 
replaced with `_: StringType` to accommodate collated strings. `(TimestampType, 
ByteType|ShortType|IntegerType)` added to `canAnsiCast`. `NullIntolerant` -> 
`nullIntolerant: Boolean` refactor. New `ToPrettyString.BinaryFormatter` 
semantics for `Binary -> String` are replicated natively via 
`spark_binary_formatter`. Numeric-to-numeric matrix unchanged.
 - Spark 4.1.1 (audited 2026-05-27): `TimeType` added; many `TimeType` arms in 
`canCast`/`canAnsiCast`. Geospatial `GeographyType` / `GeometryType` types 
added with their own conversion rules. Numeric-to-numeric matrix unchanged.
+- Spark 4.0.5, 4.1.4 and 4.2.1 (release candidates; in 4.0.5-rc3, 4.1.4-rc4 
and 4.2.1-rc3): `Decimal.fromString` and `fromStringANSI` no longer count 
integral digits for zero (SPARK-60118), so a zero with a large exponent such as 
`'0e39'` casts to 0 instead of NULL (or `NUMERIC_OUT_OF_SUPPORTED_RANGE` under 
ANSI). `CometCast` sets the `decimal_zero_any_exponent` cast option from 
`SparkFixes.castsZeroWithAnyExponentToDecimal`, and `parse_string_to_decimal` 
skips the zero limit when it is set.

Review Comment:
   Thanks, I checked: the SPARK-60119 back-ports are in 4.0.5-rc3, 4.1.4-rc4 
and 4.2.1-rc3. When the scale change is over 38, `changePrecision` now rounds a 
value below 0.01 ulp of the target scale as 0.01 ulp of the same sign, so 
`CAST('1e-2147483647' AS DECIMAL(10,2))` gives `0.00`, as the native cast 
already does. In 4c92600 the audit entry and the two `string.rs` comments say 
that the positive-scale case of #6966 applies only before those releases.
   
   Its negative-scale case still differs, though. With 
`allowNegativeScaleOfDecimal=true`, `'1e-2147483647'` to `DECIMAL(10,-2)` now 
gives 0 in Spark, while the native cast raises `CAST_INVALID_INPUT` under ANSI 
and returns NULL otherwise. So `(ansi) cast string to negative-scale decimal 
fails when rescaling overflows an int` will fail once Comet builds against 
these releases. I'd like to handle that separately, gated on SPARK-60119 like 
these two, so this PR stays on SPARK-58821 and SPARK-60118.
   



##########
native/spark-expr/src/comet_scalar_funcs.rs:
##########
@@ -133,6 +133,13 @@ pub fn create_comet_physical_fun_with_eval_mode(
         "spark_sequence" => {
             make_comet_scalar_udf!("spark_sequence", spark_sequence, data_type)
         }
+        "spark_sequence_recomputed" => {

Review Comment:
   Thanks for the heads-up. Both names already share one kernel, 
`sequence(args, data_type, OverflowedLength)`, so the merge is small: whichever 
PR lands second gives `SparkSequence` the overflow mode as a field and 
constructs it for both names. If #6948 lands first I'll rebase this onto it 
that way, and otherwise I'll point #6948 here.
   



##########
spark/src/main/scala/org/apache/comet/serde/SparkFixes.scala:
##########
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.comet.serde
+
+import org.apache.spark.sql.comet.util.Utils
+
+/**
+ * Spark fixes that change a result Comet reproduces natively, and the Spark 
releases that carry
+ * them. The fixes leave nothing in the plan for Comet to detect, so the 
checks go by the version.

Review Comment:
   Added in 4c92600, on the cast and `sequence` pages rather than 
`spark-versions.md`, so the note sits next to the behavior as it does in 
`floating-point.md`. The cast page's "String to Decimal" section and 
`CometSequence.getCompatibleNotes`, which GenerateDocs puts on the array page, 
say that Comet chooses by the Spark version number. They also say what a vendor 
build that reports an older version but includes the fix gets instead: NULL for 
`'0e39'` (or an error under ANSI), and the internal error for the overflowing 
`sequence`, where Spark returns values.
   



##########
native/spark-expr/src/array_funcs/sequence.rs:
##########
@@ -425,6 +474,59 @@ mod tests {
         assert!(err.contains("Unreachable code reached."), "{err}");
     }
 
+    /// SPARK-58821's cases: `stop - start` overflows a long but a large step 
keeps the exact
+    /// length small, so `spark_sequence_recomputed` returns the elements 
instead of the internal
+    /// error. Overflows whose length really is too large still raise the 
limit error.
+    #[test]
+    fn recomputed_length_after_overflow() {
+        let args = vec![
+            ColumnarValue::Array(Arc::new(Int64Array::from(vec![
+                Some(i64::MIN),
+                Some(i64::MIN),
+                Some(i64::MAX),
+            ]))),
+            ColumnarValue::Array(Arc::new(Int64Array::from(vec![
+                Some(i64::MAX),
+                Some(0),
+                Some(i64::MIN),
+            ]))),
+            ColumnarValue::Array(Arc::new(Int64Array::from(vec![
+                Some(i64::MAX),
+                Some(4611686018427387904),
+                Some(-i64::MAX),
+            ]))),
+        ];
+        let ColumnarValue::Array(arr) =
+            spark_sequence_recomputed(&args, 
&list_of(DataType::Int64)).unwrap()
+        else {
+            unreachable!("array inputs produce an array")
+        };
+        let list = as_primitive_list(&arr);
+        assert_eq!(row_values(&list, 0), vec![i64::MIN, -1, i64::MAX - 1]);
+        assert_eq!(
+            row_values(&list, 1),
+            vec![i64::MIN, -4611686018427387904, 0]
+        );
+        assert_eq!(row_values(&list, 2), vec![i64::MAX, 0, -i64::MAX]);
+
+        // The released behaviour, on the same rows, is the internal error.

Review Comment:
   Done in 4c92600. `recomputed_length_after_overflow` keeps only the element 
checks. A new `SparkFixesSuite` holds one version table for both fixes and 
`CometSequence.nativeFunction`, and the two suites keep only their `convert` 
checks, which depend on the running Spark version. The new suite is in both PR 
build workflows.
   



-- 
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