Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.dal / org.gvsig.fmap.dal.impl / src / main / java / org / gvsig / expressionevaluator / impl / function / dataaccess / SelectFunction.java @ 46954

History | View | Annotate | Download (11.6 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.expressionevaluator.impl.function.dataaccess;
25

    
26
import java.util.List;
27
import org.apache.commons.lang3.Range;
28
import org.apache.commons.lang3.StringUtils;
29
import org.gvsig.expressionevaluator.Code;
30
import org.gvsig.expressionevaluator.Code.Callable;
31
import org.gvsig.expressionevaluator.Codes;
32
import org.gvsig.expressionevaluator.ExpressionBuilder;
33
import org.gvsig.expressionevaluator.ExpressionEvaluator;
34
import org.gvsig.expressionevaluator.ExpressionRuntimeException;
35
import org.gvsig.expressionevaluator.Interpreter;
36
import org.gvsig.expressionevaluator.Optimizer;
37
import org.gvsig.expressionevaluator.impl.DALFunctions;
38
import org.gvsig.fmap.dal.DALLocator;
39
import org.gvsig.fmap.dal.DataManager;
40
import static org.gvsig.fmap.dal.DataManager.FUNCTION_SELECT;
41
import org.gvsig.fmap.dal.SQLBuilder;
42
import static org.gvsig.fmap.dal.SQLBuilder.PROP_FEATURE_TYPE;
43
import static org.gvsig.fmap.dal.SQLBuilder.PROP_JDBCHELPER;
44
import static org.gvsig.fmap.dal.SQLBuilder.PROP_QUERY;
45
import static org.gvsig.fmap.dal.SQLBuilder.PROP_SQLBUILDER;
46
import static org.gvsig.fmap.dal.SQLBuilder.PROP_SYMBOLTABLE;
47
import static org.gvsig.fmap.dal.SQLBuilder.PROP_TABLE;
48
import org.gvsig.fmap.dal.feature.Feature;
49
import org.gvsig.fmap.dal.feature.FeatureQuery;
50
import org.gvsig.fmap.dal.feature.FeatureQueryOrder;
51
import org.gvsig.fmap.dal.feature.FeatureStore;
52
import org.gvsig.fmap.dal.feature.FeatureType;
53
import org.gvsig.fmap.dal.feature.impl.DefaultFeatureQueryOrder;
54
import org.gvsig.fmap.dal.impl.expressionevaluator.DefaultFeatureExpressionEvaluator;
55

    
56
/**
57
 *
58
 * @author jjdelcerro
59
 */
60
@SuppressWarnings("UseSpecificCatch")
61
public class SelectFunction
62
        extends AbstractSelectFunction
63
        implements Optimizer.FunctionOptimizer {
64

    
65
    public SelectFunction() {
66
        super(DALFunctions.GROUP_DATA_ACCESS,
67
                FUNCTION_SELECT,
68
                Range.is(6),
69
                "Returns a list of features of the table by applying the filter, order and limit indicated.\n"
70
                + "The syntax is:\n\n"
71
                + "SELECT * FROM table WHERE boolean_expression ORDER BY order_column LIMIT limit;\n\n"
72
                + "Indicate a filter expression with WHERE, an order or LIMIT is optional.\n"
73
                + "You can use an asterisk or enter the column names you want to retrieve separated by commas.\n"
74
                + "The SELECT statement must always end with a semicolon.",
75
                "SELECT * FROM table WHERE boolean_expression ORDER BY order_column LIMIT limit;",
76
                new String[]{
77
                    "column_names/asterisk - Names of the columns table to retrieve.",
78
                    "table_name - Name of the table",
79
                    "filter - boolean expression to apply as filter",
80
                    "order_column - the order used to retrieve the features. It is a list of column names separated by a comma. The column name can optionally be followed by ASC or DESC to indicate whether the order should be ascending or descending.",
81
                    "limit - Maximum number of features to return"
82
                },
83
                "List",
84
                true
85
        );
86
    }
87

    
88
    @Override
89
    public boolean isHidden() {
90
        return false;
91
    }
92

    
93
    @Override
94
    public boolean allowConstantFolding() {
95
        return false;
96
    }
97

    
98
    @Override
99
    public boolean useArgumentsInsteadObjects() {
100
        return true;
101
    }
102

    
103
    @Override
104
    public Object call(Interpreter interpreter, Object[] args) throws Exception {
105
        throw new UnsupportedOperationException();
106
    }
107

    
108
    private static final int COLUMNS = 0;
109
    private static final int TABLE = 1;
110
    private static final int WHERE = 2;
111
    private static final int ORDER = 3;
112
    private static final int ORDER_MODE = 4;
113
    private static final int LIMIT = 5;
114

    
115
    @Override
116
    public Object call(Interpreter interpreter, Codes args) throws Exception {
117

    
118
        String storeName = this.getIdentifier(args, TABLE);
119
        Code columns = getTupleOrNull(args, COLUMNS);
120
        Code where = this.getWhereCode(args, WHERE);
121
        Number limit = (Number) getObject(interpreter, args, LIMIT);
122

    
123
        Callable order = getTupleOrNull(args, ORDER);
124
        Callable order_mode = getTupleOrNull(args, ORDER_MODE);
125
        FeatureQueryOrder queryOrder = null;
126
        if (order != null || order_mode != null) {
127
            for (int n = 0; n < order.parameters().size(); n++) {
128
                String member = (String) interpreter.run(order.parameters().get(n));
129
                Boolean mode = (Boolean) interpreter.run(order_mode.parameters().get(n));
130
                if (queryOrder == null) {
131
                    queryOrder = new DefaultFeatureQueryOrder();
132
                }
133
                queryOrder.add(member, mode);
134
            }
135
        }
136
        FeatureStore featureStore;
137
        try {
138
            featureStore = this.getFeatureStore(storeName);
139
            if (featureStore == null) {
140
                throw new ExpressionRuntimeException("Cant locate the feature store '" + storeName + "' in function '" + this.name() + "'.");
141
            }
142
            List<Feature> features;
143
            FeatureQuery query = featureStore.createFeatureQuery();
144
            if (where != null) {
145
                Code where2 = removeOuterTablesReferences(interpreter, where);
146
                ExpressionEvaluator filter = new DefaultFeatureExpressionEvaluator(where2.toString());
147
                filter.toSymbolTable().addSymbolTable(interpreter.getSymbolTable());
148
                query.addFilter(filter);
149
            }
150
            if (queryOrder != null) {
151
                query.getOrder().copyFrom(queryOrder);
152
            }
153
            if (limit != null) {
154
                query.setLimit(limit.longValue());
155
            }
156

    
157
            // FIXME: add columns to query.addAttributeName() 
158
            query.retrievesAllAttributes();
159
            features = featureStore.getFeatures(query);
160
            return features;
161

    
162
        } catch (ExpressionRuntimeException ex) {
163
            throw ex;
164
        } catch (Exception ex) {
165
            throw new ExpressionRuntimeException("Problems calling '" + this.name() + "' function", ex);
166
        }
167
    }
168

    
169
    @Override
170
    public Code optimize(Optimizer optimizer, Callable caller) {
171
        return caller; // Don't optimize SELECT
172
    }
173

    
174
    @Override
175
    public ExpressionBuilder.Value toValue(ExpressionBuilder builder, Codes args) {
176
        try {
177
            SQLBuilder sqlBuilder = (SQLBuilder) builder.getProperty(PROP_SQLBUILDER);
178
            if(sqlBuilder == null){
179
                return super.toValue(builder, args);
180
            }
181
            FeatureType featureType = null;
182
            SQLBuilder.SelectBuilder select = sqlBuilder.createSelectBuilder();
183
            String builderTableName = (String) builder.getProperty(SQLBuilder.PROP_TABLENAME);
184

    
185
            String storeName = this.getIdentifier(args, TABLE);
186
            Callable columns = getTupleOrNull(args, COLUMNS);
187
            Code where = this.getWhereCode(args, WHERE);
188
            Callable order = getTupleOrNull(args, ORDER);
189
            Callable order_mode = getTupleOrNull(args, ORDER_MODE);
190
            Code limit = args.get(LIMIT);
191

    
192
            if (storeName != null) {
193
                select.from().table().name(storeName);
194
            }
195

    
196
            SQLBuilder.TableNameBuilder table = select.from().table();
197
            String tableName = table.getName();
198
            if (columns != null) {
199
                if(columns.parameters().isEmpty()){
200
                    select.column().all();
201
                } else {
202
                    for (Code column : columns.parameters()) {
203
                        if (column instanceof Code.Identifier) {
204
                            String columnName = ((Code.Identifier) column).name();
205
                            if(featureType == null) {
206
                                if(StringUtils.equalsIgnoreCase(builderTableName, tableName)){
207
                                    featureType = (FeatureType) builder.getProperty(SQLBuilder.PROP_FEATURE_TYPE);
208
                                } else {
209
                                    DataManager dataManager = DALLocator.getDataManager();
210
                                    featureType = dataManager.getStoresRepository().getFeatureType(tableName);
211
                                }
212
                            }
213
                            if(featureType == null){
214
                                select.column().name(
215
                                        select.from().table(),
216
                                        columnName
217
                                );
218
                            } else if(featureType.get(columnName) != null) {
219
                                select.column().name(
220
                                        select.from().table(),
221
                                        columnName
222
                                );
223
                            } else {
224
                                select.column().name(
225
                                        columnName
226
                                ).table(null);
227
                            }
228
                        }
229
                    }
230
                }
231
            }
232

    
233
            if (where != null) {
234
                ExpressionBuilder.Value value = where.toValue(builder);
235
                select.where().value(value);
236
                sqlBuilder.setProperties(value, null, SQLBuilder.PROP_ADD_TABLE_NAME_TO_COLUMNS, true);
237
            }
238

    
239
            if (limit != null) {
240
                Object value = ((Code.Constant) limit).value();
241
                if(value != null){
242
                    select.limit(((Number) value).longValue());
243
                }
244
            }
245

    
246
            if (order != null || order_mode != null) {
247
                for (int n = 0; n < order.parameters().size(); n++) {
248
                    Code member = order.parameters().get(n);
249
                    Code.Constant mode = (Code.Constant) order_mode.parameters().get(n);
250
                    select.order_by().value(member.toValue(builder)).ascending((boolean) mode.value());
251
                }
252
            }
253
            if (featureType == null) {
254
                if (StringUtils.equalsIgnoreCase(builderTableName, tableName)) {
255
                    featureType = (FeatureType) builder.getProperty(SQLBuilder.PROP_FEATURE_TYPE);
256
                } else {
257
                    DataManager dataManager = DALLocator.getDataManager();
258
                    featureType = dataManager.getStoresRepository().getFeatureType(tableName);
259
                }
260
            }
261

    
262
            sqlBuilder.setProperties(
263
                    select,
264
                    null,
265
                    PROP_FEATURE_TYPE, featureType,
266
                    PROP_TABLE, table
267
            );
268

    
269
            return builder.group(select);
270
        } catch (Exception ex) {
271
            return super.toValue(builder, args);
272
        }
273
    }
274
    
275
}