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 b9880a28a0 IGNITE-18156 Sql. Extend SQL grammar with CREATE/DROP ZONE
statement (#1372)
b9880a28a0 is described below
commit b9880a28a0f13f826ae67de97dfe2c23897d74c3
Author: Pavel Pereslegin <[email protected]>
AuthorDate: Fri Nov 25 16:57:38 2022 +0300
IGNITE-18156 Sql. Extend SQL grammar with CREATE/DROP ZONE statement (#1372)
---
modules/sql-engine/src/main/codegen/config.fmpp | 24 ++-
.../src/main/codegen/includes/parserImpls.ftl | 108 +++++++++++
.../sql/engine/sql/IgniteSqlCreateZone.java | 102 ++++++++++
.../sql/engine/sql/IgniteSqlCreateZoneOption.java | 119 ++++++++++++
.../engine/sql/IgniteSqlCreateZoneOptionEnum.java | 44 +++++
.../internal/sql/engine/sql/IgniteSqlDropZone.java | 72 +++++++
.../sql/engine/sql/AbstractDdlParserTest.java | 61 ++++++
.../internal/sql/engine/sql/SqlDdlParserTest.java | 37 +---
.../sql/engine/sql/SqlDdlZoneParserTest.java | 208 +++++++++++++++++++++
9 files changed, 738 insertions(+), 37 deletions(-)
diff --git a/modules/sql-engine/src/main/codegen/config.fmpp
b/modules/sql-engine/src/main/codegen/config.fmpp
index 658ec120d3..bbd0330ded 100644
--- a/modules/sql-engine/src/main/codegen/config.fmpp
+++ b/modules/sql-engine/src/main/codegen/config.fmpp
@@ -36,7 +36,11 @@ data: {
"org.apache.ignite.internal.sql.engine.sql.IgniteSqlCreateTable",
"org.apache.ignite.internal.sql.engine.sql.IgniteSqlCreateIndex",
"org.apache.ignite.internal.sql.engine.sql.IgniteSqlCreateTableOption",
+ "org.apache.ignite.internal.sql.engine.sql.IgniteSqlCreateZone",
+ "org.apache.ignite.internal.sql.engine.sql.IgniteSqlCreateZoneOption",
+
"org.apache.ignite.internal.sql.engine.sql.IgniteSqlCreateZoneOptionEnum",
"org.apache.ignite.internal.sql.engine.sql.IgniteSqlDropIndex",
+ "org.apache.ignite.internal.sql.engine.sql.IgniteSqlDropZone",
"org.apache.ignite.internal.sql.engine.sql.IgniteSqlIntervalTypeNameSpec",
"org.apache.ignite.internal.sql.engine.sql.IgniteSqlIndexType",
"org.apache.calcite.sql.ddl.SqlDdlNodes",
@@ -53,6 +57,13 @@ data: {
# "KEY_TYPE" // already presented in Calcite
"TREE"
"HASH"
+ "PARTITIONS"
+ "REPLICAS"
+ "AFFINITY_FUNCTION"
+ "DATA_NODES_FILTER"
+ "DATA_NODES_AUTO_ADJUST"
+ "DATA_NODES_AUTO_ADJUST_SCALE_UP"
+ "DATA_NODES_AUTO_ADJUST_SCALE_DOWN"
]
# List of non-reserved keywords to add;
@@ -546,6 +557,13 @@ data: {
"WRITE"
"YEAR"
"ZONE"
+ "PARTITIONS"
+ "REPLICAS"
+ "AFFINITY_FUNCTION"
+ "DATA_NODES_FILTER"
+ "DATA_NODES_AUTO_ADJUST"
+ "DATA_NODES_AUTO_ADJUST_SCALE_UP"
+ "DATA_NODES_AUTO_ADJUST_SCALE_DOWN"
]
# List of non-reserved keywords to add;
@@ -584,7 +602,8 @@ data: {
# Example: "SqlCreateForeignSchema".
createStatementParserMethods: [
"SqlCreateTable",
- "SqlCreateIndex"
+ "SqlCreateIndex",
+ "SqlCreateZone"
]
# List of methods for parsing extensions to "DROP" calls.
@@ -592,7 +611,8 @@ data: {
# Example: "SqlDropSchema".
dropStatementParserMethods: [
"SqlDropTable",
- "SqlDropIndex"
+ "SqlDropIndex",
+ "SqlDropZone"
]
# List of methods for parsing extensions to "DROP" calls.
diff --git a/modules/sql-engine/src/main/codegen/includes/parserImpls.ftl
b/modules/sql-engine/src/main/codegen/includes/parserImpls.ftl
index f3ef9c143a..f176a33c82 100644
--- a/modules/sql-engine/src/main/codegen/includes/parserImpls.ftl
+++ b/modules/sql-engine/src/main/codegen/includes/parserImpls.ftl
@@ -424,3 +424,111 @@ SqlNode SqlAlterTable() :
< NEGATE: "!" >
| < TILDE: "~" >
}
+
+SqlCreate SqlCreateZone(Span s, boolean replace) :
+{
+ final boolean ifNotExists;
+ final SqlIdentifier id;
+ SqlNodeList optionList = null;
+}
+{
+ <ZONE>
+ ifNotExists = IfNotExistsOpt()
+ id = CompoundIdentifier()
+ [
+ <WITH> { s.add(this); } optionList = CreateZoneOptionList()
+ ]
+ {
+ return new IgniteSqlCreateZone(s.end(this), ifNotExists, id,
optionList);
+ }
+}
+
+SqlNodeList CreateZoneOptionList() :
+{
+ List<SqlNode> list = new ArrayList<SqlNode>();
+ final Span s = Span.of();
+}
+{
+ CreateZoneOption(list)
+ (
+ <COMMA> { s.add(this); } CreateZoneOption(list)
+ )*
+ {
+ return new SqlNodeList(list, s.end(this));
+ }
+}
+
+void CreateZoneOption(List<SqlNode> list) :
+{
+ final Span s;
+ final SqlLiteral key;
+ final SqlNode val;
+}
+{
+ (
+ (
+ key = CreateNumericZoneOptionKey() { s = span(); }
+ <EQ>
+ val = NumericLiteral()
+ )
+ |
+ (
+ key = CreateStringZoneOptionKey() { s = span(); }
+ <EQ>
+ val = StringLiteral()
+ )
+ )
+ {
+ list.add(new IgniteSqlCreateZoneOption(key, val, s.end(this)));
+ }
+}
+
+SqlLiteral CreateNumericZoneOptionKey() :
+{
+}
+{
+ <PARTITIONS>
+ {
+ return
SqlLiteral.createSymbol(IgniteSqlCreateZoneOptionEnum.PARTITIONS, getPos());
+ }
+|
+ <REPLICAS>
+ {
+ return SqlLiteral.createSymbol(IgniteSqlCreateZoneOptionEnum.REPLICAS,
getPos());
+ }
+|
+ <DATA_NODES_AUTO_ADJUST>
+ {
+ return
SqlLiteral.createSymbol(IgniteSqlCreateZoneOptionEnum.DATA_NODES_AUTO_ADJUST,
getPos());
+ }
+|
+ <DATA_NODES_AUTO_ADJUST_SCALE_UP>
+ {
+ return
SqlLiteral.createSymbol(IgniteSqlCreateZoneOptionEnum.DATA_NODES_AUTO_ADJUST_SCALE_UP,
getPos());
+ }
+|
+ <DATA_NODES_AUTO_ADJUST_SCALE_DOWN>
+ {
+ return
SqlLiteral.createSymbol(IgniteSqlCreateZoneOptionEnum.DATA_NODES_AUTO_ADJUST_SCALE_DOWN,
getPos());
+ }
+}
+
+SqlLiteral CreateStringZoneOptionKey() :
+{
+}
+{
+ <AFFINITY_FUNCTION> { return
SqlLiteral.createSymbol(IgniteSqlCreateZoneOptionEnum.AFFINITY_FUNCTION,
getPos()); }
+|
+ <DATA_NODES_FILTER> { return
SqlLiteral.createSymbol(IgniteSqlCreateZoneOptionEnum.DATA_NODES_FILTER,
getPos()); }
+}
+
+SqlDrop SqlDropZone(Span s, boolean replace) :
+{
+ final boolean ifExists;
+ final SqlIdentifier zoneId;
+}
+{
+ <ZONE> ifExists = IfExistsOpt() zoneId = CompoundIdentifier() {
+ return new IgniteSqlDropZone(s.end(this), ifExists, zoneId);
+ }
+}
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
new file mode 100644
index 0000000000..56e308e595
--- /dev/null
+++
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/sql/IgniteSqlCreateZone.java
@@ -0,0 +1,102 @@
+/*
+ * 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.sql;
+
+import java.util.List;
+import java.util.Objects;
+import org.apache.calcite.sql.SqlCreate;
+import org.apache.calcite.sql.SqlIdentifier;
+import org.apache.calcite.sql.SqlKind;
+import org.apache.calcite.sql.SqlNode;
+import org.apache.calcite.sql.SqlNodeList;
+import org.apache.calcite.sql.SqlOperator;
+import org.apache.calcite.sql.SqlSpecialOperator;
+import org.apache.calcite.sql.SqlWriter;
+import org.apache.calcite.sql.parser.SqlParserPos;
+import org.apache.calcite.util.ImmutableNullableList;
+import org.checkerframework.checker.nullness.qual.Nullable;
+
+/**
+ * Parse tree for {@code CREATE ZONE} statement with Ignite specific features.
+ */
+public class IgniteSqlCreateZone extends SqlCreate {
+ private final SqlIdentifier name;
+
+ private final @Nullable SqlNodeList createOptionList;
+
+ private static final SqlOperator OPERATOR = new SqlSpecialOperator("CREATE
ZONE", SqlKind.OTHER);
+
+ /** Creates a SqlCreateZone. */
+ public IgniteSqlCreateZone(
+ SqlParserPos pos,
+ boolean ifNotExists,
+ SqlIdentifier name,
+ @Nullable SqlNodeList createOptionList
+ ) {
+ super(OPERATOR, pos, false, ifNotExists);
+
+ this.name = Objects.requireNonNull(name, "name");
+ this.createOptionList = createOptionList;
+ }
+
+ /** {@inheritDoc} */
+ @SuppressWarnings("nullness")
+ @Override
+ public List<SqlNode> getOperandList() {
+ return ImmutableNullableList.of(name, createOptionList);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void unparse(SqlWriter writer, int leftPrec, int rightPrec) {
+ writer.keyword("CREATE");
+ writer.keyword("ZONE");
+ if (ifNotExists) {
+ writer.keyword("IF NOT EXISTS");
+ }
+
+ name.unparse(writer, leftPrec, rightPrec);
+
+ if (createOptionList != null) {
+ writer.keyword("WITH");
+
+ createOptionList.unparse(writer, 0, 0);
+ }
+ }
+
+ /**
+ * Get name of the distribution zone.
+ */
+ public SqlIdentifier name() {
+ return name;
+ }
+
+ /**
+ * Get list of the specified options to create distribution zone with.
+ */
+ public SqlNodeList createOptionList() {
+ return createOptionList;
+ }
+
+ /**
+ * Get whether the IF NOT EXISTS is specified.
+ */
+ public boolean ifNotExists() {
+ return ifNotExists;
+ }
+}
diff --git
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/sql/IgniteSqlCreateZoneOption.java
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/sql/IgniteSqlCreateZoneOption.java
new file mode 100644
index 0000000000..4f40784864
--- /dev/null
+++
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/sql/IgniteSqlCreateZoneOption.java
@@ -0,0 +1,119 @@
+/*
+ * 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.sql;
+
+import java.util.List;
+import org.apache.calcite.sql.SqlCall;
+import org.apache.calcite.sql.SqlKind;
+import org.apache.calcite.sql.SqlLiteral;
+import org.apache.calcite.sql.SqlNode;
+import org.apache.calcite.sql.SqlOperator;
+import org.apache.calcite.sql.SqlSpecialOperator;
+import org.apache.calcite.sql.SqlWriter;
+import org.apache.calcite.sql.parser.SqlParserPos;
+import org.apache.calcite.sql.util.SqlVisitor;
+import org.apache.calcite.sql.validate.SqlValidator;
+import org.apache.calcite.sql.validate.SqlValidatorScope;
+import org.apache.calcite.util.Litmus;
+
+/** An AST node representing option to create distribution zone with. */
+public class IgniteSqlCreateZoneOption extends SqlCall {
+ private static final SqlOperator OPERATOR =
+ new SqlSpecialOperator("ZoneOption", SqlKind.OTHER);
+
+ /** Option key. */
+ private final SqlLiteral key;
+
+ /** Option value. */
+ private final SqlNode value;
+
+ /** Creates {@link IgniteSqlCreateZoneOption}. */
+ public IgniteSqlCreateZoneOption(SqlLiteral key, SqlNode value,
SqlParserPos pos) {
+ super(pos);
+
+ this.key = key;
+ this.value = value;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public SqlOperator getOperator() {
+ return OPERATOR;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public List<SqlNode> getOperandList() {
+ return List.of(key, value);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public SqlNode clone(SqlParserPos pos) {
+ return new IgniteSqlCreateZoneOption(key, value, pos);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void unparse(SqlWriter writer, int leftPrec, int rightPrec) {
+ key.unparse(writer, leftPrec, rightPrec);
+ writer.keyword("=");
+ value.unparse(writer, leftPrec, rightPrec);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void validate(SqlValidator validator, SqlValidatorScope scope) {
+ throw new UnsupportedOperationException();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public <R> R accept(SqlVisitor<R> visitor) {
+ throw new UnsupportedOperationException();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean equalsDeep(SqlNode node, Litmus litmus) {
+ if (!(node instanceof IgniteSqlCreateZoneOption)) {
+ return litmus.fail("{} != {}", this, node);
+ }
+
+ IgniteSqlCreateZoneOption that = (IgniteSqlCreateZoneOption) node;
+ if (key != that.key) {
+ return litmus.fail("{} != {}", this, node);
+ }
+
+ return value.equalsDeep(that.value, litmus);
+ }
+
+ /**
+ * Get option's key.
+ */
+ public SqlLiteral key() {
+ return key;
+ }
+
+ /**
+ * Get option's value.
+ */
+ public SqlNode value() {
+ return value;
+ }
+}
diff --git
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/sql/IgniteSqlCreateZoneOptionEnum.java
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/sql/IgniteSqlCreateZoneOptionEnum.java
new file mode 100644
index 0000000000..04d231ce1e
--- /dev/null
+++
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/sql/IgniteSqlCreateZoneOptionEnum.java
@@ -0,0 +1,44 @@
+/*
+ * 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.sql;
+
+/**
+ * Enumerates the options for CREATE ZONE statement.
+ */
+public enum IgniteSqlCreateZoneOptionEnum {
+ /** Number of partitions. */
+ PARTITIONS,
+
+ /** Number of replicas. */
+ REPLICAS,
+
+ /** Affinity function name. */
+ AFFINITY_FUNCTION,
+
+ /** An expression to filter data nodes. */
+ DATA_NODES_FILTER,
+
+ /** Data nodes auto adjust timeout. */
+ DATA_NODES_AUTO_ADJUST,
+
+ /** Data nodes scale up auto adjust timeout. */
+ DATA_NODES_AUTO_ADJUST_SCALE_UP,
+
+ /** Data nodes scale down auto adjust timeout. */
+ DATA_NODES_AUTO_ADJUST_SCALE_DOWN
+}
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
new file mode 100644
index 0000000000..2df1fda7a2
--- /dev/null
+++
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/sql/IgniteSqlDropZone.java
@@ -0,0 +1,72 @@
+/*
+ * 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.sql;
+
+import java.util.List;
+import java.util.Objects;
+import org.apache.calcite.sql.SqlDrop;
+import org.apache.calcite.sql.SqlIdentifier;
+import org.apache.calcite.sql.SqlKind;
+import org.apache.calcite.sql.SqlNode;
+import org.apache.calcite.sql.SqlOperator;
+import org.apache.calcite.sql.SqlSpecialOperator;
+import org.apache.calcite.sql.SqlWriter;
+import org.apache.calcite.sql.parser.SqlParserPos;
+import org.apache.calcite.util.ImmutableNullableList;
+
+/**
+ * Parse tree for {@code DROP ZONE} statement.
+ */
+public class IgniteSqlDropZone extends SqlDrop {
+ /** Zone name. */
+ private final SqlIdentifier name;
+
+ /** Sql operator. */
+ private static final SqlOperator OPERATOR = new SqlSpecialOperator("DROP
ZONE", SqlKind.OTHER);
+
+ /** Constructor. */
+ public IgniteSqlDropZone(SqlParserPos pos, boolean ifExists, SqlIdentifier
name) {
+ super(OPERATOR, pos, ifExists);
+
+ this.name = Objects.requireNonNull(name, "zone name");
+ }
+
+ /** {@inheritDoc} */
+ @Override public List<SqlNode> getOperandList() {
+ return ImmutableNullableList.of(name);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void unparse(SqlWriter writer, int leftPrec, int
rightPrec) {
+ writer.keyword(getOperator().getName()); // "DROP ..."
+
+ if (ifExists) {
+ writer.keyword("IF EXISTS");
+ }
+
+ name.unparse(writer, leftPrec, rightPrec);
+ }
+
+ public SqlIdentifier name() {
+ return name;
+ }
+
+ public boolean ifExists() {
+ return ifExists;
+ }
+}
diff --git
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/sql/AbstractDdlParserTest.java
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/sql/AbstractDdlParserTest.java
new file mode 100644
index 0000000000..1570d46e39
--- /dev/null
+++
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/sql/AbstractDdlParserTest.java
@@ -0,0 +1,61 @@
+/*
+ * 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.sql;
+
+import java.util.function.Predicate;
+import org.apache.calcite.sql.SqlNode;
+import org.apache.calcite.sql.parser.SqlParseException;
+import org.apache.calcite.sql.parser.SqlParser;
+import
org.apache.ignite.internal.generated.query.calcite.sql.IgniteSqlParserImpl;
+import org.hamcrest.CustomMatcher;
+import org.hamcrest.Matcher;
+
+/**
+ * Common methods to verify parsing of the DDL command.
+ */
+public abstract class AbstractDdlParserTest {
+ /**
+ * Parses a given statement and returns a resulting AST.
+ *
+ * @param stmt Statement to parse.
+ * @return An AST.
+ */
+ protected SqlNode parse(String stmt) throws SqlParseException {
+ SqlParser parser = SqlParser.create(stmt,
SqlParser.config().withParserFactory(IgniteSqlParserImpl.FACTORY));
+
+ return parser.parseStmt();
+ }
+
+ /**
+ * Matcher to verify that an object of the expected type and matches the
given predicate.
+ *
+ * @param desc Description for this matcher.
+ * @param cls Expected class to verify the object is instance of.
+ * @param pred Addition check that would be applied to the object.
+ * @return {@code true} in case the object if instance of the given class
and matches the predicat.
+ */
+ protected <T> Matcher<T> ofTypeMatching(String desc, Class<T> cls,
Predicate<T> pred) {
+ return new CustomMatcher<T>(desc) {
+ /** {@inheritDoc} */
+ @Override
+ public boolean matches(Object item) {
+ return item != null && cls.isAssignableFrom(item.getClass())
&& pred.test((T) item);
+ }
+ };
+ }
+}
diff --git
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/sql/SqlDdlParserTest.java
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/sql/SqlDdlParserTest.java
index 34735a318f..569467d05f 100644
---
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/sql/SqlDdlParserTest.java
+++
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/sql/SqlDdlParserTest.java
@@ -32,7 +32,6 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
import java.util.List;
import java.util.Objects;
import java.util.Set;
-import java.util.function.Predicate;
import java.util.stream.Collectors;
import org.apache.calcite.sql.SqlBasicCall;
import org.apache.calcite.sql.SqlIdentifier;
@@ -42,9 +41,7 @@ import org.apache.calcite.sql.SqlNode;
import org.apache.calcite.sql.ddl.SqlColumnDeclaration;
import org.apache.calcite.sql.ddl.SqlKeyConstraint;
import org.apache.calcite.sql.parser.SqlParseException;
-import org.apache.calcite.sql.parser.SqlParser;
import org.apache.calcite.sql.pretty.SqlPrettyWriter;
-import
org.apache.ignite.internal.generated.query.calcite.sql.IgniteSqlParserImpl;
import org.hamcrest.CustomMatcher;
import org.hamcrest.Matcher;
import org.junit.jupiter.api.Test;
@@ -52,7 +49,7 @@ import org.junit.jupiter.api.Test;
/**
* Test suite to verify parsing of the DDL command.
*/
-public class SqlDdlParserTest {
+public class SqlDdlParserTest extends AbstractDdlParserTest {
/**
* Very simple case where only table name and a few columns are presented.
*/
@@ -544,18 +541,6 @@ public class SqlDdlParserTest {
return (IgniteSqlCreateTable) node;
}
- /**
- * 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();
- }
-
/**
* Matcher to verify name in the column declaration.
*
@@ -573,25 +558,7 @@ public class SqlDdlParserTest {
};
}
- /**
- * Matcher to verify that an object of the expected type and matches the
given predicate.
- *
- * @param desc Description for this matcher.
- * @param cls Expected class to verify the object is instance of.
- * @param pred Addition check that would be applied to the object.
- * @return {@code true} in case the object if instance of the given class
and matches the predicat.
- */
- private static <T> Matcher<T> ofTypeMatching(String desc, Class<T> cls,
Predicate<T> pred) {
- return new CustomMatcher<T>(desc) {
- /** {@inheritDoc} */
- @Override
- public boolean matches(Object item) {
- return item != null && cls.isAssignableFrom(item.getClass())
&& pred.test((T) item);
- }
- };
- }
-
- private static void assertThatOptionPresent(List<SqlNode> optionList,
String option, Object expVal) {
+ private void assertThatOptionPresent(List<SqlNode> optionList, String
option, Object expVal) {
assertThat(optionList, hasItem(ofTypeMatching(
option + "=" + expVal,
IgniteSqlCreateTableOption.class,
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/SqlDdlZoneParserTest.java
new file mode 100644
index 0000000000..442dcce2fa
--- /dev/null
+++
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/sql/SqlDdlZoneParserTest.java
@@ -0,0 +1,208 @@
+/*
+ * 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.sql;
+
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.equalTo;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+import org.apache.calcite.sql.SqlLiteral;
+import org.apache.calcite.sql.SqlNode;
+import org.apache.calcite.sql.parser.SqlParseException;
+import org.apache.calcite.sql.pretty.SqlPrettyWriter;
+import org.hamcrest.Matchers;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Test suite to verify parsing of the DDL "ZONE" commands.
+ */
+public class SqlDdlZoneParserTest extends AbstractDdlParserTest {
+ /**
+ * Parse simple CREATE ZONE statement.
+ */
+ @Test
+ public void createZoneNoOptions() throws SqlParseException {
+ // Simple name.
+ IgniteSqlCreateZone createZone = parseCreateZone("create zone
test_zone");
+
+ assertThat(createZone.name().names, is(List.of("TEST_ZONE")));
+ assertFalse(createZone.ifNotExists());
+ assertNull(createZone.createOptionList());
+
+ // Fully qualified name.
+ createZone = parseCreateZone("create zone public.test_zone");
+ assertThat(createZone.name().names, is(List.of("PUBLIC",
"TEST_ZONE")));
+
+ // Quoted identifier.
+ createZone = parseCreateZone("create zone \"public\".\"test_Zone\"");
+ assertThat(createZone.name().names, is(List.of("public",
"test_Zone")));
+
+ createZone = parseCreateZone("create zone \"public-test_Zone\"");
+ assertThat(createZone.name().names, is(List.of("public-test_Zone")));
+ }
+
+ /**
+ * Parse CREATE ZONE IF NOT EXISTS statement.
+ */
+ @Test
+ public void createZoneIfNotExists() throws SqlParseException {
+ IgniteSqlCreateZone createZone = parseCreateZone("create zone if not
exists test_zone");
+
+ assertTrue(createZone.ifNotExists());
+ assertNull(createZone.createOptionList());
+ }
+
+ /**
+ * Parse CREATE ZONE WITH ... statement.
+ */
+ @Test
+ public void createZoneWithOptions() throws SqlParseException {
+ IgniteSqlCreateZone createZone = parseCreateZone(
+ "create zone test_zone with "
+ + "replicas=2, "
+ + "partitions=3, "
+ + "data_nodes_filter='(\"US\" || \"EU\") && \"SSD\"', "
+ + "affinity_function='test_Affinity', "
+ + "data_nodes_auto_adjust=1, "
+ + "data_nodes_auto_adjust_scale_up=2, "
+ + "data_nodes_auto_adjust_scale_down=3"
+ );
+
+ assertNotNull(createZone.createOptionList());
+
+ List<SqlNode> optList = createZone.createOptionList().getList();
+
+ assertThatZoneOptionPresent(optList,
IgniteSqlCreateZoneOptionEnum.REPLICAS, 2);
+ assertThatZoneOptionPresent(optList,
IgniteSqlCreateZoneOptionEnum.PARTITIONS, 3);
+ assertThatZoneOptionPresent(optList,
IgniteSqlCreateZoneOptionEnum.AFFINITY_FUNCTION, "test_Affinity");
+ assertThatZoneOptionPresent(optList,
IgniteSqlCreateZoneOptionEnum.DATA_NODES_FILTER, "(\"US\" || \"EU\") &&
\"SSD\"");
+ assertThatZoneOptionPresent(optList,
IgniteSqlCreateZoneOptionEnum.DATA_NODES_AUTO_ADJUST, 1);
+
+ SqlPrettyWriter w = new SqlPrettyWriter();
+ createZone.unparse(w, 0, 0);
+
+ assertThat(w.toString(), equalTo("CREATE ZONE \"TEST_ZONE\" WITH "
+ + "REPLICAS = 2, "
+ + "PARTITIONS = 3, "
+ + "DATA_NODES_FILTER = '(\"US\" || \"EU\") && \"SSD\"', "
+ + "AFFINITY_FUNCTION = 'test_Affinity', "
+ + "DATA_NODES_AUTO_ADJUST = 1, "
+ + "DATA_NODES_AUTO_ADJUST_SCALE_UP = 2, "
+ + "DATA_NODES_AUTO_ADJUST_SCALE_DOWN = 3"));
+ }
+
+ /**
+ * Parse CREATE ZONE WITH unknown option.
+ */
+ @Test
+ public void createZoneWithInvalidOptions() {
+ // Unknown option.
+ assertThrows(SqlParseException.class, () -> parseCreateZone("create
zone test_zone with foo='bar'"));
+
+ // Invalid option type.
+ String query = "create zone test_zone with %s=%s";
+
+ List<String> numericOptNames = Arrays.asList("PARTITIONS", "REPLICAS",
"DATA_NODES_AUTO_ADJUST",
+ "DATA_NODES_AUTO_ADJUST_SCALE_UP",
"DATA_NODES_AUTO_ADJUST_SCALE_DOWN");
+
+ for (String optName : numericOptNames) {
+ assertThrows(SqlParseException.class, () ->
parseCreateZone(String.format(query, optName, "'bar'")));
+ }
+
+ List<String> stringOptNames = Arrays.asList("AFFINITY_FUNCTION",
"DATA_NODES_FILTER");
+
+ for (String optName : stringOptNames) {
+ assertThrows(SqlParseException.class, () ->
parseCreateZone(String.format(query, optName, "1")));
+ }
+ }
+
+ /**
+ * Parsing DROP ZONE statement.
+ */
+ @Test
+ public void dropZone() throws SqlParseException {
+ // Simple name.
+ SqlNode node = parse("drop zone test_zone");
+
+ assertThat(node, instanceOf(IgniteSqlDropZone.class));
+
+ IgniteSqlDropZone dropZone = (IgniteSqlDropZone) node;
+
+ assertThat(dropZone.name().names, is(List.of("TEST_ZONE")));
+ assertFalse(dropZone.ifExists());
+
+ // Fully qualified name.
+ dropZone = ((IgniteSqlDropZone) parse("drop zone public.test_zone"));
+
+ assertThat(dropZone.name().names, is(List.of("PUBLIC", "TEST_ZONE")));
+ }
+
+ /**
+ * Parsing DROP ZONE IF EXISTS statement.
+ */
+ @Test
+ public void dropZoneIfExists() throws SqlParseException {
+ IgniteSqlDropZone dropZone = (IgniteSqlDropZone) parse("drop zone if
exists test_zone");
+
+ assertTrue(dropZone.ifExists());
+
+ SqlPrettyWriter w = new SqlPrettyWriter();
+ dropZone.unparse(w, 0, 0);
+
+ assertThat(w.toString(), equalTo("DROP ZONE IF EXISTS \"TEST_ZONE\""));
+ }
+
+ /**
+ * Parse CREATE ZONE statement.
+ *
+ * @param stmt Create zone query.
+ * @return {@link org.apache.calcite.sql.SqlCreate SqlCreate} node.
+ */
+ private IgniteSqlCreateZone parseCreateZone(String stmt) throws
SqlParseException {
+ SqlNode node = parse(stmt);
+
+ assertThat(node, instanceOf(IgniteSqlCreateZone.class));
+
+ return (IgniteSqlCreateZone) node;
+ }
+
+ private void assertThatZoneOptionPresent(List<SqlNode> optionList,
IgniteSqlCreateZoneOptionEnum name, Object expVal) {
+ assertThat(optionList, Matchers.hasItem(ofTypeMatching(
+ name + "=" + expVal,
+ IgniteSqlCreateZoneOption.class,
+ opt -> {
+ if (name ==
opt.key().symbolValue(IgniteSqlCreateZoneOptionEnum.class)) {
+ if (opt.value() instanceof SqlLiteral) {
+ return Objects.equals(expVal, ((SqlLiteral)
opt.value()).getValueAs(expVal.getClass()));
+ }
+ }
+
+ return false;
+ }
+ )));
+ }
+}