embulk-output-jdbc 0.2.4 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/build.gradle +2 -2
  3. data/classpath/embulk-output-jdbc-0.3.0.jar +0 -0
  4. data/lib/embulk/output/jdbc.rb +3 -3
  5. data/src/main/java/org/embulk/output/JdbcOutputPlugin.java +138 -120
  6. data/src/main/java/org/embulk/output/jdbc/AbstractJdbcOutputPlugin.java +964 -755
  7. data/src/main/java/org/embulk/output/jdbc/BatchInsert.java +54 -54
  8. data/src/main/java/org/embulk/output/jdbc/JdbcColumn.java +59 -23
  9. data/src/main/java/org/embulk/output/jdbc/JdbcColumnOption.java +34 -0
  10. data/src/main/java/org/embulk/output/jdbc/JdbcOutputConnection.java +95 -114
  11. data/src/main/java/org/embulk/output/jdbc/JdbcOutputConnector.java +8 -8
  12. data/src/main/java/org/embulk/output/jdbc/JdbcSchema.java +60 -37
  13. data/src/main/java/org/embulk/output/jdbc/JdbcUtils.java +155 -155
  14. data/src/main/java/org/embulk/output/jdbc/StandardBatchInsert.java +8 -5
  15. data/src/main/java/org/embulk/output/jdbc/setter/BigDecimalColumnSetter.java +70 -0
  16. data/src/main/java/org/embulk/output/jdbc/setter/BooleanColumnSetter.java +54 -52
  17. data/src/main/java/org/embulk/output/jdbc/setter/ByteColumnSetter.java +76 -0
  18. data/src/main/java/org/embulk/output/jdbc/setter/ColumnSetter.java +10 -91
  19. data/src/main/java/org/embulk/output/jdbc/setter/ColumnSetterFactory.java +189 -137
  20. data/src/main/java/org/embulk/output/jdbc/setter/ColumnSetterVisitor.java +96 -0
  21. data/src/main/java/org/embulk/output/jdbc/setter/DefaultValueSetter.java +48 -0
  22. data/src/main/java/org/embulk/output/jdbc/setter/DoubleColumnSetter.java +61 -51
  23. data/src/main/java/org/embulk/output/jdbc/setter/FloatColumnSetter.java +61 -0
  24. data/src/main/java/org/embulk/output/jdbc/setter/IntColumnSetter.java +76 -0
  25. data/src/main/java/org/embulk/output/jdbc/setter/LongColumnSetter.java +72 -62
  26. data/src/main/java/org/embulk/output/jdbc/setter/NStringColumnSetter.java +59 -0
  27. data/src/main/java/org/embulk/output/jdbc/setter/NullColumnSetter.java +53 -43
  28. data/src/main/java/org/embulk/output/jdbc/setter/NullDefaultValueSetter.java +105 -0
  29. data/src/main/java/org/embulk/output/jdbc/setter/PassThroughColumnSetter.java +56 -0
  30. data/src/main/java/org/embulk/output/jdbc/setter/ShortColumnSetter.java +76 -0
  31. data/src/main/java/org/embulk/output/jdbc/setter/SkipColumnSetter.java +43 -38
  32. data/src/main/java/org/embulk/output/jdbc/setter/SqlDateColumnSetter.java +63 -0
  33. data/src/main/java/org/embulk/output/jdbc/setter/SqlTimeColumnSetter.java +55 -0
  34. data/src/main/java/org/embulk/output/jdbc/setter/SqlTimestampColumnSetter.java +55 -48
  35. data/src/main/java/org/embulk/output/jdbc/setter/StringColumnSetter.java +59 -48
  36. data/src/test/java/org/embulk/output/TestJdbcOutputPlugin.java +5 -5
  37. metadata +16 -4
  38. data/classpath/embulk-output-jdbc-0.2.4.jar +0 -0
  39. data/src/main/java/org/embulk/output/jdbc/RetryExecutor.java +0 -105
@@ -1,8 +1,8 @@
1
- package org.embulk.output.jdbc;
2
-
3
- import java.sql.SQLException;
4
-
5
- public interface JdbcOutputConnector
6
- {
7
- public JdbcOutputConnection connect(boolean autoCommit) throws SQLException;
8
- }
1
+ package org.embulk.output.jdbc;
2
+
3
+ import java.sql.SQLException;
4
+
5
+ public interface JdbcOutputConnector
6
+ {
7
+ public JdbcOutputConnection connect(boolean autoCommit) throws SQLException;
8
+ }
@@ -1,37 +1,60 @@
1
- package org.embulk.output.jdbc;
2
-
3
- import java.util.List;
4
- import com.fasterxml.jackson.annotation.JsonCreator;
5
- import com.fasterxml.jackson.annotation.JsonValue;
6
-
7
- public class JdbcSchema
8
- {
9
- private List<JdbcColumn> columns;
10
-
11
- @JsonCreator
12
- public JdbcSchema(List<JdbcColumn> columns)
13
- {
14
- this.columns = columns;
15
- }
16
-
17
- @JsonValue
18
- public List<JdbcColumn> getColumns()
19
- {
20
- return columns;
21
- }
22
-
23
- public int getCount()
24
- {
25
- return columns.size();
26
- }
27
-
28
- public JdbcColumn getColumn(int i)
29
- {
30
- return columns.get(i);
31
- }
32
-
33
- public String getColumnName(int i)
34
- {
35
- return columns.get(i).getName();
36
- }
37
- }
1
+ package org.embulk.output.jdbc;
2
+
3
+ import java.util.List;
4
+ import com.google.common.base.Optional;
5
+ import com.google.common.collect.ImmutableList;
6
+ import com.fasterxml.jackson.annotation.JsonCreator;
7
+ import com.fasterxml.jackson.annotation.JsonValue;
8
+
9
+ public class JdbcSchema
10
+ {
11
+ private List<JdbcColumn> columns;
12
+
13
+ @JsonCreator
14
+ public JdbcSchema(List<JdbcColumn> columns)
15
+ {
16
+ this.columns = columns;
17
+ }
18
+
19
+ @JsonValue
20
+ public List<JdbcColumn> getColumns()
21
+ {
22
+ return columns;
23
+ }
24
+
25
+ public Optional<JdbcColumn> findColumn(String name)
26
+ {
27
+ for (JdbcColumn column : columns) {
28
+ if (column.getName().equals(name)) {
29
+ return Optional.of(column);
30
+ }
31
+ }
32
+ return Optional.absent();
33
+ }
34
+
35
+ public int getCount()
36
+ {
37
+ return columns.size();
38
+ }
39
+
40
+ public JdbcColumn getColumn(int i)
41
+ {
42
+ return columns.get(i);
43
+ }
44
+
45
+ public String getColumnName(int i)
46
+ {
47
+ return columns.get(i).getName();
48
+ }
49
+
50
+ public static JdbcSchema filterSkipColumns(JdbcSchema schema)
51
+ {
52
+ ImmutableList.Builder<JdbcColumn> builder = ImmutableList.builder();
53
+ for (JdbcColumn c : schema.getColumns()) {
54
+ if (!c.isSkipColumn()) {
55
+ builder.add(c);
56
+ }
57
+ }
58
+ return new JdbcSchema(builder.build());
59
+ }
60
+ }
@@ -1,155 +1,155 @@
1
- package org.embulk.output.jdbc;
2
-
3
- import java.sql.Connection;
4
- import java.sql.PreparedStatement;
5
- import java.sql.SQLException;
6
- import java.sql.Statement;
7
- import java.util.regex.Matcher;
8
- import java.util.regex.Pattern;
9
- import org.slf4j.Logger;
10
- import org.embulk.spi.Exec;
11
-
12
- public class JdbcUtils
13
- {
14
- public final Logger logger = Exec.getLogger(JdbcUtils.class.getName());
15
-
16
- private static String[] SEARCH_STRING_SPECIAL_CHARS = new String[] { "_", "%" };
17
-
18
- public static String escapeSearchString(String searchString, String escapeString)
19
- {
20
- if (searchString != null && escapeString != null) {
21
- // First of all, escape escapeString '\' itself: '\' -> '\\'
22
- searchString = searchString.replaceAll(Pattern.quote(escapeString),
23
- Matcher.quoteReplacement(escapeString + escapeString));
24
- for (String specialChar : SEARCH_STRING_SPECIAL_CHARS) {
25
- if (specialChar.equals(escapeString)) {
26
- throw new IllegalArgumentException("Special char " + specialChar + " cannot be an escape char");
27
- }
28
- searchString = searchString.replaceAll(Pattern.quote(specialChar),
29
- Matcher.quoteReplacement(escapeString + specialChar));
30
- }
31
- }
32
- return searchString;
33
- }
34
-
35
- private Class<?> connectionClass;
36
-
37
- // Connection.isValid() is available from Java 1.6 + JDBC4.
38
- //private boolean hasIsValid;
39
-
40
- // Connection.setNetworkTimeout() is available from Java 1.7 + JDBC4.
41
- //private boolean hasSetNetworkTimeout;
42
- //private Method setNetworkTimeoutMethod;
43
-
44
- public JdbcUtils(Class<?> connectionClass)
45
- {
46
- this.connectionClass = connectionClass;
47
-
48
- //configureSetNetworkTimeout();
49
- }
50
-
51
- public int executeUpdateWithSqlLogging(Statement stmt, String sql) throws SQLException
52
- {
53
- logger.info("SQL: " + sql);
54
- long startTime = System.currentTimeMillis();
55
- int count = stmt.executeUpdate(sql);
56
- double seconds = (System.currentTimeMillis() - startTime) / 1000.0;
57
- if (count == 0) {
58
- logger.info(String.format("> %.2f seconds", seconds));
59
- } else {
60
- logger.info(String.format("> %.2f seconds (%,d rows)", seconds, count));
61
- }
62
- return count;
63
- }
64
-
65
- //private void configureSetNetworkTimeout() {
66
- // try {
67
- // Method m = connectionClass.getMethod("setNetworkTimeout", Executor.class, int.class);
68
- // if (isCallableMethod(m)) {
69
- // setNetworkTimeoutMethod = m;
70
- // hasSetNetworkTimeout = true;
71
- // }
72
- // } catch (SecurityException ex) {
73
- // } catch (NoSuchMethodException ex) {
74
- // }
75
- //}
76
-
77
- //private boolean isCallableMethod(Method m) {
78
- // int modifiers = m.getModifiers();
79
- // if (Modifier.isAbstract(modifiers)) {
80
- // // Method.invoke throws java.lang.AbstractMethodError if it's an
81
- // // abstract method. Applications can't catch AbstractMethodError.
82
- // return false;
83
- // }
84
- // if (!Modifier.isPublic(modifiers)) {
85
- // // we can only call public methods
86
- // return false;
87
- // }
88
- // return true;
89
- //}
90
-
91
- // PostgreSQL JDBC driver implements isValid() method. But the
92
- // implementation throws following exception:
93
- // "java.io.IOException: Method org.postgresql.jdbc4.Jdbc4Connection.isValid(int) is not yet implemented."
94
- //
95
- // So, checking mechanism doesn't work at all.
96
- // Thus here just runs "SELECT 1" to check connectivity.
97
- //
98
- //public boolean isValidConnection(Connection connection, int timeout) throws SQLException
99
- //{
100
- // Statement stmt = connection.createStatement();
101
- // try {
102
- // stmt.executeQuery("SELECT 1").close();
103
- // return true;
104
- // } catch (SQLException ex) {
105
- // return false;
106
- // } finally {
107
- // stmt.close();
108
- // }
109
- //}
110
-
111
- //public void setNetworkTimeout(Connection connection,
112
- // Executor executor, int milliseconds) throws SQLException {
113
- // Throwable exception = null;
114
- // if (hasSetNetworkTimeout) {
115
- // try {
116
- // setNetworkTimeoutMethod.invoke(connection, executor, milliseconds);
117
- // return;
118
- //
119
- // } catch (IllegalArgumentException ex) {
120
- // // ignore error
121
- // LOG.warn("Connection.setNetworkTimeout failed due to IllegalArgumentException.");
122
- // exception = ex;
123
- //
124
- // } catch (IllegalAccessException ex) {
125
- // // ignore error
126
- // LOG.warn("Connection.setNetworkTimeout failed due to IllegalAccessException.");
127
- // exception = ex;
128
- //
129
- // } catch (InvocationTargetException ex) {
130
- // //Throwable cause = ex.getTargetException();
131
- // //if (cause instanceof SQLException) {
132
- // // throw (SQLException) cause;
133
- // //} else if (cause instanceof RuntimeException) {
134
- // // throw (RuntimeException) cause;
135
- // //} else if (cause instanceof Error) {
136
- // // throw (Error) cause;
137
- // //} else {
138
- // // throw new SQLException(cause);
139
- // //}
140
- // exception = ex.getTargetException();
141
- // // It's safe to ignore exceptions.
142
- // }
143
- //
144
- // hasSetNetworkTimeout = false;
145
- // }
146
- //
147
- // if (exception != null) {
148
- // LOG.warn("Connection.setNetworkTimeout is not available: "+exception);
149
- // } else {
150
- // LOG.warn("Connection.setNetworkTimeout is not available.");
151
- // }
152
- // // TODO any substitute implementations?
153
- //}
154
- }
155
-
1
+ package org.embulk.output.jdbc;
2
+
3
+ import java.sql.Connection;
4
+ import java.sql.PreparedStatement;
5
+ import java.sql.SQLException;
6
+ import java.sql.Statement;
7
+ import java.util.regex.Matcher;
8
+ import java.util.regex.Pattern;
9
+ import org.slf4j.Logger;
10
+ import org.embulk.spi.Exec;
11
+
12
+ public class JdbcUtils
13
+ {
14
+ public final Logger logger = Exec.getLogger(JdbcUtils.class.getName());
15
+
16
+ private static String[] SEARCH_STRING_SPECIAL_CHARS = new String[] { "_", "%" };
17
+
18
+ public static String escapeSearchString(String searchString, String escapeString)
19
+ {
20
+ if (searchString != null && escapeString != null) {
21
+ // First of all, escape escapeString '\' itself: '\' -> '\\'
22
+ searchString = searchString.replaceAll(Pattern.quote(escapeString),
23
+ Matcher.quoteReplacement(escapeString + escapeString));
24
+ for (String specialChar : SEARCH_STRING_SPECIAL_CHARS) {
25
+ if (specialChar.equals(escapeString)) {
26
+ throw new IllegalArgumentException("Special char " + specialChar + " cannot be an escape char");
27
+ }
28
+ searchString = searchString.replaceAll(Pattern.quote(specialChar),
29
+ Matcher.quoteReplacement(escapeString + specialChar));
30
+ }
31
+ }
32
+ return searchString;
33
+ }
34
+
35
+ private Class<?> connectionClass;
36
+
37
+ // Connection.isValid() is available from Java 1.6 + JDBC4.
38
+ //private boolean hasIsValid;
39
+
40
+ // Connection.setNetworkTimeout() is available from Java 1.7 + JDBC4.
41
+ //private boolean hasSetNetworkTimeout;
42
+ //private Method setNetworkTimeoutMethod;
43
+
44
+ public JdbcUtils(Class<?> connectionClass)
45
+ {
46
+ this.connectionClass = connectionClass;
47
+
48
+ //configureSetNetworkTimeout();
49
+ }
50
+
51
+ public int executeUpdateWithSqlLogging(Statement stmt, String sql) throws SQLException
52
+ {
53
+ logger.info("SQL: " + sql);
54
+ long startTime = System.currentTimeMillis();
55
+ int count = stmt.executeUpdate(sql);
56
+ double seconds = (System.currentTimeMillis() - startTime) / 1000.0;
57
+ if (count == 0) {
58
+ logger.info(String.format("> %.2f seconds", seconds));
59
+ } else {
60
+ logger.info(String.format("> %.2f seconds (%,d rows)", seconds, count));
61
+ }
62
+ return count;
63
+ }
64
+
65
+ //private void configureSetNetworkTimeout() {
66
+ // try {
67
+ // Method m = connectionClass.getMethod("setNetworkTimeout", Executor.class, int.class);
68
+ // if (isCallableMethod(m)) {
69
+ // setNetworkTimeoutMethod = m;
70
+ // hasSetNetworkTimeout = true;
71
+ // }
72
+ // } catch (SecurityException ex) {
73
+ // } catch (NoSuchMethodException ex) {
74
+ // }
75
+ //}
76
+
77
+ //private boolean isCallableMethod(Method m) {
78
+ // int modifiers = m.getModifiers();
79
+ // if (Modifier.isAbstract(modifiers)) {
80
+ // // Method.invoke throws java.lang.AbstractMethodError if it's an
81
+ // // abstract method. Applications can't catch AbstractMethodError.
82
+ // return false;
83
+ // }
84
+ // if (!Modifier.isPublic(modifiers)) {
85
+ // // we can only call public methods
86
+ // return false;
87
+ // }
88
+ // return true;
89
+ //}
90
+
91
+ // PostgreSQL JDBC driver implements isValid() method. But the
92
+ // implementation throws following exception:
93
+ // "java.io.IOException: Method org.postgresql.jdbc4.Jdbc4Connection.isValid(int) is not yet implemented."
94
+ //
95
+ // So, checking mechanism doesn't work at all.
96
+ // Thus here just runs "SELECT 1" to check connectivity.
97
+ //
98
+ //public boolean isValidConnection(Connection connection, int timeout) throws SQLException
99
+ //{
100
+ // Statement stmt = connection.createStatement();
101
+ // try {
102
+ // stmt.executeQuery("SELECT 1").close();
103
+ // return true;
104
+ // } catch (SQLException ex) {
105
+ // return false;
106
+ // } finally {
107
+ // stmt.close();
108
+ // }
109
+ //}
110
+
111
+ //public void setNetworkTimeout(Connection connection,
112
+ // Executor executor, int milliseconds) throws SQLException {
113
+ // Throwable exception = null;
114
+ // if (hasSetNetworkTimeout) {
115
+ // try {
116
+ // setNetworkTimeoutMethod.invoke(connection, executor, milliseconds);
117
+ // return;
118
+ //
119
+ // } catch (IllegalArgumentException ex) {
120
+ // // ignore error
121
+ // LOG.warn("Connection.setNetworkTimeout failed due to IllegalArgumentException.");
122
+ // exception = ex;
123
+ //
124
+ // } catch (IllegalAccessException ex) {
125
+ // // ignore error
126
+ // LOG.warn("Connection.setNetworkTimeout failed due to IllegalAccessException.");
127
+ // exception = ex;
128
+ //
129
+ // } catch (InvocationTargetException ex) {
130
+ // //Throwable cause = ex.getTargetException();
131
+ // //if (cause instanceof SQLException) {
132
+ // // throw (SQLException) cause;
133
+ // //} else if (cause instanceof RuntimeException) {
134
+ // // throw (RuntimeException) cause;
135
+ // //} else if (cause instanceof Error) {
136
+ // // throw (Error) cause;
137
+ // //} else {
138
+ // // throw new SQLException(cause);
139
+ // //}
140
+ // exception = ex.getTargetException();
141
+ // // It's safe to ignore exceptions.
142
+ // }
143
+ //
144
+ // hasSetNetworkTimeout = false;
145
+ // }
146
+ //
147
+ // if (exception != null) {
148
+ // LOG.warn("Connection.setNetworkTimeout is not available: "+exception);
149
+ // } else {
150
+ // LOG.warn("Connection.setNetworkTimeout is not available.");
151
+ // }
152
+ // // TODO any substitute implementations?
153
+ //}
154
+ }
155
+
@@ -1,5 +1,6 @@
1
1
  package org.embulk.output.jdbc;
2
2
 
3
+ import java.util.List;
3
4
  import java.io.IOException;
4
5
  import java.math.BigDecimal;
5
6
  import java.sql.PreparedStatement;
@@ -7,6 +8,7 @@ import java.sql.SQLException;
7
8
  import java.sql.Date;
8
9
  import java.sql.Time;
9
10
  import java.sql.Timestamp;
11
+ import com.google.common.base.Optional;
10
12
  import org.slf4j.Logger;
11
13
  import org.embulk.spi.Exec;
12
14
 
@@ -16,6 +18,7 @@ public class StandardBatchInsert
16
18
  private final Logger logger = Exec.getLogger(StandardBatchInsert.class);
17
19
 
18
20
  private final JdbcOutputConnector connector;
21
+ private final Optional<List<String>> mergeKeys;
19
22
 
20
23
  private JdbcOutputConnection connection;
21
24
  private PreparedStatement batch;
@@ -24,25 +27,25 @@ public class StandardBatchInsert
24
27
  private int batchRows;
25
28
  private long totalRows;
26
29
 
27
- public StandardBatchInsert(JdbcOutputConnector connector) throws IOException, SQLException
30
+ public StandardBatchInsert(JdbcOutputConnector connector, Optional<List<String>> mergeKeys) throws IOException, SQLException
28
31
  {
29
32
  this.connector = connector;
33
+ this.mergeKeys = mergeKeys;
30
34
  }
31
35
 
32
36
  public void prepare(String loadTable, JdbcSchema insertSchema) throws SQLException
33
37
  {
34
38
  this.connection = connector.connect(true);
35
- this.batch = newPreparedStatement(connection, loadTable, insertSchema);
36
39
  this.index = 1; // PreparedStatement index begings from 1
37
40
  this.batchRows = 0;
38
41
  this.totalRows = 0;
42
+ this.batch = prepareStatement(loadTable, insertSchema);
39
43
  batch.clearBatch();
40
44
  }
41
45
 
42
- protected PreparedStatement newPreparedStatement(JdbcOutputConnection connection,
43
- String loadTable, JdbcSchema insertSchema) throws SQLException
46
+ protected PreparedStatement prepareStatement(String loadTable, JdbcSchema insertSchema) throws SQLException
44
47
  {
45
- return connection.prepareInsertSql(loadTable, insertSchema);
48
+ return connection.prepareBatchInsertStatement(loadTable, insertSchema, mergeKeys);
46
49
  }
47
50
 
48
51
  public int getBatchWeight()