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

    
23
public class CalculateEnvelopeOfColumnOperation extends AbstractConnectionOperation {
24

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

    
32
    public CalculateEnvelopeOfColumnOperation(
33
            JDBCHelper helper,
34
            FeatureType featureType,
35
            TableReference table,
36
            String columnName,
37
            String baseFilter,
38
            Envelope limit,
39
            IProjection crs
40
    ) {
41
        super(helper);
42
        this.featureType = featureType;
43
        this.table = table;
44
        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
        Envelope env = calculateEnvelopeOfColumn(conn);
53
        return env;
54
    }
55

    
56
    public String getSQL() {
57
        //
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
        JDBCSQLBuilderBase sqlbuilder = this.createSQLBuilder();
66
        GeometryExpressionBuilder expbuilder = sqlbuilder.expression();
67
        
68
        sqlbuilder.select().column().value(
69
//            expbuilder.ifnull(
70
//                expbuilder.column(columnName), 
71
//                expbuilder.constant(null), 
72
                expbuilder.as_geometry(
73
                    expbuilder.ST_ExtentAggregate(
74
                            expbuilder.column(columnName)
75
                    )
76
                )
77
//            )
78
        );
79
//        sqlbuilder.select().group_by(expbuilder.column(columnName));
80
        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

    
86
        if (StringUtils.isEmpty(baseFilter)) {
87
            if (limit != null) {
88
                sqlbuilder.select().where().set(
89
                        expbuilder.ST_Intersects(
90
                                expbuilder.ST_Envelope(
91
                                        expbuilder.column(columnName)
92
                                ),
93
                                expbuilder.ST_Envelope(
94
                                        expbuilder.geometry(limit.getGeometry(), crs)
95
                                )
96
                        )
97
                );
98
            }
99
        } else {
100
            sqlbuilder.select().where().set( expbuilder.custom(baseFilter) );
101
            if (limit != null) {
102
                sqlbuilder.select().where().and(
103
                        expbuilder.ST_Intersects(
104
                            expbuilder.ST_Envelope(
105
                                    expbuilder.column(columnName)
106
                            ),
107
                            expbuilder.ST_Envelope(
108
                                    expbuilder.geometry(limit.getGeometry(), crs)
109
                            )
110
                        )
111
                );
112
            }
113
        }
114
        sqlbuilder.select().where().and(        
115
            expbuilder.not_is_null(expbuilder.column(columnName))
116
        );
117
        this.helper.processSpecialFunctions(sqlbuilder, featureType, null);
118
        sqlbuilder.setProperties(
119
                Variable.class, 
120
                PROP_TABLE, table
121
        );
122
        String sql = sqlbuilder.select().toString();
123
        return sql;
124
    }
125
    
126
    public Envelope calculateEnvelopeOfColumn(Connection conn) throws DataException {
127
        String sql = this.getSQL();
128
        
129
        Statement st = null;
130
        ResultSet rs = null;
131
        try {
132
            st = conn.createStatement();
133
            try {
134
                LOGGER.debug("execute query SQL:"+sql);
135
                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
            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
}