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: import org.dbunit.dataset.filter.IColumnFilter;
029: import org.dbunit.dataset.datatype.DataType;
030: import org.dbunit.dataset.datatype.IDataTypeFactory;
031:
032: import java.sql.*;
033: import java.util.ArrayList;
034: import java.util.Arrays;
035: import java.util.Collections;
036: import java.util.List;
037:
038: /**
039: * @author Manuel Laflamme
040: * @version $Revision: 554 $
041: * @since Mar 8, 2002
042: */
043: public class DatabaseTableMetaData extends AbstractTableMetaData {
044:
045: /**
046: * Logger for this class
047: */
048: private static final Logger logger = LoggerFactory
049: .getLogger(DatabaseTableMetaData.class);
050:
051: private final String _tableName;
052: private final IDatabaseConnection _connection;
053: private Column[] _columns;
054: private Column[] _primaryKeys;
055:
056: DatabaseTableMetaData(String tableName,
057: IDatabaseConnection connection) {
058: _tableName = tableName;
059: _connection = connection;
060: }
061:
062: public static ITableMetaData createMetaData(String tableName,
063: ResultSet resultSet, IDataTypeFactory dataTypeFactory)
064: throws DataSetException, SQLException {
065: logger.debug("createMetaData(tableName=" + tableName
066: + ", resultSet=" + resultSet + ", dataTypeFactory="
067: + dataTypeFactory + ") - start");
068:
069: ResultSetMetaData metaData = resultSet.getMetaData();
070: Column[] columns = new Column[metaData.getColumnCount()];
071: for (int i = 0; i < columns.length; i++) {
072: int columnType = metaData.getColumnType(i + 1);
073: String columnTypeName = metaData.getColumnTypeName(i + 1);
074: DataType dataType = dataTypeFactory.createDataType(
075: columnType, columnTypeName);
076: columns[i] = new Column(metaData.getColumnName(i + 1),
077: dataType, columnTypeName, Column
078: .nullableValue(metaData.isNullable(i + 1)));
079: }
080:
081: return new DefaultTableMetaData(tableName, columns);
082: }
083:
084: public static ITableMetaData createMetaData(String tableName,
085: ResultSet resultSet, IDatabaseConnection connection)
086: throws SQLException, DataSetException {
087: logger.debug("createMetaData(tableName=" + tableName
088: + ", resultSet=" + resultSet + ", connection="
089: + connection + ") - start");
090:
091: DatabaseConfig config = connection.getConfig();
092: IDataTypeFactory typeFactory = (IDataTypeFactory) config
093: .getProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY);
094: return createMetaData(tableName, resultSet, typeFactory);
095: }
096:
097: private String[] getPrimaryKeyNames() throws SQLException {
098: logger.debug("getPrimaryKeyNames() - start");
099:
100: // qualified names support
101: String schemaName = _connection.getSchema();
102: String tableName = _tableName;
103: int index = tableName.indexOf(".");
104: if (index >= 0) {
105: schemaName = tableName.substring(0, index);
106: tableName = tableName.substring(index + 1);
107: }
108:
109: Connection connection = _connection.getConnection();
110: DatabaseMetaData databaseMetaData = connection.getMetaData();
111: ResultSet resultSet = databaseMetaData.getPrimaryKeys(null,
112: schemaName, tableName);
113:
114: List list = new ArrayList();
115: try {
116: while (resultSet.next()) {
117: String name = resultSet.getString(4);
118: int sequence = resultSet.getInt(5);
119: list.add(new PrimaryKeyData(name, sequence));
120: }
121: } finally {
122: resultSet.close();
123: }
124:
125: Collections.sort(list);
126: String[] keys = new String[list.size()];
127: for (int i = 0; i < keys.length; i++) {
128: PrimaryKeyData data = (PrimaryKeyData) list.get(i);
129: keys[i] = data.getName();
130: }
131:
132: return keys;
133: }
134:
135: private class PrimaryKeyData implements Comparable {
136:
137: /**
138: * Logger for this class
139: */
140: private final Logger logger = LoggerFactory
141: .getLogger(PrimaryKeyData.class);
142:
143: private final String _name;
144: private final int _index;
145:
146: public PrimaryKeyData(String name, int index) {
147: _name = name;
148: _index = index;
149: }
150:
151: public String getName() {
152: logger.debug("getName() - start");
153:
154: return _name;
155: }
156:
157: public int getIndex() {
158: logger.debug("getIndex() - start");
159:
160: return _index;
161: }
162:
163: ////////////////////////////////////////////////////////////////////////
164: // Comparable interface
165:
166: public int compareTo(Object o) {
167: logger.debug("compareTo(o=" + o + ") - start");
168:
169: PrimaryKeyData data = (PrimaryKeyData) o;
170: return getIndex() - data.getIndex();
171: }
172: }
173:
174: ////////////////////////////////////////////////////////////////////////////
175: // ITableMetaData interface
176:
177: public String getTableName() {
178: logger.debug("getTableName() - start");
179:
180: return _tableName;
181: }
182:
183: public Column[] getColumns() throws DataSetException {
184: logger.debug("getColumns() - start");
185:
186: if (_columns == null) {
187: try {
188: // qualified names support
189: String schemaName = _connection.getSchema();
190: String tableName = _tableName;
191: int index = tableName.indexOf(".");
192: if (index >= 0) {
193: schemaName = tableName.substring(0, index);
194: tableName = tableName.substring(index + 1);
195: }
196:
197: Connection jdbcConnection = _connection.getConnection();
198: DatabaseMetaData databaseMetaData = jdbcConnection
199: .getMetaData();
200: ResultSet resultSet = databaseMetaData.getColumns(null,
201: schemaName, tableName, "%");
202:
203: try {
204: DatabaseConfig config = _connection.getConfig();
205: IDataTypeFactory dataTypeFactory = (IDataTypeFactory) config
206: .getProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY);
207: boolean datatypeWarning = config
208: .getFeature(DatabaseConfig.FEATURE_DATATYPE_WARNING);
209:
210: List columnList = new ArrayList();
211: while (resultSet.next()) {
212: String columnName = resultSet.getString(4);
213: int sqlType = resultSet.getInt(5);
214: String sqlTypeName = resultSet.getString(6);
215: // int columnSize = resultSet.getInt(7);
216: int nullable = resultSet.getInt(11);
217:
218: // Convert SQL type to DataType
219: DataType dataType = dataTypeFactory
220: .createDataType(sqlType, sqlTypeName);
221: if (dataType != DataType.UNKNOWN) {
222: Column column = new Column(columnName,
223: dataType, sqlTypeName, Column
224: .nullableValue(nullable));
225: columnList.add(column);
226: } else if (datatypeWarning) {
227: System.out
228: .println("WARNING - "
229: + tableName
230: + "."
231: + columnName
232: + " data type ("
233: + sqlType
234: + ", ‘"
235: + sqlTypeName
236: + "’) not recognized and will be ignored. See FAQ for more information.");
237: }
238: }
239:
240: if (columnList.size() == 0) {
241: throw new NoColumnsFoundException(tableName);
242: }
243:
244: _columns = (Column[]) columnList
245: .toArray(new Column[0]);
246: } finally {
247: resultSet.close();
248: }
249: } catch (SQLException e) {
250: logger.error("getColumns()", e);
251:
252: throw new DataSetException(e);
253: }
254: }
255: return _columns;
256: }
257:
258: public Column[] getPrimaryKeys() throws DataSetException {
259: logger.debug("getPrimaryKeys() - start");
260:
261: if (_primaryKeys == null) {
262: try {
263: DatabaseConfig config = _connection.getConfig();
264: IColumnFilter primaryKeysFilter = (IColumnFilter) config
265: .getProperty(DatabaseConfig.PROPERTY_PRIMARY_KEY_FILTER);
266: if (primaryKeysFilter != null) {
267: _primaryKeys = getPrimaryKeys(getTableName(),
268: getColumns(), primaryKeysFilter);
269: } else {
270: _primaryKeys = getPrimaryKeys(getColumns(),
271: getPrimaryKeyNames());
272: }
273: } catch (SQLException e) {
274: logger.error("getPrimaryKeys()", e);
275:
276: throw new DataSetException(e);
277: }
278: }
279: return _primaryKeys;
280: }
281:
282: ////////////////////////////////////////////////////////////////////////////
283: // Object class
284: public String toString() {
285: logger.debug("toString() - start");
286:
287: try {
288: String tableName = getTableName();
289: String columns = Arrays.asList(getColumns()).toString();
290: String primaryKeys = Arrays.asList(getPrimaryKeys())
291: .toString();
292: return "table=" + tableName + ", cols=" + columns + ", pk="
293: + primaryKeys + "";
294: } catch (DataSetException e) {
295: logger.error("toString()", e);
296:
297: return super.toString();
298: }
299: }
300: }
|