View Javadoc

1   package liquibase.ext.spatial.sqlgenerator;
2   
3   import java.util.ArrayList;
4   import java.util.Arrays;
5   import java.util.List;
6   
7   import liquibase.database.Database;
8   import liquibase.database.core.DerbyDatabase;
9   import liquibase.database.core.H2Database;
10  import liquibase.datatype.DataTypeFactory;
11  import liquibase.datatype.LiquibaseDataType;
12  import liquibase.exception.ValidationErrors;
13  import liquibase.ext.spatial.datatype.GeometryType;
14  import liquibase.sql.Sql;
15  import liquibase.sql.UnparsedSql;
16  import liquibase.sqlgenerator.SqlGenerator;
17  import liquibase.sqlgenerator.SqlGeneratorChain;
18  import liquibase.sqlgenerator.core.AbstractSqlGenerator;
19  import liquibase.statement.core.AddColumnStatement;
20  import liquibase.util.StringUtils;
21  
22  /**
23   * <code>AddGeometryColumnGeneratorGeoDB</code> is a SQL generator that
24   * specializes in GeoDB. Regardless of the column type, the next SQL generator
25   * in the chain is invoked to handle the normal column addition. If the column
26   * to be added has a geometry type, the <code>AddGeometryColumn</code> stored
27   * procedure is invoked to ensure that the necessary metadata is created in the
28   * database.
29   */
30  public class AddGeometryColumnGeneratorGeoDB extends
31        AbstractSqlGenerator<AddColumnStatement> {
32     /**
33      * @see liquibase.sqlgenerator.core.AbstractSqlGenerator#supports(liquibase.statement.SqlStatement,
34      *      liquibase.database.Database)
35      */
36     @Override
37     public boolean supports(final AddColumnStatement statement,
38           final Database database) {
39        return database instanceof DerbyDatabase
40              || database instanceof H2Database;
41     }
42  
43     /**
44      * @see liquibase.sqlgenerator.core.AbstractSqlGenerator#getPriority()
45      */
46     @Override
47     public int getPriority() {
48        return SqlGenerator.PRIORITY_DATABASE + 1;
49     }
50  
51     @Override
52     public ValidationErrors validate(final AddColumnStatement statement,
53           final Database database, final SqlGeneratorChain sqlGeneratorChain) {
54        final ValidationErrors errors = new ValidationErrors();
55        final LiquibaseDataType dataType = DataTypeFactory.getInstance()
56              .fromDescription(statement.getColumnType(), database);
57  
58        // Ensure that the SRID parameter is provided.
59        if (dataType instanceof GeometryType) {
60           final GeometryType geometryType = (GeometryType) dataType;
61           if (geometryType.getSRID() == null) {
62              errors.addError("The SRID parameter is required on the geometry type");
63           }
64        }
65        final ValidationErrors chainErrors = sqlGeneratorChain.validate(
66              statement, database);
67        if (chainErrors != null) {
68           errors.addAll(chainErrors);
69        }
70        return errors;
71     }
72  
73     @Override
74     public Sql[] generateSql(final AddColumnStatement statement,
75           final Database database, final SqlGeneratorChain sqlGeneratorChain) {
76  
77        GeometryType geometryType = null;
78        final LiquibaseDataType dataType = DataTypeFactory.getInstance()
79              .fromDescription(statement.getColumnType(), database);
80        if (dataType instanceof GeometryType) {
81           geometryType = (GeometryType) dataType;
82        }
83  
84        final boolean isGeometryColumn = geometryType != null;
85  
86        // The AddGeometryColumn procedure handles the column already being
87        // present, so let a
88        // downstream SQL generator handle the typical column addition logic (e.g.
89        // placement in the
90        // table) then invoke the procedure.
91        final List<Sql> list = new ArrayList<Sql>();
92        list.addAll(Arrays.asList(sqlGeneratorChain.generateSql(statement,
93              database)));
94        if (isGeometryColumn) {
95           String schemaName = statement.getSchemaName();
96           if (schemaName == null) {
97              schemaName = database.getDefaultSchemaName();
98           }
99           final String tableName = statement.getTableName();
100          final String columnName = statement.getColumnName();
101 
102          final int srid = geometryType.getSRID();
103          final String geomType = StringUtils.trimToNull(geometryType
104                .getGeometryType()) == null ? "'Geometry'" : "'"
105                + database.escapeStringForDatabase(geometryType
106                      .getGeometryType()) + "'";
107          final String sql = "CALL AddGeometryColumn('" + schemaName + "', '"
108                + tableName + "', '" + columnName + "', " + srid + ", "
109                + geomType + ", 2)";
110          final Sql addGeometryColumn = new UnparsedSql(sql);
111          list.add(addGeometryColumn);
112       }
113       return list.toArray(new Sql[list.size()]);
114    }
115 }