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
@@ -1,52 +0,0 @@
1
- package org.embulk.output.jdbc;
2
-
3
- import java.math.BigDecimal;
4
- import java.util.Calendar;
5
- import java.io.IOException;
6
- import java.sql.SQLException;
7
- import org.embulk.spi.time.Timestamp;
8
-
9
- public interface BatchInsert
10
- {
11
- public void prepare(String loadTable, JdbcSchema insertSchema) throws SQLException;
12
-
13
- public int getBatchWeight();
14
-
15
- public void add() throws IOException, SQLException;
16
-
17
- public void close() throws IOException, SQLException;
18
-
19
- public void flush() throws IOException, SQLException;
20
-
21
- public void finish() throws IOException, SQLException;
22
-
23
- public void setNull(int sqlType) throws IOException, SQLException;
24
-
25
- public void setBoolean(boolean v) throws IOException, SQLException;
26
-
27
- public void setByte(byte v) throws IOException, SQLException;
28
-
29
- public void setShort(short v) throws IOException, SQLException;
30
-
31
- public void setInt(int v) throws IOException, SQLException;
32
-
33
- public void setLong(long v) throws IOException, SQLException;
34
-
35
- public void setFloat(float v) throws IOException, SQLException;
36
-
37
- public void setDouble(double v) throws IOException, SQLException;
38
-
39
- public void setBigDecimal(BigDecimal v) throws IOException, SQLException;
40
-
41
- public void setString(String v) throws IOException, SQLException;
42
-
43
- public void setNString(String v) throws IOException, SQLException;
44
-
45
- public void setBytes(byte[] v) throws IOException, SQLException;
46
-
47
- public void setSqlDate(Timestamp v, Calendar cal) throws IOException, SQLException;
48
-
49
- public void setSqlTime(Timestamp v, Calendar cal) throws IOException, SQLException;
50
-
51
- public void setSqlTimestamp(Timestamp v, Calendar cal) throws IOException, SQLException;
52
- }
@@ -1,134 +0,0 @@
1
- package org.embulk.output.jdbc;
2
-
3
- import com.google.common.base.Optional;
4
- import com.fasterxml.jackson.annotation.JsonCreator;
5
- import com.fasterxml.jackson.annotation.JsonProperty;
6
- import com.fasterxml.jackson.annotation.JsonIgnore;
7
-
8
- public class JdbcColumn
9
- {
10
- private final String name;
11
- private final String simpleTypeName;
12
- private final int sqlType;
13
- private final int sizeTypeParameter;
14
- private final int scaleTypeParameter;
15
- private final int dataLength;
16
- private final Optional<String> declaredType;
17
- private final boolean isNotNull;
18
- private final boolean isUniqueKey;
19
-
20
- @JsonCreator
21
- public JdbcColumn(
22
- @JsonProperty("name") String name,
23
- @JsonProperty("sqlType") int sqlType,
24
- @JsonProperty("simpleTypeName") String simpleTypeName,
25
- @JsonProperty("sizeTypeParameter") int sizeTypeParameter,
26
- @JsonProperty("scaleTypeParameter") int scaleTypeParameter,
27
- @JsonProperty("dataLength") int dataLength,
28
- @JsonProperty("declaredType") Optional<String> declaredType,
29
- @JsonProperty("notNull") boolean isNotNull,
30
- @JsonProperty("uniqueKey") boolean isUniqueKey)
31
- {
32
- this.name = name;
33
- this.simpleTypeName = simpleTypeName;
34
- this.sqlType = sqlType;
35
- this.sizeTypeParameter = sizeTypeParameter;
36
- this.scaleTypeParameter = scaleTypeParameter;
37
- this.dataLength = dataLength;
38
- this.declaredType = declaredType;
39
- this.isNotNull = isNotNull;
40
- this.isUniqueKey = isUniqueKey;
41
- }
42
-
43
- public static JdbcColumn newGenericTypeColumn(String name, int sqlType,
44
- String simpleTypeName, int sizeTypeParameter, int scaleTypeParameter, int dataLength,
45
- boolean isNotNull, boolean isUniqueKey)
46
- {
47
- return new JdbcColumn(name, sqlType,
48
- simpleTypeName, sizeTypeParameter, scaleTypeParameter, dataLength,
49
- Optional.<String>absent(), isNotNull, isUniqueKey);
50
- }
51
-
52
- public static JdbcColumn newGenericTypeColumn(String name, int sqlType,
53
- String simpleTypeName, int sizeTypeParameter, int scaleTypeParameter,
54
- boolean isNotNull, boolean isUniqueKey)
55
- {
56
- return new JdbcColumn(name, sqlType,
57
- simpleTypeName, sizeTypeParameter, scaleTypeParameter, sizeTypeParameter,
58
- Optional.<String>absent(), isNotNull, isUniqueKey);
59
- }
60
-
61
- public static JdbcColumn newTypeDeclaredColumn(String name, int sqlType,
62
- String declaredType, boolean isNotNull, boolean isUniqueKey)
63
- {
64
- return new JdbcColumn(name, sqlType,
65
- declaredType, 0, 0, 0,
66
- Optional.of(declaredType), isNotNull, isUniqueKey);
67
- }
68
-
69
- @JsonIgnore
70
- public static JdbcColumn skipColumn()
71
- {
72
- return new JdbcColumn(null, 0, null, 0, 0, 0, Optional.<String>absent(), false, false);
73
- }
74
-
75
- @JsonIgnore
76
- public boolean isSkipColumn()
77
- {
78
- return name == null;
79
- }
80
-
81
- @JsonProperty("name")
82
- public String getName()
83
- {
84
- return name;
85
- }
86
-
87
- @JsonProperty("sqlType")
88
- public int getSqlType()
89
- {
90
- return sqlType;
91
- }
92
-
93
- @JsonProperty("simpleTypeName")
94
- public String getSimpleTypeName()
95
- {
96
- return simpleTypeName;
97
- }
98
-
99
- @JsonProperty("sizeTypeParameter")
100
- public int getSizeTypeParameter()
101
- {
102
- return sizeTypeParameter;
103
- }
104
-
105
- @JsonProperty("scaleTypeParameter")
106
- public int getScaleTypeParameter()
107
- {
108
- return scaleTypeParameter;
109
- }
110
-
111
- @JsonProperty("dataLength")
112
- public int getDataLength()
113
- {
114
- return dataLength;
115
- }
116
-
117
- @JsonProperty("declaredType")
118
- public Optional<String> getDeclaredType()
119
- {
120
- return declaredType;
121
- }
122
-
123
- @JsonProperty("notNull")
124
- public boolean isNotNull()
125
- {
126
- return isNotNull;
127
- }
128
-
129
- @JsonProperty("uniqueKey")
130
- public boolean isUniqueKey()
131
- {
132
- return isUniqueKey;
133
- }
134
- }
@@ -1,34 +0,0 @@
1
- package org.embulk.output.jdbc;
2
-
3
- import com.google.common.base.Optional;
4
- import org.joda.time.DateTimeZone;
5
- import org.jruby.embed.ScriptingContainer;
6
- import org.embulk.config.Task;
7
- import org.embulk.config.Config;
8
- import org.embulk.config.ConfigDefault;
9
- import org.embulk.config.ConfigInject;
10
- import org.embulk.spi.time.TimestampFormat;
11
-
12
- public interface JdbcColumnOption
13
- extends Task
14
- {
15
- @Config("type")
16
- @ConfigDefault("null")
17
- public Optional<String> getType();
18
-
19
- @Config("value_type")
20
- @ConfigDefault("\"coerce\"")
21
- public String getValueType();
22
-
23
- @Config("timestamp_format")
24
- @ConfigDefault("\"%Y-%m-%d %H:%M:%S.%6N\"")
25
- public TimestampFormat getTimestampFormat();
26
-
27
- @Config("timezone")
28
- @ConfigDefault("null")
29
- public Optional<DateTimeZone> getTimeZone();
30
-
31
- // required by TimestampFormatter
32
- @ConfigInject
33
- public ScriptingContainer getJRuby();
34
- }
@@ -1,549 +0,0 @@
1
- package org.embulk.output.jdbc;
2
-
3
- import java.util.List;
4
- import java.nio.charset.Charset;
5
- import java.nio.charset.StandardCharsets;
6
- import java.sql.Connection;
7
- import java.sql.DatabaseMetaData;
8
- import java.sql.PreparedStatement;
9
- import java.sql.ResultSet;
10
- import java.sql.SQLException;
11
- import java.sql.Statement;
12
-
13
- import org.slf4j.Logger;
14
- import com.google.common.base.Optional;
15
- import org.embulk.spi.Exec;
16
-
17
- public class JdbcOutputConnection
18
- implements AutoCloseable
19
- {
20
- private final Logger logger = Exec.getLogger(JdbcOutputConnection.class);
21
- protected final Connection connection;
22
- protected final String schemaName;
23
- protected final DatabaseMetaData databaseMetaData;
24
- protected String identifierQuoteString;
25
-
26
- public JdbcOutputConnection(Connection connection, String schemaName)
27
- throws SQLException
28
- {
29
- this.connection = connection;
30
- this.schemaName = schemaName;
31
- this.databaseMetaData = connection.getMetaData();
32
- this.identifierQuoteString = databaseMetaData.getIdentifierQuoteString();
33
- if (schemaName != null) {
34
- setSearchPath(schemaName);
35
- }
36
- }
37
-
38
- @Override
39
- public void close() throws SQLException
40
- {
41
- if (!connection.isClosed()) {
42
- connection.close();
43
- }
44
- }
45
-
46
- public String getSchemaName()
47
- {
48
- return schemaName;
49
- }
50
-
51
- public DatabaseMetaData getMetaData() throws SQLException
52
- {
53
- return databaseMetaData;
54
- }
55
-
56
- public Charset getTableNameCharset() throws SQLException
57
- {
58
- return StandardCharsets.UTF_8;
59
- }
60
-
61
- protected void setSearchPath(String schema) throws SQLException
62
- {
63
- Statement stmt = connection.createStatement();
64
- try {
65
- String sql = "DATABASE " + quoteIdentifierString(schema);
66
- executeUpdate(stmt, sql);
67
- commitIfNecessary(connection);
68
- } finally {
69
- stmt.close();
70
- }
71
- }
72
-
73
- public boolean tableExists(String tableName) throws SQLException
74
- {
75
- try (ResultSet rs = connection.getMetaData().getTables(null, schemaName, tableName, null)) {
76
- return rs.next();
77
- }
78
- }
79
-
80
- public void dropTableIfExists(String tableName) throws SQLException
81
- {
82
- Statement stmt = connection.createStatement();
83
- try {
84
- dropTableIfExists(stmt, tableName);
85
- commitIfNecessary(connection);
86
- } catch (SQLException ex) {
87
- throw safeRollback(connection, ex);
88
- } finally {
89
- stmt.close();
90
- }
91
- }
92
-
93
- protected void dropTableIfExists(Statement stmt, String tableName) throws SQLException
94
- {
95
- if (existTable(tableName))
96
- {
97
- String sql = String.format("DROP TABLE %s", quoteIdentifierString(tableName));
98
- executeUpdate(stmt, sql);
99
- }
100
- }
101
-
102
- // TODO: Teradata doesn't support IF EXISTS
103
- public boolean existTable(String tableName)
104
- {
105
- try{
106
- String sql = String.format("SELECT COUNT(1) FROM %s", quoteIdentifierString(tableName));
107
- executeSql(sql);
108
- } catch (SQLException se){
109
- return false;
110
- }
111
- return true;
112
- }
113
-
114
- public void dropTable(String tableName) throws SQLException
115
- {
116
- Statement stmt = connection.createStatement();
117
- try {
118
- dropTable(stmt, tableName);
119
- commitIfNecessary(connection);
120
- } catch (SQLException ex) {
121
- throw safeRollback(connection, ex);
122
- } finally {
123
- stmt.close();
124
- }
125
- }
126
-
127
- protected void dropTable(Statement stmt, String tableName) throws SQLException
128
- {
129
- String sql = String.format("DROP TABLE %s", quoteIdentifierString(tableName));
130
- executeUpdate(stmt, sql);
131
- }
132
-
133
- public void createTableIfNotExists(String tableName, JdbcSchema schema) throws SQLException
134
- {
135
- Statement stmt = connection.createStatement();
136
- try {
137
- String sql = buildCreateTableIfNotExistsSql(tableName, schema);
138
-
139
- if (!tableExists(tableName)) {
140
- executeUpdate(stmt, sql);
141
- commitIfNecessary(connection);
142
- }
143
-
144
- } catch (SQLException ex) {
145
- throw safeRollback(connection, ex);
146
- } finally {
147
- stmt.close();
148
- }
149
- }
150
-
151
- protected String buildCreateTableIfNotExistsSql(String name, JdbcSchema schema)
152
- {
153
- StringBuilder sb = new StringBuilder();
154
-
155
- sb.append("CREATE TABLE ");
156
- quoteIdentifierString(sb, name);
157
- sb.append(buildCreateTableSchemaSql(schema));
158
- sb.append(" NO PRIMARY INDEX");
159
- return sb.toString();
160
- }
161
-
162
- protected String buildCreateTableSchemaSql(JdbcSchema schema)
163
- {
164
- StringBuilder sb = new StringBuilder();
165
-
166
- sb.append(" (");
167
- for (int i=0; i < schema.getCount(); i++) {
168
- if (i != 0) { sb.append(", "); }
169
- quoteIdentifierString(sb, schema.getColumnName(i));
170
- sb.append(" ");
171
- String typeName = getCreateTableTypeName(schema.getColumn(i));
172
- sb.append(typeName);
173
- }
174
- sb.append(")");
175
-
176
- return sb.toString();
177
- }
178
-
179
- protected String buildRenameTableSql(String fromTable, String toTable)
180
- {
181
- StringBuilder sb = new StringBuilder();
182
- sb.append("ALTER TABLE ");
183
- quoteIdentifierString(sb, fromTable);
184
- sb.append(" RENAME TO ");
185
- quoteIdentifierString(sb, toTable);
186
- return sb.toString();
187
- }
188
-
189
- public static enum ColumnDeclareType
190
- {
191
- SIMPLE,
192
- SIZE,
193
- SIZE_AND_SCALE,
194
- SIZE_AND_OPTIONAL_SCALE,
195
- };
196
-
197
- protected String getCreateTableTypeName(JdbcColumn c)
198
- {
199
- if (c.getDeclaredType().isPresent()) {
200
- return c.getDeclaredType().get();
201
- } else {
202
- return buildColumnTypeName(c);
203
- }
204
- }
205
-
206
- protected String buildColumnTypeName(JdbcColumn c)
207
- {
208
- String simpleTypeName = c.getSimpleTypeName();
209
- switch (getColumnDeclareType(simpleTypeName, c)) {
210
- case SIZE:
211
- return String.format("%s(%d)", simpleTypeName, c.getSizeTypeParameter());
212
- case SIZE_AND_SCALE:
213
- if (c.getScaleTypeParameter() < 0) {
214
- return String.format("%s(%d,0)", simpleTypeName, c.getSizeTypeParameter());
215
- } else {
216
- return String.format("%s(%d,%d)", simpleTypeName, c.getSizeTypeParameter(), c.getScaleTypeParameter());
217
- }
218
- case SIZE_AND_OPTIONAL_SCALE:
219
- if (c.getScaleTypeParameter() < 0) {
220
- return String.format("%s(%d)", simpleTypeName, c.getSizeTypeParameter());
221
- } else {
222
- return String.format("%s(%d,%d)", simpleTypeName, c.getSizeTypeParameter(), c.getScaleTypeParameter());
223
- }
224
- default: // SIMPLE
225
- return simpleTypeName;
226
- }
227
- }
228
-
229
- // TODO
230
- private static final String[] STANDARD_SIZE_TYPE_NAMES = new String[] {
231
- "CHAR",
232
- "VARCHAR", "CHAR VARYING", "CHARACTER VARYING", "LONGVARCHAR",
233
- "NCHAR",
234
- "NVARCHAR", "NCHAR VARYING", "NATIONAL CHAR VARYING", "NATIONAL CHARACTER VARYING",
235
- "BINARY",
236
- "VARBINARY", "BINARY VARYING", "LONGVARBINARY",
237
- "BIT",
238
- "VARBIT", "BIT VARYING",
239
- "FLOAT", // SQL standard's FLOAT[(p)] optionally accepts precision
240
- };
241
-
242
- private static final String[] STANDARD_SIZE_AND_SCALE_TYPE_NAMES = new String[] {
243
- "DECIMAL",
244
- "NUMERIC",
245
- };
246
-
247
- protected ColumnDeclareType getColumnDeclareType(String convertedTypeName, JdbcColumn col)
248
- {
249
- for (String x : STANDARD_SIZE_TYPE_NAMES) {
250
- if (x.equals(convertedTypeName)) {
251
- return ColumnDeclareType.SIZE;
252
- }
253
- }
254
-
255
- for (String x : STANDARD_SIZE_AND_SCALE_TYPE_NAMES) {
256
- if (x.equals(convertedTypeName)) {
257
- return ColumnDeclareType.SIZE_AND_SCALE;
258
- }
259
- }
260
-
261
- return ColumnDeclareType.SIMPLE;
262
- }
263
-
264
- public PreparedStatement prepareBatchInsertStatement(String toTable, JdbcSchema toTableSchema, Optional<MergeConfig> mergeConfig) throws SQLException
265
- {
266
- String sql;
267
- if (mergeConfig.isPresent()) {
268
- sql = buildPreparedMergeSql(toTable, toTableSchema, mergeConfig.get());
269
- } else {
270
- sql = buildPreparedInsertSql(toTable, toTableSchema);
271
- }
272
- logger.info("Prepared SQL: {}", sql);
273
- return connection.prepareStatement(sql);
274
- }
275
-
276
- protected String buildPreparedInsertSql(String toTable, JdbcSchema toTableSchema) throws SQLException
277
- {
278
- StringBuilder sb = new StringBuilder();
279
-
280
- sb.append("INSERT INTO ");
281
- quoteIdentifierString(sb, toTable);
282
-
283
- sb.append(" (");
284
- for (int i=0; i < toTableSchema.getCount(); i++) {
285
- if(i != 0) { sb.append(", "); }
286
- quoteIdentifierString(sb, toTableSchema.getColumnName(i));
287
- }
288
- sb.append(") VALUES (");
289
- for(int i=0; i < toTableSchema.getCount(); i++) {
290
- if(i != 0) { sb.append(", "); }
291
- sb.append("?");
292
- }
293
- sb.append(")");
294
-
295
- return sb.toString();
296
- }
297
-
298
- protected String buildPreparedMergeSql(String toTable, JdbcSchema toTableSchema, MergeConfig mergeConfig) throws SQLException
299
- {
300
- throw new UnsupportedOperationException("not implemented");
301
- }
302
-
303
- protected void executeSql(String sql) throws SQLException
304
- {
305
- Statement stmt = connection.createStatement();
306
- try {
307
- executeUpdate(stmt, sql);
308
- commitIfNecessary(connection);
309
- } catch (SQLException ex) {
310
- throw safeRollback(connection, ex);
311
- } finally {
312
- stmt.close();
313
- }
314
- }
315
-
316
- protected void collectInsert(List<String> fromTables, JdbcSchema schema, String toTable,
317
- boolean truncateDestinationFirst, Optional<String> additionalSql) throws SQLException
318
- {
319
- if (fromTables.isEmpty()) {
320
- return;
321
- }
322
-
323
- Statement stmt = connection.createStatement();
324
- try {
325
- if (truncateDestinationFirst) {
326
- String sql = buildTruncateSql(toTable);
327
- executeUpdate(stmt, sql);
328
- }
329
- String sql = buildCollectInsertSql(fromTables, schema, toTable);
330
- executeUpdate(stmt, sql);
331
- if (additionalSql.isPresent()) {
332
- executeUpdate(stmt, additionalSql.get());
333
- }
334
- commitIfNecessary(connection);
335
- } catch (SQLException ex) {
336
- throw safeRollback(connection, ex);
337
- } finally {
338
- stmt.close();
339
- }
340
- }
341
-
342
- protected String buildTruncateSql(String table)
343
- {
344
- StringBuilder sb = new StringBuilder();
345
-
346
- sb.append("DELETE FROM ");
347
- quoteIdentifierString(sb, table);
348
-
349
- return sb.toString();
350
- }
351
-
352
- protected String buildCollectInsertSql(List<String> fromTables, JdbcSchema schema, String toTable)
353
- {
354
- StringBuilder sb = new StringBuilder();
355
-
356
- sb.append("INSERT INTO ");
357
- quoteIdentifierString(sb, toTable);
358
- sb.append(" (");
359
- for (int i=0; i < schema.getCount(); i++) {
360
- if (i != 0) { sb.append(", "); }
361
- quoteIdentifierString(sb, schema.getColumnName(i));
362
- }
363
- sb.append(") ");
364
- for (int i=0; i < fromTables.size(); i++) {
365
- if (i != 0) { sb.append(" UNION ALL "); }
366
- sb.append("SELECT ");
367
- for (int j=0; j < schema.getCount(); j++) {
368
- if (j != 0) { sb.append(", "); }
369
- quoteIdentifierString(sb, schema.getColumnName(j));
370
- }
371
- sb.append(" FROM ");
372
- quoteIdentifierString(sb, fromTables.get(i));
373
- }
374
-
375
- return sb.toString();
376
- }
377
-
378
- protected void collectMerge(List<String> fromTables, JdbcSchema schema, String toTable, MergeConfig mergeConfig,
379
- Optional<String> additionalSql) throws SQLException
380
- {
381
- if (fromTables.isEmpty()) {
382
- return;
383
- }
384
-
385
- Statement stmt = connection.createStatement();
386
- try {
387
- String sql = buildCollectMergeSql(fromTables, schema, toTable, mergeConfig);
388
- executeUpdate(stmt, sql);
389
- if (additionalSql.isPresent()) {
390
- executeUpdate(stmt, additionalSql.get());
391
- }
392
- commitIfNecessary(connection);
393
- } catch (SQLException ex) {
394
- throw safeRollback(connection, ex);
395
- } finally {
396
- stmt.close();
397
- }
398
- }
399
-
400
- protected String buildCollectMergeSql(List<String> fromTables, JdbcSchema schema, String toTable, MergeConfig mergeConfig) throws SQLException
401
- {
402
- throw new UnsupportedOperationException("not implemented");
403
- }
404
-
405
- public void replaceTable(String fromTable, JdbcSchema schema, String toTable, Optional<String> additionalSql) throws SQLException
406
- {
407
- Statement stmt = connection.createStatement();
408
- try {
409
- dropTableIfExists(stmt, toTable);
410
- executeUpdate(stmt, buildRenameTableSql(fromTable, toTable));
411
- if (additionalSql.isPresent()) {
412
- executeUpdate(stmt, additionalSql.get());
413
- }
414
- commitIfNecessary(connection);
415
- } catch (SQLException ex) {
416
- throw safeRollback(connection, ex);
417
- } finally {
418
- stmt.close();
419
- }
420
- }
421
-
422
- protected void quoteIdentifierString(StringBuilder sb, String str)
423
- {
424
- sb.append(quoteIdentifierString(str, identifierQuoteString));
425
- }
426
-
427
- protected String quoteIdentifierString(String str)
428
- {
429
- return quoteIdentifierString(str, identifierQuoteString);
430
- }
431
-
432
- protected String quoteIdentifierString(String str, String quoteString)
433
- {
434
- // TODO if identifierQuoteString.equals(" ") && str.contains([^a-zA-Z0-9_connection.getMetaData().getExtraNameCharacters()])
435
- // TODO if str.contains(identifierQuoteString);
436
- return quoteString + str + quoteString;
437
- }
438
-
439
- // PostgreSQL JDBC driver implements isValid() method. But the
440
- // implementation throws following exception:
441
- // "java.io.IOException: Method org.postgresql.jdbc4.Jdbc4Connection.isValid(int) is not yet implemented."
442
- //
443
- // So, checking mechanism doesn't work at all.
444
- // Thus here just runs "SELECT 1" to check connectivity.
445
- //
446
- public boolean isValidConnection(int timeout) throws SQLException
447
- {
448
- Statement stmt = connection.createStatement();
449
- try {
450
- stmt.executeQuery("SELECT 1").close();
451
- return true;
452
- } catch (SQLException ex) {
453
- return false;
454
- } finally {
455
- stmt.close();
456
- }
457
- }
458
-
459
- protected String[] getDeterministicSqlStates()
460
- {
461
- return new String[0];
462
- }
463
-
464
- protected int[] getDeterministicErrorCodes()
465
- {
466
- return new int[0];
467
- }
468
-
469
- protected Class[] getDeterministicRootCauses()
470
- {
471
- return new Class[] {
472
- // Don't retry on UnknownHostException.
473
- java.net.UnknownHostException.class,
474
-
475
- //// we should not retry on connect() error?
476
- //java.net.ConnectException.class,
477
- };
478
- }
479
-
480
- public boolean isRetryableException(SQLException exception)
481
- {
482
- String sqlState = exception.getSQLState();
483
- for (String deterministic : getDeterministicSqlStates()) {
484
- if (sqlState.equals(deterministic)) {
485
- return false;
486
- }
487
- }
488
-
489
- int errorCode = exception.getErrorCode();
490
- for (int deterministic : getDeterministicErrorCodes()) {
491
- if (errorCode == deterministic) {
492
- return false;
493
- }
494
- }
495
-
496
- Throwable rootCause = getRootCause(exception);
497
- for (Class deterministic : getDeterministicRootCauses()) {
498
- if (deterministic.equals(rootCause.getClass())) {
499
- return false;
500
- }
501
- }
502
-
503
- return true;
504
- }
505
-
506
- private Throwable getRootCause(Throwable e) {
507
- while (e.getCause() != null) {
508
- e = e.getCause();
509
- }
510
- return e;
511
- }
512
-
513
- protected int executeUpdate(Statement stmt, String sql) throws SQLException
514
- {
515
- logger.info("SQL: " + sql);
516
- long startTime = System.currentTimeMillis();
517
- int count = stmt.executeUpdate(sql);
518
- double seconds = (System.currentTimeMillis() - startTime) / 1000.0;
519
- if (count == 0) {
520
- logger.info(String.format("> %.2f seconds", seconds));
521
- } else {
522
- logger.info(String.format("> %.2f seconds (%,d rows)", seconds, count));
523
- }
524
- return count;
525
- }
526
-
527
- protected void commitIfNecessary(Connection con) throws SQLException
528
- {
529
- if (!con.getAutoCommit()) {
530
- con.commit();
531
- }
532
- }
533
-
534
- protected SQLException safeRollback(Connection con, SQLException cause)
535
- {
536
- try {
537
- if (!con.getAutoCommit()) {
538
- con.rollback();
539
- }
540
- return cause;
541
- } catch (SQLException ex) {
542
- if (cause != null) {
543
- cause.addSuppressed(ex);
544
- return cause;
545
- }
546
- return ex;
547
- }
548
- }
549
- }