From 98792e6ebbaed1420ee515c3bcfca181e159a89e Mon Sep 17 00:00:00 2001 From: ignitetcbot <43213589+ignitetcbot@users.noreply.github.com> Date: Mon, 7 Sep 2026 10:26:45 +0300 Subject: [PATCH 1/7] IGNITE-29041 Update SQL conformance for recursive CTEs --- docs/_docs/sql-reference/sql-conformance.adoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/_docs/sql-reference/sql-conformance.adoc b/docs/_docs/sql-reference/sql-conformance.adoc index 7cc2ed5c61043..63e8d53749aa1 100644 --- a/docs/_docs/sql-reference/sql-conformance.adoc +++ b/docs/_docs/sql-reference/sql-conformance.adoc @@ -162,7 +162,7 @@ Ignite does not support the following sub-feature: `E071–06` Table operators in subqueries -Note that there is no support for non-recursive WITH clause in H2 and Ignite. According to link:http://www.h2database.com/html/grammar.html#with[the H2 docs, window=_blank] there is support for recursive WITH clause, but it fails in Ignite. +The H2-based SQL engine does not support non-recursive `WITH` clauses. The Calcite-based SQL engine supports recursive CTEs with `WITH RECURSIVE` and `UNION ALL`; see link:SQL/sql-calcite#recursive-ctes[Recursive CTEs, window=_blank]. | E081 Basic Privileges | Ignite does not support the following sub-feature: @@ -173,7 +173,7 @@ Note that there is no support for non-recursive WITH clause in H2 and Ignite. Ac `E081–03` INSERT privilege at the table level -`E081–04` UPDATE privilege at the table level +`E081–04` UPDATE privilege `E081–05` UPDATE privilege at the column level From 110029b6a669734553dfdd955e34fecab96af559 Mon Sep 17 00:00:00 2001 From: ignitetcbot <43213589+ignitetcbot@users.noreply.github.com> Date: Mon, 7 Sep 2026 10:32:23 +0300 Subject: [PATCH 2/7] IGNITE-29041 Document Calcite recursive CTEs --- docs/_docs/SQL/sql-calcite.adoc | 52 +++++++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 3 deletions(-) diff --git a/docs/_docs/SQL/sql-calcite.adoc b/docs/_docs/SQL/sql-calcite.adoc index 1bc5aa0d50956..0ce33329e85af 100644 --- a/docs/_docs/SQL/sql-calcite.adoc +++ b/docs/_docs/SQL/sql-calcite.adoc @@ -189,6 +189,52 @@ The new SQL engine mostly inherits data manipulation language (DML) statements s In most cases, statement syntax is compliant with the old SQL engine. But there are still some differences between DML dialects in H2-based engine and Calcite-based engine. For example, note the `MERGE` statement syntax has changed. +=== Recursive CTEs + +The Calcite-based SQL engine supports recursive common table expressions (CTEs) that use `WITH RECURSIVE` and `UNION ALL`. +Recursive CTEs can be used to express hierarchical traversals, graph-style parent-child walks, and sequence generation queries. + +[source,sql] +---- +WITH RECURSIVE employee_hierarchy (id, manager_id, name, depth) AS ( + SELECT id, manager_id, name, 0 + FROM employee + WHERE manager_id IS NULL + + UNION ALL + + SELECT e.id, e.manager_id, e.name, h.depth + 1 + FROM employee e + JOIN employee_hierarchy h ON e.manager_id = h.id +) +SELECT id, manager_id, name, depth +FROM employee_hierarchy +ORDER BY depth, id; +---- + +The recursive part can reference the recursive CTE more than once and can contain multiple recursive branches. +`UNION DISTINCT` recursive CTEs are not supported. + +Recursive CTE execution keeps the recursive delta on the query coordinator. +The delta memory is included into the Calcite query memory quota. See <> for details about memory quota configuration. + +To protect the cluster from accidentally unbounded recursion, Ignite limits the number of recursive CTE iterations to `100` by default. +You can change the limit with the `sql.calcite.recursiveCteIterationLimit` distributed property. A negative value disables the limit. + +[tabs] +-- +tab:Unix[] +[source,shell] +---- +control.sh --property set --name sql.calcite.recursiveCteIterationLimit --val 1000 +---- +tab:Windows[] +[source,shell] +---- +control.bat --property set --name sql.calcite.recursiveCteIterationLimit --val 1000 +---- +-- + === Transactions The Calcite-based SQL engine supports SQL savepoint commands for explicit transactions. See link:sql-reference/transactions[Transactions, window=_blank] for syntax and usage details. @@ -310,7 +356,7 @@ The Calcite-based SQL engine supports SQL window functions. See link:sql-referen |`SHA1` |`SHA1(string)` -|Returns the SHA-1 hash of a string as a hexadecimal string. +|Returns the SHA-1 hash of a string. |`SUBSTRING` |`SUBSTRING(string FROM start [FOR length])` @@ -1058,7 +1104,7 @@ It is allowed to define several hints for the same relation operator. To use sev Example: [source, SQL] ---- -SELECT /*+ NO_INDEX, EXPAND_DISTINCT_AGG */ SUM(DISTINCT V1), AVG(DISTINCT V2) FROM TBL1 WHERE V3=? GROUP BY V3 +SELECT /*+ NO_INDEX, EXPAND_DISTINCT_AGG */ SUM(DISTINCT V1), AVG(DISTINCT V2) FROM TBL1 GROUP BY V3 ---- ==== Hint parameters @@ -1072,7 +1118,7 @@ Example: ---- SELECT /*+ FORCE_INDEX(TBL1_IDX2,TBL2_IDX1) */ T1.V1, T2.V1 FROM TBL1 T1, TBL2 T2 WHERE T1.V1 = T2.V1 AND T1.V2 > ? AND T2.V2 > ?; -SELECT /*+ FORCE_INDEX('TBL2_idx1') */ T1.V1, T2.V1 FROM TBL1 T1, TBL2 T2 WHERE T1.V1 = T2.V1 AND T1.V2 > ? AND T2.V2 > ?; +SELECT /*+ FORCE_INDEX('TBL2_idx1') */ T1.V1, T2.V1 FROM TBL1 T1, T2 T2 WHERE T1.V1 = T2.V1 AND T1.V2 > ? AND T2.V2 > ?; ---- === Hint scope From 29b9eec0b6aedb975aff82a8aa6ed13fd43dff28 Mon Sep 17 00:00:00 2001 From: ignitetcbot <43213589+ignitetcbot@users.noreply.github.com> Date: Mon, 7 Sep 2026 10:34:50 +0300 Subject: [PATCH 3/7] IGNITE-29041 Restore conformance wording from master --- docs/_docs/sql-reference/sql-conformance.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/_docs/sql-reference/sql-conformance.adoc b/docs/_docs/sql-reference/sql-conformance.adoc index 63e8d53749aa1..6ddf7f3ba50e5 100644 --- a/docs/_docs/sql-reference/sql-conformance.adoc +++ b/docs/_docs/sql-reference/sql-conformance.adoc @@ -173,7 +173,7 @@ The H2-based SQL engine does not support non-recursive `WITH` clauses. The Calci `E081–03` INSERT privilege at the table level -`E081–04` UPDATE privilege +`E081–04` UPDATE privilege at the table level `E081–05` UPDATE privilege at the column level From 896c384476e9a220bb0868c6450aceabfebbbbbe Mon Sep 17 00:00:00 2001 From: ignitetcbot <43213589+ignitetcbot@users.noreply.github.com> Date: Mon, 7 Sep 2026 10:38:33 +0300 Subject: [PATCH 4/7] IGNITE-29041 Restore Calcite docs wording from master --- docs/_docs/SQL/sql-calcite.adoc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/_docs/SQL/sql-calcite.adoc b/docs/_docs/SQL/sql-calcite.adoc index 0ce33329e85af..21e7cb5a6e831 100644 --- a/docs/_docs/SQL/sql-calcite.adoc +++ b/docs/_docs/SQL/sql-calcite.adoc @@ -356,7 +356,7 @@ The Calcite-based SQL engine supports SQL window functions. See link:sql-referen |`SHA1` |`SHA1(string)` -|Returns the SHA-1 hash of a string. +|Returns the SHA-1 hash of a string as a hexadecimal string. |`SUBSTRING` |`SUBSTRING(string FROM start [FOR length])` @@ -479,7 +479,7 @@ The Calcite-based SQL engine supports SQL window functions. See link:sql-referen |Checks whether a string does not match a case-sensitive POSIX regular expression. |`!~*` -|`string !~* pattern` +|`string !~ pattern` |Checks whether a string does not match a case-insensitive POSIX regular expression. |`REGEXP_REPLACE` @@ -1104,7 +1104,7 @@ It is allowed to define several hints for the same relation operator. To use sev Example: [source, SQL] ---- -SELECT /*+ NO_INDEX, EXPAND_DISTINCT_AGG */ SUM(DISTINCT V1), AVG(DISTINCT V2) FROM TBL1 GROUP BY V3 +SELECT /*+ NO_INDEX, EXPAND_DISTINCT_AGG */ SUM(DISTINCT V1), AVG(DISTINCT V2) FROM TBL1 WHERE V3=? GROUP BY V3 ---- ==== Hint parameters @@ -1118,7 +1118,7 @@ Example: ---- SELECT /*+ FORCE_INDEX(TBL1_IDX2,TBL2_IDX1) */ T1.V1, T2.V1 FROM TBL1 T1, TBL2 T2 WHERE T1.V1 = T2.V1 AND T1.V2 > ? AND T2.V2 > ?; -SELECT /*+ FORCE_INDEX('TBL2_idx1') */ T1.V1, T2.V1 FROM TBL1 T1, T2 T2 WHERE T1.V1 = T2.V1 AND T1.V2 > ? AND T2.V2 > ?; +SELECT /*+ FORCE_INDEX('TBL2_idx1') */ T1.V1, T2.V1 FROM TBL1 T1, TBL2 T2 WHERE T1.V1 = T2.V1 AND T1.V2 > ? AND T2.V2 > ?; ---- === Hint scope From cfa368f7068ab8e462063f3948944b1031ae37d1 Mon Sep 17 00:00:00 2001 From: ignitetcbot <43213589+ignitetcbot@users.noreply.github.com> Date: Mon, 7 Sep 2026 10:44:15 +0300 Subject: [PATCH 5/7] IGNITE-29041 Restore regex operator syntax --- docs/_docs/SQL/sql-calcite.adoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/_docs/SQL/sql-calcite.adoc b/docs/_docs/SQL/sql-calcite.adoc index 21e7cb5a6e831..be628144a32f5 100644 --- a/docs/_docs/SQL/sql-calcite.adoc +++ b/docs/_docs/SQL/sql-calcite.adoc @@ -479,7 +479,7 @@ The Calcite-based SQL engine supports SQL window functions. See link:sql-referen |Checks whether a string does not match a case-sensitive POSIX regular expression. |`!~*` -|`string !~ pattern` +|`string !~* pattern` |Checks whether a string does not match a case-insensitive POSIX regular expression. |`REGEXP_REPLACE` @@ -1308,7 +1308,7 @@ The following API "transactional aware": 1. ACID in the same way as key-value API. 2. Any data modified or deleted within a transaction will not be visible to concurrent transactions until it is committed. -3. Any data modified by a query will be returned with updated values by subsequent queries within the same transaction. +3. Any data modified by a query will be returned with updated values by subsequent queries within a transaction. So, when `txAwareQueriesEnabled = true` enabled the usage: From 3fa80fd5037f0437f9fded35b84a402a59028c3f Mon Sep 17 00:00:00 2001 From: ignitetcbot <43213589+ignitetcbot@users.noreply.github.com> Date: Mon, 7 Sep 2026 10:48:40 +0300 Subject: [PATCH 6/7] IGNITE-29041 Restore transaction wording from master --- docs/_docs/SQL/sql-calcite.adoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/_docs/SQL/sql-calcite.adoc b/docs/_docs/SQL/sql-calcite.adoc index be628144a32f5..295f18dfa2816 100644 --- a/docs/_docs/SQL/sql-calcite.adoc +++ b/docs/_docs/SQL/sql-calcite.adoc @@ -768,7 +768,7 @@ The Calcite-based SQL engine supports SQL window functions. See link:sql-referen |`TIME` |`TIME(value)` or `TIME(hour, minute, second)` -|Converts a value to a time or creates a time from time fields. +|Converts a value to a time or creates a time from date fields. |`DATETIME` |`DATETIME(value)` or `DATETIME(year, month, day, hour, minute, second)` @@ -1308,7 +1308,7 @@ The following API "transactional aware": 1. ACID in the same way as key-value API. 2. Any data modified or deleted within a transaction will not be visible to concurrent transactions until it is committed. -3. Any data modified by a query will be returned with updated values by subsequent queries within a transaction. +3. Any data modified by a query will be returned with updated values by subsequent queries within the same transaction. So, when `txAwareQueriesEnabled = true` enabled the usage: From 486a6367610c4c891b729e89373695ef83165345 Mon Sep 17 00:00:00 2001 From: ignitetcbot <43213589+ignitetcbot@users.noreply.github.com> Date: Mon, 7 Sep 2026 10:52:46 +0300 Subject: [PATCH 7/7] IGNITE-29041 Restore TIME function wording from master --- docs/_docs/SQL/sql-calcite.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/_docs/SQL/sql-calcite.adoc b/docs/_docs/SQL/sql-calcite.adoc index 295f18dfa2816..7c4825337e60a 100644 --- a/docs/_docs/SQL/sql-calcite.adoc +++ b/docs/_docs/SQL/sql-calcite.adoc @@ -768,7 +768,7 @@ The Calcite-based SQL engine supports SQL window functions. See link:sql-referen |`TIME` |`TIME(value)` or `TIME(hour, minute, second)` -|Converts a value to a time or creates a time from date fields. +|Converts a value to a time or creates a time from time fields. |`DATETIME` |`DATETIME(value)` or `DATETIME(year, month, day, hour, minute, second)`