embulk-output-mysql 0.7.7 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +21 -0
  3. data/build.gradle +3 -3
  4. data/classpath/embulk-output-jdbc-0.8.0.jar +0 -0
  5. data/classpath/embulk-output-mysql-0.8.0.jar +0 -0
  6. data/default_jdbc_driver/mysql-connector-java-5.1.44.jar +0 -0
  7. data/src/main/java/org/embulk/output/MySQLOutputPlugin.java +56 -16
  8. data/src/main/java/org/embulk/output/MySQLTimeZoneComparison.java +107 -0
  9. data/src/main/java/org/embulk/output/mysql/MySQLOutputConnection.java +14 -5
  10. data/src/main/java/org/embulk/output/mysql/MySQLOutputConnector.java +3 -8
  11. data/src/test/java/org/embulk/output/mysql/AfterLoadTest.java +136 -0
  12. data/src/test/java/org/embulk/output/mysql/BeforeLoadTest.java +124 -0
  13. data/src/test/java/org/embulk/output/mysql/CreateTableTest.java +79 -0
  14. data/src/test/java/org/embulk/output/mysql/MySQLTests.java +69 -0
  15. data/src/test/resources/org/embulk/output/mysql/test/expect/after_load/setup.sql +8 -0
  16. data/src/test/resources/org/embulk/output/mysql/test/expect/after_load/test1.csv +4 -0
  17. data/src/test/resources/org/embulk/output/mysql/test/expect/after_load/test_expected.diff +2 -0
  18. data/src/test/resources/org/embulk/output/mysql/test/expect/after_load/test_insert_after_load.yml +3 -0
  19. data/src/test/resources/org/embulk/output/mysql/test/expect/after_load/test_insert_after_load_expected.csv +5 -0
  20. data/src/test/resources/org/embulk/output/mysql/test/expect/after_load/test_insert_direct_after_load.yml +3 -0
  21. data/src/test/resources/org/embulk/output/mysql/test/expect/after_load/test_merge_after_load.yml +3 -0
  22. data/src/test/resources/org/embulk/output/mysql/test/expect/after_load/test_merge_after_load_expected.csv +5 -0
  23. data/src/test/resources/org/embulk/output/mysql/test/expect/after_load/test_merge_direct_after_load.yml +3 -0
  24. data/src/test/resources/org/embulk/output/mysql/test/expect/after_load/test_replace_after_load.yml +3 -0
  25. data/src/test/resources/org/embulk/output/mysql/test/expect/after_load/test_replace_after_load_expected.csv +3 -0
  26. data/src/test/resources/org/embulk/output/mysql/test/expect/after_load/test_truncate_insert_after_load.yml +3 -0
  27. data/src/test/resources/org/embulk/output/mysql/test/expect/after_load/test_truncate_insert_after_load_expected.csv +3 -0
  28. data/src/test/resources/org/embulk/output/mysql/test/expect/before_load/setup.sql +8 -0
  29. data/src/test/resources/org/embulk/output/mysql/test/expect/before_load/test1.csv +4 -0
  30. data/src/test/resources/org/embulk/output/mysql/test/expect/before_load/test_expected.diff +2 -0
  31. data/src/test/resources/org/embulk/output/mysql/test/expect/before_load/test_insert_before_load.yml +3 -0
  32. data/src/test/resources/{mysql/data/test1.csv → org/embulk/output/mysql/test/expect/before_load/test_insert_before_load_expected.csv} +1 -0
  33. data/src/test/resources/org/embulk/output/mysql/test/expect/before_load/test_insert_direct_before_load.yml +3 -0
  34. data/src/test/resources/org/embulk/output/mysql/test/expect/before_load/test_merge_before_load.yml +3 -0
  35. data/src/test/resources/org/embulk/output/mysql/test/expect/before_load/test_merge_before_load_expected.csv +4 -0
  36. data/src/test/resources/org/embulk/output/mysql/test/expect/before_load/test_merge_direct_before_load.yml +3 -0
  37. data/src/test/resources/org/embulk/output/mysql/test/expect/before_load/test_truncate_insert_before_load.yml +3 -0
  38. data/src/test/resources/org/embulk/output/mysql/test/expect/before_load/test_truncate_insert_before_load_expected.csv +4 -0
  39. data/src/test/resources/org/embulk/output/mysql/test/expect/create_table/setup.sql +1 -0
  40. data/src/test/resources/org/embulk/output/mysql/test/expect/create_table/test1.csv +4 -0
  41. data/src/test/resources/org/embulk/output/mysql/test/expect/create_table/test_table_constraint.yml +5 -0
  42. data/src/test/resources/org/embulk/output/mysql/test/expect/create_table/test_table_constraint_expected.csv +3 -0
  43. data/src/test/resources/org/embulk/output/mysql/test/expect/create_table/test_table_option.yml +5 -0
  44. data/src/test/resources/org/embulk/output/mysql/test/expect/create_table/test_table_option_expected.csv +3 -0
  45. metadata +40 -18
  46. data/classpath/embulk-output-jdbc-0.7.7.jar +0 -0
  47. data/classpath/embulk-output-mysql-0.7.7.jar +0 -0
  48. data/classpath/mysql-connector-java-5.1.34.jar +0 -0
  49. data/src/test/java/org/embulk/output/mysql/MySQLOutputPluginTest.java +0 -569
  50. data/src/test/resources/mysql/yml/test-insert-after-load.yml +0 -22
  51. data/src/test/resources/mysql/yml/test-insert-before-load.yml +0 -22
  52. data/src/test/resources/mysql/yml/test-insert-direct-after-load.yml +0 -22
  53. data/src/test/resources/mysql/yml/test-insert-direct-before-load.yml +0 -22
  54. data/src/test/resources/mysql/yml/test-merge-after-load.yml +0 -22
  55. data/src/test/resources/mysql/yml/test-merge-before-load.yml +0 -22
  56. data/src/test/resources/mysql/yml/test-merge-direct-after-load.yml +0 -22
  57. data/src/test/resources/mysql/yml/test-merge-direct-before-load.yml +0 -22
  58. data/src/test/resources/mysql/yml/test-replace-after-load.yml +0 -22
  59. data/src/test/resources/mysql/yml/test-truncate-insert-after-load.yml +0 -22
  60. data/src/test/resources/mysql/yml/test-truncate-insert-before-load.yml +0 -22
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bf58d4882f474c11125f531945a5048f350c0f39
4
- data.tar.gz: 2f28afb1f6bf1bcfdc700595f59eaaf0143984c7
3
+ metadata.gz: 6da5ba42634421a68e79de5f9c753a76d8406786
4
+ data.tar.gz: 7f80247c0f4c5fa8b973d9dca3914151f90815e5
5
5
  SHA512:
6
- metadata.gz: 227b8b0b5a95eb0c464a98a67a2824fb79d93c0491b97bcb729c0b15f624307d86095cdd5c1ed74afc2a424215ca87df070046fdcb2990f83b9398ac72e4e671
7
- data.tar.gz: 9536f2f57ae9a11a48a0b594b4f67157a8ff35bb83ba3528db9cf05544fec85c60c4ae8a0fd17b979d92e35c5b413e058c41236e0751ad6786fda2e821519fcd
6
+ metadata.gz: be36e44971e9d805842958a0acd90f69cbde13c141df4e727aff2fcd05158452d463ebfe7d36ff476643e76a71f0793494dc694e1687083ea46892ef5e59955f
7
+ data.tar.gz: 2bbf372969dd29e6368d32da9c29db14322f9035c4291696853d7c8d6f7a75261dae5086b063a09efe5435fa53a57359eb00d8f22b127ec9d493affd86600d46
data/README.md CHANGED
@@ -10,12 +10,17 @@ MySQL output plugin for Embulk loads records to MySQL.
10
10
 
11
11
  ## Configuration
12
12
 
13
+ - **driver_path**: path to the jar file of the MySQL JDBC driver. If not set, the bundled JDBC driver (MySQL Connector/J 5.1.44) will be used (string). NOTE: the bundled JDBC driver version was upgrade from 5.1.34 to 5.1.44 at embulk-output-mysql 0.8.0 . Please check release notes for MySQL Connector/J (https://dev.mysql.com/doc/relnotes/connector-j/5.1/en/news-5-1.html) .
13
14
  - **host**: database host name (string, required)
14
15
  - **port**: database port number (integer, default: 3306)
15
16
  - **user**: database login user name (string, required)
16
17
  - **password**: database login password (string, default: "")
18
+ - **ssl**: use SSL to connect to the database (string, default: `disable`. `enable` uses SSL without server-side validation and `verify` checks the certificate. For compatibility reasons, `true` behaves as `enable` and `false` behaves as `disable`.)
17
19
  - **database**: destination database name (string, required)
20
+ - **temp_database**: database name for intermediate tables. by default, intermediate tables will be created in the database specified by `database`. (string, optional)
18
21
  - **table**: destination table name (string, required)
22
+ - **create_table_constraint** table constraint added to `CREATE TABLE` statement, like `CREATE TABLE <table_name> (<column1> <type1>, <column2> <type2>, ..., <create_table_constraint>) <create_table_option>`.
23
+ - **create_table_option** table option added to `CREATE TABLE` statement, like `CREATE TABLE <table_name> (<column1> <type1>, <column2> <type2>, ..., <create_table_constraint>) <create_table_option>`.
19
24
  - **options**: extra connection properties (hash, default: {})
20
25
  - **retry_limit** max retry count for database operations (integer, default: 12)
21
26
  - **retry_wait** initial retry wait time in milliseconds (integer, default: 1000 (1 second))
@@ -118,3 +123,19 @@ out:
118
123
  ```
119
124
  $ ./gradlew gem
120
125
  ```
126
+
127
+ Running tests:
128
+
129
+ You need to create 'mysql.yml' as follows.
130
+ ```
131
+ type: mysql
132
+ host: localhost
133
+ port: 3306
134
+ database: database
135
+ user: user
136
+ password: pass
137
+ ```
138
+
139
+ ```
140
+ $ EMBULK_OUTPUT_MYSQL_TEST_CONFIG=mysql.yml ./gradlew :embulk-output-mysql:check --info
141
+ ```
data/build.gradle CHANGED
@@ -1,7 +1,7 @@
1
1
  dependencies {
2
2
  compile project(':embulk-output-jdbc')
3
- compile 'mysql:mysql-connector-java:5.1.34'
3
+ compile 'mysql:mysql-connector-java:5.1.44'
4
+ defaultJdbcDriver 'mysql:mysql-connector-java:5.1.44'
4
5
 
5
- testCompile 'org.embulk:embulk-standards:0.8.8'
6
- testCompile project(':embulk-output-jdbc').sourceSets.test.output
6
+ testCompile 'org.embulk:embulk-standards:0.8.22'
7
7
  }
@@ -3,14 +3,21 @@ package org.embulk.output;
3
3
  import java.util.Properties;
4
4
  import java.io.IOException;
5
5
  import java.sql.SQLException;
6
+
6
7
  import com.google.common.base.Optional;
8
+
7
9
  import org.embulk.config.Config;
8
10
  import org.embulk.config.ConfigDefault;
9
11
  import org.embulk.output.jdbc.AbstractJdbcOutputPlugin;
12
+ import org.embulk.output.jdbc.Ssl;
10
13
  import org.embulk.output.jdbc.BatchInsert;
14
+ import org.embulk.output.jdbc.JdbcOutputConnection;
11
15
  import org.embulk.output.jdbc.MergeConfig;
16
+ import org.embulk.output.jdbc.TableIdentifier;
17
+ import org.embulk.output.mysql.MySQLOutputConnection;
12
18
  import org.embulk.output.mysql.MySQLOutputConnector;
13
19
  import org.embulk.output.mysql.MySQLBatchInsert;
20
+ import org.embulk.spi.Schema;
14
21
 
15
22
  public class MySQLOutputPlugin
16
23
  extends AbstractJdbcOutputPlugin
@@ -18,6 +25,10 @@ public class MySQLOutputPlugin
18
25
  public interface MySQLPluginTask
19
26
  extends PluginTask
20
27
  {
28
+ @Config("driver_path")
29
+ @ConfigDefault("null")
30
+ public Optional<String> getDriverPath();
31
+
21
32
  @Config("host")
22
33
  public String getHost();
23
34
 
@@ -34,6 +45,15 @@ public class MySQLOutputPlugin
34
45
 
35
46
  @Config("database")
36
47
  public String getDatabase();
48
+
49
+ @Config("temp_database")
50
+ @ConfigDefault("null")
51
+ public Optional<String> getTempDatabase();
52
+
53
+ @Config("ssl")
54
+ @ConfigDefault("\"disable\"") // backward compatibility
55
+ public Ssl getSsl();
56
+
37
57
  }
38
58
 
39
59
  @Override
@@ -55,6 +75,8 @@ public class MySQLOutputPlugin
55
75
  {
56
76
  MySQLPluginTask t = (MySQLPluginTask) task;
57
77
 
78
+ loadDriver("com.mysql.jdbc.Driver", t.getDriverPath());
79
+
58
80
  String url = String.format("jdbc:mysql://%s:%d/%s",
59
81
  t.getHost(), t.getPort(), t.getDatabase());
60
82
 
@@ -70,21 +92,21 @@ public class MySQLOutputPlugin
70
92
  // Socket options TCP_KEEPCNT, TCP_KEEPIDLE, and TCP_KEEPINTVL are not configurable.
71
93
  props.setProperty("tcpKeepAlive", "true");
72
94
 
73
- // TODO
74
- //switch t.getSssl() {
75
- //when "disable":
76
- // break;
77
- //when "enable":
78
- // props.setProperty("useSSL", "true");
79
- // props.setProperty("requireSSL", "false");
80
- // props.setProperty("verifyServerCertificate", "false");
81
- // break;
82
- //when "verify":
83
- // props.setProperty("useSSL", "true");
84
- // props.setProperty("requireSSL", "true");
85
- // props.setProperty("verifyServerCertificate", "true");
86
- // break;
87
- //}
95
+ switch (t.getSsl()) {
96
+ case DISABLE:
97
+ props.setProperty("useSSL", "false");
98
+ break;
99
+ case ENABLE:
100
+ props.setProperty("useSSL", "true");
101
+ props.setProperty("requireSSL", "true");
102
+ props.setProperty("verifyServerCertificate", "false");
103
+ break;
104
+ case VERIFY:
105
+ props.setProperty("useSSL", "true");
106
+ props.setProperty("requireSSL", "true");
107
+ props.setProperty("verifyServerCertificate", "true");
108
+ break;
109
+ }
88
110
 
89
111
  if (!retryableMetadataOperation) {
90
112
  // non-retryable batch operation uses longer timeout
@@ -97,12 +119,21 @@ public class MySQLOutputPlugin
97
119
  // TODO validate task.getMergeKeys is null
98
120
 
99
121
  props.setProperty("user", t.getUser());
100
- logger.info("Connecting to {} options {}", url, props);
101
122
  props.setProperty("password", t.getPassword());
123
+ logConnectionProperties(url, props);
102
124
 
103
125
  return new MySQLOutputConnector(url, props);
104
126
  }
105
127
 
128
+ @Override
129
+ protected TableIdentifier buildIntermediateTableId(JdbcOutputConnection con, PluginTask task, String tableName) {
130
+ MySQLPluginTask t = (MySQLPluginTask) task;
131
+ if (t.getTempDatabase().isPresent()) {
132
+ return new TableIdentifier(t.getTempDatabase().get(), null, tableName);
133
+ }
134
+ return super.buildIntermediateTableId(con, task, tableName);
135
+ }
136
+
106
137
  @Override
107
138
  protected BatchInsert newBatchInsert(PluginTask task, Optional<MergeConfig> mergeConfig) throws IOException, SQLException
108
139
  {
@@ -122,4 +153,13 @@ public class MySQLOutputPlugin
122
153
  return false;
123
154
  }
124
155
  }
156
+
157
+ @Override
158
+ protected void doBegin(JdbcOutputConnection con,
159
+ PluginTask task, final Schema schema, int taskCount) throws SQLException
160
+ {
161
+ MySQLOutputConnection mySQLCon = (MySQLOutputConnection)con;
162
+ mySQLCon.compareTimeZone();
163
+ super.doBegin(con,task,schema,taskCount);
164
+ }
125
165
  }
@@ -0,0 +1,107 @@
1
+ package org.embulk.output;
2
+
3
+ import org.embulk.spi.Exec;
4
+ import org.slf4j.Logger;
5
+
6
+
7
+ import java.sql.Connection;
8
+ import java.sql.ResultSet;
9
+ import java.sql.SQLException;
10
+ import java.sql.Statement;
11
+ import java.util.Date;
12
+ import java.util.Locale;
13
+ import java.util.TimeZone;
14
+
15
+ public class MySQLTimeZoneComparison {
16
+
17
+ private static final int ONE_HOUR_SEC = 3600;
18
+ private static final int ONE_MIN_SEC = 60;
19
+
20
+ private Connection connection;
21
+
22
+ private final Logger logger = Exec.getLogger(getClass());
23
+
24
+ public MySQLTimeZoneComparison(Connection connection)
25
+ {
26
+ this.connection = connection;
27
+ }
28
+
29
+ public void compareTimeZone()
30
+ throws SQLException
31
+ {
32
+ TimeZone serverTimeZone = null;
33
+ try {
34
+ serverTimeZone = getServerTimeZone();
35
+ }
36
+ catch (SQLException ex) {
37
+ logger.warn("Can't get server TimeZone.");
38
+ logger.warn(String.format(Locale.ENGLISH, "SQLException raised %s", ex.toString()));
39
+ }
40
+
41
+ TimeZone clientTimeZone = TimeZone.getDefault();
42
+ Date today = new Date();
43
+ int clientOffset = clientTimeZone.getRawOffset();
44
+
45
+ if (clientTimeZone.inDaylightTime(today)) {
46
+ clientOffset += clientTimeZone.getDSTSavings();
47
+ }
48
+
49
+ //
50
+ // Compare offset only. Although I expect to return true, the following code return false,
51
+ //
52
+ // TimeZone tz_jst = TimeZone.getTimeZone("JST");
53
+ // TimeZone tz_gmt9 = TimeZone.getTimeZone("GMT+9");
54
+ // tz_jst.hasSameRules(tz_gmt9) // return false.
55
+ //
56
+ if (clientOffset != serverTimeZone.getRawOffset()) {
57
+ logger.warn(String.format(Locale.ENGLISH,
58
+ "The client timezone(%s) is different from the server timezone(%s). The plugin will store wrong datetime values.",
59
+ clientTimeZone.getID(), serverTimeZone.getID()));
60
+ logger.warn(String.format(Locale.ENGLISH,
61
+ "You may need to set options `useLegacyDatetimeCode` and `serverTimezone`"));
62
+ logger.warn(String.format(Locale.ENGLISH,
63
+ "Example. `options: { useLegacyDatetimeCode: false, serverTimezone: UTC }`"));
64
+ }
65
+ logger.warn(String.format(Locale.ENGLISH, "The plugin will set `useLegacyDatetimeCode=false` by default in future."));
66
+ }
67
+
68
+ private TimeZone getServerTimeZone()
69
+ throws SQLException
70
+ {
71
+ //
72
+ // First, I used `@@system_time_zone`. but It return non Time Zone Abbreviations name on a specific platform.
73
+ // So, This method calculate GMT offset with query.
74
+ //
75
+ String query = "select TIME_TO_SEC(timediff(now(),utc_timestamp()));";
76
+ Statement stmt = connection.createStatement();
77
+
78
+ try {
79
+ ResultSet rs = stmt.executeQuery(query);
80
+ if (rs.next()) {
81
+ int offsetSeconds = rs.getInt(1);
82
+ return fromGMTOffsetSeconds(offsetSeconds);
83
+ }
84
+ throw new SQLException(String.format(Locale.ENGLISH,
85
+ "The timezone comparison query(%s) doesn't return the result.",query));
86
+ }
87
+ finally {
88
+ stmt.close();
89
+ }
90
+ }
91
+
92
+ private TimeZone fromGMTOffsetSeconds(int offsetSeconds)
93
+ {
94
+ if (offsetSeconds == 0) {
95
+ return TimeZone.getTimeZone("UTC");
96
+ }
97
+
98
+ String sign = offsetSeconds > 0 ? "+" : "-";
99
+ int absOffsetSec = Math.abs(offsetSeconds);
100
+ int tzHour = absOffsetSec / ONE_HOUR_SEC;
101
+ int tzMin = absOffsetSec % ONE_HOUR_SEC / ONE_MIN_SEC;
102
+ String tzName = String.format(Locale.ENGLISH, "GMT%s%02d:%02d", sign, tzHour, tzMin);
103
+ return TimeZone.getTimeZone(tzName);
104
+ }
105
+
106
+
107
+ }
@@ -4,10 +4,12 @@ import java.util.List;
4
4
  import java.sql.Connection;
5
5
  import java.sql.SQLException;
6
6
 
7
+ import org.embulk.output.MySQLTimeZoneComparison;
7
8
  import org.embulk.output.jdbc.JdbcColumn;
8
9
  import org.embulk.output.jdbc.JdbcSchema;
9
10
  import org.embulk.output.jdbc.JdbcOutputConnection;
10
11
  import org.embulk.output.jdbc.MergeConfig;
12
+ import org.embulk.output.jdbc.TableIdentifier;
11
13
 
12
14
  public class MySQLOutputConnection
13
15
  extends JdbcOutputConnection
@@ -20,12 +22,12 @@ public class MySQLOutputConnection
20
22
  }
21
23
 
22
24
  @Override
23
- protected String buildPreparedMergeSql(String toTable, JdbcSchema toTableSchema, MergeConfig mergeConfig) throws SQLException
25
+ protected String buildPreparedMergeSql(TableIdentifier toTable, JdbcSchema toTableSchema, MergeConfig mergeConfig) throws SQLException
24
26
  {
25
27
  StringBuilder sb = new StringBuilder();
26
28
 
27
29
  sb.append("INSERT INTO ");
28
- quoteIdentifierString(sb, toTable);
30
+ quoteTableIdentifier(sb, toTable);
29
31
  sb.append(" (");
30
32
  for (int i = 0; i < toTableSchema.getCount(); i++) {
31
33
  if(i != 0) { sb.append(", "); }
@@ -58,12 +60,12 @@ public class MySQLOutputConnection
58
60
  }
59
61
 
60
62
  @Override
61
- protected String buildCollectMergeSql(List<String> fromTables, JdbcSchema schema, String toTable, MergeConfig mergeConfig) throws SQLException
63
+ protected String buildCollectMergeSql(List<TableIdentifier> fromTables, JdbcSchema schema, TableIdentifier toTable, MergeConfig mergeConfig) throws SQLException
62
64
  {
63
65
  StringBuilder sb = new StringBuilder();
64
66
 
65
67
  sb.append("INSERT INTO ");
66
- quoteIdentifierString(sb, toTable);
68
+ quoteTableIdentifier(sb, toTable);
67
69
  sb.append(" (");
68
70
  for (int i = 0; i < schema.getCount(); i++) {
69
71
  if (i != 0) { sb.append(", "); }
@@ -78,7 +80,7 @@ public class MySQLOutputConnection
78
80
  quoteIdentifierString(sb, schema.getColumnName(j));
79
81
  }
80
82
  sb.append(" FROM ");
81
- quoteIdentifierString(sb, fromTables.get(i));
83
+ quoteTableIdentifier(sb, fromTables.get(i));
82
84
  }
83
85
  sb.append(" ON DUPLICATE KEY UPDATE ");
84
86
  if (mergeConfig.getMergeRule().isPresent()) {
@@ -110,4 +112,11 @@ public class MySQLOutputConnection
110
112
  return super.buildColumnTypeName(c);
111
113
  }
112
114
  }
115
+
116
+ public void compareTimeZone() throws SQLException
117
+ {
118
+ MySQLTimeZoneComparison timeZoneComparison = new MySQLTimeZoneComparison(connection);
119
+ timeZoneComparison.compareTimeZone();
120
+ }
121
+
113
122
  }
@@ -1,25 +1,20 @@
1
1
  package org.embulk.output.mysql;
2
2
 
3
3
  import java.util.Properties;
4
- import java.sql.Driver;
5
4
  import java.sql.Connection;
5
+ import java.sql.DriverManager;
6
6
  import java.sql.SQLException;
7
+
7
8
  import org.embulk.output.jdbc.JdbcOutputConnector;
8
9
 
9
10
  public class MySQLOutputConnector
10
11
  implements JdbcOutputConnector
11
12
  {
12
- private final Driver driver;
13
13
  private final String url;
14
14
  private final Properties properties;
15
15
 
16
16
  public MySQLOutputConnector(String url, Properties properties)
17
17
  {
18
- try {
19
- this.driver = new com.mysql.jdbc.Driver(); // new com.mysql.jdbc.Driver throws SQLException
20
- } catch (SQLException ex) {
21
- throw new RuntimeException(ex);
22
- }
23
18
  this.url = url;
24
19
  this.properties = properties;
25
20
  }
@@ -27,7 +22,7 @@ public class MySQLOutputConnector
27
22
  @Override
28
23
  public MySQLOutputConnection connect(boolean autoCommit) throws SQLException
29
24
  {
30
- Connection c = driver.connect(url, properties);
25
+ Connection c = DriverManager.getConnection(url, properties);
31
26
  try {
32
27
  MySQLOutputConnection con = new MySQLOutputConnection(c, autoCommit);
33
28
  c = null;
@@ -0,0 +1,136 @@
1
+ package org.embulk.output.mysql;
2
+
3
+ import static org.embulk.output.mysql.MySQLTests.execute;
4
+ import static org.embulk.output.mysql.MySQLTests.selectRecords;
5
+ import static org.hamcrest.Matchers.is;
6
+ import static org.junit.Assert.assertThat;
7
+
8
+ import java.io.File;
9
+ import java.net.URISyntaxException;
10
+ import java.net.URL;
11
+ import java.nio.file.FileSystems;
12
+ import java.nio.file.Path;
13
+
14
+ import org.embulk.config.ConfigDiff;
15
+ import org.embulk.config.ConfigSource;
16
+ import org.embulk.output.MySQLOutputPlugin;
17
+ import org.embulk.spi.OutputPlugin;
18
+ import org.embulk.test.EmbulkTests;
19
+ import org.embulk.test.TestingEmbulk;
20
+ import org.junit.Before;
21
+ import org.junit.Rule;
22
+ import org.junit.Test;
23
+
24
+ import com.google.common.io.Resources;
25
+
26
+ public class AfterLoadTest
27
+ {
28
+ private static final String BASIC_RESOURCE_PATH = "org/embulk/output/mysql/test/expect/after_load/";
29
+
30
+ private static ConfigSource loadYamlResource(TestingEmbulk embulk, String fileName)
31
+ {
32
+ return embulk.loadYamlResource(BASIC_RESOURCE_PATH + fileName);
33
+ }
34
+
35
+ private static String readResource(String fileName)
36
+ {
37
+ return EmbulkTests.readResource(BASIC_RESOURCE_PATH + fileName);
38
+ }
39
+
40
+ @Rule
41
+ public TestingEmbulk embulk = TestingEmbulk.builder()
42
+ .registerPlugin(OutputPlugin.class, "mysql", MySQLOutputPlugin.class)
43
+ .build();
44
+
45
+ private ConfigSource baseConfig;
46
+
47
+ @Before
48
+ public void setup()
49
+ {
50
+ baseConfig = MySQLTests.baseConfig();
51
+ execute(readResource("setup.sql")); // setup rows
52
+ }
53
+
54
+ @Test
55
+ public void testInsertAfterLoad() throws Exception
56
+ {
57
+ execute("insert into test1 values('B001', 0, 'z')");
58
+ execute("insert into test1 values('B002', 9, 'z')");
59
+
60
+ Path in1 = toPath("test1.csv");
61
+ TestingEmbulk.RunResult result1 = embulk.runOutput(baseConfig.merge(loadYamlResource(embulk, "test_insert_after_load.yml")), in1);
62
+ assertThat(selectRecords(embulk, "test1"), is(readResource("test_insert_after_load_expected.csv")));
63
+ //assertThat(result1.getConfigDiff(), is((ConfigDiff) loadYamlResource(embulk, "test_expected.diff")));
64
+ }
65
+
66
+ @Test
67
+ public void testInsertDirectAfterLoad() throws Exception
68
+ {
69
+ execute("insert into test1 values('B001', 0, 'z')");
70
+ execute("insert into test1 values('B002', 9, 'z')");
71
+
72
+ Path in1 = toPath("test1.csv");
73
+ TestingEmbulk.RunResult result1 = embulk.runOutput(baseConfig.merge(loadYamlResource(embulk, "test_insert_direct_after_load.yml")), in1);
74
+ assertThat(selectRecords(embulk, "test1"), is(readResource("test_insert_after_load_expected.csv")));
75
+ //assertThat(result1.getConfigDiff(), is((ConfigDiff) loadYamlResource(embulk, "test_expected.diff")));
76
+ }
77
+
78
+ @Test
79
+ public void testTruncateInsertAfterLoad() throws Exception
80
+ {
81
+ execute("insert into test1 values('B001', 0, 'z')");
82
+ execute("insert into test1 values('B002', 9, 'z')");
83
+
84
+ Path in1 = toPath("test1.csv");
85
+ TestingEmbulk.RunResult result1 = embulk.runOutput(baseConfig.merge(loadYamlResource(embulk, "test_replace_after_load.yml")), in1);
86
+ assertThat(selectRecords(embulk, "test1"), is(readResource("test_replace_after_load_expected.csv")));
87
+ //assertThat(result1.getConfigDiff(), is((ConfigDiff) loadYamlResource(embulk, "test_expected.diff")));
88
+ }
89
+
90
+ @Test
91
+ public void testReplaceAfterLoad() throws Exception
92
+ {
93
+ execute("insert into test1 values('B001', 0, 'z')");
94
+ execute("insert into test1 values('B002', 9, 'z')");
95
+
96
+ Path in1 = toPath("test1.csv");
97
+ TestingEmbulk.RunResult result1 = embulk.runOutput(baseConfig.merge(loadYamlResource(embulk, "test_truncate_insert_after_load.yml")), in1);
98
+ assertThat(selectRecords(embulk, "test1"), is(readResource("test_truncate_insert_after_load_expected.csv")));
99
+ //assertThat(result1.getConfigDiff(), is((ConfigDiff) loadYamlResource(embulk, "test_expected.diff")));
100
+ }
101
+
102
+ @Test
103
+ public void testMergeAfterLoad() throws Exception
104
+ {
105
+ execute("insert into test1 values('A002', 1, 'y')");
106
+ execute("insert into test1 values('A003', 1, 'y')");
107
+ execute("insert into test1 values('B001', 0, 'z')");
108
+ execute("insert into test1 values('B002', 9, 'z')");
109
+
110
+ Path in1 = toPath("test1.csv");
111
+ TestingEmbulk.RunResult result1 = embulk.runOutput(baseConfig.merge(loadYamlResource(embulk, "test_merge_after_load.yml")), in1);
112
+ assertThat(selectRecords(embulk, "test1"), is(readResource("test_merge_after_load_expected.csv")));
113
+ //assertThat(result1.getConfigDiff(), is((ConfigDiff) loadYamlResource(embulk, "test_expected.diff")));
114
+ }
115
+
116
+ @Test
117
+ public void testMergeDirectAfterLoad() throws Exception
118
+ {
119
+ execute("insert into test1 values('A002', 1, 'y')");
120
+ execute("insert into test1 values('A003', 1, 'y')");
121
+ execute("insert into test1 values('B001', 0, 'z')");
122
+ execute("insert into test1 values('B002', 9, 'z')");
123
+
124
+ Path in1 = toPath("test1.csv");
125
+ TestingEmbulk.RunResult result1 = embulk.runOutput(baseConfig.merge(loadYamlResource(embulk, "test_merge_direct_after_load.yml")), in1);
126
+ assertThat(selectRecords(embulk, "test1"), is(readResource("test_merge_after_load_expected.csv")));
127
+ //assertThat(result1.getConfigDiff(), is((ConfigDiff) loadYamlResource(embulk, "test_expected.diff")));
128
+ }
129
+
130
+ private Path toPath(String fileName) throws URISyntaxException
131
+ {
132
+ URL url = Resources.getResource(BASIC_RESOURCE_PATH + fileName);
133
+ return FileSystems.getDefault().getPath(new File(url.toURI()).getAbsolutePath());
134
+ }
135
+
136
+ }
@@ -0,0 +1,124 @@
1
+ package org.embulk.output.mysql;
2
+
3
+ import static org.embulk.output.mysql.MySQLTests.execute;
4
+ import static org.embulk.output.mysql.MySQLTests.selectRecords;
5
+ import static org.hamcrest.Matchers.is;
6
+ import static org.junit.Assert.assertThat;
7
+
8
+ import java.io.File;
9
+ import java.net.URISyntaxException;
10
+ import java.net.URL;
11
+ import java.nio.file.FileSystems;
12
+ import java.nio.file.Path;
13
+
14
+ import org.embulk.config.ConfigDiff;
15
+ import org.embulk.config.ConfigSource;
16
+ import org.embulk.output.MySQLOutputPlugin;
17
+ import org.embulk.spi.OutputPlugin;
18
+ import org.embulk.test.EmbulkTests;
19
+ import org.embulk.test.TestingEmbulk;
20
+ import org.junit.Before;
21
+ import org.junit.Rule;
22
+ import org.junit.Test;
23
+
24
+ import com.google.common.io.Resources;
25
+
26
+ public class BeforeLoadTest
27
+ {
28
+ private static final String BASIC_RESOURCE_PATH = "org/embulk/output/mysql/test/expect/before_load/";
29
+
30
+ private static ConfigSource loadYamlResource(TestingEmbulk embulk, String fileName)
31
+ {
32
+ return embulk.loadYamlResource(BASIC_RESOURCE_PATH + fileName);
33
+ }
34
+
35
+ private static String readResource(String fileName)
36
+ {
37
+ return EmbulkTests.readResource(BASIC_RESOURCE_PATH + fileName);
38
+ }
39
+
40
+ @Rule
41
+ public TestingEmbulk embulk = TestingEmbulk.builder()
42
+ .registerPlugin(OutputPlugin.class, "mysql", MySQLOutputPlugin.class)
43
+ .build();
44
+
45
+ private ConfigSource baseConfig;
46
+
47
+ @Before
48
+ public void setup()
49
+ {
50
+ baseConfig = MySQLTests.baseConfig();
51
+ execute(readResource("setup.sql")); // setup rows
52
+ }
53
+
54
+ @Test
55
+ public void testInsertBeforeLoad() throws Exception
56
+ {
57
+ execute("insert into test1 values('B001', 0, 'z')");
58
+ execute("insert into test1 values('B002', 9, 'z')");
59
+
60
+ Path in1 = toPath("test1.csv");
61
+ TestingEmbulk.RunResult result1 = embulk.runOutput(baseConfig.merge(loadYamlResource(embulk, "test_insert_before_load.yml")), in1);
62
+ assertThat(selectRecords(embulk, "test1"), is(readResource("test_insert_before_load_expected.csv")));
63
+ //assertThat(result1.getConfigDiff(), is((ConfigDiff) loadYamlResource(embulk, "test_expected.diff")));
64
+ }
65
+
66
+ @Test
67
+ public void testInsertDirectBeforeLoad() throws Exception
68
+ {
69
+ execute("insert into test1 values('B001', 0, 'z')");
70
+ execute("insert into test1 values('B002', 9, 'z')");
71
+
72
+ Path in1 = toPath("test1.csv");
73
+ TestingEmbulk.RunResult result1 = embulk.runOutput(baseConfig.merge(loadYamlResource(embulk, "test_insert_direct_before_load.yml")), in1);
74
+ assertThat(selectRecords(embulk, "test1"), is(readResource("test_insert_before_load_expected.csv")));
75
+ //assertThat(result1.getConfigDiff(), is((ConfigDiff) loadYamlResource(embulk, "test_expected.diff")));
76
+ }
77
+
78
+ @Test
79
+ public void testTruncateInsertBeforeLoad() throws Exception
80
+ {
81
+ execute("insert into test1 values('B001', 0, 'z')");
82
+ execute("insert into test1 values('B002', 9, 'z')");
83
+
84
+ Path in1 = toPath("test1.csv");
85
+ TestingEmbulk.RunResult result1 = embulk.runOutput(baseConfig.merge(loadYamlResource(embulk, "test_truncate_insert_before_load.yml")), in1);
86
+ assertThat(selectRecords(embulk, "test1"), is(readResource("test_truncate_insert_before_load_expected.csv")));
87
+ //assertThat(result1.getConfigDiff(), is((ConfigDiff) loadYamlResource(embulk, "test_expected.diff")));
88
+ }
89
+
90
+ @Test
91
+ public void testMergeBeforeLoad() throws Exception
92
+ {
93
+ execute("insert into test1 values('A002', 1, 'y')");
94
+ execute("insert into test1 values('A003', 1, 'y')");
95
+ execute("insert into test1 values('B001', 0, 'z')");
96
+ execute("insert into test1 values('B002', 9, 'z')");
97
+
98
+ Path in1 = toPath("test1.csv");
99
+ TestingEmbulk.RunResult result1 = embulk.runOutput(baseConfig.merge(loadYamlResource(embulk, "test_merge_before_load.yml")), in1);
100
+ assertThat(selectRecords(embulk, "test1"), is(readResource("test_merge_before_load_expected.csv")));
101
+ //assertThat(result1.getConfigDiff(), is((ConfigDiff) loadYamlResource(embulk, "test_expected.diff")));
102
+ }
103
+
104
+ @Test
105
+ public void testMergeDirectBeforeLoad() throws Exception
106
+ {
107
+ execute("insert into test1 values('A002', 1, 'y')");
108
+ execute("insert into test1 values('A003', 1, 'y')");
109
+ execute("insert into test1 values('B001', 0, 'z')");
110
+ execute("insert into test1 values('B002', 9, 'z')");
111
+
112
+ Path in1 = toPath("test1.csv");
113
+ TestingEmbulk.RunResult result1 = embulk.runOutput(baseConfig.merge(loadYamlResource(embulk, "test_merge_direct_before_load.yml")), in1);
114
+ assertThat(selectRecords(embulk, "test1"), is(readResource("test_merge_before_load_expected.csv")));
115
+ //assertThat(result1.getConfigDiff(), is((ConfigDiff) loadYamlResource(embulk, "test_expected.diff")));
116
+ }
117
+
118
+ private Path toPath(String fileName) throws URISyntaxException
119
+ {
120
+ URL url = Resources.getResource(BASIC_RESOURCE_PATH + fileName);
121
+ return FileSystems.getDefault().getPath(new File(url.toURI()).getAbsolutePath());
122
+ }
123
+
124
+ }