This is an automated email from the ASF dual-hosted git repository.
ppa 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 ff52ee946b IGNITE-24025 Introduced catalog command to drop schema
(#4972)
ff52ee946b is described below
commit ff52ee946b374241e638ab93f3e301cdea4a375e
Author: Pavel Pereslegin <[email protected]>
AuthorDate: Mon Dec 30 13:13:49 2024 +0300
IGNITE-24025 Introduced catalog command to drop schema (#4972)
---
.../ignite/internal/catalog/CatalogService.java | 12 ++
.../internal/catalog/commands/CatalogUtils.java | 8 +-
.../catalog/commands/DropSchemaCommand.java | 116 +++++++++++++++++++
.../catalog/commands/DropSchemaCommandBuilder.java | 34 ++++++
.../descriptors/CatalogSchemaDescriptor.java | 5 +
.../internal/catalog/storage/DropSchemaEntry.java | 91 +++++++++++++++
.../CatalogEntrySerializerProvider.java | 2 +
.../serialization/MarshallableEntryType.java | 3 +-
.../ignite/internal/catalog/CatalogIndexTest.java | 8 +-
.../ignite/internal/catalog/CatalogSchemaTest.java | 125 +++++++++++++++++++--
.../catalog/CatalogSchemaValidationTest.java | 98 ++++++++++++++++
.../storage/CatalogEntrySerializationTest.java | 4 +
.../internal/catalog/BaseCatalogManagerTest.java | 23 +++-
.../internal/sql/engine/ItCreateTableDdlTest.java | 11 +-
14 files changed, 521 insertions(+), 19 deletions(-)
diff --git
a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/CatalogService.java
b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/CatalogService.java
index ecdb478974..4e91a28f04 100644
---
a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/CatalogService.java
+++
b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/CatalogService.java
@@ -48,6 +48,18 @@ public interface CatalogService extends
EventProducer<CatalogEvent, CatalogEvent
/** System schema name. */
String SYSTEM_SCHEMA_NAME = "SYSTEM";
+ /**
+ * Information schema - a system schema defined by SQL standard.
+ * The schema provides system-views, which describe Catalog objects, and
can be read by a user.
+ */
+ String INFORMATION_SCHEMA = "INFORMATION_SCHEMA";
+
+ /**
+ * Definition schema - a system schema defined by SQL standard.
+ * The schema provides tables/sources for Catalog object’s metadata and
can’t be accessed by a user directly.
+ */
+ String DEFINITION_SCHEMA = "DEFINITION_SCHEMA";
+
/** Default storage profile. */
String DEFAULT_STORAGE_PROFILE = "default";
diff --git
a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/CatalogUtils.java
b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/CatalogUtils.java
index 3db8bc06ab..b822113c56 100644
---
a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/CatalogUtils.java
+++
b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/CatalogUtils.java
@@ -18,6 +18,8 @@
package org.apache.ignite.internal.catalog.commands;
import static java.util.stream.Collectors.toList;
+import static
org.apache.ignite.internal.catalog.CatalogService.DEFINITION_SCHEMA;
+import static
org.apache.ignite.internal.catalog.CatalogService.INFORMATION_SCHEMA;
import static
org.apache.ignite.internal.catalog.CatalogService.SYSTEM_SCHEMA_NAME;
import static
org.apache.ignite.internal.catalog.commands.DefaultValue.Type.FUNCTION_CALL;
import static org.apache.ignite.internal.lang.IgniteStringFormatter.format;
@@ -145,7 +147,11 @@ public class CatalogUtils {
FUNCTIONAL_DEFAULT_FUNCTIONS.put("RAND_UUID", ColumnType.UUID);
}
- public static final List<String> SYSTEM_SCHEMAS =
List.of(SYSTEM_SCHEMA_NAME);
+ public static final Set<String> SYSTEM_SCHEMAS = Set.of(
+ SYSTEM_SCHEMA_NAME,
+ DEFINITION_SCHEMA,
+ INFORMATION_SCHEMA
+ );
/** System schema names. */
public static boolean isSystemSchema(String schemaName) {
diff --git
a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/DropSchemaCommand.java
b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/DropSchemaCommand.java
new file mode 100644
index 0000000000..d166d5db79
--- /dev/null
+++
b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/DropSchemaCommand.java
@@ -0,0 +1,116 @@
+/*
+ * 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.catalog.commands;
+
+import static
org.apache.ignite.internal.catalog.CatalogParamsValidationUtils.validateIdentifier;
+import static
org.apache.ignite.internal.catalog.commands.CatalogUtils.schemaOrThrow;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.ignite.internal.catalog.Catalog;
+import org.apache.ignite.internal.catalog.CatalogCommand;
+import org.apache.ignite.internal.catalog.CatalogValidationException;
+import org.apache.ignite.internal.catalog.descriptors.CatalogIndexDescriptor;
+import org.apache.ignite.internal.catalog.descriptors.CatalogSchemaDescriptor;
+import org.apache.ignite.internal.catalog.descriptors.CatalogTableDescriptor;
+import org.apache.ignite.internal.catalog.storage.DropIndexEntry;
+import org.apache.ignite.internal.catalog.storage.DropSchemaEntry;
+import org.apache.ignite.internal.catalog.storage.DropTableEntry;
+import org.apache.ignite.internal.catalog.storage.UpdateEntry;
+
+/**
+ * A command that drops a schema with specified name.
+ */
+public class DropSchemaCommand implements CatalogCommand {
+ /** Returns builder to create a command to drop schema with specified
name. */
+ public static DropSchemaCommandBuilder builder() {
+ return new Builder();
+ }
+
+ private final String schemaName;
+
+ private final boolean cascade;
+
+ /**
+ * Constructor.
+ *
+ * @param schemaName Name of the schema.
+ * @param cascade Flag indicating forced deletion of a non-empty schema.
+ * @throws CatalogValidationException if any of restrictions above is
violated.
+ */
+ private DropSchemaCommand(String schemaName, boolean cascade) throws
CatalogValidationException {
+ validateIdentifier(schemaName, "Name of the schema");
+
+ this.schemaName = schemaName;
+ this.cascade = cascade;
+ }
+
+ @Override
+ public List<UpdateEntry> get(Catalog catalog) {
+ if (CatalogUtils.isSystemSchema(schemaName)) {
+ throw new CatalogValidationException("System schema can't be
dropped [name={}].", schemaName);
+ }
+
+ CatalogSchemaDescriptor schema = schemaOrThrow(catalog, schemaName);
+
+ if (!cascade && !schema.isEmpty()) {
+ throw new CatalogValidationException("Schema '{}' is not empty.
Use CASCADE to drop it anyway.", schemaName);
+ }
+
+ List<UpdateEntry> updateEntries = new ArrayList<>();
+
+ for (CatalogIndexDescriptor idx : schema.indexes()) {
+ updateEntries.add(new DropIndexEntry(idx.id()));
+ }
+
+ for (CatalogTableDescriptor tbl : schema.tables()) {
+ updateEntries.add(new DropTableEntry(tbl.id()));
+ }
+
+ updateEntries.add(new DropSchemaEntry(schema.id()));
+
+ return updateEntries;
+ }
+
+ /**
+ * Implementation of {@link DropSchemaCommandBuilder}.
+ */
+ private static class Builder implements DropSchemaCommandBuilder {
+ private String schemaName;
+ private boolean cascade;
+
+ @Override
+ public DropSchemaCommandBuilder name(String schemaName) {
+ this.schemaName = schemaName;
+
+ return this;
+ }
+
+ @Override
+ public DropSchemaCommandBuilder cascade(boolean cascade) {
+ this.cascade = cascade;
+
+ return this;
+ }
+
+ @Override
+ public CatalogCommand build() {
+ return new DropSchemaCommand(schemaName, cascade);
+ }
+ }
+}
diff --git
a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/DropSchemaCommandBuilder.java
b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/DropSchemaCommandBuilder.java
new file mode 100644
index 0000000000..fa5d5d7ad4
--- /dev/null
+++
b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/commands/DropSchemaCommandBuilder.java
@@ -0,0 +1,34 @@
+/*
+ * 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.catalog.commands;
+
+import org.apache.ignite.internal.catalog.CatalogCommand;
+
+/**
+ * Builder of a command that drop specified schema.
+ */
+public interface DropSchemaCommandBuilder {
+ /** Sets schema name. Should not be null or blank. */
+ DropSchemaCommandBuilder name(String schemaName);
+
+ /** Sets flag indicating forced deletion of a non-empty schema. */
+ DropSchemaCommandBuilder cascade(boolean cascade);
+
+ /** Returns a command with specified parameters. */
+ CatalogCommand build();
+}
diff --git
a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/descriptors/CatalogSchemaDescriptor.java
b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/descriptors/CatalogSchemaDescriptor.java
index ec3567bcdd..b5ce13a894 100644
---
a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/descriptors/CatalogSchemaDescriptor.java
+++
b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/descriptors/CatalogSchemaDescriptor.java
@@ -100,6 +100,11 @@ public class CatalogSchemaDescriptor extends
CatalogObjectDescriptor {
return systemViewsMap.get(name);
}
+ /** Returns {@code true} if the schema doesn't contain any objects,
otherwise {@code false}. */
+ public boolean isEmpty() {
+ return tables.length == 0 && indexes.length == 0 && systemViews.length
== 0;
+ }
+
private void rebuildMaps() {
tablesMap =
Arrays.stream(tables).collect(toUnmodifiableMap(CatalogObjectDescriptor::name,
Function.identity()));
indexesMap = Arrays.stream(indexes)
diff --git
a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/storage/DropSchemaEntry.java
b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/storage/DropSchemaEntry.java
new file mode 100644
index 0000000000..ad8241c8b5
--- /dev/null
+++
b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/storage/DropSchemaEntry.java
@@ -0,0 +1,91 @@
+/*
+ * 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.catalog.storage;
+
+import static java.util.stream.Collectors.toList;
+import static
org.apache.ignite.internal.catalog.commands.CatalogUtils.defaultZoneIdOpt;
+
+import java.io.IOException;
+import org.apache.ignite.internal.catalog.Catalog;
+import
org.apache.ignite.internal.catalog.storage.serialization.CatalogObjectSerializer;
+import
org.apache.ignite.internal.catalog.storage.serialization.MarshallableEntryType;
+import org.apache.ignite.internal.tostring.S;
+import org.apache.ignite.internal.util.io.IgniteDataInput;
+import org.apache.ignite.internal.util.io.IgniteDataOutput;
+
+/**
+ * Describes deletion of a schema.
+ */
+public class DropSchemaEntry implements UpdateEntry {
+ public static final CatalogObjectSerializer<DropSchemaEntry> SERIALIZER =
new DropSchemaSerializer();
+
+ private final int schemaId;
+
+ /**
+ * Constructs the object.
+ *
+ * @param schemaId An id of a schema to drop.
+ */
+ public DropSchemaEntry(int schemaId) {
+ this.schemaId = schemaId;
+ }
+
+ /** Returns an id of a schema to drop. */
+ public int schemaId() {
+ return schemaId;
+ }
+
+ @Override
+ public int typeId() {
+ return MarshallableEntryType.DROP_SCHEMA.id();
+ }
+
+ @Override
+ public Catalog applyUpdate(Catalog catalog, long causalityToken) {
+ return new Catalog(
+ catalog.version(),
+ catalog.time(),
+ catalog.objectIdGenState(),
+ catalog.zones(),
+ catalog.schemas().stream().filter(s -> s.id() !=
schemaId).collect(toList()),
+ defaultZoneIdOpt(catalog)
+ );
+ }
+
+ @Override
+ public String toString() {
+ return S.toString(this);
+ }
+
+ /**
+ * Serializer for {@link DropSchemaEntry}.
+ */
+ private static class DropSchemaSerializer implements
CatalogObjectSerializer<DropSchemaEntry> {
+ @Override
+ public DropSchemaEntry readFrom(IgniteDataInput input) throws
IOException {
+ int schemaId = input.readVarIntAsInt();
+
+ return new DropSchemaEntry(schemaId);
+ }
+
+ @Override
+ public void writeTo(DropSchemaEntry entry, IgniteDataOutput output)
throws IOException {
+ output.writeVarInt(entry.schemaId());
+ }
+ }
+}
diff --git
a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/storage/serialization/CatalogEntrySerializerProvider.java
b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/storage/serialization/CatalogEntrySerializerProvider.java
index 86167adc33..5b14f5b93f 100644
---
a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/storage/serialization/CatalogEntrySerializerProvider.java
+++
b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/storage/serialization/CatalogEntrySerializerProvider.java
@@ -23,6 +23,7 @@ import
org.apache.ignite.internal.catalog.storage.AlterColumnEntry;
import org.apache.ignite.internal.catalog.storage.AlterZoneEntry;
import org.apache.ignite.internal.catalog.storage.DropColumnsEntry;
import org.apache.ignite.internal.catalog.storage.DropIndexEntry;
+import org.apache.ignite.internal.catalog.storage.DropSchemaEntry;
import org.apache.ignite.internal.catalog.storage.DropTableEntry;
import org.apache.ignite.internal.catalog.storage.DropZoneEntry;
import org.apache.ignite.internal.catalog.storage.MakeIndexAvailableEntry;
@@ -81,6 +82,7 @@ public interface CatalogEntrySerializerProvider {
serializers[MarshallableEntryType.RENAME_INDEX.id()] =
RenameIndexEntry.SERIALIZER;
serializers[MarshallableEntryType.SET_DEFAULT_ZONE.id()] =
SetDefaultZoneEntry.SERIALIZER;
serializers[MarshallableEntryType.NEW_SCHEMA.id()] =
NewSchemaEntry.SERIALIZER;
+ serializers[MarshallableEntryType.DROP_SCHEMA.id()] =
DropSchemaEntry.SERIALIZER;
//noinspection ThisEscapedInObjectConstruction
serializers[MarshallableEntryType.VERSIONED_UPDATE.id()] = new
VersionedUpdateSerializer(this);
diff --git
a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/storage/serialization/MarshallableEntryType.java
b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/storage/serialization/MarshallableEntryType.java
index 8cdb7230d0..13ddeaddcf 100644
---
a/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/storage/serialization/MarshallableEntryType.java
+++
b/modules/catalog/src/main/java/org/apache/ignite/internal/catalog/storage/serialization/MarshallableEntryType.java
@@ -41,7 +41,8 @@ public enum MarshallableEntryType {
VERSIONED_UPDATE(17),
RENAME_INDEX(18),
SET_DEFAULT_ZONE(19),
- NEW_SCHEMA(20);
+ NEW_SCHEMA(20),
+ DROP_SCHEMA(21);
/** Type ID. */
private final int id;
diff --git
a/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/CatalogIndexTest.java
b/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/CatalogIndexTest.java
index 27ce986cca..b9f112108b 100644
---
a/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/CatalogIndexTest.java
+++
b/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/CatalogIndexTest.java
@@ -848,10 +848,10 @@ public class CatalogIndexTest extends
BaseCatalogManagerTest {
}
private void createSomeSortedIndex(String tableName, String indexName) {
- assertThat(
- manager.execute(createSortedIndexCommand(tableName, indexName,
false, List.of("key1"), List.of(ASC_NULLS_LAST))),
- willCompleteSuccessfully()
- );
+ CatalogCommand newSortedIndexCommand = createSortedIndexCommand(
+ SqlCommon.DEFAULT_SCHEMA_NAME, tableName, indexName, false,
List.of("key1"), List.of(ASC_NULLS_LAST));
+
+ assertThat(manager.execute(newSortedIndexCommand),
willCompleteSuccessfully());
}
private void renameIndex(String indexName, String newIndexName) {
diff --git
a/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/CatalogSchemaTest.java
b/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/CatalogSchemaTest.java
index f468fd9f1f..3a00f619c7 100644
---
a/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/CatalogSchemaTest.java
+++
b/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/CatalogSchemaTest.java
@@ -17,33 +17,144 @@
package org.apache.ignite.internal.catalog;
+import static org.apache.ignite.internal.catalog.CatalogTestUtils.columnParams;
+import static
org.apache.ignite.internal.catalog.descriptors.CatalogColumnCollation.ASC_NULLS_LAST;
import static
org.apache.ignite.internal.testframework.matchers.CompletableFutureExceptionMatcher.willThrowFast;
import static
org.apache.ignite.internal.testframework.matchers.CompletableFutureMatcher.willCompleteSuccessfully;
+import static org.apache.ignite.sql.ColumnType.INT32;
import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.hasSize;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.hamcrest.Matchers.nullValue;
import static org.junit.jupiter.api.Assertions.assertNotNull;
+import java.util.List;
import org.apache.ignite.internal.catalog.commands.CreateSchemaCommand;
+import org.apache.ignite.internal.catalog.commands.DropSchemaCommand;
+import org.apache.ignite.internal.catalog.descriptors.CatalogSchemaDescriptor;
import org.apache.ignite.internal.sql.SqlCommon;
import org.junit.jupiter.api.Test;
/** Tests for schema related commands. */
public class CatalogSchemaTest extends BaseCatalogManagerTest {
+ private static final String TEST_SCHEMA = "S1";
@Test
public void testCreateSchema() {
- String schemaName = "S1";
+
assertThat(manager.execute(CreateSchemaCommand.builder().name(TEST_SCHEMA).build()),
willCompleteSuccessfully());
-
assertThat(manager.execute(CreateSchemaCommand.builder().name(schemaName).build()),
willCompleteSuccessfully());
+ Catalog latestCatalog = latestCatalog();
- Catalog latestCatalog =
manager.catalog(manager.activeCatalogVersion(clock.nowLong()));
-
- assertNotNull(latestCatalog);
- assertNotNull(latestCatalog.schema(schemaName));
+ assertNotNull(latestCatalog.schema(TEST_SCHEMA));
assertNotNull(latestCatalog.schema(SqlCommon.DEFAULT_SCHEMA_NAME));
assertThat(
-
manager.execute(CreateSchemaCommand.builder().name(schemaName).build()),
+
manager.execute(CreateSchemaCommand.builder().name(TEST_SCHEMA).build()),
willThrowFast(CatalogValidationException.class, "Schema with
name 'S1' already exists")
);
}
+
+ @Test
+ public void testDropEmpty() {
+ int initialSchemasCount = latestCatalog().schemas().size();
+
+
assertThat(manager.execute(CreateSchemaCommand.builder().name(TEST_SCHEMA).build()),
willCompleteSuccessfully());
+
+ assertThat(latestCatalog().schemas(), hasSize(initialSchemasCount +
1));
+
+ CatalogCommand cmd =
DropSchemaCommand.builder().name(TEST_SCHEMA).build();
+
+ assertThat(manager.execute(cmd), willCompleteSuccessfully());
+ assertThat(latestCatalog().schema(TEST_SCHEMA), nullValue());
+ assertThat(latestCatalog().schemas(), hasSize(initialSchemasCount));
+
+ assertThat(
+
manager.execute(DropSchemaCommand.builder().name(TEST_SCHEMA).build()),
+ willThrowFast(CatalogValidationException.class, "Schema with
name 'S1' not found")
+ );
+ }
+
+ @Test
+ public void testDropDefaultSchemaIsAllowed() {
+ CatalogCommand cmd =
DropSchemaCommand.builder().name(SqlCommon.DEFAULT_SCHEMA_NAME).build();
+
+ assertThat(manager.execute(cmd), willCompleteSuccessfully());
+ assertThat(latestCatalog().schema(SqlCommon.DEFAULT_SCHEMA_NAME),
nullValue());
+
+ assertThat(
+ manager.execute(simpleTable("test")),
+ willThrowFast(CatalogValidationException.class, "Schema with
name 'PUBLIC' not found")
+ );
+ }
+
+ @Test
+ public void testDropNonEmpty() {
+ CatalogCommand newSchemaCmd =
CreateSchemaCommand.builder().name(TEST_SCHEMA).build();
+ CatalogCommand newTableCmd = newTableCommand("T1");
+ CatalogCommand idxCmd = newIndexCommand("T1", "I1");
+
+ assertThat(
+ manager.execute(List.of(newSchemaCmd, newTableCmd, idxCmd)),
+ willCompleteSuccessfully()
+ );
+
+ // RESTRICT
+ {
+ assertThat(
+
manager.execute(DropSchemaCommand.builder().name(TEST_SCHEMA).build()),
+ willThrowFast(CatalogValidationException.class, "Schema
'S1' is not empty. Use CASCADE to drop it anyway.")
+ );
+
+ CatalogSchemaDescriptor schemaDescriptor =
latestCatalog().schema(TEST_SCHEMA);
+
+ assertThat(schemaDescriptor, is(notNullValue()));
+ assertThat(schemaDescriptor.tables().length, is(1));
+ }
+
+ // CASCADE
+ {
+ assertThat(latestCatalog().tables(), hasSize(1));
+ assertThat(latestCatalog().indexes(), hasSize(2));
+
+ CatalogCommand dropCmd =
DropSchemaCommand.builder().name(TEST_SCHEMA).cascade(true).build();
+
+ assertThat(manager.execute(dropCmd), willCompleteSuccessfully());
+
+ assertThat(latestCatalog().schema(TEST_SCHEMA), nullValue());
+ assertThat(latestCatalog().tables(), hasSize(0));
+ assertThat(latestCatalog().indexes(), hasSize(0));
+ }
+ }
+
+ private Catalog latestCatalog() {
+ Catalog latestCatalog =
manager.catalog(manager.activeCatalogVersion(clock.nowLong()));
+
+ assertThat(latestCatalog, is(notNullValue()));
+
+ return latestCatalog;
+ }
+
+ @SuppressWarnings("SameParameterValue")
+ private static CatalogCommand newTableCommand(String tableName) {
+ return createTableCommand(
+ TEST_SCHEMA,
+ tableName,
+ List.of(columnParams("key1", INT32), columnParams("key2",
INT32), columnParams("val", INT32, true)),
+ List.of("key1", "key2"),
+ List.of("key2")
+ );
+ }
+
+ @SuppressWarnings("SameParameterValue")
+ private static CatalogCommand newIndexCommand(String tableName, String
indexName) {
+ return createSortedIndexCommand(
+ TEST_SCHEMA,
+ tableName,
+ indexName,
+ false,
+ List.of("key1"),
+ List.of(ASC_NULLS_LAST)
+ );
+ }
}
diff --git
a/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/CatalogSchemaValidationTest.java
b/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/CatalogSchemaValidationTest.java
new file mode 100644
index 0000000000..134495cfe3
--- /dev/null
+++
b/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/CatalogSchemaValidationTest.java
@@ -0,0 +1,98 @@
+/*
+ * 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.catalog;
+
+import static org.apache.ignite.internal.lang.IgniteStringFormatter.format;
+import static
org.apache.ignite.internal.testframework.matchers.CompletableFutureExceptionMatcher.willThrowFast;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import org.apache.ignite.internal.catalog.commands.CreateSchemaCommand;
+import org.apache.ignite.internal.catalog.commands.DropSchemaCommand;
+import org.apache.ignite.internal.sql.SqlCommon;
+import org.apache.ignite.internal.testframework.IgniteTestUtils;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+
+/** Validation tests for schema related commands. */
+public class CatalogSchemaValidationTest extends BaseCatalogManagerTest {
+ @Test
+ public void testCreateSchemaWithExistingName() {
+ assertThat(
+
manager.execute(CreateSchemaCommand.builder().name(SqlCommon.DEFAULT_SCHEMA_NAME).build()),
+ willThrowFast(CatalogValidationException.class, "Schema with
name 'PUBLIC' already exists")
+ );
+ }
+
+ @Test
+ public void testDropNonExistingSchema() {
+ assertThat(
+
manager.execute(DropSchemaCommand.builder().name("NON_EXISTING").build()),
+ willThrowFast(CatalogValidationException.class, "Schema with
name 'NON_EXISTING' not found")
+ );
+ }
+
+ @Test
+ @SuppressWarnings("ThrowableNotThrown")
+ public void testCreateSchemaWithNullOrEmptyNameIsRejected() {
+ //noinspection DataFlowIssue
+ IgniteTestUtils.assertThrows(
+ CatalogValidationException.class,
+ () ->
manager.execute(CreateSchemaCommand.builder().name(null).build()),
+ "Name of the schema can't be null or blank"
+ );
+
+ IgniteTestUtils.assertThrows(
+ CatalogValidationException.class,
+ () ->
manager.execute(CreateSchemaCommand.builder().name("").build()),
+ "Name of the schema can't be null or blank"
+ );
+ }
+
+ @ParameterizedTest
+ @ValueSource(strings = {
+ CatalogService.SYSTEM_SCHEMA_NAME,
+ CatalogService.INFORMATION_SCHEMA,
+ CatalogService.DEFINITION_SCHEMA
+ })
+ public void testDropSystemSchemaIsForbidden(String schemaName) {
+ CatalogCommand dropCmd =
DropSchemaCommand.builder().name(schemaName).build();
+
+ assertThat(
+ manager.execute(dropCmd),
+ willThrowFast(CatalogValidationException.class, format("System
schema can't be dropped [name={}]", schemaName))
+ );
+ }
+
+ @Test
+ @SuppressWarnings("ThrowableNotThrown")
+ public void testDropSchemaWithNullOrEmptyNameIsRejected() {
+ //noinspection DataFlowIssue
+ IgniteTestUtils.assertThrows(
+ CatalogValidationException.class,
+ () ->
manager.execute(DropSchemaCommand.builder().name(null).build()),
+ "Name of the schema can't be null or blank"
+ );
+
+ IgniteTestUtils.assertThrows(
+ CatalogValidationException.class,
+ () ->
manager.execute(DropSchemaCommand.builder().name("").build()),
+ "Name of the schema can't be null or blank"
+ );
+ }
+}
diff --git
a/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/storage/CatalogEntrySerializationTest.java
b/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/storage/CatalogEntrySerializationTest.java
index 0a54dfed3e..1254fd2ae6 100644
---
a/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/storage/CatalogEntrySerializationTest.java
+++
b/modules/catalog/src/test/java/org/apache/ignite/internal/catalog/storage/CatalogEntrySerializationTest.java
@@ -173,6 +173,10 @@ public class CatalogEntrySerializationTest extends
BaseIgniteAbstractTest {
0, "S", new CatalogTableDescriptor[0], new
CatalogIndexDescriptor[0], new CatalogSystemViewDescriptor[0], 0)));
break;
+ case DROP_SCHEMA:
+ checkSerialization(new DropSchemaEntry(1));
+ break;
+
default:
throw new UnsupportedOperationException("Test not implemented
" + type);
}
diff --git
a/modules/catalog/src/testFixtures/java/org/apache/ignite/internal/catalog/BaseCatalogManagerTest.java
b/modules/catalog/src/testFixtures/java/org/apache/ignite/internal/catalog/BaseCatalogManagerTest.java
index 75958af48c..deb75422d0 100644
---
a/modules/catalog/src/testFixtures/java/org/apache/ignite/internal/catalog/BaseCatalogManagerTest.java
+++
b/modules/catalog/src/testFixtures/java/org/apache/ignite/internal/catalog/BaseCatalogManagerTest.java
@@ -193,10 +193,11 @@ public abstract class BaseCatalogManagerTest extends
BaseIgniteAbstractTest {
@Nullable List<String> indexColumns,
@Nullable List<CatalogColumnCollation> columnsCollations
) {
- return createSortedIndexCommand(TABLE_NAME, indexName, unique,
indexColumns, columnsCollations);
+ return createSortedIndexCommand(SqlCommon.DEFAULT_SCHEMA_NAME,
TABLE_NAME, indexName, unique, indexColumns, columnsCollations);
}
protected static CatalogCommand createSortedIndexCommand(
+ String schemaName,
String tableName,
String indexName,
boolean unique,
@@ -204,7 +205,7 @@ public abstract class BaseCatalogManagerTest extends
BaseIgniteAbstractTest {
@Nullable List<CatalogColumnCollation> columnsCollations
) {
return CreateSortedIndexCommand.builder()
- .schemaName(SqlCommon.DEFAULT_SCHEMA_NAME)
+ .schemaName(schemaName)
.tableName(tableName)
.indexName(indexName)
.unique(unique)
@@ -227,11 +228,23 @@ public abstract class BaseCatalogManagerTest extends
BaseIgniteAbstractTest {
List<String> primaryKeys,
@Nullable List<String> colocationColumns
) {
- return createTableCommandBuilder(tableName, columns, primaryKeys,
colocationColumns)
+ return createTableCommand(SqlCommon.DEFAULT_SCHEMA_NAME, tableName,
columns, primaryKeys, colocationColumns);
+ }
+
+ protected static CatalogCommand createTableCommand(
+ String schemaName,
+ String tableName,
+ List<ColumnParams> columns,
+ List<String> primaryKeys,
+ @Nullable List<String> colocationColumns
+ ) {
+ return createTableCommandBuilder(schemaName, tableName, columns,
primaryKeys, colocationColumns)
.build();
}
- protected static CreateTableCommandBuilder
createTableCommandBuilder(String tableName,
+ protected static CreateTableCommandBuilder createTableCommandBuilder(
+ String schemaName,
+ String tableName,
List<ColumnParams> columns,
List<String> primaryKeys, @Nullable List<String>
colocationColumns) {
@@ -240,7 +253,7 @@ public abstract class BaseCatalogManagerTest extends
BaseIgniteAbstractTest {
.build();
return CreateTableCommand.builder()
- .schemaName(SqlCommon.DEFAULT_SCHEMA_NAME)
+ .schemaName(schemaName)
.tableName(tableName)
.columns(columns)
.primaryKey(primaryKey)
diff --git
a/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItCreateTableDdlTest.java
b/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItCreateTableDdlTest.java
index 3f50938557..990db0efeb 100644
---
a/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItCreateTableDdlTest.java
+++
b/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItCreateTableDdlTest.java
@@ -20,6 +20,8 @@ package org.apache.ignite.internal.sql.engine;
import static org.apache.ignite.internal.TestWrappers.unwrapIgniteImpl;
import static org.apache.ignite.internal.TestWrappers.unwrapTableViewInternal;
import static
org.apache.ignite.internal.catalog.CatalogService.DEFAULT_STORAGE_PROFILE;
+import static
org.apache.ignite.internal.catalog.CatalogService.DEFINITION_SCHEMA;
+import static
org.apache.ignite.internal.catalog.CatalogService.INFORMATION_SCHEMA;
import static
org.apache.ignite.internal.catalog.commands.CatalogUtils.SYSTEM_SCHEMAS;
import static org.apache.ignite.internal.lang.IgniteStringFormatter.format;
import static
org.apache.ignite.internal.sql.engine.util.SqlTestUtils.assertThrowsSqlException;
@@ -41,11 +43,13 @@ import org.apache.ignite.Ignite;
import org.apache.ignite.internal.app.IgniteImpl;
import org.apache.ignite.internal.catalog.Catalog;
import org.apache.ignite.internal.catalog.CatalogManager;
+import org.apache.ignite.internal.catalog.commands.CreateSchemaCommand;
import org.apache.ignite.internal.catalog.descriptors.CatalogTableDescriptor;
import org.apache.ignite.internal.catalog.descriptors.CatalogZoneDescriptor;
import org.apache.ignite.internal.schema.Column;
import org.apache.ignite.internal.sql.BaseSqlIntegrationTest;
import org.apache.ignite.internal.table.partition.HashPartition;
+import org.apache.ignite.internal.testframework.IgniteTestUtils;
import org.apache.ignite.internal.testframework.WithSystemProperty;
import org.apache.ignite.sql.SqlException;
import org.apache.ignite.table.Table;
@@ -328,8 +332,13 @@ public class ItCreateTableDdlTest extends
BaseSqlIntegrationTest {
@ParameterizedTest
@MethodSource("reservedSchemaNames")
- @SuppressWarnings("ThrowableNotThrown")
public void testItIsNotPossibleToCreateTablesInSystemSchema(String schema)
{
+ if (DEFINITION_SCHEMA.equals(schema) ||
INFORMATION_SCHEMA.equals(schema)) {
+ IgniteImpl igniteImpl = unwrapIgniteImpl(CLUSTER.aliveNode());
+
+
IgniteTestUtils.await(igniteImpl.catalogManager().execute(CreateSchemaCommand.builder().name(schema).build()));
+ }
+
assertThrowsSqlException(
STMT_VALIDATION_ERR,
"Operations with system schemas are not allowed",