001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) Copyright IBM Corporation, 2005. All rights reserved.
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation;
009: * version 2.1 of the License.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: */
017: /*
018: * Created on May 16, 2005
019: *
020: * To change the template for this generated file go to
021: * Window>Preferences>Java>Code Generation>Code and Comments
022: */
023: package org.geotools.data.db2;
024:
025: import java.io.IOException;
026: import java.sql.Connection;
027: import java.sql.ResultSet;
028: import java.sql.SQLException;
029: import java.sql.Statement;
030: import java.util.logging.Logger;
031:
032: import org.geotools.data.DataSourceException;
033: import org.geotools.data.Query;
034: import org.geotools.data.Transaction;
035: import org.geotools.data.jdbc.JDBCFeatureStore;
036: import org.geotools.feature.FeatureType;
037: import org.geotools.feature.GeometryAttributeType;
038:
039: import org.geotools.filter.SQLEncoderException;
040: import org.geotools.geometry.jts.ReferencedEnvelope;
041: import org.opengis.filter.Filter;
042: import org.opengis.referencing.crs.CoordinateReferenceSystem;
043:
044: import com.vividsolutions.jts.geom.Envelope;
045:
046: /**
047: * DB2 FeatureStore implementation. Overrides functionality in
048: * JDBCFeatureStore to provide more efficient or more appropriate DB2-specific
049: * implementation.
050: *
051: * @author David Adler - IBM Corporation
052: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/unsupported/db2/src/main/java/org/geotools/data/db2/DB2FeatureStore.java $
053: */
054: public class DB2FeatureStore extends JDBCFeatureStore {
055: private static final Logger LOGGER = org.geotools.util.logging.Logging
056: .getLogger("org.geotools.data.db2");
057:
058: /**
059: * Basic constructor for DB2FeatureStore
060: *
061: * @param dataStore
062: * @param featureType
063: */
064: public DB2FeatureStore(DB2DataStore dataStore,
065: FeatureType featureType) {
066: super (dataStore, featureType);
067: }
068:
069: /**
070: * Gets the bounds of the feature using the specified query.
071: *
072: * @param query a query object.
073: *
074: * @return the envelope representing the bounds of the features.
075: *
076: * @throws IOException if there was an encoder problem.
077: * @throws DataSourceException if there was an error executing the query to
078: * get the bounds.
079: */
080: public Envelope getBounds(Query query) throws IOException {
081: Envelope env = new Envelope();
082: CoordinateReferenceSystem crs = null;
083: String typeName = "null";
084:
085: if (getSchema() != null) {
086: typeName = getSchema().getTypeName();
087: GeometryAttributeType geomType = getSchema()
088: .getDefaultGeometry();
089:
090: if (query.getFilter() != Filter.EXCLUDE) {
091: String sqlStmt = null;
092:
093: try {
094: DB2SQLBuilder builder = (DB2SQLBuilder) ((DB2DataStore) this
095: .getDataStore()).getSqlBuilder(typeName);
096: sqlStmt = builder.buildSQLBoundsQuery(typeName,
097: geomType, query.getFilter());
098: } catch (SQLEncoderException e) {
099: throw new IOException("SQLEncoderException: " + e);
100: }
101:
102: Connection conn = null;
103: Transaction transaction = null;
104: Statement statement = null;
105: ResultSet results = null;
106:
107: try {
108: conn = getConnection();
109: transaction = getTransaction();
110: statement = conn.createStatement();
111: results = statement.executeQuery(sqlStmt);
112:
113: if (results.next()) {
114: double minx = results.getDouble(1);
115: double miny = results.getDouble(2);
116: double maxx = results.getDouble(3);
117: double maxy = results.getDouble(4);
118: env = new Envelope(minx, maxx, miny, maxy);
119: } else {
120: env = new Envelope();
121: }
122: } catch (SQLException e) {
123: closeAll(results, statement, conn, transaction, e);
124: System.out.println(e);
125: throw new DataSourceException(
126: "Could not get bounds " + query.getHandle(),
127: e);
128: }
129:
130: closeAll(results, statement, conn, transaction, null);
131: }
132:
133: crs = geomType.getCoordinateSystem();
134: env = new ReferencedEnvelope(env, crs);
135: }
136:
137: LOGGER.finer(typeName + " bounds: " + env.toString());
138:
139: return env;
140: }
141:
142: /**
143: * Closes everything associated with a query, the ResultSet, Statement and
144: * Connection.
145: *
146: * @param rs the ResultSet
147: * @param stmt the Statement
148: * @param conn the Connection
149: * @param transaction the Transaction
150: * @param e the SQLException, if any, or null
151: */
152: protected void closeAll(ResultSet rs, Statement stmt,
153: Connection conn, Transaction transaction, SQLException e) {
154: close(rs);
155: close(stmt);
156: close(conn, transaction, e);
157: }
158:
159: /**
160: * Direct SQL query number of rows in query.
161: *
162: * <p>
163: * Note this is a low level SQL statement and if it fails the provided
164: * Transaction will be rolled back.
165: * </p>
166: * <p>
167: * SQL: SELECT COUNT(*) as cnt FROM table WHERE filter
168: * </p>
169: * @param query
170: * @param transaction
171: *
172: * @return Number of rows in query, or -1 if not optimizable.
173: *
174: * @throws IOException Usual on the basis of a filter error
175: */
176: public int count(Query query, Transaction transaction)
177: throws IOException {
178: int count = 0; // we may return this as default if some tests fail
179: String typeName = "null";
180: Filter filter = query.getFilter();
181:
182: if (getSchema() != null) {
183: typeName = getSchema().getTypeName();
184: GeometryAttributeType geomType = getSchema()
185: .getDefaultGeometry();
186:
187: if (filter != Filter.EXCLUDE) {
188: DB2SQLBuilder builder = (DB2SQLBuilder) ((DB2DataStore) getDataStore())
189: .getSqlBuilder(typeName);
190:
191: Connection conn = null;
192: Statement statement = null;
193: ResultSet results = null;
194:
195: try {
196: conn = getConnection();
197: StringBuffer sql = new StringBuffer();
198: //chorner: we should hit an indexed column, * will likely tablescan
199: sql.append("SELECT COUNT(*) as cnt");
200: builder.sqlFrom(sql, typeName);
201: builder.sqlWhere(sql, filter); //safe to assume filter = prefilter
202: statement = conn.createStatement();
203: results = statement.executeQuery(sql.toString());
204:
205: if (results.next()) {
206: count = results.getInt("cnt");
207: }
208: } catch (SQLException e) {
209: closeAll(results, statement, conn, transaction, e);
210: System.out.println(e);
211: throw new DataSourceException(
212: "Could not get count " + query.getHandle(),
213: e);
214: } catch (SQLEncoderException e) {
215: closeAll(results, statement, conn, transaction,
216: null);
217: System.out.println(e);
218: throw new DataSourceException(
219: "Could not get count " + query.getHandle(),
220: e);
221: }
222: closeAll(results, statement, conn, transaction, null);
223: }
224: }
225: LOGGER.finer(typeName + " count: " + count);
226: return count;
227: }
228: }
|