liquibase-core/src/main/java/liquibase/snapshot/SnapshotGeneratorFactory.java
public boolean has(DatabaseObject example, Database database) throws DatabaseException, InvalidExampleException {
        // @todo I have seen duplicates in types - maybe convert the List into a Set? Need to understand it more thoroughly.
        List<Class<? extends DatabaseObject>> types = new ArrayList<>(getContainerTypes(example.getClass(), database));
        types.add(example.getClass());

        /*
         * Does the query concern the DATABASECHANGELOG / DATABASECHANGELOGLOCK table? If so, we do a quick & dirty
         * SELECT COUNT(*) on that table. If that works, we count that as confirmation of existence.
         */
        // @todo Actually, there may be extreme cases (distorted table statistics etc.) where a COUNT(*) might not be so cheap. Maybe SELECT a dummy constant is the better way?
        if ((example instanceof Table) && (example.getName().equals(database.getDatabaseChangeLogTableName()) ||
            example.getName().equals(database.getDatabaseChangeLogLockTableName()))) {
            try {
                ExecutorService.getInstance().getExecutor(database).queryForInt(
                        new RawSqlStatement("SELECT COUNT(*) FROM " +
                                database.escapeObjectName(database.getLiquibaseCatalogName(),
                                        database.getLiquibaseSchemaName(), example.getName(), Table.class)));
                return true;
            } catch (DatabaseException e) {
                if (database instanceof PostgresDatabase) { // throws "current transaction is aborted" unless we roll back the connection
                    database.rollback();
                }
                return false;
            }
        }

        /*
          * If the query is about another object, try to create a snapshot of the of the object (or used the cached
          * snapshot. If that works, we count that as confirmation of existence.
          */

        SnapshotControl snapshotControl = (new SnapshotControl(database, false, types.toArray(new Class[types.size()])));
        snapshotControl.setWarnIfObjectNotFound(false);

        if (createSnapshot(example, database,snapshotControl) != null) {
            return true;
        }
        CatalogAndSchema catalogAndSchema;
        if (example.getSchema() == null) {
            catalogAndSchema = database.getDefaultSchema();
        } else {
            catalogAndSchema = example.getSchema().toCatalogAndSchema();
        }
        DatabaseSnapshot snapshot = createSnapshot(catalogAndSchema, database,
            new SnapshotControl(database, false, example.getClass()).setWarnIfObjectNotFound(false)
        );

        for (DatabaseObject obj : snapshot.get(example.getClass())) {
            if (DatabaseObjectComparatorFactory.getInstance().isSameObject(example, obj, null, database)) {
                return true;
            }
        }
        return false;
    }
public boolean has(DatabaseObject example, Database database) throws DatabaseException, InvalidExampleException {
        // @todo I have seen duplicates in types - maybe convert the List into a Set? Need to understand it more thoroughly.
        List<Class<? extends DatabaseObject>> types = new ArrayList<>(getContainerTypes(example.getClass(), database));
        types.add(example.getClass());

        /*
         * Does the query concern the DATABASECHANGELOG / DATABASECHANGELOGLOCK table? If so, we do a quick & dirty
         * SELECT COUNT(*) on that table. If that works, we count that as confirmation of existence.
         */
        // @todo Actually, there may be extreme cases (distorted table statistics etc.) where a COUNT(*) might not be so cheap. Maybe SELECT a dummy constant is the better way?
        if ((example instanceof Table) && (example.getName().equals(database.getDatabaseChangeLogTableName()) ||
            example.getName().equals(database.getDatabaseChangeLogLockTableName()))) {
            try {
                ExecutorService.getInstance().getExecutor(database).queryForInt(
                        new RawSqlStatement("SELECT COUNT(*) FROM " +
                                database.escapeObjectName(database.getLiquibaseCatalogName(),
                                        database.getLiquibaseSchemaName(), example.getName(), Table.class)));
                return true;
            } catch (DatabaseException e) {
                if (database instanceof PostgresDatabase) { // throws "current transaction is aborted" unless we roll back the connection
                    database.rollback();
                }
                return false;
            }
        }

        /*
          * If the query is about another object, try to create a snapshot of the of the object (or used the cached
          * snapshot. If that works, we count that as confirmation of existence.
          */

        SnapshotControl snapshotControl = (new SnapshotControl(database, false, types.toArray(new Class[types.size()])));
        snapshotControl.setWarnIfObjectNotFound(false);

        if (createSnapshot(example, database,snapshotControl) != null) {
            return true;
        }
        CatalogAndSchema catalogAndSchema;
        if (example.getSchema() == null) {
            catalogAndSchema = database.getDefaultSchema();
        } else {
            catalogAndSchema = example.getSchema().toCatalogAndSchema();
        }
        DatabaseSnapshot snapshot = createSnapshot(catalogAndSchema, database,
            new SnapshotControl(database, false, example.getClass()).setWarnIfObjectNotFound(false)
        );

        for (DatabaseObject obj : snapshot.get(example.getClass())) {
            if (DatabaseObjectComparatorFactory.getInstance().isSameObject(example, obj, null, database)) {
                return true;
            }
        }
        return false;
    }
Checks if a specific object is present in a database
@param example The DatabaseObject to check for existence
@param database The DBMS in which the object might exist
@return true if object existence can be confirmed, false otherweise
@throws DatabaseException If a problem occurs in the DBMS-specific code
@throws InvalidExampleException If the object cannot be checked properly, e.g. if the object name is ambiguous