/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
* (C) Copyright IBM Corporation, 2005. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
*/
/*
* Created on May 16, 2005
*
* To change the template for this generated file go to
* Window>Preferences>Java>Code Generation>Code and Comments
*/
package org.geotools.data.db2;
import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.logging.Logger;
import org.geotools.data.DataSourceException;
import org.geotools.data.Query;
import org.geotools.data.Transaction;
import org.geotools.data.jdbc.JDBCFeatureStore;
import org.geotools.filter.SQLEncoderException;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.feature.type.GeometryDescriptor;
import org.opengis.filter.Filter;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
/**
* DB2 FeatureStore implementation. Overrides functionality in
* JDBCFeatureStore to provide more efficient or more appropriate DB2-specific
* implementation.
*
* @author David Adler - IBM Corporation
* @source $URL$
*/
public class DB2FeatureStore extends JDBCFeatureStore{
private static final Logger LOGGER = org.geotools.util.logging.Logging.getLogger(
"org.geotools.data.db2");
/**
* Basic constructor for DB2FeatureStore
*
* @param dataStore
* @param featureType
*/
public DB2FeatureStore(DB2DataStore dataStore, SimpleFeatureType featureType) {
super(dataStore, featureType);
}
/**
* Gets the bounds of the feature using the specified query.
*
* @param query a query object.
*
* @return the envelope representing the bounds of the features.
*
* @throws IOException if there was an encoder problem.
* @throws DataSourceException if there was an error executing the query to
* get the bounds.
*/
public ReferencedEnvelope getBounds(Query query) throws IOException {
ReferencedEnvelope env = new ReferencedEnvelope();
CoordinateReferenceSystem crs = null;
String typeName = "null";
if (getSchema() != null) {
typeName = getSchema().getTypeName();
GeometryDescriptor geomType = getSchema()
.getGeometryDescriptor();
if (query.getFilter() != Filter.EXCLUDE) {
String sqlStmt = null;
try {
DB2SQLBuilder builder = (DB2SQLBuilder) ((DB2DataStore)this.getDataStore())
.getSqlBuilder(typeName);
sqlStmt = builder.buildSQLBoundsQuery(typeName, geomType,
query.getFilter());
} catch (SQLEncoderException e) {
throw new IOException("SQLEncoderException: " + e);
}
Connection conn = null;
Transaction transaction = null;
Statement statement = null;
ResultSet results = null;
try {
conn = getConnection();
transaction = getTransaction();
statement = conn.createStatement();
results = statement.executeQuery(sqlStmt);
if (results.next()) {
double minx = results.getDouble(1);
double miny = results.getDouble(2);
double maxx = results.getDouble(3);
double maxy = results.getDouble(4);
env = new ReferencedEnvelope(minx, maxx, miny, maxy, null);
} else {
env = new ReferencedEnvelope();
}
} catch (SQLException e) {
closeAll(results, statement, conn, transaction, e);
System.out.println(e);
throw new DataSourceException("Could not get bounds "
+ query.getHandle(), e);
}
closeAll(results, statement, conn, transaction, null);
}
crs = geomType.getCoordinateReferenceSystem();
env = new ReferencedEnvelope(env, crs);
}
LOGGER.finer(typeName + " bounds: " + env.toString());
return env;
}
/**
* Closes everything associated with a query, the ResultSet, Statement and
* Connection.
*
* @param rs the ResultSet
* @param stmt the Statement
* @param conn the Connection
* @param transaction the Transaction
* @param e the SQLException, if any, or null
*/
protected void closeAll(ResultSet rs, Statement stmt, Connection conn,
Transaction transaction, SQLException e) {
close(rs);
close(stmt);
close(conn, transaction, e);
}
/**
* Direct SQL query number of rows in query.
*
* <p>
* Note this is a low level SQL statement and if it fails the provided
* Transaction will be rolled back.
* </p>
* <p>
* SQL: SELECT COUNT(*) as cnt FROM table WHERE filter
* </p>
* @param query
* @param transaction
*
* @return Number of rows in query, or -1 if not optimizable.
*
* @throws IOException Usual on the basis of a filter error
*/
public int count(Query query, Transaction transaction) throws IOException {
int count = 0; // we may return this as default if some tests fail
String typeName = "null";
Filter filter = query.getFilter();
if (getSchema() != null) {
typeName = getSchema().getTypeName();
GeometryDescriptor geomType = (GeometryDescriptor)getSchema().getGeometryDescriptor();
if (filter != Filter.EXCLUDE) {
DB2SQLBuilder builder = (DB2SQLBuilder) ((DB2DataStore)
getDataStore()).getSqlBuilder(typeName);
Connection conn = null;
Statement statement = null;
ResultSet results = null;
try {
conn = getConnection();
StringBuffer sql = new StringBuffer();
//chorner: we should hit an indexed column, * will likely tablescan
sql.append("SELECT COUNT(*) as cnt");
builder.sqlFrom(sql, typeName);
builder.sqlWhere(sql, filter); //safe to assume filter = prefilter
statement = conn.createStatement();
results = statement.executeQuery(sql.toString());
if (results.next()) {
count = results.getInt("cnt");
}
} catch (SQLException e) {
closeAll(results, statement, conn, transaction, e);
System.out.println(e);
throw new DataSourceException("Could not get count "
+ query.getHandle(), e);
} catch (SQLEncoderException e) {
closeAll(results, statement, conn, transaction, null);
System.out.println(e);
throw new DataSourceException("Could not get count "
+ query.getHandle(), e);
}
closeAll(results, statement, conn, transaction, null);
}
}
LOGGER.finer(typeName + " count: " + count);
return count;
}
}