This is an automated email from the ASF dual-hosted git repository.
mihaibudiu pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/calcite.git
The following commit(s) were added to refs/heads/main by this push:
new fc9af0751c [CALCITE-7585] SqlMerge unparse EXISTS predicates in ON
clause without parentheses
fc9af0751c is described below
commit fc9af0751c649b3055a780d7d47ddc94b33c4138
Author: zzwqqq <[email protected]>
AuthorDate: Sun Jun 14 07:46:06 2026 +0800
[CALCITE-7585] SqlMerge unparse EXISTS predicates in ON clause without
parentheses
---
.../java/org/apache/calcite/sql/SqlDelete.java | 3 +-
.../main/java/org/apache/calcite/sql/SqlMerge.java | 5 ++--
.../org/apache/calcite/sql/SqlSelectOperator.java | 3 +-
.../java/org/apache/calcite/sql/SqlUpdate.java | 3 +-
.../main/java/org/apache/calcite/sql/SqlUtil.java | 34 ++++++++++------------
.../calcite/rel/rel2sql/RelToSqlConverterTest.java | 17 +++++++++++
6 files changed, 40 insertions(+), 25 deletions(-)
diff --git a/core/src/main/java/org/apache/calcite/sql/SqlDelete.java
b/core/src/main/java/org/apache/calcite/sql/SqlDelete.java
index c9da35c48b..7b3cf41c5c 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlDelete.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlDelete.java
@@ -152,7 +152,8 @@ public SqlNode getTargetTable() {
}
SqlNode condition = this.condition;
if (condition != null) {
- SqlUtil.unparseWhereClause(writer, condition, opLeft, opRight);
+ writer.sep("WHERE");
+ SqlUtil.unparseConditionClause(writer, condition, opLeft, opRight);
}
writer.endList(frame);
}
diff --git a/core/src/main/java/org/apache/calcite/sql/SqlMerge.java
b/core/src/main/java/org/apache/calcite/sql/SqlMerge.java
index ddadf32959..df450974a5 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlMerge.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlMerge.java
@@ -197,9 +197,8 @@ public void setSourceSelect(SqlSelect sourceSelect) {
writer.keyword("USING");
source.unparse(writer, opLeft, opRight);
- writer.newlineAndIndent();
- writer.keyword("ON");
- condition.unparse(writer, opLeft, opRight);
+ writer.sep("ON");
+ SqlUtil.unparseConditionClause(writer, condition, opLeft, opRight);
SqlUpdate updateCall = this.updateCall;
if (updateCall != null) {
diff --git a/core/src/main/java/org/apache/calcite/sql/SqlSelectOperator.java
b/core/src/main/java/org/apache/calcite/sql/SqlSelectOperator.java
index 7e37ac732f..8605eef7b3 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlSelectOperator.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlSelectOperator.java
@@ -173,7 +173,8 @@ public SqlSelect createCall(
SqlNode where = select.where;
if (where != null) {
- SqlUtil.unparseWhereClause(writer, where, 0, 0);
+ writer.sep("WHERE");
+ SqlUtil.unparseConditionClause(writer, where, 0, 0);
}
if (select.groupBy != null) {
SqlNodeList groupBy =
diff --git a/core/src/main/java/org/apache/calcite/sql/SqlUpdate.java
b/core/src/main/java/org/apache/calcite/sql/SqlUpdate.java
index 22d669efcf..0f743540d1 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlUpdate.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlUpdate.java
@@ -202,7 +202,8 @@ public void setSourceSelect(SqlSelect sourceSelect) {
writer.endList(setFrame);
SqlNode condition = this.condition;
if (condition != null) {
- SqlUtil.unparseWhereClause(writer, condition, opLeft, opRight);
+ writer.sep("WHERE");
+ SqlUtil.unparseConditionClause(writer, condition, opLeft, opRight);
}
writer.endList(frame);
}
diff --git a/core/src/main/java/org/apache/calcite/sql/SqlUtil.java
b/core/src/main/java/org/apache/calcite/sql/SqlUtil.java
index 1bafd7cfff..b5c91a1c7a 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlUtil.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlUtil.java
@@ -455,34 +455,30 @@ public static void unparseBinarySyntax(
}
/**
- * Unparses a WHERE clause.
+ * Unparses a condition using a
+ * {@link SqlWriter.FrameTypeEnum#WHERE_LIST} frame, which provides
+ * predicate-list formatting.
*
- * <p>Unparsing the condition in a {@link SqlWriter.FrameTypeEnum#WHERE_LIST}
- * frame lets sub-queries in predicates recognize that they need
- * parentheses.
- *
- * @param writer Writer
- * @param where WHERE condition
+ * @param writer Writer
+ * @param condition Condition
* @param leftPrec Left precedence
* @param rightPrec Right precedence
*/
- public static void unparseWhereClause(SqlWriter writer, SqlNode where,
- int leftPrec, int rightPrec) {
- writer.sep("WHERE");
-
+ public static void unparseConditionClause(SqlWriter writer,
+ SqlNode condition, int leftPrec, int rightPrec) {
if (!writer.isAlwaysUseParentheses()) {
- SqlNode node = where;
+ SqlNode node = condition;
// Decide whether to split on ORs or ANDs.
- SqlBinaryOperator whereSep = SqlStdOperatorTable.AND;
+ SqlBinaryOperator conditionSep = SqlStdOperatorTable.AND;
if ((node instanceof SqlCall)
&& node.getKind() == SqlKind.OR) {
- whereSep = SqlStdOperatorTable.OR;
+ conditionSep = SqlStdOperatorTable.OR;
}
- // Unroll whereClause.
+ // Unroll condition.
final List<SqlNode> list = new ArrayList<>(0);
- while (node.getKind() == whereSep.kind) {
+ while (node.getKind() == conditionSep.kind) {
assert node instanceof SqlCall;
final SqlCall call1 = (SqlCall) node;
list.add(0, call1.operand(1));
@@ -490,10 +486,10 @@ public static void unparseWhereClause(SqlWriter writer,
SqlNode where,
}
list.add(0, node);
- writer.list(SqlWriter.FrameTypeEnum.WHERE_LIST, whereSep,
- new SqlNodeList(list, where.getParserPosition()));
+ writer.list(SqlWriter.FrameTypeEnum.WHERE_LIST, conditionSep,
+ new SqlNodeList(list, condition.getParserPosition()));
} else {
- where.unparse(writer, leftPrec, rightPrec);
+ condition.unparse(writer, leftPrec, rightPrec);
}
}
diff --git
a/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java
b/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java
index 97d782fcae..4e2825bb3b 100644
---
a/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java
+++
b/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java
@@ -10046,6 +10046,23 @@ private void checkLiteral2(String expression, String
expected) {
sql(sql7)
.schema(CalciteAssert.SchemaSpec.JDBC_SCOTT)
.ok(expected7);
+
+ // [CALCITE-7585] SqlMerge unparse EXISTS predicates in ON clause
+ // without parentheses.
+ final String sql8 = "merge into \"DEPT\" as \"t\"\n"
+ + "using \"DEPT\" as \"s\"\n"
+ + "on exists (select 1 from \"EMP\" as \"e\" where \"e\".\"DEPTNO\" =
\"s\".\"DEPTNO\")\n"
+ + "when matched then\n"
+ + "update set \"DNAME\" = \"s\".\"DNAME\"";
+ final String expected8 = "MERGE INTO \"SCOTT\".\"DEPT\" AS \"DEPT0\"\n"
+ + "USING \"SCOTT\".\"DEPT\"\n"
+ + "ON EXISTS (SELECT *\n"
+ + "FROM \"SCOTT\".\"EMP\"\n"
+ + "WHERE \"DEPTNO\" = \"DEPT\".\"DEPTNO\")\n"
+ + "WHEN MATCHED THEN UPDATE SET \"DNAME\" = \"DEPT\".\"DNAME\"";
+ sql(sql8)
+ .schema(CalciteAssert.SchemaSpec.JDBC_SCOTT)
+ .ok(expected8);
}
/** Test case for