Skip to content

feat: add math functions SIGN/CBRT/TRUNC#813

Merged
Leomrlin merged 3 commits into
apache:masterfrom
YinZiBenRun:feature/add-math-functions-sign-cbrt-trunc
Jul 24, 2026
Merged

feat: add math functions SIGN/CBRT/TRUNC#813
Leomrlin merged 3 commits into
apache:masterfrom
YinZiBenRun:feature/add-math-functions-sign-cbrt-trunc

Conversation

@YinZiBenRun

Copy link
Copy Markdown
Contributor

What & Why

The math folder udf/table/math/ currently has only E, Log2, and Round — noticeably thin. Adding SIGN (the sign of a
number), CBRT (cube root), and TRUNC (truncate to N decimals) is a quick win that meaningfully fills out the SQL
toolbox.

Resolves #790

Changes

New UDF classes

  • Sign.javasign(x) returns -1 for negative, 0 for zero, 1 for positive. Supports Double/Long/Integer input.
  • Cbrt.javacbrt(x) returns the cube root of x. Supports Double input.
  • Trunc.javatrunc(x, d) truncates x to d decimal places (not round). Supports Double/Long/Integer input with
    optional scale parameter.

Registration

  • Added Sign, Cbrt, Trunc to BuildInSqlFunctionTable.java
  • Added cbrt(Double) and trunc(Double, Integer) static methods to GeaFlowBuiltinFunctions.java (sign already
    existed)

Tests

  • Added MathUdfTest.java — unit tests for Sign, Cbrt, Trunc UDF classes
  • Added testCbrt() and testTrunc() to InternalFunctionsTest.java
  • All tests pass: 20/20

TRUNC vs ROUND — key distinction

trunc uses RoundingMode.DOWN while round uses RoundingMode.HALF_UP:

-- trunc: truncate (no rounding)
SELECT trunc(3.1465, 2)  →  3.14
SELECT trunc(-3.1465, 2) →  -3.14

-- round: round half up
SELECT round(3.1465, 2)  →  3.15
SELECT round(-3.1465, 2) →  -3.15

Edge cases covered

┌──────────┬─────────────────────────────┬────────┬─────────┐
│ Function │          Negative           │  Zero  │  Null   │
├──────────┼─────────────────────────────┼────────┼─────────┤
│ sign     │ ✅ -1                       │ ✅ 0   │ ✅ null │
├──────────┼─────────────────────────────┼────────┼─────────┤
│ cbrt     │ ✅ -2.0 (cbrt(-8))          │ ✅ 0.0 │ ✅ null │
├──────────┼─────────────────────────────┼────────┼─────────┤
│ trunc    │ ✅ -3.14 (trunc(-3.1465,2)) │ ✅ 0.0 │ ✅ null │
└──────────┴─────────────────────────────┴────────┴─────────┘

- sign(x): returns -1 for negative, 0 for zero, 1 for positive
- cbrt(x): returns the cube root of a number
- trunc(x, d): truncates x to d decimal places (not round)

Add UDF classes (Sign.java, Cbrt.java, Trunc.java) and register
them in BuildInSqlFunctionTable. Add cbrt/trunc static methods
to GeaFlowBuiltinFunctions. Add unit tests covering negative,
zero, and null edge cases.

Resolves apache#790

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@YinZiBenRun

Copy link
Copy Markdown
Contributor Author

#790

1 similar comment
@YinZiBenRun

Copy link
Copy Markdown
Contributor Author

#790

public class MathUdfTest {

@Test
public void testSign() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

These tests verify the Java methods directly, but they do not exercise SQL registration, overload resolution, type inference, or runtime invocation.
Could we add an end-to-end SQL test for SIGN/CBRT/TRUNC there?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

已添加端到端 SQL 测试,通过完整查询管线验证函数的注册、重载解析、类型推断和运行时调用。测试在 geaflow-dsl-runtime 模块:

  • MathSignCbrtTruncTest.java - 通过 QueryTester 驱动测试
  • query/math_sign_cbrt_trunc_001.sql - 覆盖 sign(Double/Long/Integer)、cbrt(Double)、trunc(Double 带/不带 scale、Long、Integer)
  • data/ + expect/ - 输入数据与期望输出

测试揭示了 Calcite 真实的重载解析行为:sign(bigint)/sign(int) 会被提升为 double,匹配 sign(Double) 重载(返回 1.0/-1.0);而
trunc(bigint)/trunc(int) 则精确匹配 Long/Integer 重载。期望输出里记录了这个差异。

已在本地验证通过(Tests run: 1, Failures: 0, Errors: 0)。

1+5 and others added 2 commits July 22, 2026 23:45
The existing MathUdfTest verifies the Java eval() methods directly but
does not exercise SQL registration, overload resolution, type inference,
or runtime invocation. Add an E2E SQL test via QueryTester that runs the
functions through the full query pipeline.

Covers:
- SQL registration in BuildInSqlFunctionTable (sign/cbrt/trunc)
- Overload resolution: sign(Double/Long/Integer), trunc(Double,Long/
  Integer, with and without scale)
- Type inference: each overload returns a distinct type, propagated
  un-cast to the sink schema
- Runtime invocation through the query engine
- Null-free boundary cases (zero, negative, positive, integer doubles)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Use a relative forward-slash sink path instead of the ${target}
placeholder. QueryTester rewrites ${target} to an absolute path that on
Windows contains backslashes; injected into a SQL string literal those
backslashes get escaped (\t -> tab, \U/\s/\g dropped) and the sink path
is corrupted, so the test fails on Windows. A relative path avoids the
rewrite and resolves to the same target/ directory checkSinkResult()
reads, on both Windows and Linux.

Also align the expected output with the real Calcite overload resolution
behaviour: sign(bigint)/sign(int) are promoted to double and match
sign(Double) (Long/Integer overloads not selected), while trunc(bigint)
and trunc(int) select the Long/Integer overloads. This type-inference
difference is exactly what an end-to-end SQL test surfaces.

Verified locally: Tests run: 1, Failures: 0, Errors: 0.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

@Leomrlin Leomrlin left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

@Leomrlin
Leomrlin merged commit 1fc3f0f into apache:master Jul 24, 2026
2 checks passed
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.

Add the math functions SIGN / CBRT / TRUNC

2 participants