View Javadoc

1   package liquibase.ext.spatial.preconditions;
2   
3   import java.util.LinkedHashSet;
4   import java.util.Set;
5   
6   import liquibase.changelog.ChangeSet;
7   import liquibase.changelog.DatabaseChangeLog;
8   import liquibase.database.Database;
9   import liquibase.database.core.DerbyDatabase;
10  import liquibase.database.core.H2Database;
11  import liquibase.database.core.MySQLDatabase;
12  import liquibase.database.core.OracleDatabase;
13  import liquibase.database.core.PostgresDatabase;
14  import liquibase.exception.DatabaseException;
15  import liquibase.exception.LiquibaseException;
16  import liquibase.exception.PreconditionErrorException;
17  import liquibase.exception.PreconditionFailedException;
18  import liquibase.exception.UnexpectedLiquibaseException;
19  import liquibase.exception.ValidationErrors;
20  import liquibase.exception.Warnings;
21  import liquibase.executor.ExecutorService;
22  import liquibase.ext.spatial.xml.XmlConstants;
23  import liquibase.parser.core.ParsedNode;
24  import liquibase.parser.core.ParsedNodeException;
25  import liquibase.precondition.AbstractPrecondition;
26  import liquibase.precondition.ErrorPrecondition;
27  import liquibase.precondition.core.TableExistsPrecondition;
28  import liquibase.precondition.core.ViewExistsPrecondition;
29  import liquibase.resource.ResourceAccessor;
30  import liquibase.statement.core.RawSqlStatement;
31  
32  /**
33   * <code>SpatialSupportedPrecondition</code> checks the state of the database and determines if it
34   * has spatial support.
35   *
36   * @author Lonny Jacobson
37   */
38  public class SpatialSupportedPrecondition extends AbstractPrecondition {
39     @Override
40     public String getName() {
41        return "spatialSupported";
42     }
43  
44     @Override
45     public Warnings warn(final Database database) {
46        final Warnings warnings = new Warnings();
47        if (!(database instanceof DerbyDatabase || database instanceof H2Database
48              || database instanceof MySQLDatabase || database instanceof OracleDatabase || database instanceof PostgresDatabase)) {
49           warnings.addWarning(database.getDatabaseProductName()
50                 + " is not supported by this extension");
51        }
52        return warnings;
53     }
54  
55     @Override
56     public ValidationErrors validate(final Database database) {
57        final ValidationErrors errors = new ValidationErrors();
58        if (!(database instanceof DerbyDatabase || database instanceof H2Database
59              || database instanceof MySQLDatabase || database instanceof OracleDatabase || database instanceof PostgresDatabase)) {
60           errors.addError(database.getDatabaseProductName() + " is not supported by this extension");
61        }
62        return errors;
63     }
64  
65     @Override
66     public void check(final Database database, final DatabaseChangeLog changeLog,
67           final ChangeSet changeSet) throws PreconditionFailedException, PreconditionErrorException {
68        if (database instanceof DerbyDatabase || database instanceof H2Database) {
69           final TableExistsPrecondition precondition = new TableExistsPrecondition();
70           precondition.setTableName("geometry_columns");
71           precondition.check(database, changeLog, changeSet);
72        } else if (database instanceof PostgresDatabase) {
73           final ViewExistsPrecondition precondition = new ViewExistsPrecondition();
74           precondition.setSchemaName("public");
75           precondition.setViewName("geometry_columns");
76           precondition.check(database, changeLog, changeSet);
77        } else if (database instanceof OracleDatabase) {
78           // Explicitly query the database due to CORE-2198.
79           final RawSqlStatement sql = new RawSqlStatement(
80                 "SELECT count(*) FROM ALL_VIEWS WHERE upper(VIEW_NAME)='USER_SDO_GEOM_METADATA' AND OWNER='MDSYS'");
81           try {
82              final Integer result = ExecutorService.getInstance().getExecutor(database)
83                    .queryForObject(sql, Integer.class);
84              if (result == null || result.intValue() == 0) {
85                 throw new PreconditionFailedException(
86                       "The view MDSYS.USER_SDO_GEOM_METADATA does not exist. This database is not spatially enabled",
87                       changeLog, this);
88              }
89           } catch (final DatabaseException e) {
90              throw new PreconditionErrorException(e, changeLog, this);
91           }
92        } else if (!(database instanceof MySQLDatabase)) {
93           final Throwable exception = new LiquibaseException(database.getDatabaseProductName()
94                 + " is not supported by this extension");
95           final ErrorPrecondition errorPrecondition = new ErrorPrecondition(exception, changeLog,
96                 this);
97           throw new PreconditionErrorException(errorPrecondition);
98        }
99     }
100 
101    /**
102     * @see liquibase.serializer.LiquibaseSerializable#getSerializedObjectName()
103     */
104    @Override
105    public String getSerializedObjectName() {
106       return getName();
107    }
108 
109    /**
110     * @see liquibase.serializer.LiquibaseSerializable#getSerializableFields()
111     */
112    @Override
113    public Set<String> getSerializableFields() {
114       return new LinkedHashSet<String>();
115    }
116 
117    /**
118     * @see liquibase.serializer.LiquibaseSerializable#getSerializableFieldValue(java.lang.String)
119     */
120    @Override
121    public Object getSerializableFieldValue(final String field) {
122       throw new UnexpectedLiquibaseException("Unexpected field request on "
123             + getSerializedObjectName() + ": " + field);
124    }
125 
126    /**
127     * @see liquibase.serializer.LiquibaseSerializable#getSerializableFieldType(java.lang.String)
128     */
129    @Override
130    public SerializationType getSerializableFieldType(final String field) {
131       return SerializationType.NAMED_FIELD;
132    }
133 
134    /**
135     * @see liquibase.serializer.LiquibaseSerializable#getSerializedObjectNamespace()
136     */
137    @Override
138    public String getSerializedObjectNamespace() {
139       return XmlConstants.SPATIAL_CHANGELOG_NAMESPACE;
140    }
141 
142    /**
143     * @see liquibase.serializer.LiquibaseSerializable#serialize()
144     */
145    @Override
146    public ParsedNode serialize() throws ParsedNodeException {
147       return new ParsedNode(getSerializedObjectNamespace(), getSerializedObjectName());
148    }
149 
150    /**
151     * @see liquibase.precondition.Precondition#load(liquibase.parser.core.ParsedNode,
152     *      liquibase.resource.ResourceAccessor)
153     */
154    @Override
155    public void load(final ParsedNode parsedNode, final ResourceAccessor resourceAccessor)
156          throws ParsedNodeException {
157    }
158 }