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 / CountOperation.java @ 46050

History | View | Annotate | Download (14 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2020 gvSIG Association.
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 3
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24
package org.gvsig.fmap.dal.store.jdbc2.spi.operations;
25

    
26
import java.sql.Connection;
27
import java.sql.ResultSet;
28
import java.sql.SQLException;
29
import java.sql.Statement;
30
import java.util.ArrayList;
31
import java.util.List;
32
import org.apache.commons.lang3.StringUtils;
33
import org.gvsig.expressionevaluator.Code;
34
import org.gvsig.expressionevaluator.Expression;
35
import org.gvsig.expressionevaluator.ExpressionBuilder;
36
import org.gvsig.expressionevaluator.ExpressionUtils;
37
import org.gvsig.expressionevaluator.SymbolTable;
38
import org.gvsig.fmap.dal.SQLBuilder.SelectBuilder;
39
import org.gvsig.fmap.dal.exception.DataException;
40
import org.gvsig.fmap.dal.expressionevaluator.FeatureAttributeEmulatorExpression;
41
import org.gvsig.fmap.dal.feature.EditableFeatureAttributeDescriptor;
42
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
43
import org.gvsig.fmap.dal.feature.FeatureAttributeEmulator;
44
import org.gvsig.fmap.dal.feature.FeatureQuery;
45
import org.gvsig.fmap.dal.feature.FeatureQueryOrder;
46
import org.gvsig.fmap.dal.feature.FeatureType;
47
import org.gvsig.fmap.dal.store.jdbc2.JDBCHelper;
48
import org.gvsig.fmap.dal.store.jdbc2.spi.JDBCSQLBuilderBase;
49
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCSQLException;
50
import org.gvsig.fmap.dal.store.jdbc2.JDBCUtils;
51
import org.gvsig.fmap.dal.store.jdbc2.OperationsFactory.TableReference;
52
import static org.gvsig.fmap.dal.store.jdbc2.spi.JDBCSQLBuilderBase.PROP_FEATURE_TYPE;
53
import static org.gvsig.fmap.dal.store.jdbc2.spi.JDBCSQLBuilderBase.PROP_JDBCHELPER;
54
import static org.gvsig.fmap.dal.store.jdbc2.spi.JDBCSQLBuilderBase.PROP_QUERY;
55
import static org.gvsig.fmap.dal.store.jdbc2.spi.JDBCSQLBuilderBase.PROP_SYMBOLTABLE;
56
import static org.gvsig.fmap.dal.store.jdbc2.spi.JDBCSQLBuilderBase.PROP_TABLE;
57
import org.gvsig.tools.dynobject.DynField;
58
import org.gvsig.tools.evaluator.Evaluator;
59

    
60
public class CountOperation extends AbstractConnectionOperation {
61

    
62
    private final TableReference table;
63
    private final String baseFilter;
64
    private final FeatureQuery query;
65
    private final FeatureType featureType;
66

    
67
    public CountOperation(
68
            JDBCHelper helper
69
        ) {
70
        this(helper, null, null, null, null);
71
    }
72

    
73
    public CountOperation(
74
            JDBCHelper helper,
75
            FeatureType featureType,
76
            TableReference table,
77
            String baseFilter,
78
            FeatureQuery query
79
        ) {
80
        super(helper);
81
        this.featureType = featureType;
82
        this.table = table;
83
        this.baseFilter = baseFilter;
84
        this.query = query;
85
    }
86

    
87
    @Override
88
    public final Object perform(Connection conn) throws DataException {
89
        return this.count(conn);
90
    }
91

    
92
    public String getSQL() {
93
        JDBCSQLBuilderBase sqlbuilder = this.createSQLBuilder();
94
        ExpressionBuilder expbuilder = sqlbuilder.expression();
95

    
96
        SelectBuilder select = sqlbuilder.select();
97
        ArrayList<ExpressionBuilder.Value> valuesToRemoveFeatureType = new ArrayList<>();
98

    
99
        if (this.query != null && this.query.hasGroupByColumns()) {
100
            JDBCSQLBuilderBase subsqlbuilder = this.createSQLBuilder();
101
            SelectBuilder subselect = subsqlbuilder.select();
102
            
103
            subselect.column().value(subsqlbuilder.count().all());
104
            for (FeatureAttributeDescriptor attr : this.featureType) {
105
                if (attr.isComputed()) {
106
                    if (attr.getRelationType() == DynField.RELATION_TYPE_NONE) {
107
                        FeatureAttributeEmulator attrEmulator = attr.getFeatureAttributeEmulator();
108
                        if (attrEmulator instanceof FeatureAttributeEmulatorExpression) {
109
                            FeatureAttributeEmulatorExpression x = (FeatureAttributeEmulatorExpression) attrEmulator;
110
                            Expression exp = x.getExpression();
111

    
112
                            if (query != null && query.hasGroupByColumns()) {
113
                                String aggregate = query.getAggregate(this.table.getTable(), attr.getName());
114
                                if (this.query.isAGroupByColumn(attr.getName())) {
115
                                    if (!subselect.has_column(attr.getName())) {
116
                                        subselect.column().value(exp.getCode().toValue()).as(attr.getName());
117
                                    }
118
                             
119
                                } else if (aggregate == null) {
120
                                    subselect.column().value(expbuilder.constant(null)).as(attr.getName());
121
                                } else {
122
                                    String fn = this.query.getAggregateFunctions().get(attr.getName());
123
                                    ExpressionBuilder.Function aggregateExp = expbuilder.function(fn, exp.getCode().toValue());
124
                                    if (!subselect.has_column(attr.getName())) {
125
                                        subselect.column().value(aggregateExp).as(attr.getName());
126
                                    }
127
                                
128
                                }
129
                            } else {
130
                                if (exp != null && !exp.isEmpty() && this.helper.supportExpression(this.featureType, exp.getPhrase())) {
131
                                    Code code = exp.getCode();
132
                                    subselect.column()
133
                                            .value(code.toValue(expbuilder))
134
                                            .as(attr.getName());
135
                                
136
                                }
137

    
138
                            }
139
                        }
140
                    }
141
                }
142
            }
143
            
144
            
145
            
146
            
147
            
148
            if (this.query.hasGroupByColumns()) {
149
                if (this.query.hasOrder()) {
150
                    FeatureQueryOrder order = query.getOrder();
151
                    if (order != null) {
152
                        for (FeatureQueryOrder.FeatureQueryOrderMember member : order.members()) {
153
                            if (member.hasEvaluator()) {
154
                                String sqlorder = member.getEvaluator().getSQL();
155
                                if (!StringUtils.isEmpty(sqlorder)) {
156
                                    subselect.order_by()
157
                                            .value(expbuilder.toValue(sqlorder))
158
                                            .ascending(member.getAscending());
159
                                }
160
                            } else {
161
                                subselect.order_by()
162
                                        .column(member.getAttributeName())
163
                                        .ascending(member.getAscending());
164
                            }
165
                        }
166
                    }
167
                }
168
                subselect.from().table()
169
                        .database(this.table.getDatabase())
170
                        .schema(this.table.getSchema())
171
                        .name(this.table.getTable());
172
                subselect.from().subquery(this.table.getSubquery());
173
                Evaluator filter = query == null ? null : query.getFilter();
174
                if (filter != null) {
175
                    String sqlfilter = filter.getSQL();
176
                    if (!StringUtils.isEmpty(sqlfilter)) {
177
                        if (this.helper.supportFilter(this.featureType, filter)) {
178
                            subselect.where().set(expbuilder.toValue(sqlfilter));
179
                        }
180
                    }
181
                }
182
                if (!StringUtils.isEmpty(baseFilter)) {
183
                    subselect.where().and(expbuilder.toValue(baseFilter));
184
                }
185

    
186

    
187
                List<String> groupbyColumns = query == null ? null : query.getGroupByColumns();
188
                if (groupbyColumns != null && !groupbyColumns.isEmpty()) {
189
                    for (String columnName : groupbyColumns) {
190
                        if (this.featureType.getAttributeDescriptor(columnName) != null) {
191
                            subselect.group_by(expbuilder.column(columnName));
192
                        } else if(this.featureType.getExtraColumns().get(columnName)!=null) {
193
                            EditableFeatureAttributeDescriptor attr = this.featureType.getExtraColumns().get(columnName);
194
                            subselect.group_by(expbuilder.column(columnName));
195
                            Expression exp = ((FeatureAttributeEmulatorExpression) attr.getFeatureAttributeEmulator()).getExpression();
196
                            subselect.column().value(exp.getCode().toValue()).as(columnName);
197
                        } else {
198
                            try {
199
                                try {
200
                                    Code groupByColumnCode = ExpressionUtils.compile(columnName);
201
    //                                if (groupByColumnCode.code() == Code.CALLABLE) {
202
    //                                    Code.Callable callable = (Code.Callable) groupByColumnCode;
203
    //                                    if (callable.name().equalsIgnoreCase(FUNCTION_LET)) {
204
    //                                        Code exp = callable.parameters().get(1);
205
    //                                        Code name = callable.parameters().get(0);
206
    //                                        subselect.column().value(exp.toValue())
207
    //                                                .as((String) ((Code.Constant) name).value());
208
    //                                        // nombre que se pone en la parte del groupby debe de ser el nombre de la var del set
209
    //                                        groupByColumnCode = exp; 
210
    //                                    }
211
    //                                }
212
                                    subselect.group_by(groupByColumnCode.toValue());
213
                                } catch (Exception ex) {
214
                                    throw new RuntimeException("Not able to create column by expression in groupby query", ex);
215
                                }
216
                            } catch (Exception ex) {
217
                                throw new RuntimeException("Not able to create column by expression in groupby query", ex);
218
                            }
219
                        }
220
                    }
221
                }
222
                this.helper.processSpecialFunctions(subsqlbuilder, featureType, null);
223
                subsqlbuilder.setProperties(
224
                        ExpressionBuilder.Variable.class,
225
                        PROP_FEATURE_TYPE, this.featureType,
226
                        PROP_TABLE, table,
227
                        PROP_SYMBOLTABLE, this.query == null ? null : this.query.getSymbolTable(),
228
                        PROP_JDBCHELPER, this.helper,
229
                        PROP_QUERY, this.query
230
                );
231
                String subsql = subselect.toString();
232
                select.from().table()
233
                        .database(this.table.getDatabase())
234
                        .schema(this.table.getSchema())
235
                        .name(this.table.getTable());
236
                select.from().subquery(subsql);
237
            }
238
        } else {
239
            select.column().value(sqlbuilder.count().all());
240
            select.from().table()
241
                    .database(this.table.getDatabase())
242
                    .schema(this.table.getSchema())
243
                    .name(this.table.getTable());
244
            select.from().subquery(this.table.getSubquery());
245
            if (!StringUtils.isEmpty(baseFilter)) {
246
                sqlbuilder.select().where().set(expbuilder.custom(baseFilter));
247
            }
248
            if (this.query != null) {
249
                if (this.query.getFilter() != null && !StringUtils.isBlank(this.query.getFilter().getSQL())) {
250
                    // El and() hace un set() si no hay un filtro previo
251
                    select.where().and(expbuilder.toValue(this.query.getFilter().getSQL()));
252
                }
253
            }
254
        }
255
        this.helper.processSpecialFunctions(sqlbuilder, featureType, null);
256

    
257
        select.remove_all_columns();
258
        select.column().value(sqlbuilder.count().all());
259

    
260
//        sqlbuilder.setProperties(
261
//                ExpressionBuilder.Variable.class,
262
//                PROP_TABLE, table
263
//        );
264
        sqlbuilder.setProperties(
265
                null,
266
                PROP_FEATURE_TYPE, this.featureType,
267
                PROP_TABLE, table,
268
                PROP_SYMBOLTABLE, this.query==null? null:this.query.getSymbolTable(),
269
                PROP_JDBCHELPER, this.helper,
270
                PROP_QUERY, this.query
271
        );
272

    
273
        String sql = select.toString();
274
        return sql;
275
    }
276

    
277
    public long count(Connection conn) throws DataException {
278

    
279
        String sql = this.getSQL();
280
        Statement st = null;
281
        ResultSet rs = null;
282
        try {
283
            st = conn.createStatement();
284
            rs = JDBCUtils.executeQuery(st, sql);
285
            if (!rs.next()) {
286
                return 0;
287
            }
288
            return rs.getLong(1);
289

    
290
        } catch (SQLException ex) {
291
            throw new JDBCSQLException(ex);
292
        } finally {
293
            JDBCUtils.closeQuietly(st);
294
            JDBCUtils.closeQuietly(rs);
295
        }
296
    }
297
       
298
}