You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@calcite.apache.org by jh...@apache.org on 2018/05/09 16:42:27 UTC

calcite git commit: [CALCITE-2276] Allow explicit ROW value constructor in SELECT clause and elsewhere (Danny Chan)

Repository: calcite
Updated Branches:
  refs/heads/master 972c54c44 -> 2a4f6c2c7


[CALCITE-2276] Allow explicit ROW value constructor in SELECT clause and elsewhere (Danny Chan)

Close apache/calcite#679


Project: http://git-wip-us.apache.org/repos/asf/calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/calcite/commit/2a4f6c2c
Tree: http://git-wip-us.apache.org/repos/asf/calcite/tree/2a4f6c2c
Diff: http://git-wip-us.apache.org/repos/asf/calcite/diff/2a4f6c2c

Branch: refs/heads/master
Commit: 2a4f6c2c7509c94b5eeb89d3925c91828f8ef1e1
Parents: 972c54c
Author: yuzhao.cyz <yu...@alibaba-inc.com>
Authored: Thu Apr 26 12:12:04 2018 +0800
Committer: Julian Hyde <jh...@apache.org>
Committed: Tue May 8 17:41:28 2018 -0700

----------------------------------------------------------------------
 core/src/main/codegen/templates/Parser.jj       |  3 +-
 .../sql/validate/SqlAbstractConformance.java    |  4 ++
 .../calcite/sql/validate/SqlConformance.java    | 18 +++++++
 .../sql/validate/SqlConformanceEnum.java        | 10 ++++
 .../calcite/sql/parser/SqlParserTest.java       | 53 ++++++++++++++++++++
 core/src/test/resources/sql/misc.iq             | 23 ++++++++-
 6 files changed, 108 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/calcite/blob/2a4f6c2c/core/src/main/codegen/templates/Parser.jj
----------------------------------------------------------------------
diff --git a/core/src/main/codegen/templates/Parser.jj b/core/src/main/codegen/templates/Parser.jj
index 881ab11..7970db6 100644
--- a/core/src/main/codegen/templates/Parser.jj
+++ b/core/src/main/codegen/templates/Parser.jj
@@ -3242,7 +3242,8 @@ SqlNode Expression3(ExprContext exprContext) :
     }
     list = ParenthesizedSimpleIdentifierList() {
         if (exprContext != ExprContext.ACCEPT_ALL
-            && exprContext != ExprContext.ACCEPT_CURSOR)
+            && exprContext != ExprContext.ACCEPT_CURSOR
+            && !this.conformance.allowExplicitRowValueConstructor())
         {
             throw SqlUtil.newContextException(s.end(list),
                 RESOURCE.illegalRowExpression());

http://git-wip-us.apache.org/repos/asf/calcite/blob/2a4f6c2c/core/src/main/java/org/apache/calcite/sql/validate/SqlAbstractConformance.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/validate/SqlAbstractConformance.java b/core/src/main/java/org/apache/calcite/sql/validate/SqlAbstractConformance.java
index dbf8b6b..85465b8 100644
--- a/core/src/main/java/org/apache/calcite/sql/validate/SqlAbstractConformance.java
+++ b/core/src/main/java/org/apache/calcite/sql/validate/SqlAbstractConformance.java
@@ -71,6 +71,10 @@ public abstract class SqlAbstractConformance implements SqlConformance {
     return SqlConformanceEnum.DEFAULT.allowNiladicParentheses();
   }
 
+  public boolean allowExplicitRowValueConstructor() {
+    return SqlConformanceEnum.DEFAULT.allowExplicitRowValueConstructor();
+  }
+
   public boolean allowExtend() {
     return SqlConformanceEnum.DEFAULT.allowExtend();
   }

http://git-wip-us.apache.org/repos/asf/calcite/blob/2a4f6c2c/core/src/main/java/org/apache/calcite/sql/validate/SqlConformance.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/validate/SqlConformance.java b/core/src/main/java/org/apache/calcite/sql/validate/SqlConformance.java
index 76b6da9..6ba9a6f 100644
--- a/core/src/main/java/org/apache/calcite/sql/validate/SqlConformance.java
+++ b/core/src/main/java/org/apache/calcite/sql/validate/SqlConformance.java
@@ -261,6 +261,24 @@ public interface SqlConformance {
   boolean allowNiladicParentheses();
 
   /**
+   * Whether to allow SQL syntax "{@code ROW(expr1, expr2, expr3)}".
+   * <p>The equivalent syntax in standard SQL is
+   * "{@code (expr1, expr2, expr3)}".
+   *
+   * <p>Standard SQL does not allow this because the type is not
+   * well-defined. However, PostgreSQL allows this behavior.
+   *
+   * <p>Standard SQL allows row expressions in other contexts, for instance
+   * inside {@code VALUES} clause.
+   *
+   * <p>Among the built-in conformance levels, true in
+   * {@link SqlConformanceEnum#DEFAULT},
+   * {@link SqlConformanceEnum#LENIENT};
+   * false otherwise.
+   */
+  boolean allowExplicitRowValueConstructor();
+
+  /**
    * Whether to allow mixing table columns with extended columns in
    * {@code INSERT} (or {@code UPSERT}).
    *

http://git-wip-us.apache.org/repos/asf/calcite/blob/2a4f6c2c/core/src/main/java/org/apache/calcite/sql/validate/SqlConformanceEnum.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/validate/SqlConformanceEnum.java b/core/src/main/java/org/apache/calcite/sql/validate/SqlConformanceEnum.java
index 1a5752f..e24450a 100644
--- a/core/src/main/java/org/apache/calcite/sql/validate/SqlConformanceEnum.java
+++ b/core/src/main/java/org/apache/calcite/sql/validate/SqlConformanceEnum.java
@@ -210,6 +210,16 @@ public enum SqlConformanceEnum implements SqlConformance {
     }
   }
 
+  public boolean allowExplicitRowValueConstructor() {
+    switch (this) {
+    case DEFAULT:
+    case LENIENT:
+      return true;
+    default:
+      return false;
+    }
+  }
+
   public boolean allowExtend() {
     switch (this) {
     case LENIENT:

http://git-wip-us.apache.org/repos/asf/calcite/blob/2a4f6c2c/core/src/test/java/org/apache/calcite/sql/parser/SqlParserTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/sql/parser/SqlParserTest.java b/core/src/test/java/org/apache/calcite/sql/parser/SqlParserTest.java
index de9ca4d..d29f762 100644
--- a/core/src/test/java/org/apache/calcite/sql/parser/SqlParserTest.java
+++ b/core/src/test/java/org/apache/calcite/sql/parser/SqlParserTest.java
@@ -1016,6 +1016,46 @@ public class SqlParserTest {
         "SELECT `T`.`R`.`EXPR$1`.`EXPR$2`\n"
             + "FROM (SELECT (ROW((ROW(1, 2)), (ROW(3, 4, 5, 6)))) AS `R`\n"
             + "FROM `SALES`.`DEPTS`) AS `T`");
+
+    // Conformance DEFAULT and LENIENT support explicit row value constructor
+    conformance = SqlConformanceEnum.DEFAULT;
+    final String selectRow = "select ^row(t1a, t2a)^ from t1";
+    final String expected = "SELECT (ROW(`T1A`, `T2A`))\n"
+        + "FROM `T1`";
+    sql(selectRow).sansCarets().ok(expected);
+    conformance = SqlConformanceEnum.LENIENT;
+    sql(selectRow).sansCarets().ok(expected);
+
+    final String pattern = "ROW expression encountered in illegal context";
+    conformance = SqlConformanceEnum.MYSQL_5;
+    sql(selectRow).fails(pattern);
+    conformance = SqlConformanceEnum.ORACLE_12;
+    sql(selectRow).fails(pattern);
+    conformance = SqlConformanceEnum.STRICT_2003;
+    sql(selectRow).fails(pattern);
+    conformance = SqlConformanceEnum.SQL_SERVER_2008;
+    sql(selectRow).fails(pattern);
+
+    final String whereRow = "select 1 from t2 where ^row (x, y)^ < row (a, b)";
+    final String whereExpected = "SELECT 1\n"
+        + "FROM `T2`\n"
+        + "WHERE ((ROW(`X`, `Y`)) < (ROW(`A`, `B`)))";
+    conformance = SqlConformanceEnum.DEFAULT;
+    sql(whereRow).sansCarets().ok(whereExpected);
+    conformance = SqlConformanceEnum.SQL_SERVER_2008;
+    sql(whereRow).fails(pattern);
+
+    final String whereRow2 = "select 1 from t2 where ^(x, y)^ < (a, b)";
+    conformance = SqlConformanceEnum.DEFAULT;
+    sql(whereRow2).sansCarets().ok(whereExpected);
+    if (this instanceof SqlUnParserTest) {
+      // After this point, SqlUnparserTest has problems.
+      // We generate ROW in a dialect that does not allow ROW in all contexts.
+      // So bail out.
+      return;
+    }
+    conformance = SqlConformanceEnum.SQL_SERVER_2008;
+    sql(whereRow2).sansCarets().ok(whereExpected);
   }
 
   @Test public void testPeriod() {
@@ -1079,6 +1119,12 @@ public class SqlParserTest {
             + "WHERE (`X` IS DISTINCT FROM (ROW(4, 5, 6)))");
 
     check(
+        "select * from t where x is distinct from row (4,5,6)",
+        "SELECT *\n"
+            + "FROM `T`\n"
+            + "WHERE (`X` IS DISTINCT FROM (ROW(4, 5, 6)))");
+
+    check(
         "select * from t where true is distinct from true",
         "SELECT *\n"
             + "FROM `T`\n"
@@ -8356,6 +8402,13 @@ public class SqlParserTest {
     public Sql expression() {
       return expression ? this : new Sql(sql, true);
     }
+
+    /** Removes the carets from the SQL string. Useful if you want to run
+     * a test once at a conformance level where it fails, then run it again
+     * at a conformance level where it succeeds. */
+    public Sql sansCarets() {
+      return new Sql(sql.replace("^", ""), expression);
+    }
   }
 
   /** Runs tests on period operators such as OVERLAPS, IMMEDIATELY PRECEDES. */

http://git-wip-us.apache.org/repos/asf/calcite/blob/2a4f6c2c/core/src/test/resources/sql/misc.iq
----------------------------------------------------------------------
diff --git a/core/src/test/resources/sql/misc.iq b/core/src/test/resources/sql/misc.iq
index 0aeb99d..e643b97 100644
--- a/core/src/test/resources/sql/misc.iq
+++ b/core/src/test/resources/sql/misc.iq
@@ -1330,8 +1330,27 @@ from "scott".emp;
 # Explicit ROW
 select deptno, row (empno, deptno) as r
 from "scott".emp;
-ROW expression encountered in illegal context
-!error
++--------+------------+
+| DEPTNO | R          |
++--------+------------+
+|     10 | {7782, 10} |
+|     10 | {7839, 10} |
+|     10 | {7934, 10} |
+|     20 | {7369, 20} |
+|     20 | {7566, 20} |
+|     20 | {7788, 20} |
+|     20 | {7876, 20} |
+|     20 | {7902, 20} |
+|     30 | {7499, 30} |
+|     30 | {7521, 30} |
+|     30 | {7654, 30} |
+|     30 | {7698, 30} |
+|     30 | {7844, 30} |
+|     30 | {7900, 30} |
++--------+------------+
+(14 rows)
+
+!ok
 
 # [CALCITE-877] Allow ROW as argument to COLLECT
 select deptno, collect(r) as empnos