All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.dbunit.database.DatabaseTableMetaData Maven / Gradle / Ivy

The newest version!
/*
 *
 * The DbUnit Database Testing Framework
 * Copyright (C)2002-2004, DbUnit.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

package org.dbunit.database;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import org.dbunit.dataset.AbstractTableMetaData;
import org.dbunit.dataset.Column;
import org.dbunit.dataset.Columns;
import org.dbunit.dataset.DataSetException;
import org.dbunit.dataset.ITableMetaData;
import org.dbunit.dataset.NoSuchTableException;
import org.dbunit.dataset.datatype.IDataTypeFactory;
import org.dbunit.dataset.filter.IColumnFilter;
import org.dbunit.util.QualifiedTableName;
import org.dbunit.util.SQLHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Container for the metadata for one database table. The metadata is initialized
 * using a {@link IDatabaseConnection}.
 * 
 * @author Manuel Laflamme
 * @author Last changed by: $Author$
 * @version $Revision$ $Date$
 * @since Mar 8, 2002
 * @see ITableMetaData
 */
public class DatabaseTableMetaData extends AbstractTableMetaData
{

    /**
     * Logger for this class
     */
    private static final Logger logger = LoggerFactory.getLogger(DatabaseTableMetaData.class);

    /**
     * Table name, potentially qualified
     */
    private final QualifiedTableName _qualifiedTableNameSupport;
    private final String _originalTableName;
    private final IDatabaseConnection _connection;
    private Column[] _columns;
    private Column[] _primaryKeys;
    private boolean _caseSensitiveMetaData;
	//added by hzhan032
    private IColumnFilter lastKeyFilter;

    
    DatabaseTableMetaData(String tableName, IDatabaseConnection connection) throws DataSetException
    {
    	this(tableName, connection, true);
    }
    
    /**
     * Creates a new database table metadata
     * @param tableName The name of the table - can be fully qualified
     * @param connection The database connection
     * @param validate Whether or not to validate the given input data. It is not recommended to
     * set the validation to false because it is then possible to create an instance
     * of this object for a db table that does not exist.
     * @throws DataSetException
     */
    DatabaseTableMetaData(String tableName, IDatabaseConnection connection, boolean validate) throws DataSetException
    {
        this(tableName, connection, validate, false);
    }
    
    /**
     * Creates a new database table metadata
     * @param tableName The name of the table - can be fully qualified
     * @param connection The database connection
     * @param validate Whether or not to validate the given input data. It is not recommended to
     * set the validation to false because it is then possible to create an instance
     * of this object for a db table that does not exist.
     * @param caseSensitiveMetaData Whether or not the metadata looked up in a case sensitive way
     * @throws DataSetException
     * @since 2.4.1
     */
    DatabaseTableMetaData(final String tableName, IDatabaseConnection connection, boolean validate, boolean caseSensitiveMetaData) throws DataSetException
    {
    	if (tableName == null) {
			throw new NullPointerException("The parameter 'tableName' must not be null");
		}
    	if (connection == null) {
			throw new NullPointerException("The parameter 'connection' must not be null");
		}
    	
        _connection = connection;
        _caseSensitiveMetaData = caseSensitiveMetaData;

        try
        {
             Connection jdbcConnection = connection.getConnection();
             if(!caseSensitiveMetaData)
             {
                 _originalTableName = SQLHelper.correctCase(tableName, jdbcConnection);
                 SQLHelper.logDebugIfValueChanged(tableName, _originalTableName, "Corrected table name:", DatabaseTableMetaData.class);
             }
             else
             {
                 _originalTableName = tableName;
             }
             
             // qualified names support - table name and schema is stored here
             _qualifiedTableNameSupport = new QualifiedTableName(_originalTableName, _connection.getSchema());

             if(validate) 
             {
                 String schemaName = _qualifiedTableNameSupport.getSchema();
                 String plainTableName = _qualifiedTableNameSupport.getTable();
                 logger.debug("Validating if table '{}' exists in schema '{}' ...", plainTableName, schemaName);
                 try {
                     DatabaseConfig config = connection.getConfig();
                     IMetadataHandler metadataHandler = (IMetadataHandler) config.getProperty(DatabaseConfig.PROPERTY_METADATA_HANDLER);
                     DatabaseMetaData databaseMetaData = jdbcConnection.getMetaData();
                     if(!metadataHandler.tableExists(databaseMetaData, schemaName, plainTableName))
                     {
                         throw new NoSuchTableException("Did not find table '" + plainTableName + "' in schema '" + schemaName + "'");
                     }
                 }
                 catch (SQLException e)
                 {
                     throw new DataSetException("Exception while validation existence of table '" + plainTableName + "'", e);
                 }
             }
             else
             {
                 logger.debug("Validation switched off. Will not check if table exists.");
             }
        }
        catch (SQLException e)
        {
            throw new DataSetException("Exception while retrieving JDBC connection from dbunit connection '" + connection + "'", e);
        }
        
    }

    /**
     * @param tableName
     * @param resultSet
     * @param dataTypeFactory
     * @return The table metadata created for the given parameters
     * @throws DataSetException
     * @throws SQLException
     * @deprecated since 2.3.0. use {@link ResultSetTableMetaData#ResultSetTableMetaData(String, ResultSet, IDataTypeFactory, boolean)}
     */
    public static ITableMetaData createMetaData(String tableName,
            ResultSet resultSet, IDataTypeFactory dataTypeFactory)
            throws DataSetException, SQLException
    {
    	if (logger.isDebugEnabled())
    	{
    		logger.debug("createMetaData(tableName={}, resultSet={}, dataTypeFactory={}) - start",
    				new Object[]{ tableName, resultSet, dataTypeFactory });
    	}

    	return new ResultSetTableMetaData(tableName, resultSet, dataTypeFactory, false);
    }


    
    /**
     * @param tableName
     * @param resultSet
     * @param connection
     * @return The table metadata created for the given parameters
     * @throws SQLException
     * @throws DataSetException
     * @deprecated since 2.3.0. use {@link org.dbunit.database.ResultSetTableMetaData#ResultSetTableMetaData(String, ResultSet, IDatabaseConnection, boolean)}
     */
    public static ITableMetaData createMetaData(String tableName,
            ResultSet resultSet, IDatabaseConnection connection)
            throws SQLException, DataSetException
    {
    	if (logger.isDebugEnabled())
    	{
    		logger.debug("createMetaData(tableName={}, resultSet={}, connection={}) - start",
    				new Object[] { tableName, resultSet, connection });
    	}
    	return new ResultSetTableMetaData(tableName,resultSet,connection, false);
    }

    private String[] getPrimaryKeyNames() throws SQLException
    {
        logger.debug("getPrimaryKeyNames() - start");

    	String schemaName = _qualifiedTableNameSupport.getSchema();
    	String tableName = _qualifiedTableNameSupport.getTable();

        Connection connection = _connection.getConnection();
        DatabaseMetaData databaseMetaData = connection.getMetaData();
        
        DatabaseConfig config = _connection.getConfig();
        IMetadataHandler metadataHandler = (IMetadataHandler) config.getProperty(DatabaseConfig.PROPERTY_METADATA_HANDLER);
        
        ResultSet resultSet = metadataHandler.getPrimaryKeys(databaseMetaData, schemaName, tableName);

        List list = new ArrayList();
        try
        {
            while (resultSet.next())
            {
                String name = resultSet.getString(4);
                int sequence = resultSet.getInt(5);
                list.add(new PrimaryKeyData(name, sequence));
            }
        }
        finally
        {
            resultSet.close();
        }

        Collections.sort(list);
        String[] keys = new String[list.size()];
        for (int i = 0; i < keys.length; i++)
        {
            PrimaryKeyData data = (PrimaryKeyData)list.get(i);
            keys[i] = data.getName();
        }

        return keys;
    }

    private class PrimaryKeyData implements Comparable
    {
        private final String _name;
        private final int _index;

        public PrimaryKeyData(String name, int index)
        {
            _name = name;
            _index = index;
        }

        public String getName()
        {
            logger.debug("getName() - start");

            return _name;
        }

        public int getIndex()
        {
            return _index;
        }

        ////////////////////////////////////////////////////////////////////////
        // Comparable interface

        public int compareTo(Object o)
        {
            PrimaryKeyData data = (PrimaryKeyData)o;
            return getIndex() - data.getIndex();
        }
    }

    ////////////////////////////////////////////////////////////////////////////
    // ITableMetaData interface

    public String getTableName()
    {
        // Ensure that the same table name is returned as specified in the input.
        // This is necessary to support fully qualified XML dataset imports.
        //""
        //""
        //""
        //"";
        return this._originalTableName;
    }

    public Column[] getColumns() throws DataSetException
    {
        logger.debug("getColumns() - start");

        if (_columns == null)
        {
            try
            {
                // qualified names support
            	String schemaName = _qualifiedTableNameSupport.getSchema();
            	String tableName = _qualifiedTableNameSupport.getTable();
            	
                Connection jdbcConnection = _connection.getConnection();
                DatabaseMetaData databaseMetaData = jdbcConnection.getMetaData();
                
                DatabaseConfig config = _connection.getConfig();
                
                IMetadataHandler metadataHandler = (IMetadataHandler)config.getProperty(DatabaseConfig.PROPERTY_METADATA_HANDLER);
                ResultSet resultSet = metadataHandler.getColumns(databaseMetaData, schemaName, tableName);

                try
                {
                    IDataTypeFactory dataTypeFactory = super.getDataTypeFactory(_connection);
                    boolean datatypeWarning = config.getFeature(
                            DatabaseConfig.FEATURE_DATATYPE_WARNING);

                    List columnList = new ArrayList();
                    while (resultSet.next())
                    {
                        // Check for exact table/schema name match because
                        // databaseMetaData.getColumns() uses patterns for the lookup
                        boolean match = metadataHandler.matches(resultSet, schemaName, tableName, _caseSensitiveMetaData);
                        if(match)
                        {
                            Column column = SQLHelper.createColumn(resultSet, dataTypeFactory, datatypeWarning);
                            if(column != null)
                            {
                                columnList.add(column);
                            }
                        }
                        else
                        {
                            logger.debug("Skipping  '" + resultSet.getString(2) + "." + 
                                    resultSet.getString(3) + "' because names do not exactly match.");
                        }
                    }

                    if (columnList.size() == 0)
                    {
                    	logger.warn("No columns found for table '"+ tableName +"' that are supported by dbunit. " +
                    			"Will return an empty column list");
                    }

                    _columns = (Column[])columnList.toArray(new Column[0]);
                }
                finally
                {
                    resultSet.close();
                }
            }
            catch (SQLException e)
            {
                throw new DataSetException(e);
            }
        }
        return _columns;
    }

    private boolean primaryKeyFilterChanged(IColumnFilter keyFilter)
    {
        return (keyFilter != lastKeyFilter);
    }

    public Column[] getPrimaryKeys() throws DataSetException
    {
        logger.debug("getPrimaryKeys() - start");
                DatabaseConfig config = _connection.getConfig();
        IColumnFilter primaryKeysFilter = (IColumnFilter) config.getProperty(
                        DatabaseConfig.PROPERTY_PRIMARY_KEY_FILTER);

        if (_primaryKeys == null || primaryKeyFilterChanged(primaryKeysFilter)) {
            try {
                lastKeyFilter = primaryKeysFilter;
                if (primaryKeysFilter != null) {
                	_primaryKeys = Columns.getColumns(getTableName(), getColumns(),
                            primaryKeysFilter);
                } else {
                	String[] pkNames = getPrimaryKeyNames();
                    _primaryKeys = Columns.getColumns(pkNames, getColumns());
                }
            }
            catch (SQLException e)
            {
                throw new DataSetException(e);
            }
        }
        return _primaryKeys;
    }

    ////////////////////////////////////////////////////////////////////////////
    // Object class
    public String toString()
    {
        try
        {
            String tableName = getTableName();
            String columns = Arrays.asList(getColumns()).toString();
            String primaryKeys = Arrays.asList(getPrimaryKeys()).toString();
            return "table=" + tableName + ", cols=" + columns + ", pk=" + primaryKeys + "";
        }
        catch (DataSetException e)
        {
            return super.toString();
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy