View Javadoc

1   package liquibase.ext.spatial.utils;
2   
3   import java.sql.ResultSet;
4   import java.sql.SQLException;
5   import java.sql.Statement;
6   
7   import liquibase.database.Database;
8   import liquibase.database.DatabaseConnection;
9   import liquibase.database.core.DerbyDatabase;
10  import liquibase.database.core.H2Database;
11  import liquibase.database.core.PostgresDatabase;
12  import liquibase.database.jvm.JdbcConnection;
13  import liquibase.exception.LiquibaseException;
14  import liquibase.exception.UnexpectedLiquibaseException;
15  import liquibase.snapshot.SnapshotGeneratorFactory;
16  import liquibase.structure.DatabaseObject;
17  import liquibase.structure.core.Table;
18  import liquibase.structure.core.View;
19  
20  /**
21   * <code>GeometryColumnsUtils</code> provides useful methods for checking the
22   * <code>GEOMETRY_COLUMNS</code> table.
23   */
24  public class GeometryColumnsUtils {
25  
26     /**
27      * Hide the default constructor.
28      */
29     private GeometryColumnsUtils() {
30     }
31  
32     /**
33      * Determines if the given table is in <code>GEOMETRY_COLUMNS</code> and,
34      * therefore, has a geometry column.
35      * 
36      * @param database
37      *           the database to query.
38      * @param schemaName
39      *           the schema name.
40      * @param tableName
41      *           the table name to check.
42      * @return <code>true</code> if the table has a geometry column.
43      */
44     public static boolean hasGeometryColumn(final Database database,
45           final String schemaName, final String tableName) {
46        boolean isSpatialColumn = false;
47        Statement jdbcStatement = null;
48        try {
49           if (geometryColumnsExists(database)) {
50              final String query = "SELECT * FROM geometry_columns WHERE f_table_schema = '"
51                    + (schemaName == null ? database.getDefaultSchemaName()
52                          : schemaName)
53                    + "' AND f_table_name = '"
54                    + tableName
55                    + "'";
56              final DatabaseConnection databaseConnection = database
57                    .getConnection();
58              final JdbcConnection jdbcConnection = (JdbcConnection) databaseConnection;
59              jdbcStatement = jdbcConnection.getUnderlyingConnection()
60                    .createStatement();
61              final ResultSet rs = jdbcStatement.executeQuery(query);
62              isSpatialColumn = rs.next();
63           }
64        } catch (final SQLException e) {
65           throw new UnexpectedLiquibaseException(
66                 "Failed to determine if the table has a geometry column", e);
67        } finally {
68           if (jdbcStatement != null) {
69              try {
70                 jdbcStatement.close();
71              } catch (final SQLException ignore) {
72              }
73           }
74        }
75        return isSpatialColumn;
76     }
77  
78     /**
79      * Determines if the given column is in <code>GEOMETRY_COLUMNS</code>.
80      * 
81      * @param database
82      *           the database to query.
83      * @param schemaName
84      *           the schema name.
85      * @param tableName
86      *           the table name.
87      * @param columnName
88      *           the column name.
89      * @return <code>true</code> if the column is a geometry column.
90      */
91     public static boolean isGeometryColumn(final Database database,
92           final String schemaName, final String tableName,
93           final String columnName) {
94        boolean isSpatialColumn = false;
95        Statement jdbcStatement = null;
96        try {
97           if (geometryColumnsExists(database)) {
98              final String query = "SELECT * FROM geometry_columns WHERE f_table_schema = '"
99                    + (schemaName == null ? database.getDefaultSchemaName()
100                         : schemaName)
101                   + "' AND f_table_name = '"
102                   + tableName
103                   + "' AND upper(f_geometry_column) = '"
104                   + columnName.toUpperCase() + "'";
105             final DatabaseConnection databaseConnection = database
106                   .getConnection();
107             final JdbcConnection jdbcConnection = (JdbcConnection) databaseConnection;
108             jdbcStatement = jdbcConnection.getUnderlyingConnection()
109                   .createStatement();
110             final ResultSet rs = jdbcStatement.executeQuery(query);
111             isSpatialColumn = rs.next();
112          }
113       } catch (final SQLException e) {
114          throw new UnexpectedLiquibaseException(
115                "Failed to determine if the column to be dropped is a geometry column",
116                e);
117       } finally {
118          if (jdbcStatement != null) {
119             try {
120                jdbcStatement.close();
121             } catch (final SQLException ignore) {
122             }
123          }
124       }
125       return isSpatialColumn;
126    }
127 
128    /**
129     * Indicates if the <code>GEOMETRY_COLUMNS</code> table or view exists.
130     * 
131     * @param database
132     *           the database to check.
133     * @return <code>true</code> if the table or view exists.
134     */
135    public static boolean geometryColumnsExists(final Database database) {
136       String geometryColumnsName = database.correctObjectName(
137             "geometry_columns", Table.class);
138       DatabaseObject example = null;
139       if (database instanceof DerbyDatabase || database instanceof H2Database) {
140          final Table tableExample = new Table();
141          tableExample.setName(geometryColumnsName);
142          tableExample.setSchema(database.getDefaultCatalogName(),
143                database.getDefaultSchemaName());
144          example = tableExample;
145       } else if (database instanceof PostgresDatabase) {
146          final View viewExample = new View();
147          viewExample.setName(geometryColumnsName);
148          viewExample.setSchema(database.getDefaultCatalogName(), "public");
149          example = viewExample;
150       }
151       try {
152          return example != null
153                && SnapshotGeneratorFactory.getInstance().has(example, database);
154       } catch (final LiquibaseException e) {
155          throw new UnexpectedLiquibaseException(
156                "Failed to determine if the geometry_columns table or view exists",
157                e);
158       }
159    }
160 }