Class FilterToSQL

  • All Implemented Interfaces:
    ExpressionVisitor, FilterVisitor
    Direct Known Subclasses:
    H2FilterToSQL, H2GISFilterToSQL, InformixFilterToSQL, MySQLFilterToSQL, NestedFilterToSQL, PostgisFilterToSQL, PreparedFilterToSQL, SQLServerFilterToSQL

    public class FilterToSQL
    extends Object
    implements FilterVisitor, ExpressionVisitor
    Encodes a filter into a SQL WHERE statement. It should hopefully be generic enough that any SQL database will work with it. This generic SQL encoder should eventually be able to encode all filters except Geometry Filters. This is because the OGC's SFS for SQL document specifies two ways of doing SQL databases, one with native geometry types and one without. To implement an encoder for one of the two types simply subclass off of this encoder and put in the proper GeometryFilter visit method. Then add the filter types supported to the capabilities by overriding the {createFilterCapabilities() method.

    The output Writer can be provided either through the constructor, or with a setWriter(Writer). It must be provided before a call to encode.

    Note that the class isn't thread-safe and a new object should be created for each call to any of the encode functions.

    Author:
    originally by Chris Holmes, TOPP, ported by Saul Farber, MassGIS
    • Field Detail

      • filterFactory

        protected static FilterFactory filterFactory
        filter factory
      • capabilities

        protected FilterCapabilities capabilities
        The filter types that this class can encode
      • LOGGER

        protected static Logger LOGGER
        Standard java logger
      • sqlNameEscape

        protected String sqlNameEscape
        Character used to escape database schema, table and column names
      • out

        protected Writer out
        where to write the constructed string from visiting the filters.
      • primaryKey

        protected PrimaryKey primaryKey
        The primary key corresponding to the table the filter is being encoded against.
      • databaseSchema

        protected String databaseSchema
        The schema that contains the table the filter being encoded against.
      • featureType

        protected SimpleFeatureType featureType
        the schmema the encoder will be used to be encode sql for
      • encodingFunction

        protected boolean encodingFunction
        flag which indicates that the encoder is currently encoding a function
      • currentGeometry

        protected GeometryDescriptor currentGeometry
        the geometry descriptor corresponding to the current binary spatial filter being encoded
      • currentSRID

        protected Integer currentSRID
        the srid corresponding to the current binary spatial filter being encoded
      • currentDimension

        protected Integer currentDimension
        The dimension corresponding to the current binary spatial filter being encoded
      • inline

        protected boolean inline
        inline flag, controlling whether "WHERE" will prefix the SQL encoded filter
      • inEncodingEnabled

        protected boolean inEncodingEnabled
        Whether the encoder should try to encode "in" function into a SQL IN operator
      • escapeBackslash

        protected boolean escapeBackslash
        Whether to escape backslash characters in string literals
    • Constructor Detail

      • FilterToSQL

        public FilterToSQL()
        Default constructor
      • FilterToSQL

        public FilterToSQL​(Writer out)
    • Method Detail

      • setWriter

        public void setWriter​(Writer out)
        Sets the writer the encoder will write to.
      • setInline

        public void setInline​(boolean inline)
      • isInEncodingEnabled

        public boolean isInEncodingEnabled()
        Whether "in" like functions are encoded in SQL or not
        Returns:
        a boolean value, true if the in linke functions are encoded
      • setInEncodingEnabled

        public void setInEncodingEnabled​(boolean inEncodingEnabled)
        Makes the encoder translate in like functions into SQL (see also InFunction.isInFunction(Expression)
        Parameters:
        inEncodingEnabled - the new flag controlling in encoding
      • isEscapeBackslash

        public boolean isEscapeBackslash()
        Returns:
        whether to escape backslash characters in string literals
      • setEscapeBackslash

        public void setEscapeBackslash​(boolean escapeBackslash)
        Parameters:
        escapeBackslash - whether to escape backslash characters in string literals
      • encode

        public void encode​(Filter filter)
                    throws FilterToSQLException
        Performs the encoding, sends the encoded sql to the writer passed in.
        Parameters:
        filter - the Filter to be encoded.
        Throws:
        FilterToSQLException - If filter type not supported, or if there were io problems.
      • encodeToString

        public String encodeToString​(Filter filter)
                              throws FilterToSQLException
        purely a convenience method.

        Equivalent to:

        StringWriter out = new StringWriter(); new FilterToSQL(out).encode(filter); out.getBuffer().toString();

        Returns:
        a string representing the filter encoded to SQL.
        Throws:
        FilterToSQLException
      • encode

        public void encode​(Expression expression)
                    throws FilterToSQLException
        Performs the encoding, sends the encoded sql to the writer passed in.
        Parameters:
        expression - the Expression to be encoded.
        Throws:
        FilterToSQLException - If filter type not supported, or if there were io problems.
      • encodeToString

        public String encodeToString​(Expression expression)
                              throws FilterToSQLException
        purely a convenience method.

        Equivalent to:

        StringWriter out = new StringWriter(); new FilterToSQL(out).encode(filter); out.getBuffer().toString();

        Returns:
        a string representing the filter encoded to SQL.
        Throws:
        FilterToSQLException
      • setFeatureType

        public void setFeatureType​(SimpleFeatureType featureType)
        Sets the featuretype the encoder is encoding sql for.

        This is used for context for attribute expressions when encoding to sql.

      • getFeatureType

        public SimpleFeatureType getFeatureType()
        Returns the feature type set in this encoder, if any
      • getPrimaryKey

        public PrimaryKey getPrimaryKey()
      • setPrimaryKey

        public void setPrimaryKey​(PrimaryKey primaryKey)
      • getDatabaseSchema

        public String getDatabaseSchema()
      • setDatabaseSchema

        public void setDatabaseSchema​(String databaseSchema)
      • createFilterCapabilities

        protected FilterCapabilities createFilterCapabilities()
        Sets the capabilities of this filter.
        Returns:
        FilterCapabilities for this Filter
      • getCapabilities

        public final FilterCapabilities getCapabilities()
        Describes the capabilities of this encoder.

        Performs lazy creation of capabilities. If you're subclassing this class, override createFilterCapabilities to declare which filtercapabilities you support. Don't use this method.

        Returns:
        The capabilities supported by this encoder.
      • setCapabilities

        public void setCapabilities​(FilterCapabilities capabilities)
        Sets the capabilities for the encoder.
      • visit

        public Object visit​(ExcludeFilter filter,
                            Object extraData)
        Description copied from interface: FilterVisitor
        Visit Filter.EXCLUDE (often used during data structure transformations).
        Specified by:
        visit in interface FilterVisitor
        Parameters:
        filter - the filter to be visited
        extraData - Value object provided to visitor
        Returns:
        subclass supplied
      • visit

        public Object visit​(IncludeFilter filter,
                            Object extraData)
        Description copied from interface: FilterVisitor
        Visit Filter.INCLUDE (often used during data structure transformations).
        Specified by:
        visit in interface FilterVisitor
        Parameters:
        filter - the filter to be visited
        extraData - Value object provided to visitor
        Returns:
        subclass supplied
      • visit

        public Object visit​(PropertyIsLike filter,
                            Object extraData)
        Writes the SQL for the Like Filter. Assumes the current java implemented wildcards for the Like Filter: . for multi and .? for single. And replaces them with the SQL % and _, respectively.
        Specified by:
        visit in interface FilterVisitor
        Parameters:
        filter - the Like Filter to be visited.
        TODO:
        REVISIT: Need to think through the escape char, so it works right when Java uses one, and escapes correctly with an '_'.
      • visit

        public Object visit​(And filter,
                            Object extraData)
        Write the SQL for an And filter
        Specified by:
        visit in interface FilterVisitor
        Parameters:
        filter - the filter to visit
        extraData - extra data (unused by this method)
      • visit

        public Object visit​(Not filter,
                            Object extraData)
        Write the SQL for a Not filter
        Specified by:
        visit in interface FilterVisitor
        Parameters:
        filter - the filter to visit
        extraData - extra data (unused by this method)
      • visit

        public Object visit​(Or filter,
                            Object extraData)
        Write the SQL for an Or filter
        Specified by:
        visit in interface FilterVisitor
        Parameters:
        filter - the filter to visit
        extraData - extra data (unused by this method)
      • visit

        protected Object visit​(BinaryLogicOperator filter,
                               Object extraData)
        Common implementation for BinaryLogicOperator filters. This way they're all handled centrally.
        Parameters:
        filter - the logic statement to be turned into SQL.
        extraData - extra filter data. Not modified directly by this method.
      • visit

        public Object visit​(PropertyIsEqualTo filter,
                            Object extraData)
        Write the SQL for this kind of filter
        Specified by:
        visit in interface FilterVisitor
        Parameters:
        filter - the filter to visit
        extraData - extra data (unused by this method)
      • visit

        public Object visit​(PropertyIsGreaterThan filter,
                            Object extraData)
        Write the SQL for this kind of filter
        Specified by:
        visit in interface FilterVisitor
        Parameters:
        filter - the filter to visit
        extraData - extra data (unused by this method)
      • visit

        public Object visit​(PropertyIsLessThan filter,
                            Object extraData)
        Write the SQL for this kind of filter
        Specified by:
        visit in interface FilterVisitor
        Parameters:
        filter - the filter to visit
        extraData - extra data (unused by this method)
      • visit

        public Object visit​(PropertyIsNotEqualTo filter,
                            Object extraData)
        Write the SQL for this kind of filter
        Specified by:
        visit in interface FilterVisitor
        Parameters:
        filter - the filter to visit
        extraData - extra data (unused by this method)
      • visitBinaryComparisonOperator

        protected void visitBinaryComparisonOperator​(BinaryComparisonOperator filter,
                                                     Object extraData)
                                              throws RuntimeException
        Common implementation for BinaryComparisonOperator filters. This way they're all handled centrally. DJB: note, postgis overwrites this implementation because of the way null is handled. This is for filters and filters are handled. They will come here with "property = null". NOTE: SELECT * FROM WHERE isnull; -- postgresql SELECT * FROM
        WHERE isnull(); -- oracle???
        Parameters:
        filter - the comparison to be turned into SQL.
        Throws:
        RuntimeException - for io exception with writer
        • encodeBinaryComparisonOperator

          protected void encodeBinaryComparisonOperator​(BinaryComparisonOperator filter,
                                                        Object extraData,
                                                        Expression left,
                                                        Expression right,
                                                        Class leftContext,
                                                        Class rightContext)
          Encode a BinaryComparisonOperator to SQL
          Parameters:
          filter - the comparison operator to be turned to SQL
          extraData - extraData
          left - left parameter of the binary operator
          right - right parameter of the binary operator
          leftContext - expression type of the right parameter used as context for the left parameter
          rightContext - expression type of the left parameter used as context for the right parameter
        • writeBinaryExpressionMember

          protected void writeBinaryExpressionMember​(Expression exp,
                                                     Class context)
                                              throws IOException
          Writes out an expression, wrapping it in parenthesis if it's a binary one
          Throws:
          IOException
        • getExpressionType

          public Class getExpressionType​(Expression expression)
          Returns the expression type, if can be found, or null otherwise. Based on feature type inspection for attribute references, and function return types otherwise. Cannot yet handle arithmetics or literals (the latter are actually not useful and should be ignored, expression in geotools are free to use a string where a number is needed due to the on the fly conversion, here we are concerned only with types that are a reliable reference).
          Returns:
          The expression return type, or null if cannot be computed
        • getFunctionReturnType

          protected Class getFunctionReturnType​(Function f)
        • isBinaryExpression

          protected boolean isBinaryExpression​(Expression e)
        • visitBinarySpatialOperator

          protected Object visitBinarySpatialOperator​(BinarySpatialOperator filter,
                                                      PropertyName property,
                                                      Literal geometry,
                                                      boolean swapped,
                                                      Object extraData)
          Handles the common case of a PropertyName,Literal geometry binary spatial operator.
        • visitBinarySpatialOperator

          protected Object visitBinarySpatialOperator​(BinarySpatialOperator filter,
                                                      Expression e1,
                                                      Expression e2,
                                                      Object extraData)
          Handles the more general case of two generic expressions.

          The most common case is two PropertyName expressions, which happens during a spatial join.

        • visitBinaryTemporalOperator

          protected Object visitBinaryTemporalOperator​(BinaryTemporalOperator filter,
                                                       PropertyName property,
                                                       Literal temporal,
                                                       boolean swapped,
                                                       Object 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.

        • visitBinaryTemporalOperator

          protected Object visitBinaryTemporalOperator​(BinaryTemporalOperator filter,
                                                       Expression e1,
                                                       Expression e2,
                                                       Object 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.

        • visitNullFilter

          public Object visitNullFilter​(Object extraData)
          Encodes a null filter value. The current implementation does exactly nothing.
          Specified by:
          visitNullFilter in interface FilterVisitor
          Parameters:
          extraData - extra data to be used to evaluate the filter
          Returns:
          the untouched extraData parameter
        • cast

          protected String cast​(String encodedProperty,
                                Class target)
                         throws IOException
          Gives the opportunity to subclasses to force the property to the desired type. By default it simply writes out the property as-is (the property must be already escaped).
          Throws:
          IOException
        • evaluateLiteral

          public Object evaluateLiteral​(Literal expression,
                                        Class<?> target)
        • writeLiteral

          protected void writeLiteral​(Object literal)
                               throws IOException
          Writes out a non null, non geometry literal. The base class properly handles null, numeric and booleans (true|false), and turns everything else into a string. Subclasses are expected to override this shall they need a different treatment (e.g. for dates)
          Throws:
          IOException
        • escapeLiteral

          public String escapeLiteral​(String literal)
          Escapes the string literal.
        • visitLiteralGeometry

          protected void visitLiteralGeometry​(Literal expression)
                                       throws IOException
          Subclasses must implement this method in order to encode geometry filters according to the specific database implementation
          Throws:
          IOException
        • visitLiteralTimePeriod

          protected void visitLiteralTimePeriod​(Period expression)
        • visit

          public Object visit​(Function function,
                              Object extraData)
                       throws RuntimeException
          Writes sql for a function expression. By default it will write the call by using the same arguments provided to the GeoTools function, subclasses should override on a case by case basis if this behavior is not the desired one.
          Specified by:
          visit in interface ExpressionVisitor
          Parameters:
          function - a function expression
          Throws:
          RuntimeException - If an IO error occurs.
          See Also:
          getFunctionName(Function)
        • getParameter

          protected Expression getParameter​(Function function,
                                            int idx,
                                            boolean mandatory)
          Returns the n-th parameter of a function, throwing an exception if the parameter is not there and has been marked as mandatory
        • getFunctionName

          protected String getFunctionName​(Function function)
          Maps the function to the native database function name
        • visit

          public Object visit​(NilExpression expression,
                              Object extraData)
          Description copied from interface: ExpressionVisitor
          Used to visit a Expression.NIL, also called for null where an expression is expected.

          This is particularly useful when doing data transformations, as an example when using a StyleSymbolizer Expression.NIL can be used to represent the default stroke color.

          Specified by:
          visit in interface ExpressionVisitor
          Returns:
          implementation specific
        • setSqlNameEscape

          public void setSqlNameEscape​(String escape)
          Sets the SQL name escape string.

          The value of this string is prefixed and appended to table schema names, table names and column names in an SQL statement to support mixed-case and non-English names. Without this, the DBMS may assume a mixed-case name in the query should be treated as upper-case and an SQLCODE of -204 or 206 may result if the name is not found.

          Typically this is the double-quote character, ", but may not be for all databases.

          If a name contains the escape string itself, the escape string is duplicated.

          For example, consider the following query:

          SELECT Geom FROM Spear.ArchSites May be interpreted by the database as: SELECT GEOM FROM SPEAR.ARCHSITES If the column and table names were actually created using mixed-case, the query needs to be specified as: SELECT "Geom" from "Spear"."ArchSites"

          Parameters:
          escape - the character to be used to escape database names
        • getSqlNameEscape

          public String getSqlNameEscape()
          Returns:
          the sqlNameEscape
        • escapeName

          public String escapeName​(String name)
          Surrounds a name with the SQL escape string.

          If the name contains the SQL escape string, the SQL escape string is duplicated.

        • setFieldEncoder

          public void setFieldEncoder​(FilterToSQL.FieldEncoder fieldEncoder)
          Set custom field encoder
          Parameters:
          fieldEncoder - the field encoder
        • getDistanceInNativeUnits

          protected double getDistanceInNativeUnits​(DistanceBufferOperator operator)
          Rough evaluation of distance in the units of the current SRID, assuming that the SRID maps to a known EPSG code. Will use a rather imprecise transformation for distances over degrees, but better than nothing.