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] &rarr; SELECT ARRAY (1, 2, 3)
+   * SELECT MAP['k1', 'v1', 'k2', 'v2'] &rarr; 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() {

Reply via email to