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(&quot;type&quot;=&quot;full&quot;)" 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(&quot;backup_privilege&quot;=&quot;true&quot;,&quot;backup_catalog&quot;=&quot;true&quot;)"
 db-types="Doris" />
+</sql-cases>


Reply via email to