001: /*
002: *
003: * The DbUnit Database Testing Framework
004: * Copyright (C)2002-2004, DbUnit.org
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2.1 of the License, or (at your option) any later version.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this library; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: *
020: */
021:
022: package org.dbunit.database;
023:
024: import org.slf4j.Logger;
025: import org.slf4j.LoggerFactory;
026:
027: import org.dbunit.dataset.*;
028:
029: import java.sql.Connection;
030: import java.sql.DatabaseMetaData;
031: import java.sql.ResultSet;
032: import java.sql.SQLException;
033: import java.util.*;
034:
035: /**
036: * provides access
037: to a database instance as a dataset.
038:
039: * @author Manuel Laflamme
040: * @version $Revision: 583 $
041: * @since Feb 17, 2002
042: */
043: public class DatabaseDataSet extends AbstractDataSet {
044:
045: /**
046: * Logger for this class
047: */
048: private static final Logger logger = LoggerFactory
049: .getLogger(DatabaseDataSet.class);
050:
051: private final IDatabaseConnection _connection;
052: private final Map _tableMap = new HashMap();
053: private List _nameList = null;
054:
055: DatabaseDataSet(IDatabaseConnection connection) throws SQLException {
056: _connection = connection;
057: }
058:
059: static String getSelectStatement(String schema,
060: ITableMetaData metaData, String escapePattern)
061: throws DataSetException {
062: logger.debug("getSelectStatement(schema=" + schema
063: + ", metaData=" + metaData + ", escapePattern="
064: + escapePattern + ") - start");
065:
066: Column[] columns = metaData.getColumns();
067: Column[] primaryKeys = metaData.getPrimaryKeys();
068:
069: // select
070: StringBuffer sqlBuffer = new StringBuffer(128);
071: sqlBuffer.append("select ");
072: for (int i = 0; i < columns.length; i++) {
073: if (i > 0) {
074: sqlBuffer.append(", ");
075: }
076: String columnName = DataSetUtils.getQualifiedName(null,
077: columns[i].getColumnName(), escapePattern);
078: sqlBuffer.append(columnName);
079: }
080:
081: // from
082: sqlBuffer.append(" from ");
083: sqlBuffer.append(DataSetUtils.getQualifiedName(schema, metaData
084: .getTableName(), escapePattern));
085:
086: // order by
087: for (int i = 0; i < primaryKeys.length; i++) {
088: if (i == 0) {
089: sqlBuffer.append(" order by ");
090: } else {
091: sqlBuffer.append(", ");
092: }
093: sqlBuffer.append(DataSetUtils.getQualifiedName(null,
094: primaryKeys[i].getColumnName(), escapePattern));
095:
096: }
097:
098: return sqlBuffer.toString();
099: }
100:
101: private String getQualifiedName(String prefix, String name) {
102: logger.debug("getQualifiedName(prefix=" + prefix + ", name="
103: + name + ") - start");
104:
105: DatabaseConfig config = _connection.getConfig();
106: boolean feature = config
107: .getFeature(DatabaseConfig.FEATURE_QUALIFIED_TABLE_NAMES);
108: if (feature) {
109: return DataSetUtils.getQualifiedName(prefix, name);
110: }
111: return name;
112: }
113:
114: /**
115: * Get all the table names form the database that are not system tables.
116: */
117: private void initialize() throws DataSetException {
118: logger.debug("initialize() - start");
119:
120: if (_nameList != null) {
121: return;
122: }
123:
124: try {
125: Connection jdbcConnection = _connection.getConnection();
126: String schema = _connection.getSchema();
127: String[] tableType = (String[]) _connection.getConfig()
128: .getProperty(DatabaseConfig.PROPERTY_TABLE_TYPE);
129:
130: DatabaseMetaData databaseMetaData = jdbcConnection
131: .getMetaData();
132: ResultSet resultSet = databaseMetaData.getTables(null,
133: schema, "%", tableType);
134:
135: try {
136: List nameList = new ArrayList();
137: while (resultSet.next()) {
138: String schemaName = resultSet.getString(2);
139: String tableName = resultSet.getString(3);
140:
141: // skip oracle 10g recycle bin system tables if enabled
142: if (_connection
143: .getConfig()
144: .getFeature(
145: DatabaseConfig.FEATURE_SKIP_ORACLE_RECYCLEBIN_TABLES)) {
146: // Oracle 10g workaround
147: // don't process system tables (oracle recycle bin tables) which
148: // are reported to the application due a bug in the oracle JDBC driver
149: if (tableName.startsWith("BIN$"))
150: continue;
151: }
152: tableName = getQualifiedName(schemaName, tableName);
153:
154: // prevent table name conflict
155: if (_tableMap.containsKey(tableName.toUpperCase())) {
156: throw new AmbiguousTableNameException(tableName);
157: }
158: nameList.add(tableName);
159: _tableMap.put(tableName.toUpperCase(), null);
160: }
161:
162: _nameList = nameList;
163: } finally {
164: resultSet.close();
165: }
166: } catch (SQLException e) {
167: logger.error("initialize()", e);
168:
169: throw new DataSetException(e);
170: }
171: }
172:
173: ////////////////////////////////////////////////////////////////////////////
174: // AbstractDataSet class
175:
176: protected ITableIterator createIterator(boolean reversed)
177: throws DataSetException {
178: logger.debug("createIterator(reversed=" + reversed
179: + ") - start");
180:
181: String[] names = getTableNames();
182: if (reversed) {
183: names = DataSetUtils.reverseStringArray(names);
184: }
185:
186: return new DatabaseTableIterator(names, this );
187: }
188:
189: ////////////////////////////////////////////////////////////////////////////
190: // IDataSet interface
191:
192: public String[] getTableNames() throws DataSetException {
193: logger.debug("getTableNames() - start");
194:
195: initialize();
196:
197: return (String[]) _nameList.toArray(new String[0]);
198: }
199:
200: public ITableMetaData getTableMetaData(String tableName)
201: throws DataSetException {
202: logger.debug("getTableMetaData(tableName=" + tableName
203: + ") - start");
204:
205: initialize();
206:
207: // Verify if table exist in the database
208: String upperTableName = tableName.toUpperCase();
209: if (!_tableMap.containsKey(upperTableName)) {
210: throw new NoSuchTableException(tableName);
211: }
212:
213: // Try to find cached metadata
214: ITableMetaData metaData = (ITableMetaData) _tableMap
215: .get(upperTableName);
216: if (metaData != null) {
217: return metaData;
218: }
219:
220: // Search for original database table name
221: for (Iterator it = _nameList.iterator(); it.hasNext();) {
222: String databaseTableName = (String) it.next();
223: if (databaseTableName.equalsIgnoreCase(tableName)) {
224: // Create metadata and cache it
225: metaData = new DatabaseTableMetaData(databaseTableName,
226: _connection);
227: _tableMap.put(upperTableName, metaData);
228: break;
229: }
230: }
231:
232: return metaData;
233: }
234:
235: public ITable getTable(String tableName) throws DataSetException {
236: logger.debug("getTable(tableName=" + tableName + ") - start");
237:
238: initialize();
239:
240: try {
241: ITableMetaData metaData = getTableMetaData(tableName);
242:
243: DatabaseConfig config = _connection.getConfig();
244: IResultSetTableFactory factory = (IResultSetTableFactory) config
245: .getProperty(DatabaseConfig.PROPERTY_RESULTSET_TABLE_FACTORY);
246: return factory.createTable(metaData, _connection);
247: } catch (SQLException e) {
248: logger.error("getTable()", e);
249:
250: throw new DataSetException(e);
251: }
252: }
253: }
|