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 8459091d167 Support parsing Doris CREATE JOB syntax (#38268)
8459091d167 is described below

commit 8459091d1674254a5c0cbb1fd83e3ed00ad195e2
Author: cxy <[email protected]>
AuthorDate: Sat Feb 28 17:13:51 2026 +0800

    Support parsing Doris CREATE JOB syntax (#38268)
---
 .../core/database/visitor/SQLVisitorRule.java      |   2 +
 .../src/main/antlr4/imports/doris/DDLStatement.g4  |   9 ++
 .../sql/parser/autogen/DorisStatement.g4           |   1 +
 .../statement/type/DorisDDLStatementVisitor.java   |  41 +++++++
 .../core/segment/ddl/job/JobCommentSegment.java    |  36 ++++++
 .../ddl/job/JobScheduleIntervalSegment.java        |  38 ++++++
 .../core/segment/ddl/job/JobScheduleSegment.java   |  84 ++++++++++++++
 .../ddl/job/JobScheduleTimestampSegment.java       |  36 ++++++
 .../doris/ddl/DorisCreateJobStatement.java         |  58 ++++++++++
 .../doris/DorisCreateJobStatementAssert.java       | 121 +++++++++++++++++++
 .../ddl/dialect/doris/DorisDDLStatementAssert.java |   4 +
 .../cases/parser/jaxb/RootSQLParserTestCases.java  |   4 +
 .../jaxb/segment/impl/job/ExpectedJobComment.java  |  38 ++++++
 .../jaxb/segment/impl/job/ExpectedJobName.java     |  30 +++++
 .../jaxb/segment/impl/job/ExpectedJobSchedule.java |  51 ++++++++
 .../impl/job/ExpectedJobScheduleInterval.java      |  41 +++++++
 .../impl/job/ExpectedJobScheduleTimestamp.java     |  38 ++++++
 .../doris/DorisCreateJobStatementTestCase.java     |  58 ++++++++++
 .../src/main/resources/case/ddl/create-job.xml     | 128 +++++++++++++++++++++
 .../resources/sql/supported/ddl/create-job.xml     |  25 ++++
 20 files changed, 843 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 8fa65d270ec..7bb6b8c6d69 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
@@ -289,6 +289,8 @@ public enum SQLVisitorRule {
     
     UNLISTEN("Unlisten", SQLStatementType.DDL),
     
+    CREATE_JOB("CreateJob", SQLStatementType.DDL),
+    
     RESUME_JOB("ResumeJob", SQLStatementType.DDL),
     
     RESUME_SYNC_JOB("ResumeSyncJob", SQLStatementType.DDL),
diff --git 
a/parser/sql/engine/dialect/doris/src/main/antlr4/imports/doris/DDLStatement.g4 
b/parser/sql/engine/dialect/doris/src/main/antlr4/imports/doris/DDLStatement.g4
index 1086a85f994..7752d04a71e 100644
--- 
a/parser/sql/engine/dialect/doris/src/main/antlr4/imports/doris/DDLStatement.g4
+++ 
b/parser/sql/engine/dialect/doris/src/main/antlr4/imports/doris/DDLStatement.g4
@@ -990,6 +990,15 @@ signalInformationItem
     : conditionInformationItemName EQ_ expr
     ;
 
+createJob
+    : CREATE JOB jobName ON SCHEDULE jobScheduleExpression (COMMENT string_)? 
DO insert
+    ;
+
+jobScheduleExpression
+    : AT timestampValue
+    | EVERY intervalValue (STARTS timestampValue)? (ENDS timestampValue)?
+    ;
+
 resumeJob
     : RESUME JOB WHERE jobName EQ_ stringLiterals
     ;
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 96d91657da2..ab4336d5978 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
@@ -158,6 +158,7 @@ execute
     | dropFile
     | sync
     | unsetVariable
+    | createJob
     // 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/DorisDDLStatementVisitor.java
 
b/parser/sql/engine/dialect/doris/src/main/java/org/apache/shardingsphere/sql/parser/engine/doris/visitor/statement/type/DorisDDLStatementVisitor.java
index 1ff0587bac8..d98a6f1f00c 100644
--- 
a/parser/sql/engine/dialect/doris/src/main/java/org/apache/shardingsphere/sql/parser/engine/doris/visitor/statement/type/DorisDDLStatementVisitor.java
+++ 
b/parser/sql/engine/dialect/doris/src/main/java/org/apache/shardingsphere/sql/parser/engine/doris/visitor/statement/type/DorisDDLStatementVisitor.java
@@ -67,6 +67,8 @@ import 
org.apache.shardingsphere.sql.parser.autogen.DorisStatementParser.Compoun
 import 
org.apache.shardingsphere.sql.parser.autogen.DorisStatementParser.CreateDatabaseContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.DorisStatementParser.CreateDefinitionClauseContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.DorisStatementParser.CreateEventContext;
+import 
org.apache.shardingsphere.sql.parser.autogen.DorisStatementParser.CreateJobContext;
+import 
org.apache.shardingsphere.sql.parser.autogen.DorisStatementParser.JobScheduleExpressionContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.DorisStatementParser.CreateFunctionContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.DorisStatementParser.CreateIndexContext;
 import 
org.apache.shardingsphere.sql.parser.autogen.DorisStatementParser.CreateLikeClauseContext;
@@ -188,7 +190,11 @@ import 
org.apache.shardingsphere.sql.parser.statement.core.segment.ddl.rollup.Ro
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.ddl.routine.FunctionNameSegment;
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.ddl.routine.RoutineBodySegment;
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.ddl.routine.ValidStatementSegment;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.ddl.job.JobCommentSegment;
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.ddl.job.JobNameSegment;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.ddl.job.JobScheduleIntervalSegment;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.ddl.job.JobScheduleSegment;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.ddl.job.JobScheduleTimestampSegment;
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.ddl.job.ChannelDescriptionSegment;
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.ddl.job.BinlogDescriptionSegment;
 import 
org.apache.shardingsphere.sql.parser.statement.core.segment.ddl.table.AlgorithmTypeSegment;
@@ -259,6 +265,7 @@ import 
org.apache.shardingsphere.sql.parser.statement.doris.ddl.DorisResumeJobSt
 import 
org.apache.shardingsphere.sql.parser.statement.doris.ddl.DorisResumeSyncJobStatement;
 import 
org.apache.shardingsphere.sql.parser.statement.doris.ddl.DorisPauseSyncJobStatement;
 import 
org.apache.shardingsphere.sql.parser.statement.doris.ddl.DorisCreateSyncJobStatement;
+import 
org.apache.shardingsphere.sql.parser.statement.doris.ddl.DorisCreateJobStatement;
 import 
org.apache.shardingsphere.sql.parser.statement.doris.ddl.DorisStopSyncJobStatement;
 import 
org.apache.shardingsphere.sql.parser.statement.mysql.ddl.event.MySQLAlterEventStatement;
 import 
org.apache.shardingsphere.sql.parser.statement.mysql.ddl.event.MySQLCreateEventStatement;
@@ -469,6 +476,40 @@ public final class DorisDDLStatementVisitor extends 
DorisStatementVisitor implem
         return new PropertySegment(ctx.start.getStartIndex(), 
ctx.stop.getStopIndex(), key, value);
     }
     
+    @Override
+    public ASTNode visitCreateJob(final CreateJobContext ctx) {
+        DorisCreateJobStatement result = new 
DorisCreateJobStatement(getDatabaseType());
+        result.setJobName(new 
JobNameSegment(ctx.jobName().start.getStartIndex(), 
ctx.jobName().stop.getStopIndex(), (IdentifierValue) 
visit(ctx.jobName().identifier())));
+        
result.setSchedule(createJobScheduleSegment(ctx.jobScheduleExpression()));
+        if (null != ctx.COMMENT() && null != ctx.string_()) {
+            result.setComment(new 
JobCommentSegment(ctx.COMMENT().getSymbol().getStartIndex(), 
ctx.string_().stop.getStopIndex(), 
SQLUtils.getExactlyValue(ctx.string_().getText())));
+        }
+        result.setInsertStatement((InsertStatement) visit(ctx.insert()));
+        return result;
+    }
+    
+    private JobScheduleSegment createJobScheduleSegment(final 
JobScheduleExpressionContext ctx) {
+        boolean everySchedule = null == ctx.AT();
+        JobScheduleSegment result = new 
JobScheduleSegment(ctx.start.getStartIndex(), ctx.stop.getStopIndex(), 
everySchedule);
+        if (!everySchedule) {
+            result.setAtTimestamp(
+                    new 
JobScheduleTimestampSegment(ctx.timestampValue(0).start.getStartIndex(), 
ctx.timestampValue(0).stop.getStopIndex(), 
SQLUtils.getExactlyValue(ctx.timestampValue(0).getText())));
+        } else {
+            result.setInterval(new 
JobScheduleIntervalSegment(ctx.intervalValue().start.getStartIndex(), 
ctx.intervalValue().stop.getStopIndex(), 
Long.parseLong(ctx.intervalValue().expr().getText()),
+                    ctx.intervalValue().intervalUnit().getText()));
+            if (null != ctx.STARTS()) {
+                result.setStartsTimestamp(new 
JobScheduleTimestampSegment(ctx.timestampValue(0).start.getStartIndex(), 
ctx.timestampValue(0).stop.getStopIndex(),
+                        
SQLUtils.getExactlyValue(ctx.timestampValue(0).getText())));
+            }
+            if (null != ctx.ENDS()) {
+                int endsTimestampIndex = null != ctx.STARTS() ? 1 : 0;
+                result.setEndsTimestamp(new 
JobScheduleTimestampSegment(ctx.timestampValue(endsTimestampIndex).start.getStartIndex(),
 ctx.timestampValue(endsTimestampIndex).stop.getStopIndex(),
+                        
SQLUtils.getExactlyValue(ctx.timestampValue(endsTimestampIndex).getText())));
+            }
+        }
+        return result;
+    }
+    
     @SuppressWarnings("unchecked")
     @Override
     public ASTNode visitCreateTable(final CreateTableContext ctx) {
diff --git 
a/parser/sql/statement/core/src/main/java/org/apache/shardingsphere/sql/parser/statement/core/segment/ddl/job/JobCommentSegment.java
 
b/parser/sql/statement/core/src/main/java/org/apache/shardingsphere/sql/parser/statement/core/segment/ddl/job/JobCommentSegment.java
new file mode 100644
index 00000000000..8e360638e3b
--- /dev/null
+++ 
b/parser/sql/statement/core/src/main/java/org/apache/shardingsphere/sql/parser/statement/core/segment/ddl/job/JobCommentSegment.java
@@ -0,0 +1,36 @@
+/*
+ * 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.ddl.job;
+
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import org.apache.shardingsphere.sql.parser.statement.core.segment.SQLSegment;
+
+/**
+ * Job comment segment.
+ */
+@RequiredArgsConstructor
+@Getter
+public final class JobCommentSegment implements SQLSegment {
+    
+    private final int startIndex;
+    
+    private final int stopIndex;
+    
+    private final String value;
+}
diff --git 
a/parser/sql/statement/core/src/main/java/org/apache/shardingsphere/sql/parser/statement/core/segment/ddl/job/JobScheduleIntervalSegment.java
 
b/parser/sql/statement/core/src/main/java/org/apache/shardingsphere/sql/parser/statement/core/segment/ddl/job/JobScheduleIntervalSegment.java
new file mode 100644
index 00000000000..3e9a71d72b2
--- /dev/null
+++ 
b/parser/sql/statement/core/src/main/java/org/apache/shardingsphere/sql/parser/statement/core/segment/ddl/job/JobScheduleIntervalSegment.java
@@ -0,0 +1,38 @@
+/*
+ * 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.ddl.job;
+
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import org.apache.shardingsphere.sql.parser.statement.core.segment.SQLSegment;
+
+/**
+ * Job schedule interval segment.
+ */
+@RequiredArgsConstructor
+@Getter
+public final class JobScheduleIntervalSegment implements SQLSegment {
+    
+    private final int startIndex;
+    
+    private final int stopIndex;
+    
+    private final long value;
+    
+    private final String unit;
+}
diff --git 
a/parser/sql/statement/core/src/main/java/org/apache/shardingsphere/sql/parser/statement/core/segment/ddl/job/JobScheduleSegment.java
 
b/parser/sql/statement/core/src/main/java/org/apache/shardingsphere/sql/parser/statement/core/segment/ddl/job/JobScheduleSegment.java
new file mode 100644
index 00000000000..d04dd1d726f
--- /dev/null
+++ 
b/parser/sql/statement/core/src/main/java/org/apache/shardingsphere/sql/parser/statement/core/segment/ddl/job/JobScheduleSegment.java
@@ -0,0 +1,84 @@
+/*
+ * 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.ddl.job;
+
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import lombok.Setter;
+import org.apache.shardingsphere.sql.parser.statement.core.segment.SQLSegment;
+
+import java.util.Optional;
+
+/**
+ * Job schedule segment.
+ */
+@RequiredArgsConstructor
+@Getter
+@Setter
+public final class JobScheduleSegment implements SQLSegment {
+    
+    private final int startIndex;
+    
+    private final int stopIndex;
+    
+    private final boolean everySchedule;
+    
+    private JobScheduleTimestampSegment atTimestamp;
+    
+    private JobScheduleIntervalSegment interval;
+    
+    private JobScheduleTimestampSegment startsTimestamp;
+    
+    private JobScheduleTimestampSegment endsTimestamp;
+    
+    /**
+     * Get at timestamp segment.
+     *
+     * @return at timestamp segment
+     */
+    public Optional<JobScheduleTimestampSegment> getAtTimestamp() {
+        return Optional.ofNullable(atTimestamp);
+    }
+    
+    /**
+     * Get interval segment.
+     *
+     * @return interval segment
+     */
+    public Optional<JobScheduleIntervalSegment> getInterval() {
+        return Optional.ofNullable(interval);
+    }
+    
+    /**
+     * Get starts timestamp segment.
+     *
+     * @return starts timestamp segment
+     */
+    public Optional<JobScheduleTimestampSegment> getStartsTimestamp() {
+        return Optional.ofNullable(startsTimestamp);
+    }
+    
+    /**
+     * Get ends timestamp segment.
+     *
+     * @return ends timestamp segment
+     */
+    public Optional<JobScheduleTimestampSegment> getEndsTimestamp() {
+        return Optional.ofNullable(endsTimestamp);
+    }
+}
diff --git 
a/parser/sql/statement/core/src/main/java/org/apache/shardingsphere/sql/parser/statement/core/segment/ddl/job/JobScheduleTimestampSegment.java
 
b/parser/sql/statement/core/src/main/java/org/apache/shardingsphere/sql/parser/statement/core/segment/ddl/job/JobScheduleTimestampSegment.java
new file mode 100644
index 00000000000..f6e761d532a
--- /dev/null
+++ 
b/parser/sql/statement/core/src/main/java/org/apache/shardingsphere/sql/parser/statement/core/segment/ddl/job/JobScheduleTimestampSegment.java
@@ -0,0 +1,36 @@
+/*
+ * 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.ddl.job;
+
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import org.apache.shardingsphere.sql.parser.statement.core.segment.SQLSegment;
+
+/**
+ * Job schedule timestamp segment.
+ */
+@RequiredArgsConstructor
+@Getter
+public final class JobScheduleTimestampSegment implements SQLSegment {
+    
+    private final int startIndex;
+    
+    private final int stopIndex;
+    
+    private final String value;
+}
diff --git 
a/parser/sql/statement/dialect/doris/src/main/java/org/apache/shardingsphere/sql/parser/statement/doris/ddl/DorisCreateJobStatement.java
 
b/parser/sql/statement/dialect/doris/src/main/java/org/apache/shardingsphere/sql/parser/statement/doris/ddl/DorisCreateJobStatement.java
new file mode 100644
index 00000000000..13c1c601f48
--- /dev/null
+++ 
b/parser/sql/statement/dialect/doris/src/main/java/org/apache/shardingsphere/sql/parser/statement/doris/ddl/DorisCreateJobStatement.java
@@ -0,0 +1,58 @@
+/*
+ * 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.ddl;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.apache.shardingsphere.database.connector.core.type.DatabaseType;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.ddl.job.JobCommentSegment;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.ddl.job.JobNameSegment;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.ddl.job.JobScheduleSegment;
+import 
org.apache.shardingsphere.sql.parser.statement.core.statement.type.ddl.DDLStatement;
+import 
org.apache.shardingsphere.sql.parser.statement.core.statement.type.dml.InsertStatement;
+
+import java.util.Optional;
+
+/**
+ * Create job statement for Doris.
+ */
+@Getter
+@Setter
+public final class DorisCreateJobStatement extends DDLStatement {
+    
+    private JobNameSegment jobName;
+    
+    private JobScheduleSegment schedule;
+    
+    private JobCommentSegment comment;
+    
+    private InsertStatement insertStatement;
+    
+    public DorisCreateJobStatement(final DatabaseType databaseType) {
+        super(databaseType);
+    }
+    
+    /**
+     * Get comment.
+     *
+     * @return comment
+     */
+    public Optional<JobCommentSegment> getComment() {
+        return Optional.ofNullable(comment);
+    }
+}
diff --git 
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/statement/ddl/dialect/doris/DorisCreateJobStatementAssert.java
 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/statement/ddl/dialect/doris/DorisCreateJobStatementAssert.java
new file mode 100644
index 00000000000..aa2aad2dbe1
--- /dev/null
+++ 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/statement/ddl/dialect/doris/DorisCreateJobStatementAssert.java
@@ -0,0 +1,121 @@
+/*
+ * 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.ddl.dialect.doris;
+
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.ddl.job.JobCommentSegment;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.ddl.job.JobScheduleSegment;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.generic.table.SimpleTableSegment;
+import 
org.apache.shardingsphere.sql.parser.statement.doris.ddl.DorisCreateJobStatement;
+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.table.TableAssert;
+import 
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.segment.where.WhereClauseAssert;
+import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.job.ExpectedJobSchedule;
+import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.ddl.dialect.doris.DorisCreateJobStatementTestCase;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Create job statement assert for Doris.
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public final class DorisCreateJobStatementAssert {
+    
+    /**
+     * Assert create job statement is correct with expected parser result.
+     *
+     * @param assertContext assert context
+     * @param actual actual create job statement
+     * @param expected expected create job statement test case
+     */
+    public static void assertIs(final SQLCaseAssertContext assertContext, 
final DorisCreateJobStatement actual, final DorisCreateJobStatementTestCase 
expected) {
+        assertJobName(assertContext, actual, expected);
+        assertSchedule(assertContext, actual, expected);
+        assertComment(assertContext, actual, expected);
+        assertInsertStatement(assertContext, actual, expected);
+    }
+    
+    private static void assertJobName(final SQLCaseAssertContext 
assertContext, final DorisCreateJobStatement actual, final 
DorisCreateJobStatementTestCase expected) {
+        assertNotNull(actual.getJobName(), assertContext.getText("Job name 
should exist."));
+        assertThat(assertContext.getText("Job name does not match: "), 
actual.getJobName().getIdentifier().getValue(), 
is(expected.getJobName().getName()));
+        SQLSegmentAssert.assertIs(assertContext, actual.getJobName(), 
expected.getJobName());
+    }
+    
+    private static void assertSchedule(final SQLCaseAssertContext 
assertContext, final DorisCreateJobStatement actual, final 
DorisCreateJobStatementTestCase expected) {
+        assertNotNull(actual.getSchedule(), assertContext.getText("Schedule 
should exist."));
+        assertNotNull(expected.getSchedule(), assertContext.getText("Expected 
schedule should exist."));
+        JobScheduleSegment actualSchedule = actual.getSchedule();
+        ExpectedJobSchedule expectedSchedule = expected.getSchedule();
+        SQLSegmentAssert.assertIs(assertContext, actualSchedule, 
expectedSchedule);
+        assertThat(assertContext.getText("Every schedule flag does not match: 
"), actualSchedule.isEverySchedule(), is(expectedSchedule.isEverySchedule()));
+        if (null != expectedSchedule.getAtTimestamp()) {
+            assertTrue(actualSchedule.getAtTimestamp().isPresent(), 
assertContext.getText("At timestamp should exist."));
+            assertThat(assertContext.getText("At timestamp value does not 
match: "), actualSchedule.getAtTimestamp().get().getValue(), 
is(expectedSchedule.getAtTimestamp().getValue()));
+            SQLSegmentAssert.assertIs(assertContext, 
actualSchedule.getAtTimestamp().get(), expectedSchedule.getAtTimestamp());
+        }
+        if (null != expectedSchedule.getInterval()) {
+            assertTrue(actualSchedule.getInterval().isPresent(), 
assertContext.getText("Interval should exist."));
+            assertThat(assertContext.getText("Interval value does not match: 
"), actualSchedule.getInterval().get().getValue(), 
is(expectedSchedule.getInterval().getValue()));
+            assertThat(assertContext.getText("Interval unit does not match: 
"), actualSchedule.getInterval().get().getUnit(), 
is(expectedSchedule.getInterval().getUnit()));
+            SQLSegmentAssert.assertIs(assertContext, 
actualSchedule.getInterval().get(), expectedSchedule.getInterval());
+        }
+        if (null != expectedSchedule.getStartsTimestamp()) {
+            assertTrue(actualSchedule.getStartsTimestamp().isPresent(), 
assertContext.getText("Starts timestamp should exist."));
+            assertThat(assertContext.getText("Starts timestamp value does not 
match: "), actualSchedule.getStartsTimestamp().get().getValue(), 
is(expectedSchedule.getStartsTimestamp().getValue()));
+            SQLSegmentAssert.assertIs(assertContext, 
actualSchedule.getStartsTimestamp().get(), 
expectedSchedule.getStartsTimestamp());
+        }
+        if (null != expectedSchedule.getEndsTimestamp()) {
+            assertTrue(actualSchedule.getEndsTimestamp().isPresent(), 
assertContext.getText("Ends timestamp should exist."));
+            assertThat(assertContext.getText("Ends timestamp value does not 
match: "), actualSchedule.getEndsTimestamp().get().getValue(), 
is(expectedSchedule.getEndsTimestamp().getValue()));
+            SQLSegmentAssert.assertIs(assertContext, 
actualSchedule.getEndsTimestamp().get(), expectedSchedule.getEndsTimestamp());
+        }
+    }
+    
+    private static void assertComment(final SQLCaseAssertContext 
assertContext, final DorisCreateJobStatement actual, final 
DorisCreateJobStatementTestCase expected) {
+        if (null != expected.getComment()) {
+            assertTrue(actual.getComment().isPresent(), 
assertContext.getText("Comment should exist."));
+            JobCommentSegment actualComment = actual.getComment().get();
+            assertThat(assertContext.getText("Comment value does not match: 
"), actualComment.getValue(), is(expected.getComment().getValue()));
+            SQLSegmentAssert.assertIs(assertContext, actualComment, 
expected.getComment());
+        }
+    }
+    
+    private static void assertInsertStatement(final SQLCaseAssertContext 
assertContext, final DorisCreateJobStatement actual, final 
DorisCreateJobStatementTestCase expected) {
+        assertNotNull(actual.getInsertStatement(), 
assertContext.getText("Insert statement should exist."));
+        if (null != expected.getInsertTable()) {
+            assertTrue(actual.getInsertStatement().getTable().isPresent(), 
assertContext.getText("Insert target table should exist."));
+            TableAssert.assertIs(assertContext, 
actual.getInsertStatement().getTable().get(), expected.getInsertTable());
+        }
+        if (null != expected.getInsertSelectTable()) {
+            
assertTrue(actual.getInsertStatement().getInsertSelect().isPresent(), 
assertContext.getText("Insert select should exist."));
+            SimpleTableSegment fromTable = (SimpleTableSegment) 
actual.getInsertStatement().getInsertSelect().get().getSelect().getFrom().orElse(null);
+            assertNotNull(fromTable, assertContext.getText("Insert select from 
table should exist."));
+            TableAssert.assertIs(assertContext, fromTable, 
expected.getInsertSelectTable());
+        }
+        if (null != expected.getInsertSelectWhere()) {
+            
assertTrue(actual.getInsertStatement().getInsertSelect().isPresent(), 
assertContext.getText("Insert select should exist."));
+            
assertTrue(actual.getInsertStatement().getInsertSelect().get().getSelect().getWhere().isPresent(),
 assertContext.getText("Insert select where should exist."));
+            WhereClauseAssert.assertIs(assertContext, 
actual.getInsertStatement().getInsertSelect().get().getSelect().getWhere().get(),
 expected.getInsertSelectWhere());
+        }
+    }
+}
diff --git 
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/statement/ddl/dialect/doris/DorisDDLStatementAssert.java
 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/statement/ddl/dialect/doris/DorisDDLStatementAssert.java
index 1cc91c5a069..8c39f0e303a 100644
--- 
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/statement/ddl/dialect/doris/DorisDDLStatementAssert.java
+++ 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/asserts/statement/ddl/dialect/doris/DorisDDLStatementAssert.java
@@ -27,11 +27,13 @@ import 
org.apache.shardingsphere.sql.parser.statement.doris.ddl.DorisResumeJobSt
 import 
org.apache.shardingsphere.sql.parser.statement.doris.ddl.DorisResumeSyncJobStatement;
 import 
org.apache.shardingsphere.sql.parser.statement.doris.ddl.DorisPauseSyncJobStatement;
 import 
org.apache.shardingsphere.sql.parser.statement.doris.ddl.DorisStopSyncJobStatement;
+import 
org.apache.shardingsphere.sql.parser.statement.doris.ddl.DorisCreateJobStatement;
 import 
org.apache.shardingsphere.sql.parser.statement.doris.ddl.DorisCreateSyncJobStatement;
 import 
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.SQLCaseAssertContext;
 import 
org.apache.shardingsphere.test.it.sql.parser.internal.asserts.statement.ddl.dialect.doris.type.DorisAlterStoragePolicyStatementAssert;
 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.ddl.dialect.doris.DorisAlterStoragePolicyStatementTestCase;
+import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.ddl.dialect.doris.DorisCreateJobStatementTestCase;
 import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.ddl.dialect.doris.DorisDropFunctionStatementTestCase;
 import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.ddl.dialect.doris.DorisResumeJobStatementTestCase;
 import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.ddl.dialect.doris.DorisResumeSyncJobStatementTestCase;
@@ -70,6 +72,8 @@ public final class DorisDDLStatementAssert {
             DorisCreateSyncJobStatementAssert.assertIs(assertContext, 
(DorisCreateSyncJobStatement) actual, (DorisCreateSyncJobStatementTestCase) 
expected);
         } else if (actual instanceof DorisStopSyncJobStatement) {
             DorisStopSyncJobStatementAssert.assertIs(assertContext, 
(DorisStopSyncJobStatement) actual, (DorisStopSyncJobStatementTestCase) 
expected);
+        } else if (actual instanceof DorisCreateJobStatement) {
+            DorisCreateJobStatementAssert.assertIs(assertContext, 
(DorisCreateJobStatement) actual, (DorisCreateJobStatementTestCase) 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 0d7165aaec1..2747495c648 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
@@ -33,6 +33,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.ddl.dialect.doris.DorisResumeSyncJobStatementTestCase;
 import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.ddl.dialect.doris.DorisPauseSyncJobStatementTestCase;
 import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.ddl.dialect.doris.DorisStopSyncJobStatementTestCase;
+import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.ddl.dialect.doris.DorisCreateJobStatementTestCase;
 import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.ddl.dialect.doris.DorisCreateSyncJobStatementTestCase;
 import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.dal.dialect.doris.DorisAlterSqlBlockRuleStatementTestCase;
 import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.statement.dal.dialect.doris.DorisDropSqlBlockRuleStatementTestCase;
@@ -566,6 +567,9 @@ public final class RootSQLParserTestCases {
     @XmlElement(name = "create-sync-job")
     private final List<DorisCreateSyncJobStatementTestCase> 
createSyncJobTestCases = new LinkedList<>();
     
+    @XmlElement(name = "create-job")
+    private final List<DorisCreateJobStatementTestCase> createJobTestCases = 
new LinkedList<>();
+    
     @XmlElement(name = "alter-catalog")
     private final List<AlterCatalogStatementTestCase> alterCatalogTestCases = 
new LinkedList<>();
     
diff --git 
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/job/ExpectedJobComment.java
 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/job/ExpectedJobComment.java
new file mode 100644
index 00000000000..53a8179a0de
--- /dev/null
+++ 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/job/ExpectedJobComment.java
@@ -0,0 +1,38 @@
+/*
+ * 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.job;
+
+import lombok.Getter;
+import lombok.Setter;
+import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.AbstractExpectedSQLSegment;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+
+/**
+ * Expected job comment.
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@Getter
+@Setter
+public final class ExpectedJobComment extends AbstractExpectedSQLSegment {
+    
+    @XmlAttribute
+    private String value;
+}
diff --git 
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/job/ExpectedJobName.java
 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/job/ExpectedJobName.java
new file mode 100644
index 00000000000..c6f107886aa
--- /dev/null
+++ 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/job/ExpectedJobName.java
@@ -0,0 +1,30 @@
+/*
+ * 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.job;
+
+import lombok.Getter;
+import lombok.Setter;
+import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.AbstractExpectedIdentifierSQLSegment;
+
+/**
+ * Expected job name.
+ */
+@Getter
+@Setter
+public final class ExpectedJobName extends 
AbstractExpectedIdentifierSQLSegment {
+}
diff --git 
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/job/ExpectedJobSchedule.java
 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/job/ExpectedJobSchedule.java
new file mode 100644
index 00000000000..efbf7f05b5e
--- /dev/null
+++ 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/job/ExpectedJobSchedule.java
@@ -0,0 +1,51 @@
+/*
+ * 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.job;
+
+import lombok.Getter;
+import lombok.Setter;
+import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.AbstractExpectedSQLSegment;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+
+/**
+ * Expected job schedule segment.
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@Getter
+@Setter
+public final class ExpectedJobSchedule extends AbstractExpectedSQLSegment {
+    
+    @XmlAttribute(name = "every-schedule")
+    private boolean everySchedule;
+    
+    @XmlElement(name = "at-timestamp")
+    private ExpectedJobScheduleTimestamp atTimestamp;
+    
+    @XmlElement(name = "interval")
+    private ExpectedJobScheduleInterval interval;
+    
+    @XmlElement(name = "starts-timestamp")
+    private ExpectedJobScheduleTimestamp startsTimestamp;
+    
+    @XmlElement(name = "ends-timestamp")
+    private ExpectedJobScheduleTimestamp endsTimestamp;
+}
diff --git 
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/job/ExpectedJobScheduleInterval.java
 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/job/ExpectedJobScheduleInterval.java
new file mode 100644
index 00000000000..6bb2fa0dc33
--- /dev/null
+++ 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/job/ExpectedJobScheduleInterval.java
@@ -0,0 +1,41 @@
+/*
+ * 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.job;
+
+import lombok.Getter;
+import lombok.Setter;
+import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.AbstractExpectedSQLSegment;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+
+/**
+ * Expected job schedule interval.
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@Getter
+@Setter
+public final class ExpectedJobScheduleInterval extends 
AbstractExpectedSQLSegment {
+    
+    @XmlAttribute
+    private long value;
+    
+    @XmlAttribute
+    private String unit;
+}
diff --git 
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/job/ExpectedJobScheduleTimestamp.java
 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/job/ExpectedJobScheduleTimestamp.java
new file mode 100644
index 00000000000..1d910480067
--- /dev/null
+++ 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/segment/impl/job/ExpectedJobScheduleTimestamp.java
@@ -0,0 +1,38 @@
+/*
+ * 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.job;
+
+import lombok.Getter;
+import lombok.Setter;
+import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.AbstractExpectedSQLSegment;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+
+/**
+ * Expected job schedule timestamp.
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@Getter
+@Setter
+public final class ExpectedJobScheduleTimestamp extends 
AbstractExpectedSQLSegment {
+    
+    @XmlAttribute
+    private String value;
+}
diff --git 
a/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/ddl/dialect/doris/DorisCreateJobStatementTestCase.java
 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/ddl/dialect/doris/DorisCreateJobStatementTestCase.java
new file mode 100644
index 00000000000..a286b8b106e
--- /dev/null
+++ 
b/test/it/parser/src/main/java/org/apache/shardingsphere/test/it/sql/parser/internal/cases/parser/jaxb/statement/ddl/dialect/doris/DorisCreateJobStatementTestCase.java
@@ -0,0 +1,58 @@
+/*
+ * 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.ddl.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.job.ExpectedJobComment;
+import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.job.ExpectedJobName;
+import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.job.ExpectedJobSchedule;
+import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.table.ExpectedSimpleTable;
+import 
org.apache.shardingsphere.test.it.sql.parser.internal.cases.parser.jaxb.segment.impl.where.ExpectedWhereClause;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+
+/**
+ * Create job statement test case for Doris.
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@Getter
+@Setter
+public final class DorisCreateJobStatementTestCase extends SQLParserTestCase {
+    
+    @XmlElement(name = "job-name")
+    private ExpectedJobName jobName;
+    
+    @XmlElement(name = "schedule")
+    private ExpectedJobSchedule schedule;
+    
+    @XmlElement(name = "job-comment")
+    private ExpectedJobComment comment;
+    
+    @XmlElement(name = "insert-table")
+    private ExpectedSimpleTable insertTable;
+    
+    @XmlElement(name = "insert-select-table")
+    private ExpectedSimpleTable insertSelectTable;
+    
+    @XmlElement(name = "insert-select-where")
+    private ExpectedWhereClause insertSelectWhere;
+}
diff --git a/test/it/parser/src/main/resources/case/ddl/create-job.xml 
b/test/it/parser/src/main/resources/case/ddl/create-job.xml
new file mode 100644
index 00000000000..860054f05c9
--- /dev/null
+++ b/test/it/parser/src/main/resources/case/ddl/create-job.xml
@@ -0,0 +1,128 @@
+<?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>
+    <create-job sql-case-id="create_job_every_minute">
+        <job-name name="my_job" start-index="11" stop-index="16" />
+        <schedule start-index="30" stop-index="43" every-schedule="true">
+            <interval start-index="36" stop-index="43" value="1" unit="MINUTE" 
/>
+        </schedule>
+        <insert-table name="tbl1" start-index="60" stop-index="67">
+            <owner name="db1" start-index="60" stop-index="62" />
+        </insert-table>
+        <insert-select-table name="tbl2" start-index="83" stop-index="90">
+            <owner name="db2" start-index="83" stop-index="85" />
+        </insert-select-table>
+    </create-job>
+
+    <create-job sql-case-id="create_job_at_once">
+        <job-name name="my_job" start-index="11" stop-index="16" />
+        <schedule start-index="30" stop-index="53" every-schedule="false">
+            <at-timestamp start-index="33" stop-index="53" value="2020-01-01 
00:00:00" />
+        </schedule>
+        <insert-table name="tbl1" start-index="70" stop-index="77">
+            <owner name="db1" start-index="70" stop-index="72" />
+        </insert-table>
+        <insert-select-table name="tbl2" start-index="93" stop-index="100">
+            <owner name="db2" start-index="93" stop-index="95" />
+        </insert-select-table>
+    </create-job>
+
+    <create-job sql-case-id="create_job_every_day_with_starts">
+        <job-name name="my_job" start-index="11" stop-index="16" />
+        <schedule start-index="30" stop-index="69" every-schedule="true">
+            <interval start-index="36" stop-index="40" value="1" unit="DAY" />
+            <starts-timestamp start-index="49" stop-index="69" 
value="2020-01-01 00:00:00" />
+        </schedule>
+        <insert-table name="tbl1" start-index="86" stop-index="93">
+            <owner name="db1" start-index="86" stop-index="88" />
+        </insert-table>
+        <insert-select-table name="tbl2" start-index="109" stop-index="116">
+            <owner name="db2" start-index="109" stop-index="111" />
+        </insert-select-table>
+        <insert-select-where start-index="118" stop-index="156">
+            <expr>
+                <binary-operation-expression start-index="124" 
stop-index="156">
+                    <left>
+                        <column name="create_time" start-index="124" 
stop-index="134" />
+                    </left>
+                    <operator>&gt;=</operator>
+                    <right>
+                        <function function-name="days_add" start-index="139" 
stop-index="156" text="days_add(now(),-1)">
+                            <parameter>
+                                <function function-name="now" 
start-index="148" stop-index="152" text="now()" />
+                            </parameter>
+                            <parameter>
+                                <literal-expression start-index="154" 
stop-index="155" value="-1" />
+                            </parameter>
+                        </function>
+                    </right>
+                </binary-operation-expression>
+            </expr>
+        </insert-select-where>
+    </create-job>
+
+    <create-job sql-case-id="create_job_every_day_with_starts_and_ends">
+        <job-name name="my_job" start-index="11" stop-index="16" />
+        <schedule start-index="30" stop-index="96" every-schedule="true">
+            <interval start-index="36" stop-index="40" value="1" unit="DAY" />
+            <starts-timestamp start-index="49" stop-index="69" 
value="2020-01-01 00:00:00" />
+            <ends-timestamp start-index="76" stop-index="96" value="2020-01-01 
00:10:00" />
+        </schedule>
+        <insert-table name="tbl1" start-index="113" stop-index="120">
+            <owner name="db1" start-index="113" stop-index="115" />
+        </insert-table>
+        <insert-select-table name="tbl2" start-index="136" stop-index="143">
+            <owner name="db2" start-index="136" stop-index="138" />
+        </insert-select-table>
+        <insert-select-where start-index="145" stop-index="183">
+            <expr>
+                <binary-operation-expression start-index="151" 
stop-index="183">
+                    <left>
+                        <column name="create_time" start-index="151" 
stop-index="161" />
+                    </left>
+                    <operator>&gt;=</operator>
+                    <right>
+                        <function function-name="days_add" start-index="166" 
stop-index="183" text="days_add(now(),-1)">
+                            <parameter>
+                                <function function-name="now" 
start-index="175" stop-index="179" text="now()" />
+                            </parameter>
+                            <parameter>
+                                <literal-expression start-index="181" 
stop-index="182" value="-1" />
+                            </parameter>
+                        </function>
+                    </right>
+                </binary-operation-expression>
+            </expr>
+        </insert-select-where>
+    </create-job>
+
+    <create-job sql-case-id="create_job_every_minute_with_comment">
+        <job-name name="my_job" start-index="11" stop-index="16" />
+        <schedule start-index="30" stop-index="43" every-schedule="true">
+            <interval start-index="36" stop-index="43" value="1" unit="MINUTE" 
/>
+        </schedule>
+        <job-comment start-index="45" stop-index="66" value="test comment" />
+        <insert-table name="tbl1" start-index="83" stop-index="90">
+            <owner name="db1" start-index="83" stop-index="85" />
+        </insert-table>
+        <insert-select-table name="tbl2" start-index="106" stop-index="113">
+            <owner name="db2" start-index="106" stop-index="108" />
+        </insert-select-table>
+    </create-job>
+</sql-parser-test-cases>
diff --git a/test/it/parser/src/main/resources/sql/supported/ddl/create-job.xml 
b/test/it/parser/src/main/resources/sql/supported/ddl/create-job.xml
new file mode 100644
index 00000000000..0af36dc8c41
--- /dev/null
+++ b/test/it/parser/src/main/resources/sql/supported/ddl/create-job.xml
@@ -0,0 +1,25 @@
+<?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="create_job_every_minute" value="CREATE JOB my_job ON 
SCHEDULE EVERY 1 MINUTE DO INSERT INTO db1.tbl1 SELECT * FROM db2.tbl2" 
db-types="Doris" />
+    <sql-case id="create_job_at_once" value="CREATE JOB my_job ON SCHEDULE AT 
'2020-01-01 00:00:00' DO INSERT INTO db1.tbl1 SELECT * FROM db2.tbl2" 
db-types="Doris" />
+    <sql-case id="create_job_every_day_with_starts" value="CREATE JOB my_job 
ON SCHEDULE EVERY 1 DAY STARTS '2020-01-01 00:00:00' DO INSERT INTO db1.tbl1 
SELECT * FROM db2.tbl2 WHERE create_time &gt;= days_add(now(),-1)" 
db-types="Doris" />
+    <sql-case id="create_job_every_day_with_starts_and_ends" value="CREATE JOB 
my_job ON SCHEDULE EVERY 1 DAY STARTS '2020-01-01 00:00:00' ENDS '2020-01-01 
00:10:00' DO INSERT INTO db1.tbl1 SELECT * FROM db2.tbl2 WHERE create_time 
&gt;= days_add(now(),-1)" db-types="Doris" />
+    <sql-case id="create_job_every_minute_with_comment" value="CREATE JOB 
my_job ON SCHEDULE EVERY 1 MINUTE COMMENT 'test comment' DO INSERT INTO 
db1.tbl1 SELECT * FROM db2.tbl2" db-types="Doris" />
+</sql-cases>

Reply via email to