Package org.geotools.data.teradata

Source Code of org.geotools.data.teradata.TeradataFilterToSQL

/*
*    GeoTools - The Open Source Java GIS Toolkit
*    http://geotools.org
*
*    (C) 2002-2009, 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.teradata;

import java.io.IOException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.geotools.feature.type.BasicFeatureTypes;
import org.geotools.filter.FilterCapabilities;
import org.geotools.jdbc.PreparedFilterToSQL;
import org.geotools.jdbc.PrimaryKeyColumn;
import org.geotools.jdbc.SQLDialect;
import org.geotools.util.logging.Logging;
import org.opengis.filter.expression.Literal;
import org.opengis.filter.expression.PropertyName;
import org.opengis.filter.spatial.BBOX;
import org.opengis.filter.spatial.Beyond;
import org.opengis.filter.spatial.BinarySpatialOperator;
import org.opengis.filter.spatial.Contains;
import org.opengis.filter.spatial.Crosses;
import org.opengis.filter.spatial.DWithin;
import org.opengis.filter.spatial.Disjoint;
import org.opengis.filter.spatial.DistanceBufferOperator;
import org.opengis.filter.spatial.Equals;
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 com.vividsolutions.jts.geom.Envelope;
import com.vividsolutions.jts.geom.Geometry;

/**
*
*
* @source $URL$
*/
public class TeradataFilterToSQL extends PreparedFilterToSQL {

    static final Logger LOGGER = Logging.getLogger(TeradataFilterToSQL.class);
   
    boolean looseBBOX;

    public TeradataFilterToSQL(TeradataDialect dialect) {
        super(dialect);
        looseBBOX = dialect.isLooseBBOXEnabled();
    }

    @Override
    protected FilterCapabilities createFilterCapabilities() {
        FilterCapabilities caps = new FilterCapabilities();
        caps.addAll(SQLDialect.BASE_DBMS_CAPABILITIES);

        // adding the spatial filters support
        caps.addType(BBOX.class);
        caps.addType(Contains.class);
        caps.addType(Crosses.class);
        caps.addType(Disjoint.class);
        caps.addType(Equals.class);
        caps.addType(Intersects.class);
        caps.addType(Overlaps.class);
        caps.addType(Touches.class);
        caps.addType(Within.class);
        caps.addType(DWithin.class);
        caps.addType(Beyond.class);

        return caps;
    }

//    protected void visitLiteralGeometry(Literal expression) throws IOException {
//        // evaluate the literal and store it for later
//        Geometry geom = (Geometry) evaluateLiteral(expression, Geometry.class);
//
//        if (geom instanceof LinearRing) {
//            // teradata does not handle linear rings, convert to just a line
//            // string
//            geom = geom.getFactory().createLineString(((LinearRing) geom).getCoordinateSequence());
//        }
//
//        out.write("'");
//        out.write(geom.toText());
//        out.write("'");
//    }

   

    protected Object visitBinarySpatialOperator(BinarySpatialOperator filter,
            PropertyName property, Literal geometry, boolean swapped, Object extraData) {
        try {
            if (filter instanceof DistanceBufferOperator) {
                visitDistanceSpatialOperator((DistanceBufferOperator) filter, property, geometry,
                        swapped, extraData);
            } else {
                visitComparisonSpatialOperator(filter, property, geometry, swapped, 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 {

        if ((filter instanceof DWithin && !swapped) || (filter instanceof Beyond && swapped)) {
            encodeIndexPredicate(property, geometry);

            property.accept(this, extraData);
            out.write(".ST_DWithin(new ST_Geometry(");
            geometry.accept(this, extraData);
            out.write("),");
            out.write(Double.toString(filter.getDistance()));
            out.write(")");
        }
        if ((filter instanceof DWithin && swapped) || (filter instanceof Beyond && !swapped)) {
            encodeIndexPredicate(property, geometry);

            property.accept(this, extraData);
            out.write(".ST_Distance(SYSSPATIAL.ST_Geometry(");
            geometry.accept(this, extraData);
            out.write(")) > ");
            out.write(Double.toString(filter.getDistance()));
        }
    }

    void visitComparisonSpatialOperator(BinarySpatialOperator filter, PropertyName property,
            Literal geometry, boolean swapped, Object extraData) throws IOException {

        if (!(filter instanceof Disjoint)) {
            if (encodeIndexPredicate(property, geometry)) {
                out.write( " AND ");
            }
        }

        property.accept(this, extraData);
        out.write(".");

        if (filter instanceof Equals) {
            out.write("ST_Equals");
        } else if (filter instanceof Disjoint) {
            out.write("ST_Disjoint ");
        } else if (filter instanceof Intersects || filter instanceof BBOX) {
            out.write("ST_Intersects");
        } else if (filter instanceof Crosses) {
            out.write("ST_Crosses");
        } else if (filter instanceof Within) {
            if (swapped)
                out.write("ST_Contains");
            else
                out.write("ST_Within");
        } else if (filter instanceof Contains) {
            if (swapped)
                out.write("ST_Within");
            else
                out.write("ST_Contains");
        } else if (filter instanceof Overlaps) {
            out.write("ST_Overlaps");
        } else if (filter instanceof Touches) {
            out.write("ST_Touches");
        } else {
            throw new RuntimeException("Unsupported filter type " + filter.getClass());
        }

        int tdVersion = ((TeradataDialect)dialect).getTdVersion();
        if (tdVersion > 12) {
            out.write("(new ST_Geometry(");
            geometry.accept(this, extraData);
            out.write(")) = 1");
        }
        else {
            out.write("(CAST (");
            geometry.accept(this, extraData);
            out.write(" AS ST_Geometry)) = 1");
        }
    }

    boolean encodeIndexPredicate(PropertyName property, Literal geometry) throws IOException {
       
        TessellationInfo tinfo =
            (TessellationInfo) currentGeometry.getUserData().get(TessellationInfo.KEY);
        if (tinfo == null) {
            LOGGER.info("Tessellation info not available for " + currentGeometry.getLocalName() +
                ", unable to perform spatially indexed query");
            return false;
        }
       
        if (tinfo.getIndexTableName() == null) {
            LOGGER.info("Tessellation info available for " + currentGeometry.getLocalName() +
                ", but index table does not exist, unable to perform spatially index query.");
            return false;
        }
       
        if (primaryKey == null || primaryKey.getColumns().isEmpty()) {
            LOGGER.info("No primary key for " + featureType.getTypeName() +
                ", unable to perform spatially indexed query");
            return false;
        }

        Geometry g = (Geometry) geometry.getValue();
       
        //check the geomtry envelope vs the world envelope, if it falls outside of the world bounds
        // we can't use the index
        Envelope oenv = g.getEnvelopeInternal();
        Envelope uenv = tinfo.getUBounds();
       
        if (!uenv.contains(oenv)) {
            if (LOGGER.isLoggable(Level.FINE)) {
                LOGGER.fine("Bounds:" + oenv + " falls outside of univerise bounds: " + uenv +
                    ". Unable to perform index query.");
            }
            return false;
        }
       
        //check coverage... if the geometry bounds covers most of the the index universe don't use
        // the index since the join query is expensive... it will be more efficient to just do the
        // direct intersection
        //TODO: make this threshhold configurable
        double coverage = uenv.intersection(oenv).getArea() / uenv.getArea();
        if (coverage > 0.5) {
            if (LOGGER.isLoggable(Level.FINE)) {
                LOGGER.fine("Bounds:" + oenv + " covers " + (coverage * 100) + " of universe bounds: "
                  + uenv + ". Forgoing index query.");
            }
            return false;
        }
       
        out.write('(');
        for (Iterator<PrimaryKeyColumn> it = primaryKey.getColumns().iterator(); it.hasNext();) {
            out.write(it.next().getName());
            if (it.hasNext()) {
                out.write(", ");
            }
        }
        out.write(')');

        out.write(" IN (SELECT DISTINCT ");
        for (Iterator<PrimaryKeyColumn> it = primaryKey.getColumns().iterator(); it.hasNext();) {
            out.write("t." + it.next().getName());
            if (it.hasNext()) {
                out.write(", ");
            }
        }
       
        out.write(" FROM ");
        if (tinfo.getSchemaName() != null) {
            out.write(escapeName(tinfo.getSchemaName()));
            out.write(".");
        }
        out.write(escapeName(tinfo.getIndexTableName()));
        out.write( " t, TABLE (SYSSPATIAL.tessellate_search(1,");
       
        out.write(String.format("%f, %f, %f, %f, %f, %f, %f, %f, %d, %d, %d, %f, %d)) AS i ",
            oenv.getMinX(), oenv.getMinY(), oenv.getMaxX(), oenv.getMaxY(), uenv.getMinX(),
            uenv.getMinY(), uenv.getMaxX(), uenv.getMaxY(), tinfo.getNx(), tinfo.getNy(),
            tinfo.getLevels(), tinfo.getScale(), tinfo.getShift()));
       
        out.write(" WHERE t.cellid = i.cellid)");
        return true;
    }
}
TOP

Related Classes of org.geotools.data.teradata.TeradataFilterToSQL

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.