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

History | View | Annotate | Download (13.3 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.fmap.dal.SQLBuilder.SelectBuilder;
38
import org.gvsig.fmap.dal.exception.DataException;
39
import org.gvsig.fmap.dal.expressionevaluator.FeatureAttributeEmulatorExpression;
40
import org.gvsig.fmap.dal.feature.EditableFeatureAttributeDescriptor;
41
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
42
import org.gvsig.fmap.dal.feature.FeatureAttributeEmulator;
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.JDBCUtils;
49
import org.gvsig.fmap.dal.store.jdbc2.OperationsFactory.TableReference;
50
import static org.gvsig.fmap.dal.store.jdbc2.spi.JDBCSQLBuilderBase.PROP_FEATURE_TYPE;
51
import static org.gvsig.fmap.dal.store.jdbc2.spi.JDBCSQLBuilderBase.PROP_JDBCHELPER;
52
import static org.gvsig.fmap.dal.store.jdbc2.spi.JDBCSQLBuilderBase.PROP_QUERY;
53
import static org.gvsig.fmap.dal.store.jdbc2.spi.JDBCSQLBuilderBase.PROP_SYMBOLTABLE;
54
import static org.gvsig.fmap.dal.store.jdbc2.spi.JDBCSQLBuilderBase.PROP_TABLE;
55
import org.gvsig.tools.dynobject.DynField;
56
import org.gvsig.tools.evaluator.Evaluator;
57

    
58
public class CountOperation extends AbstractConnectionOperation {
59

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

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

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

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

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

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

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

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

    
136
                            }
137
                        }
138
                    }
139
                }
140
            }
141
            
142
            
143
            
144
            
145
            
146
            if (this.query.hasGroupByColumns()) {
147
                subselect.from().table()
148
                        .database(this.table.getDatabase())
149
                        .schema(this.table.getSchema())
150
                        .name(this.table.getTable());
151
                subselect.from().subquery(this.table.getSubquery());
152
                Evaluator filter = query == null ? null : query.getFilter();
153
                if (filter != null) {
154
                    String sqlfilter = filter.getSQL();
155
                    if (!StringUtils.isEmpty(sqlfilter)) {
156
                        if (this.helper.supportFilter(this.featureType, filter)) {
157
                            subselect.where().set(expbuilder.toValue(sqlfilter));
158
                        }
159
                    }
160
                }
161
                if (!StringUtils.isEmpty(baseFilter)) {
162
                    subselect.where().and(expbuilder.toValue(baseFilter));
163
                }
164

    
165

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

    
240

    
241
        select.remove_all_columns();
242
        select.column().value(sqlbuilder.count().all());
243
//        sqlbuilder.setProperties(
244
//                ExpressionBuilder.Variable.class,
245
//                PROP_TABLE, table
246
//        );
247
        sqlbuilder.setProperties(
248
                null,
249
                PROP_FEATURE_TYPE, this.featureType,
250
                PROP_TABLE, table,
251
                PROP_SYMBOLTABLE, this.query==null? null:this.query.getSymbolTable(),
252
                PROP_JDBCHELPER, this.helper,
253
                PROP_QUERY, this.query
254
        );
255
        this.helper.expandCalculedColumns(sqlbuilder);
256
        this.helper.processSpecialFunctions(sqlbuilder, featureType, null);
257

    
258
        select.remove_all_columns();
259
        select.column().value(sqlbuilder.count().all());
260
        
261
        String sql = select.toString();
262
        return sql;
263
    }
264

    
265
    public long count(Connection conn) throws DataException {
266

    
267
        String sql = this.getSQL();
268
        Statement st = null;
269
        ResultSet rs = null;
270
        try {
271
            st = conn.createStatement();
272
            rs = JDBCUtils.executeQuery(st, sql);
273
            if (!rs.next()) {
274
                return 0;
275
            }
276
            return rs.getLong(1);
277

    
278
        } catch (SQLException ex) {
279
            throw new JDBCSQLException(ex);
280
        } finally {
281
            JDBCUtils.closeQuietly(st);
282
            JDBCUtils.closeQuietly(rs);
283
        }
284
    }
285
       
286
}