This is an automated email from the ASF dual-hosted git repository.
alexpl pushed a commit to branch sql-calcite
in repository https://gitbox.apache.org/repos/asf/ignite.git
The following commit(s) were added to refs/heads/sql-calcite by this push:
new b8c3003 IGNITE-14555 Create table from query result - Fixes #9119.
b8c3003 is described below
commit b8c300313a9d3b36c2139cacb8255c684e5ee1e4
Author: Aleksey Plekhanov <[email protected]>
AuthorDate: Tue Sep 28 09:38:13 2021 +0300
IGNITE-14555 Create table from query result - Fixes #9119.
Signed-off-by: Aleksey Plekhanov <[email protected]>
---
.../src/main/codegen/includes/parserImpls.ftl | 39 ++++--
.../query/calcite/exec/ExecutionServiceImpl.java | 50 +++++---
.../calcite/prepare/ddl/CreateTableCommand.java | 19 ++-
.../prepare/ddl/DdlSqlToCommandConverter.java | 135 +++++++++++++++------
.../query/calcite/sql/IgniteSqlCreateTable.java | 25 +++-
.../integration/AbstractDdlIntegrationTest.java | 19 ++-
.../integration/TableDdlIntegrationTest.java | 93 ++++++++++++++
.../query/calcite/sql/SqlDdlParserTest.java | 32 +++++
.../aggregates/test_group_by_many_groups.test_slow | 5 +-
.../test_group_by_many_groups.test_slow_ignore | 15 ---
.../sql/aggregate/aggregates/test_perfect_ht.test | 15 +--
.../aggregates/test_perfect_ht.test_ignore | 1 -
.../test/sql/types/decimal/decimal_aggregates.test | 22 ++++
.../types/decimal/decimal_aggregates.test_ignored | 91 --------------
14 files changed, 361 insertions(+), 200 deletions(-)
diff --git a/modules/calcite/src/main/codegen/includes/parserImpls.ftl
b/modules/calcite/src/main/codegen/includes/parserImpls.ftl
index 62c80ca..725aac0 100644
--- a/modules/calcite/src/main/codegen/includes/parserImpls.ftl
+++ b/modules/calcite/src/main/codegen/includes/parserImpls.ftl
@@ -24,19 +24,23 @@ boolean IfNotExistsOpt() :
{ return false; }
}
-SqlNodeList CreateTableOptionList() :
+SqlNodeList WithCreateTableOptionList() :
{
List<SqlNode> list = new ArrayList<SqlNode>();
- final Span s = Span.of();
+ final Span s;
}
{
- CreateTableOption(list)
- (
- <COMMA> { s.add(this); } CreateTableOption(list)
- )*
- {
- return new SqlNodeList(list, s.end(this));
- }
+ [
+ <WITH> { s = span(); }
+ CreateTableOption(list)
+ (
+ <COMMA> { s.add(this); } CreateTableOption(list)
+ )*
+ {
+ return new SqlNodeList(list, s.end(this));
+ }
+ ]
+ { return null; }
}
SqlLiteral CreateTableOptionKey() :
@@ -148,19 +152,28 @@ SqlCreate SqlCreateTable(Span s, boolean replace) :
final SqlIdentifier id;
final SqlNodeList columnList;
final SqlNodeList optionList;
+ final SqlNode query;
}
{
<TABLE>
ifNotExists = IfNotExistsOpt()
id = CompoundIdentifier()
- columnList = TableElementList()
(
- <WITH> { s.add(this); } optionList = CreateTableOptionList()
+ LOOKAHEAD(3)
+ columnList = TableElementList()
+ optionList = WithCreateTableOptionList()
+ { query = null; }
|
- { optionList = null; }
+ (
+ columnList = ParenthesizedSimpleIdentifierList()
+ |
+ { columnList = null; }
+ )
+ optionList = WithCreateTableOptionList()
+ <AS> { s.add(this); } query =
OrderedQueryOrExpr(ExprContext.ACCEPT_QUERY)
)
{
- return new IgniteSqlCreateTable(s.end(this), ifNotExists, id,
columnList, optionList);
+ return new IgniteSqlCreateTable(s.end(this), ifNotExists, id,
columnList, query, optionList);
}
}
diff --git
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/ExecutionServiceImpl.java
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/ExecutionServiceImpl.java
index ed3bce2..46e7678 100644
---
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/ExecutionServiceImpl.java
+++
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/ExecutionServiceImpl.java
@@ -27,15 +27,16 @@ import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
-
import org.apache.calcite.plan.Context;
import org.apache.calcite.plan.Contexts;
import org.apache.calcite.plan.RelOptUtil;
import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.runtime.CalciteContextException;
import org.apache.calcite.schema.SchemaPlus;
import org.apache.calcite.sql.SqlDdl;
import org.apache.calcite.sql.SqlExplain;
import org.apache.calcite.sql.SqlExplainLevel;
+import org.apache.calcite.sql.SqlInsert;
import org.apache.calcite.sql.SqlKind;
import org.apache.calcite.sql.SqlNode;
import org.apache.calcite.sql.SqlNodeList;
@@ -95,6 +96,7 @@ import
org.apache.ignite.internal.processors.query.calcite.prepare.QueryPlanCach
import
org.apache.ignite.internal.processors.query.calcite.prepare.QueryTemplate;
import org.apache.ignite.internal.processors.query.calcite.prepare.Splitter;
import
org.apache.ignite.internal.processors.query.calcite.prepare.ValidationResult;
+import
org.apache.ignite.internal.processors.query.calcite.prepare.ddl.CreateTableCommand;
import
org.apache.ignite.internal.processors.query.calcite.prepare.ddl.DdlSqlToCommandConverter;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteRel;
import org.apache.ignite.internal.processors.query.calcite.schema.SchemaHolder;
@@ -534,8 +536,8 @@ public class ExecutionServiceImpl<Row> extends
AbstractService implements Execut
"querySql=\"" + ctx.query() + "\"]",
IgniteQueryErrorCode.UNSUPPORTED_OPERATION);
}
}
- catch (ValidationException e) {
- throw new IgniteSQLException("Failed to validate query.",
IgniteQueryErrorCode.PARSING, e);
+ catch (ValidationException | CalciteContextException e) {
+ throw new IgniteSQLException("Failed to validate query: " +
e.getMessage(), IgniteQueryErrorCode.PARSING, e);
}
}
@@ -550,12 +552,8 @@ public class ExecutionServiceImpl<Row> extends
AbstractService implements Execut
IgniteRel igniteRel = optimize(sqlNode, planner, log);
- // Split query plan to query fragments.
- List<Fragment> fragments = new Splitter().go(igniteRel);
-
- QueryTemplate template = new QueryTemplate(mappingSvc, fragments);
-
- return new MultiStepQueryPlan(template, queryFieldsMetadata(ctx,
validated.dataType(), validated.origins()));
+ return new MultiStepQueryPlan(queryTemplate(igniteRel),
+ queryFieldsMetadata(ctx, validated.dataType(),
validated.origins()));
}
/** */
@@ -568,12 +566,8 @@ public class ExecutionServiceImpl<Row> extends
AbstractService implements Execut
// Convert to Relational operators graph
IgniteRel igniteRel = optimize(sqlNode, planner, log);
- // Split query plan to query fragments.
- List<Fragment> fragments = new Splitter().go(igniteRel);
-
- QueryTemplate template = new QueryTemplate(mappingSvc, fragments);
-
- return new MultiStepDmlPlan(template, queryFieldsMetadata(ctx,
igniteRel.getRowType(), null));
+ return new MultiStepDmlPlan(queryTemplate(igniteRel),
+ queryFieldsMetadata(ctx, igniteRel.getRowType(), null));
}
/** */
@@ -601,6 +595,14 @@ public class ExecutionServiceImpl<Row> extends
AbstractService implements Execut
}
/** */
+ private QueryTemplate queryTemplate(IgniteRel rel) {
+ // Split query plan to query fragments.
+ List<Fragment> fragments = new Splitter().go(rel);
+
+ return new QueryTemplate(mappingSvc, fragments);
+ }
+
+ /** */
private FieldsMetadata explainFieldsMetadata(PlanningContext ctx) {
IgniteTypeFactory factory = ctx.typeFactory();
RelDataType planStrDataType =
@@ -659,7 +661,23 @@ public class ExecutionServiceImpl<Row> extends
AbstractService implements Execut
", err=" + e.getMessage() + ']', e);
}
- return H2Utils.zeroCursor();
+ if (plan.command() instanceof CreateTableCommand &&
((CreateTableCommand)plan.command()).insertStatement() != null) {
+ SqlInsert insertStmt =
((CreateTableCommand)plan.command()).insertStatement();
+
+ try {
+ // Create new planning context containing created table in the
schema.
+ PlanningContext dmlCtx = createContext(pctx,
pctx.schemaName(), pctx.query(), pctx.parameters());
+
+ QueryPlan dmlPlan = prepareDml(insertStmt, dmlCtx);
+
+ return executePlan(qryId, dmlCtx, dmlPlan);
+ }
+ catch (ValidationException e) {
+ throw new IgniteSQLException("Failed to validate query.",
IgniteQueryErrorCode.PARSING, e);
+ }
+ }
+ else
+ return H2Utils.zeroCursor();
}
/** */
diff --git
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/ddl/CreateTableCommand.java
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/ddl/CreateTableCommand.java
index f474f49..12436c5 100644
---
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/ddl/CreateTableCommand.java
+++
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/ddl/CreateTableCommand.java
@@ -18,7 +18,7 @@
package org.apache.ignite.internal.processors.query.calcite.prepare.ddl;
import java.util.List;
-
+import org.apache.calcite.sql.SqlInsert;
import org.apache.ignite.cache.CacheAtomicityMode;
import org.apache.ignite.cache.CacheWriteSynchronizationMode;
import org.jetbrains.annotations.Nullable;
@@ -78,6 +78,9 @@ public class CreateTableCommand implements DdlCommand {
/** Encrypted flag. */
private boolean encrypted;
+ /** Insert statement for AS SELECT query. */
+ private SqlInsert insertStmt;
+
/**
* @return Cache name upon which new cache configuration for this table
must be based.
*/
@@ -301,4 +304,18 @@ public class CreateTableCommand implements DdlCommand {
public void encrypted(boolean encrypted) {
this.encrypted = encrypted;
}
+
+ /**
+ * @return Data insert statement for CREATE AS SELECT command.
+ */
+ public SqlInsert insertStatement() {
+ return insertStmt;
+ }
+
+ /**
+ * @param insertStmt Data insert statement for CREATE AS SELECT command.
+ */
+ public void insertStatement(SqlInsert insertStmt) {
+ this.insertStmt = insertStmt;
+ }
}
diff --git
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/ddl/DdlSqlToCommandConverter.java
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/ddl/DdlSqlToCommandConverter.java
index 9d1f981..f728750 100644
---
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/ddl/DdlSqlToCommandConverter.java
+++
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/ddl/DdlSqlToCommandConverter.java
@@ -29,8 +29,10 @@ import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.rel.type.RelDataTypeField;
import org.apache.calcite.sql.SqlDdl;
import org.apache.calcite.sql.SqlIdentifier;
+import org.apache.calcite.sql.SqlInsert;
import org.apache.calcite.sql.SqlLiteral;
import org.apache.calcite.sql.SqlNode;
import org.apache.calcite.sql.SqlNodeList;
@@ -45,6 +47,7 @@ import
org.apache.ignite.internal.processors.query.IgniteSQLException;
import org.apache.ignite.internal.processors.query.QueryUtils;
import
org.apache.ignite.internal.processors.query.calcite.prepare.IgnitePlanner;
import
org.apache.ignite.internal.processors.query.calcite.prepare.PlanningContext;
+import
org.apache.ignite.internal.processors.query.calcite.prepare.ValidationResult;
import
org.apache.ignite.internal.processors.query.calcite.sql.IgniteSqlAlterTableAddColumn;
import
org.apache.ignite.internal.processors.query.calcite.sql.IgniteSqlAlterTableDropColumn;
import
org.apache.ignite.internal.processors.query.calcite.sql.IgniteSqlCreateTable;
@@ -150,8 +153,11 @@ public class DdlSqlToCommandConverter {
private CreateTableCommand convertCreateTable(IgniteSqlCreateTable
createTblNode, PlanningContext ctx) {
CreateTableCommand createTblCmd = new CreateTableCommand();
- createTblCmd.schemaName(deriveSchemaName(createTblNode.name(), ctx));
- createTblCmd.tableName(deriveObjectName(createTblNode.name(), ctx,
"tableName"));
+ String schemaName = deriveSchemaName(createTblNode.name(), ctx);
+ String tableName = deriveObjectName(createTblNode.name(), ctx,
"tableName");
+
+ createTblCmd.schemaName(schemaName);
+ createTblCmd.tableName(tableName);
createTblCmd.ifNotExists(createTblNode.ifNotExists());
createTblCmd.templateName(QueryUtils.TEMPLATE_PARTITIONED);
@@ -163,56 +169,109 @@ public class DdlSqlToCommandConverter {
}
}
- List<SqlColumnDeclaration> colDeclarations =
createTblNode.columnList().getList().stream()
- .filter(SqlColumnDeclaration.class::isInstance)
- .map(SqlColumnDeclaration.class::cast)
- .collect(Collectors.toList());
-
IgnitePlanner planner = ctx.planner();
- List<ColumnDefinition> cols = new ArrayList<>();
+ if (createTblNode.query() == null) {
+ List<SqlColumnDeclaration> colDeclarations =
createTblNode.columnList().getList().stream()
+ .filter(SqlColumnDeclaration.class::isInstance)
+ .map(SqlColumnDeclaration.class::cast)
+ .collect(Collectors.toList());
+
+ List<ColumnDefinition> cols = new ArrayList<>();
+
+ for (SqlColumnDeclaration col : colDeclarations) {
+ if (!col.name.isSimple())
+ throw new IgniteSQLException("Unexpected value of
columnName [" +
+ "expected a simple identifier, but was " + col.name +
"; " +
+ "querySql=\"" + ctx.query() + "\"]",
IgniteQueryErrorCode.PARSING);
+
+ String name = col.name.getSimple();
+ RelDataType type = planner.convert(col.dataType);
+
+ Object dflt = null;
+ if (col.expression != null)
+ dflt = ((SqlLiteral)col.expression).getValue();
+
+ cols.add(new ColumnDefinition(name, type, dflt));
+ }
+
+ createTblCmd.columns(cols);
+
+ List<SqlKeyConstraint> pkConstraints =
createTblNode.columnList().getList().stream()
+ .filter(SqlKeyConstraint.class::isInstance)
+ .map(SqlKeyConstraint.class::cast)
+ .collect(Collectors.toList());
- for (SqlColumnDeclaration col : colDeclarations) {
- if (!col.name.isSimple())
- throw new IgniteSQLException("Unexpected value of columnName
[" +
- "expected a simple identifier, but was " + col.name + "; "
+
+ if (pkConstraints.size() > 1)
+ throw new IgniteSQLException("Unexpected amount of primary key
constraints [" +
+ "expected at most one, but was " + pkConstraints.size() +
"; " +
"querySql=\"" + ctx.query() + "\"]",
IgniteQueryErrorCode.PARSING);
- String name = col.name.getSimple();
- RelDataType type = planner.convert(col.dataType);
+ if (!F.isEmpty(pkConstraints)) {
+ Set<String> dedupSet = new HashSet<>();
- Object dflt = null;
- if (col.expression != null)
- dflt = ((SqlLiteral)col.expression).getValue();
+ List<String> pkCols = pkConstraints.stream()
+ .map(pk -> pk.getOperandList().get(1))
+ .map(SqlNodeList.class::cast)
+ .flatMap(l -> l.getList().stream())
+ .map(SqlIdentifier.class::cast)
+ .map(SqlIdentifier::getSimple)
+ .filter(dedupSet::add)
+ .collect(Collectors.toList());
- cols.add(new ColumnDefinition(name, type, dflt));
+ createTblCmd.primaryKeyColumns(pkCols);
+ }
}
+ else { // CREATE AS SELECT.
+ ValidationResult res =
planner.validateAndGetTypeMetadata(createTblNode.query());
- createTblCmd.columns(cols);
+ // Create INSERT node on top of AS SELECT node.
+ SqlInsert sqlInsert = new SqlInsert(
+ createTblNode.query().getParserPosition(),
+ SqlNodeList.EMPTY,
+ createTblNode.name(),
+ res.sqlNode(),
+ null
+ );
- List<SqlKeyConstraint> pkConstraints =
createTblNode.columnList().getList().stream()
- .filter(SqlKeyConstraint.class::isInstance)
- .map(SqlKeyConstraint.class::cast)
- .collect(Collectors.toList());
+ createTblCmd.insertStatement(sqlInsert);
- if (pkConstraints.size() > 1)
- throw new IgniteSQLException("Unexpected amount of primary key
constraints [" +
- "expected at most one, but was " + pkConstraints.size() + "; "
+
- "querySql=\"" + ctx.query() + "\"]",
IgniteQueryErrorCode.PARSING);
+ List<RelDataTypeField> fields = res.dataType().getFieldList();
+ List<ColumnDefinition> cols = new ArrayList<>(fields.size());
- if (!F.isEmpty(pkConstraints)) {
- Set<String> dedupSet = new HashSet<>();
+ if (createTblNode.columnList() != null) {
+ // Derive column names from the CREATE TABLE clause and column
types from the query.
+ List<SqlIdentifier> colNames =
createTblNode.columnList().getList().stream()
+ .map(SqlIdentifier.class::cast)
+ .collect(Collectors.toList());
- List<String> pkCols = pkConstraints.stream()
- .map(pk -> pk.getOperandList().get(1))
- .map(SqlNodeList.class::cast)
- .flatMap(l -> l.getList().stream())
- .map(SqlIdentifier.class::cast)
- .map(SqlIdentifier::getSimple)
- .filter(dedupSet::add)
- .collect(Collectors.toList());
+ if (fields.size() != colNames.size()) {
+ throw new IgniteSQLException("Number of columns must match
number of query columns",
+ IgniteQueryErrorCode.PARSING);
+ }
+
+ for (int i = 0; i < colNames.size(); i++) {
+ SqlIdentifier colName = colNames.get(i);
+
+ assert colName.isSimple();
+
+ RelDataType type = fields.get(i).getType();
+
+ cols.add(new ColumnDefinition(colName.getSimple(), type,
null));
+ }
+ }
+ else {
+ // Derive column names and column types from the query.
+ for (RelDataTypeField field : fields)
+ cols.add(new ColumnDefinition(field.getName(),
field.getType(), null));
+ }
+
+ createTblCmd.columns(cols);
+ }
- createTblCmd.primaryKeyColumns(pkCols);
+ if (createTblCmd.columns() == null) {
+ throw new IgniteSQLException("Column list or query should be
specified for CREATE TABLE command",
+ IgniteQueryErrorCode.PARSING);
}
return createTblCmd;
diff --git
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/sql/IgniteSqlCreateTable.java
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/sql/IgniteSqlCreateTable.java
index e6a28f4..bda05e6 100644
---
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/sql/IgniteSqlCreateTable.java
+++
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/sql/IgniteSqlCreateTable.java
@@ -18,7 +18,6 @@ package
org.apache.ignite.internal.processors.query.calcite.sql;
import java.util.List;
import java.util.Objects;
-
import org.apache.calcite.sql.SqlCreate;
import org.apache.calcite.sql.SqlIdentifier;
import org.apache.calcite.sql.SqlKind;
@@ -42,6 +41,9 @@ public class IgniteSqlCreateTable extends SqlCreate {
private final @Nullable SqlNodeList columnList;
/** */
+ private final @Nullable SqlNode qry;
+
+ /** */
private final @Nullable SqlNodeList createOptionList;
/** */
@@ -49,18 +51,19 @@ public class IgniteSqlCreateTable extends SqlCreate {
new SqlSpecialOperator("CREATE TABLE", SqlKind.CREATE_TABLE);
/** Creates a SqlCreateTable. */
- protected IgniteSqlCreateTable(SqlParserPos pos, boolean ifNotExists,
- SqlIdentifier name, @Nullable SqlNodeList columnList, @Nullable
SqlNodeList createOptionList) {
+ protected IgniteSqlCreateTable(SqlParserPos pos, boolean ifNotExists,
SqlIdentifier name,
+ @Nullable SqlNodeList columnList, @Nullable SqlNode qry, @Nullable
SqlNodeList createOptionList) {
super(OPERATOR, pos, false, ifNotExists);
this.name = Objects.requireNonNull(name, "name");
this.columnList = columnList;
+ this.qry = qry;
this.createOptionList = createOptionList;
}
/** {@inheritDoc} */
@SuppressWarnings("nullness")
@Override public List<SqlNode> getOperandList() {
- return ImmutableNullableList.of(name, columnList, createOptionList);
+ return ImmutableNullableList.of(name, columnList, qry,
createOptionList);
}
/** {@inheritDoc} */
@@ -71,6 +74,7 @@ public class IgniteSqlCreateTable extends SqlCreate {
writer.keyword("IF NOT EXISTS");
name.unparse(writer, leftPrec, rightPrec);
+
if (columnList != null) {
SqlWriter.Frame frame = writer.startList("(", ")");
for (SqlNode c : columnList) {
@@ -85,6 +89,12 @@ public class IgniteSqlCreateTable extends SqlCreate {
createOptionList.unparse(writer, 0, 0);
}
+
+ if (qry != null) {
+ writer.keyword("AS");
+ writer.newlineAndIndent();
+ qry.unparse(writer, 0, 0);
+ }
}
/**
@@ -102,6 +112,13 @@ public class IgniteSqlCreateTable extends SqlCreate {
}
/**
+ * @return Query of "CREATE TABLE AS query" statement.
+ */
+ public SqlNode query() {
+ return qry;
+ }
+
+ /**
* @return List of the specified options to create table with.
*/
public SqlNodeList createOptionList() {
diff --git
a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/AbstractDdlIntegrationTest.java
b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/AbstractDdlIntegrationTest.java
index f851b67..c89bbab 100644
---
a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/AbstractDdlIntegrationTest.java
+++
b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/AbstractDdlIntegrationTest.java
@@ -47,7 +47,7 @@ public class AbstractDdlIntegrationTest extends
GridCommonAbstractTest {
/** {@inheritDoc} */
@Override protected void beforeTestsStarted() throws Exception {
- startGrids(1);
+ startGrids(2);
client = startClientGrid(CLIENT_NODE_NAME);
@@ -55,6 +55,15 @@ public class AbstractDdlIntegrationTest extends
GridCommonAbstractTest {
}
/** {@inheritDoc} */
+ @Override protected void afterTestsStopped() throws Exception {
+ super.afterTestsStopped();
+
+ stopAllGrids();
+
+ cleanPersistenceDir();
+ }
+
+ /** {@inheritDoc} */
@Override protected IgniteConfiguration getConfiguration(String
igniteInstanceName) throws Exception {
return super.getConfiguration(igniteInstanceName)
.setSqlConfiguration(
@@ -80,13 +89,13 @@ public class AbstractDdlIntegrationTest extends
GridCommonAbstractTest {
}
/** */
- protected List<List<?>> executeSql(String sql) {
- return executeSql(client, sql);
+ protected List<List<?>> executeSql(String sql, Object... params) {
+ return executeSql(client, sql, params);
}
/** */
- protected List<List<?>> executeSql(IgniteEx ignite, String sql) {
- List<FieldsQueryCursor<List<?>>> cur =
queryProcessor(ignite).query(null, "PUBLIC", sql);
+ protected List<List<?>> executeSql(IgniteEx ignite, String sql, Object...
params) {
+ List<FieldsQueryCursor<List<?>>> cur =
queryProcessor(ignite).query(null, "PUBLIC", sql, params);
try (QueryCursor<List<?>> srvCursor = cur.get(0)) {
return srvCursor.getAll();
diff --git
a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/TableDdlIntegrationTest.java
b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/TableDdlIntegrationTest.java
index ac81cae..d35cf9d 100644
---
a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/TableDdlIntegrationTest.java
+++
b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/TableDdlIntegrationTest.java
@@ -276,6 +276,99 @@ public class TableDdlIntegrationTest extends
AbstractDdlIntegrationTest {
}
/**
+ * Creates table as select.
+ */
+ @Test
+ public void createTableAsSelectSimpleCase() {
+ executeSql("create table my_table as select 1 as i, 'test' as s");
+ List<List<?>> res = executeSql("select i, s from my_table");
+
+ assertEquals(1, res.size());
+
+ List<?> row = res.get(0);
+
+ assertEquals(1, row.get(0));
+ assertEquals("test", row.get(1));
+ }
+
+ /**
+ * Creates table with specified columns as select.
+ */
+ @Test
+ public void createTableAsSelectWithColumns() {
+ executeSql("create table my_table(i, s) as select 1 as a, 'test' as
b");
+ List<List<?>> res = executeSql("select i, s from my_table");
+
+ assertEquals(1, res.size());
+
+ List<?> row = res.get(0);
+
+ assertEquals(1, row.get(0));
+ assertEquals("test", row.get(1));
+
+ assertThrows("select a from my_table", IgniteSQLException.class,
"Column 'A' not found in any table");
+ }
+
+ /**
+ * Creates table with options as select.
+ */
+ @SuppressWarnings("unchecked")
+ @Test
+ public void createTableAsSelectWithOptions() {
+ executeSql("create table my_table(s, i) with
cache_name=\"CacheWithOpts\", cache_group=\"CacheGroup\" as select '1', 1");
+ List<List<?>> res = executeSql("select * from my_table");
+
+ assertEquals(1, res.size());
+
+ List<?> row = res.get(0);
+
+ assertEquals("1", row.get(0));
+ assertEquals(1, row.get(1));
+
+ IgniteCache<?, ?> cache = client.cache("CacheWithOpts");
+ assertNotNull(cache);
+ assertEquals("CacheGroup",
cache.getConfiguration(CacheConfiguration.class).getGroupName());
+ }
+
+ /**
+ * Creates table as select with dynamic parameters to query.
+ */
+ @Test
+ public void createTableAsSelectWithParameters() {
+ executeSql("create table my_table(s, i) as select cast(? as varchar),
cast(? as int)", "a", 1);
+ List<List<?>> res = executeSql("select * from my_table");
+
+ assertEquals(1, res.size());
+
+ List<?> row = res.get(0);
+
+ assertEquals("a", row.get(0));
+ assertEquals(1, row.get(1));
+ }
+
+ /** */
+ @Test
+ public void createTableAsSelectWrongColumnsCount() {
+ GridTestUtils.assertThrowsAnyCause(log,
+ () -> executeSql("create table my_table(i, s1, s2) as select 1,
'test'"),
+ IgniteSQLException.class, "Number of columns");
+ }
+
+ /**
+ * Creates table as select from another table.
+ */
+ @Test
+ public void createTableAsSelectFromDistributedTable() {
+ executeSql("create table my_table1(i) as select x from
table(system_range(1, 100))");
+
+ assertEquals(100L, executeSql("select count(*) from
my_table1").get(0).get(0));
+
+ executeSql("create table my_table2(i) as select * from my_table1");
+
+ assertEquals(100L, executeSql("select count(*) from
my_table2").get(0).get(0));
+ }
+
+ /**
* Drops a table created in a default schema.
*/
@Test
diff --git
a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/sql/SqlDdlParserTest.java
b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/sql/SqlDdlParserTest.java
index 0109554..de653e7 100644
---
a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/sql/SqlDdlParserTest.java
+++
b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/sql/SqlDdlParserTest.java
@@ -248,6 +248,38 @@ public class SqlDdlParserTest extends
GridCommonAbstractTest {
}
/**
+ * Parsing of CREATE TABLE AS SELECT.
+ */
+ @Test
+ public void createTableAsSelect() throws SqlParseException {
+ IgniteSqlCreateTable createTable = parse("create table my_table(id) as
select 1");
+
+ assertEquals(1, createTable.columnList().size());
+ assertNotNull(createTable.query());
+
+ createTable = parse("create table my_table(id, name) as select 1,
'a'");
+
+ assertEquals(2, createTable.columnList().size());
+ assertNotNull(createTable.query());
+
+ createTable = parse("create table my_table as select 1, 'a'");
+
+ assertNull(createTable.columnList());
+ assertNull(createTable.createOptionList());
+ assertNotNull(createTable.query());
+
+ createTable = parse("create table my_table with cache_name=a,
cache_group=b as select 1");
+
+ assertNull(createTable.columnList());
+ assertNotNull(createTable.createOptionList());
+ assertNotNull(createTable.query());
+
+ assertParserThrows("create table my_table(id int) as select 1",
SqlParseException.class);
+ assertParserThrows("create table my_table(id.a) as select 1",
SqlParseException.class);
+ assertParserThrows("create table my_table(id) as select 1 with
cache_name=a", SqlParseException.class);
+ }
+
+ /**
* Create index with list of indexed columns.
*/
@Test
diff --git
a/modules/calcite/src/test/sql/aggregate/aggregates/test_group_by_many_groups.test_slow
b/modules/calcite/src/test/sql/aggregate/aggregates/test_group_by_many_groups.test_slow
index 9b22d09..7563c0a 100644
---
a/modules/calcite/src/test/sql/aggregate/aggregates/test_group_by_many_groups.test_slow
+++
b/modules/calcite/src/test/sql/aggregate/aggregates/test_group_by_many_groups.test_slow
@@ -3,10 +3,7 @@
# group: [aggregates]
statement ok
-CREATE TABLE integers(i INTEGER, j INTEGER);
-
-statement ok
-INSERT INTO integers SELECT x, 1 FROM table(system_range(0, 9999, 1)) UNION
ALL SELECT x, 2 FROM table(system_range(0, 9999, 1));
+CREATE TABLE integers AS SELECT x AS i, 1 AS j FROM table(system_range(0,
9999, 1)) UNION ALL SELECT x AS i, 2 j FROM table(system_range(0, 9999, 1));
query RR
diff --git
a/modules/calcite/src/test/sql/aggregate/aggregates/test_group_by_many_groups.test_slow_ignore
b/modules/calcite/src/test/sql/aggregate/aggregates/test_group_by_many_groups.test_slow_ignore
deleted file mode 100644
index 3d01e7f..0000000
---
a/modules/calcite/src/test/sql/aggregate/aggregates/test_group_by_many_groups.test_slow_ignore
+++ /dev/null
@@ -1,15 +0,0 @@
-# name: test/sql/aggregate/aggregates/test_group_by_many_groups.test_slow
-# description: Test GROUP BY with many groups
-# group: [aggregates]
-# Ignored: https://issues.apache.org/jira/browse/IGNITE-14555
-
-statement ok
-CREATE TABLE integers AS SELECT x AS i, 1 AS j FROM table(system_range(0,
9999, 1)) UNION ALL SELECT x AS i, 2 j FROM table(system_range(0, 9999, 1));
-
-
-query RR
-SELECT SUM(i), SUM(sums) FROM (SELECT i, SUM(j) AS sums FROM integers GROUP BY
i) tbl1
-----
-49995000
-30000
-
diff --git
a/modules/calcite/src/test/sql/aggregate/aggregates/test_perfect_ht.test
b/modules/calcite/src/test/sql/aggregate/aggregates/test_perfect_ht.test
index aab3c6e..f0580f5 100644
--- a/modules/calcite/src/test/sql/aggregate/aggregates/test_perfect_ht.test
+++ b/modules/calcite/src/test/sql/aggregate/aggregates/test_perfect_ht.test
@@ -25,10 +25,7 @@ NULL 1 1 1
# many small columns each having only the values 0 and 1
# total possible combinations is 2^10, but there are only 2 groups
statement ok
-create table manycolumns(a INTEGER, b INTEGER, c INTEGER, d INTEGER, e
INTEGER);
-
-statement ok
-insert into manycolumns select x a, x b, x c, x d, x e from
table(system_range(0,1));
+create table manycolumns as select x a, x b, x c, x d, x e from
table(system_range(0,1));
query IIIII
select a, b, c, d, e FROM manycolumns GROUP BY a, b, c, d, e ORDER BY 1
@@ -40,10 +37,7 @@ select a, b, c, d, e FROM manycolumns GROUP BY a, b, c, d, e
ORDER BY 1
# create a table of tinyints [-127, 127] stored as varchar
# by forcing a varchar to tinyint cast we lose statistics
statement ok
-CREATE TABLE tinyints (t TINYINT);
-
-statement ok
-INSERT INTO tinyints SELECT x::TINYINT::VARCHAR AS t FROM
table(system_range(-127, 127));
+CREATE TABLE tinyints AS SELECT x::TINYINT::VARCHAR AS t FROM
table(system_range(-127, 127));
query IIII
SELECT COUNT(DISTINCT i), MIN(i), MAX(i), SUM(i) / COUNT(i) FROM (SELECT
t::TINYINT i FROM tinyints GROUP BY t)
@@ -52,10 +46,7 @@ SELECT COUNT(DISTINCT i), MIN(i), MAX(i), SUM(i) / COUNT(i)
FROM (SELECT t::TINY
# now do the same with a single smallint column
statement ok
-CREATE TABLE smallints (t SMALLINT)
-
-statement ok
-INSERT INTO smallints SELECT x::SMALLINT::VARCHAR AS t FROM
table(system_range(-32767, 32767));
+CREATE TABLE smallints AS SELECT x::SMALLINT::VARCHAR AS t FROM
table(system_range(-32767, 32767));
query IIII
SELECT COUNT(DISTINCT i), MIN(i), MAX(i), SUM(i) / COUNT(i) FROM (SELECT
t::SMALLINT i FROM smallints GROUP BY t)
diff --git
a/modules/calcite/src/test/sql/aggregate/aggregates/test_perfect_ht.test_ignore
b/modules/calcite/src/test/sql/aggregate/aggregates/test_perfect_ht.test_ignore
index 8dba3ba..48b56b9 100644
---
a/modules/calcite/src/test/sql/aggregate/aggregates/test_perfect_ht.test_ignore
+++
b/modules/calcite/src/test/sql/aggregate/aggregates/test_perfect_ht.test_ignore
@@ -1,7 +1,6 @@
# name: test/sql/aggregate/aggregates/test_perfect_ht.test
# description: Test aggregates that can trigger a perfect HT
# group: [aggregates]
-# Ignored: https://issues.apache.org/jira/browse/IGNITE-14555
# Ignored: https://issues.apache.org/jira/browse/IGNITE-14636
# Ignored: https://issues.apache.org/jira/browse/IGNITE-14730
# Ignored: https://issues.apache.org/jira/browse/IGNITE-14885
diff --git a/modules/calcite/src/test/sql/types/decimal/decimal_aggregates.test
b/modules/calcite/src/test/sql/types/decimal/decimal_aggregates.test
index c6fe9b9..82145c1 100644
--- a/modules/calcite/src/test/sql/types/decimal/decimal_aggregates.test
+++ b/modules/calcite/src/test/sql/types/decimal/decimal_aggregates.test
@@ -66,3 +66,25 @@ NULL
45672564564938245.1
4567645908450368043562342564564938245.1
+# decimal aggregates over a table
+statement ok
+CREATE TABLE decimals AS SELECT x::DECIMAL(4,1) AS d1, (x * x)::DECIMAL(9,1)
AS d2, (x * x * x)::DECIMAL(18,1) AS d3, (x * x * x * x)::DECIMAL(38,1) AS d4
FROM table(system_range(1, 999));
+
+query IIII
+SELECT SUM(d1)::VARCHAR, SUM(d2)::VARCHAR, SUM(d3)::VARCHAR, SUM(d4)::VARCHAR
FROM decimals;
+----
+499500.0
+332833500.0
+249500250000.0
+199500333333300.0
+
+statement ok
+INSERT INTO decimals VALUES ('0.1', '0.1', '0.1', '0.1'), ('0.2', '0.2',
'0.2', '0.2')
+
+query IIII
+SELECT SUM(d1)::VARCHAR, SUM(d2)::VARCHAR, SUM(d3)::VARCHAR, SUM(d4)::VARCHAR
FROM decimals;
+----
+499500.3
+332833500.3
+249500250000.3
+199500333333300.3
diff --git
a/modules/calcite/src/test/sql/types/decimal/decimal_aggregates.test_ignored
b/modules/calcite/src/test/sql/types/decimal/decimal_aggregates.test_ignored
deleted file mode 100644
index fca12be..0000000
--- a/modules/calcite/src/test/sql/types/decimal/decimal_aggregates.test_ignored
+++ /dev/null
@@ -1,91 +0,0 @@
-# name: test/sql/types/decimal/decimal_aggregates.test
-# description: Test decimal aggregates
-# group: [decimal]
-# Ignore: https://issues.apache.org/jira/browse/IGNITE-14555
-
-statement ok
-PRAGMA enable_verification
-
-query I
-SELECT typeof(ANY_VALUE('0.1'::DECIMAL(4,1)))
-----
-DECIMAL(4, 1)
-
-# scalar aggregates
-# first
-query IIIII
-SELECT ANY_VALUE(NULL::DECIMAL),
- ANY_VALUE('0.1'::DECIMAL(4,1))::VARCHAR,
- ANY_VALUE('4938245.1'::DECIMAL(9,1))::VARCHAR,
- ANY_VALUE('45672564564938245.1'::DECIMAL(18,1))::VARCHAR,
-
ANY_VALUE('4567645908450368043562342564564938245.1'::DECIMAL(38,1))::VARCHAR
-----
-NULL
-0.1
-4938245.1
-45672564564938245.1
-4567645908450368043562342564564938245.1
-
-# min
-query IIIII
-SELECT MIN(NULL::DECIMAL),
- MIN('0.1'::DECIMAL(4,1))::VARCHAR,
- MIN('4938245.1'::DECIMAL(9,1))::VARCHAR,
- MIN('45672564564938245.1'::DECIMAL(18,1))::VARCHAR,
- MIN('4567645908450368043562342564564938245.1'::DECIMAL(38,1))::VARCHAR
-----
-NULL
-0.1
-4938245.1
-45672564564938245.1
-4567645908450368043562342564564938245.1
-
-query IIIII
-SELECT MAX(NULL::DECIMAL),
- MAX('0.1'::DECIMAL(4,1))::VARCHAR,
- MAX('4938245.1'::DECIMAL(9,1))::VARCHAR,
- MAX('45672564564938245.1'::DECIMAL(18,1))::VARCHAR,
- MAX('4567645908450368043562342564564938245.1'::DECIMAL(38,1))::VARCHAR
-----
-NULL
-0.1
-4938245.1
-45672564564938245.1
-4567645908450368043562342564564938245.1
-
-# sum
-query IIIII
-SELECT SUM(NULL::DECIMAL),
- SUM('0.1'::DECIMAL(4,1))::VARCHAR,
- SUM('4938245.1'::DECIMAL(9,1))::VARCHAR,
- SUM('45672564564938245.1'::DECIMAL(18,1))::VARCHAR,
- SUM('4567645908450368043562342564564938245.1'::DECIMAL(38,1))::VARCHAR
-----
-NULL
-0.1
-4938245.1
-45672564564938245.1
-4567645908450368043562342564564938245.1
-
-# decimal aggregates over a table
-statement ok
-CREATE TABLE decimals AS SELECT i::DECIMAL(4,1) AS d1, (i * i)::DECIMAL(9,1)
AS d2, (i * i * i)::DECIMAL(18,1) AS d3, (i * i * i * i)::DECIMAL(38,1) AS d4
FROM range(1000) tbl(i);
-
-query IIII
-SELECT SUM(d1)::VARCHAR, SUM(d2)::VARCHAR, SUM(d3)::VARCHAR, SUM(d4)::VARCHAR
FROM decimals;
-----
-499500.0
-332833500.0
-249500250000.0
-199500333333300.0
-
-statement ok
-INSERT INTO decimals VALUES ('0.1', '0.1', '0.1', '0.1'), ('0.2', '0.2',
'0.2', '0.2')
-
-query IIII
-SELECT SUM(d1)::VARCHAR, SUM(d2)::VARCHAR, SUM(d3)::VARCHAR, SUM(d4)::VARCHAR
FROM decimals;
-----
-499500.3
-332833500.3
-249500250000.3
-199500333333300.3