You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by tl...@apache.org on 2022/03/15 10:18:50 UTC
[ignite-3] branch main updated: IGNITE-16591 DDL syntax COLOCATE BY (#711)
This is an automated email from the ASF dual-hosted git repository.
tledkov pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git
The following commit(s) were added to refs/heads/main by this push:
new 8d08ada IGNITE-16591 DDL syntax COLOCATE BY (#711)
8d08ada is described below
commit 8d08ada8e77a5130778a2f5d04d11e95e0aad91e
Author: Taras Ledkov <tl...@gridgain.com>
AuthorDate: Tue Mar 15 13:18:42 2022 +0300
IGNITE-16591 DDL syntax COLOCATE BY (#711)
---
.../sql/engine/AbstractBasicIntegrationTest.java | 4 +
.../internal/sql/engine/ItCreateTableDdlTest.java | 96 ++++++++++++++++++++--
.../definition/index/PrimaryKeyDefinitionImpl.java | 10 ++-
.../internal/schema/SchemaConfigurationTest.java | 55 +++++++------
modules/sql-engine/src/main/codegen/config.fmpp | 2 +
.../src/main/codegen/includes/parserImpls.ftl | 17 ++--
.../sql/engine/exec/ddl/DdlCommandHandler.java | 2 +-
.../sql/engine/prepare/ddl/CreateTableCommand.java | 25 +++---
.../prepare/ddl/DdlSqlToCommandConverter.java | 9 ++
.../sql/engine/sql/IgniteSqlCreateTable.java | 33 +++++++-
.../internal/sql/engine/sql/SqlDdlParserTest.java | 69 ++++++++++++++++
11 files changed, 265 insertions(+), 57 deletions(-)
diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/AbstractBasicIntegrationTest.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/AbstractBasicIntegrationTest.java
index 26a3640..53b8436 100644
--- a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/AbstractBasicIntegrationTest.java
+++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/AbstractBasicIntegrationTest.java
@@ -195,6 +195,10 @@ public class AbstractBasicIntegrationTest extends BaseIgniteAbstractTest {
);
}
+ protected static Table table(String canonicalName) {
+ return CLUSTER_NODES.get(0).tables().table(canonicalName);
+ }
+
protected static void insertData(String tblName, String[] columnNames, Object[]... tuples) {
insertData(CLUSTER_NODES.get(0).tables().table(tblName), columnNames, tuples);
}
diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItCreateTableDdlTest.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItCreateTableDdlTest.java
index 45f7a2d..ff70862 100644
--- a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItCreateTableDdlTest.java
+++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItCreateTableDdlTest.java
@@ -17,15 +17,39 @@
package org.apache.ignite.internal.sql.engine;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.containsString;
+import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
+import org.apache.ignite.internal.schema.Column;
+import org.apache.ignite.internal.table.TableImpl;
import org.apache.ignite.lang.IgniteException;
+import org.apache.ignite.table.Table;
+import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestInfo;
/**
* Integration test for set op (EXCEPT, INTERSECT).
*/
public class ItCreateTableDdlTest extends AbstractBasicIntegrationTest {
+ /**
+ * Clear tables after each test.
+ *
+ * @param testInfo Test information oject.
+ * @throws Exception If failed.
+ */
+ @AfterEach
+ @Override
+ public void tearDown(TestInfo testInfo) throws Exception {
+ for (Table t : CLUSTER_NODES.get(0).tables().tables()) {
+ sql("DROP TABLE " + t.name());
+ }
+
+ super.tearDownBase(testInfo);
+ }
+
@Test
public void pkWithNullableColumns() {
assertThrows(
@@ -42,16 +66,76 @@ public class ItCreateTableDdlTest extends AbstractBasicIntegrationTest {
@Test
public void undefinedColumnsInPrimaryKey() {
- assertThrows(
- IgniteException.class,
- () -> sql("CREATE TABLE T0(ID INT, VAL INT, PRIMARY KEY (ID1, ID0, ID2))"),
- " Primary key constrain contains undefined columns: [cols=[ID0, ID2, ID1]]"
+ assertThat(
+ assertThrows(
+ IgniteException.class,
+ () -> sql("CREATE TABLE T0(ID INT, VAL INT, PRIMARY KEY (ID1, ID0, ID2))")
+ ).getMessage(),
+ containsString("Primary key constrain contains undefined columns: [cols=[ID0, ID2, ID1]]")
+ );
+ }
+
+ /**
+ * Check invalid colocation columns configuration:
+ * - not PK columns;
+ * - duplicates colocation columns.
+ */
+ @Test
+ public void invalidColocationColumns() {
+ assertThat(
+ assertThrows(
+ IgniteException.class,
+ () -> sql("CREATE TABLE T0(ID0 INT, ID1 INT, VAL INT, PRIMARY KEY (ID1, ID0)) COLOCATE (ID0, VAL)")
+ ).getMessage(),
+ containsString("Schema definition error: All colocation columns must be part of primary key")
+ );
+
+ assertThat(
+ assertThrows(
+ IgniteException.class,
+ () -> sql("CREATE TABLE T0(ID0 INT, ID1 INT, VAL INT, PRIMARY KEY (ID1, ID0)) COLOCATE (ID1, ID0, ID1)")
+ ).getMessage(),
+ containsString("Schema definition error: Colocation columns must not be duplicated")
);
}
+ /**
+ * Check implicit colocation columns configuration (defined by PK)..
+ */
@Test
- public void dbg() {
- sql("CREATE TABLE T0(ID INT, VAL INT, PRIMARY KEY (ID))");
+ public void implicitColocationColumns() {
+ sql("CREATE TABLE T0(ID0 INT, ID1 INT, VAL INT, PRIMARY KEY (ID1, ID0))");
+
+ Column[] colocationColumns = ((TableImpl) table("PUBLIC.T0")).schemaView().schema().colocationColumns();
+
+ assertEquals(2, colocationColumns.length);
+ assertEquals("ID1", colocationColumns[0].name());
+ assertEquals("ID0", colocationColumns[1].name());
}
+ /**
+ * Check explicit colocation columns configuration.
+ */
+ @Test
+ public void explicitColocationColumns() {
+ sql("CREATE TABLE T0(ID0 INT, ID1 INT, VAL INT, PRIMARY KEY (ID1, ID0)) COLOCATE BY (id0)");
+
+ Column[] colocationColumns = ((TableImpl) table("PUBLIC.T0")).schemaView().schema().colocationColumns();
+
+ assertEquals(1, colocationColumns.length);
+ assertEquals("ID0", colocationColumns[0].name());
+ }
+
+ /**
+ * Check explicit colocation columns configuration.
+ */
+ @Test
+ public void explicitColocationColumnsCaseSensitive() {
+ sql("CREATE TABLE T0(\"Id0\" INT, ID1 INT, VAL INT, PRIMARY KEY (ID1, \"Id0\")) COLOCATE BY (\"Id0\")");
+
+ Column[] colocationColumns = ((TableImpl) table("PUBLIC.T0")).schemaView().schema().colocationColumns();
+
+ assertEquals(1, colocationColumns.length);
+ assertEquals("Id0", colocationColumns[0].name());
+ }
}
diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/definition/index/PrimaryKeyDefinitionImpl.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/definition/index/PrimaryKeyDefinitionImpl.java
index 79b106d..43304a3 100644
--- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/definition/index/PrimaryKeyDefinitionImpl.java
+++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/definition/index/PrimaryKeyDefinitionImpl.java
@@ -48,9 +48,13 @@ public class PrimaryKeyDefinitionImpl extends AbstractSchemaObject implements Pr
if (CollectionUtils.nullOrEmpty(columns)) {
throw new IllegalStateException("Primary key column(s) must be configured.");
- } else if (!columns.containsAll(colocationColumns)) {
- throw new IllegalStateException("Schema definition error: All colocation columns must be part of key.");
- } else if (colocationColumns.size() != Set.copyOf(colocationColumns).size()) {
+ }
+
+ Set<String> colocationColumnsSet = Set.copyOf(colocationColumns);
+
+ if (!columns.containsAll(colocationColumnsSet)) {
+ throw new IllegalStateException("Schema definition error: All colocation columns must be part of primary key.");
+ } else if (colocationColumns.size() != colocationColumnsSet.size()) {
throw new IllegalStateException("Schema definition error: Colocation columns must not be duplicated.");
}
diff --git a/modules/schema/src/test/java/org/apache/ignite/internal/schema/SchemaConfigurationTest.java b/modules/schema/src/test/java/org/apache/ignite/internal/schema/SchemaConfigurationTest.java
index 3143916..4e4644a 100644
--- a/modules/schema/src/test/java/org/apache/ignite/internal/schema/SchemaConfigurationTest.java
+++ b/modules/schema/src/test/java/org/apache/ignite/internal/schema/SchemaConfigurationTest.java
@@ -17,6 +17,8 @@
package org.apache.ignite.internal.schema;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.containsString;
import static org.junit.jupiter.api.Assertions.assertThrows;
import java.util.Map;
@@ -133,31 +135,38 @@ public class SchemaConfigurationTest {
}
/**
- * TestInitialSchema.
- * TODO Documentation https://issues.apache.org/jira/browse/IGNITE-15859
+ * Check invalid colocation columns configuration:
+ * - not PK columns;
+ * - duplicates colocation columns.
*/
@Test
public void invalidColocationColumns() {
- final TableDefinitionBuilder builder = SchemaBuilders.tableBuilder(SchemaObject.DEFAULT_DATABASE_SCHEMA_NAME, "table1");
-
- assertThrows(
- IllegalStateException.class,
- () ->
- SchemaBuilders.primaryKey() // Declare index column in order.
- .withColumns("id0", "id1", "id2")
- .withColocationColumns(
- "val")
- .build(),
- "Schema definition error: All colocation columns must be part of key.");
-
- assertThrows(
- IllegalStateException.class,
- () ->
- SchemaBuilders.primaryKey() // Declare index column in order.
- .withColumns("id0", "id1", "id2")
- .withColocationColumns(
- "id0, id1, id0")
- .build(),
- "Schema definition error: Colocation columns must not be duplicated.");
+ assertThat(
+ assertThrows(
+ IllegalStateException.class,
+ () ->
+ SchemaBuilders.primaryKey() // Declare index column in order.
+ .withColumns("id0", "id1", "id2")
+ .withColocationColumns(
+ "val")
+ .build(),
+ "Schema definition error: All colocation columns must be part of key."
+ ).getMessage(),
+ containsString("Schema definition error: All colocation columns must be part of primary key")
+ );
+
+ assertThat(
+ assertThrows(
+ IllegalStateException.class,
+ () ->
+ SchemaBuilders.primaryKey() // Declare index column in order.
+ .withColumns("id0", "id1", "id2")
+ .withColocationColumns(
+ "id0, id1, id0")
+ .build(),
+ "Schema definition error: Colocation columns must not be duplicated."
+ ).getMessage(),
+ containsString("Schema definition error: All colocation columns must be part of primary key")
+ );
}
}
diff --git a/modules/sql-engine/src/main/codegen/config.fmpp b/modules/sql-engine/src/main/codegen/config.fmpp
index 57d3f80..40d2ddc 100644
--- a/modules/sql-engine/src/main/codegen/config.fmpp
+++ b/modules/sql-engine/src/main/codegen/config.fmpp
@@ -45,6 +45,7 @@ data: {
# List of new keywords. Example: "DATABASES", "TABLES". If the keyword is
# not a reserved keyword, add it to the 'nonReservedKeywords' section.
keywords: [
+ "COLOCATE"
"SEMI"
"IF"
"REPLICAS"
@@ -136,6 +137,7 @@ data: {
"COLLATE"
"COLLATION"
"COLLECT"
+ "COLOCATE"
"COLUMN"
"COMMIT"
"CONDITION"
diff --git a/modules/sql-engine/src/main/codegen/includes/parserImpls.ftl b/modules/sql-engine/src/main/codegen/includes/parserImpls.ftl
index c95183b..eaa6878 100644
--- a/modules/sql-engine/src/main/codegen/includes/parserImpls.ftl
+++ b/modules/sql-engine/src/main/codegen/includes/parserImpls.ftl
@@ -152,7 +152,7 @@ Boolean NullableOptDefaultNull() :
}
- SqlNodeList TableElementList() :
+SqlNodeList TableElementList() :
{
final Span s;
final List<SqlNode> list = new ArrayList<SqlNode>();
@@ -173,20 +173,23 @@ SqlCreate SqlCreateTable(Span s, boolean replace) :
final boolean ifNotExists;
final SqlIdentifier id;
final SqlNodeList columnList;
- final SqlNodeList optionList;
+ SqlNodeList optionList = null;
+ SqlNodeList colocationColumns = null;
}
{
<TABLE>
ifNotExists = IfNotExistsOpt()
id = CompoundIdentifier()
columnList = TableElementList()
- (
+ [
+ <COLOCATE> [<BY>] {s.add(this);}
+ colocationColumns = ParenthesizedSimpleIdentifierList()
+ ]
+ [
<WITH> { s.add(this); } optionList = CreateTableOptionList()
- |
- { optionList = null; }
- )
+ ]
{
- return new IgniteSqlCreateTable(s.end(this), ifNotExists, id, columnList, optionList);
+ return new IgniteSqlCreateTable(s.end(this), ifNotExists, id, columnList, colocationColumns, optionList);
}
}
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/ddl/DdlCommandHandler.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/ddl/DdlCommandHandler.java
index 68bd9c1..775c13f 100644
--- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/ddl/DdlCommandHandler.java
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/ddl/DdlCommandHandler.java
@@ -109,7 +109,7 @@ public class DdlCommandHandler {
final PrimaryKeyDefinitionBuilder pkeyDef = SchemaBuilders.primaryKey();
pkeyDef.withColumns(IgniteObjectName.quoteNames(cmd.primaryKeyColumns()));
- pkeyDef.withColocationColumns(IgniteObjectName.quoteNames(cmd.affColumns()));
+ pkeyDef.withColocationColumns(IgniteObjectName.quoteNames(cmd.colocationColumns()));
final IgniteTypeFactory typeFactory = Commons.typeFactory();
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/CreateTableCommand.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/CreateTableCommand.java
index c45579e..5543cab 100644
--- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/CreateTableCommand.java
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/CreateTableCommand.java
@@ -33,8 +33,8 @@ public class CreateTableCommand extends AbstractTableDdlCommand {
/** Primary key columns. */
private List<String> pkCols;
- /** Affinity key columns. */
- private List<String> affCols;
+ /** Colocation columns. */
+ private List<String> colocationCols;
/** Columns. */
private List<ColumnDefinition> cols;
@@ -85,7 +85,7 @@ public class CreateTableCommand extends AbstractTableDdlCommand {
}
/**
- * Table columns.
+ * Get table columns.
*
* @return Columns.
*/
@@ -94,7 +94,7 @@ public class CreateTableCommand extends AbstractTableDdlCommand {
}
/**
- * Table columns.
+ * Set table columns.
*
* @param cols Columns.
*/
@@ -103,22 +103,21 @@ public class CreateTableCommand extends AbstractTableDdlCommand {
}
/**
- * Affinity columns.
+ * Set colocation column names.
*
- * @return Affinity key columns.
+ * @return Collocation column names.
*/
@Nullable
- public List<String> affColumns() {
- return affCols;
+ public List<String> colocationColumns() {
+ return colocationCols;
}
/**
- * Affinity columns.
+ * Get colocation column names.
*
- * @param affCols Set affinity key columns.
+ * @param colocationCols Colocation column names.
*/
- // todo: support aff columns https://issues.apache.org/jira/browse/IGNITE-16069
- public void affColumns(List<String> affCols) {
- this.affCols = affCols;
+ public void colocationColumns(List<String> colocationCols) {
+ this.colocationCols = colocationCols;
}
}
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/DdlSqlToCommandConverter.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/DdlSqlToCommandConverter.java
index 641a5f3..934e64e 100644
--- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/DdlSqlToCommandConverter.java
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/DdlSqlToCommandConverter.java
@@ -169,6 +169,15 @@ public class DdlSqlToCommandConverter {
createTblCmd.primaryKeyColumns(pkCols);
+ List<String> colocationCols = createTblNode.colocationColumns() == null
+ ? null
+ : createTblNode.colocationColumns().getList().stream()
+ .map(SqlIdentifier.class::cast)
+ .map(SqlIdentifier::getSimple)
+ .collect(Collectors.toList());
+
+ createTblCmd.colocationColumns(colocationCols);
+
List<SqlColumnDeclaration> colDeclarations = createTblNode.columnList().getList().stream()
.filter(SqlColumnDeclaration.class::isInstance)
.map(SqlColumnDeclaration.class::cast)
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/sql/IgniteSqlCreateTable.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/sql/IgniteSqlCreateTable.java
index d4b0f6c..37aff93 100644
--- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/sql/IgniteSqlCreateTable.java
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/sql/IgniteSqlCreateTable.java
@@ -39,16 +39,26 @@ public class IgniteSqlCreateTable extends SqlCreate {
private final @Nullable SqlNodeList columnList;
+ private final @Nullable SqlNodeList colocationColumns;
+
private final @Nullable SqlNodeList createOptionList;
private static final SqlOperator OPERATOR = new SqlSpecialOperator("CREATE TABLE", SqlKind.CREATE_TABLE);
/** Creates a SqlCreateTable. */
- public IgniteSqlCreateTable(SqlParserPos pos, boolean ifNotExists,
- SqlIdentifier name, @Nullable SqlNodeList columnList, @Nullable SqlNodeList createOptionList) {
+ public IgniteSqlCreateTable(
+ SqlParserPos pos,
+ boolean ifNotExists,
+ SqlIdentifier name,
+ @Nullable SqlNodeList columnList,
+ @Nullable SqlNodeList colocationColumns,
+ @Nullable SqlNodeList createOptionList
+ ) {
super(OPERATOR, pos, false, ifNotExists);
+
this.name = Objects.requireNonNull(name, "name");
this.columnList = columnList;
+ this.colocationColumns = colocationColumns;
this.createOptionList = createOptionList;
}
@@ -78,6 +88,14 @@ public class IgniteSqlCreateTable extends SqlCreate {
writer.endList(frame);
}
+ if (colocationColumns != null) {
+ writer.keyword("COLOCATE BY");
+
+ SqlWriter.Frame frame = writer.startList("(", ")");
+ colocationColumns.unparse(writer, 0, 0);
+ writer.endList(frame);
+ }
+
if (createOptionList != null) {
writer.keyword("WITH");
@@ -93,14 +111,21 @@ public class IgniteSqlCreateTable extends SqlCreate {
}
/**
- * GEt list of the specified columns and constraints.
+ * Get list of the specified columns and constraints.
*/
public SqlNodeList columnList() {
return columnList;
}
/**
- * GEt list of the specified options to create table with.
+ * Get list of the colocation columns.
+ */
+ public SqlNodeList colocationColumns() {
+ return colocationColumns;
+ }
+
+ /**
+ * Get list of the specified options to create table with.
*/
public SqlNodeList createOptionList() {
return createOptionList;
diff --git a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/sql/SqlDdlParserTest.java b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/sql/SqlDdlParserTest.java
index d3c99ce..1fd040f 100644
--- a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/sql/SqlDdlParserTest.java
+++ b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/sql/SqlDdlParserTest.java
@@ -18,14 +18,18 @@
package org.apache.ignite.internal.sql.engine.sql;
import static java.util.Collections.singleton;
+import static org.hamcrest.CoreMatchers.endsWith;
import static org.hamcrest.CoreMatchers.hasItem;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.equalTo;
+import static org.junit.jupiter.api.Assertions.assertNull;
import java.util.List;
import java.util.Objects;
import java.util.function.Predicate;
+import java.util.stream.Collectors;
import org.apache.calcite.sql.SqlIdentifier;
import org.apache.calcite.sql.SqlKind;
import org.apache.calcite.sql.SqlLiteral;
@@ -35,6 +39,7 @@ import org.apache.calcite.sql.ddl.SqlColumnDeclaration;
import org.apache.calcite.sql.ddl.SqlKeyConstraint;
import org.apache.calcite.sql.parser.SqlParseException;
import org.apache.calcite.sql.parser.SqlParser;
+import org.apache.calcite.sql.pretty.SqlPrettyWriter;
import org.apache.ignite.internal.generated.query.calcite.sql.IgniteSqlParserImpl;
import org.hamcrest.CustomMatcher;
import org.hamcrest.Matcher;
@@ -215,6 +220,70 @@ public class SqlDdlParserTest {
}
/**
+ * Parsing of CREATE TABLE with specified colocation columns.
+ */
+ @Test
+ public void createTableWithColocation() throws SqlParseException {
+ IgniteSqlCreateTable createTable;
+
+ createTable = parseCreateTable(
+ "CREATE TABLE MY_TABLE(ID0 INT, ID1 INT, ID2 INT, VAL INT, PRIMARY KEY (ID0, ID1, ID2))"
+ );
+
+ assertNull(createTable.colocationColumns());
+
+ createTable = parseCreateTable(
+ "CREATE TABLE MY_TABLE(ID0 INT, ID1 INT, ID2 INT, VAL INT, PRIMARY KEY (ID0, ID1, ID2)) COLOCATE BY (ID2, ID1)"
+ );
+
+ assertThat(
+ createTable.colocationColumns().getList().stream()
+ .map(SqlIdentifier.class::cast)
+ .map(SqlIdentifier::getSimple)
+ .collect(Collectors.toList()),
+ equalTo(List.of("ID2", "ID1"))
+ );
+
+ SqlPrettyWriter w = new SqlPrettyWriter();
+ createTable.unparse(w, 0, 0);
+
+ assertThat(w.toString(), endsWith("COLOCATE BY (\"ID2\", \"ID1\")"));
+
+ createTable = parseCreateTable(
+ "CREATE TABLE MY_TABLE(ID0 INT, ID1 INT, ID2 INT, VAL INT, PRIMARY KEY (ID0, ID1, ID2)) COLOCATE (ID0)"
+ );
+
+ assertThat(
+ createTable.colocationColumns().getList().stream()
+ .map(SqlIdentifier.class::cast)
+ .map(SqlIdentifier::getSimple)
+ .collect(Collectors.toList()),
+ equalTo(List.of("ID0"))
+ );
+
+ // Check uparse 'COLOCATE' and 'WITH' together.
+ createTable = parseCreateTable(
+ "CREATE TABLE MY_TABLE(ID0 INT, ID1 INT, ID2 INT, VAL INT, PRIMARY KEY (ID0, ID1, ID2)) COLOCATE (ID0) "
+ + "with "
+ + "replicas=2, "
+ + "partitions=3"
+ );
+
+ w = new SqlPrettyWriter();
+ createTable.unparse(w, 0, 0);
+
+ assertThat(w.toString(), endsWith("COLOCATE BY (\"ID0\") WITH REPLICAS = 2, PARTITIONS = 3"));
+ }
+
+ private IgniteSqlCreateTable parseCreateTable(String stmt) throws SqlParseException {
+ SqlNode node = parse(stmt);
+
+ assertThat(node, instanceOf(IgniteSqlCreateTable.class));
+
+ return (IgniteSqlCreateTable) node;
+ }
+
+ /**
* Parses a given statement and returns a resulting AST.
*
* @param stmt Statement to parse.