/*
*
* SchemaCrawler
* http://sourceforge.net/projects/schemacrawler
* Copyright (c) 2000-2013, Sualeh Fatehi.
*
* 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 schemacrawler.crawl;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
import java.util.logging.Level;
import java.util.logging.Logger;
import schemacrawler.schema.Database;
import schemacrawler.schema.ResultsColumns;
import schemacrawler.schema.RoutineType;
import schemacrawler.schema.Schema;
import schemacrawler.schemacrawler.SchemaCrawlerException;
import schemacrawler.schemacrawler.SchemaCrawlerOptions;
import schemacrawler.schemacrawler.SchemaCrawlerSQLException;
import schemacrawler.schemacrawler.SchemaInfoLevel;
/**
* SchemaCrawler uses database meta-data to get the details about the
* schema.
*
* @author Sualeh Fatehi
*/
public final class SchemaCrawler
{
private static final Logger LOGGER = Logger.getLogger(SchemaCrawler.class
.getName());
/**
* Gets the result set columns metadata.
*
* @param resultSet
* Result set
* @return Schema
*/
public static ResultsColumns getResultColumns(final ResultSet resultSet)
{
ResultsColumns resultColumns = null;
try
{
final ResultsRetriever resultsRetriever = new ResultsRetriever(resultSet);
resultColumns = resultsRetriever.retrieveResults();
}
catch (final SQLException e)
{
LOGGER.log(Level.WARNING, e.getMessage(), e);
resultColumns = null;
}
return resultColumns;
}
private static void crawlColumnDataTypes(final MutableDatabase database,
final RetrieverConnection retrieverConnection,
final SchemaCrawlerOptions options)
throws SchemaCrawlerException
{
try
{
final SchemaInfoLevel infoLevel = options.getSchemaInfoLevel();
final DatabaseInfoRetriever retriever = new DatabaseInfoRetriever(retrieverConnection,
database);
if (infoLevel.isRetrieveColumnDataTypes())
{
retriever.retrieveSystemColumnDataTypes();
}
if (infoLevel.isRetrieveUserDefinedColumnDataTypes())
{
for (final Schema schema: retriever.getSchemas())
{
retriever.retrieveUserDefinedColumnDataTypes(schema.getCatalogName(),
schema.getName());
}
}
}
catch (final SQLException e)
{
throw new SchemaCrawlerException("Exception retrieving column data type information",
e);
}
}
private static void crawlDatabaseInfo(final MutableDatabase database,
final RetrieverConnection retrieverConnection,
final SchemaCrawlerOptions options)
throws SchemaCrawlerException
{
try
{
final SchemaInfoLevel infoLevel = options.getSchemaInfoLevel();
final DatabaseInfoRetriever retriever = new DatabaseInfoRetriever(retrieverConnection,
database);
if (infoLevel.isRetrieveSchemaCrawlerInfo())
{
retriever.retrieveSchemaCrawlerInfo();
if (infoLevel.isRetrieveAdditionalSchemaCrawlerInfo())
{
retriever.retrieveAdditionalSchemaCrawlerInfo();
}
}
if (infoLevel.isRetrieveDatabaseInfo())
{
retriever.retrieveDatabaseInfo();
if (infoLevel.isRetrieveAdditionalDatabaseInfo())
{
retriever.retrieveAdditionalDatabaseInfo();
}
}
if (infoLevel.isRetrieveJdbcDriverInfo())
{
retriever.retrieveJdbcDriverInfo();
if (infoLevel.isRetrieveAdditionalJdbcDriverInfo())
{
retriever.retrieveAdditionalJdbcDriverInfo();
}
}
}
catch (final SQLException e)
{
throw new SchemaCrawlerException("Exception retrieving database information",
e);
}
}
private static void crawlRoutines(final MutableDatabase database,
final RetrieverConnection retrieverConnection,
final SchemaCrawlerOptions options)
throws SchemaCrawlerException
{
final SchemaInfoLevel infoLevel = options.getSchemaInfoLevel();
final boolean retrieveRoutines = infoLevel.isRetrieveRoutines();
if (!retrieveRoutines)
{
return;
}
final RoutineRetriever retriever;
final RoutineExRetriever retrieverExtra;
try
{
retriever = new RoutineRetriever(retrieverConnection, database);
retrieverExtra = new RoutineExRetriever(retrieverConnection, database);
final Collection<RoutineType> routineTypes = options.getRoutineTypes();
for (final Schema schema: retriever.getSchemas())
{
if (routineTypes.contains(RoutineType.procedure))
{
retriever.retrieveProcedures(schema.getCatalogName(),
schema.getName(),
options.getRoutineInclusionRule());
}
if (routineTypes.contains(RoutineType.function))
{
retriever.retrieveFunctions(schema.getCatalogName(),
schema.getName(),
options.getRoutineInclusionRule());
}
}
final NamedObjectList<MutableRoutine> allRoutines = database
.getAllRoutines();
for (final MutableRoutine routine: allRoutines)
{
if (infoLevel.isRetrieveRoutineColumns())
{
if (routine instanceof MutableProcedure
&& routineTypes.contains(RoutineType.procedure))
{
retriever
.retrieveProcedureColumns((MutableProcedure) routine,
options.getRoutineColumnInclusionRule());
}
if (routine instanceof MutableFunction
&& routineTypes.contains(RoutineType.function))
{
retriever
.retrieveFunctionColumns((MutableFunction) routine,
options.getRoutineColumnInclusionRule());
}
}
}
// Filter the list of routines based on grep criteria, and
// parent-child relationships
final RoutineFilter routineFiter = new RoutineFilter(options, allRoutines);
routineFiter.filter();
if (infoLevel.isRetrieveRoutineInformation())
{
retrieverExtra.retrieveRoutineInformation();
}
}
catch (final SQLException e)
{
if (e instanceof SchemaCrawlerSQLException)
{
final Throwable cause = e.getCause();
throw new SchemaCrawlerException(e.getMessage() + ": "
+ cause.getMessage(), cause);
}
else
{
throw new SchemaCrawlerException("Exception retrieving routines", e);
}
}
}
private static void crawlSchemas(final MutableDatabase database,
final RetrieverConnection retrieverConnection,
final SchemaCrawlerOptions options)
throws SchemaCrawlerException
{
try
{
final SchemaRetriever retriever = new SchemaRetriever(retrieverConnection,
database);
retriever.retrieveSchemas(options.getSchemaInclusionRule());
}
catch (final SQLException e)
{
throw new SchemaCrawlerException("Exception retrieving database information",
e);
}
}
private static void crawlSynonyms(final MutableDatabase database,
final RetrieverConnection retrieverConnection,
final SchemaCrawlerOptions options)
throws SchemaCrawlerException
{
final SchemaInfoLevel infoLevel = options.getSchemaInfoLevel();
final boolean retrieveSynonyms = infoLevel.isRetrieveSynonymInformation();
if (!retrieveSynonyms)
{
return;
}
final SynonymRetriever retrieverExtra;
try
{
retrieverExtra = new SynonymRetriever(retrieverConnection, database);
retrieverExtra.retrieveSynonymInformation(options
.getSynonymInclusionRule());
}
catch (final SQLException e)
{
if (e instanceof SchemaCrawlerSQLException)
{
final Throwable cause = e.getCause();
throw new SchemaCrawlerException(e.getMessage() + ": "
+ cause.getMessage(), cause);
}
else
{
throw new SchemaCrawlerException("Exception retrieving schemas", e);
}
}
}
private static void crawlTables(final MutableDatabase database,
final RetrieverConnection retrieverConnection,
final SchemaCrawlerOptions options)
throws SchemaCrawlerException
{
final SchemaInfoLevel infoLevel = options.getSchemaInfoLevel();
final boolean retrieveTables = infoLevel.isRetrieveTables();
if (!retrieveTables)
{
return;
}
final TableRetriever retriever;
final TableExRetriever retrieverExtra;
try
{
retriever = new TableRetriever(retrieverConnection, database);
retrieverExtra = new TableExRetriever(retrieverConnection, database);
for (final Schema schema: retriever.getSchemas())
{
retriever.retrieveTables(schema.getCatalogName(),
schema.getName(),
options.getTableNamePattern(),
options.getTableTypes(),
options.getTableInclusionRule());
}
final NamedObjectList<MutableTable> allTables = database.getAllTables();
for (final MutableTable table: allTables)
{
if (infoLevel.isRetrieveTableColumns())
{
retriever.retrieveColumns(table, options.getColumnInclusionRule());
}
}
if (!infoLevel.isRetrieveForeignKeys())
{
LOGGER
.log(Level.WARNING,
"Foreign-keys are not being retrieved, so tables cannot be sorted using the natural sort order");
}
for (final MutableTable table: allTables)
{
final boolean isView = table instanceof MutableView;
if (!isView && infoLevel.isRetrieveTableColumns())
{
retriever.retrievePrimaryKey(table);
if (infoLevel.isRetrieveIndices())
{
retriever.retrieveIndices(table, true);
retriever.retrieveIndices(table, false);
//
table.replacePrimaryKey();
}
if (infoLevel.isRetrieveForeignKeys())
{
retriever.retrieveForeignKeys(table);
}
}
}
final TablesGraph tablesGraph = new TablesGraph(allTables);
tablesGraph.setTablesSortIndices();
// Filter the list of tables based on grep criteria, and
// parent-child relationships
final TableFilter tableFiter = new TableFilter(options, allTables);
tableFiter.filter();
if (infoLevel.isRetrieveCheckConstraintInformation())
{
retrieverExtra.retrieveCheckConstraintInformation();
}
if (infoLevel.isRetrieveTriggerInformation())
{
retrieverExtra.retrieveTriggerInformation();
}
if (infoLevel.isRetrieveViewInformation())
{
retrieverExtra.retrieveViewInformation();
}
if (infoLevel.isRetrieveAdditionalTableAttributes())
{
retrieverExtra.retrieveAdditionalTableAttributes();
}
if (infoLevel.isRetrieveTablePrivileges())
{
retrieverExtra.retrieveTablePrivileges();
}
if (infoLevel.isRetrieveAdditionalColumnAttributes())
{
retrieverExtra.retrieveAdditionalColumnAttributes();
}
if (infoLevel.isRetrieveTableColumnPrivileges())
{
retrieverExtra.retrieveTableColumnPrivileges();
}
}
catch (final SQLException e)
{
if (e instanceof SchemaCrawlerSQLException)
{
final Throwable cause = e.getCause();
throw new SchemaCrawlerException(e.getMessage() + ": "
+ cause.getMessage(), cause);
}
else
{
throw new SchemaCrawlerException("Exception retrieving tables", e);
}
}
}
private final Connection connection;
/**
* Constructs a SchemaCrawler object, from a connection.
*
* @param connection
* An database connection.
* @throws SchemaCrawlerException
* On a crawler exception
*/
public SchemaCrawler(final Connection connection)
throws SchemaCrawlerException
{
if (connection == null)
{
throw new SchemaCrawlerException("No connection specified");
}
this.connection = connection;
}
/**
* Crawls the database, to obtain database metadata.
*
* @param options
* SchemaCrawler options that control what metadata is returned
* @return Database metadata
* @throws SchemaCrawlerException
* On an exception
*/
public Database crawl(final SchemaCrawlerOptions options)
throws SchemaCrawlerException
{
final MutableDatabase database = new MutableDatabase("database");
RetrieverConnection retrieverConnection = null;
try
{
SchemaCrawlerOptions schemaCrawlerOptions = options;
if (schemaCrawlerOptions == null)
{
schemaCrawlerOptions = new SchemaCrawlerOptions();
}
retrieverConnection = new RetrieverConnection(connection,
schemaCrawlerOptions);
crawlSchemas(database, retrieverConnection, schemaCrawlerOptions);
crawlDatabaseInfo(database, retrieverConnection, schemaCrawlerOptions);
crawlColumnDataTypes(database, retrieverConnection, schemaCrawlerOptions);
crawlTables(database, retrieverConnection, schemaCrawlerOptions);
crawlRoutines(database, retrieverConnection, schemaCrawlerOptions);
crawlSynonyms(database, retrieverConnection, schemaCrawlerOptions);
return database;
}
catch (final SQLException e)
{
throw new SchemaCrawlerException("Database access exception", e);
}
}
}