Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.dal / org.gvsig.fmap.dal.db / org.gvsig.fmap.dal.db.jdbc / src / main / java / org / gvsig / fmap / dal / store / jdbc2 / spi / operations / CalculateEnvelopeOfColumnOperation.java @ 44748

History | View | Annotate | Download (6.29 KB)

1 43020 jjdelcerro
package org.gvsig.fmap.dal.store.jdbc2.spi.operations;
2
3
import java.sql.Connection;
4
import java.sql.ResultSet;
5
import java.sql.SQLException;
6
import java.sql.Statement;
7 44678 jjdelcerro
import java.util.List;
8 43020 jjdelcerro
import org.apache.commons.lang3.StringUtils;
9
import org.cresques.cts.IProjection;
10 44198 jjdelcerro
import org.gvsig.expressionevaluator.ExpressionBuilder.Variable;
11 44644 jjdelcerro
import org.gvsig.expressionevaluator.GeometryExpressionBuilder;
12 43020 jjdelcerro
import org.gvsig.fmap.dal.exception.DataException;
13 44376 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureType;
14 43020 jjdelcerro
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCSQLException;
15
import org.gvsig.fmap.dal.store.jdbc2.JDBCHelper;
16
import org.gvsig.fmap.dal.store.jdbc2.JDBCUtils;
17 44058 jjdelcerro
import org.gvsig.fmap.dal.store.jdbc2.OperationsFactory.TableReference;
18 43020 jjdelcerro
import org.gvsig.fmap.dal.store.jdbc2.spi.JDBCSQLBuilderBase;
19 44198 jjdelcerro
import static org.gvsig.fmap.dal.store.jdbc2.spi.JDBCSQLBuilderBase.PROP_TABLE;
20 43020 jjdelcerro
import org.gvsig.fmap.geom.Geometry;
21
import org.gvsig.fmap.geom.primitive.Envelope;
22
23
public class CalculateEnvelopeOfColumnOperation extends AbstractConnectionOperation {
24
25 44058 jjdelcerro
    private final TableReference table;
26 43020 jjdelcerro
    private final String columnName;
27
    private final String baseFilter;
28
    private final Envelope limit;
29
    private final IProjection crs;
30 44376 jjdelcerro
    private final FeatureType featureType;
31 43020 jjdelcerro
32
    public CalculateEnvelopeOfColumnOperation(
33
            JDBCHelper helper,
34 44376 jjdelcerro
            FeatureType featureType,
35 44058 jjdelcerro
            TableReference table,
36 43020 jjdelcerro
            String columnName,
37
            String baseFilter,
38
            Envelope limit,
39
            IProjection crs
40
    ) {
41
        super(helper);
42 44376 jjdelcerro
        this.featureType = featureType;
43 44058 jjdelcerro
        this.table = table;
44 43020 jjdelcerro
        this.columnName = columnName;
45
        this.baseFilter = baseFilter;
46
        this.limit = limit;
47
        this.crs = crs;
48
    }
49
50
    @Override
51
    public final Object perform(Connection conn) throws DataException {
52 44678 jjdelcerro
        Envelope env = calculateEnvelopeOfColumn(conn);
53 43020 jjdelcerro
        return env;
54
    }
55
56 44678 jjdelcerro
    public String getSQL() {
57 43088 jjdelcerro
        //
58
        // Parece ser que en versiones anteriores a SQL Server 2012 no esta
59
        // disponible la funcion ST_ExtentAggregate.
60
        // Habria que determinar si es necesario implementar una alternativa
61
        // para estos casos.
62
        //
63
        // https://alastaira.wordpress.com/2011/07/26/determining-the-geographic-extent-of-spatial-features-in-a-sql-server-table/
64
        //
65 43020 jjdelcerro
        JDBCSQLBuilderBase sqlbuilder = this.createSQLBuilder();
66 44644 jjdelcerro
        GeometryExpressionBuilder expbuilder = sqlbuilder.expression();
67 44198 jjdelcerro
68 43020 jjdelcerro
        sqlbuilder.select().column().value(
69 44361 jjdelcerro
//            expbuilder.ifnull(
70
//                expbuilder.column(columnName),
71
//                expbuilder.constant(null),
72 44345 jjdelcerro
                expbuilder.as_geometry(
73
                    expbuilder.ST_ExtentAggregate(
74
                            expbuilder.column(columnName)
75
                    )
76 43020 jjdelcerro
                )
77 44361 jjdelcerro
//            )
78 43020 jjdelcerro
        );
79 44361 jjdelcerro
//        sqlbuilder.select().group_by(expbuilder.column(columnName));
80 44058 jjdelcerro
        sqlbuilder.select().from().table()
81
                .database(this.table.getDatabase())
82
                .schema(this.table.getSchema())
83
                .name(this.table.getTable());
84
        sqlbuilder.select().from().subquery(this.table.getSubquery());
85 43020 jjdelcerro
86
        if (StringUtils.isEmpty(baseFilter)) {
87
            if (limit != null) {
88
                sqlbuilder.select().where().set(
89 44198 jjdelcerro
                        expbuilder.ST_Intersects(
90
                                expbuilder.ST_Envelope(
91
                                        expbuilder.column(columnName)
92 43020 jjdelcerro
                                ),
93 44198 jjdelcerro
                                expbuilder.ST_Envelope(
94
                                        expbuilder.geometry(limit.getGeometry(), crs)
95 43020 jjdelcerro
                                )
96
                        )
97
                );
98
            }
99
        } else {
100 44198 jjdelcerro
            sqlbuilder.select().where().set( expbuilder.custom(baseFilter) );
101 43020 jjdelcerro
            if (limit != null) {
102
                sqlbuilder.select().where().and(
103 44198 jjdelcerro
                        expbuilder.ST_Intersects(
104
                            expbuilder.ST_Envelope(
105
                                    expbuilder.column(columnName)
106 43020 jjdelcerro
                            ),
107 44198 jjdelcerro
                            expbuilder.ST_Envelope(
108
                                    expbuilder.geometry(limit.getGeometry(), crs)
109 43020 jjdelcerro
                            )
110
                        )
111
                );
112
            }
113
        }
114 44361 jjdelcerro
        sqlbuilder.select().where().and(
115
            expbuilder.not_is_null(expbuilder.column(columnName))
116
        );
117 44748 jjdelcerro
        this.helper.processSpecialFunctions(sqlbuilder, featureType, null);
118 44198 jjdelcerro
        sqlbuilder.setProperties(
119
                Variable.class,
120
                PROP_TABLE, table
121
        );
122 43020 jjdelcerro
        String sql = sqlbuilder.select().toString();
123 44678 jjdelcerro
        return sql;
124
    }
125
126
    public Envelope calculateEnvelopeOfColumn(Connection conn) throws DataException {
127
        String sql = this.getSQL();
128
129 43020 jjdelcerro
        Statement st = null;
130
        ResultSet rs = null;
131
        try {
132
            st = conn.createStatement();
133 44533 jjdelcerro
            try {
134 44608 jjdelcerro
                LOGGER.debug("execute query SQL:"+sql);
135 44533 jjdelcerro
                rs = st.executeQuery(sql);
136
                // No llamo al de JDBC utils para que no meta el error
137
                // en el log.
138
                // rs = JDBCUtils.executeQuery(st, sql);
139
            } catch(SQLException ex) {
140
//                Para calcular el envelope se esta lanzando una colsulta como:
141
//                   SELECT ST_AsBinary(ST_Extent("geometry"))
142
//                   FROM "gis_osm_roads_free_1"
143
//                   WHERE ( ("geometry") IS NOT NULL )
144
//                Que falla cuando no hay registros al recibir un NULL en el
145
//                ST_AsBinary.
146
//                A falta de una forma mejor de detectar eso, si peta en este
147
//                punto asumiremos que no hay registros en la consulta y devolveremos
148
//                null como envelope.
149
                return null;
150
            }
151 43020 jjdelcerro
            if (!rs.next()) {
152
                return null;
153
            }
154
            Geometry geom = this.helper.getGeometryFromColumn(rs, 1);
155
            if (geom == null) {
156
                return null;
157
            }
158
            return geom.getEnvelope();
159
160
        } catch (SQLException ex) {
161
            throw new JDBCSQLException(ex);
162
        } finally {
163
            JDBCUtils.closeQuietly(st);
164
            JDBCUtils.closeQuietly(rs);
165
        }
166
    }
167
168
}