You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by pp...@apache.org on 2022/12/05 09:58:54 UTC
[ignite-3] branch main updated: IGNITE-18157 Sql. Provide commands and handlers for distribution zones related operations (#1385)
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 085ebed682 IGNITE-18157 Sql. Provide commands and handlers for distribution zones related operations (#1385)
085ebed682 is described below
commit 085ebed682e0d4d7f26ca91266aa48e2dfd823fa
Author: Pavel Pereslegin <xx...@gmail.com>
AuthorDate: Mon Dec 5 12:58:48 2022 +0300
IGNITE-18157 Sql. Provide commands and handlers for distribution zones related operations (#1385)
---
.../java/org/apache/ignite/lang/ErrorGroups.java | 35 ++--
.../org/apache/ignite/internal/app/IgniteImpl.java | 11 +-
modules/sql-engine/build.gradle | 1 +
modules/sql-engine/pom.xml | 5 +
.../internal/sql/engine/SqlQueryProcessor.java | 7 +
.../sql/engine/exec/ExecutionServiceImpl.java | 4 +-
.../sql/engine/exec/ddl/DdlCommandHandler.java | 55 ++++-
.../sql/engine/prepare/PrepareServiceImpl.java | 4 +-
...OptionInfo.java => AbstractZoneDdlCommand.java} | 47 ++---
.../sql/engine/prepare/ddl/CreateZoneCommand.java | 113 ++++++++++
.../{TableOptionInfo.java => DdlOptionInfo.java} | 21 +-
.../prepare/ddl/DdlSqlToCommandConverter.java | 227 ++++++++++++++-------
.../{TableOptionInfo.java => DropZoneCommand.java} | 40 +---
.../sql/engine/sql/IgniteSqlCreateZone.java | 2 +-
.../internal/sql/engine/sql/IgniteSqlDropZone.java | 2 +-
.../internal/sql/engine/StopCalciteModuleTest.java | 5 +
.../sql/engine/exec/MockedStructuresTest.java | 5 +
.../ddl/DistributionZoneDdlCommandHandlerTest.java | 144 +++++++++++++
.../ddl/AbstractDdlSqlToCommandConverterTest.java | 66 ++++++
.../prepare/ddl/DdlSqlToCommandConverterTest.java | 104 ++--------
.../DistributionZoneSqlToCommandConverterTest.java | 124 +++++++++++
....java => DistributionZoneSqlDdlParserTest.java} | 2 +-
22 files changed, 750 insertions(+), 274 deletions(-)
diff --git a/modules/core/src/main/java/org/apache/ignite/lang/ErrorGroups.java b/modules/core/src/main/java/org/apache/ignite/lang/ErrorGroups.java
index 6d47deadeb..4b215db2a8 100755
--- a/modules/core/src/main/java/org/apache/ignite/lang/ErrorGroups.java
+++ b/modules/core/src/main/java/org/apache/ignite/lang/ErrorGroups.java
@@ -134,7 +134,7 @@ public class ErrorGroups {
public static final int TOO_MANY_GROUPING_EXPRESSIONS_ERR = SQL_ERR_GROUP.registerErrorCode(12);
/** Unsupported sql operation. */
- public static final int USUPPORTED_SQL_OPERATION_KIND_ERR = SQL_ERR_GROUP.registerErrorCode(13);
+ public static final int UNSUPPORTED_SQL_OPERATION_KIND_ERR = SQL_ERR_GROUP.registerErrorCode(13);
/** Unsupported DDL operation. */
public static final int UNSUPPORTED_DDL_OPERATION_ERR = SQL_ERR_GROUP.registerErrorCode(14);
@@ -151,53 +151,50 @@ public class ErrorGroups {
/** Table version not found. */
public static final int TABLE_VER_NOT_FOUND_ERR = SQL_ERR_GROUP.registerErrorCode(18);
- /** Invalid table option. */
- public static final int TABLE_OPTION_ERR = SQL_ERR_GROUP.registerErrorCode(19);
-
/** Query mapping error. */
- public static final int QUERY_MAPPING_ERR = SQL_ERR_GROUP.registerErrorCode(20);
+ public static final int QUERY_MAPPING_ERR = SQL_ERR_GROUP.registerErrorCode(19);
/** DDL execution error. */
- public static final int DDL_EXEC_ERR = SQL_ERR_GROUP.registerErrorCode(21);
+ public static final int DDL_EXEC_ERR = SQL_ERR_GROUP.registerErrorCode(20);
/** DML result error. */
- public static final int INVALID_DML_RESULT_ERR = SQL_ERR_GROUP.registerErrorCode(22);
+ public static final int INVALID_DML_RESULT_ERR = SQL_ERR_GROUP.registerErrorCode(21);
/** SQL data type to relational conversion error. */
- public static final int SQL_TO_REL_CONVERSION_ERR = SQL_ERR_GROUP.registerErrorCode(23);
+ public static final int SQL_TO_REL_CONVERSION_ERR = SQL_ERR_GROUP.registerErrorCode(22);
/** Relational expression serialization error. */
- public static final int REL_SERIALIZATION_ERR = SQL_ERR_GROUP.registerErrorCode(24);
+ public static final int REL_SERIALIZATION_ERR = SQL_ERR_GROUP.registerErrorCode(23);
/** Relational expression deserialization error. */
- public static final int REL_DESERIALIZATION_ERR = SQL_ERR_GROUP.registerErrorCode(25);
+ public static final int REL_DESERIALIZATION_ERR = SQL_ERR_GROUP.registerErrorCode(24);
/** Class not found error. */
- public static final int CLASS_NOT_FOUND_ERR = SQL_ERR_GROUP.registerErrorCode(26);
+ public static final int CLASS_NOT_FOUND_ERR = SQL_ERR_GROUP.registerErrorCode(25);
/** Expression compilation error. */
- public static final int EXPRESSION_COMPILATION_ERR = SQL_ERR_GROUP.registerErrorCode(27);
+ public static final int EXPRESSION_COMPILATION_ERR = SQL_ERR_GROUP.registerErrorCode(26);
/** Node left the cluster. */
- public static final int NODE_LEFT_ERR = SQL_ERR_GROUP.registerErrorCode(28);
+ public static final int NODE_LEFT_ERR = SQL_ERR_GROUP.registerErrorCode(27);
/** Message send error. */
- public static final int MESSAGE_SEND_ERR = SQL_ERR_GROUP.registerErrorCode(29);
+ public static final int MESSAGE_SEND_ERR = SQL_ERR_GROUP.registerErrorCode(28);
/** Operation aborted/interrupted error. */
- public static final int OPERATION_INTERRUPTED_ERR = SQL_ERR_GROUP.registerErrorCode(30);
+ public static final int OPERATION_INTERRUPTED_ERR = SQL_ERR_GROUP.registerErrorCode(29);
/** An error occurred while canceling the operation. */
- public static final int CANCEL_OPERATION_ERR = SQL_ERR_GROUP.registerErrorCode(31);
+ public static final int CANCEL_OPERATION_ERR = SQL_ERR_GROUP.registerErrorCode(30);
/** Session expired error. */
- public static final int SESSION_EXPIRED_ERR = SQL_ERR_GROUP.registerErrorCode(32);
+ public static final int SESSION_EXPIRED_ERR = SQL_ERR_GROUP.registerErrorCode(31);
/** Schema evaluation error. */
- public static final int SCHEMA_EVALUATION_ERR = SQL_ERR_GROUP.registerErrorCode(33);
+ public static final int SCHEMA_EVALUATION_ERR = SQL_ERR_GROUP.registerErrorCode(32);
/** Execution cancelled. */
- public static final int EXECUTION_CANCELLED_ERR = SQL_ERR_GROUP.registerErrorCode(34);
+ public static final int EXECUTION_CANCELLED_ERR = SQL_ERR_GROUP.registerErrorCode(33);
}
/** Meta storage error group. */
diff --git a/modules/runner/src/main/java/org/apache/ignite/internal/app/IgniteImpl.java b/modules/runner/src/main/java/org/apache/ignite/internal/app/IgniteImpl.java
index 940b364058..58b4d7f4a3 100644
--- a/modules/runner/src/main/java/org/apache/ignite/internal/app/IgniteImpl.java
+++ b/modules/runner/src/main/java/org/apache/ignite/internal/app/IgniteImpl.java
@@ -412,6 +412,11 @@ public class IgniteImpl implements Ignite {
indexManager = new IndexManager(tablesConfiguration, schemaManager, distributedTblMgr);
+ DistributionZonesConfiguration zonesConfiguration = clusterCfgMgr.configurationRegistry()
+ .getConfiguration(DistributionZonesConfiguration.KEY);
+
+ distributionZoneManager = new DistributionZoneManager(zonesConfiguration);
+
qryEngine = new SqlQueryProcessor(
registry,
clusterSvc,
@@ -420,6 +425,7 @@ public class IgniteImpl implements Ignite {
schemaManager,
dataStorageMgr,
txManager,
+ distributionZoneManager,
() -> dataStorageModules.collectSchemasFields(modules.distributed().polymorphicSchemaExtensions()),
clock
);
@@ -439,11 +445,6 @@ public class IgniteImpl implements Ignite {
sql,
() -> cmgMgr.clusterState().thenApply(s -> s.clusterTag().clusterId())
);
-
- DistributionZonesConfiguration zonesConfiguration = clusterCfgMgr.configurationRegistry()
- .getConfiguration(DistributionZonesConfiguration.KEY);
-
- distributionZoneManager = new DistributionZoneManager(zonesConfiguration);
}
private RestComponent createRestComponent(String name) {
diff --git a/modules/sql-engine/build.gradle b/modules/sql-engine/build.gradle
index 70af81ceeb..8653e6a368 100644
--- a/modules/sql-engine/build.gradle
+++ b/modules/sql-engine/build.gradle
@@ -32,6 +32,7 @@ dependencies {
implementation project(':ignite-schema')
implementation project(':ignite-transactions')
implementation project(':ignite-replicator')
+ implementation project(':ignite-distribution-zones')
implementation libs.jetbrains.annotations
implementation libs.fastutil.core
implementation libs.caffeine
diff --git a/modules/sql-engine/pom.xml b/modules/sql-engine/pom.xml
index 7eb4eca49f..6ad7ca90dc 100644
--- a/modules/sql-engine/pom.xml
+++ b/modules/sql-engine/pom.xml
@@ -57,6 +57,11 @@
<artifactId>ignite-table</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.apache.ignite</groupId>
+ <artifactId>ignite-distribution-zones</artifactId>
+ </dependency>
+
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/SqlQueryProcessor.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/SqlQueryProcessor.java
index fd74d12688..1b98bca14c 100644
--- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/SqlQueryProcessor.java
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/SqlQueryProcessor.java
@@ -43,6 +43,7 @@ import org.apache.calcite.sql.SqlNode;
import org.apache.calcite.sql.SqlNodeList;
import org.apache.calcite.tools.Frameworks;
import org.apache.calcite.util.Pair;
+import org.apache.ignite.internal.distributionzones.DistributionZoneManager;
import org.apache.ignite.internal.hlc.HybridClock;
import org.apache.ignite.internal.hlc.HybridTimestamp;
import org.apache.ignite.internal.index.IndexManager;
@@ -141,6 +142,9 @@ public class SqlQueryProcessor implements QueryProcessor {
/** Transaction manager. */
private final TxManager txManager;
+ /** Distribution zones manager. */
+ private final DistributionZoneManager distributionZoneManager;
+
/** Clock. */
private final HybridClock clock;
@@ -153,6 +157,7 @@ public class SqlQueryProcessor implements QueryProcessor {
SchemaManager schemaManager,
DataStorageManager dataStorageManager,
TxManager txManager,
+ DistributionZoneManager distributionZoneManager,
Supplier<Map<String, Map<String, Class<?>>>> dataStorageFieldsSupplier,
HybridClock clock
) {
@@ -163,6 +168,7 @@ public class SqlQueryProcessor implements QueryProcessor {
this.schemaManager = schemaManager;
this.dataStorageManager = dataStorageManager;
this.txManager = txManager;
+ this.distributionZoneManager = distributionZoneManager;
this.dataStorageFieldsSupplier = dataStorageFieldsSupplier;
this.clock = clock;
}
@@ -208,6 +214,7 @@ public class SqlQueryProcessor implements QueryProcessor {
clusterSrvc.topologyService(),
msgSrvc,
sqlSchemaManager,
+ distributionZoneManager,
tableManager,
indexManager,
taskExecutor,
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/ExecutionServiceImpl.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/ExecutionServiceImpl.java
index 540c9ec6bf..1d401738c7 100644
--- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/ExecutionServiceImpl.java
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/ExecutionServiceImpl.java
@@ -40,6 +40,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Function;
import org.apache.calcite.tools.Frameworks;
import org.apache.ignite.configuration.ConfigurationChangeException;
+import org.apache.ignite.internal.distributionzones.DistributionZoneManager;
import org.apache.ignite.internal.hlc.HybridTimestamp;
import org.apache.ignite.internal.index.IndexManager;
import org.apache.ignite.internal.logger.IgniteLogger;
@@ -130,6 +131,7 @@ public class ExecutionServiceImpl<RowT> implements ExecutionService, TopologyEve
TopologyService topSrvc,
MessageService msgSrvc,
SqlSchemaManager sqlSchemaManager,
+ DistributionZoneManager distributionZoneManager,
TableManager tblManager,
IndexManager indexManager,
QueryTaskExecutor taskExecutor,
@@ -143,7 +145,7 @@ public class ExecutionServiceImpl<RowT> implements ExecutionService, TopologyEve
msgSrvc,
new MappingServiceImpl(topSrvc),
sqlSchemaManager,
- new DdlCommandHandler(tblManager, indexManager, dataStorageManager),
+ new DdlCommandHandler(distributionZoneManager, tblManager, indexManager, dataStorageManager),
taskExecutor,
handler,
exchangeSrvc,
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 b3927b655d..487f6e4bfb 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
@@ -37,6 +37,10 @@ import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import org.apache.ignite.configuration.NamedListView;
+import org.apache.ignite.internal.distributionzones.DistributionZoneConfigurationParameters;
+import org.apache.ignite.internal.distributionzones.DistributionZoneManager;
+import org.apache.ignite.internal.distributionzones.exception.DistributionZoneAlreadyExistsException;
+import org.apache.ignite.internal.distributionzones.exception.DistributionZoneNotFoundException;
import org.apache.ignite.internal.index.IndexManager;
import org.apache.ignite.internal.schema.BitmaskNativeType;
import org.apache.ignite.internal.schema.DecimalNativeType;
@@ -63,11 +67,13 @@ import org.apache.ignite.internal.sql.engine.prepare.ddl.AlterTableDropCommand;
import org.apache.ignite.internal.sql.engine.prepare.ddl.ColumnDefinition;
import org.apache.ignite.internal.sql.engine.prepare.ddl.CreateIndexCommand;
import org.apache.ignite.internal.sql.engine.prepare.ddl.CreateTableCommand;
+import org.apache.ignite.internal.sql.engine.prepare.ddl.CreateZoneCommand;
import org.apache.ignite.internal.sql.engine.prepare.ddl.DdlCommand;
import org.apache.ignite.internal.sql.engine.prepare.ddl.DefaultValueDefinition.ConstantValue;
import org.apache.ignite.internal.sql.engine.prepare.ddl.DefaultValueDefinition.FunctionCall;
import org.apache.ignite.internal.sql.engine.prepare.ddl.DropIndexCommand;
import org.apache.ignite.internal.sql.engine.prepare.ddl.DropTableCommand;
+import org.apache.ignite.internal.sql.engine.prepare.ddl.DropZoneCommand;
import org.apache.ignite.internal.sql.engine.schema.IgniteIndex.Collation;
import org.apache.ignite.internal.sql.engine.type.IgniteTypeFactory;
import org.apache.ignite.internal.storage.DataStorageManager;
@@ -84,6 +90,8 @@ import org.apache.ignite.sql.SqlException;
/** DDL commands handler. */
public class DdlCommandHandler {
+ private final DistributionZoneManager distributionZoneManager;
+
private final TableManager tableManager;
private final IndexManager indexManager;
@@ -94,10 +102,12 @@ public class DdlCommandHandler {
* Constructor.
*/
public DdlCommandHandler(
+ DistributionZoneManager distributionZoneManager,
TableManager tableManager,
IndexManager indexManager,
DataStorageManager dataStorageManager
) {
+ this.distributionZoneManager = distributionZoneManager;
this.tableManager = tableManager;
this.indexManager = indexManager;
this.dataStorageManager = dataStorageManager;
@@ -119,6 +129,10 @@ public class DdlCommandHandler {
return handleCreateIndex((CreateIndexCommand) cmd);
} else if (cmd instanceof DropIndexCommand) {
return handleDropIndex((DropIndexCommand) cmd);
+ } else if (cmd instanceof CreateZoneCommand) {
+ return handleCreateZone((CreateZoneCommand) cmd);
+ } else if (cmd instanceof DropZoneCommand) {
+ return handleDropZone((DropZoneCommand) cmd);
} else {
return failedFuture(new IgniteInternalCheckedException(UNSUPPORTED_DDL_OPERATION_ERR, "Unsupported DDL operation ["
+ "cmdName=" + (cmd == null ? null : cmd.getClass().getSimpleName()) + "; "
@@ -137,6 +151,33 @@ public class DdlCommandHandler {
}
}
+ /** Handles create distribution zone command. */
+ private CompletableFuture<Boolean> handleCreateZone(CreateZoneCommand cmd) {
+ DistributionZoneConfigurationParameters.Builder zoneCfgBuilder =
+ new DistributionZoneConfigurationParameters.Builder(cmd.zoneName());
+
+ if (cmd.dataNodesAutoAdjust() != null) {
+ zoneCfgBuilder.dataNodesAutoAdjust(cmd.dataNodesAutoAdjust());
+ }
+
+ if (cmd.dataNodesAutoAdjustScaleUp() != null) {
+ zoneCfgBuilder.dataNodesAutoAdjustScaleUp(cmd.dataNodesAutoAdjustScaleUp());
+ }
+
+ if (cmd.dataNodesAutoAdjustScaleDown() != null) {
+ zoneCfgBuilder.dataNodesAutoAdjustScaleDown(cmd.dataNodesAutoAdjustScaleDown());
+ }
+
+ return distributionZoneManager.createZone(zoneCfgBuilder.build())
+ .handle(handleModificationResult(cmd.ifNotExists(), DistributionZoneAlreadyExistsException.class));
+ }
+
+ /** Handles drop distribution zone command. */
+ private CompletableFuture<Boolean> handleDropZone(DropZoneCommand cmd) {
+ return distributionZoneManager.dropZone(cmd.zoneName())
+ .handle(handleModificationResult(cmd.ifExists(), DistributionZoneNotFoundException.class));
+ }
+
/** Handles create table command. */
private CompletableFuture<Boolean> handleCreateTable(CreateTableCommand cmd) {
Consumer<TableChange> tblChanger = tableChange -> {
@@ -170,14 +211,14 @@ public class DdlCommandHandler {
return tableManager.createTableAsync(cmd.tableName(), tblChanger)
.thenApply(Objects::nonNull)
- .handle(handleTableModificationResult(cmd.ifTableExists()));
+ .handle(handleModificationResult(cmd.ifTableExists(), TableAlreadyExistsException.class));
}
/** Handles drop table command. */
private CompletableFuture<Boolean> handleDropTable(DropTableCommand cmd) {
return tableManager.dropTableAsync(cmd.tableName())
.thenApply(v -> Boolean.TRUE)
- .handle(handleTableModificationResult(cmd.ifTableExists()));
+ .handle(handleModificationResult(cmd.ifTableExists(), TableNotFoundException.class));
}
/** Handles add column command. */
@@ -187,7 +228,7 @@ public class DdlCommandHandler {
}
return addColumnInternal(cmd.tableName(), cmd.columns(), cmd.ifColumnNotExists())
- .handle(handleTableModificationResult(cmd.ifTableExists()));
+ .handle(handleModificationResult(cmd.ifTableExists(), TableNotFoundException.class));
}
/** Handles drop column command. */
@@ -197,17 +238,17 @@ public class DdlCommandHandler {
}
return dropColumnInternal(cmd.tableName(), cmd.columns(), cmd.ifColumnExists())
- .handle(handleTableModificationResult(cmd.ifTableExists()));
+ .handle(handleModificationResult(cmd.ifTableExists(), TableNotFoundException.class));
}
- private static BiFunction<Object, Throwable, Boolean> handleTableModificationResult(boolean ignoreTableExistenceErrors) {
+ private static BiFunction<Object, Throwable, Boolean> handleModificationResult(boolean ignoreExpectedError, Class<?> expErrCls) {
return (val, err) -> {
if (err == null) {
return val instanceof Boolean ? (Boolean) val : Boolean.TRUE;
- } else if (ignoreTableExistenceErrors) {
+ } else if (ignoreExpectedError) {
Throwable err0 = err instanceof CompletionException ? err.getCause() : err;
- if (err0 instanceof TableAlreadyExistsException || err0 instanceof TableNotFoundException) {
+ if (expErrCls.isAssignableFrom(err0.getClass())) {
return Boolean.FALSE;
}
}
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/PrepareServiceImpl.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/PrepareServiceImpl.java
index 7f79156fae..3ebc985bc1 100644
--- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/PrepareServiceImpl.java
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/PrepareServiceImpl.java
@@ -20,7 +20,7 @@ package org.apache.ignite.internal.sql.engine.prepare;
import static org.apache.ignite.internal.sql.engine.prepare.PlannerHelper.optimize;
import static org.apache.ignite.internal.sql.engine.trait.TraitUtils.distributionPresent;
import static org.apache.ignite.lang.ErrorGroups.Sql.QUERY_VALIDATION_ERR;
-import static org.apache.ignite.lang.ErrorGroups.Sql.USUPPORTED_SQL_OPERATION_KIND_ERR;
+import static org.apache.ignite.lang.ErrorGroups.Sql.UNSUPPORTED_SQL_OPERATION_KIND_ERR;
import com.github.benmanes.caffeine.cache.Caffeine;
import java.util.ArrayList;
@@ -172,7 +172,7 @@ public class PrepareServiceImpl implements PrepareService, SchemaUpdateListener
return prepareExplain(sqlNode, planningContext);
default:
- throw new IgniteInternalException(USUPPORTED_SQL_OPERATION_KIND_ERR, "Unsupported operation ["
+ throw new IgniteInternalException(UNSUPPORTED_SQL_OPERATION_KIND_ERR, "Unsupported operation ["
+ "sqlNodeKind=" + sqlNode.getKind() + "; "
+ "querySql=\"" + planningContext.query() + "\"]");
}
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/TableOptionInfo.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/AbstractZoneDdlCommand.java
similarity index 50%
copy from modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/TableOptionInfo.java
copy to modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/AbstractZoneDdlCommand.java
index bccc783044..2be4e10ffe 100644
--- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/TableOptionInfo.java
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/AbstractZoneDdlCommand.java
@@ -17,40 +17,29 @@
package org.apache.ignite.internal.sql.engine.prepare.ddl;
-import java.util.function.BiConsumer;
-import java.util.function.Consumer;
-import org.jetbrains.annotations.Nullable;
-
/**
- * Table option information for its processing.
+ * Abstract zone ddl command.
*/
-class TableOptionInfo<T> {
- final String name;
+public class AbstractZoneDdlCommand implements DdlCommand {
+ /** Table zone. */
+ private String zoneName;
- final Class<T> type;
+ /** Schema name where this new zone will be created. */
+ private String schemaName;
- @Nullable
- final Consumer<T> validator;
+ public String zoneName() {
+ return zoneName;
+ }
- final BiConsumer<CreateTableCommand, T> setter;
+ public void zoneName(String zoneName) {
+ this.zoneName = zoneName;
+ }
+
+ public String schemaName() {
+ return schemaName;
+ }
- /**
- * Constructor.
- *
- * @param name Table option name.
- * @param type Table option type.
- * @param validator Table option value validator.
- * @param setter Table option value setter.
- */
- TableOptionInfo(
- String name,
- Class<T> type,
- @Nullable Consumer<T> validator,
- BiConsumer<CreateTableCommand, T> setter
- ) {
- this.name = name;
- this.type = type;
- this.validator = validator;
- this.setter = setter;
+ public void schemaName(String schemaName) {
+ this.schemaName = schemaName;
}
}
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/CreateZoneCommand.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/CreateZoneCommand.java
new file mode 100644
index 0000000000..c1a5ca096c
--- /dev/null
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/CreateZoneCommand.java
@@ -0,0 +1,113 @@
+/*
+ * 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.sql.engine.prepare.ddl;
+
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * CREATE ZONE statement.
+ */
+public class CreateZoneCommand extends AbstractZoneDdlCommand {
+ /** Quietly ignore this command if zone is already exists. */
+ private boolean ifNotExists;
+
+ /** Replicas number. */
+ private Integer replicas;
+
+ /** Number of partitions. */
+ private Integer partitions;
+
+ /** Affinity function name. */
+ private String affinity;
+
+ /** Data nodes filter expression. */
+ private String nodeFiler;
+
+ /** Data nodes auto adjust timeout. */
+ private Integer dataNodesAutoAdjust;
+
+ /** Data nodes auto adjust scale up timeout. */
+ private Integer dataNodesAutoAdjustScaleUp;
+
+ /** Data nodes auto adjust scale down timeout. */
+ private Integer dataNodesAutoAdjustScaleDown;
+
+ public boolean ifNotExists() {
+ return ifNotExists;
+ }
+
+ public void ifNotExists(boolean ifNotExists) {
+ this.ifNotExists = ifNotExists;
+ }
+
+ @Nullable public Integer replicas() {
+ return replicas;
+ }
+
+ public void replicas(Integer replicas) {
+ this.replicas = replicas;
+ }
+
+ @Nullable public Integer partitions() {
+ return partitions;
+ }
+
+ public void partitions(Integer partitions) {
+ this.partitions = partitions;
+ }
+
+ @Nullable public String affinity() {
+ return affinity;
+ }
+
+ public void affinity(String affinity) {
+ this.affinity = affinity;
+ }
+
+ @Nullable public String nodeFilter() {
+ return nodeFiler;
+ }
+
+ public void nodeFilter(String nodeFiler) {
+ this.nodeFiler = nodeFiler;
+ }
+
+ @Nullable public Integer dataNodesAutoAdjust() {
+ return dataNodesAutoAdjust;
+ }
+
+ public void dataNodesAutoAdjust(Integer dataNodesAutoAdjust) {
+ this.dataNodesAutoAdjust = dataNodesAutoAdjust;
+ }
+
+ @Nullable public Integer dataNodesAutoAdjustScaleUp() {
+ return dataNodesAutoAdjustScaleUp;
+ }
+
+ public void dataNodesAutoAdjustScaleUp(Integer dataNodesAutoAdjustScaleUp) {
+ this.dataNodesAutoAdjustScaleUp = dataNodesAutoAdjustScaleUp;
+ }
+
+ @Nullable public Integer dataNodesAutoAdjustScaleDown() {
+ return dataNodesAutoAdjustScaleDown;
+ }
+
+ public void dataNodesAutoAdjustScaleDown(Integer dataNodesAutoAdjustScaleDown) {
+ this.dataNodesAutoAdjustScaleDown = dataNodesAutoAdjustScaleDown;
+ }
+}
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/TableOptionInfo.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/DdlOptionInfo.java
similarity index 73%
copy from modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/TableOptionInfo.java
copy to modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/DdlOptionInfo.java
index bccc783044..dc12975126 100644
--- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/TableOptionInfo.java
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/DdlOptionInfo.java
@@ -22,33 +22,28 @@ import java.util.function.Consumer;
import org.jetbrains.annotations.Nullable;
/**
- * Table option information for its processing.
+ * DDL option information for its processing.
*/
-class TableOptionInfo<T> {
- final String name;
-
+class DdlOptionInfo<S, T> {
final Class<T> type;
@Nullable
final Consumer<T> validator;
- final BiConsumer<CreateTableCommand, T> setter;
+ final BiConsumer<S, T> setter;
/**
* Constructor.
*
- * @param name Table option name.
- * @param type Table option type.
- * @param validator Table option value validator.
- * @param setter Table option value setter.
+ * @param type DDL option type.
+ * @param validator DDL option value validator.
+ * @param setter DDL option value updater.
*/
- TableOptionInfo(
- String name,
+ DdlOptionInfo(
Class<T> type,
@Nullable Consumer<T> validator,
- BiConsumer<CreateTableCommand, T> setter
+ BiConsumer<S, T> setter
) {
- this.name = name;
this.type = type;
this.validator = validator;
this.setter = setter;
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 a8d2eeb1bd..ac7d4e7ea9 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
@@ -20,14 +20,21 @@ package org.apache.ignite.internal.sql.engine.prepare.ddl;
import static java.util.function.Function.identity;
import static java.util.stream.Collectors.toUnmodifiableMap;
import static org.apache.ignite.internal.schema.configuration.storage.UnknownDataStorageConfigurationSchema.UNKNOWN_DATA_STORAGE;
+import static org.apache.ignite.internal.sql.engine.sql.IgniteSqlCreateZoneOptionEnum.AFFINITY_FUNCTION;
+import static org.apache.ignite.internal.sql.engine.sql.IgniteSqlCreateZoneOptionEnum.DATA_NODES_AUTO_ADJUST;
+import static org.apache.ignite.internal.sql.engine.sql.IgniteSqlCreateZoneOptionEnum.DATA_NODES_AUTO_ADJUST_SCALE_DOWN;
+import static org.apache.ignite.internal.sql.engine.sql.IgniteSqlCreateZoneOptionEnum.DATA_NODES_AUTO_ADJUST_SCALE_UP;
+import static org.apache.ignite.internal.sql.engine.sql.IgniteSqlCreateZoneOptionEnum.DATA_NODES_FILTER;
+import static org.apache.ignite.internal.sql.engine.sql.IgniteSqlCreateZoneOptionEnum.PARTITIONS;
+import static org.apache.ignite.internal.sql.engine.sql.IgniteSqlCreateZoneOptionEnum.REPLICAS;
import static org.apache.ignite.internal.util.CollectionUtils.nullOrEmpty;
import static org.apache.ignite.lang.ErrorGroups.Sql.PRIMARY_KEYS_MULTIPLE_ERR;
import static org.apache.ignite.lang.ErrorGroups.Sql.PRIMARY_KEY_MISSING_ERR;
import static org.apache.ignite.lang.ErrorGroups.Sql.QUERY_INVALID_ERR;
+import static org.apache.ignite.lang.ErrorGroups.Sql.QUERY_VALIDATION_ERR;
import static org.apache.ignite.lang.ErrorGroups.Sql.SCHEMA_NOT_FOUND_ERR;
import static org.apache.ignite.lang.ErrorGroups.Sql.SQL_TO_REL_CONVERSION_ERR;
import static org.apache.ignite.lang.ErrorGroups.Sql.STORAGE_ENGINE_NOT_VALID_ERR;
-import static org.apache.ignite.lang.ErrorGroups.Sql.TABLE_OPTION_ERR;
import static org.apache.ignite.lang.ErrorGroups.Sql.UNSUPPORTED_DDL_OPERATION_ERR;
import java.math.BigDecimal;
@@ -35,7 +42,9 @@ import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneOffset;
+import java.util.AbstractMap.SimpleEntry;
import java.util.ArrayList;
+import java.util.EnumSet;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -44,7 +53,6 @@ import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
import java.util.stream.Collectors;
-import java.util.stream.Stream;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.schema.ColumnStrategy;
import org.apache.calcite.sql.SqlBasicTypeNameSpec;
@@ -74,10 +82,13 @@ import org.apache.ignite.internal.sql.engine.sql.IgniteSqlAlterTableDropColumn;
import org.apache.ignite.internal.sql.engine.sql.IgniteSqlCreateIndex;
import org.apache.ignite.internal.sql.engine.sql.IgniteSqlCreateTable;
import org.apache.ignite.internal.sql.engine.sql.IgniteSqlCreateTableOption;
+import org.apache.ignite.internal.sql.engine.sql.IgniteSqlCreateZone;
+import org.apache.ignite.internal.sql.engine.sql.IgniteSqlCreateZoneOption;
+import org.apache.ignite.internal.sql.engine.sql.IgniteSqlCreateZoneOptionEnum;
import org.apache.ignite.internal.sql.engine.sql.IgniteSqlDropIndex;
+import org.apache.ignite.internal.sql.engine.sql.IgniteSqlDropZone;
import org.apache.ignite.internal.sql.engine.sql.IgniteSqlIndexType;
import org.apache.ignite.internal.sql.engine.util.Commons;
-import org.apache.ignite.internal.util.ArrayUtils;
import org.apache.ignite.lang.IgniteException;
import org.apache.ignite.sql.SqlException;
import org.jetbrains.annotations.Nullable;
@@ -96,17 +107,14 @@ public class DdlSqlToCommandConverter {
*/
private final Map<String, String> dataStorageNames;
- /**
- * Mapping: Table option ID -> table option info.
- *
- * <p>Example for "replicas": {@code Map.of("REPLICAS", TableOptionInfo@123)}.
- */
- private final Map<String, TableOptionInfo<?>> tableOptionInfos;
+ /** Mapping: Table option ID -> DDL option info. */
+ private final Map<String, DdlOptionInfo<CreateTableCommand, ?>> tableOptionInfos;
- /**
- * Like {@link #tableOptionInfos}, but for each data storage name.
- */
- private final Map<String, Map<String, TableOptionInfo<?>>> dataStorageOptionInfos;
+ /** Like {@link #tableOptionInfos}, but for each data storage name. */
+ private final Map<String, Map<String, DdlOptionInfo<CreateTableCommand, ?>>> dataStorageOptionInfos;
+
+ /** Mapping: Zone option ID -> DDL option info. */
+ private final Map<IgniteSqlCreateZoneOptionEnum, DdlOptionInfo<CreateZoneCommand, ?>> zoneOptionInfos;
/**
* Constructor.
@@ -122,23 +130,36 @@ public class DdlSqlToCommandConverter {
this.dataStorageNames = collectDataStorageNames(dataStorageFields.keySet());
- this.tableOptionInfos = collectTableOptionInfos(
- new TableOptionInfo<>("replicas", Integer.class, this::checkPositiveNumber, CreateTableCommand::replicas),
- new TableOptionInfo<>("partitions", Integer.class, this::checkPositiveNumber, CreateTableCommand::partitions)
+ this.tableOptionInfos = Map.of(
+ REPLICAS.name(), new DdlOptionInfo<>(Integer.class, this::checkPositiveNumber, CreateTableCommand::replicas),
+ PARTITIONS.name(), new DdlOptionInfo<>(Integer.class, this::checkPositiveNumber, CreateTableCommand::partitions)
);
this.dataStorageOptionInfos = dataStorageFields.entrySet()
.stream()
.collect(toUnmodifiableMap(
Entry::getKey,
- e0 -> collectTableOptionInfos(
- e0.getValue().entrySet().stream()
- .map(this::dataStorageFieldOptionInfo)
- .toArray(TableOptionInfo[]::new)
- )
+ e0 -> e0.getValue().entrySet().stream()
+ .map(this::dataStorageFieldOptionInfo)
+ .collect(toUnmodifiableMap(k -> k.getKey().toUpperCase(), Entry::getValue))
));
- dataStorageOptionInfos.forEach((k, v) -> checkDuplicates(v, tableOptionInfos));
+ dataStorageOptionInfos.values().forEach(v -> checkDuplicates(v.keySet(), tableOptionInfos.keySet()));
+
+ // CREATE ZONE options.
+ zoneOptionInfos = Map.of(
+ REPLICAS, new DdlOptionInfo<>(Integer.class, this::checkPositiveNumber, CreateZoneCommand::replicas),
+ PARTITIONS, new DdlOptionInfo<>(Integer.class, this::checkPositiveNumber, CreateZoneCommand::partitions),
+ AFFINITY_FUNCTION, new DdlOptionInfo<>(String.class, null, CreateZoneCommand::affinity),
+ DATA_NODES_FILTER, new DdlOptionInfo<>(String.class, null, CreateZoneCommand::nodeFilter),
+
+ DATA_NODES_AUTO_ADJUST,
+ new DdlOptionInfo<>(Integer.class, this::checkPositiveNumber, CreateZoneCommand::dataNodesAutoAdjust),
+ DATA_NODES_AUTO_ADJUST_SCALE_UP,
+ new DdlOptionInfo<>(Integer.class, this::checkPositiveNumber, CreateZoneCommand::dataNodesAutoAdjustScaleUp),
+ DATA_NODES_AUTO_ADJUST_SCALE_DOWN,
+ new DdlOptionInfo<>(Integer.class, this::checkPositiveNumber, CreateZoneCommand::dataNodesAutoAdjustScaleDown)
+ );
}
/**
@@ -172,6 +193,14 @@ public class DdlSqlToCommandConverter {
return convertDropIndex((IgniteSqlDropIndex) ddlNode, ctx);
}
+ if (ddlNode instanceof IgniteSqlCreateZone) {
+ return convertCreateZone((IgniteSqlCreateZone) ddlNode, ctx);
+ }
+
+ if (ddlNode instanceof IgniteSqlDropZone) {
+ return convertDropZone((IgniteSqlDropZone) ddlNode, ctx);
+ }
+
throw new SqlException(UNSUPPORTED_DDL_OPERATION_ERR, "Unsupported operation ["
+ "sqlNodeKind=" + ddlNode.getKind() + "; "
+ "querySql=\"" + ctx.query() + "\"]");
@@ -185,13 +214,16 @@ public class DdlSqlToCommandConverter {
*/
private CreateTableCommand convertCreateTable(IgniteSqlCreateTable createTblNode, PlanningContext ctx) {
CreateTableCommand createTblCmd = new CreateTableCommand();
+ String dataStorageName = deriveDataStorage(createTblNode.engineName(), ctx);
createTblCmd.schemaName(deriveSchemaName(createTblNode.name(), ctx));
createTblCmd.tableName(deriveObjectName(createTblNode.name(), ctx, "tableName"));
createTblCmd.ifTableExists(createTblNode.ifNotExists());
- createTblCmd.dataStorage(deriveDataStorage(createTblNode.engineName(), ctx));
+ createTblCmd.dataStorage(dataStorageName);
if (createTblNode.createOptionList() != null) {
+ Map<String, DdlOptionInfo<CreateTableCommand, ?>> dsOptInfos = dataStorageOptionInfos.get(dataStorageName);
+
for (SqlNode optionNode : createTblNode.createOptionList().getList()) {
IgniteSqlCreateTableOption option = (IgniteSqlCreateTableOption) optionNode;
@@ -199,13 +231,17 @@ public class DdlSqlToCommandConverter {
String optionKey = option.key().getSimple().toUpperCase();
- if (tableOptionInfos.containsKey(optionKey)) {
- processTableOption(tableOptionInfos.get(optionKey), option, ctx, createTblCmd);
- } else if (dataStorageOptionInfos.get(createTblCmd.dataStorage()).containsKey(optionKey)) {
- processTableOption(dataStorageOptionInfos.get(createTblCmd.dataStorage()).get(optionKey), option, ctx, createTblCmd);
+ DdlOptionInfo<CreateTableCommand, ?> tblOptionInfo = tableOptionInfos.get(optionKey);
+
+ if (tblOptionInfo == null) {
+ tblOptionInfo = dsOptInfos.get(optionKey);
+ }
+
+ if (tblOptionInfo != null) {
+ updateCommandOption("Table", optionKey, (SqlLiteral) option.value(), tblOptionInfo, ctx.query(), createTblCmd);
} else {
throw new IgniteException(
- TABLE_OPTION_ERR, String.format("Unexpected table option [option=%s, query=%s]", optionKey, ctx.query()));
+ QUERY_VALIDATION_ERR, String.format("Unexpected table option [option=%s, query=%s]", optionKey, ctx.query()));
}
}
}
@@ -438,6 +474,61 @@ public class DdlSqlToCommandConverter {
return dropCmd;
}
+ /**
+ * Converts a given CreateZone AST to a CreateZone command.
+ *
+ * @param createZoneNode Root node of the given AST.
+ * @param ctx Planning context.
+ */
+ private CreateZoneCommand convertCreateZone(IgniteSqlCreateZone createZoneNode, PlanningContext ctx) {
+ CreateZoneCommand createZoneCmd = new CreateZoneCommand();
+
+ createZoneCmd.schemaName(deriveSchemaName(createZoneNode.name(), ctx));
+ createZoneCmd.zoneName(deriveObjectName(createZoneNode.name(), ctx, "zoneName"));
+ createZoneCmd.ifNotExists(createZoneNode.ifNotExists());
+
+ if (createZoneNode.createOptionList() == null) {
+ return createZoneCmd;
+ }
+
+ Set<IgniteSqlCreateZoneOptionEnum> knownOptionNames = EnumSet.allOf(IgniteSqlCreateZoneOptionEnum.class);
+
+ for (SqlNode optionNode : createZoneNode.createOptionList().getList()) {
+ IgniteSqlCreateZoneOption option = (IgniteSqlCreateZoneOption) optionNode;
+ IgniteSqlCreateZoneOptionEnum optionName = option.key().symbolValue(IgniteSqlCreateZoneOptionEnum.class);
+
+ if (!knownOptionNames.remove(optionName)) {
+ throw new IgniteException(QUERY_VALIDATION_ERR,
+ String.format("Duplicate DDL command option specified [option=%s, query=%s]", optionName, ctx.query()));
+ }
+
+ DdlOptionInfo<CreateZoneCommand, ?> zoneOptionInfo = zoneOptionInfos.get(optionName);
+
+ assert zoneOptionInfo != null : optionName;
+ assert option.value() instanceof SqlLiteral : option.value();
+
+ updateCommandOption("Zone", optionName, (SqlLiteral) option.value(), zoneOptionInfo, ctx.query(), createZoneCmd);
+ }
+
+ return createZoneCmd;
+ }
+
+ /**
+ * Converts a given DropZone AST to a DropZone command.
+ *
+ * @param dropZoneNode Root node of the given AST.
+ * @param ctx Planning context.
+ */
+ private DropZoneCommand convertDropZone(IgniteSqlDropZone dropZoneNode, PlanningContext ctx) {
+ DropZoneCommand dropZoneCmd = new DropZoneCommand();
+
+ dropZoneCmd.schemaName(deriveSchemaName(dropZoneNode.name(), ctx));
+ dropZoneCmd.zoneName(deriveObjectName(dropZoneNode.name(), ctx, "zoneName"));
+ dropZoneCmd.ifExists(dropZoneNode.ifExists());
+
+ return dropZoneCmd;
+ }
+
/** Derives a schema name from the compound identifier. */
private String deriveSchemaName(SqlIdentifier id, PlanningContext ctx) {
String schemaName;
@@ -495,32 +586,17 @@ public class DdlSqlToCommandConverter {
return dataStorages.stream().collect(toUnmodifiableMap(String::toUpperCase, identity()));
}
- /**
- * Collects a mapping of the ID of the table option to a table option info.
- *
- * <p>Example for "replicas": {@code Map.of("REPLICAS", TableOptionInfo@123)}.
- *
- * @param tableOptionInfos Table option information's.
- * @throws IllegalStateException If there is a duplicate ID.
- */
- static Map<String, TableOptionInfo<?>> collectTableOptionInfos(TableOptionInfo<?>... tableOptionInfos) {
- return ArrayUtils.nullOrEmpty(tableOptionInfos) ? Map.of() : Stream.of(tableOptionInfos).collect(toUnmodifiableMap(
- tableOptionInfo -> tableOptionInfo.name.toUpperCase(),
- identity()
- ));
- }
-
/**
* Checks that there are no ID duplicates.
*
- * @param tableOptionInfos0 Table options information.
- * @param tableOptionInfos1 Table options information.
+ * @param set0 Set of string identifiers.
+ * @param set1 Set of string identifiers.
* @throws IllegalStateException If there is a duplicate ID.
*/
- static void checkDuplicates(Map<String, TableOptionInfo<?>> tableOptionInfos0, Map<String, TableOptionInfo<?>> tableOptionInfos1) {
- for (String id : tableOptionInfos1.keySet()) {
- if (tableOptionInfos0.containsKey(id)) {
- throw new IllegalStateException("Duplicate id:" + id);
+ static void checkDuplicates(Set<String> set0, Set<String> set1) {
+ for (String id : set1) {
+ if (set0.contains(id)) {
+ throw new IllegalStateException("Duplicate id: " + id);
}
}
}
@@ -550,51 +626,56 @@ public class DdlSqlToCommandConverter {
return dataStorageNames.get(dataStorage);
}
- private void processTableOption(
- TableOptionInfo tableOptionInfo,
- IgniteSqlCreateTableOption option,
- PlanningContext context,
- CreateTableCommand createTableCommand
+ private <S, T> void updateCommandOption(
+ String sqlObjName,
+ Object optId,
+ SqlLiteral value,
+ DdlOptionInfo<S, T> optInfo,
+ String query,
+ S target
) {
- assert option.value() instanceof SqlLiteral : option.value();
-
- Object optionValue;
+ T value0;
try {
- optionValue = ((SqlLiteral) option.value()).getValueAs(tableOptionInfo.type);
+ value0 = value.getValueAs(optInfo.type);
} catch (AssertionError | ClassCastException e) {
- throw new IgniteException(TABLE_OPTION_ERR, String.format(
- "Unsuspected table option type [option=%s, expectedType=%s, query=%s]",
- option.key().getSimple(),
- tableOptionInfo.type.getSimpleName(),
- context.query())
+ throw new IgniteException(QUERY_VALIDATION_ERR, String.format(
+ "Unsuspected %s option type [option=%s, expectedType=%s, query=%s]",
+ sqlObjName.toLowerCase(),
+ optId,
+ optInfo.type.getSimpleName(),
+ query)
);
}
- if (tableOptionInfo.validator != null) {
+ if (optInfo.validator != null) {
try {
- tableOptionInfo.validator.accept(optionValue);
+ optInfo.validator.accept(value0);
} catch (Throwable e) {
- throw new IgniteException(TABLE_OPTION_ERR, String.format(
- "Table option validation failed [option=%s, err=%s, query=%s]",
- option.key().getSimple(),
+ throw new IgniteException(QUERY_VALIDATION_ERR, String.format(
+ "%s option validation failed [option=%s, err=%s, query=%s]",
+ sqlObjName,
+ optId,
e.getMessage(),
- context.query()
+ query
), e);
}
}
- tableOptionInfo.setter.accept(createTableCommand, optionValue);
+ optInfo.setter.accept(target, value0);
}
private void checkPositiveNumber(int num) {
if (num < 0) {
- throw new IgniteException(TABLE_OPTION_ERR, "Must be positive:" + num);
+ throw new IgniteException(QUERY_VALIDATION_ERR, "Must be positive:" + num);
}
}
- private TableOptionInfo<?> dataStorageFieldOptionInfo(Entry<String, Class<?>> e) {
- return new TableOptionInfo<>(e.getKey(), e.getValue(), null, (cmd, o) -> cmd.addDataStorageOption(e.getKey(), o));
+ private Entry<String, DdlOptionInfo<CreateTableCommand, ?>> dataStorageFieldOptionInfo(Entry<String, Class<?>> e) {
+ return new SimpleEntry<>(
+ e.getKey(),
+ new DdlOptionInfo<>(e.getValue(), null, (cmd, o) -> cmd.addDataStorageOption(e.getKey(), o))
+ );
}
private Type convertIndexType(IgniteSqlIndexType type) {
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/TableOptionInfo.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/DropZoneCommand.java
similarity index 50%
rename from modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/TableOptionInfo.java
rename to modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/DropZoneCommand.java
index bccc783044..4186418bdb 100644
--- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/TableOptionInfo.java
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/DropZoneCommand.java
@@ -17,40 +17,18 @@
package org.apache.ignite.internal.sql.engine.prepare.ddl;
-import java.util.function.BiConsumer;
-import java.util.function.Consumer;
-import org.jetbrains.annotations.Nullable;
-
/**
- * Table option information for its processing.
+ * DROP ZONE statement.
*/
-class TableOptionInfo<T> {
- final String name;
-
- final Class<T> type;
+public class DropZoneCommand extends AbstractZoneDdlCommand {
+ /** Quietly ignore this command if the zone does not exist. */
+ private boolean ifExists;
- @Nullable
- final Consumer<T> validator;
-
- final BiConsumer<CreateTableCommand, T> setter;
+ public boolean ifExists() {
+ return ifExists;
+ }
- /**
- * Constructor.
- *
- * @param name Table option name.
- * @param type Table option type.
- * @param validator Table option value validator.
- * @param setter Table option value setter.
- */
- TableOptionInfo(
- String name,
- Class<T> type,
- @Nullable Consumer<T> validator,
- BiConsumer<CreateTableCommand, T> setter
- ) {
- this.name = name;
- this.type = type;
- this.validator = validator;
- this.setter = setter;
+ public void ifExists(boolean ifExists) {
+ this.ifExists = ifExists;
}
}
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/sql/IgniteSqlCreateZone.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/sql/IgniteSqlCreateZone.java
index 56e308e595..3a8739c15e 100644
--- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/sql/IgniteSqlCreateZone.java
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/sql/IgniteSqlCreateZone.java
@@ -39,7 +39,7 @@ public class IgniteSqlCreateZone extends SqlCreate {
private final @Nullable SqlNodeList createOptionList;
- private static final SqlOperator OPERATOR = new SqlSpecialOperator("CREATE ZONE", SqlKind.OTHER);
+ private static final SqlOperator OPERATOR = new SqlSpecialOperator("CREATE ZONE", SqlKind.OTHER_DDL);
/** Creates a SqlCreateZone. */
public IgniteSqlCreateZone(
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/sql/IgniteSqlDropZone.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/sql/IgniteSqlDropZone.java
index 2df1fda7a2..c4573e9df5 100644
--- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/sql/IgniteSqlDropZone.java
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/sql/IgniteSqlDropZone.java
@@ -37,7 +37,7 @@ public class IgniteSqlDropZone extends SqlDrop {
private final SqlIdentifier name;
/** Sql operator. */
- private static final SqlOperator OPERATOR = new SqlSpecialOperator("DROP ZONE", SqlKind.OTHER);
+ private static final SqlOperator OPERATOR = new SqlSpecialOperator("DROP ZONE", SqlKind.OTHER_DDL);
/** Constructor. */
public IgniteSqlDropZone(SqlParserPos pos, boolean ifExists, SqlIdentifier name) {
diff --git a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/StopCalciteModuleTest.java b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/StopCalciteModuleTest.java
index 3cec811cb1..b766eb6039 100644
--- a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/StopCalciteModuleTest.java
+++ b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/StopCalciteModuleTest.java
@@ -44,6 +44,7 @@ import java.util.concurrent.Flow;
import java.util.function.Consumer;
import java.util.function.Function;
import org.apache.ignite.configuration.ConfigurationValue;
+import org.apache.ignite.internal.distributionzones.DistributionZoneManager;
import org.apache.ignite.internal.hlc.HybridClock;
import org.apache.ignite.internal.index.IndexManager;
import org.apache.ignite.internal.logger.IgniteLogger;
@@ -117,6 +118,9 @@ public class StopCalciteModuleTest {
@Mock
private TxManager txManager;
+ @Mock
+ private DistributionZoneManager distributionZoneManager;
+
@Mock
private TopologyService topologySrvc;
@@ -211,6 +215,7 @@ public class StopCalciteModuleTest {
schemaManager,
dataStorageManager,
txManager,
+ distributionZoneManager,
Map::of,
clock
);
diff --git a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/MockedStructuresTest.java b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/MockedStructuresTest.java
index 49906280a7..fc0af30136 100644
--- a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/MockedStructuresTest.java
+++ b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/MockedStructuresTest.java
@@ -48,6 +48,7 @@ import org.apache.ignite.internal.configuration.notifications.ConfigurationStora
import org.apache.ignite.internal.configuration.testframework.ConfigurationExtension;
import org.apache.ignite.internal.configuration.testframework.InjectConfiguration;
import org.apache.ignite.internal.configuration.testframework.InjectRevisionListenerHolder;
+import org.apache.ignite.internal.distributionzones.DistributionZoneManager;
import org.apache.ignite.internal.hlc.HybridClock;
import org.apache.ignite.internal.index.IndexManager;
import org.apache.ignite.internal.metastorage.MetaStorageManager;
@@ -167,6 +168,9 @@ public class MockedStructuresTest extends IgniteAbstractTest {
@Mock
private ConfigurationRegistry configRegistry;
+ @Mock
+ private DistributionZoneManager distributionZoneManager;
+
DataStorageManager dataStorageManager;
SchemaManager schemaManager;
@@ -244,6 +248,7 @@ public class MockedStructuresTest extends IgniteAbstractTest {
schemaManager,
dataStorageManager,
tm,
+ distributionZoneManager,
() -> dataStorageModules.collectSchemasFields(
List.of(
RocksDbDataStorageConfigurationSchema.class,
diff --git a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/ddl/DistributionZoneDdlCommandHandlerTest.java b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/ddl/DistributionZoneDdlCommandHandlerTest.java
new file mode 100644
index 0000000000..3d91c33de4
--- /dev/null
+++ b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/ddl/DistributionZoneDdlCommandHandlerTest.java
@@ -0,0 +1,144 @@
+/*
+ * 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.sql.engine.exec.ddl;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.equalTo;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.atomic.AtomicReference;
+import org.apache.ignite.internal.distributionzones.DistributionZoneConfigurationParameters;
+import org.apache.ignite.internal.distributionzones.DistributionZoneManager;
+import org.apache.ignite.internal.index.IndexManager;
+import org.apache.ignite.internal.sql.engine.prepare.ddl.CreateZoneCommand;
+import org.apache.ignite.internal.sql.engine.prepare.ddl.DdlCommand;
+import org.apache.ignite.internal.sql.engine.prepare.ddl.DropZoneCommand;
+import org.apache.ignite.internal.storage.DataStorageManager;
+import org.apache.ignite.internal.table.distributed.TableManager;
+import org.apache.ignite.internal.testframework.IgniteAbstractTest;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.mockito.junit.jupiter.MockitoSettings;
+import org.mockito.quality.Strictness;
+import org.mockito.stubbing.Answer;
+
+/**
+ * Tests distribution zone commands handling.
+ */
+@ExtendWith(MockitoExtension.class)
+@MockitoSettings(strictness = Strictness.LENIENT)
+public class DistributionZoneDdlCommandHandlerTest extends IgniteAbstractTest {
+ /** Holder of the result of the invoked method. */
+ private final AtomicReference<Object> invocationResultHolder = new AtomicReference<>();
+
+ @Mock
+ private TableManager tableManager;
+
+ @Mock
+ private IndexManager indexManager;
+
+ @Mock
+ private DataStorageManager dataStorageManager;
+
+ /** DDL commands handler. */
+ private DdlCommandHandler commandHandler;
+
+ /** Inner initialisation. */
+ @BeforeEach
+ void before() {
+ DistributionZoneManager distributionZoneManager = Mockito.mock(DistributionZoneManager.class,
+ (Answer<CompletableFuture<Void>>) invocationOnMock -> {
+ invocationResultHolder.set(invocationOnMock.getArgument(0));
+
+ return CompletableFuture.completedFuture(null);
+ });
+
+ commandHandler = new DdlCommandHandler(distributionZoneManager, tableManager, indexManager, dataStorageManager);
+ }
+
+
+ @Test
+ public void testCreateZone() {
+ CreateZoneCommand cmd = new CreateZoneCommand();
+ cmd.zoneName("test_zone");
+
+ DistributionZoneConfigurationParameters params = invokeHandler(cmd);
+
+ assertNotNull(params);
+ assertThat(params.name(), equalTo(cmd.zoneName()));
+ }
+
+ @Test
+ public void testCreateZoneOptions() {
+ String name = "test_zone";
+ int autoAdjust = 1;
+ int autoAdjustScaleUp = 2;
+ int autoAdjustScaleDown = 3;
+
+ // Invalid options combination.
+ CreateZoneCommand cmdInvalidOptions = new CreateZoneCommand();
+ cmdInvalidOptions.zoneName(name);
+ cmdInvalidOptions.dataNodesAutoAdjust(autoAdjust);
+ cmdInvalidOptions.dataNodesAutoAdjustScaleUp(autoAdjustScaleUp);
+ cmdInvalidOptions.dataNodesAutoAdjustScaleDown(autoAdjustScaleDown);
+
+ assertThrows(IllegalArgumentException.class, () -> invokeHandler(cmdInvalidOptions));
+
+ // Valid options combination.
+ CreateZoneCommand cmdValidArguments1 = new CreateZoneCommand();
+ cmdValidArguments1.zoneName(name);
+ cmdValidArguments1.dataNodesAutoAdjust(autoAdjust);
+
+ DistributionZoneConfigurationParameters params = invokeHandler(cmdValidArguments1);
+
+ assertNotNull(params);
+ assertThat(params.dataNodesAutoAdjust(), equalTo(autoAdjust));
+
+ // Another valid options combination.
+ CreateZoneCommand cmdValidArguments2 = new CreateZoneCommand();
+ cmdValidArguments2.zoneName(name);
+ cmdValidArguments2.dataNodesAutoAdjustScaleUp(autoAdjustScaleUp);
+ cmdValidArguments2.dataNodesAutoAdjustScaleDown(autoAdjustScaleDown);
+
+ params = invokeHandler(cmdValidArguments2);
+
+ assertThat(params.dataNodesAutoAdjustScaleUp(), equalTo(autoAdjustScaleUp));
+ assertThat(params.dataNodesAutoAdjustScaleDown(), equalTo(autoAdjustScaleDown));
+ }
+
+ @Test
+ public void testDropZone() {
+ DropZoneCommand cmd = new DropZoneCommand();
+ cmd.zoneName("test_zone");
+
+ String name = invokeHandler(cmd);
+ assertThat(name, equalTo(cmd.zoneName()));
+ }
+
+ private <T> T invokeHandler(DdlCommand cmd) {
+ commandHandler.handle(cmd);
+
+ return (T) invocationResultHolder.get();
+ }
+}
diff --git a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/prepare/ddl/AbstractDdlSqlToCommandConverterTest.java b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/prepare/ddl/AbstractDdlSqlToCommandConverterTest.java
new file mode 100644
index 0000000000..3943e897ff
--- /dev/null
+++ b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/prepare/ddl/AbstractDdlSqlToCommandConverterTest.java
@@ -0,0 +1,66 @@
+/*
+ * 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.sql.engine.prepare.ddl;
+
+import static org.apache.calcite.tools.Frameworks.newConfigBuilder;
+import static org.apache.ignite.internal.sql.engine.util.Commons.FRAMEWORK_CONFIG;
+
+import java.util.Map;
+import org.apache.calcite.sql.SqlNode;
+import org.apache.calcite.sql.parser.SqlParseException;
+import org.apache.calcite.sql.parser.SqlParser;
+import org.apache.calcite.tools.Frameworks;
+import org.apache.ignite.internal.generated.query.calcite.sql.IgniteSqlParserImpl;
+import org.apache.ignite.internal.sql.engine.prepare.PlanningContext;
+import org.apache.ignite.internal.sql.engine.schema.IgniteSchema;
+import org.apache.ignite.internal.sql.engine.util.BaseQueryContext;
+import org.apache.ignite.internal.testframework.BaseIgniteAbstractTest;
+
+/**
+ * Common methods for {@link DdlSqlToCommandConverter} testing.
+ */
+class AbstractDdlSqlToCommandConverterTest extends BaseIgniteAbstractTest {
+ /** DDL SQL to command converter. */
+ DdlSqlToCommandConverter converter = new DdlSqlToCommandConverter(Map.of(), () -> "default");
+
+ /**
+ * Parses a given statement and returns a resulting AST.
+ *
+ * @param stmt Statement to parse.
+ * @return An AST.
+ */
+ static SqlNode parse(String stmt) throws SqlParseException {
+ SqlParser parser = SqlParser.create(stmt, SqlParser.config().withParserFactory(IgniteSqlParserImpl.FACTORY));
+
+ return parser.parseStmt();
+ }
+
+ static PlanningContext createContext() {
+ var schemaName = "PUBLIC";
+ var schema = Frameworks.createRootSchema(false).add(schemaName, new IgniteSchema(schemaName));
+
+ return PlanningContext.builder()
+ .parentContext(BaseQueryContext.builder()
+ .frameworkConfig(newConfigBuilder(FRAMEWORK_CONFIG)
+ .defaultSchema(schema)
+ .build())
+ .build())
+ .query("")
+ .build();
+ }
+}
diff --git a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/prepare/ddl/DdlSqlToCommandConverterTest.java b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/prepare/ddl/DdlSqlToCommandConverterTest.java
index d8528a8cd0..4978465b89 100644
--- a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/prepare/ddl/DdlSqlToCommandConverterTest.java
+++ b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/prepare/ddl/DdlSqlToCommandConverterTest.java
@@ -17,11 +17,8 @@
package org.apache.ignite.internal.sql.engine.prepare.ddl;
-import static org.apache.calcite.tools.Frameworks.newConfigBuilder;
import static org.apache.ignite.internal.sql.engine.prepare.ddl.DdlSqlToCommandConverter.checkDuplicates;
import static org.apache.ignite.internal.sql.engine.prepare.ddl.DdlSqlToCommandConverter.collectDataStorageNames;
-import static org.apache.ignite.internal.sql.engine.prepare.ddl.DdlSqlToCommandConverter.collectTableOptionInfos;
-import static org.apache.ignite.internal.sql.engine.util.Commons.FRAMEWORK_CONFIG;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.allOf;
@@ -37,19 +34,11 @@ import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import org.apache.calcite.sql.SqlDdl;
-import org.apache.calcite.sql.SqlNode;
import org.apache.calcite.sql.parser.SqlParseException;
-import org.apache.calcite.sql.parser.SqlParser;
import org.apache.calcite.sql.type.SqlTypeName;
-import org.apache.calcite.tools.Frameworks;
-import org.apache.ignite.internal.generated.query.calcite.sql.IgniteSqlParserImpl;
-import org.apache.ignite.internal.sql.engine.prepare.PlanningContext;
import org.apache.ignite.internal.sql.engine.prepare.ddl.DefaultValueDefinition.FunctionCall;
import org.apache.ignite.internal.sql.engine.prepare.ddl.DefaultValueDefinition.Type;
-import org.apache.ignite.internal.sql.engine.schema.IgniteSchema;
-import org.apache.ignite.internal.sql.engine.util.BaseQueryContext;
import org.apache.ignite.internal.sql.engine.util.Commons;
-import org.apache.ignite.internal.testframework.BaseIgniteAbstractTest;
import org.apache.ignite.internal.testframework.IgniteTestUtils;
import org.apache.ignite.internal.testframework.WithSystemProperty;
import org.apache.ignite.lang.IgniteException;
@@ -62,7 +51,7 @@ import org.junit.jupiter.api.Test;
/**
* For {@link DdlSqlToCommandConverter} testing.
*/
-public class DdlSqlToCommandConverterTest extends BaseIgniteAbstractTest {
+public class DdlSqlToCommandConverterTest extends AbstractDdlSqlToCommandConverterTest {
@AfterAll
public static void resetStaticState() {
IgniteTestUtils.setFieldValue(Commons.class, "implicitPkEnabled", null);
@@ -96,58 +85,22 @@ public class DdlSqlToCommandConverterTest extends BaseIgniteAbstractTest {
}
@Test
- void testCollectTableOptionInfos() {
- assertThat(collectTableOptionInfos(new TableOptionInfo[0]), equalTo(Map.of()));
-
- TableOptionInfo<?> replicas = tableOptionInfo("replicas");
-
- assertThat(
- collectTableOptionInfos(replicas),
- equalTo(Map.of("REPLICAS", replicas))
- );
-
- replicas = tableOptionInfo("REPLICAS");
-
- assertThat(
- collectTableOptionInfos(replicas),
- equalTo(Map.of("REPLICAS", replicas))
- );
-
- replicas = tableOptionInfo("replicas");
- TableOptionInfo<?> partitions = tableOptionInfo("partitions");
-
- assertThat(
- collectTableOptionInfos(replicas, partitions),
- equalTo(Map.of("REPLICAS", replicas, "PARTITIONS", partitions))
- );
-
- TableOptionInfo<?> replicas0 = tableOptionInfo("replicas");
- TableOptionInfo<?> replicas1 = tableOptionInfo("REPLICAS");
-
- IllegalStateException exception = assertThrows(
- IllegalStateException.class,
- () -> collectTableOptionInfos(replicas0, replicas1)
- );
-
- assertThat(exception.getMessage(), startsWith("Duplicate key"));
- }
-
- @Test
- void testCheckPositiveNumber() {
+ void testCheckDuplicates() {
IllegalStateException exception = assertThrows(
IllegalStateException.class,
() -> checkDuplicates(
- collectTableOptionInfos(tableOptionInfo("replicas")),
- collectTableOptionInfos(tableOptionInfo("replicas"))
+ Set.of("replicas", "affinity"),
+ Set.of("partitions", "replicas")
)
);
- assertThat(exception.getMessage(), startsWith("Duplicate id"));
+ assertThat(exception.getMessage(), startsWith("Duplicate id: replicas"));
assertDoesNotThrow(() -> checkDuplicates(
- collectTableOptionInfos(tableOptionInfo("replicas")),
- collectTableOptionInfos(tableOptionInfo("partitions"))
- ));
+ Set.of("replicas", "affinity"),
+ Set.of("replicas0", "affinity0")
+ )
+ );
}
@Test
@@ -160,7 +113,7 @@ public class DdlSqlToCommandConverterTest extends BaseIgniteAbstractTest {
var ex = assertThrows(
IgniteException.class,
- () -> new DdlSqlToCommandConverter(Map.of(), () -> "default").convert((SqlDdl) node, createContext())
+ () -> converter.convert((SqlDdl) node, createContext())
);
assertThat(ex.getMessage(), containsString("Table without PRIMARY KEY is not supported"));
@@ -177,7 +130,7 @@ public class DdlSqlToCommandConverterTest extends BaseIgniteAbstractTest {
var ex = assertThrows(
IgniteException.class,
- () -> new DdlSqlToCommandConverter(Map.of(), () -> "default").convert((SqlDdl) node, createContext())
+ () -> converter.convert((SqlDdl) node, createContext())
);
assertThat(ex.getMessage(), containsString("Table without PRIMARY KEY is not supported"));
@@ -192,7 +145,7 @@ public class DdlSqlToCommandConverterTest extends BaseIgniteAbstractTest {
assertThat(node, instanceOf(SqlDdl.class));
- var cmd = new DdlSqlToCommandConverter(Map.of(), () -> "default").convert((SqlDdl) node, createContext());
+ var cmd = converter.convert((SqlDdl) node, createContext());
assertThat(cmd, Matchers.instanceOf(CreateTableCommand.class));
@@ -224,7 +177,7 @@ public class DdlSqlToCommandConverterTest extends BaseIgniteAbstractTest {
assertThat(node, instanceOf(SqlDdl.class));
- var cmd = new DdlSqlToCommandConverter(Map.of(), () -> "default").convert((SqlDdl) node, createContext());
+ var cmd = converter.convert((SqlDdl) node, createContext());
assertThat(cmd, Matchers.instanceOf(CreateTableCommand.class));
@@ -246,11 +199,6 @@ public class DdlSqlToCommandConverterTest extends BaseIgniteAbstractTest {
);
}
- private TableOptionInfo tableOptionInfo(String name) {
- return new TableOptionInfo<>(name, Object.class, null, (createTableCommand, o) -> {
- });
- }
-
private static Matcher<ColumnDefinition> columnThat(String description, Function<ColumnDefinition, Boolean> checker) {
return new CustomMatcher<>(description) {
@Override
@@ -259,30 +207,4 @@ public class DdlSqlToCommandConverterTest extends BaseIgniteAbstractTest {
}
};
}
-
- /**
- * Parses a given statement and returns a resulting AST.
- *
- * @param stmt Statement to parse.
- * @return An AST.
- */
- private static SqlNode parse(String stmt) throws SqlParseException {
- SqlParser parser = SqlParser.create(stmt, SqlParser.config().withParserFactory(IgniteSqlParserImpl.FACTORY));
-
- return parser.parseStmt();
- }
-
- private static PlanningContext createContext() {
- var schemaName = "PUBLIC";
- var schema = Frameworks.createRootSchema(false).add(schemaName, new IgniteSchema(schemaName));
-
- return PlanningContext.builder()
- .parentContext(BaseQueryContext.builder()
- .frameworkConfig(newConfigBuilder(FRAMEWORK_CONFIG)
- .defaultSchema(schema)
- .build())
- .build())
- .query("")
- .build();
- }
}
diff --git a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/prepare/ddl/DistributionZoneSqlToCommandConverterTest.java b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/prepare/ddl/DistributionZoneSqlToCommandConverterTest.java
new file mode 100644
index 0000000000..95f0ec23c6
--- /dev/null
+++ b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/prepare/ddl/DistributionZoneSqlToCommandConverterTest.java
@@ -0,0 +1,124 @@
+/*
+ * 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.sql.engine.prepare.ddl;
+
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.equalTo;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import org.apache.calcite.sql.SqlDdl;
+import org.apache.calcite.sql.SqlNode;
+import org.apache.calcite.sql.parser.SqlParseException;
+import org.apache.ignite.lang.ErrorGroups.Sql;
+import org.apache.ignite.lang.IgniteException;
+import org.hamcrest.Matchers;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Tests the conversion of a sql zone definition to a command.
+ */
+public class DistributionZoneSqlToCommandConverterTest extends AbstractDdlSqlToCommandConverterTest {
+ @Test
+ public void testCreateZone() throws SqlParseException {
+ SqlNode node = parse("CREATE ZONE test");
+
+ assertThat(node, instanceOf(SqlDdl.class));
+
+ DdlCommand cmd = converter.convert((SqlDdl) node, createContext());
+
+ assertThat(cmd, Matchers.instanceOf(CreateZoneCommand.class));
+
+ CreateZoneCommand zoneCmd = (CreateZoneCommand) cmd;
+
+ assertThat(zoneCmd.zoneName(), equalTo("TEST"));
+ }
+
+ @Test
+ public void testCreateZoneWithOptions() throws SqlParseException {
+ SqlNode node = parse("CREATE ZONE test with "
+ + "partitions=2, "
+ + "replicas=3, "
+ + "affinity_function='rendezvous', "
+ + "data_nodes_filter='\"attr1\" && \"attr2\"', "
+ + "data_nodes_auto_adjust_scale_up=100, "
+ + "data_nodes_auto_adjust_scale_down=200, "
+ + "data_nodes_auto_adjust=300");
+
+ assertThat(node, instanceOf(SqlDdl.class));
+
+ DdlCommand cmd = converter.convert((SqlDdl) node, createContext());
+
+ CreateZoneCommand createZone = (CreateZoneCommand) cmd;
+
+ assertThat(createZone.partitions(), equalTo(2));
+ assertThat(createZone.replicas(), equalTo(3));
+ assertThat(createZone.affinity(), equalTo("rendezvous"));
+ assertThat(createZone.nodeFilter(), equalTo("\"attr1\" && \"attr2\""));
+ assertThat(createZone.dataNodesAutoAdjustScaleUp(), equalTo(100));
+ assertThat(createZone.dataNodesAutoAdjustScaleDown(), equalTo(200));
+ assertThat(createZone.dataNodesAutoAdjust(), equalTo(300));
+
+ // Check option validation.
+ IgniteException ex = assertThrows(
+ IgniteException.class,
+ () -> converter.convert((SqlDdl) parse("CREATE ZONE test with partitions=-1"), createContext())
+ );
+
+ assertThat(ex.code(), equalTo(Sql.QUERY_VALIDATION_ERR));
+ assertThat(ex.getMessage(), containsString("Zone option validation failed [option=PARTITIONS"));
+
+ ex = assertThrows(
+ IgniteException.class,
+ () -> converter.convert((SqlDdl) parse("CREATE ZONE test with replicas=-1"), createContext())
+ );
+
+ assertThat(ex.code(), equalTo(Sql.QUERY_VALIDATION_ERR));
+ assertThat(ex.getMessage(), containsString("Zone option validation failed [option=REPLICAS"));
+ }
+
+ @Test
+ public void testCreateZoneWithDuplicateOptions() throws SqlParseException {
+ SqlNode node = parse("CREATE ZONE test with partitions=2, replicas=0, PARTITIONS=1");
+
+ assertThat(node, instanceOf(SqlDdl.class));
+
+ IgniteException ex = assertThrows(
+ IgniteException.class,
+ () -> converter.convert((SqlDdl) node, createContext())
+ );
+
+ assertThat(ex.code(), equalTo(Sql.QUERY_VALIDATION_ERR));
+ }
+
+ @Test
+ public void testDropZone() throws SqlParseException {
+ SqlNode node = parse("DROP ZONE test");
+
+ assertThat(node, instanceOf(SqlDdl.class));
+
+ DdlCommand cmd = converter.convert((SqlDdl) node, createContext());
+
+ assertThat(cmd, Matchers.instanceOf(DropZoneCommand.class));
+
+ DropZoneCommand zoneCmd = (DropZoneCommand) cmd;
+
+ assertThat(zoneCmd.zoneName(), equalTo("TEST"));
+ }
+}
diff --git a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/sql/SqlDdlZoneParserTest.java b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/sql/DistributionZoneSqlDdlParserTest.java
similarity index 99%
rename from modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/sql/SqlDdlZoneParserTest.java
rename to modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/sql/DistributionZoneSqlDdlParserTest.java
index 442dcce2fa..737e3e8c28 100644
--- a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/sql/SqlDdlZoneParserTest.java
+++ b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/sql/DistributionZoneSqlDdlParserTest.java
@@ -40,7 +40,7 @@ import org.junit.jupiter.api.Test;
/**
* Test suite to verify parsing of the DDL "ZONE" commands.
*/
-public class SqlDdlZoneParserTest extends AbstractDdlParserTest {
+public class DistributionZoneSqlDdlParserTest extends AbstractDdlParserTest {
/**
* Parse simple CREATE ZONE statement.
*/