embulk-output-mysql 0.2.4 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 54ae48d0cd8f8a4b20e470008c338d7f8f50a15f
4
- data.tar.gz: 30910e0ea400a868af1e9869ac4337029af5b02a
3
+ metadata.gz: b35f2d66f92a633b5326a958d7995b73f02f3737
4
+ data.tar.gz: a059b0f6436a26896cecf2e3bbfb6d305d109405
5
5
  SHA512:
6
- metadata.gz: d7ec8503e5ecd071de55099962d4bc1937ff49333110577e53310ba1d110a01f1b1c5f7d0659c6802db75fa888a91079f72ad98afd36c8482171531e35233664
7
- data.tar.gz: 7db52807e1444a4a17038720fc59ffafa9b9c87b83b83433a0acd693f809746e7a76a325adde92d6e8e79b0fe077e4a050ceb193327aa442a10710d6e35afe67
6
+ metadata.gz: 9bed384f0d48c7f46bb5bff652b78d2f11080ae569fb2c91229f184c07ef923379b0334f9563d8e3048944358138a8ba6865e14ea0c40033dd6a463846913674
7
+ data.tar.gz: 03ab7574a43af5fa86e9db38d9d7ad28221182724fc29c9ed5355d259040dcb9bb25f212bd79c2edb27b0361f625ca91ff64c1c8793515dd3dc744a1f7730dac
data/README.md CHANGED
@@ -1,42 +1,92 @@
1
- # MySQL output plugins for Embulk
2
-
3
- MySQL output plugins for Embulk loads records to MySQL.
4
-
5
- ## Overview
6
-
7
- * **Plugin type**: output
8
- * **Load all or nothing**: depnds on the mode:
9
- * **insert**: no
10
- * **replace**: yes
11
- * **Resume supported**: no
12
-
13
- ## Configuration
14
-
15
- - **host**: database host name (string, required)
16
- - **port**: database port number (integer, default: 3306)
17
- - **user**: database login user name (string, required)
18
- - **password**: database login password (string, default: "")
19
- - **database**: destination database name (string, required)
20
- - **table**: destination table name (string, required)
21
- - **mode**: "replace", "merge" or "insert" (string, required)
22
- - **batch_size**: size of a single batch insert (integer, default: 16777216)
23
- - **options**: extra connection properties (hash, default: {})
24
-
25
- ### Example
26
-
27
- ```yaml
28
- out:
29
- type: mysql
30
- host: localhost
31
- user: root
32
- password: ""
33
- database: my_database
34
- table: my_table
35
- mode: insert
36
- ```
37
-
38
- ### Build
39
-
40
- ```
41
- $ ./gradlew gem
42
- ```
1
+ # MySQL output plugins for Embulk
2
+
3
+ MySQL output plugins for Embulk loads records to MySQL.
4
+
5
+ ## Overview
6
+
7
+ * **Plugin type**: output
8
+ * **Load all or nothing**: depnds on the mode. see bellow.
9
+ * **Resume supported**: depnds on the mode. see bellow.
10
+
11
+ ## Configuration
12
+
13
+ - **host**: database host name (string, required)
14
+ - **port**: database port number (integer, default: 3306)
15
+ - **user**: database login user name (string, required)
16
+ - **password**: database login password (string, default: "")
17
+ - **database**: destination database name (string, required)
18
+ - **table**: destination table name (string, required)
19
+ - **options**: extra connection properties (hash, default: {})
20
+ - **mode**: "insert", "insert_direct", "truncate_insert", "merge", "merge_direct", or "replace". See bellow. (string, required)
21
+ - **batch_size**: size of a single batch insert (integer, default: 16777216)
22
+ - **default_timezone**: If input column type (embulk type) is timestamp and destination column type is `string` or `nstring`, this plugin needs to format the timestamp into a string. This default_timezone option is used to control the timezone. You can overwrite timezone for each columns using column_options option. (string, default: `UTC`)
23
+ - **column_options**: advanced: a key-value pairs where key is a column name and value is options for the column.
24
+ - **type**: type of a column when this plugin creates new tables (e.g. `VARCHAR(255)`, `INTEGER NOT NULL UNIQUE`). This used when this plugin creates intermediate tables (insert, insert_truncate and merge modes), when it creates the target table (insert_direct, merge_direct and replace modes), and when it creates nonexistent target table automatically. (string, default: depends on input column type. `BIGINT` if input column type is long, `BOOLEAN` if boolean, `DOUBLE PRECISION` if double, `CLOB` if string, `TIMESTAMP` if timestamp)
25
+ - **value_type**: This plugin converts input column type (embulk type) into a database type to build a INSERT statement. This value_type option controls the type of the value in a INSERT statement. (string, default: depends on input column type. Available values options are: `byte`, `short`, `int`, `long`, `double`, `float`, `boolean`, `string`, `nstring`, `date`, `time`, `timestamp`, `decimal`, `null`, `pass`)
26
+ - **timestamp_format**: If input column type (embulk type) is timestamp and value_type is `string` or `nstring`, this plugin needs to format the timestamp value into a string. This timestamp_format option is used to control the format of the timestamp. (string, default: `%Y-%m-%d %H:%M:%S.%6N`)
27
+ - **timezone**: If input column type (embulk type) is timestamp and value_type is `string` or `nstring`, this plugin needs to format the timestamp value into a string. And if the input column type is timestamp and value_type is `date`, this plugin needs to consider timezone. In those cases, this timezone option is used to control the timezone. (string, value of default_timezone option is used by default)
28
+
29
+ ### Modes
30
+
31
+ * **insert**:
32
+ * Behavior: This mode writes rows to some intermediate tables first. If all those tasks run correctly, runs `INSERT INTO <target_table> SELECT * FROM <intermediate_table_1> UNION ALL SELECT * FROM <intermediate_table_2> UNION ALL ...` query.
33
+ * Transactional: Yes. This mode successfully writes all rows, or fails with writing zero rows.
34
+ * Resumable: Yes.
35
+ * **insert_direct**:
36
+ * Behavior: This mode inserts rows to the target table directly.
37
+ * Transactional: No. If fails, the target table could have some rows inserted.
38
+ * Resumable: No.
39
+ * **truncate_insert**:
40
+ * Behavior: Same with `insert` mode excepting that it truncates the target table right before the last `INSERT ...` query.
41
+ * Transactional: Yes.
42
+ * Resumable: Yes.
43
+ * **merge**:
44
+ * Behavior: This mode writes rows to some intermediate tables first. If all those tasks run correctly, runs `INSERT INTO <target_table> SELECT * FROM <intermediate_table_1> UNION ALL SELECT * FROM <intermediate_table_2> UNION ALL ... ON DUPLICATE KEY UPDATE ...` query.
45
+ * Transactional: Yes.
46
+ * Resumable: Yes.
47
+ * **merge_direct**:
48
+ * Behavior: This mode inserts rows to the target table directory using `INSERT INTO ... ON DUPLICATE KEY UPDATE ...` query.
49
+ * Transactional: No.
50
+ * Resumable: No.
51
+ * **replace**:
52
+ * Behavior: Same with `insert` mode excepting that it truncates the target table right before the last `INSERT ...` query.
53
+ * Transactional: Yes.
54
+ * Resumable: No.
55
+
56
+ ### Example
57
+
58
+ ```yaml
59
+ out:
60
+ type: mysql
61
+ host: localhost
62
+ user: root
63
+ password: ""
64
+ database: my_database
65
+ table: my_table
66
+ mode: insert
67
+ ```
68
+
69
+ Advanced configuration:
70
+
71
+ ```yaml
72
+ out:
73
+ type: mysql
74
+ host: localhost
75
+ user: root
76
+ password: ""
77
+ database: my_database
78
+ table: my_table
79
+ options: {connectTimeout: 20000}
80
+ mode: insert_direct
81
+ column_options:
82
+ my_col_1: {type: 'TEXT'}
83
+ my_col_3: {type: 'INT NOT NULL'}
84
+ my_col_4: {value_type: string, timestamp_format: `%Y-%m-%d %H:%M:%S %z`, timezone: '-0700'}
85
+ my_col_5: {type: 'DECIMAL(18,9)', value_type: pass}
86
+ ```
87
+
88
+ ### Build
89
+
90
+ ```
91
+ $ ./gradlew gem
92
+ ```
@@ -1,7 +1,7 @@
1
- dependencies {
2
- compile project(':embulk-output-jdbc')
3
-
4
- compile 'mysql:mysql-connector-java:5.1.34'
5
-
6
- testCompile project(':embulk-output-jdbc').sourceSets.test.output
7
- }
1
+ dependencies {
2
+ compile project(':embulk-output-jdbc')
3
+
4
+ compile 'mysql:mysql-connector-java:5.1.34'
5
+
6
+ testCompile project(':embulk-output-jdbc').sourceSets.test.output
7
+ }
@@ -1,3 +1,3 @@
1
- Embulk::JavaPlugin.register_output(
2
- :mysql, "org.embulk.output.MySQLOutputPlugin",
3
- File.expand_path('../../../../classpath', __FILE__))
1
+ Embulk::JavaPlugin.register_output(
2
+ :mysql, "org.embulk.output.MySQLOutputPlugin",
3
+ File.expand_path('../../../../classpath', __FILE__))
@@ -1,10 +1,10 @@
1
1
  package org.embulk.output;
2
2
 
3
+ import java.util.List;
3
4
  import java.util.Properties;
4
5
  import java.io.IOException;
5
6
  import java.sql.SQLException;
6
-
7
- import org.embulk.output.mysql.MySQLBatchUpsert;
7
+ import com.google.common.base.Optional;
8
8
  import org.embulk.config.Config;
9
9
  import org.embulk.config.ConfigDefault;
10
10
  import org.embulk.output.jdbc.AbstractJdbcOutputPlugin;
@@ -42,6 +42,14 @@ public class MySQLOutputPlugin
42
42
  return MySQLPluginTask.class;
43
43
  }
44
44
 
45
+ @Override
46
+ protected Features getFeatures(PluginTask task)
47
+ {
48
+ return new Features()
49
+ .setMaxTableNameLength(64)
50
+ .setIgnoreMergeKeys(true);
51
+ }
52
+
45
53
  @Override
46
54
  protected MySQLOutputConnector getConnector(PluginTask task, boolean retryableMetadataOperation)
47
55
  {
@@ -51,8 +59,6 @@ public class MySQLOutputPlugin
51
59
  t.getHost(), t.getPort(), t.getDatabase());
52
60
 
53
61
  Properties props = new Properties();
54
- props.setProperty("user", t.getUser());
55
- props.setProperty("password", t.getPassword());
56
62
 
57
63
  props.setProperty("rewriteBatchedStatements", "true");
58
64
  props.setProperty("useCompression", "true");
@@ -88,13 +94,18 @@ public class MySQLOutputPlugin
88
94
 
89
95
  props.putAll(t.getOptions());
90
96
 
97
+ // TODO validate task.getMergeKeys is null
98
+
99
+ props.setProperty("user", t.getUser());
100
+ logger.info("Connecting to {} options {}", url, props);
101
+ props.setProperty("password", t.getPassword());
102
+
91
103
  return new MySQLOutputConnector(url, props);
92
104
  }
93
105
 
94
106
  @Override
95
- protected BatchInsert newBatchInsert(PluginTask task) throws IOException, SQLException
107
+ protected BatchInsert newBatchInsert(PluginTask task, Optional<List<String>> mergeKeys) throws IOException, SQLException
96
108
  {
97
- MySQLOutputConnector connector = getConnector(task, true);
98
- return task.getMode().isMerge() ? new MySQLBatchUpsert(connector) : new MySQLBatchInsert(connector);
109
+ return new MySQLBatchInsert(getConnector(task, true), mergeKeys);
99
110
  }
100
111
  }
@@ -1,36 +1,38 @@
1
- package org.embulk.output.mysql;
2
-
3
- import java.io.IOException;
4
- import java.sql.Types;
5
- import java.sql.PreparedStatement;
6
- import java.sql.SQLException;
7
- import org.embulk.output.jdbc.StandardBatchInsert;
8
-
9
- public class MySQLBatchInsert
10
- extends StandardBatchInsert
11
- {
12
- public MySQLBatchInsert(MySQLOutputConnector connector) throws IOException, SQLException
13
- {
14
- super(connector);
15
- }
16
-
17
- @Override
18
- public void setFloat(float v) throws IOException, SQLException
19
- {
20
- if (Float.isNaN(v) || Float.isInfinite(v)) {
21
- setNull(Types.REAL); // TODO get through argument
22
- } else {
23
- super.setFloat(v);
24
- }
25
- }
26
-
27
- @Override
28
- public void setDouble(double v) throws IOException, SQLException
29
- {
30
- if (Double.isNaN(v) || Double.isInfinite(v)) {
31
- setNull(Types.DOUBLE); // TODO get through argument
32
- } else {
33
- super.setDouble(v);
34
- }
35
- }
36
- }
1
+ package org.embulk.output.mysql;
2
+
3
+ import java.util.List;
4
+ import java.io.IOException;
5
+ import java.sql.Types;
6
+ import java.sql.PreparedStatement;
7
+ import java.sql.SQLException;
8
+ import com.google.common.base.Optional;
9
+ import org.embulk.output.jdbc.StandardBatchInsert;
10
+
11
+ public class MySQLBatchInsert
12
+ extends StandardBatchInsert
13
+ {
14
+ public MySQLBatchInsert(MySQLOutputConnector connector, Optional<List<String>> mergeKeys) throws IOException, SQLException
15
+ {
16
+ super(connector, mergeKeys);
17
+ }
18
+
19
+ @Override
20
+ public void setFloat(float v) throws IOException, SQLException
21
+ {
22
+ if (Float.isNaN(v) || Float.isInfinite(v)) {
23
+ setNull(Types.REAL); // TODO get through argument
24
+ } else {
25
+ super.setFloat(v);
26
+ }
27
+ }
28
+
29
+ @Override
30
+ public void setDouble(double v) throws IOException, SQLException
31
+ {
32
+ if (Double.isNaN(v) || Double.isInfinite(v)) {
33
+ setNull(Types.DOUBLE); // TODO get through argument
34
+ } else {
35
+ super.setDouble(v);
36
+ }
37
+ }
38
+ }
@@ -1,8 +1,9 @@
1
1
  package org.embulk.output.mysql;
2
2
 
3
+ import java.util.List;
3
4
  import java.sql.Connection;
4
5
  import java.sql.SQLException;
5
-
6
+ import org.embulk.output.jdbc.JdbcColumn;
6
7
  import org.embulk.output.jdbc.JdbcSchema;
7
8
  import org.embulk.output.jdbc.JdbcOutputConnection;
8
9
 
@@ -17,13 +18,12 @@ public class MySQLOutputConnection
17
18
  }
18
19
 
19
20
  @Override
20
- protected String buildPrepareUpsertSql(String toTable, JdbcSchema toTableSchema) throws SQLException
21
+ protected String buildPreparedMergeSql(String toTable, JdbcSchema toTableSchema, List<String> mergeKeys) throws SQLException
21
22
  {
22
23
  StringBuilder sb = new StringBuilder();
23
24
 
24
25
  sb.append("INSERT INTO ");
25
26
  quoteIdentifierString(sb, toTable);
26
-
27
27
  sb.append(" (");
28
28
  for (int i=0; i < toTableSchema.getCount(); i++) {
29
29
  if(i != 0) { sb.append(", "); }
@@ -35,11 +35,43 @@ public class MySQLOutputConnection
35
35
  sb.append("?");
36
36
  }
37
37
  sb.append(")");
38
-
39
38
  sb.append(" ON DUPLICATE KEY UPDATE ");
40
39
  for (int i=0; i < toTableSchema.getCount(); i++) {
41
40
  if(i != 0) { sb.append(", "); }
42
- final String columnName = quoteIdentifierString(toTableSchema.getColumnName(i));
41
+ String columnName = quoteIdentifierString(toTableSchema.getColumnName(i));
42
+ sb.append(columnName).append(" = VALUES(").append(columnName).append(")");
43
+ }
44
+
45
+ return sb.toString();
46
+ }
47
+
48
+ @Override
49
+ protected String buildCollectMergeSql(List<String> fromTables, JdbcSchema schema, String toTable, List<String> mergeKeys) throws SQLException
50
+ {
51
+ StringBuilder sb = new StringBuilder();
52
+
53
+ sb.append("INSERT INTO ");
54
+ quoteIdentifierString(sb, toTable);
55
+ sb.append(" (");
56
+ for (int i=0; i < schema.getCount(); i++) {
57
+ if (i != 0) { sb.append(", "); }
58
+ quoteIdentifierString(sb, schema.getColumnName(i));
59
+ }
60
+ sb.append(") ");
61
+ for (int i=0; i < fromTables.size(); i++) {
62
+ if (i != 0) { sb.append(" UNION ALL "); }
63
+ sb.append("SELECT ");
64
+ for (int j=0; j < schema.getCount(); j++) {
65
+ if (j != 0) { sb.append(", "); }
66
+ quoteIdentifierString(sb, schema.getColumnName(j));
67
+ }
68
+ sb.append(" FROM ");
69
+ quoteIdentifierString(sb, fromTables.get(i));
70
+ }
71
+ sb.append(" ON DUPLICATE KEY UPDATE ");
72
+ for (int i=0; i < schema.getCount(); i++) {
73
+ if(i != 0) { sb.append(", "); }
74
+ String columnName = quoteIdentifierString(schema.getColumnName(i));
43
75
  sb.append(columnName).append(" = VALUES(").append(columnName).append(")");
44
76
  }
45
77
 
@@ -47,13 +79,13 @@ public class MySQLOutputConnection
47
79
  }
48
80
 
49
81
  @Override
50
- protected String convertTypeName(String typeName)
82
+ protected String buildColumnTypeName(JdbcColumn c)
51
83
  {
52
- switch(typeName) {
84
+ switch(c.getSimpleTypeName()) {
53
85
  case "CLOB":
54
86
  return "TEXT";
55
87
  default:
56
- return typeName;
88
+ return super.buildColumnTypeName(c);
57
89
  }
58
90
  }
59
91
  }
@@ -1,42 +1,42 @@
1
- package org.embulk.output.mysql;
2
-
3
- import java.util.Properties;
4
- import java.sql.Driver;
5
- import java.sql.Connection;
6
- import java.sql.SQLException;
7
- import org.embulk.output.jdbc.JdbcOutputConnector;
8
- import org.embulk.output.jdbc.JdbcOutputConnection;
9
-
10
- public class MySQLOutputConnector
11
- implements JdbcOutputConnector
12
- {
13
- private final Driver driver;
14
- private final String url;
15
- private final Properties properties;
16
-
17
- public MySQLOutputConnector(String url, Properties properties)
18
- {
19
- try {
20
- this.driver = new com.mysql.jdbc.Driver(); // new com.mysql.jdbc.Driver throws SQLException
21
- } catch (SQLException ex) {
22
- throw new RuntimeException(ex);
23
- }
24
- this.url = url;
25
- this.properties = properties;
26
- }
27
-
28
- @Override
29
- public MySQLOutputConnection connect(boolean autoCommit) throws SQLException
30
- {
31
- Connection c = driver.connect(url, properties);
32
- try {
33
- MySQLOutputConnection con = new MySQLOutputConnection(c, autoCommit);
34
- c = null;
35
- return con;
36
- } finally {
37
- if (c != null) {
38
- c.close();
39
- }
40
- }
41
- }
42
- }
1
+ package org.embulk.output.mysql;
2
+
3
+ import java.util.Properties;
4
+ import java.sql.Driver;
5
+ import java.sql.Connection;
6
+ import java.sql.SQLException;
7
+ import org.embulk.output.jdbc.JdbcOutputConnector;
8
+ import org.embulk.output.jdbc.JdbcOutputConnection;
9
+
10
+ public class MySQLOutputConnector
11
+ implements JdbcOutputConnector
12
+ {
13
+ private final Driver driver;
14
+ private final String url;
15
+ private final Properties properties;
16
+
17
+ public MySQLOutputConnector(String url, Properties properties)
18
+ {
19
+ try {
20
+ this.driver = new com.mysql.jdbc.Driver(); // new com.mysql.jdbc.Driver throws SQLException
21
+ } catch (SQLException ex) {
22
+ throw new RuntimeException(ex);
23
+ }
24
+ this.url = url;
25
+ this.properties = properties;
26
+ }
27
+
28
+ @Override
29
+ public MySQLOutputConnection connect(boolean autoCommit) throws SQLException
30
+ {
31
+ Connection c = driver.connect(url, properties);
32
+ try {
33
+ MySQLOutputConnection con = new MySQLOutputConnection(c, autoCommit);
34
+ c = null;
35
+ return con;
36
+ } finally {
37
+ if (c != null) {
38
+ c.close();
39
+ }
40
+ }
41
+ }
42
+ }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: embulk-output-mysql
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.4
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sadayuki Furuhashi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-05-12 00:00:00.000000000 Z
11
+ date: 2015-05-19 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Inserts or updates records to a table.
14
14
  email:
@@ -22,11 +22,10 @@ files:
22
22
  - lib/embulk/output/mysql.rb
23
23
  - src/main/java/org/embulk/output/MySQLOutputPlugin.java
24
24
  - src/main/java/org/embulk/output/mysql/MySQLBatchInsert.java
25
- - src/main/java/org/embulk/output/mysql/MySQLBatchUpsert.java
26
25
  - src/main/java/org/embulk/output/mysql/MySQLOutputConnection.java
27
26
  - src/main/java/org/embulk/output/mysql/MySQLOutputConnector.java
28
- - classpath/embulk-output-jdbc-0.2.4.jar
29
- - classpath/embulk-output-mysql-0.2.4.jar
27
+ - classpath/embulk-output-jdbc-0.3.0.jar
28
+ - classpath/embulk-output-mysql-0.3.0.jar
30
29
  - classpath/mysql-connector-java-5.1.34.jar
31
30
  homepage: https://github.com/embulk/embulk-output-jdbc
32
31
  licenses:
@@ -1,22 +0,0 @@
1
- package org.embulk.output.mysql;
2
-
3
- import org.embulk.output.jdbc.JdbcOutputConnection;
4
- import org.embulk.output.jdbc.JdbcSchema;
5
- import java.io.IOException;
6
- import java.sql.PreparedStatement;
7
- import java.sql.SQLException;
8
-
9
- public class MySQLBatchUpsert extends MySQLBatchInsert {
10
-
11
- public MySQLBatchUpsert(MySQLOutputConnector connector) throws IOException, SQLException {
12
- super(connector);
13
- }
14
-
15
- @Override
16
- protected PreparedStatement newPreparedStatement(JdbcOutputConnection connection,
17
- String loadTable, JdbcSchema insertSchema) throws SQLException
18
- {
19
- return connection.prepareUpsertSql(loadTable, insertSchema);
20
- }
21
-
22
- }