diff --git a/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/AppSchemaDataAccess.java b/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/AppSchemaDataAccess.java
index 29603ed..66700d0 100644
--- a/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/AppSchemaDataAccess.java
+++ b/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/AppSchemaDataAccess.java
@@ -337,7 +337,7 @@ public class AppSchemaDataAccess implements DataAccess {
newQuery.setSortBy( sort.toArray(new SortBy[sort.size()]) );
JoiningQuery jQuery = new JoiningQuery(newQuery);
- jQuery.setJoins(((JoiningQuery)query).getJoins());
+ jQuery.setQueryJoins(((JoiningQuery)query).getQueryJoins());
unrolledQuery = jQuery;
}
else {
diff --git a/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/MappingFeatureSource.java b/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/MappingFeatureSource.java
index 2ecaaed..a3fd806 100644
--- a/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/MappingFeatureSource.java
+++ b/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/MappingFeatureSource.java
@@ -110,7 +110,7 @@ class MappingFeatureSource implements FeatureSource {
namedQuery.setSortBy(query.getSortBy());
namedQuery.setHints(query.getHints());
if (query instanceof JoiningQuery) {
- ((JoiningQuery) namedQuery).setJoins(((JoiningQuery) query).getJoins());
+ ((JoiningQuery) namedQuery).setQueryJoins(((JoiningQuery) query).getQueryJoins());
}
return namedQuery;
}
diff --git a/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/joining/JoiningNestedAttributeMapping.java b/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/joining/JoiningNestedAttributeMapping.java
index 751bd9e..19c7f39 100644
--- a/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/joining/JoiningNestedAttributeMapping.java
+++ b/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/joining/JoiningNestedAttributeMapping.java
@@ -138,20 +138,20 @@ public class JoiningNestedAttributeMapping extends NestedAttributeMapping {
}
Expression nestedSourceExpression = mappings.get(0).getSourceExpression();
- List joins = new ArrayList();
+ List joins = new ArrayList();
if (instance.baseTableQuery instanceof JoiningQuery) {
- if (((JoiningQuery) instance.baseTableQuery).getJoins() != null) {
- joins.addAll(((JoiningQuery) instance.baseTableQuery).getJoins());
+ if (((JoiningQuery) instance.baseTableQuery).getQueryJoins() != null) {
+ joins.addAll(((JoiningQuery) instance.baseTableQuery).getQueryJoins());
}
}
- JoiningQuery.Join join = new JoiningQuery.Join();
+ JoiningQuery.QueryJoin join = new JoiningQuery.QueryJoin();
join.setForeignKeyName(sourceExpression);
join.setJoiningKeyName(nestedSourceExpression);
join.setJoiningTypeName(instance.baseTableQuery.getTypeName());
join.setSortBy(instance.baseTableQuery.getSortBy()); // incorporate order
joins.add(0, join);
- query.setJoins(joins);
+ query.setQueryJoins(joins);
if (selectedProperties != null) {
selectedProperties = new ArrayList(selectedProperties);
@@ -192,8 +192,8 @@ public class JoiningNestedAttributeMapping extends NestedAttributeMapping {
DataAccessMappingFeatureIterator daFeatureIterator = (DataAccessMappingFeatureIterator) featureIterator;
List foreignIds = new ArrayList();
- for (int i = 0; i < query.getJoins().size(); i++) {
- for (int j = 0; j < query.getJoins().get(i).getSortBy().length; j++) {
+ for (int i = 0; i < query.getQueryJoins().size(); i++) {
+ for (int j = 0; j < query.getQueryJoins().get(i).getSortBy().length; j++) {
foreignIds.add(filterFac.property(JoiningJDBCFeatureSource.FOREIGN_ID + "_" + i
+ "_" + j));
}
diff --git a/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/joining/JoiningQuery.java b/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/joining/JoiningQuery.java
index 7d3487b..3451933 100644
--- a/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/joining/JoiningQuery.java
+++ b/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/joining/JoiningQuery.java
@@ -33,7 +33,7 @@ import org.opengis.filter.sort.SortBy;
*/
public class JoiningQuery extends Query {
- public static class Join {
+ public static class QueryJoin {
protected String joiningTypeName;
protected Expression foreignKeyName;
protected Expression joiningKeyName;
@@ -72,12 +72,12 @@ public class JoiningQuery extends Query {
}
}
- protected List joins;
+ protected List queryJoins;
public JoiningQuery(JoiningQuery query) {
super(query);
- setJoins(query.getJoins());
+ setQueryJoins(query.getQueryJoins());
}
public JoiningQuery(Query query){
@@ -87,12 +87,12 @@ public class JoiningQuery extends Query {
public JoiningQuery() {
}
- public void setJoins(List joins){
- this.joins = joins;
+ public void setQueryJoins(List queryJoins){
+ this.queryJoins = queryJoins;
}
- public List getJoins(){
- return joins;
+ public List getQueryJoins(){
+ return queryJoins;
}
}
diff --git a/modules/extension/app-schema/app-schema/src/main/java/org/geotools/jdbc/JoiningJDBCFeatureSource.java b/modules/extension/app-schema/app-schema/src/main/java/org/geotools/jdbc/JoiningJDBCFeatureSource.java
index 05b9c2b..ee1c71b 100644
--- a/modules/extension/app-schema/app-schema/src/main/java/org/geotools/jdbc/JoiningJDBCFeatureSource.java
+++ b/modules/extension/app-schema/app-schema/src/main/java/org/geotools/jdbc/JoiningJDBCFeatureSource.java
@@ -158,7 +158,7 @@ public class JoiningJDBCFeatureSource extends JDBCFeatureSource {
}
}
- protected void addMultiValuedSort(String tableName, SortBy[] sort , StringBuffer sql, JoiningQuery.Join join ) throws IOException, FilterToSQLException {
+ protected void addMultiValuedSort(String tableName, SortBy[] sort , StringBuffer sql, JoiningQuery.QueryJoin join ) throws IOException, FilterToSQLException {
sql.append(" CASE WHEN ");
FilterToSQL toSQL1 = createFilterToSQL(getDataStore().getSchema(tableName));
toSQL1.setFieldEncoder(new JoiningFieldEncoder(tableName));
@@ -182,8 +182,8 @@ public class JoiningJDBCFeatureSource extends JDBCFeatureSource {
protected void sort(JoiningQuery query, StringBuffer sql, String[] aliases) throws IOException, SQLException, FilterToSQLException {
boolean orderby = false;
- for (int j = query.getJoins() == null? -1 : query.getJoins().size() -1; j >= -1 ; j-- ) {
- JoiningQuery.Join join = j<0 ? null : query.getJoins().get(j);
+ for (int j = query.getQueryJoins() == null? -1 : query.getQueryJoins().size() -1; j >= -1 ; j-- ) {
+ JoiningQuery.QueryJoin join = j<0 ? null : query.getQueryJoins().get(j);
SortBy[] sort = j<0? query.getSortBy() : join.getSortBy();
if ((sort != null) && (sort.length > 0)) {
@@ -193,8 +193,8 @@ public class JoiningJDBCFeatureSource extends JDBCFeatureSource {
}
if (j < 0) {
sort(query.getTypeName(), sort, sql, false);
- if (query.getJoins()!= null && query.getJoins().size()>0) {
- addMultiValuedSort(query.getTypeName(), sort, sql, query.getJoins().get(0));
+ if (query.getQueryJoins()!= null && query.getQueryJoins().size()>0) {
+ addMultiValuedSort(query.getTypeName(), sort, sql, query.getQueryJoins().get(0));
}
} else {
if (aliases!=null && aliases[j] != null) {
@@ -202,8 +202,8 @@ public class JoiningJDBCFeatureSource extends JDBCFeatureSource {
} else {
sort(join.getJoiningTypeName() , sort, sql, false);
}
- if (query.getJoins().size()>j+1) {
- addMultiValuedSort(join.getJoiningTypeName(), sort, sql, query.getJoins().get(j+1));
+ if (query.getQueryJoins().size()>j+1) {
+ addMultiValuedSort(join.getJoiningTypeName(), sort, sql, query.getQueryJoins().get(j+1));
}
}
}
@@ -308,13 +308,13 @@ public class JoiningJDBCFeatureSource extends JDBCFeatureSource {
String[] aliases = null;
- if (query.getJoins() != null) {
+ if (query.getQueryJoins() != null) {
SortBy[] lastSortBy = query.getSortBy();
- aliases = new String[query.getJoins().size()];
+ aliases = new String[query.getQueryJoins().size()];
- for (int i=0; i< query.getJoins().size(); i++) {
- JoiningQuery.Join join = query.getJoins().get(i);
+ for (int i=0; i< query.getQueryJoins().size(); i++) {
+ JoiningQuery.QueryJoin join = query.getQueryJoins().get(i);
if (lastSortBy!= null && lastSortBy.length > 0) {
tableNames.add(curTypeName);
@@ -416,11 +416,11 @@ public class JoiningJDBCFeatureSource extends JDBCFeatureSource {
sql.append(",");
}
- if (query.getJoins() != null && query.getJoins().size() > 0) {
- for (int i=0; i 0) {
+ for (int i=0; i
+ * The Join class is similar to Query in that it allows one to specify a FeatureType name, a set of
+ * properties, and a filter. A Join must specify:
+ *
+ *
A type name that references the feature type to join to, see {@link #getTypeName()}
+ *
A join filter that describes how to join, see {@link #getJoinFilter()}
+ *
+ * Optionally a Join may also specify:
+ *
+ *
A set of property names constraining the attributes of joined features, see {@link #getProperties()}
+ *
A secondary filter used to constrained features from the joined feature type, see {@link #getFilter()}
+ *
An alias for the joined feature type, which can be used in the join filter to disambiguate
+ * attributes of the feature types being joined, see {@link #getAlias()}
+ *
A join type specifying what type of join (inner, outer, etc...) should be performed, see {@link #getType()}
+ *
+ *
+ *
+ * @author Justin Deoliveira, OpenGeo
+ *
+ * @since 8.0
+ */
+public class Join {
+
+ /**
+ * filter factory
+ */
+ static final FilterFactory ff = CommonFactoryFinder.getFilterFactory(null);
+
+ /**
+ * type of join
+ */
+ public static enum Type {
+ INNER, OUTER;
+ }
+
+ /** join type */
+ Type type;
+
+ /**
+ * the feature type name being joined to
+ */
+ String typeName;
+
+ /**
+ * attributes to fetch for this feature type
+ */
+ List properties = Query.ALL_PROPERTIES;
+
+ /**
+ * the join predicate
+ */
+ Filter join;
+
+ /**
+ * additional predicate against the target of the join
+ */
+ Filter filter;
+
+ /**
+ * The alias to be used for the typeName in this join
+ */
+ String alias;
+
+ /**
+ * Constructs a join.
+ *
+ * @param typeName The name of the feature type to join to.
+ * @param join The filter specifying the join condition between the two feature types being
+ * joined.
+ */
+ public Join(String typeName, Filter join) {
+ this.typeName = typeName;
+ this.join = join;
+ this.type = Type.INNER;
+ this.properties = Query.ALL_PROPERTIES;
+ this.filter = Filter.INCLUDE;
+ this.alias = null;
+ }
+
+ /**
+ * Constructs a join from another.
+ */
+ public Join(Join other) {
+ this.typeName = other.getTypeName();
+ this.join = other.getJoinFilter();
+ this.filter = other.getFilter();
+ this.type = other.getType();
+ this.properties = other.getProperties();
+ this.filter = other.getFilter();
+ this.alias = other.getAlias();
+ }
+
+ /**
+ * The name of the feature type being joined to.
+ *
+ * This name may be the same as the name of the primary feature type, this is how a self join is
+ * specified.
+ *
+ */
+ public String getTypeName() {
+ return typeName;
+ }
+
+ /**
+ * The filter defining the join condition between the primary feature type and the feature
+ * type being joined to.
+ *
+ * This filter should be a comparison operator whose contents are two {@link PropertyName}
+ * instances. For example:
+ *
+ * new Join("theOtherType", propertyIsEqualTo(propertyName("foo"), propertyName("bar")));
+ *
+ * In instances where the two property names involved in the join are the same a prefix or
+ * alias must be used to differentiate:
+ *
+ *
+ */
+ public Filter getJoinFilter() {
+ return join;
+ }
+
+ /**
+ * Sets the join type.
+ * @see #getType()
+ */
+ public void setType(Type type) {
+ this.type = type;
+ }
+
+ /**
+ * The type of the join.
+ *
+ * {@link Type#INNER} is the default join type.
+ *
+ *
+ */
+ public Type getType() {
+ return type;
+ }
+
+ /**
+ * List of properties specifying which attributes of joined features to obtain.
+ *
+ * This method has the same purpose as {@link Query#getProperties()}.
+ *
+ */
+ public List getProperties() {
+ if (properties == Query.ALL_PROPERTIES) {
+ return properties;
+ }
+ return Collections.unmodifiableList(properties);
+ }
+
+ /**
+ * Sets list of properties specifying which attributes of joined features to obtain.
+ *
+ * This method has the same purpose as {@link Query#setProperties(List)}.
+ *
+ */
+ public void setProperties(List properties) {
+ this.properties = properties;
+ }
+
+ /**
+ * List of property names specifying which attributes of joined features to obtain.
+ *
+ * This method has the same purpose as {@link Query#getPropertyNames()}.
+ *
+ */
+ public String[] getPropertyNames() {
+ if (properties == Query.ALL_PROPERTIES) {
+ return Query.ALL_NAMES;
+ }
+
+ String[] names = new String[properties.size()];
+ for (int i = 0; i < names.length; i++) {
+ names[i] = properties.get(i).getPropertyName();
+ }
+ return names;
+ }
+
+ /**
+ * Sets the filter used to constrain which features from the joined feature type to return.
+ *
+ * @see #getFilter()
+ */
+ public void setFilter(Filter filter) {
+ this.filter = filter;
+ }
+
+ /**
+ * Filter used to constrain which features from the joined feature type to return.
+ *
+ * This filter must only reference attributes from the joined feature type, and not of any other
+ * feature types involved in the join.
+ *
+ */
+ public Filter getFilter() {
+ return filter;
+ }
+
+ /**
+ * Sets an alias for the feature type being joined to.
+ * @see #getAlias()
+ */
+ public void setAlias(String alias) {
+ this.alias = alias;
+ }
+
+ /**
+ * An alias for the feature type being joined to.
+ *
+ * This method is useful in cases where the two feature types being joined contain attributes
+ * identically named, or in cases where a self join is being performed:
+ *
+ *
+ *
+ * @see #getJoinFilter()
+ */
+ public String getAlias() {
+ return alias;
+ }
+
+ /**
+ * Convenience method that returns the attribute name to be used for this join.
+ *
+ * The Query class supports the concepts of joins in that a query can result in a join of the
+ * feature type to other feature types in the same datastore. For example, the following would be
+ * a spatial join that selected the country that contain a particular city.
+ *
* Filter filter = CQL.toFilter("NAME like '%land'");
* Query query = new Query( "countries", filter );
@@ -173,6 +188,9 @@ public class Query {
/** The typeName to get */
protected String typeName;
+
+ /** The optional alias for type name */
+ protected String alias;
/** The namespace to get */
protected URI namespace =Query.NO_NAMESPACE;
@@ -194,7 +212,10 @@ public class Query {
/** The hints to be used during query execution */
protected Hints hints;
-
+
+ /** join clauses for this query */
+ protected List joins = new ArrayList();
+
/**
* Default constructor. Use setter methods to configure the Query
* before use (the default Query will retrieve all features).
@@ -326,6 +347,11 @@ public class Query {
this.version = query.getVersion();
this.hints = query.getHints();
this.startIndex = query.getStartIndex();
+ this.alias = query.getAlias();
+ this.joins = new ArrayList();
+ for (Join j : query.getJoins()) {
+ this.joins.add(new Join(j));
+ }
}
/**
@@ -585,7 +611,29 @@ public class Query {
public void setTypeName(String typeName) {
this.typeName = typeName;
}
-
+
+ /**
+ * An alias substitutable for {@link #getTypeName()}.
+ *
+ * This value is typically used in a join query in which the join filter requires disambiguation
+ * due to property name overlaps between joined types.
+ *
+ * @since 8.0
+ */
+ public String getAlias() {
+ return alias;
+ }
+
+ /**
+ * Sets the type name alias.
+ *
+ * @since 8.0
+ * @see #getAlias()
+ */
+ public void setAlias(String alias) {
+ this.alias = alias;
+ }
+
/**
* Get the namespace of the feature type to be queried.
*
@@ -904,4 +952,16 @@ public class Query {
return returnString.toString();
}
+
+ /**
+ * The list of joins for this query.
+ *
+ * Each {@link Join} object specifies a feature type to join to. The join may only reference
+ * a feature type from within the same datastore.
+ *
+ * @see Join
+ */
+ public List getJoins() {
+ return joins;
+ }
}
diff --git a/modules/library/api/src/main/java/org/geotools/data/QueryCapabilities.java b/modules/library/api/src/main/java/org/geotools/data/QueryCapabilities.java
index 71a91c7..8ccba9b 100644
--- a/modules/library/api/src/main/java/org/geotools/data/QueryCapabilities.java
+++ b/modules/library/api/src/main/java/org/geotools/data/QueryCapabilities.java
@@ -108,4 +108,11 @@ public class QueryCapabilities {
public boolean isUseProvidedFIDSupported() {
return false;
}
+
+ /**
+ * If true the datastore supports joins between feature types within the datastores.
+ */
+ public boolean isJoiningSupported() {
+ return false;
+ }
}
diff --git a/modules/library/data/src/main/java/org/geotools/data/store/ContentFeatureCollection.java b/modules/library/data/src/main/java/org/geotools/data/store/ContentFeatureCollection.java
index 4bac526..3935b76 100644
--- a/modules/library/data/src/main/java/org/geotools/data/store/ContentFeatureCollection.java
+++ b/modules/library/data/src/main/java/org/geotools/data/store/ContentFeatureCollection.java
@@ -31,6 +31,7 @@ import org.geotools.data.DefaultQuery;
import org.geotools.data.FeatureEvent;
import org.geotools.data.FeatureListener;
import org.geotools.data.FeatureReader;
+import org.geotools.data.Join;
import org.geotools.data.Query;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureIterator;
@@ -113,13 +114,23 @@ public class ContentFeatureCollection implements SimpleFeatureCollection {
this.featureSource = featureSource;
this.query = query;
+ this.featureType = featureSource.getSchema();
+
//retype feature type if necessary
if ( query.getPropertyNames() != Query.ALL_NAMES ) {
this.featureType =
- SimpleFeatureTypeBuilder.retype(featureSource.getSchema(), query.getPropertyNames() );
+ SimpleFeatureTypeBuilder.retype(this.featureType, query.getPropertyNames() );
}
- else {
- this.featureType = featureSource.getSchema();
+
+ //check for join and expand attributes as necessary
+ if (!query.getJoins().isEmpty()) {
+ SimpleFeatureTypeBuilder tb = new SimpleFeatureTypeBuilder();
+ tb.init(this.featureType);
+
+ for (Join join : query.getJoins()) {
+ tb.add(join.attributeName(), SimpleFeature.class);
+ }
+ this.featureType = tb.buildFeatureType();
}
}
diff --git a/modules/library/data/src/main/java/org/geotools/data/store/ContentFeatureSource.java b/modules/library/data/src/main/java/org/geotools/data/store/ContentFeatureSource.java
index 48684ef..4651a9b 100644
--- a/modules/library/data/src/main/java/org/geotools/data/store/ContentFeatureSource.java
+++ b/modules/library/data/src/main/java/org/geotools/data/store/ContentFeatureSource.java
@@ -477,7 +477,12 @@ public abstract class ContentFeatureSource implements SimpleFeatureSource {
dq.setSortBy(new SortBy[] {SortBy.NATURAL_ORDER});
query = dq;
}
-
+
+ //check for a join
+ if (!query.getJoins().isEmpty() && getQueryCapabilities().isJoiningSupported()) {
+ throw new IOException("Feature source does not support joins");
+ }
+
FeatureReader reader = getReaderInternal( query );
//
@@ -868,7 +873,7 @@ public abstract class ContentFeatureSource implements SimpleFeatureSource {
// join the queries
return DataUtilities.mixQueries(this.query, query, null);
}
-
+
/**
* This method changes the query object so that all propertyName references are resolved
* to simple attribute names against the schema of the feature source.
diff --git a/modules/library/jdbc/src/main/java/org/geotools/data/jdbc/FilterToSQL.java b/modules/library/jdbc/src/main/java/org/geotools/data/jdbc/FilterToSQL.java
index 315d31d..140938e 100644
--- a/modules/library/jdbc/src/main/java/org/geotools/data/jdbc/FilterToSQL.java
+++ b/modules/library/jdbc/src/main/java/org/geotools/data/jdbc/FilterToSQL.java
@@ -33,9 +33,8 @@ import org.geotools.factory.Hints;
import org.geotools.filter.FilterCapabilities;
import org.geotools.filter.FunctionImpl;
import org.geotools.filter.LikeFilterImpl;
-import org.geotools.filter.function.FilterFunction_strConcat;
-import org.geotools.filter.function.FilterFunction_strEndsWith;
import org.geotools.jdbc.JDBCDataStore;
+import org.geotools.jdbc.JoinPropertyName;
import org.geotools.jdbc.PrimaryKey;
import org.geotools.util.ConverterFactory;
import org.geotools.util.Converters;
@@ -47,6 +46,7 @@ import org.opengis.filter.BinaryComparisonOperator;
import org.opengis.filter.BinaryLogicOperator;
import org.opengis.filter.ExcludeFilter;
import org.opengis.filter.Filter;
+import org.opengis.filter.FilterFactory;
import org.opengis.filter.FilterVisitor;
import org.opengis.filter.Id;
import org.opengis.filter.IncludeFilter;
@@ -90,6 +90,7 @@ import org.opengis.filter.temporal.AnyInteracts;
import org.opengis.filter.temporal.Before;
import org.opengis.filter.temporal.Begins;
import org.opengis.filter.temporal.BegunBy;
+import org.opengis.filter.temporal.BinaryTemporalOperator;
import org.opengis.filter.temporal.During;
import org.opengis.filter.temporal.EndedBy;
import org.opengis.filter.temporal.Ends;
@@ -99,6 +100,7 @@ import org.opengis.filter.temporal.OverlappedBy;
import org.opengis.filter.temporal.TContains;
import org.opengis.filter.temporal.TEquals;
import org.opengis.filter.temporal.TOverlaps;
+import org.opengis.temporal.Period;
import com.vividsolutions.jts.geom.Geometry;
@@ -150,6 +152,9 @@ public class FilterToSQL implements FilterVisitor, ExpressionVisitor {
/** error message for exceptions */
protected static final String IO_ERROR = "io problem writing filter";
+ /** filter factory */
+ protected static FilterFactory filterFactory = CommonFactoryFinder.getFilterFactory(null);
+
/** The filter types that this class can encode */
protected FilterCapabilities capabilities = null;
@@ -188,7 +193,10 @@ public class FilterToSQL implements FilterVisitor, ExpressionVisitor {
/** the srid corresponding to the current binary spatial filter being encoded */
protected Integer currentSRID;
-
+
+ /** inline flag, controlling whether "WHERE" will prefix the SQL encoded filter */
+ protected boolean inline = false;
+
/**
* Default constructor
*/
@@ -206,7 +214,11 @@ public class FilterToSQL implements FilterVisitor, ExpressionVisitor {
public void setWriter(Writer out) {
this.out = out;
}
-
+
+ public void setInline(boolean inline) {
+ this.inline = inline;
+ }
+
/**
* Performs the encoding, sends the encoded sql to the writer passed in.
*
@@ -220,7 +232,10 @@ public class FilterToSQL implements FilterVisitor, ExpressionVisitor {
if (getCapabilities().fullySupports(filter)) {
try {
- out.write("WHERE ");
+ if (!inline) {
+ out.write("WHERE ");
+ }
+
filter.accept(this, null);
//out.write(";");
@@ -349,6 +364,17 @@ public class FilterToSQL implements FilterVisitor, ExpressionVisitor {
capabilities.addType(Id.class);
capabilities.addType(IncludeFilter.class);
capabilities.addType(ExcludeFilter.class);
+
+ //temporal filters
+ capabilities.addType(After.class);
+ capabilities.addType(Before.class);
+ capabilities.addType(Begins.class);
+ capabilities.addType(BegunBy.class);
+ capabilities.addType(During.class);
+ capabilities.addType(Ends.class);
+ capabilities.addType(EndedBy.class);
+ capabilities.addType(TContains.class);
+ capabilities.addType(TEquals.class);
return capabilities;
}
@@ -854,51 +880,244 @@ public class FilterToSQL implements FilterVisitor, ExpressionVisitor {
+ "can't do SDO relate against it: "
+ filter.getClass());
+
// extract the property name and the geometry literal
- PropertyName property;
- Literal geometry;
BinaryComparisonOperator op = (BinaryComparisonOperator) filter;
- if (op.getExpression1() instanceof PropertyName
- && op.getExpression2() instanceof Literal) {
- property = (PropertyName) op.getExpression1();
- geometry = (Literal) op.getExpression2();
- } else if (op.getExpression2() instanceof PropertyName
- && op.getExpression1() instanceof Literal) {
- property = (PropertyName) op.getExpression2();
- geometry = (Literal) op.getExpression1();
- } else {
- throw new IllegalArgumentException(
- "Can only encode spatial filters that do "
- + "compare a property name and a geometry");
+ Expression e1 = op.getExpression1();
+ Expression e2 = op.getExpression2();
+
+ if (e1 instanceof Literal && e2 instanceof PropertyName) {
+ e1 = (PropertyName) op.getExpression2();
+ e2 = (Literal) op.getExpression1();
}
- // handle native srid
- currentGeometry = null;
- currentSRID = null;
- if (featureType != null) {
- // going thru evaluate ensures we get the proper result even if the
- // name has
- // not been specified (convention -> the default geometry)
- AttributeDescriptor descriptor = (AttributeDescriptor) property
- .evaluate(featureType);
- if (descriptor instanceof GeometryDescriptor) {
- currentGeometry = (GeometryDescriptor) descriptor;
- currentSRID = (Integer) descriptor.getUserData().get(
- JDBCDataStore.JDBC_NATIVE_SRID);
+ if (e1 instanceof PropertyName) {
+ // handle native srid
+ currentGeometry = null;
+ currentSRID = null;
+ if (featureType != null) {
+ // going thru evaluate ensures we get the proper result even if the
+ // name has
+ // not been specified (convention -> the default geometry)
+ AttributeDescriptor descriptor = (AttributeDescriptor) e1.evaluate(featureType);
+ if (descriptor instanceof GeometryDescriptor) {
+ currentGeometry = (GeometryDescriptor) descriptor;
+ currentSRID = (Integer) descriptor.getUserData().get(
+ JDBCDataStore.JDBC_NATIVE_SRID);
+ }
}
}
- return visitBinarySpatialOperator(filter, property, geometry, filter
- .getExpression1() instanceof Literal, extraData);
+ if (e1 instanceof PropertyName && e2 instanceof Literal) {
+ //call the "regular" method
+ return visitBinarySpatialOperator(filter, (PropertyName)e1, (Literal)e2, filter
+ .getExpression1() instanceof Literal, extraData);
+ }
+ else {
+ //call the join version
+ return visitBinarySpatialOperator(filter, e1, e2, extraData);
+ }
+
}
+ /**
+ * Handles the common case of a PropertyName,Literal geometry binary spatial operator.
+ */
protected Object visitBinarySpatialOperator(BinarySpatialOperator filter,
PropertyName property, Literal geometry, boolean swapped,
Object extraData) {
throw new RuntimeException(
"Subclasses must implement this method in order to handle geometries");
}
-
+
+ /**
+ * Handles the more general case of two generic expressions.
+ *
+ * The most common case is two PropertyName expressions, which happens during a spatial join.
+ *
+ */
+ protected Object visitBinarySpatialOperator(BinarySpatialOperator filter, Expression e1,
+ Expression e2, Object extraData) {
+ throw new RuntimeException(
+ "Subclasses must implement this method in order to handle geometries");
+ }
+
+ protected Object visitBinaryTemporalOperator(BinaryTemporalOperator filter,
+ Object extraData) {
+ if (filter == null) {
+ throw new NullPointerException("Null filter");
+ }
+
+ Expression e1 = filter.getExpression1();
+ Expression e2 = filter.getExpression2();
+
+ if (e1 instanceof Literal && e2 instanceof PropertyName) {
+ e1 = (PropertyName) filter.getExpression2();
+ e2 = (Literal) filter.getExpression1();
+ }
+
+ if (e1 instanceof PropertyName && e2 instanceof Literal) {
+ //call the "regular" method
+ return visitBinaryTemporalOperator(filter, (PropertyName)e1, (Literal)e2,
+ filter.getExpression1() instanceof Literal, extraData);
+ }
+ else {
+ //call the join version
+ return visitBinaryTemporalOperator(filter, e1, e2, extraData);
+ }
+ }
+
+ /**
+ * Handles the common case of a PropertyName,Literal geometry binary temporal operator.
+ *
+ * Subclasses should override if they support more temporal operators than what is handled in
+ * this base class.
+ *
+ */
+ protected Object visitBinaryTemporalOperator(BinaryTemporalOperator filter,
+ PropertyName property, Literal temporal, boolean swapped, Object extraData) {
+
+ Class typeContext = null;
+ AttributeDescriptor attType = (AttributeDescriptor)property.evaluate(featureType);
+ if (attType != null) {
+ typeContext = attType.getType().getBinding();
+ }
+
+ //check for time period
+ Period period = null;
+ if (temporal.evaluate(null) instanceof Period) {
+ period = (Period) temporal.evaluate(null);
+ }
+
+ //verify that those filters that require a time period have one
+ if ((filter instanceof Begins || filter instanceof BegunBy || filter instanceof Ends ||
+ filter instanceof EndedBy || filter instanceof During || filter instanceof TContains) &&
+ period == null) {
+ if (period == null) {
+ throw new IllegalArgumentException("Filter requires a time period");
+ }
+ }
+ if (filter instanceof TEquals && period != null) {
+ throw new IllegalArgumentException("TEquals filter does not accept time period");
+ }
+
+ //ensure the time period is the correct argument
+ if ((filter instanceof Begins || filter instanceof Ends || filter instanceof During) &&
+ swapped) {
+ throw new IllegalArgumentException("Time period must be second argument of Filter");
+ }
+ if ((filter instanceof BegunBy || filter instanceof EndedBy || filter instanceof TContains) &&
+ !swapped) {
+ throw new IllegalArgumentException("Time period must be first argument of Filter");
+ }
+
+ try {
+ if (filter instanceof After || filter instanceof Before) {
+ String op = filter instanceof After ? " > " : " < ";
+ String inv = filter instanceof After ? " < " : " > ";
+
+ if (period != null) {
+ out.write("(");
+
+ property.accept(this, extraData);
+ out.write(swapped ? inv : op);
+ visitBegin(period, extraData);
+
+ out.write(" AND ");
+
+ property.accept(this, extraData);
+ out.write(swapped ? inv : op);
+ visitEnd(period, extraData);
+
+ out.write(")");
+ }
+ else {
+ if (swapped) {
+ temporal.accept(this, typeContext);
+ }
+ else {
+ property.accept(this, extraData);
+ }
+
+ out.write(op);
+
+ if (swapped) {
+ property.accept(this, extraData);
+ }
+ else {
+ temporal.accept(this, typeContext);
+ }
+ }
+ }
+ else if (filter instanceof Begins || filter instanceof Ends ||
+ filter instanceof BegunBy || filter instanceof EndedBy ) {
+ property.accept(this, extraData);
+ out.write( " = ");
+
+ if (filter instanceof Begins || filter instanceof BegunBy) {
+ visitBegin(period, extraData);
+ }
+ else {
+ visitEnd(period, extraData);
+ }
+ }
+ else if (filter instanceof During || filter instanceof TContains){
+ property.accept(this, extraData);
+ out.write( " BETWEEN ");
+
+ visitBegin(period, extraData);
+ out.write( " AND ");
+ visitEnd(period, extraData);
+ }
+ else if (filter instanceof TEquals) {
+ property.accept(this, extraData);
+ out.write(" = ");
+ temporal.accept(this, typeContext);
+ }
+ }
+ catch(IOException e) {
+ throw new RuntimeException("Error encoding temporal filter", e);
+ }
+
+ return extraData;
+ }
+
+ void visitBegin(Period p, Object extraData) {
+ filterFactory.literal(p.getBeginning().getPosition().getDate()).accept(this, extraData);
+ }
+
+ void visitEnd(Period p, Object extraData) {
+ filterFactory.literal(p.getEnding().getPosition().getDate()).accept(this, extraData);
+ }
+
+ /**
+ * Handles the general case of two expressions in a binary temporal filter.
+ *
+ * Subclasses should override if they support more temporal operators than what is handled in
+ * this base class.
+ *
+ */
+ protected Object visitBinaryTemporalOperator(BinaryTemporalOperator filter, Expression e1,
+ Expression e2, Object extraData) {
+
+ if (!(filter instanceof After || filter instanceof Before || filter instanceof TEquals)) {
+ throw new IllegalArgumentException("Unsupported filter: " + filter +
+ ". Only After,Before,TEquals supported");
+ }
+
+ String op = filter instanceof After ? ">" : filter instanceof Before ? "<" : "=";
+
+ try {
+ e1.accept(this, extraData);
+ out.write(" " + op + " ");
+ e2.accept(this, extraData);
+ }
+ catch(IOException e) {
+ return new RuntimeException("Error encoding temporal filter", e);
+ }
+ return extraData;
+ }
+
/**
* Encodes a null filter value. The current implementation
* does exactly nothing.
@@ -928,7 +1147,17 @@ public class FilterToSQL implements FilterVisitor, ExpressionVisitor {
if(extraData instanceof Class) {
target = (Class) extraData;
}
+
try {
+ SimpleFeatureType featureType = this.featureType;
+
+ //check for join
+ if (expression instanceof JoinPropertyName) {
+ //encode the prefix
+ out.write(escapeName(((JoinPropertyName)expression).getAlias()));
+ out.write(".");
+ }
+
//first evaluate expression against feautre type get the attribute,
// this handles xpath
AttributeDescriptor attribute = null;
@@ -1003,8 +1232,9 @@ public class FilterToSQL implements FilterVisitor, ExpressionVisitor {
// handle geometry case
if (literal instanceof Geometry) {
// call this method for backwards compatibility with subclasses
- visitLiteralGeometry(CommonFactoryFinder.getFilterFactory(null).literal(literal));
- } else {
+ visitLiteralGeometry(filterFactory.literal(literal));
+ }
+ else {
// write out the literal allowing subclasses to override this
// behaviour (for writing out dates and the like using the BDMS custom functions)
writeLiteral(literal);
@@ -1088,7 +1318,12 @@ public class FilterToSQL implements FilterVisitor, ExpressionVisitor {
throw new RuntimeException(
"Subclasses must implement this method in order to handle geometries");
}
-
+
+ protected void visitLiteralTimePeriod(Period expression) {
+ throw new RuntimeException("Time periods not supported, subclasses must implement this " +
+ "method to support encoding timeperiods");
+ }
+
public Object visit(Add expression, Object extraData) {
return visit((BinaryExpression)expression, "+", extraData);
}
@@ -1211,46 +1446,46 @@ public class FilterToSQL implements FilterVisitor, ExpressionVisitor {
//temporal filters, not supported
public Object visit(After after, Object extraData) {
- throw new UnsupportedOperationException("Temporal filter After not implemented");
+ return visitBinaryTemporalOperator(after, extraData);
}
public Object visit(AnyInteracts anyInteracts, Object extraData) {
- throw new UnsupportedOperationException("Temporal filter AnyInteracts not implemented");
+ return visitBinaryTemporalOperator(anyInteracts, extraData);
}
public Object visit(Before before, Object extraData) {
- throw new UnsupportedOperationException("Temporal filter Before not implemented");
+ return visitBinaryTemporalOperator(before, extraData);
}
public Object visit(Begins begins, Object extraData) {
- throw new UnsupportedOperationException("Temporal filter Begins not implemented");
+ return visitBinaryTemporalOperator(begins, extraData);
}
public Object visit(BegunBy begunBy, Object extraData) {
- throw new UnsupportedOperationException("Temporal filter BegunBy not implemented");
+ return visitBinaryTemporalOperator(begunBy, extraData);
}
public Object visit(During during, Object extraData) {
- throw new UnsupportedOperationException("Temporal filter During not implemented");
+ return visitBinaryTemporalOperator(during, extraData);
}
public Object visit(EndedBy endedBy, Object extraData) {
- throw new UnsupportedOperationException("Temporal filter EndedBy not implemented");
+ return visitBinaryTemporalOperator(endedBy, extraData);
}
public Object visit(Ends ends, Object extraData) {
- throw new UnsupportedOperationException("Temporal filter Ends not implemented");
+ return visitBinaryTemporalOperator(ends, extraData);
}
public Object visit(Meets meets, Object extraData) {
- throw new UnsupportedOperationException("Temporal filter Meets not implemented");
+ return visitBinaryTemporalOperator(meets, extraData);
}
public Object visit(MetBy metBy, Object extraData) {
- throw new UnsupportedOperationException("Temporal filter MetBy not implemented");
+ return visitBinaryTemporalOperator(metBy, extraData);
}
public Object visit(OverlappedBy overlappedBy, Object extraData) {
- throw new UnsupportedOperationException("Temporal filter OverlappedBy not implemented");
+ return visitBinaryTemporalOperator(overlappedBy, extraData);
}
public Object visit(TContains contains, Object extraData) {
- throw new UnsupportedOperationException("Temporal filter TContains not implemented");
+ return visitBinaryTemporalOperator(contains, extraData);
}
public Object visit(TEquals equals, Object extraData) {
- throw new UnsupportedOperationException("Temporal filter TEquals not implemented");
+ return visitBinaryTemporalOperator(equals, extraData);
}
public Object visit(TOverlaps contains, Object extraData) {
- throw new UnsupportedOperationException("Temporal filter TOverlaps not implemented");
+ return visitBinaryTemporalOperator(contains, extraData);
}
/**
@@ -1321,7 +1556,7 @@ public class FilterToSQL implements FilterVisitor, ExpressionVisitor {
return s;
}
}
-
+
/**
* Current field encoder
*/
diff --git a/modules/library/jdbc/src/main/java/org/geotools/jdbc/JDBCDataStore.java b/modules/library/jdbc/src/main/java/org/geotools/jdbc/JDBCDataStore.java
index 1db084a..1e6b92c 100644
--- a/modules/library/jdbc/src/main/java/org/geotools/jdbc/JDBCDataStore.java
+++ b/modules/library/jdbc/src/main/java/org/geotools/jdbc/JDBCDataStore.java
@@ -45,7 +45,6 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import javax.sql.DataSource;
-import javax.xml.transform.TransformerException;
import org.geotools.data.DataStore;
import org.geotools.data.DefaultQuery;
@@ -72,6 +71,7 @@ import org.geotools.feature.simple.SimpleFeatureBuilder;
import org.geotools.feature.visitor.CountVisitor;
import org.geotools.filter.FilterCapabilities;
import org.geotools.geometry.jts.ReferencedEnvelope;
+import org.geotools.jdbc.JoinInfo.JoinPart;
import org.geotools.referencing.CRS;
import org.geotools.util.Converters;
import org.opengis.feature.FeatureVisitor;
@@ -155,7 +155,12 @@ public final class JDBCDataStore extends ContentDataStore
* type.
*/
public static final String JDBC_NATIVE_TYPENAME = "org.geotools.jdbc.nativeTypeName";
-
+
+ /**
+ * Used to specify the column alias to use when encoding a column in a select
+ */
+ public static final String JDBC_COLUMN_ALIAS = "org.geotools.jdbc.columnAlias";
+
/**
* name of table to use to store geometries when {@link #associations}
* is set.
@@ -265,6 +270,14 @@ public final class JDBCDataStore extends ContentDataStore
*/
protected Map virtualTables = new ConcurrentHashMap();
+ public JDBCFeatureSource getAbsoluteFeatureSource(String typeName) throws IOException {
+ ContentFeatureSource featureSource = getFeatureSource(typeName);
+ if (featureSource instanceof JDBCFeatureSource) {
+ return (JDBCFeatureSource) featureSource;
+ }
+ return ((JDBCFeatureStore)featureSource).getFeatureSource();
+ }
+
/**
* Adds a virtual table to the data store. If a virtual table with the same name was registered this
* method will replace it with the new one.
@@ -1636,9 +1649,23 @@ public final class JDBCDataStore extends ContentDataStore
}
/**
- * Encodes a feature id from a primary key and result set values.
+ * Calls through to:
+ *
+ * encodeFID(pkey, rs, 0);
+ *
*/
- protected String encodeFID( PrimaryKey pkey, ResultSet rs ) throws SQLException, IOException {
+ protected String encodeFID(PrimaryKey pkey, ResultSet rs) throws SQLException, IOException {
+ return encodeFID(pkey, rs, 0);
+ }
+
+ /**
+ * Encodes a feature id from a primary key and result set values.
+ *
+ * offset specifies where in the result set to start from when reading values for the
+ * primary key.
+ *
+ */
+ protected String encodeFID( PrimaryKey pkey, ResultSet rs, int offset ) throws SQLException, IOException {
// no pk columns
if(pkey.getColumns().isEmpty()) {
return SimpleFeatureBuilder.createDefaultFeatureId();
@@ -1646,17 +1673,17 @@ public final class JDBCDataStore extends ContentDataStore
// just one, no need to build support structures
if(pkey.getColumns().size() == 1)
- return rs.getString(1);
+ return rs.getString(offset+1);
// more than one
List
*
*
- *
+ * @deprecated use {@link #encodeGeometryColumnGeneralized(GeometryDescriptor, String, int, StringBuffer, Double)}
*/
- public void encodeGeometryColumnGeneralized(GeometryDescriptor gatt, int srid,StringBuffer sql, Double distance) {
+ public final void encodeGeometryColumnGeneralized(GeometryDescriptor gatt, int srid,StringBuffer sql, Double distance) {
+ throw new UnsupportedOperationException("Geometry generalization not supported");
+ }
+
+ public void encodeGeometryColumnGeneralized(GeometryDescriptor gatt, String prefix, int srid,
+ StringBuffer sql, Double distance) {
throw new UnsupportedOperationException("Geometry generalization not supported");
}
@@ -687,12 +747,16 @@ public abstract class SQLDialect {
* If not supported, subclasses should not implement
* Only called if {@link Hints#GEOMETRY_SIMPLIFICATION is supported}
* @see SQLDialect#encodeGeometryColumnGeneralized(GeometryDescriptor, StringBuffer, Double)
- *
+ * @deprecated use {@link #encodeGeometryColumnSimplified(GeometryDescriptor, String, int, StringBuffer, Double)}
*/
public void encodeGeometryColumnSimplified(GeometryDescriptor gatt, int srid,StringBuffer sql, Double distance) {
throw new UnsupportedOperationException("Geometry simplification not supported");
}
+ public void encodeGeometryColumnSimplified(GeometryDescriptor gatt, String prefix, int srid,
+ StringBuffer sql, Double distance) {
+ throw new UnsupportedOperationException("Geometry simplification not supported");
+ }
/**
* Decodes a geometry value from the result of a query.
@@ -755,11 +819,26 @@ public abstract class SQLDialect {
*
*/
public void encodePrimaryKey(String column, StringBuffer sql) {
- encodeColumnName( column, sql );
+ encodeColumnName( null, column, sql );
sql.append( " INTEGER PRIMARY KEY" );
}
/**
+ * Encodes the syntax for a join between two tables.
+ */
+ public void encodeJoin(Type joinType, StringBuffer sql) {
+ switch(joinType) {
+ case INNER:
+ sql.append("INNER"); break;
+ case OUTER:
+ sql.append("LEFT OUTER"); break;
+ default:
+ throw new IllegalArgumentException("Join type " + joinType + " not supported");
+ }
+ sql.append(" JOIN");
+ }
+
+ /**
* Encodes anything post a column in a CREATE TABLE statement.
*
* This is appended after the column name and type. Subclasses may choose to override
@@ -1049,5 +1128,4 @@ public abstract class SQLDialect {
public boolean isAutoCommitQuery() {
return false;
}
-
}
diff --git a/modules/library/jdbc/src/test/java/org/geotools/data/jdbc/FilterToSQLTest.java b/modules/library/jdbc/src/test/java/org/geotools/data/jdbc/FilterToSQLTest.java
index c4e2802..6b5d816 100644
--- a/modules/library/jdbc/src/test/java/org/geotools/data/jdbc/FilterToSQLTest.java
+++ b/modules/library/jdbc/src/test/java/org/geotools/data/jdbc/FilterToSQLTest.java
@@ -159,4 +159,14 @@ public class FilterToSQLTest extends TestCase {
encoder.encode(equal);
assertEquals("WHERE testAttr = testAttr + 5", output.toString());
}
+
+ public void testInline() throws Exception {
+ PropertyIsEqualTo equal = filterFac.equal(filterFac.property("testAttr"), filterFac.literal(5), false);
+ StringWriter output = new StringWriter();
+ FilterToSQL encoder = new FilterToSQL(output);
+ encoder.setInline(true);
+
+ encoder.encode(equal);
+ assertEquals("testAttr = 5", output.toString());
+ }
}
diff --git a/modules/library/jdbc/src/test/java/org/geotools/jdbc/EqualsFunction.java b/modules/library/jdbc/src/test/java/org/geotools/jdbc/EqualsFunction.java
new file mode 100644
index 0000000..40bf629
--- /dev/null
+++ b/modules/library/jdbc/src/test/java/org/geotools/jdbc/EqualsFunction.java
@@ -0,0 +1,45 @@
+/*
+ * GeoTools - The Open Source Java GIS Toolkit
+ * http://geotools.org
+ *
+ * (C) 2002-2011, Open Source Geospatial Foundation (OSGeo)
+ *
+ * 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.
+ */
+
+package org.geotools.jdbc;
+
+import org.geotools.filter.FunctionImpl;
+import org.geotools.util.Converters;
+import org.opengis.filter.expression.PropertyName;
+
+/**
+ * A test function used for jdbc tests.
+ *
+ * @author Justin Deoliveira, OpenGeo
+ *
+ */
+public class EqualsFunction extends FunctionImpl {
+
+ public EqualsFunction() {
+ setName("__equals");
+ }
+
+ @Override
+ public Object evaluate(Object object) {
+ PropertyName name = (PropertyName) getParameters().get(0);
+ Object literal = getParameters().get(1).evaluate(null);
+
+ Object o = name.evaluate(object);
+ return o.equals(Converters.convert(literal, o.getClass()));
+ }
+
+}
diff --git a/modules/library/jdbc/src/test/java/org/geotools/jdbc/JDBCForeignKeyTest.java b/modules/library/jdbc/src/test/java/org/geotools/jdbc/JDBCForeignKeyTest.java
deleted file mode 100644
index 825f86f..0000000
--- a/modules/library/jdbc/src/test/java/org/geotools/jdbc/JDBCForeignKeyTest.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * GeoTools - The Open Source Java GIS Toolkit
- * http://geotools.org
- *
- * (C) 2002-2008, Open Source Geospatial Foundation (OSGeo)
- *
- * 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.
- */
-package org.geotools.jdbc;
-
-import org.geotools.data.DefaultQuery;
-import org.geotools.data.FeatureReader;
-import org.geotools.data.Transaction;
-import org.geotools.factory.Hints;
-import org.opengis.feature.Association;
-import org.opengis.feature.Property;
-import org.opengis.feature.simple.SimpleFeature;
-import org.opengis.feature.simple.SimpleFeatureType;
-import org.opengis.feature.type.AttributeDescriptor;
-
-
-/**
- *
- *
- * @source $URL$
- */
-public abstract class JDBCForeignKeyTest extends JDBCTestSupport {
- protected void connect() throws Exception {
- super.connect();
-
- dataStore.setAssociations(true);
- }
-
- public void testGetSchema() throws Exception {
- SimpleFeatureType featureType = dataStore.getSchema("fk");
-
- assertNotNull(featureType);
-
- AttributeDescriptor att = featureType.getDescriptor("ft1");
- assertNotNull(att);
-
- assertEquals(Association.class, att.getType().getBinding());
- }
-
- public void testGetFeatures() throws Exception {
- Hints hints = new Hints(Hints.ASSOCIATION_TRAVERSAL_DEPTH, new Integer(1));
-
- DefaultQuery query = new DefaultQuery();
- query.setTypeName("fk");
- query.setHints(hints);
-
- FeatureReader reader = dataStore.getFeatureReader(query, Transaction.AUTO_COMMIT);
- assertTrue(reader.hasNext());
-
- SimpleFeature feature = reader.next();
- Association association = (Association) feature.getAttribute("ft1");
- assertEquals("ft1.0", association.getUserData().get("gml:id"));
-
- SimpleFeature associated = (SimpleFeature) association.getValue();
- assertNotNull(associated);
-
- assertEquals("zero", associated.getAttribute("stringProperty"));
-
- Property attribute = feature.getProperty("ft1");
- assertEquals("ft1.0", attribute.getUserData().get("gml:id"));
-
- reader.close();
- }
-
- public void testGetFeaturesWithZeroDepth() throws Exception {
- Hints hints = new Hints(Hints.ASSOCIATION_TRAVERSAL_DEPTH, new Integer(0));
-
- DefaultQuery query = new DefaultQuery();
- query.setTypeName("fk");
- query.setHints(hints);
-
- FeatureReader reader = dataStore.getFeatureReader(query, Transaction.AUTO_COMMIT);
- assertTrue(reader.hasNext());
-
- SimpleFeature feature = reader.next();
- Association association = (Association) feature.getAttribute("ft1");
- assertNull(association.getValue());
-
- Property attribute = feature.getProperty("ft1");
- assertEquals("ft1.0", attribute.getUserData().get("gml:id"));
-
- reader.close();
- }
-}
diff --git a/modules/library/jdbc/src/test/java/org/geotools/jdbc/JDBCGeometryAssociationTestSupport.java b/modules/library/jdbc/src/test/java/org/geotools/jdbc/JDBCGeometryAssociationTestSupport.java
deleted file mode 100644
index 1b8d6e6..0000000
--- a/modules/library/jdbc/src/test/java/org/geotools/jdbc/JDBCGeometryAssociationTestSupport.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * GeoTools - The Open Source Java GIS Toolkit
- * http://geotools.org
- *
- * (C) 2002-2008, Open Source Geospatial Foundation (OSGeo)
- *
- * 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.
- */
-package org.geotools.jdbc;
-
-import java.util.Map;
-
-import org.geotools.data.DefaultQuery;
-import org.geotools.data.FeatureReader;
-import org.geotools.data.Transaction;
-import org.geotools.factory.Hints;
-import org.opengis.feature.simple.SimpleFeature;
-import org.opengis.feature.simple.SimpleFeatureType;
-import org.opengis.filter.identity.GmlObjectId;
-
-import com.vividsolutions.jts.geom.Coordinate;
-import com.vividsolutions.jts.geom.Geometry;
-import com.vividsolutions.jts.geom.MultiPoint;
-import com.vividsolutions.jts.geom.Point;
-
-
-/**
- *
- *
- * @source $URL$
- */
-public abstract class JDBCGeometryAssociationTestSupport extends JDBCTestSupport {
- protected void connect() throws Exception {
- super.connect();
-
- dataStore.setAssociations(true);
- }
-
- public void testGetFeatureNoAssociation() throws Exception {
- Hints hints = new Hints(Hints.ASSOCIATION_TRAVERSAL_DEPTH, new Integer(1));
-
- DefaultQuery query = new DefaultQuery();
- query.setTypeName("ga");
- query.setHints(hints);
-
- FeatureReader reader = dataStore.getFeatureReader(query, Transaction.AUTO_COMMIT);
- assertTrue(reader.hasNext());
-
- SimpleFeature feature = (SimpleFeature) reader.next();
- assertNotNull(feature);
-
- assertEquals("ga.0", feature.getID());
-
- Geometry g = (Geometry) feature.getDefaultGeometry();
- assertNotNull(g);
- assertEquals(new Coordinate(0, 0), g.getCoordinate());
-
- Map ud = (Map) g.getUserData();
- assertEquals("0", ud.get("gml:id"));
- reader.close();
- }
-
- public void testGetFeatureWithAssociation() throws Exception {
- Hints hints = new Hints(Hints.ASSOCIATION_TRAVERSAL_DEPTH, new Integer(1));
-
- DefaultQuery query = new DefaultQuery();
- query.setTypeName("ga");
- query.setHints(hints);
-
- FeatureReader reader = dataStore.getFeatureReader(query, Transaction.AUTO_COMMIT);
- assertTrue(reader.hasNext());
- reader.next();
-
- assertTrue(reader.hasNext());
-
- SimpleFeature feature = (SimpleFeature) reader.next();
- assertNotNull(feature);
-
- assertEquals("ga.1", feature.getID());
-
- Geometry g = (Geometry) feature.getDefaultGeometry();
- assertNotNull(g);
- assertEquals(new Coordinate(1, 1), g.getCoordinate());
- assertTrue(g.getUserData() instanceof Map);
- assertEquals("1", ((Map) g.getUserData()).get("gml:id"));
-
- reader.close();
-
- //test with zero dpeth
- query.setHints(new Hints(Hints.ASSOCIATION_TRAVERSAL_DEPTH, new Integer(0)));
- reader = dataStore.getFeatureReader(query, Transaction.AUTO_COMMIT);
-
- assertTrue(reader.hasNext());
- reader.next();
-
- assertTrue(reader.hasNext());
-
- feature = (SimpleFeature) reader.next();
- assertNotNull(feature);
-
- assertEquals("ga.1", feature.getID());
-
- g = (Geometry) feature.getDefaultGeometry();
- assertNotNull(g);
- assertTrue(g.isEmpty());
- //assertTrue( g instanceof NullGeometry );
- assertTrue(g.getUserData() instanceof Map);
- assertEquals("1", ((Map) g.getUserData()).get("gml:id"));
-
- reader.close();
- }
-
- public void testMultiGeometryAssociation() throws Exception {
- Hints hints = new Hints(Hints.ASSOCIATION_TRAVERSAL_DEPTH, new Integer(1));
-
- DefaultQuery query = new DefaultQuery();
- query.setTypeName("ga");
- query.setHints(hints);
-
- FeatureReader reader = dataStore.getFeatureReader(query, Transaction.AUTO_COMMIT);
- assertTrue(reader.hasNext());
- reader.next();
- assertTrue(reader.hasNext());
- reader.next();
-
- assertTrue(reader.hasNext());
-
- SimpleFeature feature = reader.next();
-
- Geometry g = (Geometry) feature.getDefaultGeometry();
- assertNotNull(g);
- assertTrue(g instanceof MultiPoint);
-
- MultiPoint mp = (MultiPoint) g;
- assertEquals("2", ((Map) mp.getUserData()).get("gml:id"));
-
- assertEquals(2, mp.getNumGeometries());
-
- Point p = (Point) mp.getGeometryN(0);
- assertEquals(new Coordinate(0, 0), p.getCoordinate());
- assertEquals("0", ((Map) p.getUserData()).get("gml:id"));
-
- p = (Point) mp.getGeometryN(1);
- assertEquals(new Coordinate(1, 1), p.getCoordinate());
- assertEquals("1", ((Map) p.getUserData()).get("gml:id"));
-
- reader.close();
- }
-
- public void testGetGmlObjectGeometry() throws Exception {
- GmlObjectId id = dataStore.getFilterFactory().gmlObjectId("0");
- Object o = dataStore.getGmlObject( id, null);
-
- assertNotNull( o );
- assertTrue( o instanceof Point );
- assertEquals( new Coordinate( 0 , 0 ), ((Point)o).getCoordinate() );
-
- id = dataStore.getFilterFactory().gmlObjectId( "ft1.0" );
- o = dataStore.getGmlObject( id, null);
- assertNotNull( o );
- assertTrue( o instanceof SimpleFeature );
- }
-}
diff --git a/modules/library/jdbc/src/test/java/org/geotools/jdbc/JDBCJoinTest.java b/modules/library/jdbc/src/test/java/org/geotools/jdbc/JDBCJoinTest.java
new file mode 100644
index 0000000..dcf7649
--- /dev/null
+++ b/modules/library/jdbc/src/test/java/org/geotools/jdbc/JDBCJoinTest.java
@@ -0,0 +1,435 @@
+/*
+ * GeoTools - The Open Source Java GIS Toolkit
+ * http://geotools.org
+ *
+ * (C) 2002-2011, Open Source Geospatial Foundation (OSGeo)
+ *
+ * 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.
+ */
+package org.geotools.jdbc;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.geotools.data.Join;
+import org.geotools.data.Query;
+import org.geotools.data.Join.Type;
+import org.geotools.data.simple.SimpleFeatureCollection;
+import org.geotools.data.simple.SimpleFeatureIterator;
+import org.opengis.feature.simple.SimpleFeature;
+import org.opengis.filter.Filter;
+import org.opengis.filter.FilterFactory;
+import org.opengis.filter.FilterFactory2;
+import org.opengis.filter.sort.SortBy;
+import org.opengis.filter.sort.SortOrder;
+
+public abstract class JDBCJoinTest extends JDBCTestSupport {
+
+ @Override
+ protected abstract JDBCJoinTestSetup createTestSetup();
+
+ public void testSimpleJoin() throws Exception {
+ doTestSimpleJoin(false);
+ doTestSimpleJoin(true);
+ }
+
+ void doTestSimpleJoin(boolean exposePrimaryKeys) throws Exception {
+ dataStore.setExposePrimaryKeyColumns(exposePrimaryKeys);
+ SimpleFeatureIterator ita =
+ dataStore.getFeatureSource(tname("ft1")).getFeatures().features();
+ SimpleFeatureIterator itb =
+ dataStore.getFeatureSource(tname("ftjoin")).getFeatures().features();
+
+ FilterFactory ff = dataStore.getFilterFactory();
+ Query q = new Query(tname("ft1"));
+ q.getJoins().add(new Join(tname("ftjoin"),
+ ff.equal(ff.property(aname("stringProperty")), ff.property(aname("name")), true)));
+
+ SimpleFeatureCollection features = dataStore.getFeatureSource(tname("ft1")).getFeatures(q);
+ assertEquals(dataStore.getFeatureSource(tname("ft1")).getFeatures(q).size(), features.size());
+
+ SimpleFeatureIterator it = features.features();
+ try {
+ assertTrue(it.hasNext() && ita.hasNext() && itb.hasNext());
+
+ while(it.hasNext()) {
+ SimpleFeature f = it.next();
+ assertEquals(5, f.getAttributeCount());
+
+ SimpleFeature g = (SimpleFeature) f.getAttribute(tname("ftjoin"));
+
+ SimpleFeature a = ita.next();
+ SimpleFeature b = itb.next();
+
+ for (int i = 0; i < a.getAttributeCount(); i++) {
+ assertAttributeValuesEqual(a.getAttribute(i), f.getAttribute(i));
+ }
+ for (int i = 0; i < b.getAttributeCount(); i++) {
+ assertAttributeValuesEqual(b.getAttribute(i), g.getAttribute(i));
+ }
+ }
+ }
+ finally {
+ it.close();
+ ita.close();
+ itb.close();
+ }
+ }
+
+ public void testSimpleJoinWithFilter() throws Exception {
+ doTestSimpleJoinWithFilter(false);
+ doTestSimpleJoinWithFilter(true);
+ }
+
+ void doTestSimpleJoinWithFilter(boolean exposePrimaryKeys) throws Exception {
+ dataStore.setExposePrimaryKeyColumns(exposePrimaryKeys);
+ FilterFactory ff = dataStore.getFilterFactory();
+ Query q = new Query(tname("ft1"));
+ q.getJoins().add(new Join(tname("ftjoin"),
+ ff.equal(ff.property(aname("stringProperty")), ff.property(aname("name")), true)));
+ q.setFilter(ff.equal(ff.property(aname("stringProperty")), ff.literal("two"), true));
+
+ SimpleFeatureCollection features = dataStore.getFeatureSource(tname("ft1")).getFeatures(q);
+ assertEquals(1, features.size());
+
+ SimpleFeatureIterator it = features.features();
+ try {
+ SimpleFeature f = it.next();
+ assertEquals(5, f.getAttributeCount());
+ assertEquals(2, ((Number)f.getAttribute(aname("intProperty"))).intValue());
+ assertEquals("two", f.getAttribute(aname("stringProperty")));
+
+ SimpleFeature g = (SimpleFeature) f.getAttribute(aname("ftjoin"));
+ assertEquals(3, g.getAttributeCount());
+ assertEquals(2, ((Number)g.getAttribute(aname("id"))).intValue());
+ assertEquals("two", g.getAttribute(aname("name")));
+ }
+ finally {
+ it.close();
+ }
+ }
+
+ public void testSimpleJoinWithFilterNoProperties() throws Exception {
+ doTestSimpleJoinWithFilterNoProperties(false);
+ doTestSimpleJoinWithFilterNoProperties(true);
+ }
+
+ void doTestSimpleJoinWithFilterNoProperties(boolean exposePrimaryKeys) throws Exception {
+ dataStore.setExposePrimaryKeyColumns(exposePrimaryKeys);
+ FilterFactory ff = dataStore.getFilterFactory();
+ Query q = new Query(tname("ft1"));
+ Join j = new Join(tname("ftjoin"),
+ ff.equal(ff.property(aname("stringProperty")), ff.property(aname("name")), true));
+ j.setProperties(Query.NO_PROPERTIES);
+ q.getJoins().add(j);
+ q.setFilter(ff.equal(ff.property(aname("stringProperty")), ff.literal("two"), true));
+
+ SimpleFeatureCollection features = dataStore.getFeatureSource(tname("ft1")).getFeatures(q);
+ assertEquals(1, features.size());
+
+ SimpleFeatureIterator it = features.features();
+ try {
+ SimpleFeature f = it.next();
+ assertEquals(5, f.getAttributeCount());
+ assertEquals(2, ((Number)f.getAttribute(aname("intProperty"))).intValue());
+ assertEquals("two", f.getAttribute(aname("stringProperty")));
+
+ SimpleFeature g = (SimpleFeature) f.getAttribute(aname("ftjoin"));
+ assertEquals(0, g.getAttributeCount());
+ }
+ finally {
+ it.close();
+ }
+ }
+
+ public void testSimpleJoinWithFilterCount() throws Exception {
+ doTestSimpleJoinWithFilterCount(false);
+ doTestSimpleJoinWithFilterCount(true);
+ }
+
+ void doTestSimpleJoinWithFilterCount(boolean exposePrimaryKeys) throws Exception {
+ dataStore.setExposePrimaryKeyColumns(exposePrimaryKeys);
+ FilterFactory ff = dataStore.getFilterFactory();
+ Query q = new Query(tname("ft1"));
+ Join j = new Join(tname("ftjoin"),
+ ff.equal(ff.property(aname("stringProperty")), ff.property(aname("name")), true));
+ j.filter(ff.greater(ff.property(aname("id")), ff.literal(1)));
+ q.getJoins().add(j);
+ q.setFilter(ff.less(ff.property(aname("intProperty")), ff.literal(3)));
+
+ assertEquals(1, dataStore.getFeatureSource(tname("ft1")).getCount(q));
+ }
+
+ public void testSimpleJoinWithPostFilter() throws Exception {
+ doTestSimpleJoinWithPostFilter(false);
+ doTestSimpleJoinWithPostFilter(true);
+ }
+
+ void doTestSimpleJoinWithPostFilter(boolean exposePrimaryKeys) throws Exception {
+ dataStore.setExposePrimaryKeyColumns(exposePrimaryKeys);
+ FilterFactory ff = dataStore.getFilterFactory();
+
+ Filter j = ff.equal(ff.property(aname("stringProperty")), ff.property(aname("name")), true);
+ Query q = new Query(tname("ft1"));
+ q.getJoins().add(new Join(tname("ftjoin"), j));
+ q.setFilter(ff.equal(
+ ff.function("__equals", ff.property(aname("stringProperty")), ff.literal("one")),
+ ff.literal(true), true));
+
+ SimpleFeatureCollection features = dataStore.getFeatureSource(tname("ft1")).getFeatures(q);
+ assertEquals(1, features.size());
+
+ //test with post filter on table being joined
+ q = new Query(tname("ft1"));
+ Join join = new Join(tname("ftjoin"), j);
+ join.filter(ff.equal(
+ ff.function("__equals", ff.property(aname("name")), ff.literal("one")),
+ ff.literal(true), true));
+ q.getJoins().add(join);
+
+ features = dataStore.getFeatureSource(tname("ft1")).getFeatures(q);
+ assertEquals(1, features.size());
+ }
+
+ public void testSimpleJoinWithPostFilterNoProperties() throws Exception {
+ doTestSimpleJoinWithPostFilterNoProperties(false);
+ doTestSimpleJoinWithPostFilterNoProperties(true);
+ }
+
+ void doTestSimpleJoinWithPostFilterNoProperties(boolean exposePrimaryKeys) throws Exception {
+ dataStore.setExposePrimaryKeyColumns(exposePrimaryKeys);
+ FilterFactory ff = dataStore.getFilterFactory();
+
+ Filter j = ff.equal(ff.property(aname("stringProperty")), ff.property(aname("name")), true);
+ Query q = new Query(tname("ft1"));
+ Join join = new Join(tname("ftjoin"), j);
+ join.setProperties(Query.NO_PROPERTIES);
+ q.getJoins().add(join);
+ q.setFilter(ff.equal(
+ ff.function("__equals", ff.property(aname("stringProperty")), ff.literal("one")),
+ ff.literal(true), true));
+
+ SimpleFeatureCollection features = dataStore.getFeatureSource(tname("ft1")).getFeatures(q);
+ assertEquals(1, features.size());
+
+ //test with post filter on table being joined
+ q = new Query(tname("ft1"));
+ join = new Join(tname("ftjoin"), j);
+ join.setProperties(Query.NO_PROPERTIES);
+ join.filter(ff.equal(
+ ff.function("__equals", ff.property(aname("name")), ff.literal("one")),
+ ff.literal(true), true));
+ q.getJoins().add(join);
+
+ features = dataStore.getFeatureSource(tname("ft1")).getFeatures(q);
+ assertEquals(1, features.size());
+ }
+
+ public void testSimpleJoinWithSort() throws Exception {
+ doTestSimpleJoinWithSort(false);
+ doTestSimpleJoinWithSort(true);
+ }
+
+ void doTestSimpleJoinWithSort(boolean exposePrimaryKeys) throws Exception {
+ dataStore.setExposePrimaryKeyColumns(exposePrimaryKeys);
+ FilterFactory ff = dataStore.getFilterFactory();
+
+ Filter j = ff.equal(ff.property(aname("stringProperty")), ff.property(aname("name")), true);
+ Query q = new Query(tname("ft1"));
+ q.getJoins().add(new Join(tname("ftjoin"), j));
+ q.setSortBy(new SortBy[]{ff.sort(aname("intProperty"), SortOrder.DESCENDING)});
+
+ SimpleFeatureCollection features = dataStore.getFeatureSource(tname("ft1")).getFeatures(q);
+ SimpleFeatureIterator it = features.features();
+ try {
+ assertTrue(it.hasNext());
+ assertEquals("two", it.next().getAttribute(aname("stringProperty")));
+ assertTrue(it.hasNext());
+ assertEquals("one", it.next().getAttribute(aname("stringProperty")));
+ assertTrue(it.hasNext());
+ assertEquals("zero", it.next().getAttribute(aname("stringProperty")));
+ }
+ finally {
+ it.close();
+ }
+ }
+
+ public void testSimpleJoinWithLimitOffset() throws Exception {
+ doTestSimpleJoinWithLimitOffset(false);
+ doTestSimpleJoinWithLimitOffset(true);
+ }
+
+ void doTestSimpleJoinWithLimitOffset(boolean exposePrimaryKeys) throws Exception {
+ dataStore.setExposePrimaryKeyColumns(exposePrimaryKeys);
+ FilterFactory ff = dataStore.getFilterFactory();
+
+ Filter j = ff.equal(ff.property(aname("stringProperty")), ff.property(aname("name")), true);
+ Query q = new Query(tname("ft1"));
+ q.getJoins().add(new Join(tname("ftjoin"), j));
+ q.setFilter(ff.greater(ff.property(aname("intProperty")), ff.literal(0)));
+ q.setStartIndex(1);
+ q.setSortBy(new SortBy[]{ff.sort(aname("intProperty"), SortOrder.ASCENDING)});
+
+ SimpleFeatureCollection features = dataStore.getFeatureSource(tname("ft1")).getFeatures(q);
+ assertEquals(1, features.size());
+
+ SimpleFeatureIterator it = features.features();
+ try {
+ assertTrue(it.hasNext());
+
+ SimpleFeature f = it.next();
+ assertEquals("two", f.getAttribute(aname("stringProperty")));
+
+ SimpleFeature g = (SimpleFeature) f.getAttribute(aname("ftjoin"));
+ assertEquals("two", g.getAttribute(aname("name")));
+ }
+ finally {
+ it.close();
+ }
+ }
+
+ public void testSelfJoin() throws Exception {
+ doTestSelfJoin(false);
+ doTestSelfJoin(true);
+ }
+
+ public void doTestSelfJoin(boolean exposePrimaryKeys) throws Exception {
+ dataStore.setExposePrimaryKeyColumns(exposePrimaryKeys);
+ FilterFactory ff = dataStore.getFilterFactory();
+ Query q = new Query(tname("ft1"));
+ q.getJoins().add(new Join(tname("ft1"),
+ ff.equal(ff.property(aname("intProperty")), ff.property(aname("foo.intProperty")), true)).alias(aname("foo")));
+ q.setFilter(ff.equal(ff.property(aname("stringProperty")), ff.literal("two"), true));
+
+ SimpleFeatureCollection features = dataStore.getFeatureSource(tname("ft1")).getFeatures(q);
+ assertEquals(1, features.size());
+
+ SimpleFeatureIterator it = features.features();
+ try {
+ assertTrue(it.hasNext());
+
+ SimpleFeature f = it.next();
+ assertEquals(5, f.getAttributeCount());
+ assertEquals(2, ((Number)f.getAttribute(aname("intProperty"))).intValue());
+ assertEquals("two", f.getAttribute(aname("stringProperty")));
+
+ SimpleFeature g = (SimpleFeature) f.getAttribute(aname("foo"));
+ assertEquals(4, g.getAttributeCount());
+ assertEquals(2, ((Number)g.getAttribute(aname("intProperty"))).intValue());
+ assertEquals("two", g.getAttribute(aname("stringProperty")));
+ }
+ finally {
+ it.close();
+ }
+ }
+
+ public void testSpatialJoin() throws Exception {
+ doTestSpatialJoin(false);
+ doTestSpatialJoin(true);
+ }
+
+ void doTestSpatialJoin(boolean exposePrimaryKeys) throws Exception {
+ dataStore.setExposePrimaryKeyColumns(exposePrimaryKeys);
+ FilterFactory2 ff = (FilterFactory2) dataStore.getFilterFactory();
+ Query q = new Query(tname("ft1"));
+ q.setPropertyNames(Arrays.asList(aname("geometry"), aname("intProperty")));
+ q.setSortBy(new SortBy[]{ff.sort(aname("intProperty"), SortOrder.ASCENDING)});
+ q.getJoins().add(new Join(tname("ftjoin"),
+ ff.contains(ff.property(aname("geom")), ff.property(aname("geometry")))));
+
+ SimpleFeatureCollection features = dataStore.getFeatureSource(tname("ft1")).getFeatures(q);
+ assertEquals(6, features.size());
+
+ SimpleFeatureIterator it = features.features();
+ SimpleFeature f;
+ try {
+ Set s = new HashSet(Arrays.asList("zero", "one", "two"));
+
+ assertTrue(it.hasNext());
+ f = it.next();
+ assertEquals(0, ((Number)f.getAttribute(aname("intProperty"))).intValue());
+ s.remove(((SimpleFeature)f.getAttribute(tname("ftjoin"))).getAttribute(aname("name")));
+
+ assertTrue(it.hasNext());
+ f = it.next();
+ assertEquals(0, ((Number)f.getAttribute(aname("intProperty"))).intValue());
+ s.remove(((SimpleFeature)f.getAttribute(tname("ftjoin"))).getAttribute(aname("name")));
+
+ assertTrue(it.hasNext());
+ f = it.next();
+ assertEquals(0, ((Number)f.getAttribute(aname("intProperty"))).intValue());
+ s.remove(((SimpleFeature)f.getAttribute(tname("ftjoin"))).getAttribute(aname("name")));
+
+ assertEquals(0, s.size());
+
+ s = new HashSet(Arrays.asList("one", "two"));
+
+ assertTrue(it.hasNext());
+ f = it.next();
+ assertEquals(1, ((Number)f.getAttribute(aname("intProperty"))).intValue());
+ s.remove(((SimpleFeature)f.getAttribute(tname("ftjoin"))).getAttribute(aname("name")));
+
+ assertTrue(it.hasNext());
+ f = it.next();
+ assertEquals(1, ((Number)f.getAttribute(aname("intProperty"))).intValue());
+ s.remove(((SimpleFeature)f.getAttribute(tname("ftjoin"))).getAttribute(aname("name")));
+
+ assertEquals(0, s.size());
+
+ assertTrue(it.hasNext());
+ f = it.next();
+ assertEquals(2, ((Number)f.getAttribute(aname("intProperty"))).intValue());
+ assertEquals("two", ((SimpleFeature)f.getAttribute(tname("ftjoin"))).getAttribute(aname("name")));
+
+ assertFalse(it.hasNext());
+ }
+ finally {
+ it.close();
+ }
+ }
+
+ public void testOuterJoin() throws Exception {
+ doTestOuterJoin(false);
+ doTestOuterJoin(true);
+ }
+
+ void doTestOuterJoin(boolean exposePrimaryKeys) throws Exception {
+ dataStore.setExposePrimaryKeyColumns(exposePrimaryKeys);
+ FilterFactory ff = dataStore.getFilterFactory();
+ Query q = new Query(tname("ftjoin"));
+ q.getJoins().add(new Join(tname("ft1"),
+ ff.equal(ff.property(aname("name")), ff.property(aname("stringProperty")), true)).type(Type.OUTER));
+
+ SimpleFeatureCollection features = dataStore.getFeatureSource(tname("ftjoin")).getFeatures(q);
+ assertEquals(dataStore.getFeatureSource(tname("ftjoin")).getFeatures(q).size(), features.size());
+
+ SimpleFeatureIterator it = features.features();
+ try {
+
+ while(it.hasNext()) {
+ SimpleFeature f = it.next();
+ assertEquals(4, f.getAttributeCount());
+
+ SimpleFeature g = (SimpleFeature) f.getAttribute(tname("ft1"));
+ if ("three".equals(f.getAttribute(aname("name")))) {
+ assertNull(g);
+ }
+ else {
+ assertNotNull(g);
+ }
+ }
+ }
+ finally {
+ it.close();
+ }
+ }
+}
diff --git a/modules/library/jdbc/src/test/java/org/geotools/jdbc/JDBCJoinTestSetup.java b/modules/library/jdbc/src/test/java/org/geotools/jdbc/JDBCJoinTestSetup.java
new file mode 100644
index 0000000..5032025
--- /dev/null
+++ b/modules/library/jdbc/src/test/java/org/geotools/jdbc/JDBCJoinTestSetup.java
@@ -0,0 +1,57 @@
+/*
+ * GeoTools - The Open Source Java GIS Toolkit
+ * http://geotools.org
+ *
+ * (C) 2002-2011, Open Source Geospatial Foundation (OSGeo)
+ *
+ * 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.
+ */
+package org.geotools.jdbc;
+
+import java.sql.SQLException;
+
+public abstract class JDBCJoinTestSetup extends JDBCDelegatingTestSetup {
+
+ protected JDBCJoinTestSetup(JDBCTestSetup delegate) {
+ super(delegate);
+ }
+
+ protected final void setUpData() throws Exception {
+ delegate.setUpData();
+
+ //kill all the data
+ try {
+ dropJoinTable();
+ } catch (SQLException e) {
+ }
+
+ //create all the data
+ createJoinTable();
+ }
+
+ /**
+ * Creates a table with the following schema:
+ *
+ */
+ protected abstract void createJoinTable() throws Exception;
+
+ protected abstract void dropJoinTable() throws Exception;
+
+}
diff --git a/modules/library/jdbc/src/test/java/org/geotools/jdbc/JDBCTemporalFilterTest.java b/modules/library/jdbc/src/test/java/org/geotools/jdbc/JDBCTemporalFilterTest.java
new file mode 100644
index 0000000..4a177d6
--- /dev/null
+++ b/modules/library/jdbc/src/test/java/org/geotools/jdbc/JDBCTemporalFilterTest.java
@@ -0,0 +1,212 @@
+/*
+ * GeoTools - The Open Source Java GIS Toolkit
+ * http://geotools.org
+ *
+ * (C) 2002-2011, Open Source Geospatial Foundation (OSGeo)
+ *
+ * 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.
+ */
+package org.geotools.jdbc;
+
+import java.sql.Timestamp;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import org.geotools.data.Join;
+import org.geotools.data.Query;
+import org.geotools.data.simple.SimpleFeatureCollection;
+import org.geotools.data.simple.SimpleFeatureIterator;
+import org.geotools.data.simple.SimpleFeatureSource;
+import org.geotools.temporal.object.DefaultInstant;
+import org.geotools.temporal.object.DefaultPeriod;
+import org.geotools.temporal.object.DefaultPosition;
+import org.geotools.util.Converters;
+import org.opengis.feature.simple.SimpleFeature;
+import org.opengis.filter.Filter;
+import org.opengis.filter.FilterFactory;
+import org.opengis.filter.sort.SortBy;
+import org.opengis.filter.sort.SortOrder;
+import org.opengis.filter.temporal.After;
+import org.opengis.filter.temporal.Before;
+import org.opengis.filter.temporal.Begins;
+import org.opengis.filter.temporal.BegunBy;
+import org.opengis.filter.temporal.During;
+import org.opengis.filter.temporal.Ends;
+import org.opengis.filter.temporal.TContains;
+import org.opengis.filter.temporal.TEquals;
+import org.opengis.temporal.Instant;
+import org.opengis.temporal.Period;
+
+public abstract class JDBCTemporalFilterTest extends JDBCTestSupport {
+
+ /* dates(d:Date,dt:Datetime,t:Time)
+ *
+ *
+ * The table has the following data:
+ *
+ * 2009-06-28 | 2009-06-28 15:12:41 | 15:12:41
+ * 2009-01-15 | 2009-01-15 13:10:12 | 13:10:12
+ * 2009-09-29 | 2009-09-29 17:54:23 | 17:54:23
+ */
+
+ @Override
+ protected abstract JDBCDateTestSetup createTestSetup();
+
+ void assertDatesMatch(Filter filter, String...dates) throws Exception {
+ FilterFactory ff = dataStore.getFilterFactory();
+
+ Query query = new Query(aname("dates"), filter);
+ query.setSortBy(new SortBy[]{ff.sort(aname("dt"), SortOrder.ASCENDING)});
+ assertDatesMatch(query, dates);
+ }
+
+ void assertDatesMatch(Query query, String...dates) throws Exception {
+ SimpleFeatureSource source = dataStore.getFeatureSource(tname("dates"));
+
+ assertEquals(dates.length, source.getCount(query));
+
+ SimpleFeatureCollection features = source.getFeatures(query);
+ SimpleFeatureIterator it = features.features();
+ int i = 0;
+ try {
+ while(it.hasNext()) {
+ SimpleFeature f = it.next();
+ Date expected = FORMAT.parse(dates[i++]);
+
+ assertEquals(Converters.convert(expected, Timestamp.class), f.getAttribute(aname("dt")));
+ }
+ }
+ finally {
+ it.close();
+ }
+ }
+
+ public void testAfter() throws Exception {
+ FilterFactory ff = dataStore.getFilterFactory();
+
+ After after = ff.after(ff.property(aname("dt")), ff.literal("2009-02-01 00:00:00"));
+ assertDatesMatch(after, "2009-06-28 15:12:41", "2009-09-29 17:54:23");
+ }
+
+ public void testAfterInterval() throws Exception {
+ Period period = period("2009-02-01 00:00:00", "2009-07-01 00:00:00");
+
+ FilterFactory ff = dataStore.getFilterFactory();
+
+ After after = ff.after(ff.property(aname("dt")), ff.literal(period));
+ assertDatesMatch(after, "2009-09-29 17:54:23");
+
+ after = ff.after(ff.literal(period), ff.property(aname("dt")));
+ assertDatesMatch(after, "2009-01-15 13:10:12");
+ }
+
+ public void testBefore() throws Exception {
+ FilterFactory ff = dataStore.getFilterFactory();
+
+ Before before = ff.before(ff.property(aname("dt")), ff.literal("2009-02-01 00:00:00"));
+ assertDatesMatch(before, "2009-01-15 13:10:12");
+ }
+
+ public void testBeforeInterval() throws Exception {
+ Period period = period("2009-07-01 00:00:00", "2009-12-01 00:00:00");
+
+ FilterFactory ff = dataStore.getFilterFactory();
+
+ Before before = ff.before(ff.property(aname("dt")), ff.literal(period));
+ assertDatesMatch(before, "2009-01-15 13:10:12", "2009-06-28 15:12:41");
+
+ period = period("2009-07-01 00:00:00", "2009-08-01 00:00:00");
+ before = ff.before(ff.literal(period), ff.property(aname("dt")));
+ assertDatesMatch(before, "2009-09-29 17:54:23");
+ }
+
+ public void testBegins() throws Exception {
+ Period period = period("2009-01-15 13:10:12", "2009-06-28 15:12:41");
+ FilterFactory ff = dataStore.getFilterFactory();
+
+ Begins before = ff.begins(ff.property(aname("dt")), ff.literal(period));
+ assertDatesMatch(before, "2009-01-15 13:10:12");
+ }
+
+ public void testBegunBy() throws Exception {
+ Period period = period("2009-01-15 13:10:12", "2009-06-28 15:12:41");
+ FilterFactory ff = dataStore.getFilterFactory();
+
+ BegunBy before = ff.begunBy(ff.literal(period), ff.property(aname("dt")));
+ assertDatesMatch(before, "2009-01-15 13:10:12");
+ }
+
+ public void testEnds() throws Exception {
+ Period period = period("2009-01-15 13:10:12", "2009-06-28 15:12:41");
+ FilterFactory ff = dataStore.getFilterFactory();
+
+ Ends before = ff.ends(ff.property(aname("dt")), ff.literal(period));
+ assertDatesMatch(before, "2009-06-28 15:12:41");
+ }
+
+ public void testEndedBy() throws Exception {
+ Period period = period("2009-01-15 13:10:12", "2009-06-28 15:12:41");
+ FilterFactory ff = dataStore.getFilterFactory();
+
+ Ends before = ff.ends(ff.property(aname("dt")), ff.literal(period));
+ assertDatesMatch(before, "2009-06-28 15:12:41");
+ }
+
+ public void testDuring() throws Exception {
+ Period period = period("2009-01-01 00:00:00", "2009-07-28 15:12:41");
+ FilterFactory ff = dataStore.getFilterFactory();
+
+ During during = ff.during(ff.property(aname("dt")), ff.literal(period));
+ assertDatesMatch(during, "2009-01-15 13:10:12", "2009-06-28 15:12:41");
+ }
+
+ public void testTContains() throws Exception {
+ Period period = period("2009-01-01 00:00:00", "2009-07-28 15:12:41");
+ FilterFactory ff = dataStore.getFilterFactory();
+
+ TContains during = ff.tcontains(ff.literal(period), ff.property(aname("dt")));
+ assertDatesMatch(during, "2009-01-15 13:10:12", "2009-06-28 15:12:41");
+ }
+
+ public void testTEquals() throws Exception {
+ FilterFactory ff = dataStore.getFilterFactory();
+
+ TEquals equals = ff.tequals(ff.literal("2009-01-15 13:10:12"), ff.property(aname("dt")));
+ assertDatesMatch(equals, "2009-01-15 13:10:12");
+ }
+
+ public void testTemporalJoin() throws Exception {
+ FilterFactory ff = dataStore.getFilterFactory();
+
+ After after = ff.after(ff.property(aname("dt")), ff.property("other." + aname("dt")));
+ Query q = new Query(tname("dates"));
+ q.getJoins().add(new Join(tname("dates"), after).alias("other"));
+ q.setSortBy(new SortBy[]{ff.sort(aname("dt"), SortOrder.ASCENDING)});
+
+ assertDatesMatch(q, "2009-06-28 15:12:41", "2009-09-29 17:54:23", "2009-09-29 17:54:23");
+ }
+
+ static DateFormat FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+
+ protected Date date(String date) throws ParseException {
+ return FORMAT.parse(date);
+ }
+
+ protected Instant instant(String d) throws ParseException {
+ return new DefaultInstant(new DefaultPosition(date(d)));
+ }
+
+ protected Period period(String d1, String d2) throws ParseException {
+ return new DefaultPeriod(instant(d1), instant(d2));
+ }
+}
diff --git a/modules/library/jdbc/src/test/java/org/geotools/jdbc/JDBCTestSupport.java b/modules/library/jdbc/src/test/java/org/geotools/jdbc/JDBCTestSupport.java
index 4d92ff2..2cbbf54 100644
--- a/modules/library/jdbc/src/test/java/org/geotools/jdbc/JDBCTestSupport.java
+++ b/modules/library/jdbc/src/test/java/org/geotools/jdbc/JDBCTestSupport.java
@@ -218,7 +218,20 @@ public abstract class JDBCTestSupport extends OnlineTestCase {
else {
assertTrue(texpected.getBinding().isAssignableFrom(tactual.getBinding()));
}
-
+ }
+
+ protected void assertAttributeValuesEqual(Object expected, Object actual) {
+ if (expected == null) {
+ assertNull(actual);
+ return;
+ }
+
+ if (expected instanceof Geometry) {
+ assertTrue(((Geometry)expected).equals((Geometry)actual));
+ return;
+ }
+
+ assertEquals(expected, actual);
}
protected boolean areCRSEqual(CoordinateReferenceSystem crs1, CoordinateReferenceSystem crs2) {
diff --git a/modules/library/jdbc/src/test/resources/META-INF/services/org.opengis.filter.expression.Function b/modules/library/jdbc/src/test/resources/META-INF/services/org.opengis.filter.expression.Function
new file mode 100644
index 0000000..2d827d0
--- /dev/null
+++ b/modules/library/jdbc/src/test/resources/META-INF/services/org.opengis.filter.expression.Function
@@ -0,0 +1 @@
+org.geotools.jdbc.EqualsFunction
\ No newline at end of file
diff --git a/modules/library/main/src/main/java/org/geotools/data/DefaultQuery.java b/modules/library/main/src/main/java/org/geotools/data/DefaultQuery.java
index f88fd78..17d91fd 100644
--- a/modules/library/main/src/main/java/org/geotools/data/DefaultQuery.java
+++ b/modules/library/main/src/main/java/org/geotools/data/DefaultQuery.java
@@ -141,6 +141,8 @@ public class DefaultQuery extends Query {
this.version = query.getVersion();
this.hints = query.getHints();
this.startIndex = query.getStartIndex();
+ this.alias = query.getAlias();
+ this.joins = query.getJoins();
}
}
diff --git a/modules/library/main/src/main/java/org/geotools/feature/simple/SimpleFeatureTypeBuilder.java b/modules/library/main/src/main/java/org/geotools/feature/simple/SimpleFeatureTypeBuilder.java
index d75feb8..01bd295 100644
--- a/modules/library/main/src/main/java/org/geotools/feature/simple/SimpleFeatureTypeBuilder.java
+++ b/modules/library/main/src/main/java/org/geotools/feature/simple/SimpleFeatureTypeBuilder.java
@@ -42,6 +42,7 @@ import org.opengis.feature.type.GeometryType;
import org.opengis.feature.type.Name;
import org.opengis.feature.type.Schema;
import org.opengis.filter.Filter;
+import org.opengis.filter.expression.PropertyName;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.util.InternationalString;
@@ -1014,22 +1015,25 @@ public class SimpleFeatureTypeBuilder {
* @return SimpleFeatureType containing just the types indicated by name
*/
public static SimpleFeatureType retype( SimpleFeatureType original, String[] types ) {
- SimpleFeatureTypeBuilder b = new SimpleFeatureTypeBuilder();
-
- //initialize the builder
- b.init( original );
-
- //clear the attributes
- b.attributes().clear();
-
- //add attributes in order
- for ( int i = 0; i < types.length; i++ ) {
- b.add( original.getDescriptor( types[i] ) );
- }
-
- return b.buildFeatureType();
+ return retype(original, Arrays.asList(types));
}
+ public static SimpleFeatureType retype( SimpleFeatureType original, List types ) {
+ SimpleFeatureTypeBuilder b = new SimpleFeatureTypeBuilder();
+
+ //initialize the builder
+ b.init( original );
+
+ //clear the attributes
+ b.attributes().clear();
+
+ //add attributes in order
+ for ( int i = 0; i < types.size(); i++ ) {
+ b.add( original.getDescriptor( types.get(i) ) );
+ }
+
+ return b.buildFeatureType();
+ }
/**
* Create a SimpleFeatureType with the same content; just updating the geometry
* attribute to match the provided coordinate reference system.
@@ -1060,4 +1064,28 @@ public class SimpleFeatureTypeBuilder {
}
return b.buildFeatureType();
}
+
+ /**
+ * Copys a feature type.
+ *
+ * This method does a deep copy in that all individual attributes are copied as well.
+ *
+ */
+ public static SimpleFeatureType copy( SimpleFeatureType original ) {
+ SimpleFeatureTypeBuilder b = new SimpleFeatureTypeBuilder();
+
+ //initialize the builder
+ b.init( original );
+
+ //clear attributes
+ b.attributes().clear();
+
+ //add attributes in order
+ for( AttributeDescriptor descriptor : original.getAttributeDescriptors() ){
+ AttributeTypeBuilder ab = new AttributeTypeBuilder( b.factory );
+ ab.init( descriptor );
+ b.add( ab.buildDescriptor( descriptor.getLocalName() ));
+ }
+ return b.buildFeatureType();
+ }
}
diff --git a/modules/library/main/src/main/java/org/geotools/filter/visitor/DuplicatingFilterVisitor.java b/modules/library/main/src/main/java/org/geotools/filter/visitor/DuplicatingFilterVisitor.java
index e43d360..cb948b0 100644
--- a/modules/library/main/src/main/java/org/geotools/filter/visitor/DuplicatingFilterVisitor.java
+++ b/modules/library/main/src/main/java/org/geotools/filter/visitor/DuplicatingFilterVisitor.java
@@ -407,7 +407,7 @@ public class DuplicatingFilterVisitor implements FilterVisitor, ExpressionVisito
}
public Object visit(TContains contains, Object extraData) {
- return getFactory(extraData).contains(visit(contains.getExpression1(), extraData),
+ return getFactory(extraData).tcontains(visit(contains.getExpression1(), extraData),
visit(contains.getExpression2(), extraData));
}
diff --git a/modules/library/main/src/main/java/org/geotools/util/CommonsConverterFactory.java b/modules/library/main/src/main/java/org/geotools/util/CommonsConverterFactory.java
index 1848a34..e53304f 100644
--- a/modules/library/main/src/main/java/org/geotools/util/CommonsConverterFactory.java
+++ b/modules/library/main/src/main/java/org/geotools/util/CommonsConverterFactory.java
@@ -221,23 +221,22 @@ public class CommonsConverterFactory implements ConverterFactory {
static class DateConverter implements Converter {
private static SimpleDateFormat format1 = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss.S a" );
private static SimpleDateFormat format2 = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ssa" );
+ private static SimpleDateFormat format3 = new SimpleDateFormat( "yyyy-MM-dd" );
+ private static SimpleDateFormat[] formats = new SimpleDateFormat[]{format1,format2,format3};
public T convert(Object source, Class target) throws Exception {
if( source == null ) return null;
String string = (String) source;
- try {
- Date parsed = format1.parse(string);
- return target.cast( parsed );
- }
- catch( Exception ignore){
- }
- try {
- Date parsed = format2.parse(string);
- return target.cast( parsed );
- }
- catch( Exception ignore){
+ for (SimpleDateFormat format : formats) {
+ try {
+ Date parsed = format.parse(string);
+ return target.cast( parsed );
+ }
+ catch( Exception ignore){
+ }
}
+
return null;
}
}
diff --git a/modules/plugin/jdbc/jdbc-db2/src/main/java/org/geotools/data/db2/DB2SQLDialect.java b/modules/plugin/jdbc/jdbc-db2/src/main/java/org/geotools/data/db2/DB2SQLDialect.java
index f9cbd4c..7a71089 100644
--- a/modules/plugin/jdbc/jdbc-db2/src/main/java/org/geotools/data/db2/DB2SQLDialect.java
+++ b/modules/plugin/jdbc/jdbc-db2/src/main/java/org/geotools/data/db2/DB2SQLDialect.java
@@ -231,15 +231,15 @@ public class DB2SQLDialect extends SQLDialect {
return srid;
}
-
- public void encodeGeometryColumn(GeometryDescriptor gatt, int srid, StringBuffer sql) {
- encodeGeometryColumn(gatt, sql);
+ @Override
+ public void encodeGeometryColumn(GeometryDescriptor gatt, String prefix, int srid,
+ StringBuffer sql) {
+ encodeGeometryColumn(gatt, prefix, sql);
}
-
-
- public void encodeGeometryColumn(GeometryDescriptor gatt, StringBuffer sql) {
+
+ public void encodeGeometryColumn(GeometryDescriptor gatt, String prefix, StringBuffer sql) {
sql.append("db2gse.ST_AsBinary(");
- encodeColumnName(gatt.getLocalName(), sql);
+ encodeColumnName(prefix, gatt.getLocalName(), sql);
sql.append(")");
}
@@ -247,7 +247,7 @@ public class DB2SQLDialect extends SQLDialect {
public void encodeGeometryEnvelope(String tableName,String geometryColumn, StringBuffer sql) {
sql.append("db2gse.ST_AsBinary(db2gse.ST_GetAggrResult(MAX(db2gse.ST_BuildMBRAggr(");
- encodeColumnName(geometryColumn, sql);
+ encodeColumnName(null, geometryColumn, sql);
sql.append("))))");
// sql.append("db2gse.ST_AsBinary(");
@@ -536,11 +536,11 @@ public class DB2SQLDialect extends SQLDialect {
}
}
- public void encodeGeometryColumnGeneralized(GeometryDescriptor gatt, int srid, StringBuffer sql,Double distance) {
+ public void encodeGeometryColumnGeneralized(GeometryDescriptor gatt, String prefix, int srid, StringBuffer sql,Double distance) {
sql.append("db2gse.ST_AsBinary(db2gse.st_Generalize(");
- encodeColumnName(gatt.getLocalName(), sql);
+ encodeColumnName(null, gatt.getLocalName(), sql);
sql.append(",").append(distance);
sql.append("))");
}
diff --git a/modules/plugin/jdbc/jdbc-db2/src/main/java/org/geotools/data/db2/DB2SQLDialectBasic.java b/modules/plugin/jdbc/jdbc-db2/src/main/java/org/geotools/data/db2/DB2SQLDialectBasic.java
index 498ef7c..d849771 100644
--- a/modules/plugin/jdbc/jdbc-db2/src/main/java/org/geotools/data/db2/DB2SQLDialectBasic.java
+++ b/modules/plugin/jdbc/jdbc-db2/src/main/java/org/geotools/data/db2/DB2SQLDialectBasic.java
@@ -88,15 +88,15 @@ public class DB2SQLDialectBasic extends BasicSQLDialect {
}
-
public void encodeGeometryColumn(GeometryDescriptor gatt,StringBuffer sql) {
- delegate.encodeGeometryColumn(gatt, sql);
- }
-
- public void encodeGeometryColumn(GeometryDescriptor gatt, int srid, StringBuffer sql) {
- delegate.encodeGeometryColumn(gatt, srid, sql);
+ delegate.encodeGeometryColumn(gatt, null, sql);
}
+ @Override
+ public void encodeGeometryColumn(GeometryDescriptor gatt, String prefix, int srid,
+ StringBuffer sql) {
+ delegate.encodeGeometryColumn(gatt, prefix, srid, sql);
+ }
@Override
public void encodeGeometryEnvelope(String tableName,String geometryColumn, StringBuffer sql) {
@@ -184,9 +184,12 @@ public class DB2SQLDialectBasic extends BasicSQLDialect {
delegate.applyLimitOffset(sql, limit, offset);
}
- public void encodeGeometryColumnGeneralized(GeometryDescriptor gatt, int srid, StringBuffer sql,Double distance) {
- delegate.encodeGeometryColumnGeneralized(gatt, srid, sql, distance);
+ @Override
+ public void encodeGeometryColumnGeneralized(GeometryDescriptor gatt, String prefix, int srid,
+ StringBuffer sql, Double distance) {
+ delegate.encodeGeometryColumnGeneralized(gatt, prefix, srid, sql, distance);
}
+
@Override
protected void addSupportedHints(Set hints) {
delegate.addSupportedHints(hints);
diff --git a/modules/plugin/jdbc/jdbc-db2/src/main/java/org/geotools/data/db2/DB2SQLDialectPrepared.java b/modules/plugin/jdbc/jdbc-db2/src/main/java/org/geotools/data/db2/DB2SQLDialectPrepared.java
index 4e21b0c..b53a0e3 100644
--- a/modules/plugin/jdbc/jdbc-db2/src/main/java/org/geotools/data/db2/DB2SQLDialectPrepared.java
+++ b/modules/plugin/jdbc/jdbc-db2/src/main/java/org/geotools/data/db2/DB2SQLDialectPrepared.java
@@ -87,14 +87,15 @@ public class DB2SQLDialectPrepared extends PreparedStatementSQLDialect {
}
public void encodeGeometryColumn(GeometryDescriptor gatt, StringBuffer sql) {
- delegate.encodeGeometryColumn(gatt, sql);
+ delegate.encodeGeometryColumn(gatt, null, sql);
}
- public void encodeGeometryColumn(GeometryDescriptor gatt, int srid, StringBuffer sql) {
- delegate.encodeGeometryColumn(gatt, srid, sql);
+ @Override
+ public void encodeGeometryColumn(GeometryDescriptor gatt, String prefix, int srid,
+ StringBuffer sql) {
+ delegate.encodeGeometryColumn(gatt, prefix, srid, sql);
}
-
@Override
public void encodeGeometryEnvelope(String tableName,String geometryColumn, StringBuffer sql) {
delegate.encodeGeometryEnvelope(tableName, geometryColumn, sql);
@@ -208,9 +209,13 @@ public class DB2SQLDialectPrepared extends PreparedStatementSQLDialect {
delegate.applyLimitOffset(sql, limit, offset);
}
- public void encodeGeometryColumnGeneralized(GeometryDescriptor gatt, int srid,StringBuffer sql,Double distance) {
- delegate.encodeGeometryColumnGeneralized(gatt,srid,sql,distance);
+ @Override
+ public void encodeGeometryColumnGeneralized(GeometryDescriptor gatt, String prefix, int srid,
+ StringBuffer sql, Double distance) {
+
+ delegate.encodeGeometryColumnGeneralized(gatt, prefix, srid, sql, distance);
}
+
@Override
protected void addSupportedHints(Set hints) {
delegate.addSupportedHints(hints);
diff --git a/modules/plugin/jdbc/jdbc-h2/src/main/java/org/geotools/data/h2/H2Dialect.java b/modules/plugin/jdbc/jdbc-h2/src/main/java/org/geotools/data/h2/H2Dialect.java
index 4de92f8..c5d043d 100644
--- a/modules/plugin/jdbc/jdbc-h2/src/main/java/org/geotools/data/h2/H2Dialect.java
+++ b/modules/plugin/jdbc/jdbc-h2/src/main/java/org/geotools/data/h2/H2Dialect.java
@@ -294,7 +294,7 @@ public class H2Dialect extends SQLDialect {
//try grabbing directly from a geometry
StringBuffer sql = new StringBuffer();
sql.append("SELECT ST_SRID(");
- encodeColumnName(columnName, sql);
+ encodeColumnName(null, columnName, sql);
sql.append(") ");
sql.append("FROM ");
@@ -305,7 +305,7 @@ public class H2Dialect extends SQLDialect {
encodeSchemaName(tableName, sql);
sql.append(" WHERE ");
- encodeColumnName(columnName, sql);
+ encodeColumnName(null, columnName, sql);
sql.append(" is not null LIMIT 1");
dataStore.getLogger().fine(sql.toString());
@@ -332,7 +332,7 @@ public class H2Dialect extends SQLDialect {
public void encodeGeometryEnvelope(String tableName, String geometryColumn, StringBuffer sql) {
//TODO: change spatialdbbox to use envelope
sql.append("ST_Envelope(");
- encodeColumnName(geometryColumn, sql);
+ encodeColumnName(null, geometryColumn, sql);
sql.append(")");
}
@@ -373,7 +373,7 @@ public class H2Dialect extends SQLDialect {
}
public void encodePrimaryKey(String column, StringBuffer sql) {
- encodeColumnName(column, sql);
+ encodeColumnName(null, column, sql);
sql.append(" int AUTO_INCREMENT(1) PRIMARY KEY");
}
diff --git a/modules/plugin/jdbc/jdbc-h2/src/main/java/org/geotools/data/h2/H2FilterToSQL.java b/modules/plugin/jdbc/jdbc-h2/src/main/java/org/geotools/data/h2/H2FilterToSQL.java
index a14f1e9..178176f 100644
--- a/modules/plugin/jdbc/jdbc-h2/src/main/java/org/geotools/data/h2/H2FilterToSQL.java
+++ b/modules/plugin/jdbc/jdbc-h2/src/main/java/org/geotools/data/h2/H2FilterToSQL.java
@@ -17,9 +17,12 @@
package org.geotools.data.h2;
import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
import org.geotools.data.jdbc.FilterToSQL;
import org.geotools.filter.FilterCapabilities;
+import org.opengis.filter.expression.Expression;
import org.opengis.filter.expression.Literal;
import org.opengis.filter.expression.PropertyName;
import org.opengis.filter.spatial.BBOX;
@@ -75,16 +78,29 @@ public class H2FilterToSQL extends FilterToSQL {
out.write( "ST_GeomFromText('"+g.toText()+"', "+currentSRID+")");
}
+
@Override
protected Object visitBinarySpatialOperator(BinarySpatialOperator filter,
PropertyName property, Literal geometry, boolean swapped, Object extraData) {
-
+ return visitBinarySpatialOperator(filter, (Expression) property, (Expression) geometry,
+ swapped, extraData);
+ }
+
+ @Override
+ protected Object visitBinarySpatialOperator(BinarySpatialOperator filter, Expression e1,
+ Expression e2, Object extraData) {
+ return visitBinarySpatialOperator(filter, e1, e2, false, extraData);
+ }
+
+ protected Object visitBinarySpatialOperator(BinarySpatialOperator filter, Expression e1,
+ Expression e2, boolean swapped, Object extraData) {
+
try {
if (filter instanceof DistanceBufferOperator) {
out.write("ST_Distance(");
- property.accept(this, extraData);
+ e1.accept(this, extraData);
out.write(", ");
- geometry.accept(this, extraData);
+ e2.accept(this, extraData);
out.write(")");
if (filter instanceof DWithin) {
@@ -101,9 +117,9 @@ public class H2FilterToSQL extends FilterToSQL {
else if (filter instanceof BBOX) {
//TODO: make a loose bounding box parameter
out.write("ST_Intersects(");
- property.accept(this, extraData);
+ e1.accept(this, extraData);
out.write(",");
- geometry.accept(this, extraData);
+ e2.accept(this, extraData);
out.write(")");
}
else {
@@ -137,20 +153,21 @@ public class H2FilterToSQL extends FilterToSQL {
}
if (swapped) {
- geometry.accept(this, extraData);
+ e2.accept(this, extraData);
out.write(", ");
- property.accept(this, extraData);
+ e1.accept(this, extraData);
}
else {
- property.accept(this, extraData);
+ e1.accept(this, extraData);
out.write(", ");
- geometry.accept(this, extraData);
+ e2.accept(this, extraData);
}
out.write(")");
}
- if (!(filter instanceof Disjoint)) {
+ Expression geometry = e1 instanceof Literal ? e1 : e2 instanceof Literal ? e2 : null;
+ if (geometry != null && !(filter instanceof Disjoint)) {
String spatialIndex = (String)
currentGeometry.getUserData().get(H2Dialect.H2_SPATIAL_INDEX);
if (spatialIndex != null) {
@@ -185,4 +202,24 @@ public class H2FilterToSQL extends FilterToSQL {
return extraData;
}
+
+ static SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");
+ static SimpleDateFormat DATETIME_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSZ");
+
+ @Override
+ protected void writeLiteral(Object literal) throws IOException {
+ if (literal instanceof Date) {
+ out.write("PARSEDATETIME(");
+ if (literal instanceof java.sql.Date) {
+ out.write("'" + DATE_FORMAT.format(literal) + "', 'yyyy-MM-dd'");
+ }
+ else {
+ out.write("'" + DATETIME_FORMAT.format(literal) + "', 'yyyy-MM-dd HH:mm:ss.SSSZ'");
+ }
+ out.write(")");
+ }
+ else {
+ super.writeLiteral(literal);
+ }
+ }
}
diff --git a/modules/plugin/jdbc/jdbc-h2/src/test/java/org/geotools/data/h2/H2DateTestSetup.java b/modules/plugin/jdbc/jdbc-h2/src/test/java/org/geotools/data/h2/H2DateTestSetup.java
index 234d5b3..451034f 100644
--- a/modules/plugin/jdbc/jdbc-h2/src/test/java/org/geotools/data/h2/H2DateTestSetup.java
+++ b/modules/plugin/jdbc/jdbc-h2/src/test/java/org/geotools/data/h2/H2DateTestSetup.java
@@ -15,6 +15,9 @@ public class H2DateTestSetup extends JDBCDateTestSetup {
@Override
protected void createDateTable() throws Exception {
+ String sql = "CREATE SCHEMA \"geotools\";";
+ runSafe(sql);
+
run( "CREATE TABLE \"geotools\".\"dates\" (\"d\" DATE, \"dt\" TIMESTAMP, \"t\" TIME)");
run( "INSERT INTO \"geotools\".\"dates\" VALUES (" +
diff --git a/modules/plugin/jdbc/jdbc-h2/src/test/java/org/geotools/data/h2/H2ForeignKeyTest.java b/modules/plugin/jdbc/jdbc-h2/src/test/java/org/geotools/data/h2/H2ForeignKeyTest.java
deleted file mode 100644
index 2a17686..0000000
--- a/modules/plugin/jdbc/jdbc-h2/src/test/java/org/geotools/data/h2/H2ForeignKeyTest.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * GeoTools - The Open Source Java GIS Toolkit
- * http://geotools.org
- *
- * (C) 2002-2008, Open Source Geospatial Foundation (OSGeo)
- *
- * 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.
- */
-package org.geotools.data.h2;
-
-import org.geotools.jdbc.JDBCForeignKeyTest;
-import org.geotools.jdbc.JDBCTestSetup;
-
-
-/**
- *
- *
- * @source $URL$
- */
-public class H2ForeignKeyTest extends JDBCForeignKeyTest {
- protected JDBCTestSetup createTestSetup() {
- return new H2TestSetup() {
- protected void setUpData() throws Exception {
- super.setUpData();
-
- try {
- run("DROP TABLE \"geotools\".\"feature_relationships\"; COMMIT;");
- } catch (Exception e) {
- }
-
- ;
-
- String sql = "CREATE TABLE \"geotools\".\"feature_relationships\" ("
- + "\"table\" varchar, \"col\" varchar, \"rtable\" varchar, \"rcol\" varchar"
- + ")";
- run(sql);
-
- try {
- run("DROP TABLE \"geotools\".\"feature_associations\"; COMMIT;");
- } catch (Exception e) {
- }
-
- sql = "CREATE TABLE \"geotools\".\"feature_associations\" ("
- + "\"fid\" varchar, \"rtable\" varchar, \"rcol\" varchar, \"rfid\" varchar"
- + ");";
- run(sql);
-
- try {
- run("DROP TABLE \"geotools\".\"fk\"; COMMIT;");
- } catch (Exception e) {
- }
-
- sql = "CREATE TABLE \"geotools\".\"fk\" ("
- + "\"id\" int AUTO_INCREMENT(1) PRIMARY KEY, "
- + "\"geometry\" BLOB, \"intProperty\" int, "
- + "\"ft1\" int REFERENCES \"ft1\"" + ")";
- run(sql);
-
- sql = "INSERT INTO \"geotools\".\"fk\" VALUES ("
- + "0,ST_GeomFromText('POINT(0 0)',4326), 0, 0);";
- run(sql);
-
- sql = "INSERT INTO \"geotools\".\"feature_relationships\" VALUES ("
- + "'fk', 'ft1', 'ft1', 'id'" + ");";
- run(sql);
-
- sql = "INSERT INTO \"geotools\".\"feature_associations\" VALUES ("
- + "'fk.0', 'ft1', 'id', '0' " + ");";
- run(sql);
- }
-
- public void tearDown() throws Exception {
- super.tearDown();
-
- try {
- run("DROP TABLE \"geotools\".\"fk\"; COMMIT;");
- } catch (Exception e) {
- }
- }
- };
- }
-}
diff --git a/modules/plugin/jdbc/jdbc-h2/src/test/java/org/geotools/data/h2/H2GeometryAssociationTest.java b/modules/plugin/jdbc/jdbc-h2/src/test/java/org/geotools/data/h2/H2GeometryAssociationTest.java
deleted file mode 100644
index 7dbab4c..0000000
--- a/modules/plugin/jdbc/jdbc-h2/src/test/java/org/geotools/data/h2/H2GeometryAssociationTest.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * GeoTools - The Open Source Java GIS Toolkit
- * http://geotools.org
- *
- * (C) 2002-2008, Open Source Geospatial Foundation (OSGeo)
- *
- * 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.
- */
-package org.geotools.data.h2;
-
-import org.geotools.jdbc.JDBCGeometryAssociationTestSupport;
-import org.geotools.jdbc.JDBCTestSetup;
-
-
-/**
- *
- *
- * @source $URL$
- */
-public class H2GeometryAssociationTest extends JDBCGeometryAssociationTestSupport {
- protected JDBCTestSetup createTestSetup() {
- return new H2TestSetup() {
- protected void setUpData() throws Exception {
- super.setUpData();
-
- try {
- run("DROP TABLE \"geotools\".\"geometry\"; COMMIT;");
- } catch (Exception e) {
- }
-
- String sql = "CREATE TABLE \"geotools\".\"geometry\" ("
- + "\"id\" VARCHAR, \"name\" VARCHAR, \"description\" VARCHAR, "
- + "\"type\" VARCHAR, \"geometry\" POINT" + ")";
- run(sql);
-
- sql = "CALL AddGeometryColumn('geotools', 'geometry', 'geometry', 4326, 'POINT', 2)";
- run(sql);
-
- sql = "INSERT INTO \"geotools\".\"geometry\" VALUES ("
- + "'0','name-0','description-0', 'POINT', ST_GeomFromText('POINT(0 0)',4326) "
- + ");";
- run(sql);
-
- sql = "INSERT INTO \"geotools\".\"geometry\" VALUES ("
- + "'1','name-1','description-1', 'POINT', ST_GeomFromText('POINT(1 1)',4326) "
- + ");";
- run(sql);
-
- try {
- run("DROP TABLE \"geotools\".\"multi_geometry\"; COMMIT;");
- } catch (Exception e) {
- }
-
- sql = "CREATE TABLE \"geotools\".\"multi_geometry\" (" +
- "\"id\" VARCHAR, \"mgid\" VARCHAR, \"ref\" boolean" +
- ")";
- run(sql);
-
- sql = "INSERT INTO \"geotools\".\"geometry\" VALUES ("
- + "'2','name-2','description-2','MULTIPOINT', NULL" + ");";
- run(sql);
-
- sql = "INSERT INTO \"geotools\".\"multi_geometry\" VALUES ('2', '0', false);";
- run(sql);
-
- sql = "INSERT INTO \"geotools\".\"multi_geometry\" VALUES ('2', '1', false);";
- run(sql);
-
- try {
- run("DROP TABLE \"geotools\".\"geometry_associations\"; COMMIT;");
- } catch (Exception e) {
- }
-
- sql = "CREATE TABLE \"geotools\".\"geometry_associations\" ("
- + "\"fid\" VARCHAR, \"gid\" VARCHAR, \"gname\" VARCHAR, "
- + "\"ref\" BOOLEAN" + ")";
- run(sql);
-
- sql = "INSERT INTO \"geotools\".\"geometry_associations\" VALUES ("
- + "'ga.0', '0', 'geometry', false" + ");";
- run(sql);
-
- sql = "INSERT INTO \"geotools\".\"geometry_associations\" VALUES ("
- + "'ga.1', '1', 'geometry', true" + ");";
- run(sql);
-
- sql = "INSERT INTO \"geotools\".\"geometry_associations\" VALUES ("
- + "'ga.2', '2', 'geometry', false" + ");";
- run(sql);
-
- try {
- run("DROP TABLE \"geotools\".\"ga\"; COMMIT;");
- } catch (Exception e) {
- }
-
- sql = "CREATE TABLE \"geotools\".\"ga\" ("
- + "\"id\" int AUTO_INCREMENT(1) PRIMARY KEY, " + "\"geometry\" GEOMETRY " + ")";
- run(sql);
-
- sql = "CALL AddGeometryColumn('geotools', 'ga', 'geometry', 4326, 'GEOMETRY', 2)";
- run(sql);
-
- sql = "INSERT INTO \"geotools\".\"ga\" VALUES (0, NULL);";
- run(sql);
-
- sql = "INSERT INTO \"geotools\".\"ga\" VALUES (1, NULL);";
- run(sql);
-
- sql = "INSERT INTO \"geotools\".\"ga\" VALUES (2, NULL);";
- run(sql);
- }
-
- public void tearDown() throws Exception {
- super.tearDown();
-
- try {
- run("DROP TABLE \"geotools\".\"fk\"; COMMIT;");
- } catch (Exception e) {
- }
- }
- };
- }
-}
diff --git a/modules/plugin/jdbc/jdbc-h2/src/test/java/org/geotools/data/h2/H2JoinTest.java b/modules/plugin/jdbc/jdbc-h2/src/test/java/org/geotools/data/h2/H2JoinTest.java
new file mode 100644
index 0000000..8eb286b
--- /dev/null
+++ b/modules/plugin/jdbc/jdbc-h2/src/test/java/org/geotools/data/h2/H2JoinTest.java
@@ -0,0 +1,29 @@
+/*
+ * GeoTools - The Open Source Java GIS Toolkit
+ * http://geotools.org
+ *
+ * (C) 2002-2011, Open Source Geospatial Foundation (OSGeo)
+ *
+ * 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.
+ */
+package org.geotools.data.h2;
+
+import org.geotools.jdbc.JDBCJoinTest;
+import org.geotools.jdbc.JDBCJoinTestSetup;
+
+public class H2JoinTest extends JDBCJoinTest {
+
+ @Override
+ protected JDBCJoinTestSetup createTestSetup() {
+ return new H2JoinTestSetup();
+ }
+
+}
diff --git a/modules/plugin/jdbc/jdbc-h2/src/test/java/org/geotools/data/h2/H2JoinTestSetup.java b/modules/plugin/jdbc/jdbc-h2/src/test/java/org/geotools/data/h2/H2JoinTestSetup.java
new file mode 100644
index 0000000..3e0794a
--- /dev/null
+++ b/modules/plugin/jdbc/jdbc-h2/src/test/java/org/geotools/data/h2/H2JoinTestSetup.java
@@ -0,0 +1,43 @@
+/*
+ * GeoTools - The Open Source Java GIS Toolkit
+ * http://geotools.org
+ *
+ * (C) 2002-2011, Open Source Geospatial Foundation (OSGeo)
+ *
+ * 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.
+ */
+package org.geotools.data.h2;
+
+import org.geotools.jdbc.JDBCJoinTestSetup;
+
+public class H2JoinTestSetup extends JDBCJoinTestSetup {
+
+ protected H2JoinTestSetup() {
+ super(new H2TestSetup());
+ }
+
+ @Override
+ protected void createJoinTable() throws Exception {
+ run( "CREATE TABLE \"geotools\".\"ftjoin\" ( \"id\" int, " + "\"name\" VARCHAR, \"geom\" GEOMETRY)" );
+ run("CALL AddGeometryColumn('geotools', 'ftjoin', 'geom', 4326, 'GEOMETRY', 2)");
+
+ run( "INSERT INTO \"geotools\".\"ftjoin\" VALUES (0, 'zero', ST_GeomFromText('POLYGON ((-0.1 -0.1, -0.1 0.1, 0.1 0.1, 0.1 -0.1, -0.1 -0.1))', 4326))");
+ run( "INSERT INTO \"geotools\".\"ftjoin\" VALUES (1, 'one', ST_GeomFromText('POLYGON ((-1.1 -1.1, -1.1 1.1, 1.1 1.1, 1.1 -1.1, -1.1 -1.1))', 4326))");
+ run( "INSERT INTO \"geotools\".\"ftjoin\" VALUES (2, 'two', ST_GeomFromText('POLYGON ((-10 -10, -10 10, 10 10, 10 -10, -10 -10))', 4326))");
+ run( "INSERT INTO \"geotools\".\"ftjoin\" VALUES (3, 'three', NULL)");
+ }
+
+ @Override
+ protected void dropJoinTable() throws Exception {
+ run( "DROP TABLE \"geotools\".\"ftjoin\"" );
+ }
+
+}
diff --git a/modules/plugin/jdbc/jdbc-h2/src/test/java/org/geotools/data/h2/H2TemporalFilterTest.java b/modules/plugin/jdbc/jdbc-h2/src/test/java/org/geotools/data/h2/H2TemporalFilterTest.java
new file mode 100644
index 0000000..5ad90db
--- /dev/null
+++ b/modules/plugin/jdbc/jdbc-h2/src/test/java/org/geotools/data/h2/H2TemporalFilterTest.java
@@ -0,0 +1,13 @@
+package org.geotools.data.h2;
+
+import org.geotools.jdbc.JDBCDateTestSetup;
+import org.geotools.jdbc.JDBCTemporalFilterTest;
+
+public class H2TemporalFilterTest extends JDBCTemporalFilterTest {
+
+ @Override
+ protected JDBCDateTestSetup createTestSetup() {
+ return new H2DateTestSetup();
+ }
+
+}
diff --git a/modules/plugin/jdbc/jdbc-mysql/src/main/java/org/geotools/data/mysql/MySQLDialect.java b/modules/plugin/jdbc/jdbc-mysql/src/main/java/org/geotools/data/mysql/MySQLDialect.java
index 9034333..6629104 100644
--- a/modules/plugin/jdbc/jdbc-mysql/src/main/java/org/geotools/data/mysql/MySQLDialect.java
+++ b/modules/plugin/jdbc/jdbc-mysql/src/main/java/org/geotools/data/mysql/MySQLDialect.java
@@ -141,12 +141,12 @@ public class MySQLDialect extends SQLDialect {
//first check the geometry_columns table
StringBuffer sql = new StringBuffer();
sql.append("SELECT ");
- encodeColumnName("srid", sql);
+ encodeColumnName(null, "srid", sql);
sql.append(" FROM ");
encodeTableName("geometry_columns", sql);
sql.append(" WHERE ");
- encodeColumnName("f_table_schema", sql);
+ encodeColumnName(null, "f_table_schema", sql);
if (schemaName != null) {
sql.append( " = '").append(schemaName).append("'");
@@ -156,10 +156,10 @@ public class MySQLDialect extends SQLDialect {
}
sql.append(" AND ");
- encodeColumnName("f_table_name", sql);
+ encodeColumnName(null, "f_table_name", sql);
sql.append(" = '").append(tableName).append("' AND ");
- encodeColumnName("f_geometry_column", sql);
+ encodeColumnName(null, "f_geometry_column", sql);
sql.append(" = '").append(columnName).append("'");
dataStore.getLogger().fine(sql.toString());
@@ -186,7 +186,7 @@ public class MySQLDialect extends SQLDialect {
//execute SELECT srid() FROM LIMIT 1;
sql = new StringBuffer();
sql.append("SELECT srid(");
- encodeColumnName(columnName, sql);
+ encodeColumnName(null, columnName, sql);
sql.append(") ");
sql.append("FROM ");
@@ -197,7 +197,7 @@ public class MySQLDialect extends SQLDialect {
encodeSchemaName(tableName, sql);
sql.append(" WHERE ");
- encodeColumnName(columnName, sql);
+ encodeColumnName(null, columnName, sql);
sql.append(" is not null LIMIT 1");
dataStore.getLogger().fine(sql.toString());
@@ -221,16 +221,18 @@ public class MySQLDialect extends SQLDialect {
}
}
- public void encodeGeometryColumn(GeometryDescriptor gatt, int srid, StringBuffer sql) {
+ @Override
+ public void encodeGeometryColumn(GeometryDescriptor gatt, String prefix, int srid,
+ StringBuffer sql) {
sql.append("asWKB(");
- encodeColumnName(gatt.getLocalName(), sql);
+ encodeColumnName(prefix, gatt.getLocalName(), sql);
sql.append(")");
}
-
+
public void encodeGeometryEnvelope(String tableName, String geometryColumn, StringBuffer sql) {
sql.append("asWKB(");
sql.append("envelope(");
- encodeColumnName(geometryColumn, sql);
+ encodeColumnName(null, geometryColumn, sql);
sql.append("))");
}
@@ -335,12 +337,12 @@ public class MySQLDialect extends SQLDialect {
StringBuffer sql = new StringBuffer("CREATE TABLE ");
encodeTableName("geometry_columns", sql);
sql.append("(");
- encodeColumnName("f_table_schema", sql); sql.append(" varchar(255), ");
- encodeColumnName("f_table_name", sql); sql.append(" varchar(255), ");
- encodeColumnName("f_geometry_column", sql); sql.append(" varchar(255), ");
- encodeColumnName("coord_dimension", sql); sql.append(" int, ");
- encodeColumnName("srid", sql); sql.append(" int, ");
- encodeColumnName("type", sql); sql.append(" varchar(32)");
+ encodeColumnName(null, "f_table_schema", sql); sql.append(" varchar(255), ");
+ encodeColumnName(null, "f_table_name", sql); sql.append(" varchar(255), ");
+ encodeColumnName(null, "f_geometry_column", sql); sql.append(" varchar(255), ");
+ encodeColumnName(null, "coord_dimension", sql); sql.append(" int, ");
+ encodeColumnName(null, "srid", sql); sql.append(" int, ");
+ encodeColumnName(null, "type", sql); sql.append(" varchar(32)");
sql.append(")");
if (LOGGER.isLoggable(Level.FINE)) { LOGGER.fine(sql.toString()); }
@@ -367,7 +369,7 @@ public class MySQLDialect extends SQLDialect {
StringBuffer sql = new StringBuffer("ALTER TABLE ");
encodeTableName(featureType.getTypeName(), sql);
sql.append(" ADD SPATIAL INDEX (");
- encodeColumnName(gd.getLocalName(), sql);
+ encodeColumnName(null, gd.getLocalName(), sql);
sql.append(")");
LOGGER.fine( sql.toString() );
@@ -418,7 +420,7 @@ public class MySQLDialect extends SQLDialect {
}
public void encodePrimaryKey(String column, StringBuffer sql) {
- encodeColumnName(column, sql);
+ encodeColumnName(null, column, sql);
sql.append(" int AUTO_INCREMENT PRIMARY KEY");
}
diff --git a/modules/plugin/jdbc/jdbc-mysql/src/main/java/org/geotools/data/mysql/MySQLDialectBasic.java b/modules/plugin/jdbc/jdbc-mysql/src/main/java/org/geotools/data/mysql/MySQLDialectBasic.java
index 7f833d3..cad3d72 100644
--- a/modules/plugin/jdbc/jdbc-mysql/src/main/java/org/geotools/data/mysql/MySQLDialectBasic.java
+++ b/modules/plugin/jdbc/jdbc-mysql/src/main/java/org/geotools/data/mysql/MySQLDialectBasic.java
@@ -83,13 +83,14 @@ public class MySQLDialectBasic extends BasicSQLDialect {
}
@Override
- public void encodeColumnName(String raw, StringBuffer sql) {
- delegate.encodeColumnName(raw, sql);
+ public void encodeColumnName(String prefix, String raw, StringBuffer sql) {
+ delegate.encodeColumnName(prefix, raw, sql);
}
@Override
- public void encodeGeometryColumn(GeometryDescriptor gatt, int srid, StringBuffer sql) {
- delegate.encodeGeometryColumn(gatt, srid, sql);
+ public void encodeGeometryColumn(GeometryDescriptor gatt, String prefix, int srid,
+ StringBuffer sql) {
+ delegate.encodeGeometryColumn(gatt, prefix, srid, sql);
}
@Override
diff --git a/modules/plugin/jdbc/jdbc-mysql/src/main/java/org/geotools/data/mysql/MySQLDialectPrepared.java b/modules/plugin/jdbc/jdbc-mysql/src/main/java/org/geotools/data/mysql/MySQLDialectPrepared.java
index c50161d..95c306d 100644
--- a/modules/plugin/jdbc/jdbc-mysql/src/main/java/org/geotools/data/mysql/MySQLDialectPrepared.java
+++ b/modules/plugin/jdbc/jdbc-mysql/src/main/java/org/geotools/data/mysql/MySQLDialectPrepared.java
@@ -80,9 +80,9 @@ public class MySQLDialectPrepared extends PreparedStatementSQLDialect {
return delegate.getGeometrySRID(schemaName, tableName, columnName, cx);
}
- @Override
- public void encodeColumnName(String raw, StringBuffer sql) {
- delegate.encodeColumnName(raw, sql);
+ @Override
+ public void encodeColumnName(String prefix, String raw, StringBuffer sql) {
+ delegate.encodeColumnName(prefix, raw, sql);
}
@Override
@@ -91,9 +91,9 @@ public class MySQLDialectPrepared extends PreparedStatementSQLDialect {
}
@Override
- public void encodeGeometryColumn(GeometryDescriptor gatt, int srid,
+ public void encodeGeometryColumn(GeometryDescriptor gatt, String prefix, int srid,
StringBuffer sql) {
- delegate.encodeGeometryColumn(gatt, srid, sql);
+ delegate.encodeGeometryColumn(gatt, prefix, srid, sql);
}
@Override
diff --git a/modules/plugin/jdbc/jdbc-mysql/src/main/java/org/geotools/data/mysql/MySQLFilterToSQL.java b/modules/plugin/jdbc/jdbc-mysql/src/main/java/org/geotools/data/mysql/MySQLFilterToSQL.java
index abb8d5d..37c822a 100644
--- a/modules/plugin/jdbc/jdbc-mysql/src/main/java/org/geotools/data/mysql/MySQLFilterToSQL.java
+++ b/modules/plugin/jdbc/jdbc-mysql/src/main/java/org/geotools/data/mysql/MySQLFilterToSQL.java
@@ -20,6 +20,7 @@ import java.io.IOException;
import org.geotools.data.jdbc.FilterToSQL;
import org.geotools.filter.FilterCapabilities;
+import org.opengis.filter.expression.Expression;
import org.opengis.filter.expression.Literal;
import org.opengis.filter.expression.PropertyName;
import org.opengis.filter.spatial.BBOX;
@@ -72,18 +73,30 @@ public class MySQLFilterToSQL extends FilterToSQL {
}
out.write( "GeomFromText('"+g.toText()+"', "+currentSRID+")");
}
-
+
@Override
protected Object visitBinarySpatialOperator(BinarySpatialOperator filter,
PropertyName property, Literal geometry, boolean swapped, Object extraData) {
-
+ return visitBinarySpatialOperator(filter, (Expression)property, (Expression)geometry,
+ swapped, extraData);
+ }
+
+ @Override
+ protected Object visitBinarySpatialOperator(BinarySpatialOperator filter, Expression e1,
+ Expression e2, Object extraData) {
+ return visitBinarySpatialOperator(filter, e1, e2, false, extraData);
+ }
+
+ protected Object visitBinarySpatialOperator(BinarySpatialOperator filter, Expression e1,
+ Expression e2, boolean swapped, Object extraData) {
+
try {
if (!(filter instanceof Disjoint)) {
out.write("MbrIntersects(");
- property.accept(this, extraData);
+ e1.accept(this, extraData);
out.write(",");
- geometry.accept(this, extraData);
+ e2.accept(this, extraData);
out.write(")");
if (!(filter instanceof BBOX)) {
@@ -98,9 +111,9 @@ public class MySQLFilterToSQL extends FilterToSQL {
if (filter instanceof DistanceBufferOperator) {
out.write("Distance(");
- property.accept(this, extraData);
+ e1.accept(this, extraData);
out.write(", ");
- geometry.accept(this, extraData);
+ e2.accept(this, extraData);
out.write(")");
if (filter instanceof DWithin) {
@@ -148,14 +161,14 @@ public class MySQLFilterToSQL extends FilterToSQL {
}
if (swapped) {
- geometry.accept(this, extraData);
+ e2.accept(this, extraData);
out.write(", ");
- property.accept(this, extraData);
+ e1.accept(this, extraData);
}
else {
- property.accept(this, extraData);
+ e1.accept(this, extraData);
out.write(", ");
- geometry.accept(this, extraData);
+ e2.accept(this, extraData);
}
out.write(")");
diff --git a/modules/plugin/jdbc/jdbc-mysql/src/test/java/org/geotools/data/mysql/MySQLJoinTest.java b/modules/plugin/jdbc/jdbc-mysql/src/test/java/org/geotools/data/mysql/MySQLJoinTest.java
new file mode 100644
index 0000000..0ad0939
--- /dev/null
+++ b/modules/plugin/jdbc/jdbc-mysql/src/test/java/org/geotools/data/mysql/MySQLJoinTest.java
@@ -0,0 +1,29 @@
+/*
+ * GeoTools - The Open Source Java GIS Toolkit
+ * http://geotools.org
+ *
+ * (C) 2002-2011, Open Source Geospatial Foundation (OSGeo)
+ *
+ * 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.
+ */
+package org.geotools.data.mysql;
+
+import org.geotools.jdbc.JDBCJoinTest;
+import org.geotools.jdbc.JDBCJoinTestSetup;
+
+public class MySQLJoinTest extends JDBCJoinTest {
+
+ @Override
+ protected JDBCJoinTestSetup createTestSetup() {
+ return new MySQLJoinTestSetup();
+ }
+
+}
diff --git a/modules/plugin/jdbc/jdbc-mysql/src/test/java/org/geotools/data/mysql/MySQLJoinTestSetup.java b/modules/plugin/jdbc/jdbc-mysql/src/test/java/org/geotools/data/mysql/MySQLJoinTestSetup.java
new file mode 100644
index 0000000..b0d356e
--- /dev/null
+++ b/modules/plugin/jdbc/jdbc-mysql/src/test/java/org/geotools/data/mysql/MySQLJoinTestSetup.java
@@ -0,0 +1,66 @@
+/*
+ * GeoTools - The Open Source Java GIS Toolkit
+ * http://geotools.org
+ *
+ * (C) 2002-2011, Open Source Geospatial Foundation (OSGeo)
+ *
+ * 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.
+ */
+package org.geotools.data.mysql;
+
+import org.geotools.jdbc.JDBCDataStore;
+import org.geotools.jdbc.JDBCJoinTestSetup;
+
+public class MySQLJoinTestSetup extends JDBCJoinTestSetup {
+
+ public MySQLJoinTestSetup() {
+ super(new MySQLTestSetup());
+ }
+
+ @Override
+ protected void createJoinTable() throws Exception {
+ //create some data
+ StringBuffer sb = new StringBuffer();
+ sb.append("CREATE TABLE ftjoin ").append("(id int, ")
+ .append("name VARCHAR(255) COLLATE latin1_general_cs, geom POLYGON) ENGINE=InnoDB;");
+ run(sb.toString());
+
+ sb = new StringBuffer();
+ sb.append("INSERT INTO ftjoin VALUES (")
+ .append("0, 'zero', GeometryFromText('POLYGON ((-0.1 -0.1, -0.1 0.1, 0.1 0.1, 0.1 -0.1, -0.1 -0.1))',4326));");
+ run(sb.toString());
+
+ sb = new StringBuffer();
+ sb.append("INSERT INTO ftjoin VALUES (")
+ .append("1, 'one', GeometryFromText('POLYGON ((-1.1 -1.1, -1.1 1.1, 1.1 1.1, 1.1 -1.1, -1.1 -1.1))',4326));");
+ run(sb.toString());
+
+ sb = new StringBuffer();
+ sb.append("INSERT INTO ftjoin VALUES (")
+ .append("2, 'two', GeometryFromText('POLYGON ((-10 -10, -10 10, 10 10, 10 -10, -10 -10))',4326));");
+ run(sb.toString());
+
+ sb = new StringBuffer();
+ sb.append("INSERT INTO ftjoin VALUES (")
+ .append("3, 'three', NULL);");
+ run(sb.toString());
+ }
+
+ @Override
+ protected void dropJoinTable() throws Exception {
+ runSafe("DROP TABLE ftjoin");
+ }
+
+ @Override
+ protected void setUpDataStore(JDBCDataStore dataStore) {
+ dataStore.setDatabaseSchema(null);
+ }
+}
diff --git a/modules/plugin/jdbc/jdbc-oracle/src/main/java/org/geotools/data/oracle/OracleDialect.java b/modules/plugin/jdbc/jdbc-oracle/src/main/java/org/geotools/data/oracle/OracleDialect.java
index 9b4f847..f5c31ce 100644
--- a/modules/plugin/jdbc/jdbc-oracle/src/main/java/org/geotools/data/oracle/OracleDialect.java
+++ b/modules/plugin/jdbc/jdbc-oracle/src/main/java/org/geotools/data/oracle/OracleDialect.java
@@ -345,7 +345,15 @@ public class OracleDialect extends PreparedStatementSQLDialect {
}
@Override
- public void encodeColumnName(String raw, StringBuffer sql) {
+ public void encodeColumnName(String prefix, String raw, StringBuffer sql) {
+ if (prefix != null) {
+ prefix = prefix.toUpperCase();
+ if (prefix.length() > 30) {
+ prefix = prefix.substring(0,30);
+ }
+ sql.append(prefix).append(".");
+ }
+
raw = raw.toUpperCase();
if(raw.length() > 30)
raw = raw.substring(0, 30);
@@ -596,7 +604,7 @@ public class OracleDialect extends PreparedStatementSQLDialect {
@Override
public void encodeGeometryEnvelope(String tableName, String geometryColumn, StringBuffer sql) {
sql.append( "SDO_AGGR_MBR(");
- encodeColumnName(geometryColumn, sql);
+ encodeColumnName(null, geometryColumn, sql);
sql.append( ")");
}
diff --git a/modules/plugin/jdbc/jdbc-oracle/src/main/java/org/geotools/data/oracle/OracleFilterToSQL.java b/modules/plugin/jdbc/jdbc-oracle/src/main/java/org/geotools/data/oracle/OracleFilterToSQL.java
index 4df3482..e434138 100644
--- a/modules/plugin/jdbc/jdbc-oracle/src/main/java/org/geotools/data/oracle/OracleFilterToSQL.java
+++ b/modules/plugin/jdbc/jdbc-oracle/src/main/java/org/geotools/data/oracle/OracleFilterToSQL.java
@@ -30,6 +30,7 @@ import org.geotools.jdbc.PreparedFilterToSQL;
import org.geotools.jdbc.PreparedStatementSQLDialect;
import org.geotools.jdbc.SQLDialect;
import org.opengis.filter.Filter;
+import org.opengis.filter.expression.Expression;
import org.opengis.filter.expression.Literal;
import org.opengis.filter.expression.PropertyName;
import org.opengis.filter.spatial.BBOX;
@@ -45,6 +46,15 @@ import org.opengis.filter.spatial.Intersects;
import org.opengis.filter.spatial.Overlaps;
import org.opengis.filter.spatial.Touches;
import org.opengis.filter.spatial.Within;
+import org.opengis.filter.temporal.After;
+import org.opengis.filter.temporal.Before;
+import org.opengis.filter.temporal.Begins;
+import org.opengis.filter.temporal.BegunBy;
+import org.opengis.filter.temporal.During;
+import org.opengis.filter.temporal.EndedBy;
+import org.opengis.filter.temporal.Ends;
+import org.opengis.filter.temporal.TEquals;
+import org.opengis.filter.temporal.TOverlaps;
import com.vividsolutions.jts.geom.Envelope;
import com.vividsolutions.jts.geom.Geometry;
@@ -147,14 +157,55 @@ public class OracleFilterToSQL extends PreparedFilterToSQL {
caps.addType(DWithin.class);
caps.addType(Beyond.class);
+ //temporal filters
+ caps.addType(After.class);
+ caps.addType(Before.class);
+ caps.addType(Begins.class);
+ caps.addType(BegunBy.class);
+ caps.addType(During.class);
+ caps.addType(TOverlaps.class);
+ caps.addType(Ends.class);
+ caps.addType(EndedBy.class);
+ caps.addType(TEquals.class);
+
return caps;
}
@Override
protected Object visitBinarySpatialOperator(BinarySpatialOperator filter, PropertyName property,
Literal geometry, boolean swapped, Object extraData) {
+ return visitBinarySpatialOperator(filter, (Expression)property, (Expression) geometry,
+ swapped, extraData);
+ }
+
+ @Override
+ protected Object visitBinarySpatialOperator(BinarySpatialOperator filter, Expression e1,
+ Expression e2, Object extraData) {
+ return visitBinarySpatialOperator(filter, e1, e2, false, extraData);
+ }
+
+ protected Object visitBinarySpatialOperator(BinarySpatialOperator filter, Expression e1,
+ Expression e2, boolean swapped, Object extraData) {
+
try {
- Geometry eval = geometry.evaluate(filter, Geometry.class);
+ e1 = clipToWorld(filter, e1);
+ e2 = clipToWorld(filter, e2);
+
+ if(filter instanceof Beyond || filter instanceof DWithin)
+ doSDODistance(filter, e1, e2, extraData);
+ else if(filter instanceof BBOX && looseBBOXEnabled) {
+ doSDOFilter(filter, e1, e2, extraData);
+ } else
+ doSDORelate(filter, e1, e2, swapped, extraData);
+ } catch (IOException ioe) {
+ throw new RuntimeException(IO_ERROR, ioe);
+ }
+ return extraData;
+ }
+
+ Expression clipToWorld(BinarySpatialOperator filter, Expression e) {
+ if (e instanceof Literal) {
+ Geometry eval = e.evaluate(filter, Geometry.class);
// Oracle cannot deal with filters using geometries that span beyond the whole world
// in case the
if (dialect != null && isCurrentGeometryGeodetic() &&
@@ -165,22 +216,13 @@ public class OracleFilterToSQL extends PreparedFilterToSQL {
if(result instanceof GeometryCollection) {
result = distillSameTypeGeometries((GeometryCollection) result, eval);
}
- geometry = new FilterFactoryImpl().createLiteralExpression(result);
+ e = new FilterFactoryImpl().createLiteralExpression(result);
}
}
-
- if(filter instanceof Beyond || filter instanceof DWithin)
- doSDODistance(filter, property, geometry, extraData);
- else if(filter instanceof BBOX && looseBBOXEnabled) {
- doSDOFilter(filter, property, geometry, extraData);
- } else
- doSDORelate(filter, property, geometry, swapped, extraData);
- } catch (IOException ioe) {
- throw new RuntimeException(IO_ERROR, ioe);
}
- return extraData;
+ return e;
}
-
+
/**
* Returns true if the current geometry has the geodetic marker raised
* @return
@@ -222,11 +264,11 @@ public class OracleFilterToSQL extends PreparedFilterToSQL {
}
}
- protected void doSDOFilter(Filter filter, PropertyName property, Literal geometry, Object extraData) throws IOException {
+ protected void doSDOFilter(Filter filter, Expression e1, Expression e2, Object extraData) throws IOException {
out.write("SDO_FILTER(");
- property.accept(this, extraData);
+ e1.accept(this, extraData);
out.write(", ");
- geometry.accept(this, extraData);
+ e2.accept(this, extraData);
// for backwards compatibility with Oracle 9 we add the mask and querytypes params
out.write(", 'mask=anyinteract querytype=WINDOW') = 'TRUE' ");
}
@@ -238,7 +280,7 @@ public class OracleFilterToSQL extends PreparedFilterToSQL {
* @param geometry
* @param extraData
*/
- protected void doSDORelate(Filter filter, PropertyName property, Literal geometry, boolean swapped, Object extraData) throws IOException {
+ protected void doSDORelate(Filter filter, Expression e1, Expression e2, boolean swapped, Object extraData) throws IOException {
// grab the operating mask
String mask = null;
for (Class filterClass : SDO_RELATE_MASK_MAP.keySet()) {
@@ -252,9 +294,9 @@ public class OracleFilterToSQL extends PreparedFilterToSQL {
// ok, ready to write out the SDO_RELATE
out.write("SDO_RELATE(");
- property.accept(this, extraData);
+ e1.accept(this, extraData);
out.write(", ");
- geometry.accept(this, extraData);
+ e2.accept(this, extraData);
// for disjoint we ask for no interaction, anyinteract == false
if(filter instanceof Disjoint) {
out.write(", 'mask=ANYINTERACT querytype=WINDOW') <> 'TRUE' ");
@@ -264,15 +306,15 @@ public class OracleFilterToSQL extends PreparedFilterToSQL {
}
protected void doSDODistance(BinarySpatialOperator filter,
- PropertyName property, Literal geometry, Object extraData) throws IOException {
+ Expression e1, Expression e2, Object extraData) throws IOException {
double distance = ((DistanceBufferOperator) filter).getDistance();
String unit = ((DistanceBufferOperator) filter).getDistanceUnits();
String within = filter instanceof DWithin ? "TRUE" : "FALSE";
out.write("SDO_WITHIN_DISTANCE(");
- property.accept(this, extraData);
+ e1.accept(this, extraData);
out.write(",");
- geometry.accept(this, extraData);
+ e2.accept(this, extraData);
// encode the unit verbatim when available
if(unit != null && !"".equals(unit.trim()))
diff --git a/modules/plugin/jdbc/jdbc-oracle/src/test/java/org/geotools/data/oracle/OracleJoinTest.java b/modules/plugin/jdbc/jdbc-oracle/src/test/java/org/geotools/data/oracle/OracleJoinTest.java
new file mode 100644
index 0000000..a954ebf
--- /dev/null
+++ b/modules/plugin/jdbc/jdbc-oracle/src/test/java/org/geotools/data/oracle/OracleJoinTest.java
@@ -0,0 +1,29 @@
+/*
+ * GeoTools - The Open Source Java GIS Toolkit
+ * http://geotools.org
+ *
+ * (C) 2002-2011, Open Source Geospatial Foundation (OSGeo)
+ *
+ * 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.
+ */
+package org.geotools.data.oracle;
+
+import org.geotools.jdbc.JDBCJoinTest;
+import org.geotools.jdbc.JDBCJoinTestSetup;
+
+public class OracleJoinTest extends JDBCJoinTest {
+
+ @Override
+ protected JDBCJoinTestSetup createTestSetup() {
+ return new OracleJoinTestSetup();
+ }
+
+}
diff --git a/modules/plugin/jdbc/jdbc-oracle/src/test/java/org/geotools/data/oracle/OracleJoinTestSetup.java b/modules/plugin/jdbc/jdbc-oracle/src/test/java/org/geotools/data/oracle/OracleJoinTestSetup.java
new file mode 100644
index 0000000..d82a65e
--- /dev/null
+++ b/modules/plugin/jdbc/jdbc-oracle/src/test/java/org/geotools/data/oracle/OracleJoinTestSetup.java
@@ -0,0 +1,67 @@
+/*
+ * GeoTools - The Open Source Java GIS Toolkit
+ * http://geotools.org
+ *
+ * (C) 2002-2011, Open Source Geospatial Foundation (OSGeo)
+ *
+ * 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.
+ */
+package org.geotools.data.oracle;
+
+import org.geotools.jdbc.JDBCJoinTestSetup;
+
+public class OracleJoinTestSetup extends JDBCJoinTestSetup {
+
+ public OracleJoinTestSetup() {
+ super(new OracleTestSetup());
+ }
+
+ @Override
+ protected void createJoinTable() throws Exception {
+ String sql = "CREATE TABLE ftjoin ("
+ + "id INT, name VARCHAR(255), geom MDSYS.SDO_GEOMETRY)";
+ run(sql);
+
+ sql = "INSERT INTO USER_SDO_GEOM_METADATA (TABLE_NAME, COLUMN_NAME, DIMINFO, SRID ) " +
+ "VALUES ('ftjoin','geom',MDSYS.SDO_DIM_ARRAY(MDSYS.SDO_DIM_ELEMENT('X',-180,180,0.5), " +
+ "MDSYS.SDO_DIM_ELEMENT('Y',-90,90,0.5)), 4326)";
+ run(sql);
+
+ sql = "CREATE INDEX ftjoin_GEOMETRY_IDX ON FTJOIN(GEOM) INDEXTYPE IS MDSYS.SPATIAL_INDEX" //
+ + " PARAMETERS ('SDO_INDX_DIMS=2 LAYER_GTYPE=\"POLYGON\"')";
+ run(sql);
+
+ sql = "INSERT INTO ftjoin VALUES (0, 'zero', MDSYS.SDO_GEOMETRY(2003, 4326, NULL," +
+ " MDSYS.SDO_ELEM_INFO_ARRAY(1,1003,1), " +
+ " MDSYS.SDO_ORDINATE_ARRAY(-0.1,-0.1, -0.1,0.1, 0.1,0.1, 0.1,-0.1, -0.1,-0.1)))";
+ run(sql);
+
+ sql = "INSERT INTO ftjoin VALUES (1, 'one', MDSYS.SDO_GEOMETRY(2003, 4326, NULL," +
+ " MDSYS.SDO_ELEM_INFO_ARRAY(1,1003,1), " +
+ " MDSYS.SDO_ORDINATE_ARRAY(-1.1,-1.1, -1.1,1.1, 1.1,1.1, 1.1,-1.1, -1.1,-1.1)))";
+ run(sql);
+
+ sql = "INSERT INTO ftjoin VALUES (2, 'two', MDSYS.SDO_GEOMETRY(2003, 4326, NULL," +
+ " MDSYS.SDO_ELEM_INFO_ARRAY(1,1003,1), " +
+ " MDSYS.SDO_ORDINATE_ARRAY(-10,-10, -10,10, 10,10, 10,-10, -10,-10)))";
+ run(sql);
+
+ sql = "INSERT INTO ftjoin VALUES (3, 'three', NULL)";
+ run(sql);
+ }
+
+ @Override
+ protected void dropJoinTable() throws Exception {
+ runSafe("DELETE FROM USER_SDO_GEOM_METADATA WHERE TABLE_NAME = 'FTJOIN'");
+ runSafe("DROP TABLE ftjoin purge");
+ }
+
+}
diff --git a/modules/plugin/jdbc/jdbc-oracle/src/test/java/org/geotools/data/oracle/OracleTemporalFilterTest.java b/modules/plugin/jdbc/jdbc-oracle/src/test/java/org/geotools/data/oracle/OracleTemporalFilterTest.java
new file mode 100644
index 0000000..9ee447b
--- /dev/null
+++ b/modules/plugin/jdbc/jdbc-oracle/src/test/java/org/geotools/data/oracle/OracleTemporalFilterTest.java
@@ -0,0 +1,13 @@
+package org.geotools.data.oracle;
+
+import org.geotools.jdbc.JDBCDateTestSetup;
+import org.geotools.jdbc.JDBCTemporalFilterTest;
+
+public class OracleTemporalFilterTest extends JDBCTemporalFilterTest {
+
+ @Override
+ protected JDBCDateTestSetup createTestSetup() {
+ return new OracleDateTestSetup(new OracleTestSetup());
+ }
+
+}
diff --git a/modules/plugin/jdbc/jdbc-postgis/src/main/java/org/geotools/data/postgis/FilterToSqlHelper.java b/modules/plugin/jdbc/jdbc-postgis/src/main/java/org/geotools/data/postgis/FilterToSqlHelper.java
index 27750f9..c9a232f 100644
--- a/modules/plugin/jdbc/jdbc-postgis/src/main/java/org/geotools/data/postgis/FilterToSqlHelper.java
+++ b/modules/plugin/jdbc/jdbc-postgis/src/main/java/org/geotools/data/postgis/FilterToSqlHelper.java
@@ -69,6 +69,15 @@ import org.opengis.filter.spatial.Intersects;
import org.opengis.filter.spatial.Overlaps;
import org.opengis.filter.spatial.Touches;
import org.opengis.filter.spatial.Within;
+import org.opengis.filter.temporal.After;
+import org.opengis.filter.temporal.Before;
+import org.opengis.filter.temporal.Begins;
+import org.opengis.filter.temporal.BegunBy;
+import org.opengis.filter.temporal.During;
+import org.opengis.filter.temporal.EndedBy;
+import org.opengis.filter.temporal.Ends;
+import org.opengis.filter.temporal.TEquals;
+import org.opengis.filter.temporal.TOverlaps;
import com.vividsolutions.jts.geom.Envelope;
import com.vividsolutions.jts.geom.Geometry;
@@ -108,6 +117,17 @@ class FilterToSqlHelper {
caps.addType(DWithin.class);
caps.addType(Beyond.class);
+ //temporal filters
+ caps.addType(After.class);
+ caps.addType(Before.class);
+ caps.addType(Begins.class);
+ caps.addType(BegunBy.class);
+ caps.addType(During.class);
+ caps.addType(TOverlaps.class);
+ caps.addType(Ends.class);
+ caps.addType(EndedBy.class);
+ caps.addType(TEquals.class);
+
if(encodeFunctions) {
// add support for string functions
caps.addType(FilterFunction_strConcat.class);
@@ -153,6 +173,16 @@ class FilterToSqlHelper {
return extraData;
}
+ protected Object visitBinarySpatialOperator(BinarySpatialOperator filter, Expression e1,
+ Expression e2, Object extraData) {
+
+ try {
+ visitBinarySpatialOperator(filter, e1, e2, false, extraData);
+ } catch (IOException e) {
+ throw new RuntimeException(IO_ERROR, e);
+ }
+ return extraData;
+ }
void visitDistanceSpatialOperator(DistanceBufferOperator filter,
PropertyName property, Literal geometry, boolean swapped,
Object extraData) throws IOException {
@@ -212,6 +242,12 @@ class FilterToSqlHelper {
out.write(" AND ");
}
+ visitBinarySpatialOperator(filter, (Expression)property, (Expression)geometry, swapped, extraData);
+ }
+
+ void visitBinarySpatialOperator(BinarySpatialOperator filter, Expression e1, Expression e2,
+ boolean swapped, Object extraData) throws IOException {
+
String closingParenthesis = ")";
if (filter instanceof Equals) {
out.write("ST_Equals");
@@ -241,13 +277,13 @@ class FilterToSqlHelper {
}
out.write("(");
- property.accept(delegate, extraData);
+ e1.accept(delegate, extraData);
out.write(", ");
- geometry.accept(delegate, extraData);
+ e2.accept(delegate, extraData);
out.write(closingParenthesis);
}
-
+
boolean isCurrentGeography() {
AttributeDescriptor geom = null;
if(delegate instanceof PostgisPSFilterToSql) {
diff --git a/modules/plugin/jdbc/jdbc-postgis/src/main/java/org/geotools/data/postgis/PostGISDialect.java b/modules/plugin/jdbc/jdbc-postgis/src/main/java/org/geotools/data/postgis/PostGISDialect.java
index 180c6b8..03bb2fb 100644
--- a/modules/plugin/jdbc/jdbc-postgis/src/main/java/org/geotools/data/postgis/PostGISDialect.java
+++ b/modules/plugin/jdbc/jdbc-postgis/src/main/java/org/geotools/data/postgis/PostGISDialect.java
@@ -187,7 +187,7 @@ public class PostGISDialect extends BasicSQLDialect {
}
@Override
- public void encodeGeometryColumn(GeometryDescriptor gatt, int srid,
+ public void encodeGeometryColumn(GeometryDescriptor gatt, String prefix, int srid,
StringBuffer sql) {
boolean geography = "geography".equals(gatt.getUserData().get(JDBCDataStore.JDBC_NATIVE_TYPENAME));
@@ -198,7 +198,7 @@ public class PostGISDialect extends BasicSQLDialect {
sql.append("ST_Force_2D(");
}
- encodeColumnName(gatt.getLocalName(), sql);
+ encodeColumnName(prefix, gatt.getLocalName(), sql);
if (!geography) {
sql.append(")");
}
diff --git a/modules/plugin/jdbc/jdbc-postgis/src/main/java/org/geotools/data/postgis/PostGISPSDialect.java b/modules/plugin/jdbc/jdbc-postgis/src/main/java/org/geotools/data/postgis/PostGISPSDialect.java
index 6eddd48..4902d36 100644
--- a/modules/plugin/jdbc/jdbc-postgis/src/main/java/org/geotools/data/postgis/PostGISPSDialect.java
+++ b/modules/plugin/jdbc/jdbc-postgis/src/main/java/org/geotools/data/postgis/PostGISPSDialect.java
@@ -78,13 +78,12 @@ public class PostGISPSDialect extends PreparedStatementSQLDialect {
.decodeGeometryValue(descriptor, rs, column, factory, cx);
}
-
- public void encodeGeometryColumn(GeometryDescriptor gatt, int srid,
+ @Override
+ public void encodeGeometryColumn(GeometryDescriptor gatt, String prefix, int srid,
StringBuffer sql) {
- delegate.encodeGeometryColumn(gatt, srid, sql);
+ delegate.encodeGeometryColumn(gatt, prefix, srid, sql);
}
-
public void encodeGeometryEnvelope(String tableName, String geometryColumn,
StringBuffer sql) {
delegate.encodeGeometryEnvelope(tableName, geometryColumn, sql);
diff --git a/modules/plugin/jdbc/jdbc-postgis/src/main/java/org/geotools/data/postgis/PostgisFilterToSQL.java b/modules/plugin/jdbc/jdbc-postgis/src/main/java/org/geotools/data/postgis/PostgisFilterToSQL.java
index c1b9427..d90884e 100644
--- a/modules/plugin/jdbc/jdbc-postgis/src/main/java/org/geotools/data/postgis/PostgisFilterToSQL.java
+++ b/modules/plugin/jdbc/jdbc-postgis/src/main/java/org/geotools/data/postgis/PostgisFilterToSQL.java
@@ -23,6 +23,7 @@ import org.geotools.filter.FilterCapabilities;
import org.geotools.jdbc.JDBCDataStore;
import org.opengis.feature.type.GeometryDescriptor;
import org.opengis.filter.expression.Add;
+import org.opengis.filter.expression.Expression;
import org.opengis.filter.expression.Function;
import org.opengis.filter.expression.Literal;
import org.opengis.filter.expression.PropertyName;
@@ -95,6 +96,12 @@ public class PostgisFilterToSQL extends FilterToSQL {
swapped, extraData);
}
+ protected Object visitBinarySpatialOperator(BinarySpatialOperator filter, Expression e1,
+ Expression e2, Object extraData) {
+ helper.out = out;
+ return helper.visitBinarySpatialOperator(filter, e1, e2, extraData);
+ }
+
GeometryDescriptor getCurrentGeometry() {
return currentGeometry;
}
diff --git a/modules/plugin/jdbc/jdbc-postgis/src/main/java/org/geotools/data/postgis/PostgisPSFilterToSql.java b/modules/plugin/jdbc/jdbc-postgis/src/main/java/org/geotools/data/postgis/PostgisPSFilterToSql.java
index a8205e9..42c8077 100644
--- a/modules/plugin/jdbc/jdbc-postgis/src/main/java/org/geotools/data/postgis/PostgisPSFilterToSql.java
+++ b/modules/plugin/jdbc/jdbc-postgis/src/main/java/org/geotools/data/postgis/PostgisPSFilterToSql.java
@@ -19,6 +19,7 @@ package org.geotools.data.postgis;
import org.geotools.filter.FilterCapabilities;
import org.geotools.jdbc.PreparedFilterToSQL;
import org.opengis.feature.type.GeometryDescriptor;
+import org.opengis.filter.expression.Expression;
import org.opengis.filter.expression.Literal;
import org.opengis.filter.expression.PropertyName;
import org.opengis.filter.spatial.BinarySpatialOperator;
@@ -58,7 +59,13 @@ public class PostgisPSFilterToSql extends PreparedFilterToSQL {
helper.out = out;
return helper.visitBinarySpatialOperator(filter, property, geometry, swapped, extraData);
}
-
+
+ protected Object visitBinarySpatialOperator(BinarySpatialOperator filter, Expression e1,
+ Expression e2, Object extraData) {
+ helper.out = out;
+ return helper.visitBinarySpatialOperator(filter, e1, e2, extraData);
+ }
+
GeometryDescriptor getCurrentGeometry() {
return currentGeometry;
}
diff --git a/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/PostgisJoinTest.java b/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/PostgisJoinTest.java
new file mode 100644
index 0000000..61b413a
--- /dev/null
+++ b/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/PostgisJoinTest.java
@@ -0,0 +1,29 @@
+/*
+ * GeoTools - The Open Source Java GIS Toolkit
+ * http://geotools.org
+ *
+ * (C) 2002-2011, Open Source Geospatial Foundation (OSGeo)
+ *
+ * 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.
+ */
+package org.geotools.data.postgis;
+
+import org.geotools.jdbc.JDBCJoinTest;
+import org.geotools.jdbc.JDBCJoinTestSetup;
+
+public class PostgisJoinTest extends JDBCJoinTest {
+
+ @Override
+ protected JDBCJoinTestSetup createTestSetup() {
+ return new PostgisJoinTestSetup();
+ }
+
+}
diff --git a/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/PostgisJoinTestSetup.java b/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/PostgisJoinTestSetup.java
new file mode 100644
index 0000000..d2d1fc1
--- /dev/null
+++ b/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/PostgisJoinTestSetup.java
@@ -0,0 +1,49 @@
+/*
+ * GeoTools - The Open Source Java GIS Toolkit
+ * http://geotools.org
+ *
+ * (C) 2002-2011, Open Source Geospatial Foundation (OSGeo)
+ *
+ * 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.
+ */
+package org.geotools.data.postgis;
+
+import org.geotools.jdbc.JDBCJoinTestSetup;
+import org.geotools.jdbc.JDBCTestSetup;
+
+public class PostgisJoinTestSetup extends JDBCJoinTestSetup {
+
+ public PostgisJoinTestSetup() {
+ this(new PostGISTestSetup());
+ }
+
+ public PostgisJoinTestSetup(JDBCTestSetup setup) {
+ super(setup);
+ }
+
+ @Override
+ protected void createJoinTable() throws Exception {
+ run("CREATE TABLE \"ftjoin\" ( \"id\" int, " + "\"name\" VARCHAR, \"geom\" GEOMETRY)" );
+ run("INSERT INTO geometry_columns VALUES ('', 'public', 'ftjoin', 'geom', 2, 4326, 'GEOMETRY')");
+
+ run( "INSERT INTO \"ftjoin\" VALUES (0, 'zero', ST_GeomFromText('POLYGON ((-0.1 -0.1, -0.1 0.1, 0.1 0.1, 0.1 -0.1, -0.1 -0.1))', 4326))");
+ run( "INSERT INTO \"ftjoin\" VALUES (1, 'one', ST_GeomFromText('POLYGON ((-1.1 -1.1, -1.1 1.1, 1.1 1.1, 1.1 -1.1, -1.1 -1.1))', 4326))");
+ run( "INSERT INTO \"ftjoin\" VALUES (2, 'two', ST_GeomFromText('POLYGON ((-10 -10, -10 10, 10 10, 10 -10, -10 -10))', 4326))");
+ run( "INSERT INTO \"ftjoin\" VALUES (3, 'three', NULL)");
+ }
+
+ @Override
+ protected void dropJoinTable() throws Exception {
+ run( "DROP TABLE \"ftjoin\"" );
+ run( "DELETE FROM geometry_columns WHERE f_table_name = 'ftjoin'");
+ }
+
+}
diff --git a/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/PostgisTemporalFilterTest.java b/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/PostgisTemporalFilterTest.java
new file mode 100644
index 0000000..2a9465a
--- /dev/null
+++ b/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/PostgisTemporalFilterTest.java
@@ -0,0 +1,13 @@
+package org.geotools.data.postgis;
+
+import org.geotools.jdbc.JDBCDateTestSetup;
+import org.geotools.jdbc.JDBCTemporalFilterTest;
+
+public class PostgisTemporalFilterTest extends JDBCTemporalFilterTest {
+
+ @Override
+ protected JDBCDateTestSetup createTestSetup() {
+ return new PostgisDateTestSetup(new PostGISTestSetup());
+ }
+
+}
diff --git a/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/ps/PostgisJoinTest.java b/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/ps/PostgisJoinTest.java
new file mode 100644
index 0000000..e178c11
--- /dev/null
+++ b/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/ps/PostgisJoinTest.java
@@ -0,0 +1,30 @@
+/*
+ * GeoTools - The Open Source Java GIS Toolkit
+ * http://geotools.org
+ *
+ * (C) 2002-2011, Open Source Geospatial Foundation (OSGeo)
+ *
+ * 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.
+ */
+package org.geotools.data.postgis.ps;
+
+import org.geotools.data.postgis.PostgisJoinTestSetup;
+import org.geotools.jdbc.JDBCJoinTest;
+import org.geotools.jdbc.JDBCJoinTestSetup;
+
+public class PostgisJoinTest extends JDBCJoinTest {
+
+ @Override
+ protected JDBCJoinTestSetup createTestSetup() {
+ return new PostgisJoinTestSetup(new PostGISPSTestSetup());
+ }
+
+}
diff --git a/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/ps/PostgisTemporalFilterTest.java b/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/ps/PostgisTemporalFilterTest.java
new file mode 100644
index 0000000..73249a7
--- /dev/null
+++ b/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/ps/PostgisTemporalFilterTest.java
@@ -0,0 +1,14 @@
+package org.geotools.data.postgis.ps;
+
+import org.geotools.data.postgis.PostgisDateTestSetup;
+import org.geotools.jdbc.JDBCDateTestSetup;
+import org.geotools.jdbc.JDBCTemporalFilterTest;
+
+public class PostgisTemporalFilterTest extends JDBCTemporalFilterTest {
+
+ @Override
+ protected JDBCDateTestSetup createTestSetup() {
+ return new PostgisDateTestSetup(new PostGISPSTestSetup());
+ }
+
+}
diff --git a/modules/plugin/jdbc/jdbc-spatialite/src/main/java/org/geotools/data/spatialite/SpatiaLiteDialect.java b/modules/plugin/jdbc/jdbc-spatialite/src/main/java/org/geotools/data/spatialite/SpatiaLiteDialect.java
index 3d1d976..4fefba9 100644
--- a/modules/plugin/jdbc/jdbc-spatialite/src/main/java/org/geotools/data/spatialite/SpatiaLiteDialect.java
+++ b/modules/plugin/jdbc/jdbc-spatialite/src/main/java/org/geotools/data/spatialite/SpatiaLiteDialect.java
@@ -199,9 +199,9 @@ public class SpatiaLiteDialect extends BasicSQLDialect {
}
@Override
- public void encodeGeometryColumn(GeometryDescriptor gatt, int srid, StringBuffer sql) {
+ public void encodeGeometryColumn(GeometryDescriptor gatt, String prefix, int srid, StringBuffer sql) {
sql.append( "AsText(");
- encodeColumnName( gatt.getLocalName(), sql);
+ encodeColumnName( prefix, gatt.getLocalName(), sql);
sql.append( ")||';").append(srid).append("'");
}
@@ -239,7 +239,7 @@ public class SpatiaLiteDialect extends BasicSQLDialect {
@Override
public void encodeGeometryEnvelope(String tableName, String geometryColumn, StringBuffer sql) {
sql.append("asText(envelope(");
- encodeColumnName(geometryColumn, sql);
+ encodeColumnName(null, geometryColumn, sql);
sql.append( "))");
}
diff --git a/modules/plugin/jdbc/jdbc-sqlserver/src/main/java/org/geotools/data/sqlserver/SQLServerDialect.java b/modules/plugin/jdbc/jdbc-sqlserver/src/main/java/org/geotools/data/sqlserver/SQLServerDialect.java
index ea2c86e..6de1520 100644
--- a/modules/plugin/jdbc/jdbc-sqlserver/src/main/java/org/geotools/data/sqlserver/SQLServerDialect.java
+++ b/modules/plugin/jdbc/jdbc-sqlserver/src/main/java/org/geotools/data/sqlserver/SQLServerDialect.java
@@ -132,7 +132,7 @@ public class SQLServerDialect extends BasicSQLDialect {
sql.append( " ON ");
encodeTableName(featureType.getTypeName(), sql);
sql.append("(");
- encodeColumnName(gd.getLocalName(), sql);
+ encodeColumnName(null, gd.getLocalName(), sql);
sql.append(")");
sql.append( " WITH ( BOUNDING_BOX = ").append(bbox).append(")");
@@ -151,14 +151,14 @@ public class SQLServerDialect extends BasicSQLDialect {
String columnName, Connection cx) throws SQLException {
StringBuffer sql = new StringBuffer("SELECT ");
- encodeColumnName(columnName, sql);
+ encodeColumnName(null, columnName, sql);
sql.append( ".STSrid");
sql.append( " FROM ");
encodeTableName(schemaName, tableName, sql, true);
sql.append( " WHERE ");
- encodeColumnName(columnName, sql );
+ encodeColumnName(null, columnName, sql );
sql.append( " IS NOT NULL");
dataStore.getLogger().fine( sql.toString() );
@@ -183,14 +183,14 @@ public class SQLServerDialect extends BasicSQLDialect {
}
@Override
- public void encodeGeometryColumn(GeometryDescriptor gatt, int srid, StringBuffer sql) {
+ public void encodeGeometryColumn(GeometryDescriptor gatt, String prefix, int srid, StringBuffer sql) {
sql.append( "CAST(");
- encodeColumnName( gatt.getLocalName(), sql );
+ encodeColumnName( prefix, gatt.getLocalName(), sql );
sql.append( ".STSrid as VARCHAR)");
sql.append( " + ':' + " );
- encodeColumnName( gatt.getLocalName(), sql );
+ encodeColumnName( prefix, gatt.getLocalName(), sql );
sql.append( ".STAsText()");
//encodeColumnName(gatt.getLocalName(), sql);
@@ -253,12 +253,12 @@ public class SQLServerDialect extends BasicSQLDialect {
public void encodeGeometryEnvelope(String tableName, String geometryColumn,
StringBuffer sql) {
sql.append( "CAST(");
- encodeColumnName( geometryColumn, sql );
+ encodeColumnName( null, geometryColumn, sql );
sql.append( ".STSrid as VARCHAR)");
sql.append( " + ':' + " );
- encodeColumnName( geometryColumn, sql );
+ encodeColumnName( null, geometryColumn, sql );
sql.append( ".STEnvelope().ToString()");
}