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

History | View | Annotate | Download (12.7 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.Expression;
33
import org.gvsig.expressionevaluator.ExpressionBuilder;
34
import org.gvsig.expressionevaluator.ExpressionEvaluator;
35
import org.gvsig.expressionevaluator.ExpressionRuntimeException;
36
import org.gvsig.expressionevaluator.ExpressionUtils;
37
import org.gvsig.expressionevaluator.Interpreter;
38
import org.gvsig.expressionevaluator.MutableSymbolTable;
39
import org.gvsig.expressionevaluator.Optimizer;
40
import org.gvsig.expressionevaluator.impl.DALFunctions;
41
import org.gvsig.fmap.dal.DALLocator;
42
import org.gvsig.fmap.dal.DataManager;
43
import static org.gvsig.fmap.dal.DataManager.FUNCTION_SELECT;
44
import org.gvsig.fmap.dal.SQLBuilder;
45
import static org.gvsig.fmap.dal.SQLBuilder.PROP_FEATURE_TYPE;
46
import static org.gvsig.fmap.dal.SQLBuilder.PROP_JDBCHELPER;
47
import static org.gvsig.fmap.dal.SQLBuilder.PROP_QUERY;
48
import static org.gvsig.fmap.dal.SQLBuilder.PROP_SQLBUILDER;
49
import static org.gvsig.fmap.dal.SQLBuilder.PROP_SYMBOLTABLE;
50
import static org.gvsig.fmap.dal.SQLBuilder.PROP_TABLE;
51
import org.gvsig.fmap.dal.feature.Feature;
52
import org.gvsig.fmap.dal.feature.FeatureQuery;
53
import org.gvsig.fmap.dal.feature.FeatureQueryOrder;
54
import org.gvsig.fmap.dal.feature.FeatureStore;
55
import org.gvsig.fmap.dal.feature.FeatureType;
56
import org.gvsig.fmap.dal.feature.impl.DefaultFeatureQueryOrder;
57
import org.gvsig.fmap.dal.impl.expressionevaluator.DefaultFeatureExpressionEvaluator;
58

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

    
68
    public SelectFunction() {
69
        super(DALFunctions.GROUP_DATA_ACCESS,
70
                FUNCTION_SELECT,
71
                Range.between(6,7),
72
                "Returns a list of features of the table by applying the filter, order and limit indicated.\n"
73
                + "The syntax is:\n\n"
74
                + "SELECT * FROM table WHERE boolean_expression ORDER BY order_column LIMIT limit;\n\n"
75
                + "Indicate a filter expression with WHERE, an order or LIMIT is optional.\n"
76
                + "You can use an asterisk or enter the column names you want to retrieve separated by commas.\n"
77
                + "The SELECT statement must always end with a semicolon.",
78
                "SELECT * FROM table WHERE boolean_expression ORDER BY order_column LIMIT limit;",
79
                new String[]{
80
                    "column_names/asterisk - Names of the columns table to retrieve.",
81
                    "table_name - Name of the table",
82
                    "filter - boolean expression to apply as filter",
83
                    "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.",
84
                    "limit - Maximum number of features to return"
85
                },
86
                "List",
87
                true
88
        );
89
    }
90

    
91
    @Override
92
    public boolean isHidden() {
93
        return false;
94
    }
95

    
96
    @Override
97
    public boolean allowConstantFolding() {
98
        return false;
99
    }
100

    
101
    @Override
102
    public boolean useArgumentsInsteadObjects() {
103
        return true;
104
    }
105

    
106
    @Override
107
    public Object call(Interpreter interpreter, Object[] args) throws Exception {
108
        throw new UnsupportedOperationException();
109
    }
110

    
111
    private static final int COLUMNS = 0;
112
    private static final int TABLE = 1;
113
    private static final int WHERE = 2;
114
    private static final int ORDER = 3;
115
    private static final int ORDER_MODE = 4;
116
    private static final int LIMIT = 5;
117
    private static final int INTOVAR = 6;
118

    
119
    @Override
120
    public Object call(Interpreter interpreter, Codes args) throws Exception {
121

    
122
        String storeName = this.getIdentifier(args, TABLE);
123
        Code columns = getTupleOrNull(args, COLUMNS);
124
        Code where = this.getWhereCode(args, WHERE);
125
        Number limit = (Number) getObject(interpreter, args, LIMIT);
126

    
127
        Callable order = getTupleOrNull(args, ORDER);
128
        Callable order_mode = getTupleOrNull(args, ORDER_MODE);
129
        FeatureQueryOrder queryOrder = null;
130
        FeatureStore featureStore;
131
        try {
132
            featureStore = this.getFeatureStore(storeName);
133
            if (featureStore == null) {
134
                throw new ExpressionRuntimeException("Cant locate the feature store '" + storeName + "' in function '" + this.name() + "'.");
135
            }
136
            if (order != null || order_mode != null) {
137
                for (int n = 0; n < order.parameters().size(); n++) {
138
                    if (queryOrder == null) {
139
                        queryOrder = new DefaultFeatureQueryOrder();
140
                    }
141
                    Boolean mode = (Boolean) ((Code.Constant)order_mode.parameters().get(n)).value();
142
                    Code memberCode = order.parameters().get(n);
143
                    if(memberCode.code() == Code.IDENTIFIER) {
144
                        queryOrder.add(((Code.Identifier)memberCode).name(), mode);
145
                    } else {
146
                        Code memberCode2 = replaceLocalVariables(interpreter, memberCode, featureStore.getDefaultFeatureTypeQuietly());
147
                        Expression exp = ExpressionUtils.createExpression(memberCode2.toString());
148
                        queryOrder.add(exp, mode);
149
                    }
150
                }
151
            }
152
            String intovar = null;
153
            if( args.size()>INTOVAR ) {
154
                intovar = this.getIdentifier(args, INTOVAR);
155
            }
156
            List<Feature> features;
157
            FeatureQuery query = featureStore.createFeatureQuery();
158
            if (where != null) {
159
                Code where2 = removeOuterTablesReferences(interpreter, where, featureStore.getDefaultFeatureTypeQuietly());
160
                ExpressionEvaluator filter = new DefaultFeatureExpressionEvaluator(where2.toString());
161
                filter.toSymbolTable().addSymbolTable(interpreter.getSymbolTable());
162
                query.addFilter(filter);
163
            }
164
            if (queryOrder != null) {
165
                query.getOrder().copyFrom(queryOrder);
166
            }
167
            if (limit != null) {
168
                query.setLimit(limit.longValue());
169
            }
170

    
171
            // FIXME: add columns to query.addAttributeName() 
172
            query.retrievesAllAttributes();
173
            if( intovar!=null ) {
174
                Feature f = featureStore.findFirst(query);
175
                ((MutableSymbolTable)(interpreter.getSymbolTable())).setVar(intovar, f);
176
                return f;
177
            }
178
            features = featureStore.getFeatures(query);
179
            return features;
180

    
181
        } catch (ExpressionRuntimeException ex) {
182
            throw ex;
183
        } catch (Exception ex) {
184
            throw new ExpressionRuntimeException("Problems calling '" + this.name() + "' function", ex);
185
        }
186
    }
187

    
188
    @Override
189
    public Code optimize(Optimizer optimizer, Callable caller) {
190
        return caller; // Don't optimize SELECT
191
    }
192

    
193
    @Override
194
    public ExpressionBuilder.Value toValue(ExpressionBuilder builder, Codes args) {
195
        try {
196
            SQLBuilder sqlBuilder = (SQLBuilder) builder.getProperty(PROP_SQLBUILDER);
197
            if(sqlBuilder == null){
198
                return super.toValue(builder, args);
199
            }
200
            FeatureType featureType = null;
201
            SQLBuilder.SelectBuilder select = sqlBuilder.createSelectBuilder();
202
            String builderTableName = (String) builder.getProperty(SQLBuilder.PROP_TABLENAME);
203

    
204
            String storeName = this.getIdentifier(args, TABLE);
205
            Callable columns = getTupleOrNull(args, COLUMNS);
206
            Code where = this.getWhereCode(args, WHERE);
207
            Callable order = getTupleOrNull(args, ORDER);
208
            Callable order_mode = getTupleOrNull(args, ORDER_MODE);
209
            Code limit = args.get(LIMIT);
210

    
211
            if (storeName != null) {
212
                select.from().table().name(storeName);
213
            }
214

    
215
            SQLBuilder.TableNameBuilder table = select.from().table();
216
            String tableName = table.getName();
217
            if (columns != null) {
218
                if(columns.parameters().isEmpty()){
219
                    select.column().all();
220
                } else {
221
                    for (Code column : columns.parameters()) {
222
                        if (column instanceof Code.Identifier) {
223
                            String columnName = ((Code.Identifier) column).name();
224
                            if(featureType == null) {
225
                                if(StringUtils.equalsIgnoreCase(builderTableName, tableName)){
226
                                    featureType = (FeatureType) builder.getProperty(SQLBuilder.PROP_FEATURE_TYPE);
227
                                } else {
228
                                    DataManager dataManager = DALLocator.getDataManager();
229
                                    featureType = dataManager.getStoresRepository().getFeatureType(tableName);
230
                                }
231
                            }
232
                            if(featureType == null){
233
                                select.column().name(
234
                                        select.from().table(),
235
                                        columnName
236
                                );
237
                            } else if(featureType.get(columnName) != null) {
238
                                select.column().name(
239
                                        select.from().table(),
240
                                        columnName
241
                                );
242
                            } else {
243
                                select.column().name(
244
                                        columnName
245
                                ).table(null);
246
                            }
247
                        }
248
                    }
249
                }
250
            }
251

    
252
            if (where != null) {
253
                ExpressionBuilder.Value value = where.toValue(builder);
254
                select.where().value(value);
255
                sqlBuilder.setProperties(value, null, SQLBuilder.PROP_ADD_TABLE_NAME_TO_COLUMNS, true);
256
            }
257

    
258
            if (limit != null) {
259
                Object value = ((Code.Constant) limit).value();
260
                if(value != null){
261
                    select.limit(((Number) value).longValue());
262
                }
263
            }
264

    
265
            if (order != null || order_mode != null) {
266
                for (int n = 0; n < order.parameters().size(); n++) {
267
                    Code member = order.parameters().get(n);
268
                    Code.Constant mode = (Code.Constant) order_mode.parameters().get(n);
269
                    select.order_by().value(member.toValue(builder)).ascending((boolean) mode.value());
270
                }
271
            }
272
            if (featureType == null) {
273
                if (StringUtils.equalsIgnoreCase(builderTableName, tableName)) {
274
                    featureType = (FeatureType) builder.getProperty(SQLBuilder.PROP_FEATURE_TYPE);
275
                } else {
276
                    DataManager dataManager = DALLocator.getDataManager();
277
                    featureType = dataManager.getStoresRepository().getFeatureType(tableName);
278
                }
279
            }
280

    
281
            sqlBuilder.setProperties(
282
                    select,
283
                    null,
284
                    PROP_FEATURE_TYPE, featureType,
285
                    PROP_TABLE, table
286
            );
287

    
288
            return builder.group(select);
289
        } catch (Exception ex) {
290
            return super.toValue(builder, args);
291
        }
292
    }
293
    
294
}