This is an automated email from the ASF dual-hosted git repository.
jhyde pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/calcite.git
The following commit(s) were added to refs/heads/master by this push:
new 10a3b1a3f [CALCITE-4401] SqlJoin.toString throws RuntimeException, "No
list started"
10a3b1a3f is described below
commit 10a3b1a3f5399851bc31ff665a999411edffbcc8
Author: onTheQT <[email protected]>
AuthorDate: Tue Mar 29 22:32:18 2022 +0530
[CALCITE-4401] SqlJoin.toString throws RuntimeException, "No list started"
To resolve the RuntimeException seen in SqlJoin#toString, add
a "SELECT *" wrap over SqlJoin in SqlJoin#toSqlString. This
prevents SqlJoin#unparse method from calling
SqlPrettyWriter#sep with a null frame, and is a less fragile
fix than to mutate internal frame state.
Extend SqlPrettyWriterFixture with a method
`checkTransformedNode(UnaryOperator<SqlNode> transform)`
that does do the same as `check()` but applies a transform
function that maps from the root to another node in the tree.
Close apache/calcite#2757
---
.../main/java/org/apache/calcite/sql/SqlJoin.java | 10 +++++++
.../calcite/sql/test/SqlPrettyWriterFixture.java | 20 +++++++++++--
.../calcite/sql/test/SqlPrettyWriterTest.java | 34 ++++++++++++++++++++++
.../calcite/sql/test/SqlPrettyWriterTest.xml | 9 ++++++
4 files changed, 70 insertions(+), 3 deletions(-)
diff --git a/core/src/main/java/org/apache/calcite/sql/SqlJoin.java
b/core/src/main/java/org/apache/calcite/sql/SqlJoin.java
index 4baf3fc72..a609cb9d4 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlJoin.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlJoin.java
@@ -18,6 +18,7 @@ package org.apache.calcite.sql;
import org.apache.calcite.sql.parser.SqlParserPos;
import org.apache.calcite.sql.type.SqlTypeName;
+import org.apache.calcite.sql.util.SqlString;
import org.apache.calcite.util.ImmutableNullableList;
import org.apache.calcite.util.Util;
@@ -26,6 +27,7 @@ import com.google.common.base.Preconditions;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.List;
+import java.util.function.UnaryOperator;
import static java.util.Objects.requireNonNull;
@@ -259,4 +261,12 @@ public class SqlJoin extends SqlCall {
}
}
}
+
+ @Override public SqlString toSqlString(UnaryOperator<SqlWriterConfig>
transform) {
+ SqlNode selectWrapper =
+ new SqlSelect(SqlParserPos.ZERO, SqlNodeList.EMPTY,
+ SqlNodeList.SINGLETON_STAR, this, null, null, null,
+ SqlNodeList.EMPTY, null, null, null, SqlNodeList.EMPTY);
+ return selectWrapper.toSqlString(transform);
+ }
}
diff --git
a/core/src/test/java/org/apache/calcite/sql/test/SqlPrettyWriterFixture.java
b/core/src/test/java/org/apache/calcite/sql/test/SqlPrettyWriterFixture.java
index 537a90f38..d92eef1ba 100644
--- a/core/src/test/java/org/apache/calcite/sql/test/SqlPrettyWriterFixture.java
+++ b/core/src/test/java/org/apache/calcite/sql/test/SqlPrettyWriterFixture.java
@@ -138,17 +138,31 @@ class SqlPrettyWriterFixture {
}
SqlPrettyWriterFixture check() {
+ return checkTransformedNode(n -> n);
+ }
+
+ /** As {@link #check()}, but operates on a transformed node
+ * (say the 2nd child of the 1st child) rather than the root. */
+ SqlPrettyWriterFixture checkTransformedNode(
+ UnaryOperator<SqlNode> nodeTransformer) {
+ return check_(nodeTransformer);
+ }
+
+ private SqlPrettyWriterFixture check_(UnaryOperator<SqlNode>
nodeTransformer) {
final SqlWriterConfig config =
transform.apply(SqlPrettyWriter.config()
.withDialect(AnsiSqlDialect.DEFAULT));
final SqlPrettyWriter prettyWriter = new SqlPrettyWriter(config);
final SqlNode node;
+ final SqlNode node1;
if (expression) {
final SqlCall valuesCall = (SqlCall) parseQuery("VALUES (" + sql + ")");
final SqlCall rowCall = valuesCall.operand(0);
node = rowCall.operand(0);
+ node1 = node;
} else {
node = parseQuery(sql);
+ node1 = nodeTransformer.apply(node);
}
// Describe settings
@@ -175,11 +189,11 @@ class SqlPrettyWriterFixture {
final SqlCall rowCall = valuesCall.operand(0);
node2 = rowCall.operand(0);
} else {
- node2 = parseQuery(actual2);
+ SqlNode node2a = parseQuery(actual2);
+ node2 = nodeTransformer.apply(node2a);
}
- assertTrue(node.equalsDeep(node2, Litmus.THROW));
+ assertTrue(node1.equalsDeep(node2, Litmus.THROW));
return this;
}
-
}
diff --git
a/core/src/test/java/org/apache/calcite/sql/test/SqlPrettyWriterTest.java
b/core/src/test/java/org/apache/calcite/sql/test/SqlPrettyWriterTest.java
index fe2ae3a68..4891edd70 100644
--- a/core/src/test/java/org/apache/calcite/sql/test/SqlPrettyWriterTest.java
+++ b/core/src/test/java/org/apache/calcite/sql/test/SqlPrettyWriterTest.java
@@ -17,6 +17,7 @@
package org.apache.calcite.sql.test;
import org.apache.calcite.sql.SqlNode;
+import org.apache.calcite.sql.SqlSelect;
import org.apache.calcite.sql.SqlWriter;
import org.apache.calcite.sql.SqlWriterConfig;
import org.apache.calcite.sql.parser.SqlParseException;
@@ -27,6 +28,12 @@ import org.apache.calcite.test.DiffRepository;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
+import static org.apache.calcite.test.Matchers.isLinux;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.instanceOf;
+import static org.hamcrest.Matchers.notNullValue;
+
/**
* Unit test for {@link SqlPrettyWriter}.
*
@@ -369,6 +376,33 @@ class SqlPrettyWriterTest {
.check();
}
+ /** Test case for
+ * <a
href="https://issues.apache.org/jira/browse/CALCITE-4401">[CALCITE-4401]
+ * SqlJoin toString throws RuntimeException</a>. */
+ @Test void testJoinClauseToString() {
+ final String sql = "SELECT t.region_name, t0.o_totalprice\n"
+ + "FROM (SELECT c_custkey, region_name\n"
+ + "FROM tpch.out_tpch_vw__customer) AS t\n"
+ + "INNER JOIN (SELECT o_custkey, o_totalprice\n"
+ + "FROM tpch.out_tpch_vw__orders) AS t0 ON t.c_custkey = t0.o_custkey";
+
+ final String expectedJoinString = "SELECT *\n"
+ + "FROM (SELECT `C_CUSTKEY`, `REGION_NAME`\n"
+ + "FROM `TPCH`.`OUT_TPCH_VW__CUSTOMER`) AS `T`\n"
+ + "INNER JOIN (SELECT `O_CUSTKEY`, `O_TOTALPRICE`\n"
+ + "FROM `TPCH`.`OUT_TPCH_VW__ORDERS`) AS `T0`"
+ + " ON `T`.`C_CUSTKEY` = `T0`.`O_CUSTKEY`";
+
+ sql(sql)
+ .checkTransformedNode(root -> {
+ assertThat(root, instanceOf(SqlSelect.class));
+ SqlNode from = ((SqlSelect) root).getFrom();
+ assertThat(from, notNullValue());
+ assertThat(from.toString(), isLinux(expectedJoinString));
+ return from;
+ });
+ }
+
@Test void testWhereListItemsOnSeparateLinesOr() {
final String sql = "select x"
+ " from y"
diff --git
a/core/src/test/resources/org/apache/calcite/sql/test/SqlPrettyWriterTest.xml
b/core/src/test/resources/org/apache/calcite/sql/test/SqlPrettyWriterTest.xml
index 713668b49..965712f04 100644
---
a/core/src/test/resources/org/apache/calcite/sql/test/SqlPrettyWriterTest.xml
+++
b/core/src/test/resources/org/apache/calcite/sql/test/SqlPrettyWriterTest.xml
@@ -225,6 +225,15 @@ FROM `X`
INNER JOIN `Y` ON `X`.`K` = `Y`.`K`]]>
</Resource>
</TestCase>
+ <TestCase name="testJoinClauseToString">
+ <Resource name="formatted">
+ <![CDATA[SELECT `T`.`REGION_NAME`, `T0`.`O_TOTALPRICE`
+FROM (SELECT `C_CUSTKEY`, `REGION_NAME`
+ FROM `TPCH`.`OUT_TPCH_VW__CUSTOMER`) AS `T`
+ INNER JOIN (SELECT `O_CUSTKEY`, `O_TOTALPRICE`
+ FROM `TPCH`.`OUT_TPCH_VW__ORDERS`) AS `T0` ON `T`.`C_CUSTKEY` =
`T0`.`O_CUSTKEY`]]>
+ </Resource>
+ </TestCase>
<TestCase name="testJoinComma">
<Resource name="formatted">
<![CDATA[SELECT *