This is an automated email from the ASF dual-hosted git repository.
xiong 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 694b556a2e [CALCITE-6417] Map value constructor and Array value
constructor unparsed incorrectly for HiveSqlDialect
694b556a2e is described below
commit 694b556a2ece4953d8e9145352eb2340e1fac908
Author: Xiong Duan <[email protected]>
AuthorDate: Mon May 27 15:34:13 2024 +0800
[CALCITE-6417] Map value constructor and Array value constructor unparsed
incorrectly for HiveSqlDialect
---
.../apache/calcite/sql/dialect/HiveSqlDialect.java | 6 +++
.../calcite/sql/dialect/SparkSqlDialect.java | 14 +----
.../apache/calcite/util/RelToSqlConverterUtil.java | 30 +++++++++++
.../calcite/rel/rel2sql/RelToSqlConverterTest.java | 63 +++++++++++++---------
4 files changed, 77 insertions(+), 36 deletions(-)
diff --git
a/core/src/main/java/org/apache/calcite/sql/dialect/HiveSqlDialect.java
b/core/src/main/java/org/apache/calcite/sql/dialect/HiveSqlDialect.java
index e727eb5242..a6f9c4cae0 100644
--- a/core/src/main/java/org/apache/calcite/sql/dialect/HiveSqlDialect.java
+++ b/core/src/main/java/org/apache/calcite/sql/dialect/HiveSqlDialect.java
@@ -33,6 +33,8 @@ import org.apache.calcite.util.RelToSqlConverterUtil;
import org.checkerframework.checker.nullness.qual.Nullable;
+import static
org.apache.calcite.util.RelToSqlConverterUtil.unparseSparkArrayAndMap;
+
/**
* A <code>SqlDialect</code> implementation for the Apache Hive database.
*/
@@ -80,6 +82,10 @@ public class HiveSqlDialect extends SqlDialect {
@Override public void unparseCall(final SqlWriter writer, final SqlCall call,
final int leftPrec, final int rightPrec) {
switch (call.getKind()) {
+ case ARRAY_VALUE_CONSTRUCTOR:
+ case MAP_VALUE_CONSTRUCTOR:
+ unparseSparkArrayAndMap(writer, call, leftPrec, rightPrec);
+ break;
case POSITION:
final SqlWriter.Frame frame = writer.startFunCall("INSTR");
writer.sep(",");
diff --git
a/core/src/main/java/org/apache/calcite/sql/dialect/SparkSqlDialect.java
b/core/src/main/java/org/apache/calcite/sql/dialect/SparkSqlDialect.java
index a26fd804ca..303b21a204 100644
--- a/core/src/main/java/org/apache/calcite/sql/dialect/SparkSqlDialect.java
+++ b/core/src/main/java/org/apache/calcite/sql/dialect/SparkSqlDialect.java
@@ -32,6 +32,7 @@ import org.apache.calcite.sql.fun.SqlStdOperatorTable;
import org.checkerframework.checker.nullness.qual.Nullable;
import static org.apache.calcite.util.RelToSqlConverterUtil.unparseHiveTrim;
+import static
org.apache.calcite.util.RelToSqlConverterUtil.unparseSparkArrayAndMap;
/**
* A <code>SqlDialect</code> implementation for the APACHE SPARK database.
@@ -109,19 +110,8 @@ public class SparkSqlDialect extends SqlDialect {
switch (call.getKind()) {
case ARRAY_VALUE_CONSTRUCTOR:
case MAP_VALUE_CONSTRUCTOR:
- final String keyword =
- call.getKind() == SqlKind.ARRAY_VALUE_CONSTRUCTOR ? "array" : "map";
-
- writer.keyword(keyword);
-
- final SqlWriter.Frame frame = writer.startList("(", ")");
- for (SqlNode operand : call.getOperandList()) {
- writer.sep(",");
- operand.unparse(writer, leftPrec, rightPrec);
- }
- writer.endList(frame);
+ unparseSparkArrayAndMap(writer, call, leftPrec, rightPrec);
break;
-
case FLOOR:
if (call.operandCount() != 2) {
super.unparseCall(writer, call, leftPrec, rightPrec);
diff --git
a/core/src/main/java/org/apache/calcite/util/RelToSqlConverterUtil.java
b/core/src/main/java/org/apache/calcite/util/RelToSqlConverterUtil.java
index 9943b2b039..36816a2bfa 100644
--- a/core/src/main/java/org/apache/calcite/util/RelToSqlConverterUtil.java
+++ b/core/src/main/java/org/apache/calcite/util/RelToSqlConverterUtil.java
@@ -63,6 +63,36 @@ public abstract class RelToSqlConverterUtil {
}
}
+ /**
+ * Unparses Array and Map value constructor.
+ *
+ * <p>For example :
+ *
+ * <blockquote><pre>
+ * SELECT ARRAY[1, 2, 3] → SELECT ARRAY (1, 2, 3)
+ * SELECT MAP['k1', 'v1', 'k2', 'v2'] → SELECT MAP ('k1', 'v1', 'k2',
'v2')
+ * </pre></blockquote>
+ *
+ * @param writer writer
+ * @param call the call
+ */
+ public static void unparseSparkArrayAndMap(SqlWriter writer,
+ SqlCall call,
+ int leftPrec,
+ int rightPrec) {
+ final String keyword =
+ call.getKind() == SqlKind.ARRAY_VALUE_CONSTRUCTOR ? "array" : "map";
+
+ writer.keyword(keyword);
+
+ final SqlWriter.Frame frame = writer.startList("(", ")");
+ for (SqlNode operand : call.getOperandList()) {
+ writer.sep(",");
+ operand.unparse(writer, leftPrec, rightPrec);
+ }
+ writer.endList(frame);
+ }
+
/**
* Unparses TRIM function with value as space.
*
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 c97caae762..346b91b925 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
@@ -2252,7 +2252,7 @@ class RelToSqlConverterTest {
*/
@Test void testCastArrayCharset() {
final String query = "select cast(array['a', 'b', 'c'] as varchar array)";
- final String expected = "SELECT CAST(ARRAY['a', 'b', 'c'] AS VARCHAR
ARRAY)";
+ final String expected = "SELECT CAST(ARRAY ('a', 'b', 'c') AS VARCHAR
ARRAY)";
sql(query)
.withHive().ok(expected);
}
@@ -4288,25 +4288,6 @@ class RelToSqlConverterTest {
sql(retainLimitQuery).ok(retainLimitResult);
}
- /** Test case for
- * <a
href="https://issues.apache.org/jira/browse/CALCITE-5504">[CALCITE-5504]
- * Array literals are unparsed incorrectly for the spark dialect</a>.*/
- @Test void testArrayValueConstructorSpark() {
- final String query = "SELECT ARRAY[1, 2, 3]";
- final String expected = "SELECT ARRAY (1, 2, 3)\n"
- + "FROM (VALUES (0)) t (ZERO)";
- sql(query).withSpark().ok(expected);
- }
-
- /** Test case for
- * <a
href="https://issues.apache.org/jira/browse/CALCITE-5577">[CALCITE-5577]
- * Map value constructor is unparsed incorrectly for SparkSqlDialect</a>.*/
- @Test void testMapValueConstructorSpark() {
- final String query = "SELECT MAP['k1', 'v1', 'k2', 'v2']";
- final String expected = "SELECT MAP ('k1', 'v1', 'k2', 'v2')\n"
- + "FROM (VALUES (0)) t (ZERO)";
- sql(query).withSpark().ok(expected);
- }
/**
* Test case for
@@ -8046,15 +8027,41 @@ class RelToSqlConverterTest {
final String expectedPresto = "SELECT MAP (ARRAY['k1', 'k2'], ARRAY['v1',
'v2'])\n"
+ "FROM (VALUES (0)) AS \"t\" (\"ZERO\")";
final String expectedStarRocks = "SELECT MAP { 'k1' : 'v1', 'k2' : 'v2' }";
- sql(query).withPresto().ok(expectedPresto)
- .withStarRocks().ok(expectedStarRocks);
+ final String expectedSpark = "SELECT MAP ('k1', 'v1', 'k2', 'v2')\n"
+ + "FROM (VALUES (0)) t (ZERO)";
+ final String expectedHive = "SELECT MAP ('k1', 'v1', 'k2', 'v2')";
+ sql(query)
+ .withPresto().ok(expectedPresto)
+ .withStarRocks().ok(expectedStarRocks)
+ .withSpark().ok(expectedSpark)
+ .withHive().ok(expectedHive);
}
@Test void testMapValueConstructorWithArray() {
final String query = "SELECT MAP[ARRAY['k1', 'k2'], ARRAY['v1', 'v2']]";
final String expectedPresto = "SELECT MAP (ARRAY['k1', 'k2'], ARRAY['v1',
'v2'])\n"
+ "FROM (VALUES (0)) AS \"t\" (\"ZERO\")";
- sql(query).withPresto().ok(expectedPresto);
+ final String expectedSpark = "SELECT MAP (ARRAY ('k1', 'k2'), ARRAY ('v1',
'v2'))\n"
+ + "FROM (VALUES (0)) t (ZERO)";
+ sql(query)
+ .withPresto().ok(expectedPresto)
+ .withSpark().ok(expectedSpark);
+ }
+
+ /** Test case for
+ * <a
href="https://issues.apache.org/jira/browse/CALCITE-6417">[CALCITE-6417]
+ * Map value constructor and Array value constructor unparsed incorrectly
for HiveSqlDialect</a>.
+ *
+ * <p>According to
+ * <a
href="https://cwiki.apache.org/confluence/display/Hive/LanguageManual+Types#
+ * LanguageManualTypes-ComplexTypes">
+ * Hive Complex Types : MAP< primitive_type, data_type > Key only support
primitive type</a>.
+ * We test HiveSqlDialect by extra independent unit test.
+ * */
+ @Test void testHiveMapValueConstructorWithArray() {
+ final String query = "SELECT MAP[1, ARRAY['v1', 'v2']]";
+ final String expectedHive = "SELECT MAP (1, ARRAY ('v1', 'v2'))";
+ sql(query).withHive().ok(expectedHive);
}
/** Test case for
@@ -8070,10 +8077,18 @@ class RelToSqlConverterTest {
sql(query).withStarRocks().ok(expectedStarRocks);
}
+ /** Test case for
+ * <a
href="https://issues.apache.org/jira/browse/CALCITE-5504">[CALCITE-5504]
+ * Array literals are unparsed incorrectly for the spark dialect</a>.*/
@Test void testArrayValueConstructor() {
final String query = "SELECT ARRAY[1, 2, 3]";
final String expectedStarRocks = "SELECT[1, 2, 3]";
- sql(query).withStarRocks().ok(expectedStarRocks);
+ final String expectedSpark = "SELECT ARRAY (1, 2, 3)\n"
+ + "FROM (VALUES (0)) t (ZERO)";
+ final String expectedHive = "SELECT ARRAY (1, 2, 3)";
+ sql(query).withStarRocks().ok(expectedStarRocks)
+ .withSpark().ok(expectedSpark)
+ .withHive().ok(expectedHive);
}
@Test void testTrimWithBothSpecialCharacter() {