package liquibase.ext.spatial.preconditions; import java.util.LinkedHashSet; import java.util.Set; import liquibase.changelog.ChangeSet; import liquibase.changelog.DatabaseChangeLog; import liquibase.database.Database; import liquibase.database.core.DerbyDatabase; import liquibase.database.core.H2Database; import liquibase.database.core.MySQLDatabase; import liquibase.database.core.OracleDatabase; import liquibase.database.core.PostgresDatabase; import liquibase.exception.DatabaseException; import liquibase.exception.LiquibaseException; import liquibase.exception.PreconditionErrorException; import liquibase.exception.PreconditionFailedException; import liquibase.exception.UnexpectedLiquibaseException; import liquibase.exception.ValidationErrors; import liquibase.exception.Warnings; import liquibase.executor.ExecutorService; import liquibase.ext.spatial.xml.XmlConstants; import liquibase.parser.core.ParsedNode; import liquibase.parser.core.ParsedNodeException; import liquibase.precondition.AbstractPrecondition; import liquibase.precondition.ErrorPrecondition; import liquibase.precondition.core.TableExistsPrecondition; import liquibase.precondition.core.ViewExistsPrecondition; import liquibase.resource.ResourceAccessor; import liquibase.statement.core.RawSqlStatement; /** * <code>SpatialSupportedPrecondition</code> checks the state of the database and determines if it * has spatial support. * * @author Lonny Jacobson */ public class SpatialSupportedPrecondition extends AbstractPrecondition { @Override public String getName() { return "spatialSupported"; } @Override public Warnings warn(final Database database) { final Warnings warnings = new Warnings(); if (!(database instanceof DerbyDatabase || database instanceof H2Database || database instanceof MySQLDatabase || database instanceof OracleDatabase || database instanceof PostgresDatabase)) { warnings.addWarning(database.getDatabaseProductName() + " is not supported by this extension"); } return warnings; } @Override public ValidationErrors validate(final Database database) { final ValidationErrors errors = new ValidationErrors(); if (!(database instanceof DerbyDatabase || database instanceof H2Database || database instanceof MySQLDatabase || database instanceof OracleDatabase || database instanceof PostgresDatabase)) { errors.addError(database.getDatabaseProductName() + " is not supported by this extension"); } return errors; } @Override public void check(final Database database, final DatabaseChangeLog changeLog, final ChangeSet changeSet) throws PreconditionFailedException, PreconditionErrorException { if (database instanceof DerbyDatabase || database instanceof H2Database) { final TableExistsPrecondition precondition = new TableExistsPrecondition(); precondition.setTableName("geometry_columns"); precondition.check(database, changeLog, changeSet); } else if (database instanceof PostgresDatabase) { final ViewExistsPrecondition precondition = new ViewExistsPrecondition(); precondition.setSchemaName("public"); precondition.setViewName("geometry_columns"); precondition.check(database, changeLog, changeSet); } else if (database instanceof OracleDatabase) { // Explicitly query the database due to CORE-2198. final RawSqlStatement sql = new RawSqlStatement( "SELECT count(*) FROM ALL_VIEWS WHERE upper(VIEW_NAME)='USER_SDO_GEOM_METADATA' AND OWNER='MDSYS'"); try { final Integer result = ExecutorService.getInstance().getExecutor(database) .queryForObject(sql, Integer.class); if (result == null || result.intValue() == 0) { throw new PreconditionFailedException( "The view MDSYS.USER_SDO_GEOM_METADATA does not exist. This database is not spatially enabled", changeLog, this); } } catch (final DatabaseException e) { throw new PreconditionErrorException(e, changeLog, this); } } else if (!(database instanceof MySQLDatabase)) { final Throwable exception = new LiquibaseException(database.getDatabaseProductName() + " is not supported by this extension"); final ErrorPrecondition errorPrecondition = new ErrorPrecondition(exception, changeLog, this); throw new PreconditionErrorException(errorPrecondition); } } /** * @see liquibase.serializer.LiquibaseSerializable#getSerializedObjectName() */ @Override public String getSerializedObjectName() { return getName(); } /** * @see liquibase.serializer.LiquibaseSerializable#getSerializableFields() */ @Override public Set<String> getSerializableFields() { return new LinkedHashSet<String>(); } /** * @see liquibase.serializer.LiquibaseSerializable#getSerializableFieldValue(java.lang.String) */ @Override public Object getSerializableFieldValue(final String field) { throw new UnexpectedLiquibaseException("Unexpected field request on " + getSerializedObjectName() + ": " + field); } /** * @see liquibase.serializer.LiquibaseSerializable#getSerializableFieldType(java.lang.String) */ @Override public SerializationType getSerializableFieldType(final String field) { return SerializationType.NAMED_FIELD; } /** * @see liquibase.serializer.LiquibaseSerializable#getSerializedObjectNamespace() */ @Override public String getSerializedObjectNamespace() { return XmlConstants.SPATIAL_CHANGELOG_NAMESPACE; } /** * @see liquibase.serializer.LiquibaseSerializable#serialize() */ @Override public ParsedNode serialize() throws ParsedNodeException { return new ParsedNode(getSerializedObjectNamespace(), getSerializedObjectName()); } /** * @see liquibase.precondition.Precondition#load(liquibase.parser.core.ParsedNode, * liquibase.resource.ResourceAccessor) */ @Override public void load(final ParsedNode parsedNode, final ResourceAccessor resourceAccessor) throws ParsedNodeException { } }