1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.dbunit.operation;
23
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
26
27 import org.dbunit.DatabaseUnitException;
28 import org.dbunit.database.IDatabaseConnection;
29 import org.dbunit.database.statement.IPreparedBatchStatement;
30 import org.dbunit.database.statement.SimplePreparedStatement;
31 import org.dbunit.dataset.Column;
32 import org.dbunit.dataset.DataSetException;
33 import org.dbunit.dataset.IDataSet;
34 import org.dbunit.dataset.ITable;
35 import org.dbunit.dataset.ITableIterator;
36 import org.dbunit.dataset.ITableMetaData;
37 import org.dbunit.dataset.NoPrimaryKeyException;
38 import org.dbunit.dataset.RowOutOfBoundsException;
39 import org.dbunit.dataset.datatype.DataType;
40
41 import java.sql.PreparedStatement;
42 import java.sql.ResultSet;
43 import java.sql.SQLException;
44 import java.util.BitSet;
45
46
47
48
49
50
51
52
53
54
55
56 public class RefreshOperation extends AbstractOperation
57 {
58
59
60
61
62 private static final Logger logger = LoggerFactory.getLogger(RefreshOperation.class);
63
64 private final InsertOperation _insertOperation;
65 private final UpdateOperation _updateOperation;
66
67 RefreshOperation()
68 {
69 _insertOperation = (InsertOperation)DatabaseOperation.INSERT;
70 _updateOperation = (UpdateOperation)DatabaseOperation.UPDATE;
71 }
72
73 private boolean isEmpty(ITable table) throws DataSetException
74 {
75 return AbstractBatchOperation.isEmpty(table);
76 }
77
78
79
80
81 public void execute(IDatabaseConnection connection, IDataSet dataSet)
82 throws DatabaseUnitException, SQLException
83 {
84 logger.debug("execute(connection={}, dataSet) - start", connection);
85
86
87 ITableIterator iterator = dataSet.iterator();
88 while (iterator.next())
89 {
90 ITable table = iterator.getTable();
91
92 String tableName=table.getTableMetaData().getTableName();
93 logger.trace("execute: processing table='{}'", tableName);
94
95
96 if (isEmpty(table))
97 {
98 continue;
99 }
100
101 ITableMetaData metaData = getOperationMetaData(connection,
102 table.getTableMetaData());
103 RowOperation updateRowOperation = createUpdateOperation(connection,
104 metaData);
105 RowOperation insertRowOperation = new InsertRowOperation(connection,
106 metaData);
107
108 try
109 {
110
111 for (int i = 0; ; i++)
112 {
113 if (!updateRowOperation.execute(table, i))
114 {
115 insertRowOperation.execute(table, i);
116 }
117 }
118 }
119 catch (RowOutOfBoundsException e)
120 {
121
122
123
124
125 }
126 catch (SQLException e)
127 {
128 final String msg =
129 "Exception processing table name='" + tableName + "'";
130 throw new DatabaseUnitException(msg, e);
131 }
132 finally
133 {
134
135 updateRowOperation.close();
136 insertRowOperation.close();
137 }
138 }
139
140 }
141
142 private RowOperation createUpdateOperation(IDatabaseConnection connection,
143 ITableMetaData metaData)
144 throws DataSetException, SQLException
145 {
146 logger.debug("createUpdateOperation(connection={}, metaData={}) - start", connection, metaData);
147
148
149 if (metaData.getColumns().length > metaData.getPrimaryKeys().length)
150 {
151 return new UpdateRowOperation(connection, metaData);
152 }
153
154
155 return new RowExistOperation(connection, metaData);
156 }
157
158
159
160
161 class RowOperation
162 {
163
164
165
166
167 private final Logger logger = LoggerFactory.getLogger(RowOperation.class);
168
169 protected IPreparedBatchStatement _statement;
170 protected OperationData _operationData;
171 protected BitSet _ignoreMapping;
172
173
174
175
176
177 public boolean execute(ITable table, int row)
178 throws DataSetException, SQLException
179 {
180 logger.debug("execute(table={}, row={}) - start", table, String.valueOf(row));
181
182 Column[] columns = _operationData.getColumns();
183 for (int i = 0; i < columns.length; i++)
184 {
185
186 if (_ignoreMapping == null || !_ignoreMapping.get(i))
187 {
188 Object value = table.getValue(row, columns[i].getColumnName());
189 _statement.addValue(value, columns[i].getDataType());
190 }
191 }
192 _statement.addBatch();
193 int result = _statement.executeBatch();
194 _statement.clearBatch();
195
196 return result == 1;
197 }
198
199
200
201
202 public void close() throws SQLException
203 {
204 logger.debug("close() - start");
205
206 if (_statement != null)
207 {
208 _statement.close();
209 }
210 }
211 }
212
213
214
215
216 private class InsertRowOperation extends RowOperation
217 {
218
219
220
221
222 private final Logger logger = LoggerFactory.getLogger(InsertRowOperation.class);
223
224 private IDatabaseConnection _connection;
225 private ITableMetaData _metaData;
226
227 public InsertRowOperation(IDatabaseConnection connection,
228 ITableMetaData metaData)
229 throws DataSetException, SQLException
230 {
231 _connection = connection;
232 _metaData = metaData;
233 }
234
235 public boolean execute(ITable table, int row)
236 throws DataSetException, SQLException
237 {
238 logger.debug("execute(table={}, row={}) - start", table, row);
239
240
241
242 if (_ignoreMapping == null ||
243 !_insertOperation.equalsIgnoreMapping(_ignoreMapping, table, row))
244 {
245
246 if (_statement != null)
247 {
248 _statement.close();
249 }
250
251 _ignoreMapping = _insertOperation.getIgnoreMapping(table, row);
252 _operationData = _insertOperation.getOperationData(_metaData,
253 _ignoreMapping, _connection);
254 _statement = new SimplePreparedStatement(_operationData.getSql(),
255 _connection.getConnection());
256 }
257
258 return super.execute(table, row);
259 }
260
261 }
262
263
264
265
266 private class UpdateRowOperation extends RowOperation
267 {
268 PreparedStatement _countStatement;
269
270 public UpdateRowOperation(IDatabaseConnection connection,
271 ITableMetaData metaData)
272 throws DataSetException, SQLException
273 {
274
275 _operationData = _updateOperation.getOperationData(
276 metaData, null, connection);
277 _statement = new SimplePreparedStatement(_operationData.getSql(),
278 connection.getConnection());
279 }
280 }
281
282
283
284
285 private class RowExistOperation extends RowOperation
286 {
287
288
289
290
291 private final Logger logger = LoggerFactory.getLogger(RowExistOperation.class);
292
293 PreparedStatement _countStatement;
294
295 public RowExistOperation(IDatabaseConnection connection,
296 ITableMetaData metaData)
297 throws DataSetException, SQLException
298 {
299
300 _operationData = getSelectCountData(metaData, connection);
301 _countStatement = connection.getConnection().prepareStatement(
302 _operationData.getSql());
303 }
304
305 private OperationData getSelectCountData(
306 ITableMetaData metaData, IDatabaseConnection connection) throws DataSetException
307 {
308 logger.debug("getSelectCountData(metaData={}, connection={}) - start", metaData, connection);
309
310 Column[] primaryKeys = metaData.getPrimaryKeys();
311
312
313 if (primaryKeys.length == 0)
314 {
315 throw new NoPrimaryKeyException(metaData.getTableName());
316 }
317
318
319 final StringBuilder sqlBuffer = new StringBuilder(128);
320 sqlBuffer.append("select COUNT(*) from ");
321 sqlBuffer.append(getQualifiedName(connection.getSchema(), metaData.getTableName(), connection));
322
323
324 sqlBuffer.append(" where ");
325 for (int i = 0; i < primaryKeys.length; i++)
326 {
327 Column column = primaryKeys[i];
328
329 if (i > 0)
330 {
331 sqlBuffer.append(" and ");
332 }
333 sqlBuffer.append(getQualifiedName(null, column.getColumnName(), connection));
334 sqlBuffer.append(" = ?");
335 }
336
337 return new OperationData(sqlBuffer.toString(), primaryKeys);
338 }
339
340
341
342
343
344
345
346
347 public boolean execute(ITable table, int row)
348 throws DataSetException, SQLException
349 {
350 logger.debug("execute(table={}, row={}) - start", table, row);
351
352 Column[] columns = _operationData.getColumns();
353 for (int i = 0; i < columns.length; i++)
354 {
355 Object value = table.getValue(row, columns[i].getColumnName());
356 DataType dataType = columns[i].getDataType();
357 dataType.setSqlValue(value, i + 1, _countStatement);
358 }
359
360 ResultSet resultSet = _countStatement.executeQuery();
361 try
362 {
363 resultSet.next();
364 return resultSet.getInt(1) > 0;
365 }
366 finally
367 {
368 resultSet.close();
369 }
370 }
371
372 public void close() throws SQLException
373 {
374 logger.debug("close() - start");
375
376 _countStatement.close();
377 }
378 }
379
380 }