This is an automated email from the ASF dual-hosted git repository.

zirui pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-inlong.git


The following commit(s) were added to refs/heads/master by this push:
     new 333e6e98d [INLONG-4243][Sort] Add Oracle data extract support (#4382)
333e6e98d is described below

commit 333e6e98d07ee2d08e1e01e30036ef7819e2ea11
Author: yunqingmoswu <[email protected]>
AuthorDate: Thu May 26 15:21:22 2022 +0800

    [INLONG-4243][Sort] Add Oracle data extract support (#4382)
---
 .../inlong/sort/protocol/BuiltInFieldInfo.java     |  43 ++++++-
 .../sort/protocol/constant/OracleConstant.java     | 116 +++++++++++++++++
 .../inlong/sort/protocol/node/ExtractNode.java     |   4 +-
 .../org/apache/inlong/sort/protocol/node/Node.java |   7 +-
 .../protocol/node/extract/OracleExtractNode.java   | 139 +++++++++++++++++++++
 .../node/extract/OracleExtractNodeTest.java        |  44 +++++++
 inlong-sort/sort-connectors/pom.xml                |   5 +
 .../inlong/sort/parser/impl/FlinkSqlParser.java    |  39 ++++++
 .../sort/parser/OracleExtractSqlParseTest.java     | 128 +++++++++++++++++++
 licenses/inlong-sort/LICENSE                       |   1 +
 licenses/inlong-sort/NOTICE                        |   8 ++
 pom.xml                                            |  11 +-
 12 files changed, 539 insertions(+), 6 deletions(-)

diff --git 
a/inlong-sort/sort-common/src/main/java/org/apache/inlong/sort/protocol/BuiltInFieldInfo.java
 
b/inlong-sort/sort-common/src/main/java/org/apache/inlong/sort/protocol/BuiltInFieldInfo.java
index 81568a8ca..56d728a15 100644
--- 
a/inlong-sort/sort-common/src/main/java/org/apache/inlong/sort/protocol/BuiltInFieldInfo.java
+++ 
b/inlong-sort/sort-common/src/main/java/org/apache/inlong/sort/protocol/BuiltInFieldInfo.java
@@ -74,6 +74,7 @@ public class BuiltInFieldInfo extends FieldInfo {
         /**
          * The event time of flink
          */
+        @Deprecated
         DATA_TIME,
         /**
          * The process time of flink
@@ -81,23 +82,63 @@ public class BuiltInFieldInfo extends FieldInfo {
         PROCESS_TIME,
         /**
          * The name of the database containing this Row
+         * It is deprecated and can be replaced by ${@link 
BuiltInField#DATABASE_NAME}
+         * and will be removed in a future version.
          */
+        @Deprecated
         MYSQL_METADATA_DATABASE,
         /**
          * The name of the table containing this Row
+         * It is deprecated and can be replaced by ${@link 
BuiltInField#TABLE_NAME}
+         * and will be removed in a future version.
          */
+        @Deprecated
         MYSQL_METADATA_TABLE,
         /**
-         * The time when the Row made changes in the database
+         * The time when the Row made changes in the database.
+         * It is deprecated and can be replaced by ${@link BuiltInField#OP_TS}
+         * and will be removed in a future version.
          */
+        @Deprecated
         MYSQL_METADATA_EVENT_TIME,
+        /**
+         * Name of the schema that contain the row.
+         */
+        SCHEMA_NAME,
+        /**
+         * Name of the database that contain the row.
+         */
+        DATABASE_NAME,
+        /**
+         * Name of the table that contain the row.
+         */
+        TABLE_NAME,
+        /**
+         * It indicates the time that the change was made in the database.
+         * If the record is read from snapshot of the table instead of the 
change stream, the value is always 0
+         */
+        OP_TS,
+        /**
+         * Whether the DDL statement
+         */
+        IS_DDL,
         /**
          * Whether the DDL statement
+         * It is deprecated and can be replaced by ${@link BuiltInField#IS_DDL}
+         * and will be removed in a future version.
          */
+        @Deprecated
         MYSQL_METADATA_IS_DDL,
         /**
          * Type of database operation, such as INSERT/DELETE, etc.
          */
+        OP_TYPE,
+        /**
+         * Type of database operation, such as INSERT/DELETE, etc.
+         * It is deprecated and can be replaced by ${@link 
BuiltInField#OP_TYPE}
+         * and will be removed in a future version.
+         */
+        @Deprecated
         MYSQL_METADATA_EVENT_TYPE,
         /**
          * MySQL binlog data Row
diff --git 
a/inlong-sort/sort-common/src/main/java/org/apache/inlong/sort/protocol/constant/OracleConstant.java
 
b/inlong-sort/sort-common/src/main/java/org/apache/inlong/sort/protocol/constant/OracleConstant.java
new file mode 100644
index 000000000..f8143e9ba
--- /dev/null
+++ 
b/inlong-sort/sort-common/src/main/java/org/apache/inlong/sort/protocol/constant/OracleConstant.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.inlong.sort.protocol.constant;
+
+import lombok.Getter;
+
+/**
+ * Oracle options constant
+ */
+public class OracleConstant {
+
+    /**
+     * The key of flink connector defined in flink table
+     */
+    public static final String CONNECTOR = "connector";
+    /**
+     * Specify what flink connector to use for extract data from Oracle 
database, here should be 'oracle-cdc'
+     */
+    public static final String ORACLE_CDC = "oracle-cdc";
+    /**
+     * Database name of the Oracle server to monitor
+     */
+    public static final String DATABASE_NAME = "database-name";
+    /**
+     * IP address or hostname of the Oracle database server
+     */
+    public static final String HOSTNAME = "hostname";
+    /**
+     * Integer port number of the Oracle database server.
+     */
+    public static final String PORT = "port";
+    /**
+     * Name of the Oracle database to use when connecting to the Oracle 
database server
+     */
+    public static final String USERNAME = "username";
+    /**
+     * Password to use when connecting to the Oracle database server
+     */
+    public static final String PASSWORD = "password";
+    /**
+     * Table name of the Oracle database to monitor
+     */
+    public static final String TABLE_NAME = "table-name";
+    /**
+     * Schema name of the Oracle database to monitor
+     */
+    public static final String SCHEMA_NAME = "schema-name";
+    /**
+     * <p>The mining strategy controls how Oracle LogMiner builds
+     * and uses a given data dictionary for resolving table and column ids to 
names.</p>
+     * <p>redo_log_catalog - Writes the data dictionary to the online redo logs
+     * causing more archive logs to be generated over time.
+     * This also enables tracking DDL changes against captured tables,
+     * so if the schema changes frequently this is the ideal choice.</p>
+     * <p>online_catalog - Uses the database’s current data dictionary to 
resolve object ids
+     * and does not write any extra information to the online redo logs.
+     * This allows LogMiner to mine substantially faster but at the expense 
that DDL changes cannot be tracked.
+     * If the captured table(s) schema changes infrequently or never, this is 
the ideal choice.</p>
+     */
+    public static final String LOG_MINING_STRATEGY = 
"debezium.log.mining.strategy";
+    /**
+     * If true,CONTINUOUS_MINE option will be added to the log mining session.
+     * This will manage log files switches seamlessly.
+     */
+    public static final String LOG_MINING_CONTINUOUS_MINE = 
"debezium.log.mining.continuous.mine";
+    /**
+     * Deprecated: Case insensitive table names;set to 'true' for Oracle 
11g,'false'(default) otherwise.
+     */
+    public static final String TABLENAME_CASE_INSENSITIVE = 
"debezium.database.tablename.case.insensitive";
+    /**
+     * The key of ${@link ScanStartUpMode}
+     */
+    public static final String SCAN_STARTUP_MODE = "scan.startup.mode";
+
+    /**
+     * Optional startup mode for Oracle CDC consumer,
+     * valid enumerations are "initial" and "latest-offset".
+     * Please see Startup Reading Positionsection for more detailed 
information.
+     */
+    @Getter
+    public enum ScanStartUpMode {
+        /**
+         * Performs an initial snapshot on the monitored database tables upon 
first startup,
+         * and continue to read the latest binlog.
+         */
+        INITIAL("initial"),
+        /**
+         * Never to perform a snapshot on the monitored database tables upon 
first startup,
+         * just read from the change since the connector was started.
+         */
+        LATEST_OFFSET("latest-offset");
+
+        final String value;
+
+        ScanStartUpMode(String value) {
+            this.value = value;
+        }
+    }
+
+}
diff --git 
a/inlong-sort/sort-common/src/main/java/org/apache/inlong/sort/protocol/node/ExtractNode.java
 
b/inlong-sort/sort-common/src/main/java/org/apache/inlong/sort/protocol/node/ExtractNode.java
index 86f5b4d0c..6fa212564 100644
--- 
a/inlong-sort/sort-common/src/main/java/org/apache/inlong/sort/protocol/node/ExtractNode.java
+++ 
b/inlong-sort/sort-common/src/main/java/org/apache/inlong/sort/protocol/node/ExtractNode.java
@@ -31,6 +31,7 @@ import 
org.apache.inlong.sort.protocol.node.extract.FileSystemExtractNode;
 import org.apache.inlong.sort.protocol.node.extract.KafkaExtractNode;
 import org.apache.inlong.sort.protocol.node.extract.MongoExtractNode;
 import org.apache.inlong.sort.protocol.node.extract.MySqlExtractNode;
+import org.apache.inlong.sort.protocol.node.extract.OracleExtractNode;
 import org.apache.inlong.sort.protocol.node.extract.PostgresExtractNode;
 import org.apache.inlong.sort.protocol.node.extract.SqlServerExtractNode;
 import org.apache.inlong.sort.protocol.transformation.WatermarkField;
@@ -51,8 +52,9 @@ import java.util.Map;
         @JsonSubTypes.Type(value = KafkaExtractNode.class, name = 
"kafkaExtract"),
         @JsonSubTypes.Type(value = PostgresExtractNode.class, name = 
"postgresExtract"),
         @JsonSubTypes.Type(value = FileSystemExtractNode.class, name = 
"fileSystemExtract"),
-        @JsonSubTypes.Type(value = MongoExtractNode.class, name = 
"MongoExtract"),
+        @JsonSubTypes.Type(value = MongoExtractNode.class, name = 
"mongoExtract"),
         @JsonSubTypes.Type(value = SqlServerExtractNode.class, name = 
"sqlserverExtract"),
+        @JsonSubTypes.Type(value = OracleExtractNode.class, name = 
"oracleExtract")
 })
 @Data
 @NoArgsConstructor
diff --git 
a/inlong-sort/sort-common/src/main/java/org/apache/inlong/sort/protocol/node/Node.java
 
b/inlong-sort/sort-common/src/main/java/org/apache/inlong/sort/protocol/node/Node.java
index bdd6cddca..99363bc2a 100644
--- 
a/inlong-sort/sort-common/src/main/java/org/apache/inlong/sort/protocol/node/Node.java
+++ 
b/inlong-sort/sort-common/src/main/java/org/apache/inlong/sort/protocol/node/Node.java
@@ -26,6 +26,7 @@ import 
org.apache.inlong.sort.protocol.node.extract.FileSystemExtractNode;
 import org.apache.inlong.sort.protocol.node.extract.KafkaExtractNode;
 import org.apache.inlong.sort.protocol.node.extract.MongoExtractNode;
 import org.apache.inlong.sort.protocol.node.extract.MySqlExtractNode;
+import org.apache.inlong.sort.protocol.node.extract.OracleExtractNode;
 import org.apache.inlong.sort.protocol.node.extract.PostgresExtractNode;
 import org.apache.inlong.sort.protocol.node.load.ClickHouseLoadNode;
 import org.apache.inlong.sort.protocol.node.extract.PulsarExtractNode;
@@ -39,6 +40,7 @@ import 
org.apache.inlong.sort.protocol.node.load.SqlServerLoadNode;
 import org.apache.inlong.sort.protocol.node.transform.DistinctNode;
 import org.apache.inlong.sort.protocol.node.transform.TransformNode;
 
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.TreeMap;
@@ -58,9 +60,10 @@ import java.util.TreeMap;
         @JsonSubTypes.Type(value = SqlServerExtractNode.class, name = 
"sqlserverExtract"),
         @JsonSubTypes.Type(value = PulsarExtractNode.class, name = 
"pulsarExtract"),
         @JsonSubTypes.Type(value = MongoExtractNode.class, name = 
"mongoExtract"),
+        @JsonSubTypes.Type(value = OracleExtractNode.class, name = 
"oracleExtract"),
         @JsonSubTypes.Type(value = TransformNode.class, name = 
"baseTransform"),
-        @JsonSubTypes.Type(value = KafkaLoadNode.class, name = "kafkaLoad"),
         @JsonSubTypes.Type(value = DistinctNode.class, name = "distinct"),
+        @JsonSubTypes.Type(value = KafkaLoadNode.class, name = "kafkaLoad"),
         @JsonSubTypes.Type(value = HiveLoadNode.class, name = "hiveLoad"),
         @JsonSubTypes.Type(value = HbaseLoadNode.class, name = "hbaseLoad"),
         @JsonSubTypes.Type(value = PostgresLoadNode.class, name = 
"postgresLoad"),
@@ -84,7 +87,7 @@ public interface Node {
 
     @JsonInclude(Include.NON_NULL)
     default Map<String, String> tableOptions() {
-        Map<String, String> options = new TreeMap<>();
+        Map<String, String> options = new LinkedHashMap<>();
         if (getProperties() != null && !getProperties().isEmpty()) {
             options.putAll(getProperties());
         }
diff --git 
a/inlong-sort/sort-common/src/main/java/org/apache/inlong/sort/protocol/node/extract/OracleExtractNode.java
 
b/inlong-sort/sort-common/src/main/java/org/apache/inlong/sort/protocol/node/extract/OracleExtractNode.java
new file mode 100644
index 000000000..6b9a59ee3
--- /dev/null
+++ 
b/inlong-sort/sort-common/src/main/java/org/apache/inlong/sort/protocol/node/extract/OracleExtractNode.java
@@ -0,0 +1,139 @@
+/*
+ * 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.inlong.sort.protocol.node.extract;
+
+import com.google.common.base.Preconditions;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import 
org.apache.flink.shaded.jackson2.com.fasterxml.jackson.annotation.JsonCreator;
+import 
org.apache.flink.shaded.jackson2.com.fasterxml.jackson.annotation.JsonInclude;
+import 
org.apache.flink.shaded.jackson2.com.fasterxml.jackson.annotation.JsonProperty;
+import 
org.apache.flink.shaded.jackson2.com.fasterxml.jackson.annotation.JsonTypeName;
+import org.apache.inlong.sort.protocol.FieldInfo;
+import org.apache.inlong.sort.protocol.constant.OracleConstant;
+import org.apache.inlong.sort.protocol.node.ExtractNode;
+import org.apache.inlong.sort.protocol.transformation.WatermarkField;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import java.io.Serializable;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Oracle extract node for extract data from oracle(Currently support oracle 
11,12,19)
+ */
+@EqualsAndHashCode(callSuper = true)
+@JsonTypeName("oracleExtract")
+@Data
+public class OracleExtractNode extends ExtractNode implements Serializable {
+
+    @JsonInclude(JsonInclude.Include.NON_NULL)
+    @Nullable
+    @JsonProperty("primaryKey")
+    private String primaryKey;
+    @Nonnull
+    @JsonProperty("hostname")
+    private String hostname;
+    @Nonnull
+    @JsonProperty("username")
+    private String username;
+    @Nonnull
+    @JsonProperty("password")
+    private String password;
+    @Nonnull
+    @JsonProperty("database")
+    private String database;
+    @Nonnull
+    @JsonProperty("schemaName")
+    private String schemaName;
+    @Nonnull
+    @JsonProperty("tableName")
+    private String tableName;
+    @JsonProperty(value = "port", defaultValue = "1521")
+    private Integer port;
+    @Nullable
+    @JsonProperty("scanStartupMode")
+    @JsonInclude(JsonInclude.Include.NON_NULL)
+    private OracleConstant.ScanStartUpMode scanStartupMode;
+
+    @JsonCreator
+    public OracleExtractNode(@JsonProperty("id") String id,
+                             @JsonProperty("name") String name,
+                             @JsonProperty("fields") List<FieldInfo> fields,
+                             @Nullable @JsonProperty("watermark_field") 
WatermarkField watermarkField,
+                             @JsonProperty("properties") Map<String, String> 
properties,
+                             @Nullable @JsonProperty("primaryKey") String 
primaryKey,
+                             @JsonProperty("hostname") String hostname,
+                             @JsonProperty("username") String username,
+                             @JsonProperty("password") String password,
+                             @JsonProperty("database") String database,
+                             @JsonProperty("schemaName") String schemaName,
+                             @JsonProperty("tableName") String tableName,
+                             @JsonProperty(value = "port", defaultValue = 
"1521") Integer port,
+                             @Nullable @JsonProperty("scanStartupMode")
+                             OracleConstant.ScanStartUpMode scanStartupMode) {
+        super(id, name, fields, watermarkField, properties);
+        this.primaryKey = primaryKey;
+        this.hostname = Preconditions.checkNotNull(hostname, "hostname is 
null");
+        this.username = Preconditions.checkNotNull(username, "username is 
null");
+        this.password = Preconditions.checkNotNull(password, "password is 
null");
+        this.database = Preconditions.checkNotNull(database, "database is 
null");
+        this.schemaName = Preconditions.checkNotNull(schemaName, "schemaName 
is null");
+        this.tableName = Preconditions.checkNotNull(tableName, "tableName is 
null");
+        this.port = port;
+        this.scanStartupMode = scanStartupMode;
+    }
+
+    @Override
+    public Map<String, String> tableOptions() {
+        Map<String, String> options = super.tableOptions();
+        options.put(OracleConstant.CONNECTOR, OracleConstant.ORACLE_CDC);
+        options.put(OracleConstant.HOSTNAME, hostname);
+        options.put(OracleConstant.USERNAME, username);
+        options.put(OracleConstant.PASSWORD, password);
+        options.put(OracleConstant.DATABASE_NAME, database);
+        options.put(OracleConstant.SCHEMA_NAME, schemaName);
+        options.put(OracleConstant.TABLE_NAME, tableName);
+        if (!options.containsKey(OracleConstant.TABLENAME_CASE_INSENSITIVE)) {
+            // Set a default value:false to avoid retrieving unlisted tables 
in oracle 11g.
+            // You can set null to replace it if your oracle version is more 
than oracle 11g.
+            options.put(OracleConstant.TABLENAME_CASE_INSENSITIVE, "false");
+        }
+        if (!options.containsKey(OracleConstant.LOG_MINING_STRATEGY)) {
+            // Set a default value:online_catalog to improve performance and 
reduce latency
+            options.put(OracleConstant.LOG_MINING_STRATEGY, "online_catalog");
+        }
+        if (!options.containsKey(OracleConstant.LOG_MINING_CONTINUOUS_MINE)) {
+            // Set a default value:true to improve performance and reduce 
latency
+            options.put(OracleConstant.LOG_MINING_CONTINUOUS_MINE, "true");
+        }
+        if (port != null) {
+            options.put(OracleConstant.PORT, port.toString());
+        }
+        if (scanStartupMode != null) {
+            options.put(OracleConstant.SCAN_STARTUP_MODE, 
scanStartupMode.getValue());
+        }
+        return options;
+    }
+
+    @Override
+    public String genTableName() {
+        return String.format("node_%s", super.getId());
+    }
+}
diff --git 
a/inlong-sort/sort-common/src/test/java/org/apache/inlong/sort/protocol/node/extract/OracleExtractNodeTest.java
 
b/inlong-sort/sort-common/src/test/java/org/apache/inlong/sort/protocol/node/extract/OracleExtractNodeTest.java
new file mode 100644
index 000000000..cc80e8e94
--- /dev/null
+++ 
b/inlong-sort/sort-common/src/test/java/org/apache/inlong/sort/protocol/node/extract/OracleExtractNodeTest.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.inlong.sort.protocol.node.extract;
+
+import org.apache.inlong.sort.SerializeBaseTest;
+import org.apache.inlong.sort.formats.common.IntFormatInfo;
+import org.apache.inlong.sort.formats.common.StringFormatInfo;
+import org.apache.inlong.sort.protocol.FieldInfo;
+import org.apache.inlong.sort.protocol.node.Node;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Test for {@link OracleExtractNode}
+ */
+public class OracleExtractNodeTest extends SerializeBaseTest<Node> {
+
+    @Override
+    public Node getTestObject() {
+        List<FieldInfo> fields = Arrays.asList(
+                new FieldInfo("NAME", new StringFormatInfo()),
+                new FieldInfo("AGE", new IntFormatInfo()));
+        return new OracleExtractNode("1", "oracle_input", fields,
+                null, null, "id", "localhost",
+                "username", "password", "database", "schema_name",
+                "table_name", null, null);
+    }
+}
diff --git a/inlong-sort/sort-connectors/pom.xml 
b/inlong-sort/sort-connectors/pom.xml
index de116b316..64103e7bb 100644
--- a/inlong-sort/sort-connectors/pom.xml
+++ b/inlong-sort/sort-connectors/pom.xml
@@ -108,6 +108,11 @@
             <groupId>com.ververica</groupId>
             <artifactId>flink-connector-mongodb-cdc</artifactId>
         </dependency>
+        <!--for oracle-->
+        <dependency>
+            <groupId>com.ververica</groupId>
+            <artifactId>flink-connector-oracle-cdc</artifactId>
+        </dependency>
         <!--for debezium-->
         <dependency>
             <groupId>io.debezium</groupId>
diff --git 
a/inlong-sort/sort-core/src/main/java/org/apache/inlong/sort/parser/impl/FlinkSqlParser.java
 
b/inlong-sort/sort-core/src/main/java/org/apache/inlong/sort/parser/impl/FlinkSqlParser.java
index 6c151d9fa..396b4cc90 100644
--- 
a/inlong-sort/sort-core/src/main/java/org/apache/inlong/sort/parser/impl/FlinkSqlParser.java
+++ 
b/inlong-sort/sort-core/src/main/java/org/apache/inlong/sort/parser/impl/FlinkSqlParser.java
@@ -36,6 +36,7 @@ import org.apache.inlong.sort.protocol.node.LoadNode;
 import org.apache.inlong.sort.protocol.node.Node;
 import org.apache.inlong.sort.protocol.node.extract.KafkaExtractNode;
 import org.apache.inlong.sort.protocol.node.extract.MySqlExtractNode;
+import org.apache.inlong.sort.protocol.node.extract.OracleExtractNode;
 import org.apache.inlong.sort.protocol.node.load.HbaseLoadNode;
 import org.apache.inlong.sort.protocol.node.load.KafkaLoadNode;
 import org.apache.inlong.sort.protocol.node.transform.DistinctNode;
@@ -686,6 +687,8 @@ public class FlinkSqlParser implements Parser {
         }
         if (node instanceof MySqlExtractNode) {
             sb.append(parseMySqlExtractNodeMetaField(metaField));
+        } else if (node instanceof OracleExtractNode) {
+            sb.append(parseOracleExtractNodeMetaField(metaField));
         } else if (node instanceof KafkaExtractNode) {
             sb.append(parseKafkaExtractNodeMetaField(metaField));
         } else if (node instanceof KafkaLoadNode) {
@@ -701,21 +704,26 @@ public class FlinkSqlParser implements Parser {
         String metaType;
         switch (metaField.getBuiltInField()) {
             case MYSQL_METADATA_TABLE:
+            case TABLE_NAME:
                 metaType = "STRING METADATA FROM 'value.table'";
                 break;
             case MYSQL_METADATA_DATABASE:
+            case DATABASE_NAME:
                 metaType = "STRING METADATA FROM 'value.database'";
                 break;
             case MYSQL_METADATA_EVENT_TIME:
+            case OP_TS:
                 metaType = "TIMESTAMP(3) METADATA FROM 
'value.event-timestamp'";
                 break;
             case MYSQL_METADATA_EVENT_TYPE:
+            case OP_TYPE:
                 metaType = "STRING METADATA FROM 'value.op-type'";
                 break;
             case MYSQL_METADATA_DATA:
                 metaType = "STRING METADATA FROM 'value.data'";
                 break;
             case MYSQL_METADATA_IS_DDL:
+            case IS_DDL:
                 metaType = "BOOLEAN METADATA FROM 'value.is-ddl'";
                 break;
             case METADATA_TS:
@@ -746,9 +754,11 @@ public class FlinkSqlParser implements Parser {
         String metaType;
         switch (metaField.getBuiltInField()) {
             case MYSQL_METADATA_TABLE:
+            case TABLE_NAME:
                 metaType = "STRING METADATA FROM 'value.table'";
                 break;
             case MYSQL_METADATA_DATABASE:
+            case DATABASE_NAME:
                 metaType = "STRING METADATA FROM 'value.database'";
                 break;
             case METADATA_SQL_TYPE:
@@ -761,13 +771,16 @@ public class FlinkSqlParser implements Parser {
                 metaType = "TIMESTAMP_LTZ(3) METADATA FROM 
'value.ingestion-timestamp'";
                 break;
             case MYSQL_METADATA_EVENT_TIME:
+            case OP_TS:
                 metaType = "TIMESTAMP_LTZ(3) METADATA FROM 
'value.event-timestamp'";
                 break;
             // additional metadata
             case MYSQL_METADATA_EVENT_TYPE:
+            case OP_TYPE:
                 metaType = "STRING METADATA FROM 'value.op-type'";
                 break;
             case MYSQL_METADATA_IS_DDL:
+            case IS_DDL:
                 metaType = "BOOLEAN METADATA FROM 'value.is-ddl'";
                 break;
             case METADATA_MYSQL_TYPE:
@@ -789,21 +802,26 @@ public class FlinkSqlParser implements Parser {
         String metaType;
         switch (metaField.getBuiltInField()) {
             case MYSQL_METADATA_TABLE:
+            case TABLE_NAME:
                 metaType = "STRING METADATA FROM 'meta.table_name' VIRTUAL";
                 break;
             case MYSQL_METADATA_DATABASE:
+            case DATABASE_NAME:
                 metaType = "STRING METADATA FROM 'meta.database_name' VIRTUAL";
                 break;
             case MYSQL_METADATA_EVENT_TIME:
+            case OP_TS:
                 metaType = "TIMESTAMP(3) METADATA FROM 'meta.op_ts' VIRTUAL";
                 break;
             case MYSQL_METADATA_EVENT_TYPE:
+            case OP_TYPE:
                 metaType = "STRING METADATA FROM 'meta.op_type' VIRTUAL";
                 break;
             case MYSQL_METADATA_DATA:
                 metaType = "STRING METADATA FROM 'meta.data' VIRTUAL";
                 break;
             case MYSQL_METADATA_IS_DDL:
+            case IS_DDL:
                 metaType = "BOOLEAN METADATA FROM 'meta.is_ddl' VIRTUAL";
                 break;
             case METADATA_TS:
@@ -830,6 +848,27 @@ public class FlinkSqlParser implements Parser {
         return metaType;
     }
 
+    private String parseOracleExtractNodeMetaField(BuiltInFieldInfo metaField) 
{
+        String metaType;
+        switch (metaField.getBuiltInField()) {
+            case TABLE_NAME:
+                metaType = "STRING METADATA FROM 'table_name' VIRTUAL";
+                break;
+            case SCHEMA_NAME:
+                metaType = "STRING METADATA FROM 'schema_name' VIRTUAL";
+                break;
+            case DATABASE_NAME:
+                metaType = "STRING METADATA FROM 'database_name' VIRTUAL";
+                break;
+            case OP_TS:
+                metaType = "TIMESTAMP_LTZ(3) METADATA FROM 'op_ts' VIRTUAL";
+                break;
+            default:
+                metaType = 
TableFormatUtils.deriveLogicalType(metaField.getFormatInfo()).asSummaryString();
+        }
+        return metaType;
+    }
+
     /**
      * Generate primary key format in sql
      *
diff --git 
a/inlong-sort/sort-core/src/test/java/org/apache/inlong/sort/parser/OracleExtractSqlParseTest.java
 
b/inlong-sort/sort-core/src/test/java/org/apache/inlong/sort/parser/OracleExtractSqlParseTest.java
new file mode 100644
index 000000000..c5106f6fb
--- /dev/null
+++ 
b/inlong-sort/sort-core/src/test/java/org/apache/inlong/sort/parser/OracleExtractSqlParseTest.java
@@ -0,0 +1,128 @@
+/*
+ *   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.inlong.sort.parser;
+
+import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
+import org.apache.flink.table.api.EnvironmentSettings;
+import org.apache.flink.table.api.bridge.java.StreamTableEnvironment;
+import org.apache.flink.test.util.AbstractTestBase;
+import org.apache.inlong.sort.formats.common.IntFormatInfo;
+import org.apache.inlong.sort.formats.common.LongFormatInfo;
+import org.apache.inlong.sort.formats.common.StringFormatInfo;
+import org.apache.inlong.sort.parser.impl.FlinkSqlParser;
+import org.apache.inlong.sort.parser.result.ParseResult;
+import org.apache.inlong.sort.protocol.FieldInfo;
+import org.apache.inlong.sort.protocol.GroupInfo;
+import org.apache.inlong.sort.protocol.StreamInfo;
+import org.apache.inlong.sort.protocol.node.Node;
+import org.apache.inlong.sort.protocol.node.extract.OracleExtractNode;
+import org.apache.inlong.sort.protocol.node.format.CanalJsonFormat;
+import org.apache.inlong.sort.protocol.node.load.KafkaLoadNode;
+import org.apache.inlong.sort.protocol.transformation.FieldRelationShip;
+import 
org.apache.inlong.sort.protocol.transformation.relation.NodeRelationShip;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * Test for {@link OracleExtractNode}
+ */
+public class OracleExtractSqlParseTest extends AbstractTestBase {
+
+    /**
+     * Build oracle extract node
+     *
+     * @return The oracle extract node
+     */
+    private OracleExtractNode buildOracleExtractNode() {
+        List<FieldInfo> fields = Arrays.asList(
+                new FieldInfo("ID", new LongFormatInfo()),
+                new FieldInfo("NAME", new StringFormatInfo()),
+                new FieldInfo("AGE", new IntFormatInfo()));
+        return new OracleExtractNode("1", "oracle_input", fields,
+                null, null, "ID", "localhost",
+                "flinkuser", "flinkpw", "xE",
+                "flinkuser", "table", 1521, null);
+    }
+
+    private Node buildKafkaLoadNode() {
+        List<FieldInfo> fields = Arrays.asList(new FieldInfo("id", new 
LongFormatInfo()),
+                new FieldInfo("name", new StringFormatInfo()),
+                new FieldInfo("age", new IntFormatInfo())
+        );
+        List<FieldRelationShip> relations = Arrays
+                .asList(new FieldRelationShip(new FieldInfo("ID", new 
LongFormatInfo()),
+                                new FieldInfo("id", new LongFormatInfo())),
+                        new FieldRelationShip(new FieldInfo("NAME", new 
StringFormatInfo()),
+                                new FieldInfo("name", new StringFormatInfo())),
+                        new FieldRelationShip(new FieldInfo("AGE", new 
IntFormatInfo()),
+                                new FieldInfo("age", new IntFormatInfo()))
+                );
+        return new KafkaLoadNode("2", "kafka_output", fields, relations, null,
+                null, "topic", "localhost:9092",
+                new CanalJsonFormat(), null,
+                null, null);
+    }
+
+    /**
+     * Build node relation
+     *
+     * @param inputs  extract node
+     * @param outputs load node
+     * @return node relation
+     */
+    private NodeRelationShip buildNodeRelation(List<Node> inputs, List<Node> 
outputs) {
+        List<String> inputIds = 
inputs.stream().map(Node::getId).collect(Collectors.toList());
+        List<String> outputIds = 
outputs.stream().map(Node::getId).collect(Collectors.toList());
+        return new NodeRelationShip(inputIds, outputIds);
+    }
+
+    /**
+     * Test flink sql task for extract is oracle {@link OracleExtractNode} and 
load is kafka {@link KafkaLoadNode}
+     *
+     * @throws Exception The exception may be thrown when executing
+     */
+    @Test
+    public void testOracleExtractSqlParse() throws Exception {
+        StreamExecutionEnvironment env = 
StreamExecutionEnvironment.getExecutionEnvironment();
+        env.setParallelism(1);
+        env.enableCheckpointing(60000);
+        env.disableOperatorChaining();
+        EnvironmentSettings settings = EnvironmentSettings
+                .newInstance()
+                .useBlinkPlanner()
+                .inStreamingMode()
+                .build();
+        StreamTableEnvironment tableEnv = StreamTableEnvironment.create(env, 
settings);
+        Node inputNode = buildOracleExtractNode();
+        Node outputNode = buildKafkaLoadNode();
+        StreamInfo streamInfo = new StreamInfo("1", Arrays.asList(inputNode, 
outputNode),
+                
Collections.singletonList(buildNodeRelation(Collections.singletonList(inputNode),
+                        Collections.singletonList(outputNode))));
+        GroupInfo groupInfo = new GroupInfo("1", 
Collections.singletonList(streamInfo));
+        FlinkSqlParser parser = FlinkSqlParser.getInstance(tableEnv, 
groupInfo);
+        ParseResult result = parser.parse();
+        Assert.assertTrue(result.tryExecute());
+    }
+
+}
diff --git a/licenses/inlong-sort/LICENSE b/licenses/inlong-sort/LICENSE
index 212ca0872..8a79d118c 100644
--- a/licenses/inlong-sort/LICENSE
+++ b/licenses/inlong-sort/LICENSE
@@ -688,6 +688,7 @@ The text of each license is also included at 
licenses/LICENSE-[project].txt.
   org.eclipse.jetty:apache-jstl:9.3.20.v20170531 - Apache :: JSTL module 
(https://github.com/eclipse/jetty.project/tree/jetty-9.3.20.v20170531/apache-jstl),
 (Apache Software License - Version 2.0;  Eclipse Public License - Version 1.0)
   com.ververica:flink-connector-mysql-cdc:2.2.1 - flink-connector-mysql-cdc 
(https://github.com/ververica/flink-cdc-connectors/tree/master/flink-sql-connector-mysql-cdc/),
 (The Apache Software License, Version 2.0)
   com.ververica:flink-connector-mongodb-cdc:2.2.1 - 
flink-connector-mongodb-cdc 
(https://github.com/ververica/flink-cdc-connectors/tree/master/flink-connector-mongodb-cdc/),
 (The Apache Software License, Version 2.0)
+  com.ververica:flink-connector-oracle-cdc:2.2.1 - flink-connector-oracle-cdc 
(https://github.com/ververica/flink-cdc-connectors/tree/master/flink-connector-oracle-cdc/),
 (The Apache Software License, Version 2.0)
   com.ververica:flink-connector-postgres-cdc:2.2.1 - 
flink-connector-postgres-cdc 
(https://github.com/ververica/flink-cdc-connectors/tree/master/flink-sql-connector-postgres-cdc/),
 (The Apache Software License, Version 2.0)
   com.ververica:flink-connector-sqlserver-cdc:2.2.1 - 
flink-connector-sqlserver-cdc 
(https://github.com/ververica/flink-cdc-connectors/tree/master/flink-connector-sqlserver-cdc/),
  (The Apache Software License, Version 2.0)
   org.apache.hadoop:hadoop-annotations:2.10.1 - Apache Hadoop Annotations 
(https://github.com/apache/hadoop/tree/branch-2.10.1/hadoop-common-project/hadoop-annotations),
 (Apache License, Version 2.0)
diff --git a/licenses/inlong-sort/NOTICE b/licenses/inlong-sort/NOTICE
index 9988bebcf..950360d52 100644
--- a/licenses/inlong-sort/NOTICE
+++ b/licenses/inlong-sort/NOTICE
@@ -616,6 +616,14 @@ This distribution has a binary dependency on jersey, which 
is available under th
 License. The source code of jersey can be found at 
https://github.com/jersey/jersey/.
 
 
+========================================================================
+
+flink-connector-oracle-cdc
+Copyright 2022 The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+
 
 ========================================================================
 
diff --git a/pom.xml b/pom.xml
index 557b63b05..2e972e676 100644
--- a/pom.xml
+++ b/pom.xml
@@ -17,8 +17,8 @@
     specific language governing permissions and limitations
     under the License.
 -->
-<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
-        xmlns="http://maven.apache.org/POM/4.0.0";
+<project xmlns="http://maven.apache.org/POM/4.0.0";
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
     <modelVersion>4.0.0</modelVersion>
     <packaging>pom</packaging>
@@ -202,6 +202,7 @@
         
<flink.connector.sqlserver.cdc.version>2.2.1</flink.connector.sqlserver.cdc.version>
         <flink.pulsar.version>1.13.6.1-rc9</flink.pulsar.version>
         
<flink.connector.mongodb.cdc.version>2.2.1</flink.connector.mongodb.cdc.version>
+        
<flink.connector.oracle.cdc.version>2.2.1</flink.connector.oracle.cdc.version>
         
<qcloud.flink.cos.fs.hadoop.version>1.10.0-0.1.10</qcloud.flink.cos.fs.hadoop.version>
         <qcloud.chdfs.version>2.5</qcloud.chdfs.version>
 
@@ -989,6 +990,12 @@
                 <version>${flink.connector.postgres.cdc.version}</version>
             </dependency>
 
+            <dependency>
+                <groupId>com.ververica</groupId>
+                <artifactId>flink-connector-oracle-cdc</artifactId>
+                <version>${flink.connector.oracle.cdc.version}</version>
+            </dependency>
+
             <dependency>
                 <groupId>com.ververica</groupId>
                 <artifactId>flink-connector-sqlserver-cdc</artifactId>

Reply via email to