embulk-output-jdbc 0.2.4 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
  {