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 <[email protected]>
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 *