This is an automated email from the ASF dual-hosted git repository. amashenkov pushed a commit to branch ignite-14864 in repository https://gitbox.apache.org/repos/asf/ignite-3.git
commit fb3f3e332ed96bd6177ecfffeb4fe798ecc2eb01 Author: Andrew Mashenkov <[email protected]> AuthorDate: Wed Jun 30 17:52:16 2021 +0300 Refactor tests. --- .../runner/app/AbstractSchemaChangeTest.java | 222 +++++++++++++ .../runner/app/DynamicTableCreationTest.java | 3 - .../runner/app/SchemaChangeKVViewTest.java | 155 +++++++++ .../runner/app/SchemaChangeTableViewTest.java | 157 +++++++++ .../internal/runner/app/SchemaChangeTest.java | 363 --------------------- 5 files changed, 534 insertions(+), 366 deletions(-) diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/AbstractSchemaChangeTest.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/AbstractSchemaChangeTest.java new file mode 100644 index 0000000..0b44582 --- /dev/null +++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/AbstractSchemaChangeTest.java @@ -0,0 +1,222 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.runner.app; + +import org.apache.ignite.app.Ignite; +import org.apache.ignite.app.IgnitionManager; +import org.apache.ignite.internal.app.IgnitionCleaner; +import org.apache.ignite.internal.util.IgniteUtils; +import org.apache.ignite.schema.Column; +import org.apache.ignite.schema.ColumnType; +import org.apache.ignite.schema.SchemaBuilders; +import org.apache.ignite.schema.SchemaTable; +import org.junit.jupiter.api.AfterEach; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Consumer; + +import static org.apache.ignite.internal.schema.configuration.SchemaConfigurationConverter.convert; +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * Ignition interface tests. + */ +abstract class AbstractSchemaChangeTest { + /** + * Table name. + */ + public static final String TABLE = "tbl1"; + + /** + * Nodes bootstrap configuration. + */ + private final Map<String, String> nodesBootstrapCfg = new LinkedHashMap<>() {{ + put("node0", "{\n" + + " \"node\": {\n" + + " \"metastorageNodes\":[ \"node0\" ]\n" + + " },\n" + + " \"network\": {\n" + + " \"port\":3344,\n" + + " \"netClusterNodes\":[ \"localhost:3344\", \"localhost:3345\", \"localhost:3346\" ]\n" + + " }\n" + + "}"); + + put("node1", "{\n" + + " \"node\": {\n" + + " \"metastorageNodes\":[ \"node0\" ]\n" + + " },\n" + + " \"network\": {\n" + + " \"port\":3345,\n" + + " \"netClusterNodes\":[ \"localhost:3344\", \"localhost:3345\", \"localhost:3346\" ]\n" + + " }\n" + + "}"); + + put("node2", "{\n" + + " \"node\": {\n" + + " \"metastorageNodes\":[ \"node0\" ]\n" + + " },\n" + + " \"network\": {\n" + + " \"port\":3346,\n" + + " \"netClusterNodes\":[ \"localhost:3344\", \"localhost:3345\", \"localhost:3346\" ]\n" + + " }\n" + + "}"); + }}; + + /** */ + private final List<Ignite> clusterNodes = new ArrayList<>(); + + /** */ + @AfterEach + void tearDown() throws Exception { + IgniteUtils.closeAll(clusterNodes); + + IgnitionCleaner.removeAllData(); + } + + /** + * Check add a new column to table schema. + */ + protected void checkDropColumn( + final String columnToDrop, + Consumer<List<Ignite>> initFunc, + Consumer<List<Ignite>> validateFunc + ) { + List<Ignite> clusterNodes = new ArrayList<>(); + + for (Map.Entry<String, String> nodeBootstrapCfg : nodesBootstrapCfg.entrySet()) + clusterNodes.add(IgnitionManager.start(nodeBootstrapCfg.getKey(), nodeBootstrapCfg.getValue())); + + assertEquals(3, clusterNodes.size()); + + // Create table on node 0. + SchemaTable schTbl1 = SchemaBuilders.tableBuilder("PUBLIC", TABLE).columns( + SchemaBuilders.column("key", ColumnType.INT64).asNonNull().build(), + SchemaBuilders.column("val1", ColumnType.INT32).asNullable().build(), + SchemaBuilders.column("val2", ColumnType.string()).withDefaultValue("default").build() + ).withPrimaryKey("key").build(); + + clusterNodes.get(0).tables().createTable(schTbl1.canonicalName(), tblCh -> + convert(schTbl1, tblCh) + .changeReplicas(1) + .changePartitions(10) + ); + + initFunc.accept(clusterNodes); + + clusterNodes.get(0).tables().alterTable(schTbl1.canonicalName(), + chng -> chng.changeColumns(cols -> { + chng.columns().namedListKeys().stream() + .filter(c -> columnToDrop.equals(chng.columns().get(c).name())) + .findFirst() + .ifPresentOrElse( + cols::delete, + () -> { + throw new IllegalStateException("Column not found."); + }); + })); + + validateFunc.accept(clusterNodes); + } + + /** + * Check drop column from table schema. + */ + protected void checkAddNewColumn( + final Column columnToAdd, + Consumer<List<Ignite>> initFunc, + Consumer<List<Ignite>> validateFunc + ) { + List<Ignite> clusterNodes = new ArrayList<>(); + + for (Map.Entry<String, String> nodeBootstrapCfg : nodesBootstrapCfg.entrySet()) + clusterNodes.add(IgnitionManager.start(nodeBootstrapCfg.getKey(), nodeBootstrapCfg.getValue())); + + assertEquals(3, clusterNodes.size()); + + // Create table on node 0. + SchemaTable schTbl1 = SchemaBuilders.tableBuilder("PUBLIC", "tbl1").columns( + SchemaBuilders.column("key", ColumnType.INT64).asNonNull().build(), + SchemaBuilders.column("val1", ColumnType.INT32).asNullable().build() + ).withPrimaryKey("key").build(); + + clusterNodes.get(0).tables().createTable(schTbl1.canonicalName(), tblCh -> + convert(schTbl1, tblCh) + .changeReplicas(1) + .changePartitions(10) + ); + + initFunc.accept(clusterNodes); + + clusterNodes.get(1).tables().alterTable(schTbl1.canonicalName(), + chng -> chng.changeColumns(cols -> { + final int colIdx = chng.columns().size(); + //TODO: avoid 'colIdx' or replace with correct last colIdx. + cols.create(String.valueOf(colIdx), colChg -> convert(columnToAdd, colChg)); + })); + + validateFunc.accept(clusterNodes); + } + + /** + * Check rename column from table schema. + */ + protected void checkRenameColumn( + Consumer<List<Ignite>> initFunc, + Consumer<List<Ignite>> validateFunc + ) { + List<Ignite> clusterNodes = new ArrayList<>(); + + for (Map.Entry<String, String> nodeBootstrapCfg : nodesBootstrapCfg.entrySet()) + clusterNodes.add(IgnitionManager.start(nodeBootstrapCfg.getKey(), nodeBootstrapCfg.getValue())); + + assertEquals(3, clusterNodes.size()); + + // Create table on node 0. + SchemaTable schTbl1 = SchemaBuilders.tableBuilder("PUBLIC", "tbl1").columns( + SchemaBuilders.column("key", ColumnType.INT64).asNonNull().build(), + SchemaBuilders.column("val1", ColumnType.INT32).asNullable().build() + ).withPrimaryKey("key").build(); + + clusterNodes.get(0).tables().createTable(schTbl1.canonicalName(), tblCh -> + convert(schTbl1, tblCh) + .changeReplicas(1) + .changePartitions(10) + ); + + initFunc.accept(clusterNodes); + + clusterNodes.get(1).tables().alterTable(schTbl1.canonicalName(), + tblChanger -> tblChanger.changeColumns(cols -> { + final String colKey = tblChanger.columns().namedListKeys().stream() + .filter(c -> "val1".equals(tblChanger.columns().get(c).name())) + .findFirst() + .orElseThrow(() -> { + throw new IllegalStateException("Column not found."); + }); + + tblChanger.changeColumns(listChanger -> + listChanger.update(colKey, colChanger -> colChanger.changeName("val2")) + ); + })); + + validateFunc.accept(clusterNodes); + } +} diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/DynamicTableCreationTest.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/DynamicTableCreationTest.java index 14f9122..8b8aa82 100644 --- a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/DynamicTableCreationTest.java +++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/DynamicTableCreationTest.java @@ -49,9 +49,6 @@ import static org.junit.jupiter.api.Assertions.assertThrows; */ @Disabled("https://issues.apache.org/jira/browse/IGNITE-14581") class DynamicTableCreationTest { - /** The logger. */ - private static final IgniteLogger LOG = IgniteLogger.forClass(SchemaManager.class); - /** Nodes bootstrap configuration. */ private final Map<String, String> nodesBootstrapCfg = new LinkedHashMap<>() {{ put("node0", "{\n" + diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/SchemaChangeKVViewTest.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/SchemaChangeKVViewTest.java new file mode 100644 index 0000000..b6ec651 --- /dev/null +++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/SchemaChangeKVViewTest.java @@ -0,0 +1,155 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.runner.app; + +import org.apache.ignite.internal.table.ColumnNotFoundException; +import org.apache.ignite.schema.ColumnType; +import org.apache.ignite.schema.SchemaBuilders; +import org.apache.ignite.table.KeyValueBinaryView; +import org.apache.ignite.table.Tuple; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +/** + * Ignition interface tests. + */ +@Disabled("https://issues.apache.org/jira/browse/IGNITE-14581") +class SchemaChangeKVViewTest extends AbstractSchemaChangeTest { + /** + * Check add a new column to table schema. + */ + @Test + public void testDropColumn() { + checkDropColumn( + "val2", + (grid) -> { + final KeyValueBinaryView kvView = grid.get(1).tables().table(TABLE).kvView(); + + kvView.put(kvView.tupleBuilder().set("key", 1L).build(), + kvView.tupleBuilder().set("val1", 111).set("val2", "str").build()); + }, + (grid) -> { + KeyValueBinaryView kvView = grid.get(1).tables().table(TABLE).kvView(); + + // Check old row conversion. + final Tuple keyTuple = kvView.tupleBuilder().set("key", 1L).build(); + + assertEquals(111, (Integer) kvView.get(keyTuple).value("val1")); + assertThrows(ColumnNotFoundException.class, () -> kvView.get(keyTuple).value("val2")); + + // Check tuple of outdated schema. + assertThrows(ColumnNotFoundException.class, () -> kvView.put( + kvView.tupleBuilder().set("key", 2L).build(), + kvView.tupleBuilder().set("val1", -222).set("val2", "str").build()) + ); + + // Check tuple of correct schema. + kvView.put(kvView.tupleBuilder().set("key", 2L).build(), kvView.tupleBuilder().set("val1", 222).build()); + + final Tuple keyTuple2 = kvView.tupleBuilder().set("key", 2L).build(); + + assertEquals(222, (Integer) kvView.get(keyTuple2).value("val1")); + assertThrows(ColumnNotFoundException.class, () -> kvView.get(keyTuple2).value("val2")); + } + ); + } + + + /** + * Check drop column from table schema. + */ + @Test + public void testAddNewColumn() { + checkAddNewColumn( + SchemaBuilders.column("val2", ColumnType.string()).asNullable().withDefaultValue("default").build(), + grid -> { + // Put data on node. + KeyValueBinaryView kvView = grid.get(1).tables().table(TABLE).kvView(); + + kvView.put(kvView.tupleBuilder().set("key", 1L).build(), kvView.tupleBuilder().set("val1", 222).build()); + + assertThrows(ColumnNotFoundException.class, () -> kvView.put( + kvView.tupleBuilder().set("key", 1L).build(), + kvView.tupleBuilder().set("val1", -111).set("val2", "str").build()) + ); + }, + grid -> { + KeyValueBinaryView kvView = grid.get(2).tables().table(TABLE).kvView(); + + // Check old row conversion. + Tuple keyTuple = kvView.tupleBuilder().set("key", 1L).build(); + + assertEquals(111, (Integer) kvView.get(keyTuple).value("val1")); + assertEquals("default", kvView.get(keyTuple).value("val2")); + + // Check tuple of new schema. + kvView.put(kvView.tupleBuilder().set("key", 2L).build(), + kvView.tupleBuilder().set("val1", 222).set("val2", "str").build()); + + Tuple keyTuple2 = kvView.tupleBuilder().set("key", 2L).build(); + + assertEquals(222, (Integer) kvView.get(keyTuple2).value("val1")); + assertEquals("str", kvView.get(keyTuple2).value("val2")); + }); + } + + /** + * Check rename column from table schema. + */ + @Test + public void testRenameColumn() { + checkRenameColumn( + grid -> { + KeyValueBinaryView kvView = grid.get(1).tables().table(TABLE).kvView(); + + kvView.put(kvView.tupleBuilder().set("key", 1L).build(), kvView.tupleBuilder().set("val1", 111).build()); + + assertThrows(ColumnNotFoundException.class, () -> kvView.put( + kvView.tupleBuilder().set("key", 2L).build(), + kvView.tupleBuilder().set("val2", 222).build()) + ); + }, + grid -> { + KeyValueBinaryView kvView = grid.get(2).tables().table(TABLE).kvView(); + + // Check old row conversion. + Tuple keyTuple1 = kvView.tupleBuilder().set("key", 1L).build(); + + assertEquals(1, (Long) kvView.get(keyTuple1).value("key")); + assertEquals(111, (Integer) kvView.get(keyTuple1).value("val2")); + assertThrows(ColumnNotFoundException.class, () -> kvView.get(keyTuple1).value("val1")); + + // Check tuple of correct schema. + assertThrows(ColumnNotFoundException.class, () -> kvView.put( + kvView.tupleBuilder().set("key", 2L).build(), + kvView.tupleBuilder().set("val1", -222).build()) + ); + + // Check tuple of new schema. + kvView.put(kvView.tupleBuilder().set("key", 2L).build(), kvView.tupleBuilder().set("val2", 222).build()); + + Tuple keyTuple2 = kvView.tupleBuilder().set("key", 2L).build(); + + assertEquals(222, (Integer) kvView.get(keyTuple2).value("val2")); + assertThrows(ColumnNotFoundException.class, () -> kvView.get(keyTuple2).value("val1")); + }); + } +} diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/SchemaChangeTableViewTest.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/SchemaChangeTableViewTest.java new file mode 100644 index 0000000..4d86620 --- /dev/null +++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/SchemaChangeTableViewTest.java @@ -0,0 +1,157 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.runner.app; + +import org.apache.ignite.internal.table.ColumnNotFoundException; +import org.apache.ignite.schema.ColumnType; +import org.apache.ignite.schema.SchemaBuilders; +import org.apache.ignite.table.Table; +import org.apache.ignite.table.Tuple; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +/** + * Ignition interface tests. + */ +@Disabled("https://issues.apache.org/jira/browse/IGNITE-14581") +class SchemaChangeTableViewTest extends AbstractSchemaChangeTest { + /** + * Check add a new column to table schema. + */ + @Test + public void testDropColumn() { + checkDropColumn( + "val2", + (grid) -> { + final Table tbl = grid.get(1).tables().table(TABLE); + + tbl.insert(tbl.tupleBuilder().set("key", 1L).set("val1", 111).set("val2", "str").build()); + }, + (grid) -> { + Table tbl = grid.get(1).tables().table(TABLE); + + // Check old row conversion. + final Tuple keyTuple = tbl.tupleBuilder().set("key", 1L).build(); + + assertEquals(1, (Integer) tbl.get(keyTuple).value("key")); + assertEquals(111, (Integer) tbl.get(keyTuple).value("val1")); + assertThrows(ColumnNotFoundException.class, () -> tbl.get(keyTuple).value("val2")); + + // Check tuple of outdated schema. + assertThrows(ColumnNotFoundException.class, + () -> tbl.insert(tbl.tupleBuilder().set("key", 2L).set("val1", -222).set("val2", "str").build()) + ); + + // Check tuple of correct schema. + tbl.insert(tbl.tupleBuilder().set("key", 2L).set("val1", 222).build()); + + final Tuple keyTuple2 = tbl.tupleBuilder().set("key", 2L).build(); + + assertEquals(2, (Integer) tbl.get(keyTuple2).value("key")); + assertEquals(222, (Integer) tbl.get(keyTuple2).value("val1")); + assertThrows(ColumnNotFoundException.class, () -> tbl.get(keyTuple2).value("val2")); + } + ); + } + + + /** + * Check drop column from table schema. + */ + @Test + public void testAddNewColumn() { + checkAddNewColumn( + SchemaBuilders.column("val2", ColumnType.string()) + .asNullable() + .withDefaultValue("default") + .build(), + grid -> { + // Put data on node. + Table tbl = grid.get(1).tables().table(TABLE); + + tbl.insert(tbl.tupleBuilder().set("key", 1L).set("val1", 111).build()); + + assertThrows(ColumnNotFoundException.class, + () -> tbl.insert(tbl.tupleBuilder().set("key", 2L).set("val1", -222).set("val2", "str").build()) + ); + }, + grid -> { + Table tbl = grid.get(2).tables().table(TABLE); + + // Check old row conversion. + Tuple keyTuple1 = tbl.tupleBuilder().set("key", 1L).build(); + + assertEquals(1, (Long) tbl.get(keyTuple1).value("key")); + assertEquals(111, (Integer) tbl.get(keyTuple1).value("val1")); + assertEquals("default", tbl.get(keyTuple1).value("val2")); + + // Check tuple of new schema. + tbl.insert(tbl.tupleBuilder().set("key", 2L).set("val1", 222).set("val2", "str").build()); + + Tuple keyTuple2 = tbl.tupleBuilder().set("key", 2L).build(); + + assertEquals(2, (Long) tbl.get(keyTuple2).value("key")); + assertEquals(222, (Integer) tbl.get(keyTuple2).value("val1")); + assertEquals("str", tbl.get(keyTuple2).value("val2")); + }); + } + + /** + * Check rename column from table schema. + */ + @Test + void testRenameColumn() { + checkRenameColumn( + grid -> { + Table tbl = grid.get(1).tables().table(TABLE); + + tbl.insert(tbl.tupleBuilder().set("key", 1L).set("val1", 111).build()); + + assertThrows(ColumnNotFoundException.class, + () -> tbl.insert(tbl.tupleBuilder().set("key", 2L).set("val2", -222).build()) + ); + }, + grid -> { + Table tbl = grid.get(1).tables().table(TABLE); + + // Check old row conversion. + Tuple keyTuple1 = tbl.tupleBuilder().set("key", 1L).build(); + + assertEquals(1, (Long) tbl.get(keyTuple1).value("key")); + assertEquals(111, (Integer) tbl.get(keyTuple1).value("val2")); + assertThrows(ColumnNotFoundException.class, () -> tbl.get(keyTuple1).value("val1")); + + // Check tuple of outdated schema. + assertThrows(ColumnNotFoundException.class, + () -> tbl.insert(tbl.tupleBuilder().set("key", 2L).set("val1", -222).build()) + ); + + // Check tuple of correct schema. + tbl.insert(tbl.tupleBuilder().set("key", 2L).set("val2", 222).build()); + + Tuple keyTuple2 = tbl.tupleBuilder().set("key", 2L).build(); + + assertEquals(2, (Long) tbl.get(keyTuple2).value("key")); + assertEquals(222, (Integer) tbl.get(keyTuple2).value("val2")); + assertThrows(ColumnNotFoundException.class, () -> tbl.get(keyTuple2).value("val1")); + }); + } +} diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/SchemaChangeTest.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/SchemaChangeTest.java deleted file mode 100644 index 9857f4d..0000000 --- a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/runner/app/SchemaChangeTest.java +++ /dev/null @@ -1,363 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.ignite.internal.runner.app; - -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import org.apache.ignite.app.Ignite; -import org.apache.ignite.app.IgnitionManager; -import org.apache.ignite.internal.schema.SchemaManager; -import org.apache.ignite.internal.table.ColumnNotFoundException; -import org.apache.ignite.lang.IgniteLogger; -import org.apache.ignite.schema.Column; -import org.apache.ignite.schema.ColumnType; -import org.apache.ignite.schema.SchemaBuilders; -import org.apache.ignite.schema.SchemaTable; -import org.apache.ignite.table.KeyValueBinaryView; -import org.apache.ignite.table.Table; -import org.apache.ignite.table.Tuple; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; - -import static org.apache.ignite.internal.schema.configuration.SchemaConfigurationConverter.convert; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; - -/** - * Ignition interface tests. - */ -@Disabled("https://issues.apache.org/jira/browse/IGNITE-14581") -class SchemaChangeTest { - /** The logger. */ - private static final IgniteLogger LOG = IgniteLogger.forClass(SchemaManager.class); - - /** Nodes bootstrap configuration. */ - private final Map<String, String> nodesBootstrapCfg = new LinkedHashMap<>() {{ - put("node0", "{\n" + - " \"node\": {\n" + - " \"metastorageNodes\":[ \"node0\" ]\n" + - " },\n" + - " \"network\": {\n" + - " \"port\":3344,\n" + - " \"netClusterNodes\":[ \"localhost:3344\", \"localhost:3345\", \"localhost:3346\" ]\n" + - " }\n" + - "}"); - - put("node1", "{\n" + - " \"node\": {\n" + - " \"metastorageNodes\":[ \"node0\" ]\n" + - " },\n" + - " \"network\": {\n" + - " \"port\":3345,\n" + - " \"netClusterNodes\":[ \"localhost:3344\", \"localhost:3345\", \"localhost:3346\" ]\n" + - " }\n" + - "}"); - - put("node2", "{\n" + - " \"node\": {\n" + - " \"metastorageNodes\":[ \"node0\"]\n" + - " },\n" + - " \"network\": {\n" + - " \"port\":3346,\n" + - " \"netClusterNodes\":[ \"localhost:3344\", \"localhost:3345\", \"localhost:3346\" ]\n" + - " }\n" + - "}"); - }}; - - /** - * Check add a new column to table schema. - */ - @Test - void dropColumn() { - List<Ignite> clusterNodes = new ArrayList<>(); - - for (Map.Entry<String, String> nodeBootstrapCfg : nodesBootstrapCfg.entrySet()) - clusterNodes.add(IgnitionManager.start(nodeBootstrapCfg.getKey(), nodeBootstrapCfg.getValue())); - - assertEquals(3, clusterNodes.size()); - - // Create table on node 0. - SchemaTable schTbl1 = SchemaBuilders.tableBuilder("PUBLIC", "tbl1").columns( - SchemaBuilders.column("key", ColumnType.INT64).asNonNull().build(), - SchemaBuilders.column("val1", ColumnType.INT32).asNullable().build(), - SchemaBuilders.column("val2", ColumnType.string()).withDefaultValue("default").build() - ).withPrimaryKey("key").build(); - - clusterNodes.get(0).tables().createTable(schTbl1.canonicalName(), tblCh -> - convert(schTbl1, tblCh) - .changeReplicas(1) - .changePartitions(10) - ); - - Table tbl1 = clusterNodes.get(1).tables().table(schTbl1.canonicalName()); - Table tbl2 = clusterNodes.get(2).tables().table(schTbl1.canonicalName()); - - // Put data on node 1. - KeyValueBinaryView kvView1 = tbl1.kvView(); - - kvView1.put(tbl1.tupleBuilder().set("key", 3L).build(), tbl1.tupleBuilder().set("val1", 333).set("val2", "str").build()); - - clusterNodes.get(1).tables().alterTable(schTbl1.canonicalName(), - chng -> chng.changeColumns(cols -> { - chng.columns().namedListKeys().stream() - .filter(c -> "val2".equals(chng.columns().get(c).name())) - .findFirst() - .ifPresentOrElse( - cols::delete, - () -> { - throw new IllegalStateException("Column not found."); - }); - })); - - assertThrows(ColumnNotFoundException.class, () -> kvView1.put( - kvView1.tupleBuilder().set("key", 2L).build(), - kvView1.tupleBuilder().set("val1", 222).set("val2", "str").build()) - ); - assertThrows(ColumnNotFoundException.class, () -> tbl1.insert( - tbl1.tupleBuilder().set("key", 2L).set("val1", 222).set("val2", "str").build()) - ); - - tbl1.insert(tbl1.tupleBuilder().set("key", 1L).set("val1", 111).build()); - kvView1.put(tbl1.tupleBuilder().set("key", 2L).build(), tbl1.tupleBuilder().set("val1", 222).build()); - - // Get data on node 2. - KeyValueBinaryView kvView2 = tbl2.kvView(); - - { - final Tuple keyTuple1 = tbl2.tupleBuilder().set("key", 1L).build(); - - assertEquals(1, (Long)tbl2.get(keyTuple1).value("key")); - assertEquals(111, (Integer)tbl2.get(keyTuple1).value("val1")); - assertThrows(ColumnNotFoundException.class, () -> tbl2.get(keyTuple1).value("val2")); - - assertThrows(ColumnNotFoundException.class, () -> kvView2.get(keyTuple1).value("key")); - assertEquals(111, (Integer)kvView2.get(keyTuple1).value("val1")); - } - - { - final Tuple keyTuple2 = kvView2.tupleBuilder().set("key", 2L).build(); - - assertEquals(2, (Long)tbl2.get(keyTuple2).value("key")); - assertEquals(222, (Integer)tbl2.get(keyTuple2).value("val1")); - assertThrows(ColumnNotFoundException.class, () -> tbl2.get(keyTuple2).value("val2")); - - assertEquals(222, (Integer)kvView2.get(keyTuple2).value("val1")); - assertThrows(ColumnNotFoundException.class, () -> kvView2.get(keyTuple2).value("val2")); - } - - { // Check old row conversion. - final Tuple keyTuple3 = tbl2.tupleBuilder().set("key", 3L).build(); - - assertEquals(3, (Long)tbl2.get(keyTuple3).value("key")); - assertEquals(333, (Integer)tbl2.get(keyTuple3).value("val1")); - assertThrows(ColumnNotFoundException.class, () -> tbl2.get(keyTuple3).value("val2")); - - assertEquals(333, (Integer)kvView2.get(keyTuple3).value("val1")); - assertThrows(ColumnNotFoundException.class, () -> kvView2.get(keyTuple3).value("val2")); - } - } - - /** - * Check drop column from table schema. - */ - @Test - void addNewColumn() { - List<Ignite> clusterNodes = new ArrayList<>(); - - for (Map.Entry<String, String> nodeBootstrapCfg : nodesBootstrapCfg.entrySet()) - clusterNodes.add(IgnitionManager.start(nodeBootstrapCfg.getKey(), nodeBootstrapCfg.getValue())); - - assertEquals(3, clusterNodes.size()); - - // Create table on node 0. - SchemaTable schTbl1 = SchemaBuilders.tableBuilder("PUBLIC", "tbl1").columns( - SchemaBuilders.column("key", ColumnType.INT64).asNonNull().build(), - SchemaBuilders.column("val1", ColumnType.INT32).asNullable().build() - ).withPrimaryKey("key").build(); - - clusterNodes.get(0).tables().createTable(schTbl1.canonicalName(), tblCh -> - convert(schTbl1, tblCh) - .changeReplicas(1) - .changePartitions(10) - ); - - Table tbl1 = clusterNodes.get(1).tables().table(schTbl1.canonicalName()); - Table tbl2 = clusterNodes.get(2).tables().table(schTbl1.canonicalName()); - - // Put data on node 1. - KeyValueBinaryView kvView1 = tbl1.kvView(); - - tbl1.insert(tbl1.tupleBuilder().set("key", 1L).set("val1", 111).build()); - kvView1.put(tbl1.tupleBuilder().set("key", 2L).build(), tbl1.tupleBuilder().set("val1", 222).build()); - - assertThrows(ColumnNotFoundException.class, () -> kvView1.put( - tbl1.tupleBuilder().set("key", 2L).build(), - tbl1.tupleBuilder().set("val1", 222).set("val2", "str").build()) - ); - assertThrows(ColumnNotFoundException.class, () -> tbl1.insert( - kvView1.tupleBuilder().set("key", 2L).set("val1", 222).set("val2", "str").build()) - ); - - clusterNodes.get(1).tables().alterTable(schTbl1.canonicalName(), - chng -> chng.changeColumns(cols -> { - final int colIdx = chng.columns().size(); - final Column col = SchemaBuilders.column("val2", ColumnType.string()) - .asNullable() - .withDefaultValue("default") - .build(); - - //TODO: avoid 'colIdx' or replace with correct last colIdx. - cols.create(String.valueOf(colIdx), colChg -> convert(col, colChg)); - })); - - kvView1.put(tbl1.tupleBuilder().set("key", 3L).build(), tbl1.tupleBuilder().set("val1", 333).set("val2", "str").build()); - - // Get data on node 2. - KeyValueBinaryView kvView2 = tbl2.kvView(); - - { - Tuple keyTuple3 = tbl2.tupleBuilder().set("key", 3L).build(); - - assertEquals(3, (Long)tbl2.get(keyTuple3).value("key")); - assertEquals(333, (Integer)tbl2.get(keyTuple3).value("val1")); - assertEquals("str", tbl2.get(keyTuple3).value("val2")); - - assertEquals(333, (Integer)kvView2.get(keyTuple3).value("val1")); - assertEquals("str", kvView2.get(keyTuple3).value("val2")); - } - - { // Check old row conversion. - Tuple keyTuple1 = tbl2.tupleBuilder().set("key", 1L).build(); - - assertEquals(1, (Long)tbl2.get(keyTuple1).value("key")); - assertEquals(111, (Integer)tbl2.get(keyTuple1).value("val1")); - assertEquals("default", tbl2.get(keyTuple1).value("val2")); - - assertEquals(111, (Integer)kvView2.get(keyTuple1).value("val1")); - assertEquals("default", kvView2.get(keyTuple1).value("val2")); - } - - { - Tuple keyTuple2 = kvView2.tupleBuilder().set("key", 2L).build(); - - assertEquals(2, (Long)tbl2.get(keyTuple2).value("key")); - assertEquals(222, (Integer)tbl2.get(keyTuple2).value("val1")); - assertEquals("default", tbl2.get(keyTuple2).value("val2")); - - assertEquals(222, (Integer)kvView2.get(keyTuple2).value("val1")); - assertEquals("default", kvView2.get(keyTuple2).value("val2")); - } - } - - /** - * Check rename column from table schema. - */ - @Test - void renameColumn() { - List<Ignite> clusterNodes = new ArrayList<>(); - - for (Map.Entry<String, String> nodeBootstrapCfg : nodesBootstrapCfg.entrySet()) - clusterNodes.add(IgnitionManager.start(nodeBootstrapCfg.getKey(), nodeBootstrapCfg.getValue())); - - assertEquals(3, clusterNodes.size()); - - // Create table on node 0. - SchemaTable schTbl1 = SchemaBuilders.tableBuilder("PUBLIC", "tbl1").columns( - SchemaBuilders.column("key", ColumnType.INT64).asNonNull().build(), - SchemaBuilders.column("val1", ColumnType.INT32).asNullable().build() - ).withPrimaryKey("key").build(); - - clusterNodes.get(0).tables().createTable(schTbl1.canonicalName(), tblCh -> - convert(schTbl1, tblCh) - .changeReplicas(1) - .changePartitions(10) - ); - - Table tbl1 = clusterNodes.get(1).tables().table(schTbl1.canonicalName()); - Table tbl2 = clusterNodes.get(2).tables().table(schTbl1.canonicalName()); - - // Put data on node 1. - KeyValueBinaryView kvView1 = tbl1.kvView(); - - tbl1.insert(tbl1.tupleBuilder().set("key", 1L).set("val1", 111).build()); - kvView1.put(tbl1.tupleBuilder().set("key", 2L).build(), tbl1.tupleBuilder().set("val1", 222).build()); - - assertThrows(ColumnNotFoundException.class, () -> kvView1.put( - tbl1.tupleBuilder().set("key", 2L).build(), - tbl1.tupleBuilder().set("val2", -222).build()) - ); - - clusterNodes.get(1).tables().alterTable(schTbl1.canonicalName(), - tblChanger -> tblChanger.changeColumns(cols -> { - final String colKey = tblChanger.columns().namedListKeys().stream() - .filter(c -> "val1".equals(tblChanger.columns().get(c).name())) - .findFirst() - .orElseThrow(() -> { - throw new IllegalStateException("Column not found."); - }); - - tblChanger.changeColumns(listChanger -> - listChanger.update(colKey, colChanger -> colChanger.changeName("val2")) - ); - })); - - assertThrows(ColumnNotFoundException.class, () -> kvView1.put( - tbl1.tupleBuilder().set("key", 3L).build(), - tbl1.tupleBuilder().set("val1", -333).build()) - ); - - kvView1.put(tbl1.tupleBuilder().set("key", 3L).build(), tbl1.tupleBuilder().set("val2", 333).build()); - - // Get data on node 2. - KeyValueBinaryView kvView2 = tbl2.kvView(); - { - Tuple keyTuple3 = tbl2.tupleBuilder().set("key", 3L).build(); - - assertEquals(3, (Long)tbl2.get(keyTuple3).value("key")); - assertEquals(333, (Integer)tbl2.get(keyTuple3).value("val2")); - assertThrows(ColumnNotFoundException.class, () -> tbl2.get(keyTuple3).value("val1")); - - assertEquals(333, (Integer)kvView2.get(keyTuple3).value("val2")); - assertThrows(ColumnNotFoundException.class, () -> kvView2.get(keyTuple3).value("val1")); - } - - {// Check old row conversion. - Tuple keyTuple1 = tbl2.tupleBuilder().set("key", 1L).build(); - - assertEquals(1, (Long)tbl2.get(keyTuple1).value("key")); - assertEquals(111, (Integer)tbl2.get(keyTuple1).value("val2")); - assertThrows(ColumnNotFoundException.class, () -> tbl2.get(keyTuple1).value("val1")); - - assertEquals(111, (Integer)kvView2.get(keyTuple1).value("val2")); - assertThrows(ColumnNotFoundException.class, () -> kvView2.get(keyTuple1).value("val1")); - } - - { - Tuple keyTuple2 = kvView2.tupleBuilder().set("key", 2L).build(); - - assertEquals(2, (Long)tbl2.get(keyTuple2).value("key")); - assertEquals(222, (Integer)tbl2.get(keyTuple2).value("val2")); - assertThrows(ColumnNotFoundException.class, () -> tbl2.get(keyTuple2).value("val1")); - - assertEquals(222, (Integer)kvView2.get(keyTuple2).value("val2")); - assertThrows(ColumnNotFoundException.class, () -> kvView2.get(keyTuple2).value("val1")); - } - } -}
