From f1a01a9166a9a3eac6bd992c2b48f2eee56c00b3 Mon Sep 17 00:00:00 2001 From: Matthias Schur <107557548+MattSchur@users.noreply.github.com> Date: Fri, 21 Nov 2025 13:26:29 +0100 Subject: [PATCH 1/8] Java: Numeric Type Promotion --- java/cds-data.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/java/cds-data.md b/java/cds-data.md index 068f3d1bd..dae2b3caf 100644 --- a/java/cds-data.md +++ b/java/cds-data.md @@ -71,6 +71,22 @@ The framework isn't responsible for closing the stream when writing to the datab These types are used for the values of CDS elements with primitive type. In the [Model Reflection API](./reflection-api), they're represented by the enum [CdsBaseType](https://javadoc.io/doc/com.sap.cds/cds4j-api/latest/com/sap/cds/reflect/CdsBaseType.html). +### Numeric Type Promotion in Expressions { #numeric-promotion } + +To have a consistent behavior across different databases, numeric type promotion in arithmetic expressions is handled by the CAP Java runtime. Arithmetic expressions promote numeric types according to the following precedence: + +**Type Precedence (highest to lowest):** +`DOUBLE` (binary64), `HANA_REAL` (binary32), `DECIMAL` (base 10), `INT64`, `INT32`, `INT16`, `UINT8` + +- For addition, subtraction, and multiplication, the result type is the one with highest precedence among the operands. +- For division: + - If any operand is a binary floating-point type (`DOUBLE`, `HANA_REAL`), the result type is `DOUBLE` (binary64). + - Otherwise, the result type is `DECIMAL` (base 10), which provides higher accuracy for decimal fractions. + +::: tip +Use `type(CdsBaseType)` to explicitly set the result type if needed. +::: + ## Structured Data In CDS, structured data is used as payload of *Insert*, *Update*, and *Upsert* statements. Also the query result of *Select* may be structured. From 2c001ffa6ae670d615e99fc5443b2487f967ef03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrian=20G=C3=B6rler?= Date: Mon, 24 Nov 2025 13:55:31 +0100 Subject: [PATCH 2/8] Update java/cds-data.md Co-authored-by: Matthias Schur <107557548+MattSchur@users.noreply.github.com> --- java/cds-data.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java/cds-data.md b/java/cds-data.md index dae2b3caf..96d1f3e0d 100644 --- a/java/cds-data.md +++ b/java/cds-data.md @@ -80,8 +80,8 @@ To have a consistent behavior across different databases, numeric type promotion - For addition, subtraction, and multiplication, the result type is the one with highest precedence among the operands. - For division: - - If any operand is a binary floating-point type (`DOUBLE`, `HANA_REAL`), the result type is `DOUBLE` (binary64). - - Otherwise, the result type is `DECIMAL` (base 10), which provides higher accuracy for decimal fractions. + - If any operand is a binary floating-point type (`DOUBLE`, `HANA_REAL`), the result type is `DOUBLE`. + - Otherwise, the result type is `DECIMAL`, which provides higher accuracy for decimal fractions. ::: tip Use `type(CdsBaseType)` to explicitly set the result type if needed. From 31cff7a1ed8419a0d48affcfe38add5d936d849a Mon Sep 17 00:00:00 2001 From: Matthias Schur <107557548+MattSchur@users.noreply.github.com> Date: Mon, 24 Nov 2025 17:04:30 +0100 Subject: [PATCH 3/8] Add Numeric Standard Functions --- java/cds-data.md | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/java/cds-data.md b/java/cds-data.md index 96d1f3e0d..a043a5124 100644 --- a/java/cds-data.md +++ b/java/cds-data.md @@ -71,9 +71,17 @@ The framework isn't responsible for closing the stream when writing to the datab These types are used for the values of CDS elements with primitive type. In the [Model Reflection API](./reflection-api), they're represented by the enum [CdsBaseType](https://javadoc.io/doc/com.sap.cds/cds4j-api/latest/com/sap/cds/reflect/CdsBaseType.html). -### Numeric Type Promotion in Expressions { #numeric-promotion } +### Numeric Type Determination { #type-determination } -To have a consistent behavior across different databases, numeric type promotion in arithmetic expressions is handled by the CAP Java runtime. Arithmetic expressions promote numeric types according to the following precedence: +To have a consistent behavior across different databases, the CAP Java runtime applies numeric type determination in arithmetic expressions and numeric standard functions according to the following rules. + +::: tip +Use `type(CdsBaseType)` to explicitly set the result type if needed. +::: + +#### Arithmetic Expressions { #numeric-promotion } + +Arithmetic expressions promote numeric types according to the following precedence: **Type Precedence (highest to lowest):** `DOUBLE` (binary64), `HANA_REAL` (binary32), `DECIMAL` (base 10), `INT64`, `INT32`, `INT16`, `UINT8` @@ -83,9 +91,15 @@ To have a consistent behavior across different databases, numeric type promotion - If any operand is a binary floating-point type (`DOUBLE`, `HANA_REAL`), the result type is `DOUBLE`. - Otherwise, the result type is `DECIMAL`, which provides higher accuracy for decimal fractions. -::: tip -Use `type(CdsBaseType)` to explicitly set the result type if needed. -::: +#### Numeric Standard Functions { #type-determination-functions } + +Numeric aggregation and standard functions determine their result type based on the argument types: + +- **ceiling(x)**, **floor(x)**, **round(x)**: Return the same type as the input `x`. +- **min(x)**, **max(x)**, **sum(x)**: Aggregate functions return the same type as the argument `x`. +- **average(x)**: Returns `DECIMAL` for exact numeric types and `DOUBLE` for approximate numeric types. +- **count(x)**, **countdistinct(x)**: Always return `INT64`. + ## Structured Data From 7596e67a05b4ae02649baa8bd32b1dfe4eea11ad Mon Sep 17 00:00:00 2001 From: Matthias Schur <107557548+MattSchur@users.noreply.github.com> Date: Wed, 26 Nov 2025 15:25:28 +0100 Subject: [PATCH 4/8] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Adrian Görler --- java/cds-data.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/java/cds-data.md b/java/cds-data.md index a043a5124..6dce9c23b 100644 --- a/java/cds-data.md +++ b/java/cds-data.md @@ -84,11 +84,11 @@ Use `type(CdsBaseType)` to explicitly set the result type if needed. Arithmetic expressions promote numeric types according to the following precedence: **Type Precedence (highest to lowest):** -`DOUBLE` (binary64), `HANA_REAL` (binary32), `DECIMAL` (base 10), `INT64`, `INT32`, `INT16`, `UINT8` +`cds.Double`, `hana.REAL`, `cds.Decimal, `cds.Int64`, `cds.Int32`, `cds.Int16`, `cds.UInt8` - For addition, subtraction, and multiplication, the result type is the one with highest precedence among the operands. - For division: - - If any operand is a binary floating-point type (`DOUBLE`, `HANA_REAL`), the result type is `DOUBLE`. + - If any operand is an approximate numeric type (`cds.Double`, `hana.REAL`), the result type is `cds.Double`. - Otherwise, the result type is `DECIMAL`, which provides higher accuracy for decimal fractions. #### Numeric Standard Functions { #type-determination-functions } @@ -98,7 +98,7 @@ Numeric aggregation and standard functions determine their result type based on - **ceiling(x)**, **floor(x)**, **round(x)**: Return the same type as the input `x`. - **min(x)**, **max(x)**, **sum(x)**: Aggregate functions return the same type as the argument `x`. - **average(x)**: Returns `DECIMAL` for exact numeric types and `DOUBLE` for approximate numeric types. -- **count(x)**, **countdistinct(x)**: Always return `INT64`. +- **count(x)**, **countdistinct(x)**: return `INT64`. ## Structured Data From 9c85d5444d3f500bb14fe1dead2e47d6a6e18deb Mon Sep 17 00:00:00 2001 From: Matthias Schur <107557548+MattSchur@users.noreply.github.com> Date: Wed, 26 Nov 2025 15:26:04 +0100 Subject: [PATCH 5/8] Update java/cds-data.md --- java/cds-data.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/cds-data.md b/java/cds-data.md index 6dce9c23b..ff398b2d7 100644 --- a/java/cds-data.md +++ b/java/cds-data.md @@ -84,7 +84,7 @@ Use `type(CdsBaseType)` to explicitly set the result type if needed. Arithmetic expressions promote numeric types according to the following precedence: **Type Precedence (highest to lowest):** -`cds.Double`, `hana.REAL`, `cds.Decimal, `cds.Int64`, `cds.Int32`, `cds.Int16`, `cds.UInt8` +`cds.Double`, `hana.REAL`, `cds.Decimal`, `cds.Int64`, `cds.Int32`, `cds.Int16`, `cds.UInt8` - For addition, subtraction, and multiplication, the result type is the one with highest precedence among the operands. - For division: From fa7436ad6111416250303cb067ae5c4698ae298d Mon Sep 17 00:00:00 2001 From: Matthias Schur <107557548+MattSchur@users.noreply.github.com> Date: Wed, 26 Nov 2025 15:27:25 +0100 Subject: [PATCH 6/8] Apply suggestions from code review --- java/cds-data.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java/cds-data.md b/java/cds-data.md index ff398b2d7..adeb74645 100644 --- a/java/cds-data.md +++ b/java/cds-data.md @@ -97,8 +97,8 @@ Numeric aggregation and standard functions determine their result type based on - **ceiling(x)**, **floor(x)**, **round(x)**: Return the same type as the input `x`. - **min(x)**, **max(x)**, **sum(x)**: Aggregate functions return the same type as the argument `x`. -- **average(x)**: Returns `DECIMAL` for exact numeric types and `DOUBLE` for approximate numeric types. -- **count(x)**, **countdistinct(x)**: return `INT64`. +- **average(x)**: Returns `cds.Decimal` for exact numeric types and `cds.Double` for approximate numeric types. +- **count(x)**, **countdistinct(x)**: return `cds.Int64`. ## Structured Data From dba75da66940ac42f326b04343e8ed4cd256b101 Mon Sep 17 00:00:00 2001 From: Matthias Schur <107557548+MattSchur@users.noreply.github.com> Date: Wed, 26 Nov 2025 15:27:33 +0100 Subject: [PATCH 7/8] Apply suggestions from code review --- java/cds-data.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/cds-data.md b/java/cds-data.md index adeb74645..9c782a130 100644 --- a/java/cds-data.md +++ b/java/cds-data.md @@ -89,7 +89,7 @@ Arithmetic expressions promote numeric types according to the following preceden - For addition, subtraction, and multiplication, the result type is the one with highest precedence among the operands. - For division: - If any operand is an approximate numeric type (`cds.Double`, `hana.REAL`), the result type is `cds.Double`. - - Otherwise, the result type is `DECIMAL`, which provides higher accuracy for decimal fractions. + - Otherwise, the result type is `cds.Decimal`, which provides higher accuracy for decimal fractions. #### Numeric Standard Functions { #type-determination-functions } From f2ee30588d1a2c2e8d134b1cd0c823202c5ecee8 Mon Sep 17 00:00:00 2001 From: Mahati Shankar <93712176+smahati@users.noreply.github.com> Date: Fri, 28 Nov 2025 15:32:51 +0100 Subject: [PATCH 8/8] Apply suggestion from @smahati --- java/cds-data.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/cds-data.md b/java/cds-data.md index 9c782a130..572360c4f 100644 --- a/java/cds-data.md +++ b/java/cds-data.md @@ -98,7 +98,7 @@ Numeric aggregation and standard functions determine their result type based on - **ceiling(x)**, **floor(x)**, **round(x)**: Return the same type as the input `x`. - **min(x)**, **max(x)**, **sum(x)**: Aggregate functions return the same type as the argument `x`. - **average(x)**: Returns `cds.Decimal` for exact numeric types and `cds.Double` for approximate numeric types. -- **count(x)**, **countdistinct(x)**: return `cds.Int64`. +- **count(x)**, **countdistinct(x)**: Return `cds.Int64`. ## Structured Data