embulk-output-teradata 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/.DS_Store +0 -0
  3. data/README.md +0 -8
  4. data/build.gradle +5 -2
  5. data/embulk-output-teradata.iml +12 -0
  6. data/gradle/wrapper/gradle-wrapper.properties +2 -2
  7. data/gradlew +0 -0
  8. data/lib/embulk-output-jdbc-0.7.11.jar +0 -0
  9. data/src/main/java/org/embulk/output/teradata/TeradataOutputPlugin.java +13 -52
  10. data/src/main/java/org/embulk/output/teradata/jdbc/TeradataBatchInsert.java +37 -0
  11. data/src/main/java/org/embulk/output/teradata/jdbc/TeradataOutputConnection.java +307 -0
  12. data/src/main/java/org/embulk/output/teradata/jdbc/TeradataOutputConnector.java +46 -0
  13. metadata +10 -40
  14. data/src/main/java/org/embulk/output/teradata/JdbcOutputPlugin.java +0 -134
  15. data/src/main/java/org/embulk/output/teradata/TeradataOutputConnection.java +0 -19
  16. data/src/main/java/org/embulk/output/teradata/jdbc/AbstractJdbcOutputPlugin.java +0 -1144
  17. data/src/main/java/org/embulk/output/teradata/jdbc/BatchInsert.java +0 -52
  18. data/src/main/java/org/embulk/output/teradata/jdbc/JdbcColumn.java +0 -134
  19. data/src/main/java/org/embulk/output/teradata/jdbc/JdbcColumnOption.java +0 -34
  20. data/src/main/java/org/embulk/output/teradata/jdbc/JdbcOutputConnection.java +0 -549
  21. data/src/main/java/org/embulk/output/teradata/jdbc/JdbcOutputConnector.java +0 -8
  22. data/src/main/java/org/embulk/output/teradata/jdbc/JdbcSchema.java +0 -79
  23. data/src/main/java/org/embulk/output/teradata/jdbc/JdbcUtils.java +0 -153
  24. data/src/main/java/org/embulk/output/teradata/jdbc/MergeConfig.java +0 -23
  25. data/src/main/java/org/embulk/output/teradata/jdbc/StandardBatchInsert.java +0 -201
  26. data/src/main/java/org/embulk/output/teradata/jdbc/TimestampFormat.java +0 -37
  27. data/src/main/java/org/embulk/output/teradata/jdbc/ToString.java +0 -54
  28. data/src/main/java/org/embulk/output/teradata/jdbc/ToStringMap.java +0 -34
  29. data/src/main/java/org/embulk/output/teradata/jdbc/setter/BigDecimalColumnSetter.java +0 -76
  30. data/src/main/java/org/embulk/output/teradata/jdbc/setter/BooleanColumnSetter.java +0 -61
  31. data/src/main/java/org/embulk/output/teradata/jdbc/setter/ByteColumnSetter.java +0 -84
  32. data/src/main/java/org/embulk/output/teradata/jdbc/setter/ColumnSetter.java +0 -48
  33. data/src/main/java/org/embulk/output/teradata/jdbc/setter/ColumnSetterFactory.java +0 -199
  34. data/src/main/java/org/embulk/output/teradata/jdbc/setter/ColumnSetterVisitor.java +0 -110
  35. data/src/main/java/org/embulk/output/teradata/jdbc/setter/DefaultValueSetter.java +0 -50
  36. data/src/main/java/org/embulk/output/teradata/jdbc/setter/DoubleColumnSetter.java +0 -68
  37. data/src/main/java/org/embulk/output/teradata/jdbc/setter/FloatColumnSetter.java +0 -68
  38. data/src/main/java/org/embulk/output/teradata/jdbc/setter/IntColumnSetter.java +0 -84
  39. data/src/main/java/org/embulk/output/teradata/jdbc/setter/JsonColumnSetter.java +0 -61
  40. data/src/main/java/org/embulk/output/teradata/jdbc/setter/LongColumnSetter.java +0 -80
  41. data/src/main/java/org/embulk/output/teradata/jdbc/setter/NStringColumnSetter.java +0 -66
  42. data/src/main/java/org/embulk/output/teradata/jdbc/setter/NullColumnSetter.java +0 -61
  43. data/src/main/java/org/embulk/output/teradata/jdbc/setter/NullDefaultValueSetter.java +0 -111
  44. data/src/main/java/org/embulk/output/teradata/jdbc/setter/PassThroughColumnSetter.java +0 -66
  45. data/src/main/java/org/embulk/output/teradata/jdbc/setter/ShortColumnSetter.java +0 -84
  46. data/src/main/java/org/embulk/output/teradata/jdbc/setter/SkipColumnSetter.java +0 -49
  47. data/src/main/java/org/embulk/output/teradata/jdbc/setter/SqlDateColumnSetter.java +0 -66
  48. data/src/main/java/org/embulk/output/teradata/jdbc/setter/SqlTimeColumnSetter.java +0 -66
  49. data/src/main/java/org/embulk/output/teradata/jdbc/setter/SqlTimestampColumnSetter.java +0 -66
  50. data/src/main/java/org/embulk/output/teradata/jdbc/setter/StringColumnSetter.java +0 -66
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f842427d2bb1abc2570877c1f67c24d3815667e9
4
- data.tar.gz: 4e2029b8b0a6690025c81799cc175b6025f4aadb
3
+ metadata.gz: 1576a329c01404b00bfd22be516a1cdf3a1a06eb
4
+ data.tar.gz: cdf50889dd17602ffd2e1bed867277c0fdfbe9f1
5
5
  SHA512:
6
- metadata.gz: 911f4df3c54ffcb1b9961250cf001a2c7f129bd06f5d24c6060c58367ec9e9c8c3ce36107827cf841c994676d057556feab03110b0b2df41ed8fe1c5dc3a6906
7
- data.tar.gz: e197945ceb751127d85af9eaf6cf2ed7a276befdfe1c6db9d40d8b7a0d2998d19eae05505e3014b67033bc259ec6965fbb9646fa91b7da7bf2ee9ac50eaee0a1
6
+ metadata.gz: 12bc72528547067922f58487932e1a282ccf9f676fe0268519bec8450993ae242ae4c2781ff4ab84127b494117dcfe82365454e10a9b161040a68cd94aa9c3bd
7
+ data.tar.gz: 2a64ff07020a0c7a0338d8f59ea6b67633712dff22cb5243829605409cdc8d5e8beeb65abfd4eda67f4be70064a95ba96cbb260ee3775848175e289e82e55212
Binary file
data/README.md CHANGED
@@ -48,14 +48,6 @@ Teradata output plugin for Embulk loads records to a database using a Teradata J
48
48
  * Behavior: This mode writes rows to an intermediate table first. If all those tasks run correctly, drops the target table and alters the name of the intermediate table into the target table name.
49
49
  * Transactional: No. If fails, the target table could be dropped.
50
50
  * Resumable: No.
51
- * **merge**:
52
- * Behavior: This mode writes rows to some intermediate tables first. If all those tasks run correctly, merges the intermediate tables into the target table. Namely, if primary keys of a record in the intermediate tables already exist in the target table, the target record is updated by the intermediate record, otherwise the intermediate record is inserted. If the target table doesn't exist, it is created automatically.
53
- * Transactional: Yes.
54
- * Resumable: Yes.
55
- * **merge_direct**:
56
- * Behavior: This mode merges rows to the target table directly. Namely, if primary keys of an input record already exist in the target table, the target record is updated by the input record, otherwise the input record is inserted. If the target table doesn't exist, it is created automatically.
57
- * Transactional: No.
58
- * Resumable: No.
59
51
 
60
52
  ## Example
61
53
 
@@ -6,14 +6,16 @@ plugins {
6
6
  }
7
7
  import com.github.jrubygradle.JRubyExec
8
8
  repositories {
9
- mavenCentral()
9
+ maven {
10
+ url("https://plugins.gradle.org/m2/")
11
+ }
10
12
  jcenter()
11
13
  }
12
14
  configurations {
13
15
  provided
14
16
  }
15
17
 
16
- version = "0.1.2"
18
+ version = "0.1.3"
17
19
 
18
20
  sourceCompatibility = 1.7
19
21
  targetCompatibility = 1.7
@@ -21,6 +23,7 @@ targetCompatibility = 1.7
21
23
  dependencies {
22
24
  compile "org.embulk:embulk-core:0.8.2"
23
25
  provided "org.embulk:embulk-core:0.8.2"
26
+ compile files('lib/embulk-output-jdbc-0.7.11.jar')
24
27
  compile files('lib/tdgssconfig.jar')
25
28
  compile files('lib/terajdbc4.jar')
26
29
 
@@ -0,0 +1,12 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <module external.linked.project.id="embulk-output-teradata" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" external.system.module.group="" external.system.module.version="0.1.2" type="JAVA_MODULE" version="4">
3
+ <component name="NewModuleRootManager" inherit-compiler-output="true">
4
+ <exclude-output />
5
+ <content url="file://$MODULE_DIR$">
6
+ <excludeFolder url="file://$MODULE_DIR$/.gradle" />
7
+ <excludeFolder url="file://$MODULE_DIR$/build" />
8
+ </content>
9
+ <orderEntry type="inheritedJdk" />
10
+ <orderEntry type="sourceFolder" forTests="false" />
11
+ </component>
12
+ </module>
@@ -1,6 +1,6 @@
1
- #Wed Jan 13 12:41:02 JST 2016
1
+ #Tue Aug 29 21:53:01 JST 2017
2
2
  distributionBase=GRADLE_USER_HOME
3
3
  distributionPath=wrapper/dists
4
4
  zipStoreBase=GRADLE_USER_HOME
5
5
  zipStorePath=wrapper/dists
6
- distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-bin.zip
6
+ distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip
data/gradlew CHANGED
File without changes
@@ -1,25 +1,26 @@
1
1
  package org.embulk.output.teradata;
2
2
 
3
3
  import java.util.Properties;
4
- import java.sql.Driver;
5
4
  import java.io.IOException;
6
- import java.sql.Connection;
7
5
  import java.sql.SQLException;
8
6
 
9
7
  import com.google.common.base.Optional;
10
- import com.google.common.base.Throwables;
11
8
  import com.google.common.collect.ImmutableSet;
12
9
 
13
10
  import org.embulk.config.Config;
14
11
  import org.embulk.config.ConfigDefault;
15
- import org.embulk.output.jdbc.*;
16
- import org.embulk.output.teradata.TeradataOutputConnection;
12
+ import org.embulk.output.jdbc.AbstractJdbcOutputPlugin;
13
+ import org.embulk.output.jdbc.BatchInsert;
14
+ import org.embulk.output.jdbc.MergeConfig;
15
+ import org.embulk.output.teradata.jdbc.TeradataBatchInsert;
16
+ import org.embulk.output.teradata.jdbc.TeradataOutputConnector;
17
17
 
18
18
  public class TeradataOutputPlugin
19
19
  extends AbstractJdbcOutputPlugin
20
20
  {
21
21
 
22
- public interface GenericPluginTask extends PluginTask
22
+ public interface TeradataPluginTask
23
+ extends PluginTask
23
24
  {
24
25
  @Config("url")
25
26
  public String getUrl();
@@ -44,22 +45,22 @@ public class TeradataOutputPlugin
44
45
  @Override
45
46
  protected Class<? extends PluginTask> getTaskClass()
46
47
  {
47
- return GenericPluginTask.class;
48
+ return TeradataPluginTask.class;
48
49
  }
49
50
 
50
51
  @Override
51
52
  protected Features getFeatures(PluginTask task)
52
53
  {
53
- GenericPluginTask t = (GenericPluginTask) task;
54
+ TeradataPluginTask t = (TeradataPluginTask) task;
54
55
  return new Features()
55
56
  .setMaxTableNameLength(t.getMaxTableNameLength())
56
57
  .setSupportedModes(ImmutableSet.of(Mode.INSERT, Mode.INSERT_DIRECT, Mode.TRUNCATE_INSERT, Mode.REPLACE));
57
58
  }
58
59
 
59
60
  @Override
60
- protected GenericOutputConnector getConnector(PluginTask task, boolean retryableMetadataOperation)
61
+ protected TeradataOutputConnector getConnector(PluginTask task, boolean retryableMetadataOperation)
61
62
  {
62
- GenericPluginTask t = (GenericPluginTask) task;
63
+ TeradataPluginTask t = (TeradataPluginTask) task;
63
64
 
64
65
  Properties props = new Properties();
65
66
 
@@ -73,52 +74,12 @@ public class TeradataOutputPlugin
73
74
  props.setProperty("password", t.getPassword().get());
74
75
  }
75
76
 
76
- return new GenericOutputConnector(t.getUrl(), props, null, null);
77
- }
78
-
79
- private static class GenericOutputConnector
80
- implements JdbcOutputConnector
81
- {
82
- private final Driver driver;
83
- private final String url;
84
- private final Properties properties;
85
- private final String schemaName;
86
-
87
- public GenericOutputConnector(String url, Properties properties, String driverClass,
88
- String schemaName)
89
- {
90
- try {
91
- // TODO check Class.forName(driverClass) is a Driver before newInstance
92
- // for security
93
- this.driver = new com.teradata.jdbc.TeraDriver();
94
- } catch (Exception ex) {
95
- throw Throwables.propagate(ex);
96
- }
97
- this.url = url;
98
- this.properties = properties;
99
- this.schemaName = schemaName;
100
- }
101
-
102
- @Override
103
- public JdbcOutputConnection connect(boolean autoCommit) throws SQLException
104
- {
105
- Connection c = driver.connect(url, properties);
106
- try {
107
- c.setAutoCommit(autoCommit);
108
- JdbcOutputConnection con = new JdbcOutputConnection(c, schemaName);
109
- c = null;
110
- return con;
111
- } finally {
112
- if (c != null) {
113
- c.close();
114
- }
115
- }
116
- }
77
+ return new TeradataOutputConnector(t.getUrl(), props);
117
78
  }
118
79
 
119
80
  @Override
120
81
  protected BatchInsert newBatchInsert(PluginTask task, Optional<MergeConfig> mergeConfig) throws IOException, SQLException
121
82
  {
122
- return new StandardBatchInsert(getConnector(task, true), mergeConfig);
83
+ return new TeradataBatchInsert(getConnector(task, true), mergeConfig);
123
84
  }
124
85
  }
@@ -0,0 +1,37 @@
1
+ package org.embulk.output.teradata.jdbc;
2
+
3
+ import java.io.IOException;
4
+ import java.sql.Types;
5
+ import java.sql.SQLException;
6
+ import com.google.common.base.Optional;
7
+ import org.embulk.output.jdbc.MergeConfig;
8
+ import org.embulk.output.jdbc.StandardBatchInsert;
9
+
10
+ public class TeradataBatchInsert
11
+ extends StandardBatchInsert
12
+ {
13
+ public TeradataBatchInsert(TeradataOutputConnector connector, Optional<MergeConfig> mergeConfig) throws IOException, SQLException
14
+ {
15
+ super(connector, mergeConfig);
16
+ }
17
+
18
+ @Override
19
+ public void setFloat(float v) throws IOException, SQLException
20
+ {
21
+ if (Float.isNaN(v) || Float.isInfinite(v)) {
22
+ setNull(Types.REAL); // TODO get through argument
23
+ } else {
24
+ super.setFloat(v);
25
+ }
26
+ }
27
+
28
+ @Override
29
+ public void setDouble(double v) throws IOException, SQLException
30
+ {
31
+ if (Double.isNaN(v) || Double.isInfinite(v)) {
32
+ setNull(Types.DOUBLE); // TODO get through argument
33
+ } else {
34
+ super.setDouble(v);
35
+ }
36
+ }
37
+ }
@@ -0,0 +1,307 @@
1
+ package org.embulk.output.teradata.jdbc;
2
+
3
+ import java.nio.charset.Charset;
4
+ import java.nio.charset.StandardCharsets;
5
+ import java.sql.Connection;
6
+ import java.sql.DatabaseMetaData;
7
+ import java.sql.SQLException;
8
+ import java.sql.Statement;
9
+
10
+ import org.embulk.output.jdbc.JdbcColumn;
11
+ import org.embulk.output.jdbc.JdbcOutputConnection;
12
+ import org.embulk.output.jdbc.JdbcSchema;
13
+ import org.embulk.output.jdbc.TableIdentifier;
14
+ import org.slf4j.Logger;
15
+ import org.embulk.spi.Exec;
16
+
17
+ import static java.lang.String.format;
18
+
19
+ public class TeradataOutputConnection
20
+ extends JdbcOutputConnection
21
+ {
22
+ private final Logger logger = Exec.getLogger(TeradataOutputConnection.class);
23
+ protected final Connection connection;
24
+ protected final DatabaseMetaData databaseMetaData;
25
+ protected String identifierQuoteString;
26
+
27
+ public TeradataOutputConnection(Connection connection, boolean autoCommit)
28
+ throws SQLException
29
+ {
30
+ super(connection, null);
31
+ this.connection = connection;
32
+ this.databaseMetaData = connection.getMetaData();
33
+ this.identifierQuoteString = databaseMetaData.getIdentifierQuoteString();
34
+ if (schemaName != null) {
35
+ setSearchPath(schemaName);
36
+ }
37
+ }
38
+
39
+ @Override
40
+ public void close() throws SQLException
41
+ {
42
+ if (!connection.isClosed()) {
43
+ connection.close();
44
+ }
45
+ }
46
+
47
+ public String getSchemaName()
48
+ {
49
+ return schemaName;
50
+ }
51
+
52
+ public DatabaseMetaData getMetaData() throws SQLException
53
+ {
54
+ return databaseMetaData;
55
+ }
56
+
57
+ public Charset getTableNameCharset() throws SQLException
58
+ {
59
+ return StandardCharsets.UTF_8;
60
+ }
61
+
62
+ protected void setSearchPath(String schema) throws SQLException
63
+ {
64
+ Statement stmt = connection.createStatement();
65
+ try {
66
+ String sql = "DATABASE " + quoteIdentifierString(schema);
67
+ executeUpdate(stmt, sql);
68
+ commitIfNecessary(connection);
69
+ } finally {
70
+ stmt.close();
71
+ }
72
+ }
73
+
74
+ // Teradata doesn't support CREATE TABLE IF NOT EXIST
75
+ @Override
76
+ protected String buildCreateTableIfNotExistsSql(TableIdentifier table, JdbcSchema schema) {
77
+ StringBuilder sb = new StringBuilder();
78
+ sb.append("CREATE TABLE ");
79
+ this.quoteTableIdentifier(sb, table);
80
+ sb.append(this.buildCreateTableSchemaSql(schema));
81
+ return sb.toString();
82
+ }
83
+
84
+ @Override
85
+ protected void dropTableIfExists(Statement stmt, TableIdentifier table) throws SQLException
86
+ {
87
+ if (existTable(table.getTableName()))
88
+ {
89
+ String sql = format("DROP TABLE %s", this.quoteTableIdentifier(table));
90
+ this.executeUpdate(stmt, sql);
91
+ }
92
+ else
93
+ {
94
+ logger.info(format("Skip dropping the table: %s", quoteIdentifierString(table.getTableName())));
95
+ }
96
+ }
97
+
98
+ // Teradata doesn't support IF EXISTS
99
+ public boolean existTable(String tableName)
100
+ {
101
+ try{
102
+ String sql = format("SELECT COUNT(1) FROM %s", quoteIdentifierString(tableName));
103
+ executeSql(sql);
104
+ } catch (SQLException se){
105
+ return false;
106
+ }
107
+ return true;
108
+ }
109
+
110
+ protected String buildCreateTableSchemaSql(JdbcSchema schema)
111
+ {
112
+ StringBuilder sb = new StringBuilder();
113
+
114
+ sb.append(" (");
115
+ for (int i=0; i < schema.getCount(); i++) {
116
+ if (i != 0) { sb.append(", "); }
117
+ quoteIdentifierString(sb, schema.getColumnName(i));
118
+ sb.append(" ");
119
+ String typeName = getCreateTableTypeName(schema.getColumn(i));
120
+ sb.append(typeName);
121
+ }
122
+ sb.append(")");
123
+
124
+ return sb.toString();
125
+ }
126
+
127
+ protected String getCreateTableTypeName(JdbcColumn c)
128
+ {
129
+ if (c.getDeclaredType().isPresent()) {
130
+ return c.getDeclaredType().get();
131
+ } else {
132
+ return buildColumnTypeName(c);
133
+ }
134
+ }
135
+
136
+ protected String buildColumnTypeName(JdbcColumn c)
137
+ {
138
+ String simpleTypeName = c.getSimpleTypeName();
139
+ switch (getColumnDeclareType(simpleTypeName, c)) {
140
+ case SIZE:
141
+ return format("%s(%d)", simpleTypeName, c.getSizeTypeParameter());
142
+ case SIZE_AND_SCALE:
143
+ if (c.getScaleTypeParameter() < 0) {
144
+ return format("%s(%d,0)", simpleTypeName, c.getSizeTypeParameter());
145
+ } else {
146
+ return format("%s(%d,%d)", simpleTypeName, c.getSizeTypeParameter(), c.getScaleTypeParameter());
147
+ }
148
+ case SIZE_AND_OPTIONAL_SCALE:
149
+ if (c.getScaleTypeParameter() < 0) {
150
+ return format("%s(%d)", simpleTypeName, c.getSizeTypeParameter());
151
+ } else {
152
+ return format("%s(%d,%d)", simpleTypeName, c.getSizeTypeParameter(), c.getScaleTypeParameter());
153
+ }
154
+ default: // SIMPLE
155
+ if (simpleTypeName.equals("CLOB"))
156
+ {
157
+ return "VARCHAR(1024)";
158
+ }
159
+ return simpleTypeName;
160
+ }
161
+ }
162
+
163
+ protected void executeSql(String sql) throws SQLException
164
+ {
165
+ Statement stmt = connection.createStatement();
166
+ try {
167
+ executeUpdate(stmt, sql);
168
+ commitIfNecessary(connection);
169
+ } catch (SQLException ex) {
170
+ throw safeRollback(connection, ex);
171
+ } finally {
172
+ stmt.close();
173
+ }
174
+ }
175
+
176
+ @Override
177
+ protected String buildRenameTableSql(TableIdentifier fromTable, TableIdentifier toTable) {
178
+ StringBuilder sb = new StringBuilder();
179
+ sb.append("RENAME TABLE ");
180
+ this.quoteTableIdentifier(sb, fromTable);
181
+ sb.append(" TO ");
182
+ this.quoteTableIdentifier(sb, toTable);
183
+ return sb.toString();
184
+ }
185
+
186
+
187
+ protected void quoteIdentifierString(StringBuilder sb, String str)
188
+ {
189
+ sb.append(quoteIdentifierString(str, identifierQuoteString));
190
+ }
191
+
192
+ protected String quoteIdentifierString(String str)
193
+ {
194
+ return quoteIdentifierString(str, identifierQuoteString);
195
+ }
196
+
197
+ protected String quoteIdentifierString(String str, String quoteString)
198
+ {
199
+ // TODO if identifierQuoteString.equals(" ") && str.contains([^a-zA-Z0-9_connection.getMetaData().getExtraNameCharacters()])
200
+ // TODO if str.contains(identifierQuoteString);
201
+ return quoteString + str + quoteString;
202
+ }
203
+
204
+ public boolean isValidConnection(int timeout) throws SQLException
205
+ {
206
+ Statement stmt = connection.createStatement();
207
+ try {
208
+ stmt.executeQuery("SELECT 1").close();
209
+ return true;
210
+ } catch (SQLException ex) {
211
+ return false;
212
+ } finally {
213
+ stmt.close();
214
+ }
215
+ }
216
+
217
+ protected String[] getDeterministicSqlStates()
218
+ {
219
+ return new String[0];
220
+ }
221
+
222
+ protected int[] getDeterministicErrorCodes()
223
+ {
224
+ return new int[0];
225
+ }
226
+
227
+ protected Class[] getDeterministicRootCauses()
228
+ {
229
+ return new Class[] {
230
+ // Don't retry on UnknownHostException.
231
+ java.net.UnknownHostException.class,
232
+
233
+ //// we should not retry on connect() error?
234
+ //java.net.ConnectException.class,
235
+ };
236
+ }
237
+
238
+ public boolean isRetryableException(SQLException exception)
239
+ {
240
+ String sqlState = exception.getSQLState();
241
+ for (String deterministic : getDeterministicSqlStates()) {
242
+ if (sqlState.equals(deterministic)) {
243
+ return false;
244
+ }
245
+ }
246
+
247
+ int errorCode = exception.getErrorCode();
248
+ for (int deterministic : getDeterministicErrorCodes()) {
249
+ if (errorCode == deterministic) {
250
+ return false;
251
+ }
252
+ }
253
+
254
+ Throwable rootCause = getRootCause(exception);
255
+ for (Class deterministic : getDeterministicRootCauses()) {
256
+ if (deterministic.equals(rootCause.getClass())) {
257
+ return false;
258
+ }
259
+ }
260
+
261
+ return true;
262
+ }
263
+
264
+ private Throwable getRootCause(Throwable e) {
265
+ while (e.getCause() != null) {
266
+ e = e.getCause();
267
+ }
268
+ return e;
269
+ }
270
+
271
+ protected int executeUpdate(Statement stmt, String sql) throws SQLException
272
+ {
273
+ logger.info("SQL: " + sql);
274
+ long startTime = System.currentTimeMillis();
275
+ int count = stmt.executeUpdate(sql);
276
+ double seconds = (System.currentTimeMillis() - startTime) / 1000.0;
277
+ if (count == 0) {
278
+ logger.info(format("> %.2f seconds", seconds));
279
+ } else {
280
+ logger.info(format("> %.2f seconds (%,d rows)", seconds, count));
281
+ }
282
+ return count;
283
+ }
284
+
285
+ protected void commitIfNecessary(Connection con) throws SQLException
286
+ {
287
+ if (!con.getAutoCommit()) {
288
+ con.commit();
289
+ }
290
+ }
291
+
292
+ protected SQLException safeRollback(Connection con, SQLException cause)
293
+ {
294
+ try {
295
+ if (!con.getAutoCommit()) {
296
+ con.rollback();
297
+ }
298
+ return cause;
299
+ } catch (SQLException ex) {
300
+ if (cause != null) {
301
+ cause.addSuppressed(ex);
302
+ return cause;
303
+ }
304
+ return ex;
305
+ }
306
+ }
307
+ }