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,54 +1,54 @@
1
- package org.embulk.output.jdbc;
2
-
3
- import java.math.BigDecimal;
4
- import java.io.IOException;
5
- import java.sql.SQLException;
6
- import java.sql.PreparedStatement;
7
- import java.sql.Date;
8
- import java.sql.Time;
9
- import java.sql.Timestamp;
10
-
11
- public interface BatchInsert
12
- {
13
- public void prepare(String loadTable, JdbcSchema insertSchema) throws SQLException;
14
-
15
- public int getBatchWeight();
16
-
17
- public void add() throws IOException, SQLException;
18
-
19
- public void close() throws IOException, SQLException;
20
-
21
- public void flush() throws IOException, SQLException;
22
-
23
- public void finish() throws IOException, SQLException;
24
-
25
- public void setNull(int sqlType) throws IOException, SQLException;
26
-
27
- public void setBoolean(boolean v) throws IOException, SQLException;
28
-
29
- public void setByte(byte v) throws IOException, SQLException;
30
-
31
- public void setShort(short v) throws IOException, SQLException;
32
-
33
- public void setInt(int v) throws IOException, SQLException;
34
-
35
- public void setLong(long v) throws IOException, SQLException;
36
-
37
- public void setFloat(float v) throws IOException, SQLException;
38
-
39
- public void setDouble(double v) throws IOException, SQLException;
40
-
41
- public void setBigDecimal(BigDecimal v) throws IOException, SQLException;
42
-
43
- public void setString(String v) throws IOException, SQLException;
44
-
45
- public void setNString(String v) throws IOException, SQLException;
46
-
47
- public void setBytes(byte[] v) throws IOException, SQLException;
48
-
49
- public void setSqlDate(Date v, int sqlType) throws IOException, SQLException;
50
-
51
- public void setSqlTime(Time v, int sqlType) throws IOException, SQLException;
52
-
53
- public void setSqlTimestamp(Timestamp v, int sqlType) throws IOException, SQLException;
54
- }
1
+ package org.embulk.output.jdbc;
2
+
3
+ import java.math.BigDecimal;
4
+ import java.io.IOException;
5
+ import java.sql.SQLException;
6
+ import java.sql.PreparedStatement;
7
+ import java.sql.Date;
8
+ import java.sql.Time;
9
+ import java.sql.Timestamp;
10
+
11
+ public interface BatchInsert
12
+ {
13
+ public void prepare(String loadTable, JdbcSchema insertSchema) throws SQLException;
14
+
15
+ public int getBatchWeight();
16
+
17
+ public void add() throws IOException, SQLException;
18
+
19
+ public void close() throws IOException, SQLException;
20
+
21
+ public void flush() throws IOException, SQLException;
22
+
23
+ public void finish() throws IOException, SQLException;
24
+
25
+ public void setNull(int sqlType) throws IOException, SQLException;
26
+
27
+ public void setBoolean(boolean v) throws IOException, SQLException;
28
+
29
+ public void setByte(byte v) throws IOException, SQLException;
30
+
31
+ public void setShort(short v) throws IOException, SQLException;
32
+
33
+ public void setInt(int v) throws IOException, SQLException;
34
+
35
+ public void setLong(long v) throws IOException, SQLException;
36
+
37
+ public void setFloat(float v) throws IOException, SQLException;
38
+
39
+ public void setDouble(double v) throws IOException, SQLException;
40
+
41
+ public void setBigDecimal(BigDecimal v) throws IOException, SQLException;
42
+
43
+ public void setString(String v) throws IOException, SQLException;
44
+
45
+ public void setNString(String v) throws IOException, SQLException;
46
+
47
+ public void setBytes(byte[] v) throws IOException, SQLException;
48
+
49
+ public void setSqlDate(Date v, int sqlType) throws IOException, SQLException;
50
+
51
+ public void setSqlTime(Time v, int sqlType) throws IOException, SQLException;
52
+
53
+ public void setSqlTimestamp(Timestamp v, int sqlType) throws IOException, SQLException;
54
+ }
@@ -1,39 +1,63 @@
1
1
  package org.embulk.output.jdbc;
2
2
 
3
+ import com.google.common.base.Optional;
3
4
  import com.fasterxml.jackson.annotation.JsonCreator;
4
5
  import com.fasterxml.jackson.annotation.JsonProperty;
5
6
  import com.fasterxml.jackson.annotation.JsonIgnore;
6
7
 
7
8
  public class JdbcColumn
8
9
  {
9
- private String name;
10
- private String typeName;
11
- private int sqlType;
12
- private int sizeTypeParameter;
13
- private int scaleTypeParameter;
14
- private boolean isPrimaryKey;
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 Optional<String> declaredType;
16
+ private final boolean isNotNull;
17
+ private final boolean isUniqueKey;
15
18
 
16
19
  @JsonCreator
17
20
  public JdbcColumn(
18
21
  @JsonProperty("name") String name,
19
- @JsonProperty("typeName") String typeName,
20
22
  @JsonProperty("sqlType") int sqlType,
23
+ @JsonProperty("simpleTypeName") String simpleTypeName,
21
24
  @JsonProperty("sizeTypeParameter") int sizeTypeParameter,
22
25
  @JsonProperty("scaleTypeParameter") int scaleTypeParameter,
23
- @JsonProperty("primaryKey") boolean isPrimaryKey)
26
+ @JsonProperty("declaredType") Optional<String> declaredType,
27
+ @JsonProperty("notNull") boolean isNotNull,
28
+ @JsonProperty("uniqueKey") boolean isUniqueKey)
24
29
  {
25
30
  this.name = name;
26
- this.typeName = typeName;
31
+ this.simpleTypeName = simpleTypeName;
27
32
  this.sqlType = sqlType;
28
33
  this.sizeTypeParameter = sizeTypeParameter;
29
34
  this.scaleTypeParameter = scaleTypeParameter;
30
- this.isPrimaryKey = isPrimaryKey;
35
+ this.declaredType = declaredType;
36
+ this.isNotNull = isNotNull;
37
+ this.isUniqueKey = isUniqueKey;
38
+ }
39
+
40
+ public static JdbcColumn newGenericTypeColumn(String name, int sqlType,
41
+ String simpleTypeName, int sizeTypeParameter, int scaleTypeParameter,
42
+ boolean isNotNull, boolean isUniqueKey)
43
+ {
44
+ return new JdbcColumn(name, sqlType,
45
+ simpleTypeName, sizeTypeParameter, scaleTypeParameter, Optional.<String>absent(),
46
+ isNotNull, isUniqueKey);
47
+ }
48
+
49
+ public static JdbcColumn newTypeDeclaredColumn(String name, int sqlType,
50
+ String declaredType, boolean isNotNull, boolean isUniqueKey)
51
+ {
52
+ return new JdbcColumn(name, sqlType,
53
+ declaredType, 0, 0, Optional.of(declaredType),
54
+ isNotNull, isUniqueKey);
31
55
  }
32
56
 
33
57
  @JsonIgnore
34
58
  public static JdbcColumn skipColumn()
35
59
  {
36
- return new JdbcColumn(null, null, 0, 0, 0, false);
60
+ return new JdbcColumn(null, 0, null, 0, 0, Optional.<String>absent(), false, false);
37
61
  }
38
62
 
39
63
  @JsonIgnore
@@ -42,30 +66,24 @@ public class JdbcColumn
42
66
  return name == null;
43
67
  }
44
68
 
45
- @JsonProperty("primaryKey")
46
- public boolean isPrimaryKey()
47
- {
48
- return isPrimaryKey;
49
- }
50
-
51
69
  @JsonProperty("name")
52
70
  public String getName()
53
71
  {
54
72
  return name;
55
73
  }
56
74
 
57
- @JsonProperty("typeName")
58
- public String getTypeName()
59
- {
60
- return typeName;
61
- }
62
-
63
75
  @JsonProperty("sqlType")
64
76
  public int getSqlType()
65
77
  {
66
78
  return sqlType;
67
79
  }
68
80
 
81
+ @JsonProperty("simpleTypeName")
82
+ public String getSimpleTypeName()
83
+ {
84
+ return simpleTypeName;
85
+ }
86
+
69
87
  @JsonProperty("sizeTypeParameter")
70
88
  public int getSizeTypeParameter()
71
89
  {
@@ -77,4 +95,22 @@ public class JdbcColumn
77
95
  {
78
96
  return scaleTypeParameter;
79
97
  }
98
+
99
+ @JsonProperty("declaredType")
100
+ public Optional<String> getDeclaredType()
101
+ {
102
+ return declaredType;
103
+ }
104
+
105
+ @JsonProperty("notNull")
106
+ public boolean isNotNull()
107
+ {
108
+ return isNotNull;
109
+ }
110
+
111
+ @JsonProperty("uniqueKey")
112
+ public boolean isUniqueKey()
113
+ {
114
+ return isUniqueKey;
115
+ }
80
116
  }
@@ -0,0 +1,34 @@
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("\"coalesce\"")
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,13 +1,16 @@
1
1
  package org.embulk.output.jdbc;
2
2
 
3
+ import java.util.List;
4
+ import java.nio.charset.Charset;
5
+ import java.nio.charset.StandardCharsets;
3
6
  import java.sql.Connection;
4
7
  import java.sql.DatabaseMetaData;
5
8
  import java.sql.PreparedStatement;
6
9
  import java.sql.ResultSet;
7
10
  import java.sql.SQLException;
8
11
  import java.sql.Statement;
9
-
10
12
  import org.slf4j.Logger;
13
+ import com.google.common.base.Optional;
11
14
  import org.embulk.spi.Exec;
12
15
 
13
16
  public class JdbcOutputConnection
@@ -47,6 +50,11 @@ public class JdbcOutputConnection
47
50
  return databaseMetaData;
48
51
  }
49
52
 
53
+ public Charset getTableNameCharset() throws SQLException
54
+ {
55
+ return StandardCharsets.UTF_8;
56
+ }
57
+
50
58
  protected void setSearchPath(String schema) throws SQLException
51
59
  {
52
60
  Statement stmt = connection.createStatement();
@@ -124,46 +132,20 @@ public class JdbcOutputConnection
124
132
 
125
133
  sb.append("CREATE TABLE IF NOT EXISTS ");
126
134
  quoteIdentifierString(sb, name);
127
- sb.append(buildColumnsOfCreateTableSql(schema));
135
+ sb.append(buildCreateTableSchemaSql(schema));
128
136
  return sb.toString();
129
137
  }
130
138
 
131
- public void createTable(String tableName, JdbcSchema schema) throws SQLException
132
- {
133
- Statement stmt = connection.createStatement();
134
- try {
135
- String sql = buildCreateTableSql(tableName, schema);
136
- executeUpdate(stmt, sql);
137
- commitIfNecessary(connection);
138
- } catch (SQLException ex) {
139
- throw safeRollback(connection, ex);
140
- } finally {
141
- stmt.close();
142
- }
143
- }
144
-
145
- protected String buildCreateTableSql(String name, JdbcSchema schema)
146
- {
147
- StringBuilder sb = new StringBuilder();
148
-
149
- sb.append("CREATE TABLE ");
150
- quoteIdentifierString(sb, name);
151
- sb.append(buildColumnsOfCreateTableSql(schema));
152
- return sb.toString();
153
- }
154
-
155
- private String buildColumnsOfCreateTableSql(JdbcSchema schema)
139
+ protected String buildCreateTableSchemaSql(JdbcSchema schema)
156
140
  {
157
141
  StringBuilder sb = new StringBuilder();
158
142
 
159
143
  sb.append(" (");
160
- boolean first = true;
161
- for (JdbcColumn c : schema.getColumns()) {
162
- if (first) { first = false; }
163
- else { sb.append(", "); }
164
- quoteIdentifierString(sb, c.getName());
144
+ for (int i=0; i < schema.getCount(); i++) {
145
+ if (i != 0) { sb.append(", "); }
146
+ quoteIdentifierString(sb, schema.getColumnName(i));
165
147
  sb.append(" ");
166
- String typeName = getCreateTableTypeName(c);
148
+ String typeName = getCreateTableTypeName(schema.getColumn(i));
167
149
  sb.append(typeName);
168
150
  }
169
151
  sb.append(")");
@@ -181,33 +163,36 @@ public class JdbcOutputConnection
181
163
 
182
164
  protected String getCreateTableTypeName(JdbcColumn c)
183
165
  {
184
- String convertedTypeName = convertTypeName(c.getTypeName());
185
- switch (getColumnDeclareType(convertedTypeName, c)) {
166
+ if (c.getDeclaredType().isPresent()) {
167
+ return c.getDeclaredType().get();
168
+ } else {
169
+ return buildColumnTypeName(c);
170
+ }
171
+ }
172
+
173
+ protected String buildColumnTypeName(JdbcColumn c)
174
+ {
175
+ String simpleTypeName = c.getSimpleTypeName();
176
+ switch (getColumnDeclareType(simpleTypeName, c)) {
186
177
  case SIZE:
187
- return String.format("%s(%d)", convertedTypeName, c.getSizeTypeParameter());
178
+ return String.format("%s(%d)", simpleTypeName, c.getSizeTypeParameter());
188
179
  case SIZE_AND_SCALE:
189
180
  if (c.getScaleTypeParameter() < 0) {
190
- return String.format("%s(%d,0)", convertedTypeName, c.getSizeTypeParameter());
181
+ return String.format("%s(%d,0)", simpleTypeName, c.getSizeTypeParameter());
191
182
  } else {
192
- return String.format("%s(%d,%d)", convertedTypeName, c.getSizeTypeParameter(), c.getScaleTypeParameter());
183
+ return String.format("%s(%d,%d)", simpleTypeName, c.getSizeTypeParameter(), c.getScaleTypeParameter());
193
184
  }
194
185
  case SIZE_AND_OPTIONAL_SCALE:
195
186
  if (c.getScaleTypeParameter() < 0) {
196
- return String.format("%s(%d)", convertedTypeName, c.getSizeTypeParameter());
187
+ return String.format("%s(%d)", simpleTypeName, c.getSizeTypeParameter());
197
188
  } else {
198
- return String.format("%s(%d,%d)", convertedTypeName, c.getSizeTypeParameter(), c.getScaleTypeParameter());
189
+ return String.format("%s(%d,%d)", simpleTypeName, c.getSizeTypeParameter(), c.getScaleTypeParameter());
199
190
  }
200
191
  default: // SIMPLE
201
- return convertedTypeName;
192
+ return simpleTypeName;
202
193
  }
203
194
  }
204
195
 
205
- // hook point for subclasses
206
- protected String convertTypeName(String typeName)
207
- {
208
- return typeName;
209
- }
210
-
211
196
  // TODO
212
197
  private static final String[] STANDARD_SIZE_TYPE_NAMES = new String[] {
213
198
  "CHAR",
@@ -242,122 +227,118 @@ public class JdbcOutputConnection
242
227
  return ColumnDeclareType.SIMPLE;
243
228
  }
244
229
 
245
- protected String buildInsertTableSql(String fromTable, JdbcSchema fromTableSchema, String toTable)
230
+ public PreparedStatement prepareBatchInsertStatement(String toTable, JdbcSchema toTableSchema, Optional<List<String>> mergeKeys) throws SQLException
231
+ {
232
+ String sql;
233
+ if (mergeKeys.isPresent()) {
234
+ sql = buildPreparedMergeSql(toTable, toTableSchema, mergeKeys.get());
235
+ } else {
236
+ sql = buildPreparedInsertSql(toTable, toTableSchema);
237
+ }
238
+ logger.info("Prepared SQL: {}", sql);
239
+ return connection.prepareStatement(sql);
240
+ }
241
+
242
+ protected String buildPreparedInsertSql(String toTable, JdbcSchema toTableSchema) throws SQLException
246
243
  {
247
244
  StringBuilder sb = new StringBuilder();
248
245
 
249
246
  sb.append("INSERT INTO ");
250
247
  quoteIdentifierString(sb, toTable);
248
+
251
249
  sb.append(" (");
252
- boolean first = true;
253
- for (JdbcColumn c : fromTableSchema.getColumns()) {
254
- if (first) { first = false; }
255
- else { sb.append(", "); }
256
- quoteIdentifierString(sb, c.getName());
250
+ for (int i=0; i < toTableSchema.getCount(); i++) {
251
+ if(i != 0) { sb.append(", "); }
252
+ quoteIdentifierString(sb, toTableSchema.getColumnName(i));
257
253
  }
258
- sb.append(") ");
259
- sb.append("SELECT ");
260
- for (JdbcColumn c : fromTableSchema.getColumns()) {
261
- if (first) { first = false; }
262
- else { sb.append(", "); }
263
- quoteIdentifierString(sb, c.getName());
254
+ sb.append(") VALUES (");
255
+ for(int i=0; i < toTableSchema.getCount(); i++) {
256
+ if(i != 0) { sb.append(", "); }
257
+ sb.append("?");
264
258
  }
265
- sb.append(" FROM ");
266
- quoteIdentifierString(sb, fromTable);
259
+ sb.append(")");
267
260
 
268
261
  return sb.toString();
269
262
  }
270
263
 
271
- protected String buildTruncateSql(String table)
264
+ protected String buildPreparedMergeSql(String toTable, JdbcSchema toTableSchema, List<String> mergeKeys) throws SQLException
272
265
  {
273
- StringBuilder sb = new StringBuilder();
274
-
275
- sb.append("DELETE FROM ");
276
- quoteIdentifierString(sb, table);
277
-
278
- return sb.toString();
266
+ throw new UnsupportedOperationException("not implemented");
279
267
  }
280
268
 
281
- protected void insertTable(String fromTable, JdbcSchema fromTableSchema, String toTable,
269
+ protected void collectInsert(List<String> fromTables, JdbcSchema schema, String toTable,
282
270
  boolean truncateDestinationFirst) throws SQLException
283
271
  {
284
272
  Statement stmt = connection.createStatement();
285
273
  try {
286
- if(truncateDestinationFirst) {
274
+ if (truncateDestinationFirst) {
287
275
  String sql = buildTruncateSql(toTable);
288
276
  executeUpdate(stmt, sql);
289
277
  }
290
- String sql = buildInsertTableSql(fromTable, fromTableSchema, toTable);
278
+ String sql = buildCollectInsertSql(fromTables, schema, toTable);
291
279
  executeUpdate(stmt, sql);
292
280
  commitIfNecessary(connection);
293
281
  } catch (SQLException ex) {
294
- connection.rollback();
295
- throw ex;
282
+ throw safeRollback(connection, ex);
296
283
  } finally {
297
284
  stmt.close();
298
285
  }
299
286
  }
300
287
 
301
- public PreparedStatement prepareInsertSql(String toTable, JdbcSchema toTableSchema) throws SQLException
288
+ protected String buildTruncateSql(String table)
302
289
  {
303
- String insertSql = buildPrepareInsertSql(toTable, toTableSchema);
304
- logger.info("Prepared SQL: {}", insertSql);
305
- return connection.prepareStatement(insertSql);
306
- }
290
+ StringBuilder sb = new StringBuilder();
307
291
 
308
- public PreparedStatement prepareUpsertSql(String toTable, JdbcSchema toTableSchema) throws SQLException
309
- {
310
- String upsertSql = buildPrepareUpsertSql(toTable, toTableSchema);
311
- logger.info("Prepared SQL: {}", upsertSql);
312
- return connection.prepareStatement(upsertSql);
292
+ sb.append("DELETE FROM ");
293
+ quoteIdentifierString(sb, table);
294
+
295
+ return sb.toString();
313
296
  }
314
297
 
315
- protected String buildPrepareInsertSql(String toTable, JdbcSchema toTableSchema) throws SQLException
298
+ protected String buildCollectInsertSql(List<String> fromTables, JdbcSchema schema, String toTable)
316
299
  {
317
300
  StringBuilder sb = new StringBuilder();
318
301
 
319
302
  sb.append("INSERT INTO ");
320
303
  quoteIdentifierString(sb, toTable);
321
-
322
304
  sb.append(" (");
323
- for (int i=0; i < toTableSchema.getCount(); i++) {
324
- if(i != 0) { sb.append(", "); }
325
- quoteIdentifierString(sb, toTableSchema.getColumnName(i));
305
+ for (int i=0; i < schema.getCount(); i++) {
306
+ if (i != 0) { sb.append(", "); }
307
+ quoteIdentifierString(sb, schema.getColumnName(i));
326
308
  }
327
- sb.append(") VALUES (");
328
- for(int i=0; i < toTableSchema.getCount(); i++) {
329
- if(i != 0) { sb.append(", "); }
330
- sb.append("?");
309
+ sb.append(") ");
310
+ for (int i=0; i < fromTables.size(); i++) {
311
+ if (i != 0) { sb.append(" UNION ALL "); }
312
+ sb.append("SELECT ");
313
+ for (int j=0; j < schema.getCount(); j++) {
314
+ if (j != 0) { sb.append(", "); }
315
+ quoteIdentifierString(sb, schema.getColumnName(j));
316
+ }
317
+ sb.append(" FROM ");
318
+ quoteIdentifierString(sb, fromTables.get(i));
331
319
  }
332
- sb.append(")");
333
320
 
334
321
  return sb.toString();
335
322
  }
336
323
 
337
- protected String buildPrepareUpsertSql(String toTable, JdbcSchema toTableSchema) throws SQLException
324
+ protected void collectMerge(List<String> fromTables, JdbcSchema schema, String toTable, List<String> mergeKeys) throws SQLException
338
325
  {
339
- throw new UnsupportedOperationException("not implemented yet");
326
+ Statement stmt = connection.createStatement();
327
+ try {
328
+ String sql = buildCollectMergeSql(fromTables, schema, toTable, mergeKeys);
329
+ executeUpdate(stmt, sql);
330
+ commitIfNecessary(connection);
331
+ } catch (SQLException ex) {
332
+ throw safeRollback(connection, ex);
333
+ } finally {
334
+ stmt.close();
335
+ }
340
336
  }
341
337
 
342
- // TODO
343
- //protected void gatherInsertTables(List<String> fromTables, JdbcSchema fromTableSchema, String toTable,
344
- // boolean truncateDestinationFirst) throws SQLException
345
- //{
346
- // Statement stmt = connection.createStatement();
347
- // try {
348
- // if(truncateDestinationFirst) {
349
- // String sql = buildTruncateSql(toTable);
350
- // executeUpdate(stmt, sql);
351
- // }
352
- // String sql = buildGatherInsertTables(fromTable, fromTableSchema, toTable);
353
- // executeUpdate(stmt, sql);
354
- // commitIfNecessary(connection);
355
- // } catch (SQLException ex) {
356
- // throw safeRollback(connection, ex);
357
- // } finally {
358
- // stmt.close();
359
- // }
360
- //}
338
+ protected String buildCollectMergeSql(List<String> fromTables, JdbcSchema schema, String toTable, List<String> mergeKeys) throws SQLException
339
+ {
340
+ throw new UnsupportedOperationException("not implemented");
341
+ }
361
342
 
362
343
  public void replaceTable(String fromTable, JdbcSchema schema, String toTable) throws SQLException
363
344
  {