Skip to content

fix: query tolerance= in SQL file tests now also asserts Comet native execution#3797

Open
andygrove wants to merge 5 commits intoapache:mainfrom
andygrove:fix-sql-test-tolerance-coverage
Open

fix: query tolerance= in SQL file tests now also asserts Comet native execution#3797
andygrove wants to merge 5 commits intoapache:mainfrom
andygrove:fix-sql-test-tolerance-coverage

Conversation

@andygrove
Copy link
Copy Markdown
Member

@andygrove andygrove commented Mar 25, 2026

Which issue does this PR close?

Closes #.

Rationale for this change

CometSqlFileTestSuite supports a query tolerance=<value> directive for floating-point queries where small numeric differences are expected. However, the WithTolerance mode called checkSparkAnswerWithTolerance, which hardcodes assertCometNative = false. This meant that all 50+ queries using this directive (covering sin, cos, tan, asin, acos, atan, atan2, sinh, cosh, tanh, exp, expm1, log, log2, log10, pow, sqrt, cot, stddev, variance, avg, sum, corr, covariance) were silently skipping the assertion that Comet actually executed the expression natively.

What changes are included in this PR?

  • Add checkSparkAnswerAndOperatorWithTolerance to CometTestBase, which combines tolerance-based result comparison with assertCometNative = true.
  • Change the WithTolerance case in CometSqlFileTestSuite to call the new method instead of checkSparkAnswerWithTolerance.
  • Fix tan.sql to add allowIncompatible config so the test runs natively.
  • Add native support for Spark's Logarithm expression (two-arg log(base, value)), mapping it to DataFusion's log(base, value) function.

How are these changes tested?

The existing SQL file tests for all affected math and aggregate expressions now enforce native execution as part of their normal CI run.

… execution

The WithTolerance mode in CometSqlFileTestSuite called
checkSparkAnswerWithTolerance, which hardcodes assertCometNative=false.
This meant that all 50+ SQL test queries using 'query tolerance=...'
(sin, cos, tan, stddev, avg, etc.) silently skipped the check that
Comet actually executed the expression natively.

Add checkSparkAnswerAndOperatorWithTolerance that combines tolerance-
based result comparison with the native operator assertion, and use it
in the WithTolerance case.
@andygrove andygrove marked this pull request as draft March 25, 2026 23:57
Maps Spark's Logarithm expression to DataFusion's log(base, value) function.
Applies nullIfNegative to both base and value to match Spark's behavior of
returning null when the result would be NaN (inputs <= 0).
@andygrove andygrove marked this pull request as ready for review March 26, 2026 05:01
@andygrove andygrove requested a review from martin-g March 28, 2026 13:49
expr: Logarithm,
inputs: Seq[Attribute],
binding: Boolean): Option[ExprOuterClass.Expr] = {
// Spark's Logarithm(left=base, right=value) returns null when result is NaN,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spark 4.0.2:

spark-sql (default)> SELECT log(1, 1);
NaN
Time taken: 0.072 seconds, Fetched 1 row(s)

The result is not NULL but NaN.

inputs: Seq[Attribute],
binding: Boolean): Option[ExprOuterClass.Expr] = {
// Spark's Logarithm(left=base, right=value) returns null when result is NaN,
// which happens when base <= 0 or value <= 0. Apply nullIfNegative to both.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both base<=0 or value<=0 lead to NULL results in Spark!

But value=0 actually leads to -Infinity, not NaN, so the comment is not accurate.


/**
* Check that the query returns the correct results when Comet is enabled and that Comet
* replaced all possible operators. Use the provided `tol` when comparing floating-point
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tol - the name of the parameter is absTol

protected def checkSparkAnswerAndOperatorWithTolerance(
query: String,
absTol: Double = 1e-6): (SparkPlan, SparkPlan) = {
internalCheckSparkAnswer(sql(query), assertCometNative = true, withTol = Some(absTol))
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another option is to delegate to checkSparkAnswerAndOperatorWithTol(=> DataFrame, Double) (line 252).
You could even overload the method name - checkSparkAnswerAndOperatorWithTol. Scala allows that.

@martin-g
Copy link
Copy Markdown
Member

Neither log.sql, nor log10.sql nor log2.sql have any tests with <=0 values for the base and/or the value.

- Fix inaccurate comment on CometLogarithm (base/value <= 0 returns
  null, not "returns null when result is NaN")
- Fix doc reference tol -> absTol in checkSparkAnswerAndOperatorWithTolerance
- Delegate to existing checkSparkAnswerAndOperatorWithTol method
- Add <= 0 edge case test data to log.sql, log10.sql, log2.sql
- Add custom spark_log Rust UDF to handle <= 0 -> null internally,
  fixing DataFusion's broken null propagation for two-arg log
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants