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

schemacrawler.crawl.SchemaCrawler Maven / Gradle / Ivy

Go to download

SchemaCrawler is an open-source Java API that makes working with database metadata as easy as working with plain old Java objects. SchemaCrawler is also a database schema discovery and comprehension, and schema documentation tool. You can search for database schema objects using regular expressions, and output the schema and data in a readable text format. The output is designed to be diff-ed against other database schemas.

There is a newer version: 16.24.2
Show newest version
/*
 *
 * SchemaCrawler
 * http://sourceforge.net/projects/schemacrawler
 * Copyright (c) 2000-2015, 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 static java.util.Objects.requireNonNull;

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.Catalog;
import schemacrawler.schema.Reducible;
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
{

  /**
   * 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 MutableCatalog catalog,
                                           final RetrieverConnection retrieverConnection,
                                           final SchemaCrawlerOptions options)
    throws SchemaCrawlerException
  {
    try
    {
      final SchemaInfoLevel infoLevel = options.getSchemaInfoLevel();
      final DatabaseInfoRetriever retriever = new DatabaseInfoRetriever(retrieverConnection,
                                                                        catalog);
      if (infoLevel.isRetrieveColumnDataTypes())
      {
        LOGGER.log(Level.INFO, "Retrieving system column data types");
        retriever.retrieveSystemColumnDataTypes();
      }
      else
      {
        LOGGER
          .log(Level.INFO,
               "Not retrieving system column data types, since this was not requested");
      }
      if (infoLevel.isRetrieveUserDefinedColumnDataTypes())
      {
        LOGGER.log(Level.INFO, "Retrieving user column data types");
        for (final Schema schema: retriever.getSchemas())
        {
          retriever.retrieveUserDefinedColumnDataTypes(schema.getCatalogName(),
                                                       schema.getName());
        }
      }
      else
      {
        LOGGER
          .log(Level.INFO,
               "Not retrieving user column data types, since this was not requested");
      }
    }
    catch (final SQLException e)
    {
      throw new SchemaCrawlerException("Exception retrieving column data type information",
                                       e);
    }
  }

  private static void crawlDatabaseInfo(final MutableCatalog catalog,
                                        final RetrieverConnection retrieverConnection,
                                        final SchemaCrawlerOptions options)
    throws SchemaCrawlerException
  {
    try
    {

      final SchemaInfoLevel infoLevel = options.getSchemaInfoLevel();
      final DatabaseInfoRetriever retriever = new DatabaseInfoRetriever(retrieverConnection,
                                                                        catalog);

      if (infoLevel.isRetrieveSchemaCrawlerInfo())
      {
        LOGGER.log(Level.INFO, "Retrieving SchemaCrawler information");
        retriever.retrieveSchemaCrawlerInfo();
        if (infoLevel.isRetrieveAdditionalSchemaCrawlerInfo())
        {
          retriever.retrieveAdditionalSchemaCrawlerInfo();
        }
      }
      else
      {
        LOGGER
          .log(Level.INFO,
               "Not retrieving SchemaCrawler information, since this was not requested");
      }
      if (infoLevel.isRetrieveDatabaseInfo())
      {
        LOGGER.log(Level.INFO, "Retrieving database information");
        retriever.retrieveDatabaseInfo();
        if (infoLevel.isRetrieveAdditionalDatabaseInfo())
        {
          retriever.retrieveAdditionalDatabaseInfo();
        }
      }
      else
      {
        LOGGER
          .log(Level.INFO,
               "Not retrieving database information, since this was not requested");
      }
      if (infoLevel.isRetrieveJdbcDriverInfo())
      {
        LOGGER.log(Level.INFO, "Retrieving JDBC driver information");
        retriever.retrieveJdbcDriverInfo();
        if (infoLevel.isRetrieveAdditionalJdbcDriverInfo())
        {
          retriever.retrieveAdditionalJdbcDriverInfo();
        }
      }
      else
      {
        LOGGER
          .log(Level.INFO,
               "Not retrieving JDBC driver information, since this was not requested");
      }
    }
    catch (final SQLException e)
    {
      throw new SchemaCrawlerException("Exception retrieving database information",
                                       e);
    }
  }

  private static void crawlRoutines(final MutableCatalog catalog,
                                    final RetrieverConnection retrieverConnection,
                                    final SchemaCrawlerOptions options)
    throws SchemaCrawlerException
  {
    final SchemaInfoLevel infoLevel = options.getSchemaInfoLevel();
    final boolean retrieveRoutines = infoLevel.isRetrieveRoutines();
    if (!retrieveRoutines)
    {
      LOGGER.log(Level.INFO,
                 "Not retrieving routines, since this was not requested");
      return;
    }

    LOGGER.log(Level.INFO, "Retrieving routines");

    final RoutineRetriever retriever;
    final RoutineExtRetriever retrieverExtra;
    try
    {
      retriever = new RoutineRetriever(retrieverConnection, catalog);
      retrieverExtra = new RoutineExtRetriever(retrieverConnection, catalog);
      final Collection 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 allRoutines = catalog
        .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
      ((Reducible) catalog).reduce(options);

      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 MutableCatalog catalog,
                                   final RetrieverConnection retrieverConnection,
                                   final SchemaCrawlerOptions options)
    throws SchemaCrawlerException
  {

    LOGGER.log(Level.INFO, "Retrieving schemas");

    try
    {
      final SchemaRetriever retriever = new SchemaRetriever(retrieverConnection,
                                                            catalog);

      retriever.retrieveSchemas(options.getSchemaInclusionRule());
    }
    catch (final SQLException e)
    {
      throw new SchemaCrawlerException("Exception retrieving database information",
                                       e);
    }
  }

  private static void crawlSequences(final MutableCatalog catalog,
                                     final RetrieverConnection retrieverConnection,
                                     final SchemaCrawlerOptions options)
    throws SchemaCrawlerException
  {
    final SchemaInfoLevel infoLevel = options.getSchemaInfoLevel();
    final boolean retrieveSequences = infoLevel.isRetrieveSequenceInformation();
    if (!retrieveSequences)
    {
      LOGGER.log(Level.INFO,
                 "Not retrieving sequences, since this was not requested");
      return;
    }

    LOGGER.log(Level.INFO, "Retrieving sequences");

    final SequenceRetriever retrieverExtra;
    try
    {
      retrieverExtra = new SequenceRetriever(retrieverConnection, catalog);
      retrieverExtra.retrieveSequenceInformation(options
        .getSequenceInclusionRule());
    }
    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 crawlSynonyms(final MutableCatalog catalog,
                                    final RetrieverConnection retrieverConnection,
                                    final SchemaCrawlerOptions options)
    throws SchemaCrawlerException
  {
    final SchemaInfoLevel infoLevel = options.getSchemaInfoLevel();
    final boolean retrieveSynonyms = infoLevel.isRetrieveSynonymInformation();
    if (!retrieveSynonyms)
    {
      LOGGER.log(Level.INFO,
                 "Not retrieving synonyms, since this was not requested");
      return;
    }

    LOGGER.log(Level.INFO, "Retrieving synonyms");

    final SynonymRetriever retrieverExtra;
    try
    {
      retrieverExtra = new SynonymRetriever(retrieverConnection, catalog);
      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 MutableCatalog catalog,
                                  final RetrieverConnection retrieverConnection,
                                  final SchemaCrawlerOptions options)
    throws SchemaCrawlerException
  {
    final SchemaInfoLevel infoLevel = options.getSchemaInfoLevel();
    final boolean retrieveTables = infoLevel.isRetrieveTables();
    if (!retrieveTables)
    {
      LOGGER.log(Level.INFO,
                 "Not retrieving tables, since this was not requested");
      return;
    }

    LOGGER.log(Level.INFO, "Retrieving tables");

    final TableRetriever retriever;
    final TableExtRetriever retrieverExtra;
    try
    {
      retriever = new TableRetriever(retrieverConnection, catalog);
      retrieverExtra = new TableExtRetriever(retrieverConnection, catalog);

      for (final Schema schema: retriever.getSchemas())
      {
        retriever.retrieveTables(schema.getCatalogName(),
                                 schema.getName(),
                                 options.getTableNamePattern(),
                                 options.getTableTypes(),
                                 options.getTableInclusionRule());
      }

      final NamedObjectList allTables = catalog.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
      ((Reducible) catalog).reduce(options);

      if (infoLevel.isRetrieveTableConstraintInformation())
      {
        retrieverExtra.retrieveTableConstraintInformation();
      }
      if (infoLevel.isRetrieveTriggerInformation())
      {
        retrieverExtra.retrieveTriggerInformation();
      }
      if (infoLevel.isRetrieveViewInformation())
      {
        retrieverExtra.retrieveViewInformation();
      }
      if (infoLevel.isRetrieveTableDefinitionsInformation())
      {
        retrieverExtra.retrieveTableDefinitions();
      }
      if (infoLevel.isRetrieveIndexInformation())
      {
        retrieverExtra.retrieveIndexInformation();
      }
      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 static final Logger LOGGER = Logger.getLogger(SchemaCrawler.class
    .getName());

  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
  {
    this.connection = requireNonNull(connection, "No connection specified");
  }

  /**
   * 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 Catalog crawl(final SchemaCrawlerOptions options)
    throws SchemaCrawlerException
  {
    final MutableCatalog catalog = new MutableCatalog("catalog");

    RetrieverConnection retrieverConnection = null;
    try
    {
      SchemaCrawlerOptions schemaCrawlerOptions = options;
      if (schemaCrawlerOptions == null)
      {
        schemaCrawlerOptions = new SchemaCrawlerOptions();
      }
      retrieverConnection = new RetrieverConnection(connection,
                                                    schemaCrawlerOptions);

      crawlSchemas(catalog, retrieverConnection, schemaCrawlerOptions);
      crawlDatabaseInfo(catalog, retrieverConnection, schemaCrawlerOptions);
      crawlColumnDataTypes(catalog, retrieverConnection, schemaCrawlerOptions);
      crawlTables(catalog, retrieverConnection, schemaCrawlerOptions);
      crawlRoutines(catalog, retrieverConnection, schemaCrawlerOptions);
      crawlSynonyms(catalog, retrieverConnection, schemaCrawlerOptions);
      crawlSequences(catalog, retrieverConnection, schemaCrawlerOptions);

      return catalog;
    }
    catch (final SQLException e)
    {
      throw new SchemaCrawlerException("Database access exception", e);
    }
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy