This is an automated email from the ASF dual-hosted git repository.
zhangliang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shardingsphere.git
The following commit(s) were added to refs/heads/master by this push:
new 8e355270f94 Support parsing Doris BACKUP syntax (#38293)
8e355270f94 is described below
commit 8e355270f94c3dcdc120cd1f959bdf63b2ac7ce9
Author: cxy <[email protected]>
AuthorDate: Mon Mar 2 19:01:45 2026 +0800
Support parsing Doris BACKUP syntax (#38293)
---
.../core/database/visitor/SQLVisitorRule.java | 2 +
.../src/main/antlr4/imports/doris/DALStatement.g4 | 12 +++
.../sql/parser/autogen/DorisStatement.g4 | 1 +
.../statement/type/DorisDALStatementVisitor.java | 32 ++++++
.../core/segment/dal/BackupTableSegment.java | 42 ++++++++
.../statement/doris/dal/DorisBackupStatement.java | 56 ++++++++++
.../dal/dialect/doris/DorisDALStatementAssert.java | 5 +
.../doris/type/DorisBackupStatementAssert.java | 116 +++++++++++++++++++++
.../cases/parser/jaxb/RootSQLParserTestCases.java | 4 +
.../segment/impl/backup/ExpectedBackupTable.java | 42 ++++++++
.../doris/DorisBackupStatementTestCase.java | 62 +++++++++++
.../parser/src/main/resources/case/dal/backup.xml | 64 ++++++++++++
.../main/resources/sql/supported/dal/backup.xml | 26 +++++
13 files changed, 464 insertions(+)
diff --git
a/parser/sql/engine/core/src/main/java/org/apache/shardingsphere/sql/parser/engine/core/database/visitor/SQLVisitorRule.java
b/parser/sql/engine/core/src/main/java/org/apache/shardingsphere/sql/parser/engine/core/database/visitor/SQLVisitorRule.java
index 3a70fae2f9c..faaa168448d 100644
---
a/parser/sql/engine/core/src/main/java/org/apache/shardingsphere/sql/parser/engine/core/database/visitor/SQLVisitorRule.java
+++
b/parser/sql/engine/core/src/main/java/org/apache/shardingsphere/sql/parser/engine/core/database/visitor/SQLVisitorRule.java
@@ -551,6 +551,8 @@ public enum SQLVisitorRule {
CREATE_REPOSITORY("CreateRepository", SQLStatementType.DAL),
+ BACKUP("Backup", SQLStatementType.DAL),
+
DORIS_ALTER_SYSTEM("DorisAlterSystem", SQLStatementType.DAL),
CREATE_SQL_BLOCK_RULE("CreateSqlBlockRule", SQLStatementType.DAL),
diff --git
a/parser/sql/engine/dialect/doris/src/main/antlr4/imports/doris/DALStatement.g4
b/parser/sql/engine/dialect/doris/src/main/antlr4/imports/doris/DALStatement.g4
index 9d3440cdee0..67cbbd75a64 100644
---
a/parser/sql/engine/dialect/doris/src/main/antlr4/imports/doris/DALStatement.g4
+++
b/parser/sql/engine/dialect/doris/src/main/antlr4/imports/doris/DALStatement.g4
@@ -790,6 +790,18 @@ refresh
: REFRESH (LDAP (ALL | (FOR identifier)?)? | CATALOG identifier | DATABASE
(identifier DOT_)? identifier | TABLE ((identifier DOT_)? (identifier DOT_)?)?
identifier)
;
+backup
+ : BACKUP GLOBAL? SNAPSHOT (databaseName DOT_)? identifier TO
repositoryName backupScope? propertiesClause?
+ ;
+
+backupScope
+ : (ON | EXCLUDE) LP_ backupTableSpec (COMMA_ backupTableSpec)* RP_
+ ;
+
+backupTableSpec
+ : tableName (PARTITION LP_ partitionList RP_)?
+ ;
+
show
: showDatabases
| showTables
diff --git
a/parser/sql/engine/dialect/doris/src/main/antlr4/org/apache/shardingsphere/sql/parser/autogen/DorisStatement.g4
b/parser/sql/engine/dialect/doris/src/main/antlr4/org/apache/shardingsphere/sql/parser/autogen/DorisStatement.g4
index ab4336d5978..263c6d855c2 100644
---
a/parser/sql/engine/dialect/doris/src/main/antlr4/org/apache/shardingsphere/sql/parser/autogen/DorisStatement.g4
+++
b/parser/sql/engine/dialect/doris/src/main/antlr4/org/apache/shardingsphere/sql/parser/autogen/DorisStatement.g4
@@ -159,6 +159,7 @@ execute
| sync
| unsetVariable
| createJob
+ | backup
// TODO consider refactor following sytax to SEMI_? EOF
) (SEMI_ EOF? | EOF)
| EOF
diff --git
a/parser/sql/engine/dialect/doris/src/main/java/org/apache/shardingsphere/sql/parser/engine/doris/visitor/statement/type/DorisDALStatementVisitor.java
b/parser/sql/engine/dialect/doris/src/main/java/org/apache/shardingsphere/sql/parser/engine/doris/visitor/statement/type/DorisDALStatementVisitor.java
index e4356ab16d4..28c6be0d0a9 100644
---
a/parser/sql/engine/dialect/doris/src/main/java/org/apache/shardingsphere/sql/parser/engine/doris/visitor/statement/type/DorisDALStatementVisitor.java
+++
b/parser/sql/engine/dialect/doris/src/main/java/org/apache/shardingsphere/sql/parser/engine/doris/visitor/statement/type/DorisDALStatementVisitor.java
@@ -158,7 +158,10 @@ import
org.apache.shardingsphere.sql.parser.autogen.DorisStatementParser.Qualifi
import
org.apache.shardingsphere.sql.parser.autogen.DorisStatementParser.RuleNameContext;
import
org.apache.shardingsphere.sql.parser.autogen.DorisStatementParser.ShowBuildIndexContext;
import
org.apache.shardingsphere.sql.parser.autogen.DorisStatementParser.ShowAlterTableContext;
+import
org.apache.shardingsphere.sql.parser.autogen.DorisStatementParser.BackupContext;
+import
org.apache.shardingsphere.sql.parser.autogen.DorisStatementParser.BackupTableSpecContext;
import
org.apache.shardingsphere.sql.parser.engine.doris.visitor.statement.DorisStatementVisitor;
+import
org.apache.shardingsphere.sql.parser.statement.core.segment.dal.BackupTableSegment;
import
org.apache.shardingsphere.sql.parser.statement.core.segment.dal.CacheTableIndexSegment;
import
org.apache.shardingsphere.sql.parser.statement.core.segment.dal.CloneActionSegment;
import
org.apache.shardingsphere.sql.parser.statement.core.segment.dal.CloneInstanceSegment;
@@ -208,6 +211,7 @@ import
org.apache.shardingsphere.sql.parser.statement.core.value.literal.impl.Ot
import
org.apache.shardingsphere.sql.parser.statement.core.value.literal.impl.TemporalLiteralValue;
import
org.apache.shardingsphere.sql.parser.statement.doris.dal.DorisAlterResourceStatement;
import
org.apache.shardingsphere.sql.parser.statement.doris.dal.DorisAlterSystemStatement;
+import
org.apache.shardingsphere.sql.parser.statement.doris.dal.DorisBackupStatement;
import
org.apache.shardingsphere.sql.parser.statement.doris.dal.DorisCreateSqlBlockRuleStatement;
import
org.apache.shardingsphere.sql.parser.statement.doris.dal.DorisCreateRepositoryStatement;
import
org.apache.shardingsphere.sql.parser.statement.doris.dal.DorisSwitchStatement;
@@ -1445,4 +1449,32 @@ public final class DorisDALStatementVisitor extends
DorisStatementVisitor implem
result.addParameterMarkers(getParameterMarkerSegments());
return result;
}
+
+ @Override
+ public ASTNode visitBackup(final BackupContext ctx) {
+ DorisBackupStatement result = new
DorisBackupStatement(getDatabaseType());
+ result.setGlobal(null != ctx.GLOBAL());
+ if (null != ctx.databaseName()) {
+ result.setDatabase((DatabaseSegment) visit(ctx.databaseName()));
+ }
+ result.setSnapshotName(((IdentifierValue)
visit(ctx.identifier())).getValue());
+ RepositoryNameContext repositoryNameCtx = ctx.repositoryName();
+ IdentifierValue identifierValue = (IdentifierValue)
visit(repositoryNameCtx);
+ result.setRepositoryName(new
RepositoryNameSegment(repositoryNameCtx.start.getStartIndex(),
repositoryNameCtx.stop.getStopIndex(), identifierValue));
+ if (null != ctx.backupScope()) {
+ result.setExcludeMode(null != ctx.backupScope().EXCLUDE());
+ for (BackupTableSpecContext each :
ctx.backupScope().backupTableSpec()) {
+ SimpleTableSegment table = (SimpleTableSegment)
visit(each.tableName());
+ BackupTableSegment backupTable = new
BackupTableSegment(each.start.getStartIndex(), each.stop.getStopIndex(), table);
+ if (null != each.partitionList()) {
+
backupTable.getPartitions().addAll(((CollectionValue<PartitionSegment>)
visit(each.partitionList())).getValue());
+ }
+ result.getTables().add(backupTable);
+ }
+ }
+ if (null != ctx.propertiesClause()) {
+
result.setProperties(extractPropertiesSegment(ctx.propertiesClause()));
+ }
+ return result;
+ }
}
diff --git
a/parser/sql/statement/core/src/main/java/org/apache/shardingsphere/sql/parser/statement/core/segment/dal/BackupTableSegment.java
b/parser/sql/statement/core/src/main/java/org/apache/shardingsphere/sql/parser/statement/core/segment/dal/BackupTableSegment.java
new file mode 100644
index 00000000000..5ccec1702fd
--- /dev/null
+++
b/parser/sql/statement/core/src/main/java/org/apache/shardingsphere/sql/parser/statement/core/segment/dal/BackupTableSegment.java
@@ -0,0 +1,42 @@
+/*
+ * 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.shardingsphere.sql.parser.statement.core.segment.dal;
+
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import org.apache.shardingsphere.sql.parser.statement.core.segment.SQLSegment;
+import
org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.SimpleTableSegment;
+
+import java.util.Collection;
+import java.util.LinkedList;
+
+/**
+ * Backup table segment.
+ */
+@RequiredArgsConstructor
+@Getter
+public final class BackupTableSegment implements SQLSegment {
+
+ private final int startIndex;
+
+ private final int stopIndex;
+
+ private final SimpleTableSegment table;
+
+ private final Collection<PartitionSegment> partitions = new LinkedList<>();
+}
diff --git
a/parser/sql/statement/dialect/doris/src/main/java/org/apache/shardingsphere/sql/parser/statement/doris/dal/DorisBackupStatement.java
b/parser/sql/statement/dialect/doris/src/main/java/org/apache/shardingsphere/sql/parser/statement/doris/dal/DorisBackupStatement.java
new file mode 100644
index 00000000000..9e6a2b6ae08
--- /dev/null
+++
b/parser/sql/statement/dialect/doris/src/main/java/org/apache/shardingsphere/sql/parser/statement/doris/dal/DorisBackupStatement.java
@@ -0,0 +1,56 @@
+/*
+ * 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.shardingsphere.sql.parser.statement.doris.dal;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.apache.shardingsphere.database.connector.core.type.DatabaseType;
+import
org.apache.shardingsphere.sql.parser.statement.core.segment.dal.BackupTableSegment;
+import
org.apache.shardingsphere.sql.parser.statement.core.segment.dal.RepositoryNameSegment;
+import
org.apache.shardingsphere.sql.parser.statement.core.segment.ddl.property.PropertiesSegment;
+import
org.apache.shardingsphere.sql.parser.statement.core.segment.generic.DatabaseSegment;
+import
org.apache.shardingsphere.sql.parser.statement.core.statement.type.dal.DALStatement;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Backup statement for Doris.
+ */
+@Getter
+@Setter
+public final class DorisBackupStatement extends DALStatement {
+
+ private boolean global;
+
+ private DatabaseSegment database;
+
+ private String snapshotName;
+
+ private RepositoryNameSegment repositoryName;
+
+ private boolean excludeMode;
+
+ private final List<BackupTableSegment> tables = new LinkedList<>();
+
+ private PropertiesSegment properties;
+
+ public DorisBackupStatement(final DatabaseType databaseType) {
+ super(databaseType);
+ }
+}
diff --git
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/statement/dal/dialect/doris/DorisDALStatementAssert.java
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/statement/dal/dialect/doris/DorisDALStatementAssert.java
index 0922a75e8eb..1316716dca9 100644
---
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/statement/dal/dialect/doris/DorisDALStatementAssert.java
+++
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/statement/dal/dialect/doris/DorisDALStatementAssert.java
@@ -23,6 +23,7 @@ import
org.apache.shardingsphere.sql.parser.statement.core.statement.type.dal.DA
import
org.apache.shardingsphere.sql.parser.statement.core.statement.type.dal.UnsetVariableStatement;
import
org.apache.shardingsphere.sql.parser.statement.doris.dal.DorisAlterResourceStatement;
import
org.apache.shardingsphere.sql.parser.statement.doris.dal.DorisAlterSystemStatement;
+import
org.apache.shardingsphere.sql.parser.statement.doris.dal.DorisBackupStatement;
import
org.apache.shardingsphere.sql.parser.statement.doris.dal.DorisCreateSqlBlockRuleStatement;
import
org.apache.shardingsphere.sql.parser.statement.doris.dal.DorisCreateRepositoryStatement;
import
org.apache.shardingsphere.sql.parser.statement.doris.dal.DorisDescFunctionStatement;
@@ -38,6 +39,7 @@ import
org.apache.shardingsphere.sql.parser.statement.doris.dal.show.DorisShowQu
import
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.SQLCaseAssertContext;
import
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.statement.dal.dialect.doris.type.DorisAlterResourceStatementAssert;
import
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.statement.dal.dialect.doris.type.DorisAlterSystemStatementAssert;
+import
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.statement.dal.dialect.doris.type.DorisBackupStatementAssert;
import
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.statement.dal.dialect.doris.type.DorisCreateSqlBlockRuleStatementAssert;
import
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.statement.dal.dialect.doris.type.DorisCreateRepositoryStatementAssert;
import
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.statement.dal.dialect.doris.type.DorisDescFunctionStatementAssert;
@@ -54,6 +56,7 @@ import
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.statement.d
import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.SQLParserTestCase;
import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.dal.dialect.doris.DorisAlterResourceStatementTestCase;
import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.dal.dialect.doris.DorisAlterSystemStatementTestCase;
+import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.dal.dialect.doris.DorisBackupStatementTestCase;
import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.dal.dialect.doris.DorisCreateSqlBlockRuleStatementTestCase;
import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.dal.dialect.doris.DorisCreateRepositoryStatementTestCase;
import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.dal.dialect.doris.DorisDescFunctionStatementTestCase;
@@ -112,6 +115,8 @@ public final class DorisDALStatementAssert {
DorisShowDataTypesStatementAssert.assertIs(assertContext,
(DorisShowDataTypesStatement) actual, (DorisShowDataTypesStatementTestCase)
expected);
} else if (actual instanceof DorisShowDataStatement) {
DorisShowDataStatementAssert.assertIs(assertContext,
(DorisShowDataStatement) actual, (DorisShowDataStatementTestCase) expected);
+ } else if (actual instanceof DorisBackupStatement) {
+ DorisBackupStatementAssert.assertIs(assertContext,
(DorisBackupStatement) actual, (DorisBackupStatementTestCase) expected);
}
}
}
diff --git
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/statement/dal/dialect/doris/type/DorisBackupStatementAssert.java
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/statement/dal/dialect/doris/type/DorisBackupStatementAssert.java
new file mode 100644
index 00000000000..dd55fbba061
--- /dev/null
+++
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/statement/dal/dialect/doris/type/DorisBackupStatementAssert.java
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.statement.dal.dialect.doris.type;
+
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import
org.apache.shardingsphere.sql.parser.statement.core.segment.dal.BackupTableSegment;
+import
org.apache.shardingsphere.sql.parser.statement.core.segment.dal.PartitionSegment;
+import
org.apache.shardingsphere.sql.parser.statement.core.segment.ddl.property.PropertySegment;
+import
org.apache.shardingsphere.sql.parser.statement.doris.dal.DorisBackupStatement;
+import
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.SQLCaseAssertContext;
+import
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.segment.SQLSegmentAssert;
+import
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.segment.database.DatabaseAssert;
+import
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.segment.identifier.IdentifierValueAssert;
+import
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.segment.table.TableAssert;
+import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.backup.ExpectedBackupTable;
+import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.index.ExpectedPartition;
+import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.dal.dialect.doris.DorisBackupStatementTestCase;
+import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.dal.dialect.doris.PropertyTestCase;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Backup statement assert for Doris.
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public final class DorisBackupStatementAssert {
+
+ /**
+ * Assert backup statement is correct with expected parser result.
+ *
+ * @param assertContext assert context
+ * @param actual actual backup statement
+ * @param expected expected backup statement test case
+ */
+ public static void assertIs(final SQLCaseAssertContext assertContext,
final DorisBackupStatement actual, final DorisBackupStatementTestCase expected)
{
+ assertThat(assertContext.getText("global flag does not match: "),
actual.isGlobal(), is(expected.isGlobal()));
+ assertThat(assertContext.getText("snapshot name does not match: "),
actual.getSnapshotName(), is(expected.getSnapshotName()));
+ assertDatabase(assertContext, actual, expected);
+ assertRepositoryName(assertContext, actual, expected);
+ assertThat(assertContext.getText("exclude mode does not match: "),
actual.isExcludeMode(), is(expected.isExcludeMode()));
+ assertBackupTables(assertContext, actual, expected);
+ assertProperties(assertContext, actual, expected);
+ }
+
+ private static void assertDatabase(final SQLCaseAssertContext
assertContext, final DorisBackupStatement actual, final
DorisBackupStatementTestCase expected) {
+ if (null != expected.getDatabase()) {
+ assertNotNull(actual.getDatabase(), assertContext.getText("Actual
database should exist."));
+ DatabaseAssert.assertIs(assertContext, actual.getDatabase(),
expected.getDatabase());
+ }
+ }
+
+ private static void assertRepositoryName(final SQLCaseAssertContext
assertContext, final DorisBackupStatement actual, final
DorisBackupStatementTestCase expected) {
+ if (null != expected.getRepositoryName()) {
+ assertNotNull(actual.getRepositoryName(),
assertContext.getText("Actual repository name should exist."));
+ IdentifierValueAssert.assertIs(assertContext,
actual.getRepositoryName().getIdentifier(), expected.getRepositoryName(),
"Repository name");
+ SQLSegmentAssert.assertIs(assertContext,
actual.getRepositoryName(), expected.getRepositoryName());
+ }
+ }
+
+ private static void assertBackupTables(final SQLCaseAssertContext
assertContext, final DorisBackupStatement actual, final
DorisBackupStatementTestCase expected) {
+ assertThat(assertContext.getText("Backup tables size does not match:
"), actual.getTables().size(), is(expected.getTables().size()));
+ int count = 0;
+ for (BackupTableSegment each : actual.getTables()) {
+ ExpectedBackupTable expectedTable =
expected.getTables().get(count);
+ TableAssert.assertIs(assertContext, each.getTable(),
expectedTable.getTable());
+ SQLSegmentAssert.assertIs(assertContext, each, expectedTable);
+ assertPartitions(assertContext, new
ArrayList<>(each.getPartitions()), expectedTable.getPartitions());
+ count++;
+ }
+ }
+
+ private static void assertPartitions(final SQLCaseAssertContext
assertContext, final List<PartitionSegment> actual, final
List<ExpectedPartition> expected) {
+ assertThat(assertContext.getText("Partitions size does not match: "),
actual.size(), is(expected.size()));
+ for (int i = 0; i < expected.size(); i++) {
+ IdentifierValueAssert.assertIs(assertContext,
actual.get(i).getName(), expected.get(i), "Partition");
+ SQLSegmentAssert.assertIs(assertContext, actual.get(i),
expected.get(i));
+ }
+ }
+
+ private static void assertProperties(final SQLCaseAssertContext
assertContext, final DorisBackupStatement actual, final
DorisBackupStatementTestCase expected) {
+ if (!expected.getProperties().isEmpty()) {
+ assertNotNull(actual.getProperties(),
assertContext.getText("properties should not be null"));
+ assertThat(assertContext.getText("Properties size does not match:
"), actual.getProperties().getProperties().size(),
is(expected.getProperties().size()));
+ for (int i = 0; i < expected.getProperties().size(); i++) {
+ assertProperty(assertContext,
actual.getProperties().getProperties().get(i), expected.getProperties().get(i));
+ }
+ }
+ }
+
+ private static void assertProperty(final SQLCaseAssertContext
assertContext, final PropertySegment actual, final PropertyTestCase expected) {
+ assertThat(assertContext.getText(String.format("Property key '%s'
assertion error: ", expected.getKey())), actual.getKey(),
is(expected.getKey()));
+ assertThat(assertContext.getText(String.format("Property value for key
'%s' assertion error: ", expected.getKey())), actual.getValue(),
is(expected.getValue()));
+ SQLSegmentAssert.assertIs(assertContext, actual, expected);
+ }
+}
diff --git
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/RootSQLParserTestCases.java
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/RootSQLParserTestCases.java
index 598e75d94fe..a99710ba408 100644
---
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/RootSQLParserTestCases.java
+++
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/RootSQLParserTestCases.java
@@ -106,6 +106,7 @@ import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.s
import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.dal.dialect.mysql.table.MySQLOptimizeTableStatementTestCase;
import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.dal.dialect.mysql.table.MySQLRepairTableStatementTestCase;
import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.dal.dialect.doris.DorisAlterResourceStatementTestCase;
+import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.dal.dialect.doris.DorisBackupStatementTestCase;
import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.dal.dialect.doris.DorisSyncStatementTestCase;
import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.dal.dialect.doris.DorisDescFunctionStatementTestCase;
import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.dal.dialect.doris.DorisShowFunctionsStatementTestCase;
@@ -1279,6 +1280,9 @@ public final class RootSQLParserTestCases {
@XmlElement(name = "sync")
private final List<DorisSyncStatementTestCase> syncTestCases = new
LinkedList<>();
+ @XmlElement(name = "backup")
+ private final List<DorisBackupStatementTestCase> backupTestCases = new
LinkedList<>();
+
@XmlElement(name = "drop-shadow-algorithm")
private final List<DropShadowAlgorithmStatementTestCase>
dropShadowAlgorithmTestCases = new LinkedList<>();
diff --git
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/backup/ExpectedBackupTable.java
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/backup/ExpectedBackupTable.java
new file mode 100644
index 00000000000..f6b0b01d5c0
--- /dev/null
+++
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/backup/ExpectedBackupTable.java
@@ -0,0 +1,42 @@
+/*
+ * 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.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.backup;
+
+import lombok.Getter;
+import lombok.Setter;
+import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.AbstractExpectedSQLSegment;
+import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.index.ExpectedPartition;
+import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.table.ExpectedSimpleTable;
+
+import javax.xml.bind.annotation.XmlElement;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Expected backup table.
+ */
+@Getter
+@Setter
+public final class ExpectedBackupTable extends AbstractExpectedSQLSegment {
+
+ @XmlElement
+ private ExpectedSimpleTable table;
+
+ @XmlElement(name = "partition")
+ private final List<ExpectedPartition> partitions = new LinkedList<>();
+}
diff --git
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/dal/dialect/doris/DorisBackupStatementTestCase.java
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/dal/dialect/doris/DorisBackupStatementTestCase.java
new file mode 100644
index 00000000000..37b4e0e307e
--- /dev/null
+++
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/dal/dialect/doris/DorisBackupStatementTestCase.java
@@ -0,0 +1,62 @@
+/*
+ * 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.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.dal.dialect.doris;
+
+import lombok.Getter;
+import lombok.Setter;
+import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.SQLParserTestCase;
+import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.backup.ExpectedBackupTable;
+import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.database.ExpectedDatabase;
+import
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.repository.ExpectedRepositoryName;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Backup statement test case for Doris.
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@Getter
+@Setter
+public final class DorisBackupStatementTestCase extends SQLParserTestCase {
+
+ @XmlAttribute(name = "global")
+ private boolean global;
+
+ @XmlAttribute(name = "snapshot-name")
+ private String snapshotName;
+
+ @XmlElement
+ private ExpectedDatabase database;
+
+ @XmlElement(name = "repository-name")
+ private ExpectedRepositoryName repositoryName;
+
+ @XmlAttribute(name = "exclude-mode")
+ private boolean excludeMode;
+
+ @XmlElement(name = "backup-table")
+ private final List<ExpectedBackupTable> tables = new LinkedList<>();
+
+ @XmlElement(name = "property")
+ private final List<PropertyTestCase> properties = new LinkedList<>();
+}
diff --git a/test/it/parser/src/main/resources/case/dal/backup.xml
b/test/it/parser/src/main/resources/case/dal/backup.xml
new file mode 100644
index 00000000000..8e58b3f11e7
--- /dev/null
+++ b/test/it/parser/src/main/resources/case/dal/backup.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<sql-parser-test-cases>
+ <backup sql-case-id="backup_snapshot_with_on_table_and_properties"
snapshot-name="snapshot_label1">
+ <database name="example_db" start-index="16" stop-index="25" />
+ <repository-name name="example_repo" start-index="46" stop-index="57"
/>
+ <backup-table start-index="63" stop-index="73">
+ <table name="example_tbl" start-index="63" stop-index="73" />
+ </backup-table>
+ <property key="type" value="full" start-index="87" stop-index="99" />
+ </backup>
+
+ <backup sql-case-id="backup_snapshot_with_on_table_partition"
snapshot-name="snapshot_label2">
+ <database name="example_db" start-index="16" stop-index="25" />
+ <repository-name name="example_repo" start-index="46" stop-index="57"
/>
+ <backup-table start-index="63" stop-index="91">
+ <table name="example_tbl" start-index="63" stop-index="73" />
+ <partition name="p1" start-index="86" stop-index="87" />
+ <partition name="p2" start-index="89" stop-index="90" />
+ </backup-table>
+ <backup-table start-index="94" stop-index="105">
+ <table name="example_tbl2" start-index="94" stop-index="105" />
+ </backup-table>
+ </backup>
+
+ <backup sql-case-id="backup_snapshot_with_exclude"
snapshot-name="snapshot_label3" exclude-mode="true">
+ <database name="example_db" start-index="16" stop-index="25" />
+ <repository-name name="example_repo" start-index="46" stop-index="57"
/>
+ <backup-table start-index="68" stop-index="78">
+ <table name="example_tbl" start-index="68" stop-index="78" />
+ </backup-table>
+ </backup>
+
+ <backup sql-case-id="backup_snapshot_without_scope"
snapshot-name="snapshot_label3">
+ <database name="example_db" start-index="16" stop-index="25" />
+ <repository-name name="example_repo" start-index="46" stop-index="57"
/>
+ </backup>
+
+ <backup sql-case-id="backup_global_snapshot" global="true"
snapshot-name="snapshot_label5">
+ <repository-name name="example_repo" start-index="42" stop-index="53"
/>
+ </backup>
+
+ <backup sql-case-id="backup_global_snapshot_with_properties" global="true"
snapshot-name="snapshot_label6">
+ <repository-name name="example_repo" start-index="42" stop-index="53"
/>
+ <property key="backup_privilege" value="true" start-index="66"
stop-index="90" />
+ <property key="backup_catalog" value="true" start-index="92"
stop-index="114" />
+ </backup>
+</sql-parser-test-cases>
diff --git a/test/it/parser/src/main/resources/sql/supported/dal/backup.xml
b/test/it/parser/src/main/resources/sql/supported/dal/backup.xml
new file mode 100644
index 00000000000..8eeed0164e4
--- /dev/null
+++ b/test/it/parser/src/main/resources/sql/supported/dal/backup.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<sql-cases>
+ <sql-case id="backup_snapshot_with_on_table_and_properties" value="BACKUP
SNAPSHOT example_db.snapshot_label1 TO example_repo ON (example_tbl)
PROPERTIES("type"="full")" db-types="Doris" />
+ <sql-case id="backup_snapshot_with_on_table_partition" value="BACKUP
SNAPSHOT example_db.snapshot_label2 TO example_repo ON (example_tbl PARTITION
(p1,p2), example_tbl2)" db-types="Doris" />
+ <sql-case id="backup_snapshot_with_exclude" value="BACKUP SNAPSHOT
example_db.snapshot_label3 TO example_repo EXCLUDE (example_tbl)"
db-types="Doris" />
+ <sql-case id="backup_snapshot_without_scope" value="BACKUP SNAPSHOT
example_db.snapshot_label3 TO example_repo" db-types="Doris" />
+ <sql-case id="backup_global_snapshot" value="BACKUP GLOBAL SNAPSHOT
snapshot_label5 TO example_repo" db-types="Doris" />
+ <sql-case id="backup_global_snapshot_with_properties" value="BACKUP GLOBAL
SNAPSHOT snapshot_label6 TO example_repo
PROPERTIES("backup_privilege"="true","backup_catalog"="true")"
db-types="Doris" />
+</sql-cases>