From 164272dd4a362f26063082166b134faa46bf68a8 Mon Sep 17 00:00:00 2001 From: Hiroyuki Sato Date: Sat, 10 Aug 2024 22:16:37 +0900 Subject: [PATCH 1/3] Call loadTimeZoneMappings only if the TimeUtil class is com.mysql.jdbc.TimeUtil. --- .../org/embulk/input/mysql/MySQLInputPlugin.java | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/embulk-input-mysql/src/main/java/org/embulk/input/mysql/MySQLInputPlugin.java b/embulk-input-mysql/src/main/java/org/embulk/input/mysql/MySQLInputPlugin.java index 7e18efa0..265b07bf 100644 --- a/embulk-input-mysql/src/main/java/org/embulk/input/mysql/MySQLInputPlugin.java +++ b/embulk-input-mysql/src/main/java/org/embulk/input/mysql/MySQLInputPlugin.java @@ -124,8 +124,15 @@ protected MySQLInputConnection newConnection(PluginTask task) throws SQLExceptio props.putAll(t.getOptions()); logConnectionProperties(url, props); - // load timezone mappings - loadTimeZoneMappings(); + // loadTimeZoneMappings initializes com.mysql.jdbc.TimeUtil.timeZoneMappings static field by calling + // static timeZoneMappings method using reflection. + // It may need Connector/J 5.x (com.mysql.jdbc.TimeUtil) only. + try { + Class timeUtilClass = Class.forName("com.mysql.jdbc.TimeUtil"); + loadTimeZoneMappings(timeUtilClass); + } catch (ClassNotFoundException e) { + // do nothing + } Connection con = DriverManager.getConnection(url, props); try { @@ -145,7 +152,7 @@ protected ColumnGetterFactory newColumnGetterFactory(final PageBuilder pageBuild return new MySQLColumnGetterFactory(pageBuilder, dateTimeZone); } - private void loadTimeZoneMappings() + private void loadTimeZoneMappings(Class timeUtilClass) { // Here initializes com.mysql.jdbc.TimeUtil.timeZoneMappings static field by calling // static timeZoneMappings method using reflection. @@ -159,7 +166,6 @@ private void loadTimeZoneMappings() // Here implements a workaround as as workaround. Field f = null; try { - Class timeUtilClass = Class.forName("com.mysql.jdbc.TimeUtil"); f = timeUtilClass.getDeclaredField("timeZoneMappings"); f.setAccessible(true); @@ -172,7 +178,7 @@ private void loadTimeZoneMappings() f.set(null, timeZoneMappings); } } - catch (ClassNotFoundException | IllegalAccessException | NoSuchFieldException | IOException e) { + catch (IllegalAccessException | NoSuchFieldException | IOException e) { throw new RuntimeException(e); } finally { From 41163b976eb35364f97c600f8fb5487f8911a2e4 Mon Sep 17 00:00:00 2001 From: Hiroyuki Sato Date: Sun, 18 Aug 2024 13:23:13 +0900 Subject: [PATCH 2/3] Move the logic into loadTimeZoneMappings. --- .../embulk/input/mysql/MySQLInputPlugin.java | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/embulk-input-mysql/src/main/java/org/embulk/input/mysql/MySQLInputPlugin.java b/embulk-input-mysql/src/main/java/org/embulk/input/mysql/MySQLInputPlugin.java index 265b07bf..bb8fa248 100644 --- a/embulk-input-mysql/src/main/java/org/embulk/input/mysql/MySQLInputPlugin.java +++ b/embulk-input-mysql/src/main/java/org/embulk/input/mysql/MySQLInputPlugin.java @@ -124,15 +124,8 @@ protected MySQLInputConnection newConnection(PluginTask task) throws SQLExceptio props.putAll(t.getOptions()); logConnectionProperties(url, props); - // loadTimeZoneMappings initializes com.mysql.jdbc.TimeUtil.timeZoneMappings static field by calling - // static timeZoneMappings method using reflection. - // It may need Connector/J 5.x (com.mysql.jdbc.TimeUtil) only. - try { - Class timeUtilClass = Class.forName("com.mysql.jdbc.TimeUtil"); - loadTimeZoneMappings(timeUtilClass); - } catch (ClassNotFoundException e) { - // do nothing - } + // load timezone mappings + loadTimeZoneMappingsIfNeeded(); Connection con = DriverManager.getConnection(url, props); try { @@ -152,7 +145,7 @@ protected ColumnGetterFactory newColumnGetterFactory(final PageBuilder pageBuild return new MySQLColumnGetterFactory(pageBuilder, dateTimeZone); } - private void loadTimeZoneMappings(Class timeUtilClass) + private void loadTimeZoneMappingsIfNeeded() { // Here initializes com.mysql.jdbc.TimeUtil.timeZoneMappings static field by calling // static timeZoneMappings method using reflection. @@ -163,9 +156,13 @@ private void loadTimeZoneMappings(Class timeUtilClass) // from the classloader. It seems like a bug of JDBC Driver where it should use the class loader // that loaded com.mysql.jdbc.TimeUtil class rather than system class loader to read the // property file because the file should be in the same classpath with the class. - // Here implements a workaround as as workaround. + // Here implements a workaround as a workaround. + // + // It's not 100% sure, but this workaround is necessary for Connector/J 5.x (com.mysql.jdbc.TimeUtil) + // only. Field f = null; try { + Class timeUtilClass = Class.forName("com.mysql.jdbc.TimeUtil"); f = timeUtilClass.getDeclaredField("timeZoneMappings"); f.setAccessible(true); @@ -178,6 +175,10 @@ private void loadTimeZoneMappings(Class timeUtilClass) f.set(null, timeZoneMappings); } } + catch (ClassNotFoundException e) { + // It appears that the user uses the Connector/J 8.x driver. + // Do nothing; + } catch (IllegalAccessException | NoSuchFieldException | IOException e) { throw new RuntimeException(e); } From 53dee529877875735aab7ec2573163cd7372e85c Mon Sep 17 00:00:00 2001 From: Hiroyuki Sato Date: Sun, 18 Aug 2024 15:05:37 +0900 Subject: [PATCH 3/3] Fix review comments Co-authored-by: Dai MIKURUBE --- .../org/embulk/input/mysql/MySQLInputPlugin.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/embulk-input-mysql/src/main/java/org/embulk/input/mysql/MySQLInputPlugin.java b/embulk-input-mysql/src/main/java/org/embulk/input/mysql/MySQLInputPlugin.java index bb8fa248..ae6397c1 100644 --- a/embulk-input-mysql/src/main/java/org/embulk/input/mysql/MySQLInputPlugin.java +++ b/embulk-input-mysql/src/main/java/org/embulk/input/mysql/MySQLInputPlugin.java @@ -158,8 +158,9 @@ private void loadTimeZoneMappingsIfNeeded() // property file because the file should be in the same classpath with the class. // Here implements a workaround as a workaround. // - // It's not 100% sure, but this workaround is necessary for Connector/J 5.x (com.mysql.jdbc.TimeUtil) - // only. + // This workaround seems required only for Connector/J 5.x (com.mysql.jdbc.TimeUtil), + // not necessary for Connector/J 8.x (com.mysql.cj.util.TimeUtil). + // TODO: Clarify for Connector/J 8.x just in case. Field f = null; try { Class timeUtilClass = Class.forName("com.mysql.jdbc.TimeUtil"); @@ -176,9 +177,14 @@ private void loadTimeZoneMappingsIfNeeded() } } catch (ClassNotFoundException e) { - // It appears that the user uses the Connector/J 8.x driver. - // Do nothing; + try { + Class.forName("com.mysql.cj.util.TimeUtil"); + } catch (final ClassNotFoundException ex2) { + // Throw if neither the Connector/J 5.x nor 8.x driver is found. + throw new RuntimeException(e); + } } + // Pass-through if the Connector/J 8.x driver is found. } catch (IllegalAccessException | NoSuchFieldException | IOException e) { throw new RuntimeException(e); }