andygrove opened a new issue, #6620:
URL: https://github.com/apache/datafusion-comet/issues/6620
Part of #6615.
## What / Why
This issue moves math and arithmetic coverage to Comet SQL tests under
`sql-tests/expressions/math/` (plus `misc/width_bucket.sql`). The sources are
`CometMathExpressionSuite`, the math and arithmetic tests in
`CometExpressionSuite`, and a note on `CometFuzzMathSuite`. Decimal arithmetic
has its own issue. Static analysis on `main` at 3bc2faa934 found the following:
| Suite | Covered | Convert | Blocked | Split | Keep | Total |
|---|---|---|---|---|---|---|
| `CometExpressionSuite` | 6 | 19 | 5 | 0 | 1 | 31 |
| `CometMathExpressionSuite` | 1 | 6 | 0 | 0 | 0 | 7 |
| `CometFuzzMathSuite` | 0 | 0 | 0 | 0 | 2 | 2 |
| **Total** | **7** | **25** | **5** | **0** | **3** | **40** |
Problems with the existing fixtures that this issue has to fix:
- **NaN results are never compared.** Every per-function fixture (`acos`,
`asin`, `atan`, `atan2`, `cos`, `cosh`, `cot`, `exp`, `expm1`, `log`, `log10`,
`log2`, `sin`, `sinh`, `sqrt`, `tan`, `tanh`) runs its NaN-producing inputs
only under `query tolerance=`. Examples are NaN input, `sqrt(-1.0)`, `acos(2)`
and `sin(Infinity)`. That check skips any row where either side is NaN and
accepts +Infinity against -Infinity (#6616). The Scala math tests share that
helper and that blind spot.
- Keep `tolerance=` only for finite, non-zero results.
- Move every input whose result is NaN, ±Infinity or a signed zero into a
plain `query`.
- **Missing edge values.** No fixture has Double Min, Max or MinPositive
values. `abs.sql` has no integral MIN, which is the non-ANSI wrap case where
`abs(MIN) = MIN`, and no -0.0.
- **The `try_*` arithmetic functions have no fixture.** The Scala `try_add`,
`try_subtract` and `try_multiply` tests are all-literal, so Spark
constant-folds them and they never reached Comet. In a fixture they test the
TRY kernels for the first time.
## Work
Line numbers refer to `CometExpressionSuite` unless marked
`CometMathExpressionSuite`.
**Existing fixtures to extend**
- `arithmetic.sql`
- L1663 (divide by zero, ANSI off): double divisor columns holding `0.0`
and `double('-0.0')` under `/` and `%`, int `/` and `%` by a literal `0`, and
double `% 0.0`.
- L2217: negation of tinyint, smallint, bigint, float, double and
decimal(38,18). Only int is covered today.
- L2228: `-f` and `-d` over NaN, ±Inf, ±0.0, MinPositive, Max, Min and
NULL, as a plain query.
- L2259: `fa % fb` and `da % db`. There is no non-ANSI float remainder in
any fixture today.
- L3490: non-ANSI `a div b` with a zero divisor. The ANSI half is already
in `arithmetic_ansi.sql`.
- L2793 (non-ANSI half): `SELECT a, -a` over Max and Min of int, bigint,
smallint and tinyint.
- `abs.sql` (`CometMathExpressionSuite` L34, L45)
- Add tinyint, smallint and decimal(10,2) columns, the MIN of every
integral type, float/double ±Infinity, NaN and Min/Max.
- Add `float('-0.0')` and `double('-0.0')`.
- `abs_ansi.sql` / `abs_ansi_spark42.sql` (`CometMathExpressionSuite` L56)
- Add the non-throwing half that the Scala test compares: a plain query
over float, double, decimal(10,2) and non-MIN integral values.
- The Scala regex `.+[ARITHMETIC_OVERFLOW].+overflow...` uses a character
class, not the literal error class, so it is weaker than it reads.
- `round.sql` / `round_ansi.sql` (L3521, L3556)
- An int `2147483647` input at scales -1000, -100, -20, -19, -10, -1, 0,
1, 10, 100 and 1000. In ANSI mode, scale -1 is
`expect_error(ARITHMETIC_OVERFLOW)`.
- Long Max and Min inputs at scales -18, -38 and -39.
- `ceil.sql` / `floor.sql` (L1983)
- A bigint input and a decimal(21,1) column.
- decimal(20,0) and decimal(38,18) casts of ±0.5, ±1.2 and ±0.0.
- decimal(5,2) values 123.45, 125.00 and -129.99.
- `signum.sql` (L1975): Double Min, Max and MinPositive.
- `expm1.sql` (L1979): `double('-0.0')`, NaN and ±Inf in a plain query, plus
Max, Min and MinPositive.
- The 16 per-function fixtures (L1880): add Double Min, Max and MinPositive
to each, plus whichever of -0.0, ±Inf and ±1 it lacks. Restructure the queries
as described above.
- `misc/width_bucket.sql` (`CometMathExpressionSuite` L97, L110, L127)
- A Parquet table with value, min, max and bucket-count columns.
- Rows: the four from L97; value = max with normal and reversed bounds;
min = max; zero buckets; NaN as value, as min and as max.
- No version gate is needed; see the notes below.
**New fixtures**
- `try_arithmetic.sql` (L803, L819, L835, L851, L870)
- `try_add`, `try_subtract`, `try_multiply` and `try_divide` over int and
bigint boundary operands, as columns and as literals, plus NULL.
- `try_divide` also needs a zero divisor and a decimal overflow.
- `remainder.sql` + `remainder_ansi.sql` (L2634)
- The int/float/decimal(18,4) remainder table and the ten-expression `%` /
`mod()` projection, including `Int.MinValue % -1`.
- For ANSI, use version-paired files (`MinSparkVersion: 4.1` expecting
`REMAINDER_BY_ZERO`, `MaxSparkVersion: 4.0` expecting `DIVIDE_BY_ZERO`), or
`expect_error(BY_ZERO)`.
- `unary_minus_ansi.sql` (`MinSparkVersion: 4.0`, `MaxSparkVersion: 4.1`)
and `unary_minus_ansi_spark3.sql` (`MaxSparkVersion: 3.5`) (L2793)
- Short and byte negation overflow, plus scalar `-(cast(<max|min> as
<type>))`.
- On 3.x, Spark says "caused overflow" while Comet says "short/byte
overflow", so the only common substring is `overflow`.
- `deep_arithmetic_chains.sql` (L3884)
- 200-term `+` and `*` chains. They must not overflow the protobuf
recursion limit.
- SQL's left recursion yields left-deep trees, as the Scala test builds.
**Blocked on #6617 (error parity)**
- **L3413, L3429, L3444 (ANSI add, subtract, multiply).** These need
`MaxSparkVersion: 4.1` files (#4967).
- `arithmetic_ansi.sql` already has `expect_error(ARITHMETIC_OVERFLOW)`
for int and long.
- That substring also matches `BINARY_ARITHMETIC_OVERFLOW`, so it cannot
catch the error-class divergence these tests guard against.
- **L3460 (int `/` by zero) and L3475 (float `/` by zero).** The float case
isn't covered even weakly: the fixture's float section tests only `%`. Add an
interim `expect_error(DIVIDE_BY_ZERO)` now.
## Stays in Scala
- **L3596**: a negative-scale decimal built from a DataFrame cast. SQL
cannot declare negative-scale decimals.
- **`CometFuzzMathSuite`** (2 tests × 5 ops × 3 variants): the fuzz layer
for mixed int/bigint and decimal arithmetic with extreme values. Keep it. If it
is ever dropped, `arithmetic.sql` needs a curated table of Int/Long extremes
first.
## Notes on the Scala tests
- **The three `CometMathExpressionSuite` width_bucket tests are vacuous.**
- Their views come from `createDataFrame(Seq(...))`, a `LocalRelation`,
and `ConvertToLocalRelation` is active in `CometTestBase`. So Spark folds the
projection in both runs.
- Their `assume(isSpark35Plus)` is stale too: `width_bucket.sql` runs on
3.4.
- **`try_integral_divide overflow cases` (L870)** calls only `try_divide`,
and its -128 and -32768 are INT literals.
- **Stale comments and configs in the fixtures.**
- `arithmetic_ansi.sql` says its all-literal cases are folded before
reaching Comet. They are not, because the suite excludes ConstantFolding.
- `tan.sql`'s `Tan.allowIncompatible=true` does nothing, because Tan is a
plain `CometScalarFunction` and always Compatible.
## Done when
- Every test in the table below is accounted for. Either a fixture covers it
(the same inputs, configs and assertion strength, or stronger), the fixture
that already covers it is cited, or it stays in Scala for the reason given
above.
- Each converted Scala test is deleted in the PR that adds its coverage. A
suite left empty is deleted and removed from the suite lists in
`.github/workflows/pr_build_linux.yml` and `pr_build_macos.yml`.
- The new and changed fixtures pass on every Spark profile. Apply
`run-all-spark-profiles`, because pull requests run only the default profile.
<details><summary>Every Scala test in scope, with its verdict and target
fixture</summary>
| Suite | Line | Test | Verdict | Target |
|---|---|---|---|---|
| `CometExpressionSuite` | 619 | Integral Division Overflow Handling Matches
Spark Behavior | covered | math/arithmetic.sql |
| `CometExpressionSuite` | 803 | try_add | convert | math/try_arithmetic.sql
(new) |
| `CometExpressionSuite` | 819 | try_subtract | convert |
math/try_arithmetic.sql (new) |
| `CometExpressionSuite` | 835 | try_multiply | convert |
math/try_arithmetic.sql (new) |
| `CometExpressionSuite` | 851 | try_divide | convert |
math/try_arithmetic.sql (new) |
| `CometExpressionSuite` | 870 | try_integral_divide overflow cases |
convert | math/try_arithmetic.sql (new) |
| `CometExpressionSuite` | 885 | dictionary arithmetic | covered |
math/arithmetic.sql |
| `CometExpressionSuite` | 894 | dictionary arithmetic with scalar | covered
| math/arithmetic.sql |
| `CometExpressionSuite` | 1653 | add overflow (ANSI disable) | covered |
math/arithmetic.sql |
| `CometExpressionSuite` | 1663 | divide by zero (ANSI disable) | convert |
math/arithmetic.sql |
| `CometExpressionSuite` | 1880 | various math scalar functions | convert |
math/{acos,asin,atan,cos,cosh,exp,log,log10,log2,sin,sinh,sqrt,tan,tanh,cot,atan2}.sql
|
| `CometExpressionSuite` | 1975 | signum | convert | math/signum.sql |
| `CometExpressionSuite` | 1979 | expm1 | convert | math/expm1.sql |
| `CometExpressionSuite` | 1983 | ceil and floor | convert | math/ceil.sql +
math/floor.sql |
| `CometExpressionSuite` | 2204 | negative | covered | math/arithmetic.sql |
| `CometExpressionSuite` | 2217 | unary minus across numeric types | convert
| math/arithmetic.sql |
| `CometExpressionSuite` | 2228 | unary minus on float/double special values
and nulls | convert | math/arithmetic.sql |
| `CometExpressionSuite` | 2259 | basic arithmetic | convert |
math/arithmetic.sql |
| `CometExpressionSuite` | 2634 | remainder function | convert |
math/remainder.sql (new) + math/remainder_ansi.sql (new; or extend
math/arithmetic_ansi.sql) |
| `CometExpressionSuite` | 2793 | unary negative integer overflow test |
convert | math/arithmetic.sql + math/unary_minus_ansi.sql (new: MinSparkVersion
4.0, MaxSparkVersion 4.1) + math/unary_minus_ansi_spark3.sql (new:
MaxSparkVersion 3.5) |
| `CometExpressionSuite` | 2923 | isnan | covered | math/isnan.sql |
| `CometExpressionSuite` | 3413 | ANSI support for add | blocked: #6617 |
math/arithmetic_ansi.sql |
| `CometExpressionSuite` | 3429 | ANSI support for subtract | blocked: #6617
| math/arithmetic_ansi.sql |
| `CometExpressionSuite` | 3444 | ANSI support for multiply | blocked: #6617
| math/arithmetic_ansi.sql |
| `CometExpressionSuite` | 3460 | ANSI support for divide (division by zero)
| blocked: #6617 | math/arithmetic_ansi.sql |
| `CometExpressionSuite` | 3475 | ANSI support for divide (division by zero)
float division | blocked: #6617 | math/arithmetic_ansi.sql |
| `CometExpressionSuite` | 3490 | ANSI support for integral divide (division
by zero) | convert | math/arithmetic.sql |
| `CometExpressionSuite` | 3521 | ANSI support for round function | convert
| math/round.sql + math/round_ansi.sql |
| `CometExpressionSuite` | 3556 | ANSI support for round function with
negative scale overflow on long | convert | math/round.sql +
math/round_ansi.sql |
| `CometExpressionSuite` | 3596 | round on negative-scale decimal | keep | |
| `CometExpressionSuite` | 3884 | deep integral Add/Multiply chains do not
overflow the protobuf recursion limit | convert |
math/deep_arithmetic_chains.sql (new) |
| `CometFuzzMathSuite` | 35 | integer math: $op (instances: + - * / div,
each x3 shuffle/nativeC2R variants = 15 runtime tests) | keep | |
| `CometFuzzMathSuite` | 57 | decimal math: $op (instances: + - * / div,
each x3 shuffle/nativeC2R variants = 15 runtime tests) | keep | |
| `CometMathExpressionSuite` | 34 | abs | convert | math/abs.sql |
| `CometMathExpressionSuite` | 45 | abs - negative zero | convert |
math/abs.sql |
| `CometMathExpressionSuite` | 56 | abs (ANSI mode) | convert |
math/abs_ansi.sql + math/abs_ansi_spark42.sql |
| `CometMathExpressionSuite` | 97 | width_bucket | convert |
misc/width_bucket.sql |
| `CometMathExpressionSuite` | 110 | width_bucket - edge cases | convert |
misc/width_bucket.sql |
| `CometMathExpressionSuite` | 127 | width_bucket - NaN values | convert |
misc/width_bucket.sql |
| `CometMathExpressionSuite` | 139 | width_bucket - with range data |
covered | misc/width_bucket.sql |
</details>
--
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]