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.database;
23
24 import java.sql.Connection;
25 import java.sql.DatabaseMetaData;
26 import java.sql.ResultSet;
27 import java.sql.SQLException;
28
29 import org.dbunit.DatabaseUnitRuntimeException;
30 import org.dbunit.dataset.AbstractDataSet;
31 import org.dbunit.dataset.Column;
32 import org.dbunit.dataset.DataSetException;
33 import org.dbunit.dataset.DataSetUtils;
34 import org.dbunit.dataset.IDataSet;
35 import org.dbunit.dataset.ITable;
36 import org.dbunit.dataset.ITableIterator;
37 import org.dbunit.dataset.ITableMetaData;
38 import org.dbunit.dataset.NoSuchTableException;
39 import org.dbunit.dataset.OrderedTableNameMap;
40 import org.dbunit.dataset.filter.ITableFilterSimple;
41 import org.dbunit.util.QualifiedTableName;
42 import org.dbunit.util.SQLHelper;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
45
46
47
48
49
50
51
52
53
54 public class DatabaseDataSet extends AbstractDataSet
55 {
56
57
58
59
60 private static final Logger logger = LoggerFactory.getLogger(DatabaseDataSet.class);
61
62 private final IDatabaseConnection _connection;
63 private OrderedTableNameMap _tableMap = null;
64
65 private final ITableFilterSimple _tableFilter;
66 private final ITableFilterSimple _oracleRecycleBinTableFilter;
67
68
69
70
71
72
73 DatabaseDataSet(IDatabaseConnection connection) throws SQLException
74 {
75 this(connection, connection.getConfig().getFeature(DatabaseConfig.FEATURE_CASE_SENSITIVE_TABLE_NAMES));
76 }
77
78
79
80
81
82
83
84
85
86 public DatabaseDataSet(IDatabaseConnection connection, boolean caseSensitiveTableNames) throws SQLException
87 {
88 this(connection, caseSensitiveTableNames, null);
89 }
90
91
92
93
94
95
96
97
98
99 public DatabaseDataSet(IDatabaseConnection connection, boolean caseSensitiveTableNames, ITableFilterSimple tableFilter)
100 throws SQLException
101 {
102 super(caseSensitiveTableNames);
103 if (connection == null) {
104 throw new NullPointerException(
105 "The parameter 'connection' must not be null");
106 }
107 _connection = connection;
108 _tableFilter = tableFilter;
109 _oracleRecycleBinTableFilter = new OracleRecycleBinTableFilter(connection.getConfig());
110 }
111
112
113
114 static String getSelectStatement(String schema, ITableMetaData metaData, String escapePattern)
115 throws DataSetException
116 {
117 if (logger.isDebugEnabled())
118 {
119 logger.debug("getSelectStatement(schema={}, metaData={}, escapePattern={}) - start",
120 new Object[] { schema, metaData, escapePattern });
121 }
122
123 Column[] columns = metaData.getColumns();
124 Column[] primaryKeys = metaData.getPrimaryKeys();
125
126 if(columns.length==0){
127 throw new DatabaseUnitRuntimeException("At least one column is required to build a valid select statement. "+
128 "Cannot load data for " + metaData);
129 }
130
131
132 StringBuffer sqlBuffer = new StringBuffer(128);
133 sqlBuffer.append("select ");
134 for (int i = 0; i < columns.length; i++)
135 {
136 if (i > 0)
137 {
138 sqlBuffer.append(", ");
139 }
140 String columnName = new QualifiedTableName(
141 columns[i].getColumnName(), null, escapePattern).getQualifiedName();
142 sqlBuffer.append(columnName);
143 }
144
145
146 sqlBuffer.append(" from ");
147 sqlBuffer.append(new QualifiedTableName(
148 metaData.getTableName(), schema, escapePattern).getQualifiedName());
149
150
151 for (int i = 0; i < primaryKeys.length; i++)
152 {
153 if (i == 0)
154 {
155 sqlBuffer.append(" order by ");
156 }
157 else
158 {
159 sqlBuffer.append(", ");
160 }
161 sqlBuffer.append(new QualifiedTableName(primaryKeys[i].getColumnName(), null, escapePattern).getQualifiedName());
162
163 }
164
165 return sqlBuffer.toString();
166 }
167
168
169
170
171 private void initialize() throws DataSetException
172 {
173 logger.debug("initialize() - start");
174
175 if (_tableMap != null)
176 {
177 return;
178 }
179
180 try
181 {
182 logger.debug("Initializing the data set from the database...");
183
184 Connection jdbcConnection = _connection.getConnection();
185 DatabaseMetaData databaseMetaData = jdbcConnection.getMetaData();
186
187 String schema = _connection.getSchema();
188
189 if(SQLHelper.isSybaseDb(jdbcConnection.getMetaData()) && !jdbcConnection.getMetaData().getUserName().equals(schema) ){
190 logger.warn("For sybase the schema name should be equal to the user name. " +
191 "Otherwise the DatabaseMetaData#getTables() method might not return any columns. " +
192 "See dbunit tracker #1628896 and http://issues.apache.org/jira/browse/TORQUE-40?page=all");
193 }
194
195 DatabaseConfig config = _connection.getConfig();
196 String[] tableType = (String[])config.getProperty(DatabaseConfig.PROPERTY_TABLE_TYPE);
197 IMetadataHandler metadataHandler = (IMetadataHandler) config.getProperty(DatabaseConfig.PROPERTY_METADATA_HANDLER);
198
199 ResultSet resultSet = metadataHandler.getTables(databaseMetaData, schema, tableType);
200
201 if(logger.isDebugEnabled())
202 {
203 logger.debug(SQLHelper.getDatabaseInfo(jdbcConnection.getMetaData()));
204 logger.debug("metadata resultset={}", resultSet);
205 }
206
207 try
208 {
209 OrderedTableNameMap tableMap = super.createTableNameMap();
210 while (resultSet.next())
211 {
212 String schemaName = metadataHandler.getSchema(resultSet);
213 String tableName = resultSet.getString(3);
214
215 if(_tableFilter != null && !_tableFilter.accept(tableName))
216 {
217 logger.debug("Skipping table '{}'", tableName);
218 continue;
219 }
220 if(!_oracleRecycleBinTableFilter.accept(tableName))
221 {
222 logger.debug("Skipping oracle recycle bin table '{}'", tableName);
223 continue;
224 }
225
226
227 QualifiedTableName qualifiedTableName = new QualifiedTableName(tableName, schemaName);
228 tableName = qualifiedTableName.getQualifiedNameIfEnabled(config);
229
230
231 tableMap.add(tableName, null);
232 }
233
234 _tableMap = tableMap;
235 }
236 finally
237 {
238 resultSet.close();
239 }
240 }
241 catch (SQLException e)
242 {
243 throw new DataSetException(e);
244 }
245 }
246
247
248
249
250 protected ITableIterator createIterator(boolean reversed)
251 throws DataSetException
252 {
253 if(logger.isDebugEnabled())
254 {
255 logger.debug("createIterator(reversed={}) - start", String.valueOf(reversed));
256 }
257
258 String[] names = getTableNames();
259 if (reversed)
260 {
261 names = DataSetUtils.reverseStringArray(names);
262 }
263
264 return new DatabaseTableIterator(names, this);
265 }
266
267
268
269
270 public String[] getTableNames() throws DataSetException
271 {
272 initialize();
273
274 return _tableMap.getTableNames();
275 }
276
277 public ITableMetaData getTableMetaData(String tableName) throws DataSetException
278 {
279 logger.debug("getTableMetaData(tableName={}) - start", tableName);
280
281 initialize();
282
283
284 if (!_tableMap.containsTable(tableName))
285 {
286 logger.error("Table '{}' not found in tableMap={}", tableName,
287 _tableMap);
288 throw new NoSuchTableException(tableName);
289 }
290
291
292 ITableMetaData metaData = (ITableMetaData)_tableMap.get(tableName);
293 if (metaData != null)
294 {
295 return metaData;
296 }
297
298
299 metaData = new DatabaseTableMetaData(tableName, _connection, true, super.isCaseSensitiveTableNames());
300
301 _tableMap.update(tableName, metaData);
302
303 return metaData;
304 }
305
306 public ITable getTable(String tableName) throws DataSetException
307 {
308 logger.debug("getTable(tableName={}) - start", tableName);
309
310 initialize();
311
312 try
313 {
314 ITableMetaData metaData = getTableMetaData(tableName);
315
316 DatabaseConfig config = _connection.getConfig();
317 IResultSetTableFactory factory = (IResultSetTableFactory)config.getProperty(
318 DatabaseConfig.PROPERTY_RESULTSET_TABLE_FACTORY);
319 return factory.createTable(metaData, _connection);
320 }
321 catch (SQLException e)
322 {
323 throw new DataSetException(e);
324 }
325 }
326
327
328 private static class OracleRecycleBinTableFilter implements ITableFilterSimple
329 {
330 private final DatabaseConfig _config;
331
332 public OracleRecycleBinTableFilter(DatabaseConfig config)
333 {
334 this._config = config;
335 }
336
337 public boolean accept(String tableName) throws DataSetException
338 {
339
340 if(_config.getFeature(DatabaseConfig.FEATURE_SKIP_ORACLE_RECYCLEBIN_TABLES)) {
341
342
343
344 if (tableName.startsWith("BIN$"))
345 {
346 return false;
347 }
348 }
349
350 return true;
351 }
352 }
353
354 }