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

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

    
59
public class CountOperation extends AbstractConnectionOperation {
60

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

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

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

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

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

    
95
        SelectBuilder select = sqlbuilder.select();
96
        List<ExpressionBuilder.Value> valuesToRemoveFeatureType = new ArrayList<>();
97
        List<String> extraColumnNames = 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 (extraColumnNames != null && !extraColumnNames.contains(attr.getName())) {
107
                        extraColumnNames.add(attr.getName());
108
                    }
109
                    if (attr.getRelationType() == DynField.RELATION_TYPE_NONE) {
110
                        FeatureAttributeEmulator attrEmulator = attr.getFeatureAttributeEmulator();
111
                        if (attrEmulator instanceof FeatureAttributeEmulatorExpression) {
112
                            FeatureAttributeEmulatorExpression x = (FeatureAttributeEmulatorExpression) attrEmulator;
113
                            Expression exp = x.getExpression();
114

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

    
141
                            }
142
                        }
143
                    }
144
                }
145
            }
146
            if (this.query != null) {
147
                FeatureExtraColumns extraColumns = this.query.getExtraColumn();
148
                if (extraColumns != null && !extraColumns.isEmpty()) {
149
                    for (EditableFeatureAttributeDescriptor attr : extraColumns.getColumns()) {
150
                        if (!attr.isComputed()) {
151
                            continue;
152
                        }
153
                        if (extraColumnNames != null && !extraColumnNames.contains(attr.getName())) {
154
                            extraColumnNames.add(attr.getName());
155
                        }
156
                    }
157
                }
158
            }
159
            
160
            if (this.query.hasGroupByColumns()) {
161
                subselect.from().table()
162
                        .database(this.table.getDatabase())
163
                        .schema(this.table.getSchema())
164
                        .name(this.table.getTable());
165
                subselect.from().subquery(this.table.getSubquery());
166
                Evaluator filter = query == null ? null : query.getFilter();
167
                if (filter != null) {
168
                    String sqlfilter = filter.getSQL();
169
                    if (!StringUtils.isEmpty(sqlfilter)) {
170
                        if (this.helper.supportFilter(this.featureType, filter)) {
171
                            subselect.where().set(expbuilder.toValue(sqlfilter));
172
                        }
173
                    }
174
                }
175
                if (!StringUtils.isEmpty(baseFilter)) {
176
                    subselect.where().and(expbuilder.toValue(baseFilter));
177
                }
178

    
179

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

    
254

    
255
        select.remove_all_columns();
256
        select.column().value(sqlbuilder.count().all());
257
//        sqlbuilder.setProperties(
258
//                ExpressionBuilder.Variable.class,
259
//                PROP_TABLE, table
260
//        );
261
        sqlbuilder.setProperties(
262
                null,
263
                PROP_FEATURE_TYPE, this.featureType,
264
                PROP_TABLE, table,
265
                PROP_SYMBOLTABLE, this.query==null? null:this.query.getSymbolTable(),
266
                PROP_JDBCHELPER, this.helper,
267
                PROP_QUERY, this.query
268
        );
269
        this.helper.expandCalculedColumns(sqlbuilder);
270
        this.helper.processSpecialFunctions(sqlbuilder, featureType, null);
271

    
272
        select.remove_all_columns();
273
        select.column().value(sqlbuilder.count().all());
274
        
275
        String sql = select.toString();
276
        return sql;
277
    }
278

    
279
    public long count(JDBCConnection conn) throws DataException {
280

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

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