This is an automated email from the ASF dual-hosted git repository.

danny0405 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 b523007  [CALCITE-3855] Supports snapshot on table with virtual 
columns during sql-to-rel conversion
b523007 is described below

commit b5230070e5f495e2c5a7e4baa726a9f7a8877630
Author: yuzhao.cyz <yuzhao....@gmail.com>
AuthorDate: Thu Mar 12 16:01:18 2020 +0800

    [CALCITE-3855] Supports snapshot on table with virtual columns during 
sql-to-rel conversion
    
    In SqlToRelConverter#convertTemporalTable, we actually should not assume
    that the rel to snapshot is always a TableScan.
---
 .../apache/calcite/sql2rel/SqlToRelConverter.java  |  4 +-
 .../apache/calcite/test/SqlToRelConverterTest.java | 31 ++++++++++--
 .../test/catalog/MockCatalogReaderExtended.java    |  6 ++-
 .../catalog/VirtualColumnsExpressionFactory.java   | 18 +++++++
 .../apache/calcite/test/SqlToRelConverterTest.xml  | 58 ++++++++++++++++++++--
 5 files changed, 106 insertions(+), 11 deletions(-)

diff --git 
a/core/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java 
b/core/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java
index 783e981..f249643 100644
--- a/core/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java
+++ b/core/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java
@@ -47,7 +47,6 @@ import org.apache.calcite.rel.core.Project;
 import org.apache.calcite.rel.core.RelFactories;
 import org.apache.calcite.rel.core.Sample;
 import org.apache.calcite.rel.core.Sort;
-import org.apache.calcite.rel.core.TableScan;
 import org.apache.calcite.rel.core.Uncollect;
 import org.apache.calcite.rel.core.Values;
 import org.apache.calcite.rel.hint.HintStrategyTable;
@@ -2490,9 +2489,8 @@ public class SqlToRelConverter {
     // convert inner query, could be a table name or a derived table
     SqlNode expr = snapshot.getTableRef();
     convertFrom(bb, expr);
-    final TableScan scan = (TableScan) bb.root;
 
-    final RelNode snapshotRel = relBuilder.push(scan).snapshot(period).build();
+    final RelNode snapshotRel = 
relBuilder.push(bb.root).snapshot(period).build();
 
     bb.setRoot(snapshotRel, false);
   }
diff --git 
a/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java 
b/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java
index dc133ea..ac78d1b 100644
--- a/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java
+++ b/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java
@@ -1121,13 +1121,20 @@ public class SqlToRelConverterTest extends 
SqlToRelTestBase {
     sql("select * from dept, lateral table(ramp(deptno))").ok();
   }
 
-  @Test public void testSnapshotOnTemporalTable() {
+  @Test public void testSnapshotOnTemporalTable1() {
     final String sql = "select * from products_temporal "
         + "for system_time as of TIMESTAMP '2011-01-02 00:00:00'";
     sql(sql).ok();
   }
 
-  @Test public void testJoinTemporalTableOnSpecificTime() {
+  @Test public void testSnapshotOnTemporalTable2() {
+    // Test temporal table with virtual columns.
+    final String sql = "select * from VIRTUALCOLUMNS.VC_T1 "
+        + "for system_time as of TIMESTAMP '2011-01-02 00:00:00'";
+    sql(sql).with(getExtendedTester()).ok();
+  }
+
+  @Test public void testJoinTemporalTableOnSpecificTime1() {
     final String sql = "select stream *\n"
         + "from orders,\n"
         + "  products_temporal for system_time as of\n"
@@ -1135,7 +1142,16 @@ public class SqlToRelConverterTest extends 
SqlToRelTestBase {
     sql(sql).ok();
   }
 
-  @Test public void testJoinTemporalTableOnColumnReference() {
+  @Test public void testJoinTemporalTableOnSpecificTime2() {
+    // Test temporal table with virtual columns.
+    final String sql = "select stream *\n"
+        + "from orders,\n"
+        + "  VIRTUALCOLUMNS.VC_T1 for system_time as of\n"
+        + "    TIMESTAMP '2011-01-02 00:00:00'";
+    sql(sql).with(getExtendedTester()).ok();
+  }
+
+  @Test public void testJoinTemporalTableOnColumnReference1() {
     final String sql = "select stream *\n"
         + "from orders\n"
         + "join products_temporal for system_time as of orders.rowtime\n"
@@ -1143,6 +1159,15 @@ public class SqlToRelConverterTest extends 
SqlToRelTestBase {
     sql(sql).ok();
   }
 
+  @Test public void testJoinTemporalTableOnColumnReference2() {
+    // Test temporal table with virtual columns.
+    final String sql = "select stream *\n"
+        + "from orders\n"
+        + "join VIRTUALCOLUMNS.VC_T1 for system_time as of orders.rowtime\n"
+        + "on orders.productid = VIRTUALCOLUMNS.VC_T1.a";
+    sql(sql).with(getExtendedTester()).ok();
+  }
+
   /**
    * Lateral join with temporal table, both snapshot's input scan
    * and snapshot's period reference outer columns. Should not
diff --git 
a/core/src/test/java/org/apache/calcite/test/catalog/MockCatalogReaderExtended.java
 
b/core/src/test/java/org/apache/calcite/test/catalog/MockCatalogReaderExtended.java
index b867eaa..a12cf3b 100644
--- 
a/core/src/test/java/org/apache/calcite/test/catalog/MockCatalogReaderExtended.java
+++ 
b/core/src/test/java/org/apache/calcite/test/catalog/MockCatalogReaderExtended.java
@@ -119,12 +119,14 @@ public class MockCatalogReaderExtended extends 
MockCatalogReaderSimple {
     registerSchema(virtualColumnsSchema);
     final MockTable virtualColumnsTable1 =
         MockTable.create(this, virtualColumnsSchema, "VC_T1", false, 100,
-            null, new VirtualColumnsExpressionFactory(), false);
+            null, new VirtualColumnsExpressionFactory(), true);
     virtualColumnsTable1.addColumn("A", f.intTypeNull);
     virtualColumnsTable1.addColumn("B", f.bigintType);
     virtualColumnsTable1.addColumn("C", f.varchar10Type);
     virtualColumnsTable1.addColumn("D", f.intTypeNull);
-    virtualColumnsTable1.addColumn("E", f.bigintType);
+    // Column E has the same type as column A because it's a virtual column
+    // with expression that references column A.
+    virtualColumnsTable1.addColumn("E", f.intTypeNull);
     // Same schema with VC_T1 but with different table name.
     final MockTable virtualColumnsTable2 =
         MockTable.create(this, virtualColumnsSchema, "VC_T2", false, 100,
diff --git 
a/core/src/test/java/org/apache/calcite/test/catalog/VirtualColumnsExpressionFactory.java
 
b/core/src/test/java/org/apache/calcite/test/catalog/VirtualColumnsExpressionFactory.java
index 2efbdcb..8e206d1 100644
--- 
a/core/src/test/java/org/apache/calcite/test/catalog/VirtualColumnsExpressionFactory.java
+++ 
b/core/src/test/java/org/apache/calcite/test/catalog/VirtualColumnsExpressionFactory.java
@@ -17,7 +17,11 @@
 package org.apache.calcite.test.catalog;
 
 import org.apache.calcite.plan.RelOptTable;
+import org.apache.calcite.rex.RexNode;
 import org.apache.calcite.schema.ColumnStrategy;
+import org.apache.calcite.sql.SqlNode;
+import org.apache.calcite.sql.parser.SqlParser;
+import org.apache.calcite.sql2rel.InitializerContext;
 import org.apache.calcite.sql2rel.NullInitializerExpressionFactory;
 
 /** Define column strategies for the "VIRTUALCOLUMNS" table. */
@@ -32,4 +36,18 @@ public class VirtualColumnsExpressionFactory extends 
NullInitializerExpressionFa
       return super.generationStrategy(table, iColumn);
     }
   }
+
+  @Override public RexNode newColumnDefaultValue(
+      RelOptTable table, int iColumn, InitializerContext context) {
+    if (iColumn == 4) {
+      final SqlNode node = context.parseExpression(SqlParser.Config.DEFAULT, 
"A + 1");
+      // Actually we should validate the node with physical schema,
+      // here full table schema(includes the virtual columns) also works
+      // because the expression "A + 1" does not reference any virtual column.
+      final SqlNode validated = context.validateExpression(table.getRowType(), 
node);
+      return context.convertExpression(validated);
+    } else {
+      return super.newColumnDefaultValue(table, iColumn, context);
+    }
+  }
 }
diff --git 
a/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml 
b/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml
index 92ad19a..2f00acf 100644
--- a/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml
+++ b/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml
@@ -323,7 +323,7 @@ LogicalProject(DEPTNO=[$0], NAME=[$1], I=[$2])
 ]]>
         </Resource>
     </TestCase>
-    <TestCase name="testSnapshotOnTemporalTable">
+    <TestCase name="testSnapshotOnTemporalTable1">
         <Resource name="sql">
             <![CDATA[select * from products_temporal for system_time as of 
TIMESTAMP '2011-01-02 00:00:00']]>
         </Resource>
@@ -335,7 +335,20 @@ LogicalProject(PRODUCTID=[$0], NAME=[$1], SUPPLIERID=[$2], 
SYS_START=[$3], SYS_E
 ]]>
         </Resource>
     </TestCase>
-    <TestCase name="testJoinTemporalTableOnSpecificTime">
+    <TestCase name="testSnapshotOnTemporalTable2">
+        <Resource name="sql">
+            <![CDATA[select * from VIRTUALCOLUMNS.VC_T1 for system_time as of 
TIMESTAMP '2011-01-02 00:00:00']]>
+        </Resource>
+        <Resource name="plan">
+            <![CDATA[
+LogicalProject(A=[$0], B=[$1], C=[$2], D=[$3], E=[$4])
+  LogicalSnapshot(period=[2011-01-02 00:00:00])
+    LogicalProject(A=[$0], B=[$1], C=[$2], D=[$3], $f4=[+($0, 1)])
+      LogicalTableScan(table=[[CATALOG, VIRTUALCOLUMNS, VC_T1]])
+]]>
+        </Resource>
+    </TestCase>
+    <TestCase name="testJoinTemporalTableOnSpecificTime1">
         <Resource name="sql">
             <![CDATA[select stream *
 from orders,
@@ -353,7 +366,26 @@ LogicalDelta
 ]]>
         </Resource>
     </TestCase>
-    <TestCase name="testJoinTemporalTableOnColumnReference">
+    <TestCase name="testJoinTemporalTableOnSpecificTime2">
+        <Resource name="sql">
+            <![CDATA[select stream *
+from orders,
+  VIRTUALCOLUMNS.VC_T1 for system_time as of
+    TIMESTAMP '2011-01-02 00:00:00']]>
+        </Resource>
+        <Resource name="plan">
+            <![CDATA[
+LogicalDelta
+  LogicalProject(ROWTIME=[$0], PRODUCTID=[$1], ORDERID=[$2], A=[$3], B=[$4], 
C=[$5], D=[$6], E=[$7])
+    LogicalJoin(condition=[true], joinType=[inner])
+      LogicalTableScan(table=[[CATALOG, SALES, ORDERS]])
+      LogicalSnapshot(period=[2011-01-02 00:00:00])
+        LogicalProject(A=[$0], B=[$1], C=[$2], D=[$3], $f4=[+($0, 1)])
+          LogicalTableScan(table=[[CATALOG, VIRTUALCOLUMNS, VC_T1]])
+]]>
+        </Resource>
+    </TestCase>
+    <TestCase name="testJoinTemporalTableOnColumnReference1">
         <Resource name="sql">
             <![CDATA[select stream *
 from orders
@@ -372,6 +404,26 @@ LogicalDelta
 ]]>
         </Resource>
     </TestCase>
+    <TestCase name="testJoinTemporalTableOnColumnReference2">
+        <Resource name="sql">
+            <![CDATA[select stream *
+from orders
+join VIRTUALCOLUMNS.VC_T1 for system_time as of orders.rowtime
+on orders.productid = VIRTUALCOLUMNS.VC_T1.a]]>
+        </Resource>
+        <Resource name="plan">
+            <![CDATA[
+LogicalDelta
+  LogicalProject(ROWTIME=[$0], PRODUCTID=[$1], ORDERID=[$2], A=[$3], B=[$4], 
C=[$5], D=[$6], E=[$7])
+    LogicalCorrelate(correlation=[$cor0], joinType=[inner], 
requiredColumns=[{0, 1}])
+      LogicalTableScan(table=[[CATALOG, SALES, ORDERS]])
+      LogicalFilter(condition=[=($cor0.PRODUCTID, $0)])
+        LogicalSnapshot(period=[$cor0.ROWTIME])
+          LogicalProject(A=[$0], B=[$1], C=[$2], D=[$3], $f4=[+($0, 1)])
+            LogicalTableScan(table=[[CATALOG, VIRTUALCOLUMNS, VC_T1]])
+]]>
+        </Resource>
+    </TestCase>
     <TestCase name="testCrossJoinTemporalTable1">
         <Resource name="sql">
             <![CDATA[select stream *

Reply via email to