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 2016/12/07 19:08:40 UTC
calcite git commit: [CALCITE-1527] Support DML in the JDBC adapter
(Christian Tzolov)
Repository: calcite
Updated Branches:
refs/heads/master 106dcc0fa -> 02752fe78
[CALCITE-1527] Support DML in the JDBC adapter (Christian Tzolov)
Extend CalcisteAssert to verify DML statements;
Resolve the RowType for SqlNode UPDATE consistently with the INSERT and DELETE;
Add field sourceExpressionList field to TableModify;
Implement DML for JDBC Adapter (i.e. DmlRel-To-Sql);
Make sure the ResultSetEnumerable keeps the statment/connection open.
Use same code path for INSERT ... VALUES and INSERT ... SELECT;
fix pretty-printing of INSERT ... VALUES (Julian Hyde).
Project: http://git-wip-us.apache.org/repos/asf/calcite/repo
Commit: http://git-wip-us.apache.org/repos/asf/calcite/commit/02752fe7
Tree: http://git-wip-us.apache.org/repos/asf/calcite/tree/02752fe7
Diff: http://git-wip-us.apache.org/repos/asf/calcite/diff/02752fe7
Branch: refs/heads/master
Commit: 02752fe78f817ed317b8873d2f4c7b79bfe8b9b5
Parents: 106dcc0
Author: Christian Tzolov <ch...@gmail.com>
Authored: Sun Dec 4 17:41:32 2016 +0100
Committer: Julian Hyde <jh...@apache.org>
Committed: Wed Dec 7 08:34:46 2016 -0800
----------------------------------------------------------------------
.../enumerable/EnumerableTableModify.java | 7 +-
.../enumerable/EnumerableTableModifyRule.java | 1 +
.../apache/calcite/adapter/jdbc/JdbcRules.java | 11 +-
.../apache/calcite/adapter/jdbc/JdbcTable.java | 26 ++-
.../adapter/jdbc/JdbcToEnumerableConverter.java | 2 +-
.../org/apache/calcite/plan/RelOptUtil.java | 1 +
.../calcite/prepare/CalcitePrepareImpl.java | 2 +
.../apache/calcite/rel/core/TableModify.java | 94 ++++++---
.../calcite/rel/logical/LogicalTableModify.java | 15 +-
.../calcite/rel/rel2sql/RelToSqlConverter.java | 108 +++++++---
.../calcite/rel/rel2sql/SqlImplementor.java | 36 +++-
.../calcite/runtime/ResultSetEnumerable.java | 14 +-
.../apache/calcite/schema/ModifiableTable.java | 2 +
.../java/org/apache/calcite/sql/SqlInsert.java | 2 +-
.../apache/calcite/sql/SqlValuesOperator.java | 3 +-
.../java/org/apache/calcite/sql/SqlWriter.java | 10 +
.../apache/calcite/sql/fun/SqlRowOperator.java | 6 +-
.../calcite/sql/fun/SqlStdOperatorTable.java | 2 +-
.../calcite/sql/pretty/SqlPrettyWriter.java | 1 +
.../sql2rel/RelStructuredTypeFlattener.java | 1 +
.../calcite/sql2rel/SqlToRelConverter.java | 21 +-
.../rel/rel2sql/RelToSqlConverterTest.java | 7 +-
.../calcite/sql/parser/SqlParserTest.java | 23 ++-
.../org/apache/calcite/test/CalciteAssert.java | 29 ++-
.../apache/calcite/test/JdbcAdapterTest.java | 196 +++++++++++++++++++
.../java/org/apache/calcite/test/JdbcTest.java | 8 +-
.../calcite/test/SqlToRelConverterTest.java | 1 +
.../calcite/test/SqlToRelConverterTest.xml | 22 +--
.../adapter/spark/JdbcToSparkConverter.java | 2 +-
29 files changed, 533 insertions(+), 120 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/calcite/blob/02752fe7/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableTableModify.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableTableModify.java b/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableTableModify.java
index adcd417..07128e4 100644
--- a/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableTableModify.java
+++ b/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableTableModify.java
@@ -28,6 +28,7 @@ import org.apache.calcite.plan.RelTraitSet;
import org.apache.calcite.prepare.Prepare;
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.TableModify;
+import org.apache.calcite.rex.RexNode;
import org.apache.calcite.schema.ModifiableTable;
import org.apache.calcite.util.BuiltInMethod;
@@ -43,9 +44,10 @@ public class EnumerableTableModify extends TableModify
implements EnumerableRel {
public EnumerableTableModify(RelOptCluster cluster, RelTraitSet traits,
RelOptTable table, Prepare.CatalogReader catalogReader, RelNode child,
- Operation operation, List<String> updateColumnList, boolean flattened) {
+ Operation operation, List<String> updateColumnList,
+ List<RexNode> sourceExpressionList, boolean flattened) {
super(cluster, traits, table, catalogReader, child, operation,
- updateColumnList, flattened);
+ updateColumnList, sourceExpressionList, flattened);
assert child.getConvention() instanceof EnumerableConvention;
assert getConvention() instanceof EnumerableConvention;
final ModifiableTable modifiableTable =
@@ -64,6 +66,7 @@ public class EnumerableTableModify extends TableModify
sole(inputs),
getOperation(),
getUpdateColumnList(),
+ getSourceExpressionList(),
isFlattened());
}
http://git-wip-us.apache.org/repos/asf/calcite/blob/02752fe7/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableTableModifyRule.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableTableModifyRule.java b/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableTableModifyRule.java
index 11c6f2c..321115f 100644
--- a/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableTableModifyRule.java
+++ b/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableTableModifyRule.java
@@ -50,6 +50,7 @@ public class EnumerableTableModifyRule extends ConverterRule {
convert(modify.getInput(), traitSet),
modify.getOperation(),
modify.getUpdateColumnList(),
+ modify.getSourceExpressionList(),
modify.isFlattened());
}
}
http://git-wip-us.apache.org/repos/asf/calcite/blob/02752fe7/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcRules.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcRules.java b/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcRules.java
index 03c36c1..885ff0c 100644
--- a/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcRules.java
+++ b/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcRules.java
@@ -729,6 +729,7 @@ public class JdbcRules {
convert(modify.getInput(), traitSet),
modify.getOperation(),
modify.getUpdateColumnList(),
+ modify.getSourceExpressionList(),
modify.isFlattened());
}
}
@@ -744,9 +745,10 @@ public class JdbcRules {
RelNode input,
Operation operation,
List<String> updateColumnList,
+ List<RexNode> sourceExpressionList,
boolean flattened) {
super(cluster, traitSet, table, catalogReader, input, operation,
- updateColumnList, flattened);
+ updateColumnList, sourceExpressionList, flattened);
assert input.getConvention() instanceof JdbcConvention;
assert getConvention() instanceof JdbcConvention;
final ModifiableTable modifiableTable =
@@ -760,11 +762,16 @@ public class JdbcRules {
}
}
+ @Override public RelOptCost computeSelfCost(RelOptPlanner planner,
+ RelMetadataQuery mq) {
+ return super.computeSelfCost(planner, mq).multiplyBy(.1);
+ }
+
@Override public RelNode copy(RelTraitSet traitSet, List<RelNode> inputs) {
return new JdbcTableModify(
getCluster(), traitSet, getTable(), getCatalogReader(),
sole(inputs), getOperation(), getUpdateColumnList(),
- isFlattened());
+ getSourceExpressionList(), isFlattened());
}
public JdbcImplementor.Result implement(JdbcImplementor implementor) {
http://git-wip-us.apache.org/repos/asf/calcite/blob/02752fe7/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcTable.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcTable.java b/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcTable.java
index 237a822..d432e4a 100644
--- a/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcTable.java
+++ b/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcTable.java
@@ -25,13 +25,21 @@ import org.apache.calcite.linq4j.Enumerable;
import org.apache.calcite.linq4j.Enumerator;
import org.apache.calcite.linq4j.QueryProvider;
import org.apache.calcite.linq4j.Queryable;
+import org.apache.calcite.plan.Convention;
+import org.apache.calcite.plan.RelOptCluster;
import org.apache.calcite.plan.RelOptTable;
+import org.apache.calcite.prepare.Prepare.CatalogReader;
import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.core.TableModify;
+import org.apache.calcite.rel.core.TableModify.Operation;
+import org.apache.calcite.rel.logical.LogicalTableModify;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.rel.type.RelDataTypeFactory;
import org.apache.calcite.rel.type.RelDataTypeField;
import org.apache.calcite.rel.type.RelProtoDataType;
+import org.apache.calcite.rex.RexNode;
import org.apache.calcite.runtime.ResultSetEnumerable;
+import org.apache.calcite.schema.ModifiableTable;
import org.apache.calcite.schema.ScannableTable;
import org.apache.calcite.schema.Schema;
import org.apache.calcite.schema.SchemaPlus;
@@ -52,6 +60,7 @@ import com.google.common.collect.Lists;
import java.sql.SQLException;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -66,7 +75,7 @@ import java.util.List;
* executed efficiently on the JDBC server.</p>
*/
class JdbcTable extends AbstractQueryableTable
- implements TranslatableTable, ScannableTable {
+ implements TranslatableTable, ScannableTable, ModifiableTable {
private RelProtoDataType protoRowType;
private final JdbcSchema jdbcSchema;
private final String jdbcCatalogName;
@@ -169,6 +178,21 @@ class JdbcTable extends AbstractQueryableTable
JdbcUtils.ObjectArrayRowBuilder.factory(fieldClasses(typeFactory)));
}
+ @Override public Collection getModifiableCollection() {
+ return null;
+ }
+
+ @Override public TableModify toModificationRel(RelOptCluster cluster,
+ RelOptTable table, CatalogReader catalogReader, RelNode input,
+ Operation operation, List<String> updateColumnList,
+ List<RexNode> sourceExpressionList, boolean flattened) {
+ jdbcSchema.convention.register(cluster.getPlanner());
+
+ return new LogicalTableModify(cluster, cluster.traitSetOf(Convention.NONE),
+ table, catalogReader, input, operation, updateColumnList,
+ sourceExpressionList, flattened);
+ }
+
/** Enumerable that returns the contents of a {@link JdbcTable} by connecting
* to the JDBC data source. */
private class JdbcTableQueryable<T> extends AbstractTableQueryable<T> {
http://git-wip-us.apache.org/repos/asf/calcite/blob/02752fe7/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcToEnumerableConverter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcToEnumerableConverter.java b/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcToEnumerableConverter.java
index 732772d..c74e741 100644
--- a/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcToEnumerableConverter.java
+++ b/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcToEnumerableConverter.java
@@ -297,7 +297,7 @@ public class JdbcToEnumerableConverter
(JavaTypeFactory) getCluster().getTypeFactory());
final JdbcImplementor.Result result =
jdbcImplementor.visitChild(0, getInput());
- return result.asQuery().toSqlString(dialect).getSql();
+ return result.asStatement().toSqlString(dialect).getSql();
}
/** Whether this JDBC driver needs you to pass a Calendar object to methods
http://git-wip-us.apache.org/repos/asf/calcite/blob/02752fe7/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java b/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java
index 9491220..6ab8072 100644
--- a/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java
+++ b/core/src/main/java/org/apache/calcite/plan/RelOptUtil.java
@@ -1752,6 +1752,7 @@ public abstract class RelOptUtil {
switch (kind) {
case INSERT:
case DELETE:
+ case UPDATE:
return typeFactory.createStructType(
ImmutableList.of(
Pair.of(AvaticaConnection.ROWCOUNT_COLUMN_NAME,
http://git-wip-us.apache.org/repos/asf/calcite/blob/02752fe7/core/src/main/java/org/apache/calcite/prepare/CalcitePrepareImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/prepare/CalcitePrepareImpl.java b/core/src/main/java/org/apache/calcite/prepare/CalcitePrepareImpl.java
index 06e7263..9125d0b 100644
--- a/core/src/main/java/org/apache/calcite/prepare/CalcitePrepareImpl.java
+++ b/core/src/main/java/org/apache/calcite/prepare/CalcitePrepareImpl.java
@@ -660,6 +660,7 @@ public class CalcitePrepareImpl implements CalcitePrepare {
switch (kind) {
case INSERT:
case DELETE:
+ case UPDATE:
return Meta.StatementType.IS_DML;
default:
return Meta.StatementType.SELECT;
@@ -750,6 +751,7 @@ public class CalcitePrepareImpl implements CalcitePrepare {
switch (sqlNode.getKind()) {
case INSERT:
case DELETE:
+ case UPDATE:
case EXPLAIN:
// FIXME: getValidatedNodeType is wrong for DML
x = RelOptUtil.createDmlRowType(sqlNode.getKind(), typeFactory);
http://git-wip-us.apache.org/repos/asf/calcite/blob/02752fe7/core/src/main/java/org/apache/calcite/rel/core/TableModify.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/core/TableModify.java b/core/src/main/java/org/apache/calcite/rel/core/TableModify.java
index 79b6a0d..e94ca9a 100644
--- a/core/src/main/java/org/apache/calcite/rel/core/TableModify.java
+++ b/core/src/main/java/org/apache/calcite/rel/core/TableModify.java
@@ -28,10 +28,13 @@ import org.apache.calcite.rel.RelWriter;
import org.apache.calcite.rel.SingleRel;
import org.apache.calcite.rel.metadata.RelMetadataQuery;
import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.rel.type.RelDataTypeFactory;
+import org.apache.calcite.rex.RexNode;
import org.apache.calcite.sql.SqlKind;
import org.apache.calcite.sql.type.SqlTypeUtil;
-import java.util.Collections;
+import com.google.common.base.Preconditions;
+
import java.util.List;
/**
@@ -70,25 +73,57 @@ public abstract class TableModify extends SingleRel {
protected final RelOptTable table;
private final Operation operation;
private final List<String> updateColumnList;
+ private final List<RexNode> sourceExpressionList;
private RelDataType inputRowType;
private final boolean flattened;
//~ Constructors -----------------------------------------------------------
+ /**
+ * Creates a {@code TableModify}.
+ *
+ * <p>The UPDATE operation has format like this:
+ * <blockquote>
+ * <pre>UPDATE table SET iden1 = exp1, ident2 = exp2 WHERE condition</pre>
+ * </blockquote>
+ *
+ * @param cluster Cluster this relational expression belongs to
+ * @param traitSet Traits of this relational expression
+ * @param table Target table to modify
+ * @param catalogReader accessor to the table metadata.
+ * @param input Sub-query or filter condition
+ * @param operation Modify operation (INSERT, UPDATE, DELETE)
+ * @param updateColumnList List of column identifiers to be updated
+ * (e.g. ident1, ident2); null if not UPDATE
+ * @param sourceExpressionList List of value expressions to be set
+ * (e.g. exp1, exp2); null if not UPDATE
+ * @param flattened Whether set flattens the input row type
+ */
protected TableModify(
RelOptCluster cluster,
- RelTraitSet traits,
+ RelTraitSet traitSet,
RelOptTable table,
Prepare.CatalogReader catalogReader,
- RelNode child,
+ RelNode input,
Operation operation,
List<String> updateColumnList,
+ List<RexNode> sourceExpressionList,
boolean flattened) {
- super(cluster, traits, child);
+ super(cluster, traitSet, input);
this.table = table;
this.catalogReader = catalogReader;
this.operation = operation;
this.updateColumnList = updateColumnList;
+ this.sourceExpressionList = sourceExpressionList;
+ if (operation == Operation.UPDATE) {
+ Preconditions.checkNotNull(updateColumnList);
+ Preconditions.checkNotNull(sourceExpressionList);
+ Preconditions.checkArgument(sourceExpressionList.size()
+ == updateColumnList.size());
+ } else {
+ Preconditions.checkArgument(updateColumnList == null);
+ Preconditions.checkArgument(sourceExpressionList == null);
+ }
if (table.getRelOptSchema() != null) {
cluster.getPlanner().registerSchema(table.getRelOptSchema());
}
@@ -109,6 +144,10 @@ public abstract class TableModify extends SingleRel {
return updateColumnList;
}
+ public List<RexNode> getSourceExpressionList() {
+ return sourceExpressionList;
+ }
+
public boolean isFlattened() {
return flattened;
}
@@ -133,44 +172,43 @@ public abstract class TableModify extends SingleRel {
return operation == Operation.MERGE;
}
- // implement RelNode
- public RelDataType deriveRowType() {
+ @Override public RelDataType deriveRowType() {
return RelOptUtil.createDmlRowType(
SqlKind.INSERT, getCluster().getTypeFactory());
}
- // override RelNode
- public RelDataType getExpectedInputRowType(int ordinalInParent) {
+ @Override public RelDataType getExpectedInputRowType(int ordinalInParent) {
assert ordinalInParent == 0;
if (inputRowType != null) {
return inputRowType;
}
- if (isUpdate()) {
+ final RelDataTypeFactory typeFactory = getCluster().getTypeFactory();
+ final RelDataType rowType = table.getRowType();
+ switch (operation) {
+ case UPDATE:
inputRowType =
- getCluster().getTypeFactory().createJoinType(
- table.getRowType(),
- getCatalogReader().createTypeFromProjection(
- table.getRowType(),
+ typeFactory.createJoinType(rowType,
+ getCatalogReader().createTypeFromProjection(rowType,
updateColumnList));
- } else if (isMerge()) {
+ break;
+ case MERGE:
inputRowType =
- getCluster().getTypeFactory().createJoinType(
- getCluster().getTypeFactory().createJoinType(
- table.getRowType(),
- table.getRowType()),
- getCatalogReader().createTypeFromProjection(
- table.getRowType(),
+ typeFactory.createJoinType(
+ typeFactory.createJoinType(rowType, rowType),
+ getCatalogReader().createTypeFromProjection(rowType,
updateColumnList));
- } else {
- inputRowType = table.getRowType();
+ break;
+ default:
+ inputRowType = rowType;
+ break;
}
if (flattened) {
inputRowType =
SqlTypeUtil.flattenRecordType(
- getCluster().getTypeFactory(),
+ typeFactory,
inputRowType,
null);
}
@@ -178,15 +216,13 @@ public abstract class TableModify extends SingleRel {
return inputRowType;
}
- public RelWriter explainTerms(RelWriter pw) {
+ @Override public RelWriter explainTerms(RelWriter pw) {
return super.explainTerms(pw)
.item("table", table.getQualifiedName())
.item("operation", getOperation())
- .item(
- "updateColumnList",
- (updateColumnList == null)
- ? Collections.EMPTY_LIST
- : updateColumnList)
+ .itemIf("updateColumnList", updateColumnList, updateColumnList != null)
+ .itemIf("sourceExpressionList", sourceExpressionList,
+ sourceExpressionList != null)
.item("flattened", flattened);
}
http://git-wip-us.apache.org/repos/asf/calcite/blob/02752fe7/core/src/main/java/org/apache/calcite/rel/logical/LogicalTableModify.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/logical/LogicalTableModify.java b/core/src/main/java/org/apache/calcite/rel/logical/LogicalTableModify.java
index f8c76ab..3c4d274 100644
--- a/core/src/main/java/org/apache/calcite/rel/logical/LogicalTableModify.java
+++ b/core/src/main/java/org/apache/calcite/rel/logical/LogicalTableModify.java
@@ -23,6 +23,7 @@ import org.apache.calcite.plan.RelTraitSet;
import org.apache.calcite.prepare.Prepare;
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.TableModify;
+import org.apache.calcite.rex.RexNode;
import java.util.List;
@@ -40,9 +41,10 @@ public final class LogicalTableModify extends TableModify {
*/
public LogicalTableModify(RelOptCluster cluster, RelTraitSet traitSet,
RelOptTable table, Prepare.CatalogReader schema, RelNode input,
- Operation operation, List<String> updateColumnList, boolean flattened) {
+ Operation operation, List<String> updateColumnList,
+ List<RexNode> sourceExpressionList, boolean flattened) {
super(cluster, traitSet, table, schema, input, operation, updateColumnList,
- flattened);
+ sourceExpressionList, flattened);
}
@Deprecated // to be removed before 2.0
@@ -56,17 +58,19 @@ public final class LogicalTableModify extends TableModify {
input,
operation,
updateColumnList,
+ null,
flattened);
}
/** Creates a LogicalTableModify. */
public static LogicalTableModify create(RelOptTable table,
Prepare.CatalogReader schema, RelNode input,
- Operation operation, List<String> updateColumnList, boolean flattened) {
+ Operation operation, List<String> updateColumnList,
+ List<RexNode> sourceExpressionList, boolean flattened) {
final RelOptCluster cluster = input.getCluster();
final RelTraitSet traitSet = cluster.traitSetOf(Convention.NONE);
return new LogicalTableModify(cluster, traitSet, table, schema, input,
- operation, updateColumnList, flattened);
+ operation, updateColumnList, sourceExpressionList, flattened);
}
//~ Methods ----------------------------------------------------------------
@@ -75,7 +79,8 @@ public final class LogicalTableModify extends TableModify {
List<RelNode> inputs) {
assert traitSet.containsIfApplicable(Convention.NONE);
return new LogicalTableModify(getCluster(), traitSet, table, catalogReader,
- sole(inputs), getOperation(), getUpdateColumnList(), isFlattened());
+ sole(inputs), getOperation(), getUpdateColumnList(),
+ getSourceExpressionList(), isFlattened());
}
}
http://git-wip-us.apache.org/repos/asf/calcite/blob/02752fe7/core/src/main/java/org/apache/calcite/rel/rel2sql/RelToSqlConverter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/rel2sql/RelToSqlConverter.java b/core/src/main/java/org/apache/calcite/rel/rel2sql/RelToSqlConverter.java
index 04f3343..ba7d4a7 100644
--- a/core/src/main/java/org/apache/calcite/rel/rel2sql/RelToSqlConverter.java
+++ b/core/src/main/java/org/apache/calcite/rel/rel2sql/RelToSqlConverter.java
@@ -38,23 +38,28 @@ import org.apache.calcite.rex.RexLocalRef;
import org.apache.calcite.rex.RexNode;
import org.apache.calcite.rex.RexProgram;
import org.apache.calcite.sql.JoinConditionType;
+import org.apache.calcite.sql.SqlDelete;
import org.apache.calcite.sql.SqlDialect;
import org.apache.calcite.sql.SqlIdentifier;
+import org.apache.calcite.sql.SqlInsert;
import org.apache.calcite.sql.SqlJoin;
import org.apache.calcite.sql.SqlLiteral;
import org.apache.calcite.sql.SqlNode;
import org.apache.calcite.sql.SqlNodeList;
import org.apache.calcite.sql.SqlSelect;
+import org.apache.calcite.sql.SqlUpdate;
+import org.apache.calcite.sql.fun.SqlRowOperator;
import org.apache.calcite.sql.fun.SqlSingleValueAggFunction;
import org.apache.calcite.sql.fun.SqlStdOperatorTable;
import org.apache.calcite.sql.parser.SqlParserPos;
import org.apache.calcite.sql.validate.SqlValidatorUtil;
-import org.apache.calcite.util.Pair;
import org.apache.calcite.util.ReflectUtil;
import org.apache.calcite.util.ReflectiveVisitor;
+import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
import java.util.ArrayList;
import java.util.List;
@@ -65,6 +70,8 @@ import java.util.Map;
*/
public class RelToSqlConverter extends SqlImplementor
implements ReflectiveVisitor {
+ /** Similar to {@link SqlStdOperatorTable#ROW}, but does not print "ROW". */
+ private static final SqlRowOperator ANONYMOUS_ROW = new SqlRowOperator(" ");
private final ReflectUtil.MethodDispatcher<Result> dispatcher;
@@ -228,34 +235,14 @@ public class RelToSqlConverter extends SqlImplementor
/** @see #dispatch */
public Result visit(Values e) {
- final List<String> fields = e.getRowType().getFieldNames();
final List<Clause> clauses = ImmutableList.of(Clause.SELECT);
final Map<String, RelDataType> pairs = ImmutableMap.of();
final Context context = aliasContext(pairs, false);
- final List<SqlSelect> selects = new ArrayList<>();
+ final SqlNodeList selects = new SqlNodeList(POS);
for (List<RexLiteral> tuple : e.getTuples()) {
- final List<SqlNode> selectList = new ArrayList<>();
- for (Pair<RexLiteral, String> literal : Pair.zip(tuple, fields)) {
- selectList.add(
- SqlStdOperatorTable.AS.createCall(
- POS,
- context.toSql(null, literal.left),
- new SqlIdentifier(literal.right, POS)));
- }
- selects.add(
- new SqlSelect(POS, SqlNodeList.EMPTY,
- new SqlNodeList(selectList, POS), null, null, null,
- null, null, null, null, null));
- }
- SqlNode query = null;
- for (SqlSelect select : selects) {
- if (query == null) {
- query = select;
- } else {
- query = SqlStdOperatorTable.UNION_ALL.createCall(POS, query,
- select);
- }
+ selects.add(ANONYMOUS_ROW.createCall(exprList(context, tuple)));
}
+ SqlNode query = SqlStdOperatorTable.VALUES.createCall(selects);
return result(query, clauses, e, null);
}
@@ -285,8 +272,77 @@ public class RelToSqlConverter extends SqlImplementor
}
/** @see #dispatch */
- public Result visit(TableModify e) {
- throw new AssertionError("not implemented: " + e);
+ public Result visit(TableModify modify) {
+ final Map<String, RelDataType> pairs = ImmutableMap.of();
+ final Context context = aliasContext(pairs, false);
+
+ // Target Table Name
+ final SqlIdentifier sqlTargetTable =
+ new SqlIdentifier(modify.getTable().getQualifiedName(), POS);
+
+ switch (modify.getOperation()) {
+ case INSERT: {
+ // Convert the input to a SELECT query or keep as VALUES. Not all
+ // dialects support naked VALUES, but all support VALUES inside INSERT.
+ final SqlNode sqlSource =
+ visitChild(0, modify.getInput()).asQueryOrValues();
+
+ final SqlInsert sqlInsert =
+ new SqlInsert(POS, SqlNodeList.EMPTY, sqlTargetTable, sqlSource,
+ identifierList(modify.getInput().getRowType().getFieldNames()));
+
+ return result(sqlInsert, ImmutableList.<Clause>of(), modify, null);
+ }
+ case UPDATE: {
+ final Result input = visitChild(0, modify.getInput());
+
+ final SqlUpdate sqlUpdate =
+ new SqlUpdate(POS, sqlTargetTable,
+ identifierList(modify.getUpdateColumnList()),
+ exprList(context, modify.getSourceExpressionList()),
+ ((SqlSelect) input.node).getWhere(), input.asSelect(),
+ null);
+
+ return result(sqlUpdate, input.clauses, modify, null);
+ }
+ case DELETE: {
+ final Result input = visitChild(0, modify.getInput());
+
+ final SqlDelete sqlDelete =
+ new SqlDelete(POS, sqlTargetTable,
+ input.asSelect().getWhere(), input.asSelect(), null);
+
+ return result(sqlDelete, input.clauses, modify, null);
+ }
+ case MERGE:
+ default:
+ throw new AssertionError("not implemented: " + modify);
+ }
+ }
+
+ /** Converts a list of {@link RexNode} expressions to {@link SqlNode}
+ * expressions. */
+ private SqlNodeList exprList(final Context context,
+ List<? extends RexNode> exprs) {
+ return new SqlNodeList(
+ Lists.transform(exprs,
+ new Function<RexNode, SqlNode>() {
+ public SqlNode apply(RexNode e) {
+ return context.toSql(null, e);
+ }
+ }), POS);
+ }
+
+ /** Converts a list of names expressions to a list of single-part
+ * {@link SqlIdentifier}s. */
+ private SqlNodeList identifierList(List<String> names) {
+ return new SqlNodeList(
+ Lists.transform(names,
+ new Function<String, SqlNode>() {
+ public SqlNode apply(String name) {
+ return new SqlIdentifier(name, POS);
+ }
+ }), POS);
}
@Override public void addSelect(List<SqlNode> selectList, SqlNode node,
http://git-wip-us.apache.org/repos/asf/calcite/blob/02752fe7/core/src/main/java/org/apache/calcite/rel/rel2sql/SqlImplementor.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/rel/rel2sql/SqlImplementor.java b/core/src/main/java/org/apache/calcite/rel/rel2sql/SqlImplementor.java
index e42e84f..22c2690 100644
--- a/core/src/main/java/org/apache/calcite/rel/rel2sql/SqlImplementor.java
+++ b/core/src/main/java/org/apache/calcite/rel/rel2sql/SqlImplementor.java
@@ -468,8 +468,8 @@ public abstract class SqlImplementor {
assert node instanceof SqlJoin
|| node instanceof SqlIdentifier
|| node instanceof SqlCall
- && (((SqlCall) node).getOperator() instanceof SqlSetOperator
- || ((SqlCall) node).getOperator() == SqlStdOperatorTable.AS)
+ && (((SqlCall) node).getOperator() instanceof SqlSetOperator
+ || ((SqlCall) node).getOperator() == SqlStdOperatorTable.AS)
: node;
return new SqlSelect(POS, SqlNodeList.EMPTY, null, node, null, null, null,
SqlNodeList.EMPTY, null, null, null);
@@ -991,13 +991,35 @@ public abstract class SqlImplementor {
}
/** Converts a non-query node into a SELECT node. Set operators (UNION,
- * INTERSECT, EXCEPT) remain as is. */
- public SqlNode asQuery() {
- if (node instanceof SqlCall
- && ((SqlCall) node).getOperator() instanceof SqlSetOperator) {
+ * INTERSECT, EXCEPT) and DML operators (INSERT, UPDATE, DELETE, MERGE)
+ * remain as is. */
+ public SqlNode asStatement() {
+ switch (node.getKind()) {
+ case UNION:
+ case INTERSECT:
+ case EXCEPT:
+ case INSERT:
+ case UPDATE:
+ case DELETE:
+ case MERGE:
+ return node;
+ default:
+ return asSelect();
+ }
+ }
+
+ /** Converts a non-query node into a SELECT node. Set operators (UNION,
+ * INTERSECT, EXCEPT) and VALUES remain as is. */
+ public SqlNode asQueryOrValues() {
+ switch (node.getKind()) {
+ case UNION:
+ case INTERSECT:
+ case EXCEPT:
+ case VALUES:
return node;
+ default:
+ return asSelect();
}
- return asSelect();
}
/** Returns a context that always qualifies identifiers. Useful if the
http://git-wip-us.apache.org/repos/asf/calcite/blob/02752fe7/core/src/main/java/org/apache/calcite/runtime/ResultSetEnumerable.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/runtime/ResultSetEnumerable.java b/core/src/main/java/org/apache/calcite/runtime/ResultSetEnumerable.java
index e7cdf4e..766ef77 100644
--- a/core/src/main/java/org/apache/calcite/runtime/ResultSetEnumerable.java
+++ b/core/src/main/java/org/apache/calcite/runtime/ResultSetEnumerable.java
@@ -19,6 +19,7 @@ package org.apache.calcite.runtime;
import org.apache.calcite.linq4j.AbstractEnumerable;
import org.apache.calcite.linq4j.Enumerable;
import org.apache.calcite.linq4j.Enumerator;
+import org.apache.calcite.linq4j.Linq4j;
import org.apache.calcite.linq4j.function.Function0;
import org.apache.calcite.linq4j.function.Function1;
import org.apache.calcite.linq4j.tree.Primitive;
@@ -140,10 +141,15 @@ public class ResultSetEnumerable<T> extends AbstractEnumerable<T> {
} catch (SQLFeatureNotSupportedException e) {
LOGGER.debug("Failed to set query timeout.");
}
- final ResultSet resultSet = statement.executeQuery(sql);
- statement = null;
- connection = null;
- return new ResultSetEnumerator<T>(resultSet, rowBuilderFactory);
+ if (statement.execute(sql)) {
+ final ResultSet resultSet = statement.getResultSet();
+ statement = null;
+ connection = null;
+ return new ResultSetEnumerator<T>(resultSet, rowBuilderFactory);
+ } else {
+ Integer updateCount = statement.getUpdateCount();
+ return Linq4j.singletonEnumerator((T) updateCount);
+ }
} catch (SQLException e) {
throw new RuntimeException("while executing SQL [" + sql + "]", e);
} finally {
http://git-wip-us.apache.org/repos/asf/calcite/blob/02752fe7/core/src/main/java/org/apache/calcite/schema/ModifiableTable.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/schema/ModifiableTable.java b/core/src/main/java/org/apache/calcite/schema/ModifiableTable.java
index ce0f363..71ac06b 100644
--- a/core/src/main/java/org/apache/calcite/schema/ModifiableTable.java
+++ b/core/src/main/java/org/apache/calcite/schema/ModifiableTable.java
@@ -21,6 +21,7 @@ import org.apache.calcite.plan.RelOptTable;
import org.apache.calcite.prepare.Prepare;
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.TableModify;
+import org.apache.calcite.rex.RexNode;
import java.util.Collection;
import java.util.List;
@@ -46,6 +47,7 @@ public interface ModifiableTable extends QueryableTable {
RelNode child,
TableModify.Operation operation,
List<String> updateColumnList,
+ List<RexNode> sourceExpressionList,
boolean flattened);
}
http://git-wip-us.apache.org/repos/asf/calcite/blob/02752fe7/core/src/main/java/org/apache/calcite/sql/SqlInsert.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/SqlInsert.java b/core/src/main/java/org/apache/calcite/sql/SqlInsert.java
index 19472a7..10a0632 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlInsert.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlInsert.java
@@ -141,7 +141,7 @@ public class SqlInsert extends SqlCall {
columnList.unparse(writer, opLeft, opRight);
}
writer.newlineAndIndent();
- source.unparse(writer, opLeft, opRight);
+ source.unparse(writer, 0, 0);
}
public void validate(SqlValidator validator, SqlValidatorScope scope) {
http://git-wip-us.apache.org/repos/asf/calcite/blob/02752fe7/core/src/main/java/org/apache/calcite/sql/SqlValuesOperator.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/SqlValuesOperator.java b/core/src/main/java/org/apache/calcite/sql/SqlValuesOperator.java
index ef6ae60..9d6bc1e 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlValuesOperator.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlValuesOperator.java
@@ -33,7 +33,8 @@ public class SqlValuesOperator extends SqlSpecialOperator {
SqlCall call,
int leftPrec,
int rightPrec) {
- final SqlWriter.Frame frame = writer.startList("VALUES", "");
+ final SqlWriter.Frame frame =
+ writer.startList(SqlWriter.FrameTypeEnum.VALUES, "VALUES", "");
for (SqlNode operand : call.getOperandList()) {
writer.sep(",");
operand.unparse(writer, 0, 0);
http://git-wip-us.apache.org/repos/asf/calcite/blob/02752fe7/core/src/main/java/org/apache/calcite/sql/SqlWriter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/SqlWriter.java b/core/src/main/java/org/apache/calcite/sql/SqlWriter.java
index d45c831..bd961ae 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlWriter.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlWriter.java
@@ -189,6 +189,16 @@ public interface SqlWriter {
SETOP,
/**
+ * VALUES clause.
+ *
+ * <p>Example:
+ *
+ * <blockquote><pre>VALUES (1, 'a'),
+ * (2, 'b')</pre></blockquote>
+ */
+ VALUES,
+
+ /**
* FROM clause (containing various kinds of JOIN).
*/
FROM_LIST,
http://git-wip-us.apache.org/repos/asf/calcite/blob/02752fe7/core/src/main/java/org/apache/calcite/sql/fun/SqlRowOperator.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/fun/SqlRowOperator.java b/core/src/main/java/org/apache/calcite/sql/fun/SqlRowOperator.java
index 63ab3e9..1221e0f 100644
--- a/core/src/main/java/org/apache/calcite/sql/fun/SqlRowOperator.java
+++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlRowOperator.java
@@ -40,14 +40,14 @@ import java.util.Map;
public class SqlRowOperator extends SqlSpecialOperator {
//~ Constructors -----------------------------------------------------------
- public SqlRowOperator() {
- super(
- "ROW",
+ public SqlRowOperator(String name) {
+ super(name,
SqlKind.ROW, MDX_PRECEDENCE,
false,
null,
InferTypes.RETURN_TYPE,
OperandTypes.VARIADIC);
+ assert name.equals("ROW") || name.equals(" ");
}
//~ Methods ----------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/calcite/blob/02752fe7/core/src/main/java/org/apache/calcite/sql/fun/SqlStdOperatorTable.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/fun/SqlStdOperatorTable.java b/core/src/main/java/org/apache/calcite/sql/fun/SqlStdOperatorTable.java
index d0e60d2..3bbb425 100644
--- a/core/src/main/java/org/apache/calcite/sql/fun/SqlStdOperatorTable.java
+++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlStdOperatorTable.java
@@ -921,7 +921,7 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable {
//-------------------------------------------------------------
// SPECIAL OPERATORS
//-------------------------------------------------------------
- public static final SqlRowOperator ROW = new SqlRowOperator();
+ public static final SqlRowOperator ROW = new SqlRowOperator("ROW");
/**
* A special operator for the subtraction of two DATETIMEs. The format of
http://git-wip-us.apache.org/repos/asf/calcite/blob/02752fe7/core/src/main/java/org/apache/calcite/sql/pretty/SqlPrettyWriter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql/pretty/SqlPrettyWriter.java b/core/src/main/java/org/apache/calcite/sql/pretty/SqlPrettyWriter.java
index 948f3db..a1f719b 100644
--- a/core/src/main/java/org/apache/calcite/sql/pretty/SqlPrettyWriter.java
+++ b/core/src/main/java/org/apache/calcite/sql/pretty/SqlPrettyWriter.java
@@ -454,6 +454,7 @@ public class SqlPrettyWriter implements SqlWriter {
switch (frameTypeEnum) {
case WINDOW_DECL_LIST:
+ case VALUES:
return new FrameImpl(
frameType,
keyword,
http://git-wip-us.apache.org/repos/asf/calcite/blob/02752fe7/core/src/main/java/org/apache/calcite/sql2rel/RelStructuredTypeFlattener.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/sql2rel/RelStructuredTypeFlattener.java b/core/src/main/java/org/apache/calcite/sql2rel/RelStructuredTypeFlattener.java
index c035057..0579d4a 100644
--- a/core/src/main/java/org/apache/calcite/sql2rel/RelStructuredTypeFlattener.java
+++ b/core/src/main/java/org/apache/calcite/sql2rel/RelStructuredTypeFlattener.java
@@ -352,6 +352,7 @@ public class RelStructuredTypeFlattener implements ReflectiveVisitor {
getNewForOldRel(rel.getInput()),
rel.getOperation(),
rel.getUpdateColumnList(),
+ rel.getSourceExpressionList(),
true);
setNewForOldRel(rel, newRel);
}
http://git-wip-us.apache.org/repos/asf/calcite/blob/02752fe7/core/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java
----------------------------------------------------------------------
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 45994a0..c654d31 100644
--- a/core/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java
+++ b/core/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java
@@ -163,6 +163,7 @@ import org.apache.calcite.util.trace.CalciteTrace;
import com.google.common.base.Function;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableList.Builder;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
@@ -2924,7 +2925,7 @@ public class SqlToRelConverter {
if (modifiableTable != null) {
return modifiableTable.toModificationRel(cluster, targetTable,
catalogReader, source, LogicalTableModify.Operation.INSERT, null,
- false);
+ null, false);
}
final ModifiableView modifiableView =
targetTable.unwrap(ModifiableView.class);
@@ -2939,7 +2940,7 @@ public class SqlToRelConverter {
return createModify(delegateRelOptTable, newSource);
}
return LogicalTableModify.create(targetTable, catalogReader, source,
- LogicalTableModify.Operation.INSERT, null, false);
+ LogicalTableModify.Operation.INSERT, null, null, false);
}
/** Wraps a relational expression in the projects and filters implied by
@@ -3138,10 +3139,19 @@ public class SqlToRelConverter {
RelOptTable targetTable = getTargetTable(call);
RelNode sourceRel = convertSelect(call.getSourceSelect(), false);
return LogicalTableModify.create(targetTable, catalogReader, sourceRel,
- LogicalTableModify.Operation.DELETE, null, false);
+ LogicalTableModify.Operation.DELETE, null, null, false);
}
private RelNode convertUpdate(SqlUpdate call) {
+ final SqlValidatorScope scope = validator.getWhereScope(call.getSourceSelect());
+ Blackboard bb = createBlackboard(scope, null, false);
+
+ Builder<RexNode> rexNodeSourceExpressionListBuilder = ImmutableList.builder();
+ for (SqlNode n : call.getSourceExpressionList()) {
+ RexNode rn = bb.convertExpression(n);
+ rexNodeSourceExpressionListBuilder.add(rn);
+ }
+
RelOptTable targetTable = getTargetTable(call);
// convert update column list from SqlIdentifier to String
@@ -3159,7 +3169,8 @@ public class SqlToRelConverter {
RelNode sourceRel = convertSelect(call.getSourceSelect(), false);
return LogicalTableModify.create(targetTable, catalogReader, sourceRel,
- LogicalTableModify.Operation.UPDATE, targetColumnNameList, false);
+ LogicalTableModify.Operation.UPDATE, targetColumnNameList,
+ rexNodeSourceExpressionListBuilder.build(), false);
}
private RelNode convertMerge(SqlMerge call) {
@@ -3240,7 +3251,7 @@ public class SqlToRelConverter {
RelOptUtil.createProject(join, projects, null, true);
return LogicalTableModify.create(targetTable, catalogReader, massagedRel,
- LogicalTableModify.Operation.MERGE, targetColumnNameList, false);
+ LogicalTableModify.Operation.MERGE, targetColumnNameList, null, false);
}
/**
http://git-wip-us.apache.org/repos/asf/calcite/blob/02752fe7/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java
----------------------------------------------------------------------
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 01215d9..275da82 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
@@ -30,13 +30,14 @@ import org.apache.calcite.tools.Planner;
import org.apache.calcite.tools.Program;
import org.apache.calcite.util.Util;
+import com.google.common.base.Throwables;
+
import org.junit.Test;
import java.util.List;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
/**
* Tests for {@link RelToSqlConverter}.
@@ -538,11 +539,11 @@ public class RelToSqlConverterTest {
RelNode rel = planner.rel(validate).rel;
final RelToSqlConverter converter =
new RelToSqlConverter(dialect);
- final SqlNode sqlNode = converter.visitChild(0, rel).asQuery();
+ final SqlNode sqlNode = converter.visitChild(0, rel).asStatement();
assertThat(Util.toLinux(sqlNode.toSqlString(dialect).getSql()),
is(expectedQuery));
} catch (Exception e) {
- assertTrue("Parsing failed throwing error: " + e.getMessage(), false);
+ throw Throwables.propagate(e);
}
return this;
}
http://git-wip-us.apache.org/repos/asf/calcite/blob/02752fe7/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 7978872..294a2f3 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
@@ -1588,7 +1588,8 @@ public class SqlParserTest {
check(
"with v(i,c) as (values (1, 'a'), (2, 'bb'))\n"
+ "select c, i from v",
- "WITH `V` (`I`, `C`) AS (VALUES (ROW(1, 'a')), (ROW(2, 'bb'))) (SELECT `C`, `I`\n"
+ "WITH `V` (`I`, `C`) AS (VALUES (ROW(1, 'a')),\n"
+ + "(ROW(2, 'bb'))) (SELECT `C`, `I`\n"
+ "FROM `V`)");
}
@@ -2835,7 +2836,9 @@ public class SqlParserTest {
check(
"select * from (values(1,'two'), 3, (4, 'five'))",
"SELECT *\n"
- + "FROM (VALUES (ROW(1, 'two')), (ROW(3)), (ROW(4, 'five')))");
+ + "FROM (VALUES (ROW(1, 'two')),\n"
+ + "(ROW(3)),\n"
+ + "(ROW(4, 'five')))");
}
@Test public void testFromValuesWithoutParens() {
@@ -3140,7 +3143,7 @@ public class SqlParserTest {
final String expected3 = ""
+ "EXPLAIN PLAN INCLUDING ATTRIBUTES WITH IMPLEMENTATION FOR\n"
+ "INSERT INTO `EMPS`\n"
- + "(VALUES (ROW(1, 'a')))";
+ + "VALUES (ROW(1, 'a'))";
check("describe insert into emps values (1, 'a')", expected3);
// only allow query or DML, not explain, inside describe
checkFails("^describe^ explain plan for select * from emps",
@@ -3176,7 +3179,7 @@ public class SqlParserTest {
@Test public void testInsertValues() {
final String expected = "INSERT INTO `EMPS`\n"
- + "(VALUES (ROW(1, 'Fredkin')))";
+ + "VALUES (ROW(1, 'Fredkin'))";
sql("insert into emps values (1,'Fredkin')")
.ok(expected)
.node(not(isDdl()));
@@ -3203,7 +3206,7 @@ public class SqlParserTest {
@Test public void testUpsertValues() {
final String expected = "UPSERT INTO `EMPS`\n"
- + "(VALUES (ROW(1, 'Fredkin')))";
+ + "VALUES (ROW(1, 'Fredkin'))";
sql("upsert into emps values (1,'Fredkin')")
.ok(expected)
.node(not(isDdl()));
@@ -3220,7 +3223,7 @@ public class SqlParserTest {
sql("explain plan for upsert into emps1 values (1, 2)")
.ok("EXPLAIN PLAN INCLUDING ATTRIBUTES WITH IMPLEMENTATION FOR\n"
+ "UPSERT INTO `EMPS1`\n"
- + "(VALUES (ROW(1, 2)))");
+ + "VALUES (ROW(1, 2))");
}
@Test public void testDelete() {
@@ -3856,7 +3859,8 @@ public class SqlParserTest {
check(
"select x from (values (1, 2), (3, 4)) as t1 (\"a\", b) where \"a\" > b",
"SELECT `X`\n"
- + "FROM (VALUES (ROW(1, 2)), (ROW(3, 4))) AS `T1` (`a`, `B`)\n"
+ + "FROM (VALUES (ROW(1, 2)),\n"
+ + "(ROW(3, 4))) AS `T1` (`a`, `B`)\n"
+ "WHERE (`a` > `B`)");
// must have at least one column
@@ -7090,10 +7094,11 @@ public class SqlParserTest {
+ "FETCH NEXT 3 ROWS ONLY");
sql("insert into t values next value for my_seq, current value for my_seq")
.ok("INSERT INTO `T`\n"
- + "(VALUES (ROW((NEXT VALUE FOR `MY_SEQ`))), (ROW((CURRENT VALUE FOR `MY_SEQ`))))");
+ + "VALUES (ROW((NEXT VALUE FOR `MY_SEQ`))),\n"
+ + "(ROW((CURRENT VALUE FOR `MY_SEQ`)))");
sql("insert into t values (1, current value for my_seq)")
.ok("INSERT INTO `T`\n"
- + "(VALUES (ROW(1, (CURRENT VALUE FOR `MY_SEQ`))))");
+ + "VALUES (ROW(1, (CURRENT VALUE FOR `MY_SEQ`)))");
}
//~ Inner Interfaces -------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/calcite/blob/02752fe7/core/src/test/java/org/apache/calcite/test/CalciteAssert.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/test/CalciteAssert.java b/core/src/test/java/org/apache/calcite/test/CalciteAssert.java
index e0f8a6b..2eb14f4 100644
--- a/core/src/test/java/org/apache/calcite/test/CalciteAssert.java
+++ b/core/src/test/java/org/apache/calcite/test/CalciteAssert.java
@@ -1316,7 +1316,22 @@ public class CalciteAssert {
}
public AssertQuery planContains(String expected) {
- ensurePlan();
+ ensurePlan(null);
+ assertTrue(
+ "Plan [" + plan + "] contains [" + expected + "]",
+ Util.toLinux(plan)
+ .replaceAll("\\\\r\\\\n", "\\\\n")
+ .contains(expected));
+ return this;
+ }
+
+ public AssertQuery planUpdateHasSql(String expected, int count) {
+ ensurePlan(checkUpdateCount(count));
+ expected = "getDataSource(), \""
+ + expected.replace("\\", "\\\\")
+ .replace("\"", "\\\"")
+ .replaceAll("\n", "\\\\n")
+ + "\"";
assertTrue(
"Plan [" + plan + "] contains [" + expected + "]",
Util.toLinux(plan)
@@ -1334,7 +1349,7 @@ public class CalciteAssert {
+ "\"");
}
- private void ensurePlan() {
+ private void ensurePlan(Function<Integer, Void> checkUpdate) {
if (plan != null) {
return;
}
@@ -1347,11 +1362,11 @@ public class CalciteAssert {
});
try {
assertQuery(createConnection(), sql, limit, materializationsEnabled,
- hooks, null, null, null);
+ hooks, null, checkUpdate, null);
assertNotNull(plan);
} catch (Exception e) {
- throw new RuntimeException(
- "exception while executing [" + sql + "]", e);
+ throw new RuntimeException("exception while executing [" + sql + "]",
+ e);
}
}
@@ -1549,6 +1564,10 @@ public class CalciteAssert {
return this;
}
+ @Override public AssertQuery planUpdateHasSql(String expected, int count) {
+ return this;
+ }
+
@Override public AssertQuery
queryContains(Function<List, Void> predicate1) {
return this;
http://git-wip-us.apache.org/repos/asf/calcite/blob/02752fe7/core/src/test/java/org/apache/calcite/test/JdbcAdapterTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/test/JdbcAdapterTest.java b/core/src/test/java/org/apache/calcite/test/JdbcAdapterTest.java
index f45a9b5..2efea7b 100644
--- a/core/src/test/java/org/apache/calcite/test/JdbcAdapterTest.java
+++ b/core/src/test/java/org/apache/calcite/test/JdbcAdapterTest.java
@@ -18,6 +18,8 @@ package org.apache.calcite.test;
import org.apache.calcite.config.Lex;
import org.apache.calcite.jdbc.CalciteConnection;
+import org.apache.calcite.test.CalciteAssert.AssertThat;
+import org.apache.calcite.test.CalciteAssert.DatabaseInstance;
import com.google.common.base.Function;
import com.google.common.base.Throwables;
@@ -37,11 +39,32 @@ import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
/**
* Tests for the {@code org.apache.calcite.adapter.jdbc} package.
*/
public class JdbcAdapterTest {
+ /** VALUES is not pushed down, currently. */
+ @Test public void testValuesPlan() {
+ final String sql = "select * from \"days\", (values 1, 2) as t(c)";
+ final String explain = "PLAN="
+ + "EnumerableCalc(expr#0..2=[{inputs}], day=[$t1], week_day=[$t2], EXPR$0=[$t0])\n"
+ + " EnumerableJoin(condition=[true], joinType=[inner])\n"
+ + " EnumerableValues(tuples=[[{ 1 }, { 2 }]])\n"
+ + " JdbcToEnumerableConverter\n"
+ + " JdbcTableScan(table=[[foodmart, days]])";
+ final String jdbcSql = "SELECT *\n"
+ + "FROM \"foodmart\".\"days\"";
+ CalciteAssert.model(JdbcTest.FOODMART_MODEL)
+ .query(sql)
+ .explainContains(explain)
+ .runs()
+ .enable(CalciteAssert.DB == CalciteAssert.DatabaseInstance.HSQLDB
+ || CalciteAssert.DB == DatabaseInstance.POSTGRESQL)
+ .planHasSql(jdbcSql);
+ }
+
@Test public void testUnionPlan() {
CalciteAssert.model(JdbcTest.FOODMART_MODEL)
.query("select * from \"sales_fact_1997\"\n"
@@ -586,6 +609,179 @@ public class JdbcAdapterTest {
.enable(CalciteAssert.DB == CalciteAssert.DatabaseInstance.HSQLDB)
.returns("CENAME=0\n");
}
+
+ /**
+ * Helper method that should clean any previous TableModify states and create
+ * one expense_fact instance with store_id = 666.
+ *
+ * @param statement JDBC connection statement
+ */
+ private void tableModifyTestDbInitializer(Statement statement) {
+ try {
+ statement.executeUpdate("DELETE FROM \"foodmart\".\"expense_fact\""
+ + " WHERE \"store_id\"=666\n");
+ int rowCount = statement.executeUpdate(
+ "INSERT INTO \"foodmart\".\"expense_fact\"(\n"
+ + " \"store_id\", \"account_id\", \"exp_date\", \"time_id\","
+ + " \"category_id\", \"currency_id\", \"amount\")\n"
+ + " VALUES (666, 666, TIMESTAMP '1997-01-01 00:00:00',"
+ + " 666, '666', 666, 666)");
+ assertTrue(rowCount == 1);
+ } catch (SQLException e) {
+ throw Throwables.propagate(e);
+ }
+ }
+
+ /** Test case for
+ * <a href="https://issues.apache.org/jira/browse/CALCITE-1527">[CALCITE-1527]
+ * Support DML in the JDBC adapter</a>. */
+ @Test public void testTableModifyInsert() {
+ final String sql = "INSERT INTO \"foodmart\".\"expense_fact\"(\n"
+ + " \"store_id\", \"account_id\", \"exp_date\", \"time_id\","
+ + " \"category_id\", \"currency_id\", \"amount\")\n"
+ + "VALUES (666, 666, TIMESTAMP '1997-01-01 00:00:00',"
+ + " 666, '666', 666, 666)";
+ final String explain = "PLAN=JdbcToEnumerableConverter\n"
+ + " JdbcTableModify(table=[[foodmart, expense_fact]], operation=[INSERT], flattened=[false])\n"
+ + " JdbcValues(tuples=[[{ 666, 666, 1997-01-01 00:00:00, 666, '666', 666, 666.0000 }]])\n";
+ final String jdbcSql = "INSERT INTO \"foodmart\".\"expense_fact\""
+ + " (\"store_id\", \"account_id\", \"exp_date\", \"time_id\","
+ + " \"category_id\", \"currency_id\", \"amount\")\n"
+ + "VALUES (666, 666, TIMESTAMP '1997-01-01 00:00:00', 666, '666', 666, 666.0000)";
+ CalciteAssert.model(JdbcTest.FOODMART_MODEL)
+ .query(sql)
+ .explainContains(explain)
+ .enable(CalciteAssert.DB == DatabaseInstance.HSQLDB
+ || CalciteAssert.DB == DatabaseInstance.POSTGRESQL)
+ .planUpdateHasSql(jdbcSql, 1);
+ }
+
+ @Test public void testTableModifyInsertMultiValues() {
+ final String sql = "INSERT INTO \"foodmart\".\"expense_fact\"(\n"
+ + " \"store_id\", \"account_id\", \"exp_date\", \"time_id\","
+ + " \"category_id\", \"currency_id\", \"amount\")\n"
+ + "VALUES (666, 666, TIMESTAMP '1997-01-01 00:00:00',"
+ + " 666, '666', 666, 666),\n"
+ + " (777, 666, TIMESTAMP '1997-01-01 00:00:00',"
+ + " 666, '666', 666, 666)";
+ final String explain = "PLAN=JdbcToEnumerableConverter\n"
+ + " JdbcTableModify(table=[[foodmart, expense_fact]], operation=[INSERT], flattened=[false])\n"
+ + " JdbcValues(tuples=[[{ 666, 666, 1997-01-01 00:00:00, 666, '666', 666, 666.0000 },"
+ + " { 777, 666, 1997-01-01 00:00:00, 666, '666', 666, 666.0000 }]])\n";
+ final String jdbcSql = "INSERT INTO \"foodmart\".\"expense_fact\""
+ + " (\"store_id\", \"account_id\", \"exp_date\", \"time_id\","
+ + " \"category_id\", \"currency_id\", \"amount\")\n"
+ + "VALUES (666, 666, TIMESTAMP '1997-01-01 00:00:00', 666, '666', 666, 666.0000),\n"
+ + " (777, 666, TIMESTAMP '1997-01-01 00:00:00', 666, '666', 666, 666.0000)";
+ CalciteAssert
+ .model(JdbcTest.FOODMART_MODEL)
+ .query(sql)
+ .explainContains(explain)
+ .enable(CalciteAssert.DB == DatabaseInstance.HSQLDB
+ || CalciteAssert.DB == DatabaseInstance.POSTGRESQL)
+ .planUpdateHasSql(jdbcSql, 2);
+ }
+
+ @Test public void testTableModifyInsertWithSubQuery() throws Exception {
+ final AssertThat that = CalciteAssert
+ .model(JdbcTest.FOODMART_MODEL)
+ .enable(CalciteAssert.DB == DatabaseInstance.HSQLDB);
+
+ that.doWithConnection(new Function<CalciteConnection, Void>() {
+ public Void apply(CalciteConnection connection) {
+ try {
+ tableModifyTestDbInitializer(connection.createStatement());
+ final String sql = "INSERT INTO \"foodmart\".\"expense_fact\"(\n"
+ + " \"store_id\", \"account_id\", \"exp_date\", \"time_id\","
+ + " \"category_id\", \"currency_id\", \"amount\")\n"
+ + "SELECT \"store_id\", \"account_id\", \"exp_date\","
+ + " \"time_id\" + 1, \"category_id\", \"currency_id\","
+ + " \"amount\"\n"
+ + "FROM \"foodmart\".\"expense_fact\"\n"
+ + "WHERE \"store_id\" = 666";
+ final String explain = "PLAN=JdbcToEnumerableConverter\n"
+ + " JdbcTableModify(table=[[foodmart, expense_fact]], operation=[INSERT], flattened=[false])\n"
+ + " JdbcProject(store_id=[$0], account_id=[$1], exp_date=[$2], time_id=[+($3, 1)], category_id=[$4], currency_id=[$5], amount=[$6])\n"
+ + " JdbcFilter(condition=[=($0, 666)])\n"
+ + " JdbcTableScan(table=[[foodmart, expense_fact]])\n";
+ final String jdbcSql = "INSERT INTO \"foodmart\".\"expense_fact\""
+ + " (\"store_id\", \"account_id\", \"exp_date\", \"time_id\","
+ + " \"category_id\", \"currency_id\", \"amount\")\n"
+ + "(SELECT \"store_id\", \"account_id\", \"exp_date\","
+ + " \"time_id\" + 1 AS \"time_id\", \"category_id\","
+ + " \"currency_id\", \"amount\"\n"
+ + "FROM \"foodmart\".\"expense_fact\"\n"
+ + "WHERE \"store_id\" = 666)";
+ that.query(sql)
+ .explainContains(explain)
+ .planUpdateHasSql(jdbcSql, 1);
+ return null;
+ } catch (SQLException e) {
+ throw Throwables.propagate(e);
+ }
+ }
+ });
+ }
+
+ @Test public void testTableModifyUpdate() throws Exception {
+ final AssertThat that = CalciteAssert
+ .model(JdbcTest.FOODMART_MODEL)
+ .enable(CalciteAssert.DB == DatabaseInstance.HSQLDB);
+
+ that.doWithConnection(new Function<CalciteConnection, Void>() {
+ public Void apply(CalciteConnection connection) {
+ try {
+ tableModifyTestDbInitializer(connection.createStatement());
+ final String sql = "UPDATE \"foodmart\".\"expense_fact\"\n"
+ + " SET \"account_id\"=888\n"
+ + " WHERE \"store_id\"=666\n";
+ final String explain = "PLAN=JdbcToEnumerableConverter\n"
+ + " JdbcTableModify(table=[[foodmart, expense_fact]], operation=[UPDATE], updateColumnList=[[account_id]], sourceExpressionList=[[888]], flattened=[false])\n"
+ + " JdbcProject(store_id=[$0], account_id=[$1], exp_date=[$2], time_id=[$3], category_id=[$4], currency_id=[$5], amount=[$6], EXPR$0=[888])\n"
+ + " JdbcFilter(condition=[=($0, 666)])\n"
+ + " JdbcTableScan(table=[[foodmart, expense_fact]])";
+ final String jdbcSql = "UPDATE \"foodmart\".\"expense_fact\""
+ + " SET \"account_id\" = 888\n"
+ + "WHERE \"store_id\" = 666";
+ that.query(sql)
+ .explainContains(explain)
+ .planUpdateHasSql(jdbcSql, 1);
+ return null;
+ } catch (SQLException e) {
+ throw Throwables.propagate(e);
+ }
+ }
+ });
+ }
+
+ @Test public void testTableModifyDelete() throws Exception {
+ final AssertThat that = CalciteAssert
+ .model(JdbcTest.FOODMART_MODEL)
+ .enable(CalciteAssert.DB == DatabaseInstance.HSQLDB);
+
+ that.doWithConnection(new Function<CalciteConnection, Void>() {
+ public Void apply(CalciteConnection connection) {
+ try {
+ tableModifyTestDbInitializer(connection.createStatement());
+ final String sql = "DELETE FROM \"foodmart\".\"expense_fact\"\n"
+ + "WHERE \"store_id\"=666\n";
+ final String explain = "PLAN=JdbcToEnumerableConverter\n"
+ + " JdbcTableModify(table=[[foodmart, expense_fact]], operation=[DELETE], flattened=[false])\n"
+ + " JdbcFilter(condition=[=($0, 666)])\n"
+ + " JdbcTableScan(table=[[foodmart, expense_fact]]";
+ final String jdbcSql = "DELETE FROM \"foodmart\".\"expense_fact\"\n"
+ + "WHERE \"store_id\" = 666";
+ that.query(sql)
+ .explainContains(explain)
+ .planUpdateHasSql(jdbcSql, 1);
+ return null;
+ } catch (SQLException e) {
+ throw Throwables.propagate(e);
+ }
+ }
+ });
+ }
+
}
// End JdbcAdapterTest.java
http://git-wip-us.apache.org/repos/asf/calcite/blob/02752fe7/core/src/test/java/org/apache/calcite/test/JdbcTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/test/JdbcTest.java b/core/src/test/java/org/apache/calcite/test/JdbcTest.java
index 2740c41..643eb09 100644
--- a/core/src/test/java/org/apache/calcite/test/JdbcTest.java
+++ b/core/src/test/java/org/apache/calcite/test/JdbcTest.java
@@ -54,6 +54,7 @@ import org.apache.calcite.rel.logical.LogicalTableModify;
import org.apache.calcite.rel.rules.IntersectToDistinctRule;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.rel.type.RelDataTypeFactory;
+import org.apache.calcite.rex.RexNode;
import org.apache.calcite.runtime.FlatLists;
import org.apache.calcite.runtime.Hook;
import org.apache.calcite.runtime.SqlFunctions;
@@ -266,7 +267,7 @@ public class JdbcTest {
assertThat(resultSet.next(), is(true));
assertThat(Util.toLinux(resultSet.getString(1)),
is(
- "EnumerableTableModify(table=[[adhoc, MUTABLE_EMPLOYEES]], operation=[INSERT], updateColumnList=[[]], flattened=[false])\n"
+ "EnumerableTableModify(table=[[adhoc, MUTABLE_EMPLOYEES]], operation=[INSERT], flattened=[false])\n"
+ " EnumerableCalc(expr#0..2=[{inputs}], expr#3=[CAST($t1):JavaType(int) NOT NULL], expr#4=[10], expr#5=[CAST($t0):JavaType(class java.lang.String)], expr#6=[CAST($t2):JavaType(float) NOT NULL], expr#7=[null], empid=[$t3], deptno=[$t4], name=[$t5], salary=[$t6], commission=[$t7])\n"
+ " EnumerableValues(tuples=[[{ 'Fred', 56, 123.4 }]])\n"));
@@ -356,7 +357,7 @@ public class JdbcTest {
true)
.query("insert into \"adhoc\".v values ('n',1,2)")
.explainContains(""
- + "EnumerableTableModify(table=[[adhoc, MUTABLE_EMPLOYEES]], operation=[INSERT], updateColumnList=[[]], flattened=[false])\n"
+ + "EnumerableTableModify(table=[[adhoc, MUTABLE_EMPLOYEES]], operation=[INSERT], flattened=[false])\n"
+ " EnumerableCalc(expr#0..2=[{inputs}], expr#3=[CAST($t1):JavaType(int) NOT NULL], expr#4=[10], expr#5=[CAST($t0):JavaType(class java.lang.String)], expr#6=[CAST($t2):JavaType(float) NOT NULL], expr#7=[null], expr#8=[20], expr#9=[<($t4, $t8)], expr#10=[1000], expr#11=[>($t7, $t10)], expr#12=[OR($t9, $t11)], empid=[$t3], deptno=[$t4], name=[$t5], salary=[$t6], commission=[$t7], $condition=[$t12])\n"
+ " EnumerableValues(tuples=[[{ 'n', 1, 2 }]])");
@@ -6813,9 +6814,10 @@ public class JdbcTest {
RelNode child,
TableModify.Operation operation,
List<String> updateColumnList,
+ List<RexNode> sourceExpressionList,
boolean flattened) {
return LogicalTableModify.create(table, catalogReader, child, operation,
- updateColumnList, flattened);
+ updateColumnList, sourceExpressionList, flattened);
}
}
http://git-wip-us.apache.org/repos/asf/calcite/blob/02752fe7/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java
----------------------------------------------------------------------
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 f3e5a24..24f3294 100644
--- a/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java
+++ b/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java
@@ -1478,6 +1478,7 @@ public class SqlToRelConverterTest extends SqlToRelTestBase {
sql(sql).ok();
}
+ @Ignore("CALCITE-1527")
@Test public void testUpdateSubQuery() {
final String sql = "update emp\n"
+ "set empno = (\n"
http://git-wip-us.apache.org/repos/asf/calcite/blob/02752fe7/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml
----------------------------------------------------------------------
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 9880688..0b31805 100644
--- a/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml
+++ b/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml
@@ -2579,7 +2579,7 @@ LogicalProject(DEPTNO=[$0], B=[>($1, $2)])
</Resource>
<Resource name="plan">
<![CDATA[
-LogicalTableModify(table=[[CATALOG, SALES, EMP]], operation=[INSERT], updateColumnList=[[]], flattened=[true])
+LogicalTableModify(table=[[CATALOG, SALES, EMP]], operation=[INSERT], flattened=[true])
LogicalProject(EMPNO=[$1], ENAME=[$2], JOB=[null], MGR=[null], HIREDATE=[null], SAL=[null], COMM=[null], DEPTNO=[$0], SLACKER=[null])
LogicalValues(tuples=[[{ 10, 150, 'Fred' }]])
]]>
@@ -2605,7 +2605,7 @@ LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$
</Resource>
<Resource name="plan">
<![CDATA[
-LogicalTableModify(table=[[CATALOG, SALES, EMP]], operation=[INSERT], updateColumnList=[[]], flattened=[true])
+LogicalTableModify(table=[[CATALOG, SALES, EMP]], operation=[INSERT], flattened=[true])
LogicalFilter(condition=[>($5, 1000)])
LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[CAST($2):VARCHAR(10) CHARACTER SET "ISO-8859-1" COLLATE "ISO-8859-1$en_US$primary" NOT NULL], MGR=[$3], HIREDATE=[CAST($4):TIMESTAMP(0) NOT NULL], SAL=[CAST($5):INTEGER NOT NULL], COMM=[CAST($6):INTEGER NOT NULL], DEPTNO=[20], SLACKER=[CAST($7):BOOLEAN NOT NULL])
LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[null], MGR=[null], HIREDATE=[null], SAL=[null], COMM=[null], SLACKER=[null])
@@ -2619,7 +2619,7 @@ LogicalTableModify(table=[[CATALOG, SALES, EMP]], operation=[INSERT], updateColu
</Resource>
<Resource name="plan">
<![CDATA[
-LogicalTableModify(table=[[CATALOG, STRUCT, T]], operation=[INSERT], updateColumnList=[[]], flattened=[true])
+LogicalTableModify(table=[[CATALOG, STRUCT, T]], operation=[INSERT], flattened=[true])
LogicalProject("K0"=[?0], "C1"=[?1], "F1"."A0"=[?2], "F2"."A0"=[?3], "F0"."C0"=[?4], "F1"."C0"=[?5], "F0"."C1"=[?6], "F1"."C2"=[?7], "F2"."C3"=[?8])
LogicalValues(tuples=[[{ 0 }]])
]]>
@@ -2631,7 +2631,7 @@ LogicalTableModify(table=[[CATALOG, STRUCT, T]], operation=[INSERT], updateColum
</Resource>
<Resource name="plan">
<![CDATA[
-LogicalTableModify(table=[[CATALOG, STRUCT, T]], operation=[INSERT], updateColumnList=[[]], flattened=[true])
+LogicalTableModify(table=[[CATALOG, STRUCT, T]], operation=[INSERT], flattened=[true])
LogicalProject("K0"=[null], "C1"=[$2], "F1"."A0"=[null], "F2"."A0"=[null], "F0"."C0"=[$0], "F1"."C0"=[null], "F0"."C1"=[null], "F1"."C2"=[$1], "F2"."C3"=[null])
LogicalProject(EXPR$0=[?0], EXPR$1=[?1], EXPR$2=[?2])
LogicalValues(tuples=[[{ 0 }]])
@@ -2644,7 +2644,7 @@ LogicalTableModify(table=[[CATALOG, STRUCT, T]], operation=[INSERT], updateColum
</Resource>
<Resource name="plan">
<![CDATA[
-LogicalTableModify(table=[[CATALOG, STRUCT, T]], operation=[INSERT], updateColumnList=[[]], flattened=[true])
+LogicalTableModify(table=[[CATALOG, STRUCT, T]], operation=[INSERT], flattened=[true])
LogicalFilter(condition=[=($4, 10)])
LogicalProject("K0"=[CAST($0):VARCHAR(20) CHARACTER SET "ISO-8859-1" COLLATE "ISO-8859-1$en_US$primary" NOT NULL], "C1"=[CAST($1):VARCHAR(20) CHARACTER SET "ISO-8859-1" COLLATE "ISO-8859-1$en_US$primary" NOT NULL], "F1"."A0"=[CAST($2):INTEGER NOT NULL], "F2"."A0"=[CAST($3):BOOLEAN NOT NULL], "F0"."C0"=[CAST($4):INTEGER NOT NULL], "F1"."C0"=[$5], "F0"."C1"=[CAST($6):INTEGER NOT NULL], "F1"."C2"=[CAST($7):INTEGER NOT NULL], "F2"."C3"=[CAST($8):INTEGER NOT NULL])
LogicalProject("K0"=[null], "C1"=[$2], "F1"."A0"=[null], "F2"."A0"=[null], "F0"."C0"=[$0], "F1"."C0"=[null], "F0"."C1"=[null], "F1"."C2"=[$1], "F2"."C3"=[null])
@@ -2659,7 +2659,7 @@ LogicalTableModify(table=[[CATALOG, STRUCT, T]], operation=[INSERT], updateColum
</Resource>
<Resource name="plan">
<![CDATA[
-LogicalTableModify(table=[[CATALOG, STRUCT, T]], operation=[UPDATE], updateColumnList=[["F0"."C0"]], flattened=[true])
+LogicalTableModify(table=[[CATALOG, STRUCT, T]], operation=[UPDATE], updateColumnList=[["F0"."C0"]], sourceExpressionList=[[+($cor0."F0"."C0", 1)]], flattened=[true])
LogicalProject("K0"=[$0], "C1"=[$1], "F1"."A0"=[$2], "F2"."A0"=[$3], "F0"."C0"=[$4], "F1"."C0"=[$5], "F0"."C1"=[$6], "F1"."C2"=[$7], "F2"."C3"=[$8], EXPR$0=[+($4, 1)])
LogicalTableScan(table=[[CATALOG, STRUCT, T]])
]]>
@@ -2963,7 +2963,7 @@ LogicalProject(A=[$0], *=[$1])
</Resource>
<Resource name="plan">
<![CDATA[
-LogicalTableModify(table=[[CATALOG, SALES, EMP]], operation=[DELETE], updateColumnList=[[]], flattened=[true])
+LogicalTableModify(table=[[CATALOG, SALES, EMP]], operation=[DELETE], flattened=[true])
LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8])
LogicalFilter(condition=[=($7, 10)])
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
@@ -2987,7 +2987,7 @@ LogicalProject(EXPR$0=[+(2, 2)])
</Resource>
<Resource name="plan">
<![CDATA[
-LogicalTableModify(table=[[CATALOG, SALES, EMP]], operation=[UPDATE], updateColumnList=[[EMPNO]], flattened=[true])
+LogicalTableModify(table=[[CATALOG, SALES, EMP]], operation=[UPDATE], updateColumnList=[[EMPNO]], sourceExpressionList=[[+($cor0.EMPNO, 1)]], flattened=[true])
LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8], EXPR$0=[+($0, 1)])
LogicalFilter(condition=[=($7, 10)])
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
@@ -3000,7 +3000,7 @@ LogicalTableModify(table=[[CATALOG, SALES, EMP]], operation=[UPDATE], updateColu
</Resource>
<Resource name="plan">
<![CDATA[
-LogicalTableModify(table=[[CATALOG, SALES, EMP]], operation=[DELETE], updateColumnList=[[]], flattened=[true])
+LogicalTableModify(table=[[CATALOG, SALES, EMP]], operation=[DELETE], flattened=[true])
LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8])
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
]]>
@@ -3012,7 +3012,7 @@ LogicalTableModify(table=[[CATALOG, SALES, EMP]], operation=[DELETE], updateColu
</Resource>
<Resource name="plan">
<![CDATA[
-LogicalTableModify(table=[[CATALOG, SALES, EMP]], operation=[UPDATE], updateColumnList=[[EMPNO]], flattened=[true])
+LogicalTableModify(table=[[CATALOG, SALES, EMP]], operation=[UPDATE], updateColumnList=[[EMPNO]], sourceExpressionList=[[+($cor0.EMPNO, 1)]], flattened=[true])
LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8], EXPR$0=[+($0, 1)])
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
]]>
@@ -3026,7 +3026,7 @@ set empno = (
</Resource>
<Resource name="plan">
<![CDATA[
-LogicalTableModify(table=[[CATALOG, SALES, EMP]], operation=[UPDATE], updateColumnList=[[EMPNO]], flattened=[true])
+LogicalTableModify(table=[[CATALOG, SALES, EMP]], operation=[UPDATE], updateColumnList=[[EMPNO]], sourceExpressionList=[[]], flattened=[true])
LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8], EXPR$0=[$9])
LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2], MGR=[$3], HIREDATE=[$4], SAL=[$5], COMM=[$6], DEPTNO=[$7], SLACKER=[$8], EXPR$0=[$10])
LogicalJoin(condition=[=($7, $9)], joinType=[left])
http://git-wip-us.apache.org/repos/asf/calcite/blob/02752fe7/spark/src/main/java/org/apache/calcite/adapter/spark/JdbcToSparkConverter.java
----------------------------------------------------------------------
diff --git a/spark/src/main/java/org/apache/calcite/adapter/spark/JdbcToSparkConverter.java b/spark/src/main/java/org/apache/calcite/adapter/spark/JdbcToSparkConverter.java
index bca76c2..1c70cbe 100644
--- a/spark/src/main/java/org/apache/calcite/adapter/spark/JdbcToSparkConverter.java
+++ b/spark/src/main/java/org/apache/calcite/adapter/spark/JdbcToSparkConverter.java
@@ -114,7 +114,7 @@ public class JdbcToSparkConverter
(JavaTypeFactory) getCluster().getTypeFactory());
final JdbcImplementor.Result result =
jdbcImplementor.visitChild(0, getInput());
- return result.asQuery().toSqlString(dialect).getSql();
+ return result.asStatement().toSqlString(dialect).getSql();
}
}