@Test
  public void tableEquals() {

    final SchemaCrawlerOptions schemaCrawlerOptions = new SchemaCrawlerOptions();
    schemaCrawlerOptions.setShowStoredProcedures(true);

    final Catalog catalog = testUtility.getCatalog(schemaCrawlerOptions);
    assertNotNull("Could not obtain catalog", catalog);
    assertTrue("Could not find any schemas", catalog.getSchemas().length > 0);

    final Schema schema = catalog.getSchema("PUBLIC");
    assertNotNull("Could not obtain schema", schema);
    assertTrue("Could not find any tables", schema.getTables().length > 0);
    assertTrue("Could not find any procedures", schema.getProcedures().length > 0);

    // Try negative test
    final Table table0 = schema.getTables()[0];
    assertTrue("Could not find any columns", table0.getColumns().length > 0);

    final MutableTable table1 =
        new MutableTable(table0.getCatalogName(), table0.getSchemaName(), "Test Table 1");
    final MutableTable table2 =
        new MutableTable(table0.getCatalogName(), table0.getSchemaName(), "Test Table 2");
    final PrimaryKey primaryKey = table0.getPrimaryKey();
    table1.setPrimaryKey(primaryKey);
    table2.setPrimaryKey(primaryKey);
    for (final Column column : table0.getColumns()) {
      table1.addColumn((MutableColumn) column);
      table2.addColumn((MutableColumn) column);
    }
    for (final Index index : table0.getIndices()) {
      table1.addIndex((MutableIndex) index);
      table2.addIndex((MutableIndex) index);
    }
    for (final ForeignKey fk : table0.getForeignKeys()) {
      table1.addForeignKey((MutableForeignKey) fk);
      table2.addForeignKey((MutableForeignKey) fk);
    }
    for (final Trigger trigger : table0.getTriggers()) {
      table1.addTrigger((MutableTrigger) trigger);
      table2.addTrigger((MutableTrigger) trigger);
    }
    for (final Privilege privilege : table0.getPrivileges()) {
      table1.addPrivilege((MutablePrivilege) privilege);
      table2.addPrivilege((MutablePrivilege) privilege);
    }
    for (final CheckConstraint checkConstraint : table0.getCheckConstraints()) {
      table1.addCheckConstraint((MutableCheckConstraint) checkConstraint);
      table2.addCheckConstraint((MutableCheckConstraint) checkConstraint);
    }

    assertFalse("Tables should not be equal", table1.equals(table2));
  }
  /**
   * Retrieves a check constraint information from the database, in the INFORMATION_SCHEMA format.
   *
   * @throws SQLException On a SQL exception
   */
  void retrieveCheckConstraintInformation() throws SQLException {
    final Map<String, MutableCheckConstraint> checkConstraintsMap = new HashMap<>();

    final InformationSchemaViews informationSchemaViews =
        getRetrieverConnection().getInformationSchemaViews();

    if (!informationSchemaViews.hasTableConstraintsSql()) {
      LOGGER.log(Level.FINE, "Table constraints SQL statement was not provided");
      return;
    }
    final String tableConstraintsInformationSql = informationSchemaViews.getTableConstraintsSql();

    final Connection connection = getDatabaseConnection();
    try (final Statement statement = connection.createStatement();
        final MetadataResultSet results =
            new MetadataResultSet(statement.executeQuery(tableConstraintsInformationSql)); ) {

      while (results.next()) {
        final String catalogName = quotedName(results.getString("CONSTRAINT_CATALOG"));
        final String schemaName = quotedName(results.getString("CONSTRAINT_SCHEMA"));
        final String constraintName = quotedName(results.getString("CONSTRAINT_NAME"));
        LOGGER.log(Level.FINER, "Retrieving constraint: " + constraintName);
        // "TABLE_CATALOG", "TABLE_SCHEMA"
        final String tableName = quotedName(results.getString("TABLE_NAME"));

        final MutableTable table = lookupTable(catalogName, schemaName, tableName);
        if (table == null) {
          LOGGER.log(
              Level.FINE,
              String.format("Cannot find table, %s.%s.%s", catalogName, schemaName, tableName));
          continue;
        }

        final String constraintType = results.getString("CONSTRAINT_TYPE");
        final boolean deferrable = results.getBoolean("IS_DEFERRABLE");
        final boolean initiallyDeferred = results.getBoolean("INITIALLY_DEFERRED");

        if (constraintType.equalsIgnoreCase("check")) {
          final MutableCheckConstraint checkConstraint =
              new MutableCheckConstraint(table, constraintName);
          checkConstraint.setDeferrable(deferrable);
          checkConstraint.setInitiallyDeferred(initiallyDeferred);

          checkConstraint.addAttributes(results.getAttributes());

          // Add to map, since we will need this later
          final String constraintFullName = table.getSchema().getFullName() + "." + constraintName;
          checkConstraintsMap.put(constraintFullName, checkConstraint);
        }
      }
    } catch (final Exception e) {
      LOGGER.log(Level.WARNING, "Could not retrieve check constraint information", e);
      return;
    }

    if (!informationSchemaViews.hasCheckConstraintsSql()) {
      LOGGER.log(Level.FINE, "Check constraints SQL statement was not provided");
      return;
    }
    final String checkConstraintInformationSql = informationSchemaViews.getCheckConstraintsSql();

    // Get check constraint definitions
    try (final Statement statement = connection.createStatement();
        final MetadataResultSet results =
            new MetadataResultSet(statement.executeQuery(checkConstraintInformationSql)); ) {
      while (results.next()) {
        final String catalogName = quotedName(results.getString("CONSTRAINT_CATALOG"));
        final String schemaName = quotedName(results.getString("CONSTRAINT_SCHEMA"));
        final String constraintName = quotedName(results.getString("CONSTRAINT_NAME"));
        LOGGER.log(Level.FINER, "Retrieving constraint definition: " + constraintName);
        String definition = results.getString("CHECK_CLAUSE");

        final String constraintFullName =
            new SchemaReference(catalogName, schemaName) + "." + constraintName;
        final MutableCheckConstraint checkConstraint = checkConstraintsMap.get(constraintFullName);
        if (checkConstraint == null) {
          LOGGER.log(Level.FINEST, "Could not add check constraint to table: " + constraintName);
          continue;
        }
        final String text = checkConstraint.getDefinition();
        if (!Utility.isBlank(text)) {
          definition = checkConstraint.getDefinition() + definition;
        }

        checkConstraint.setDefinition(definition);
      }
    } catch (final Exception e) {
      LOGGER.log(Level.WARNING, "Could not retrieve check constraints", e);
    }

    // Add check constraints to tables
    final Collection<MutableCheckConstraint> checkConstraintsCollection =
        checkConstraintsMap.values();
    for (final MutableCheckConstraint checkConstraint : checkConstraintsCollection) {
      final MutableTable table = (MutableTable) checkConstraint.getParent();
      table.addCheckConstraint(checkConstraint);
    }
  }