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 @ 44533

History | View | Annotate | Download (6.45 KB)

1
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
import org.apache.commons.lang3.StringUtils;
8
import org.cresques.cts.IProjection;
9
import org.gvsig.expressionevaluator.ExpressionBuilder;
10
import org.gvsig.expressionevaluator.ExpressionBuilder.Variable;
11
import org.gvsig.fmap.dal.exception.DataException;
12
import org.gvsig.fmap.dal.feature.FeatureType;
13
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCSQLException;
14
import org.gvsig.fmap.dal.store.jdbc2.JDBCHelper;
15
import org.gvsig.fmap.dal.store.jdbc2.JDBCUtils;
16
import org.gvsig.fmap.dal.store.jdbc2.OperationsFactory.TableReference;
17
import org.gvsig.fmap.dal.store.jdbc2.spi.JDBCSQLBuilderBase;
18
import static org.gvsig.fmap.dal.store.jdbc2.spi.JDBCSQLBuilderBase.PROP_TABLE;
19
import org.gvsig.fmap.geom.Geometry;
20
import org.gvsig.fmap.geom.primitive.Envelope;
21

    
22
public class CalculateEnvelopeOfColumnOperation extends AbstractConnectionOperation {
23

    
24
    private final TableReference table;
25
    private final String columnName;
26
    private final String baseFilter;
27
    private final Envelope limit;
28
    private final IProjection crs;
29
    private final FeatureType featureType;
30

    
31
    public CalculateEnvelopeOfColumnOperation(
32
            JDBCHelper helper,
33
            FeatureType featureType,
34
            TableReference table,
35
            String columnName,
36
            String baseFilter,
37
            Envelope limit,
38
            IProjection crs
39
    ) {
40
        super(helper);
41
        this.featureType = featureType;
42
        this.table = table;
43
        this.columnName = columnName;
44
        this.baseFilter = baseFilter;
45
        this.limit = limit;
46
        this.crs = crs;
47
    }
48

    
49
    @Override
50
    public final Object perform(Connection conn) throws DataException {
51
        Envelope env = calculateEnvelopeOfColumn(
52
            conn,
53
            featureType,
54
            table,
55
            columnName,
56
            baseFilter,
57
            limit,
58
            crs
59
        );
60
        return env;
61
    }
62

    
63
    public Envelope calculateEnvelopeOfColumn(
64
            Connection conn,
65
            FeatureType featureType,
66
            TableReference table,
67
            String columnName,
68
            String baseFilter,
69
            Envelope limit,
70
            IProjection crs
71
    ) throws DataException {
72

    
73
        //
74
        // Parece ser que en versiones anteriores a SQL Server 2012 no esta
75
        // disponible la funcion ST_ExtentAggregate.
76
        // Habria que determinar si es necesario implementar una alternativa
77
        // para estos casos.
78
        //
79
        // https://alastaira.wordpress.com/2011/07/26/determining-the-geographic-extent-of-spatial-features-in-a-sql-server-table/
80
        //
81
        JDBCSQLBuilderBase sqlbuilder = this.createSQLBuilder();
82
        ExpressionBuilder expbuilder = sqlbuilder.expression();
83
        
84
        sqlbuilder.select().column().value(
85
//            expbuilder.ifnull(
86
//                expbuilder.column(columnName), 
87
//                expbuilder.constant(null), 
88
                expbuilder.as_geometry(
89
                    expbuilder.ST_ExtentAggregate(
90
                            expbuilder.column(columnName)
91
                    )
92
                )
93
//            )
94
        );
95
//        sqlbuilder.select().group_by(expbuilder.column(columnName));
96
        sqlbuilder.select().from().table()
97
                .database(this.table.getDatabase())
98
                .schema(this.table.getSchema())
99
                .name(this.table.getTable());
100
        sqlbuilder.select().from().subquery(this.table.getSubquery());
101

    
102
        if (StringUtils.isEmpty(baseFilter)) {
103
            if (limit != null) {
104
                sqlbuilder.select().where().set(
105
                        expbuilder.ST_Intersects(
106
                                expbuilder.ST_Envelope(
107
                                        expbuilder.column(columnName)
108
                                ),
109
                                expbuilder.ST_Envelope(
110
                                        expbuilder.geometry(limit.getGeometry(), crs)
111
                                )
112
                        )
113
                );
114
            }
115
        } else {
116
            sqlbuilder.select().where().set( expbuilder.custom(baseFilter) );
117
            if (limit != null) {
118
                sqlbuilder.select().where().and(
119
                        expbuilder.ST_Intersects(
120
                            expbuilder.ST_Envelope(
121
                                    expbuilder.column(columnName)
122
                            ),
123
                            expbuilder.ST_Envelope(
124
                                    expbuilder.geometry(limit.getGeometry(), crs)
125
                            )
126
                        )
127
                );
128
            }
129
        }
130
        sqlbuilder.select().where().and(        
131
            expbuilder.not_is_null(expbuilder.column(columnName))
132
        );
133
        this.helper.replaceForeingValueFunction(sqlbuilder, featureType);
134
        sqlbuilder.setProperties(
135
                Variable.class, 
136
                PROP_TABLE, table
137
        );
138
        String sql = sqlbuilder.select().toString();
139

    
140
        Statement st = null;
141
        ResultSet rs = null;
142
        try {
143
            st = conn.createStatement();
144
            try {
145
                rs = st.executeQuery(sql);
146
                // No llamo al de JDBC utils para que no meta el error
147
                // en el log.
148
                // rs = JDBCUtils.executeQuery(st, sql);
149
            } catch(SQLException ex) {
150
//                Para calcular el envelope se esta lanzando una colsulta como:
151
//                   SELECT ST_AsBinary(ST_Extent("geometry")) 
152
//                   FROM "gis_osm_roads_free_1" 
153
//                   WHERE ( ("geometry") IS NOT NULL )
154
//                Que falla cuando no hay registros al recibir un NULL en el 
155
//                ST_AsBinary. 
156
//                A falta de una forma mejor de detectar eso, si peta en este
157
//                punto asumiremos que no hay registros en la consulta y devolveremos
158
//                null como envelope.
159
                return null;
160
            }
161
            if (!rs.next()) {
162
                return null;
163
            }
164
            Geometry geom = this.helper.getGeometryFromColumn(rs, 1);
165
            if (geom == null) {
166
                return null;
167
            }
168
            return geom.getEnvelope();
169

    
170
        } catch (SQLException ex) {
171
            throw new JDBCSQLException(ex);
172
        } finally {
173
            JDBCUtils.closeQuietly(st);
174
            JDBCUtils.closeQuietly(rs);
175
        }
176
    }
177

    
178
}