embulk-output-mysql 0.2.4 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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
- }