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

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


The following commit(s) were added to refs/heads/master by this push:
     new 57e8dc3f5 [cdc] In schema building phase of mysql cdc, the connection 
should handle jdbc properties (#2507)
57e8dc3f5 is described below

commit 57e8dc3f51c66c22f419a5493bed22e5191283fd
Author: yuzelin <[email protected]>
AuthorDate: Thu Dec 14 15:50:13 2023 +0800

    [cdc] In schema building phase of mysql cdc, the connection should handle 
jdbc properties (#2507)
---
 .../flink/action/cdc/mysql/MySqlActionUtils.java   | 66 +++++++++++++++++-----
 .../action/cdc/mysql/MySqlSyncDatabaseAction.java  |  3 +-
 .../action/cdc/mysql/MySqlSyncTableAction.java     |  2 +-
 .../cdc/mysql/MySqlCdcTypeMappingITCase.java       | 29 ++++++++++
 4 files changed, 85 insertions(+), 15 deletions(-)

diff --git 
a/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/mysql/MySqlActionUtils.java
 
b/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/mysql/MySqlActionUtils.java
index b44291fc4..ba01acd36 100644
--- 
a/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/mysql/MySqlActionUtils.java
+++ 
b/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/mysql/MySqlActionUtils.java
@@ -51,6 +51,7 @@ import java.util.Properties;
 import java.util.function.Predicate;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
+import java.util.stream.Collectors;
 
 import static 
org.apache.paimon.flink.action.cdc.TypeMapping.TypeMappingMode.TINYINT1_NOT_BOOL;
 
@@ -66,17 +67,25 @@ public class MySqlActionUtils {
                     .withDescription(
                             "Whether capture the scan the newly added tables 
or not, by default is true.");
 
-    static Connection getConnection(Configuration mySqlConfig, boolean 
tinyint1NotBool)
+    static Connection getConnection(Configuration mySqlConfig, Map<String, 
String> jdbcProperties)
             throws Exception {
+        String paramString = "";
+        if (!jdbcProperties.isEmpty()) {
+            paramString =
+                    "?"
+                            + jdbcProperties.entrySet().stream()
+                                    .map(e -> e.getKey() + "=" + e.getValue())
+                                    .collect(Collectors.joining("&"));
+        }
+
         String url =
                 String.format(
                         "jdbc:mysql://%s:%d%s",
                         mySqlConfig.get(MySqlSourceOptions.HOSTNAME),
                         mySqlConfig.get(MySqlSourceOptions.PORT),
-                        // we need to add the `tinyInt1isBit` parameter to the 
connection url to
-                        // make sure the tinyint(1) in MySQL is converted to 
bits or not. Refer to
-                        // 
https://dev.mysql.com/doc/connector-j/8.0/en/connector-j-connp-props-result-sets.html#cj-conn-prop_tinyInt1isBit
-                        tinyint1NotBool ? "?tinyInt1isBit=false" : "");
+                        paramString);
+
+        LOG.info("Connect to MySQL server using url: {}", url);
 
         return DriverManager.getConnection(
                 url,
@@ -93,9 +102,9 @@ public class MySqlActionUtils {
         Pattern databasePattern =
                 
Pattern.compile(mySqlConfig.get(MySqlSourceOptions.DATABASE_NAME));
         MySqlSchemasInfo mySqlSchemasInfo = new MySqlSchemasInfo();
-        try (Connection conn =
-                MySqlActionUtils.getConnection(
-                        mySqlConfig, 
typeMapping.containsMode(TINYINT1_NOT_BOOL))) {
+        Map<String, String> jdbcProperties = getJdbcProperties(typeMapping, 
mySqlConfig);
+
+        try (Connection conn = MySqlActionUtils.getConnection(mySqlConfig, 
jdbcProperties)) {
             DatabaseMetaData metaData = conn.getMetaData();
             try (ResultSet schemas = metaData.getCatalogs()) {
                 while (schemas.next()) {
@@ -129,7 +138,7 @@ public class MySqlActionUtils {
     }
 
     public static MySqlSource<String> buildMySqlSource(
-            Configuration mySqlConfig, String tableList) {
+            Configuration mySqlConfig, String tableList, TypeMapping 
typeMapping) {
         MySqlSourceBuilder<String> sourceBuilder = MySqlSource.builder();
 
         sourceBuilder
@@ -195,18 +204,18 @@ public class MySqlActionUtils {
         }
 
         Properties jdbcProperties = new Properties();
+        jdbcProperties.putAll(getJdbcProperties(typeMapping, mySqlConfig));
+        sourceBuilder.jdbcProperties(jdbcProperties);
+
         Properties debeziumProperties = new Properties();
         for (Map.Entry<String, String> entry : mySqlConfig.toMap().entrySet()) 
{
             String key = entry.getKey();
             String value = entry.getValue();
-            if (key.startsWith(JdbcUrlUtils.PROPERTIES_PREFIX)) {
-                
jdbcProperties.put(key.substring(JdbcUrlUtils.PROPERTIES_PREFIX.length()), 
value);
-            } else if 
(key.startsWith(DebeziumOptions.DEBEZIUM_OPTIONS_PREFIX)) {
+            if (key.startsWith(DebeziumOptions.DEBEZIUM_OPTIONS_PREFIX)) {
                 debeziumProperties.put(
                         
key.substring(DebeziumOptions.DEBEZIUM_OPTIONS_PREFIX.length()), value);
             }
         }
-        sourceBuilder.jdbcProperties(jdbcProperties);
         sourceBuilder.debeziumProperties(debeziumProperties);
 
         Map<String, Object> customConverterConfigs = new HashMap<>();
@@ -223,6 +232,37 @@ public class MySqlActionUtils {
                 .build();
     }
 
+    // see
+    // 
https://ververica.github.io/flink-cdc-connectors/master/content/connectors/mysql-cdc.html#connector-options
+    // 
https://dev.mysql.com/doc/connectors/en/connector-j-reference-configuration-properties.html
+    private static Map<String, String> getJdbcProperties(
+            TypeMapping typeMapping, Configuration mySqlConfig) {
+        Map<String, String> jdbcProperties =
+                mySqlConfig.toMap().entrySet().stream()
+                        .filter(e -> 
e.getKey().startsWith(JdbcUrlUtils.PROPERTIES_PREFIX))
+                        .collect(
+                                Collectors.toMap(
+                                        e ->
+                                                e.getKey()
+                                                        .substring(
+                                                                
JdbcUrlUtils.PROPERTIES_PREFIX
+                                                                        
.length()),
+                                        Map.Entry::getValue));
+
+        if (typeMapping.containsMode(TINYINT1_NOT_BOOL)) {
+            String tinyInt1isBit = jdbcProperties.get("tinyInt1isBit");
+            if (tinyInt1isBit == null) {
+                jdbcProperties.put("tinyInt1isBit", "false");
+            } else if ("true".equals(jdbcProperties.get("tinyInt1isBit"))) {
+                throw new IllegalArgumentException(
+                        "Type mapping option 'tinyint1-not-bool' conflicts 
with jdbc properties 'jdbc.properties.tinyInt1isBit=true'. "
+                                + "Option 'tinyint1-not-bool' is equal to 
'jdbc.properties.tinyInt1isBit=false'.");
+            }
+        }
+
+        return jdbcProperties;
+    }
+
     public static void registerJdbcDriver() {
         try {
             Class.forName("com.mysql.cj.jdbc.Driver");
diff --git 
a/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/mysql/MySqlSyncDatabaseAction.java
 
b/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/mysql/MySqlSyncDatabaseAction.java
index ca7678b41..c469f6d1d 100644
--- 
a/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/mysql/MySqlSyncDatabaseAction.java
+++ 
b/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/mysql/MySqlSyncDatabaseAction.java
@@ -194,7 +194,8 @@ public class MySqlSyncDatabaseAction extends 
SyncDatabaseActionBase {
                         cdcSourceConfig.get(MySqlSourceOptions.DATABASE_NAME),
                         includingTables,
                         monitoredTables,
-                        excludedTables));
+                        excludedTables),
+                typeMapping);
     }
 
     private void logNonPkTables(List<Identifier> nonPkTables) {
diff --git 
a/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/mysql/MySqlSyncTableAction.java
 
b/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/mysql/MySqlSyncTableAction.java
index f8551a48b..9bf18308a 100644
--- 
a/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/mysql/MySqlSyncTableAction.java
+++ 
b/paimon-flink/paimon-flink-cdc/src/main/java/org/apache/paimon/flink/action/cdc/mysql/MySqlSyncTableAction.java
@@ -111,7 +111,7 @@ public class MySqlSyncTableAction extends 
SyncTableActionBase {
                 mySqlSchemasInfo.pkTables().stream()
                         .map(i -> i.getDatabaseName() + "\\." + 
i.getObjectName())
                         .collect(Collectors.joining("|"));
-        return MySqlActionUtils.buildMySqlSource(cdcSourceConfig, tableList);
+        return MySqlActionUtils.buildMySqlSource(cdcSourceConfig, tableList, 
typeMapping);
     }
 
     private void validateMySqlTableInfos(MySqlSchemasInfo mySqlSchemasInfo) {
diff --git 
a/paimon-flink/paimon-flink-cdc/src/test/java/org/apache/paimon/flink/action/cdc/mysql/MySqlCdcTypeMappingITCase.java
 
b/paimon-flink/paimon-flink-cdc/src/test/java/org/apache/paimon/flink/action/cdc/mysql/MySqlCdcTypeMappingITCase.java
index 7eb7de979..237e6c262 100644
--- 
a/paimon-flink/paimon-flink-cdc/src/test/java/org/apache/paimon/flink/action/cdc/mysql/MySqlCdcTypeMappingITCase.java
+++ 
b/paimon-flink/paimon-flink-cdc/src/test/java/org/apache/paimon/flink/action/cdc/mysql/MySqlCdcTypeMappingITCase.java
@@ -20,10 +20,12 @@ package org.apache.paimon.flink.action.cdc.mysql;
 
 import org.apache.paimon.flink.action.cdc.TypeMapping;
 import org.apache.paimon.table.FileStoreTable;
+import org.apache.paimon.testutils.assertj.AssertionUtils;
 import org.apache.paimon.types.DataType;
 import org.apache.paimon.types.DataTypes;
 import org.apache.paimon.types.RowType;
 
+import com.ververica.cdc.connectors.mysql.table.JdbcUrlUtils;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.Timeout;
@@ -43,6 +45,7 @@ import static 
org.apache.paimon.flink.action.cdc.TypeMapping.TypeMappingMode.TIN
 import static 
org.apache.paimon.flink.action.cdc.TypeMapping.TypeMappingMode.TO_NULLABLE;
 import static 
org.apache.paimon.flink.action.cdc.TypeMapping.TypeMappingMode.TO_STRING;
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
 /** IT test for {@link TypeMapping} in MySQL CDC. */
 public class MySqlCdcTypeMappingITCase extends MySqlActionITCaseBase {
@@ -61,6 +64,10 @@ public class MySqlCdcTypeMappingITCase extends 
MySqlActionITCaseBase {
         Map<String, String> mySqlConfig = getBasicMySqlConfig();
         mySqlConfig.put("database-name", "tinyint1_not_bool_test");
 
+        // test tinyInt1isBit compatibility and url building
+        mySqlConfig.put(JdbcUrlUtils.PROPERTIES_PREFIX + "tinyInt1isBit", 
"false");
+        mySqlConfig.put(JdbcUrlUtils.PROPERTIES_PREFIX + "useSSL", "false");
+
         MySqlSyncDatabaseAction action =
                 syncDatabaseActionBuilder(mySqlConfig)
                         .withTableConfig(getBasicTableConfig())
@@ -113,6 +120,28 @@ public class MySqlCdcTypeMappingITCase extends 
MySqlActionITCaseBase {
         }
     }
 
+    @Test
+    public void testConflictTinyInt1NotBool() {
+        Map<String, String> mySqlConfig = getBasicMySqlConfig();
+        mySqlConfig.put("database-name", "tinyint1_not_bool_test");
+        mySqlConfig.put(JdbcUrlUtils.PROPERTIES_PREFIX + "tinyInt1isBit", 
"true");
+
+        MySqlSyncDatabaseAction action =
+                syncDatabaseActionBuilder(mySqlConfig)
+                        .withTableConfig(getBasicTableConfig())
+                        .withMode(COMBINED.configString())
+                        .withTypeMappingModes(TINYINT1_NOT_BOOL.configString())
+                        .build();
+
+        assertThatThrownBy(action::run)
+                .satisfies(
+                        AssertionUtils.anyCauseMatches(
+                                IllegalArgumentException.class,
+                                "Type mapping option 'tinyint1-not-bool' 
conflicts with "
+                                        + "jdbc properties 
'jdbc.properties.tinyInt1isBit=true'. "
+                                        + "Option 'tinyint1-not-bool' is equal 
to 'jdbc.properties.tinyInt1isBit=false'."));
+    }
+
     // --------------------------------------- all-to-string 
---------------------------------------
 
     @Test

Reply via email to