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 @ 46517
History | View | Annotate | Download (10.3 KB)
1 | 44738 | jjdelcerro | /**
|
---|---|---|---|
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 | 46517 | fdiaz | import org.apache.commons.lang3.StringUtils; |
29 | 44750 | jjdelcerro | import org.gvsig.expressionevaluator.Code; |
30 | 44738 | jjdelcerro | import org.gvsig.expressionevaluator.Codes; |
31 | import org.gvsig.expressionevaluator.ExpressionRuntimeException; |
||
32 | import org.gvsig.expressionevaluator.Interpreter; |
||
33 | 44750 | jjdelcerro | import org.gvsig.expressionevaluator.Optimizer; |
34 | 44738 | jjdelcerro | import org.gvsig.expressionevaluator.impl.DALFunctions; |
35 | 44748 | jjdelcerro | import static org.gvsig.fmap.dal.DataManager.FUNCTION_SELECT; |
36 | 45366 | omartinez | import org.gvsig.expressionevaluator.ExpressionEvaluator; |
37 | 44738 | jjdelcerro | import org.gvsig.fmap.dal.feature.Feature; |
38 | import org.gvsig.fmap.dal.feature.FeatureQuery; |
||
39 | import org.gvsig.fmap.dal.feature.FeatureQueryOrder; |
||
40 | import org.gvsig.fmap.dal.feature.FeatureStore; |
||
41 | 45366 | omartinez | import org.gvsig.fmap.dal.impl.expressionevaluator.DefaultFeatureExpressionEvaluator; |
42 | 44752 | jjdelcerro | import org.gvsig.expressionevaluator.Code.Callable; |
43 | 46505 | fdiaz | import org.gvsig.expressionevaluator.ExpressionBuilder; |
44 | import org.gvsig.expressionevaluator.ExpressionBuilder.Value; |
||
45 | 46517 | fdiaz | import org.gvsig.fmap.dal.DALLocator; |
46 | import org.gvsig.fmap.dal.DataManager; |
||
47 | 46505 | fdiaz | import org.gvsig.fmap.dal.SQLBuilder; |
48 | 46517 | fdiaz | import org.gvsig.fmap.dal.feature.FeatureType; |
49 | 45308 | fdiaz | import org.gvsig.fmap.dal.feature.impl.DefaultFeatureQueryOrder; |
50 | 44738 | jjdelcerro | |
51 | /**
|
||
52 | *
|
||
53 | * @author jjdelcerro
|
||
54 | */
|
||
55 | 45127 | jjdelcerro | @SuppressWarnings("UseSpecificCatch") |
56 | 46088 | jjdelcerro | public class SelectFunction |
57 | extends AbstractSelectFunction
|
||
58 | implements Optimizer.FunctionOptimizer {
|
||
59 | 44738 | jjdelcerro | |
60 | 46088 | jjdelcerro | public SelectFunction() {
|
61 | super(DALFunctions.GROUP_DATA_ACCESS,
|
||
62 | FUNCTION_SELECT, |
||
63 | Range.is(6),
|
||
64 | "Returns a list of features of the table by applying the filter, order and limit indicated.\n"
|
||
65 | + "The syntax is:\n\n"
|
||
66 | + "SELECT * FROM table WHERE boolean_expression ORDER BY order_column LIMIT limit;\n\n"
|
||
67 | + "Indicate a filter expression with WHERE, an order or LIMIT is optional.\n"
|
||
68 | + "You can use an asterisk or enter the column names you want to retrieve separated by commas.\n"
|
||
69 | + "The SELECT statement must always end with a semicolon.",
|
||
70 | "SELECT * FROM table WHERE boolean_expression ORDER BY order_column LIMIT limit;",
|
||
71 | new String[]{ |
||
72 | "column_names/asterisk - Names of the columns table to retrieve.",
|
||
73 | "table_name - Name of the table",
|
||
74 | "filter - boolean expression to apply as filter",
|
||
75 | "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.",
|
||
76 | "limit - Maximum number of features to return"
|
||
77 | }, |
||
78 | "List",
|
||
79 | true
|
||
80 | ); |
||
81 | } |
||
82 | 44738 | jjdelcerro | |
83 | 46088 | jjdelcerro | @Override
|
84 | public boolean isHidden() { |
||
85 | return false; |
||
86 | } |
||
87 | 44738 | jjdelcerro | |
88 | 46088 | jjdelcerro | @Override
|
89 | public boolean allowConstantFolding() { |
||
90 | return false; |
||
91 | } |
||
92 | 44738 | jjdelcerro | |
93 | 46088 | jjdelcerro | @Override
|
94 | public boolean useArgumentsInsteadObjects() { |
||
95 | return true; |
||
96 | 44750 | jjdelcerro | } |
97 | 44738 | jjdelcerro | |
98 | 46088 | jjdelcerro | @Override
|
99 | public Object call(Interpreter interpreter, Object[] args) throws Exception { |
||
100 | throw new UnsupportedOperationException(); |
||
101 | 45117 | jjdelcerro | } |
102 | 44738 | jjdelcerro | |
103 | 46088 | jjdelcerro | private static final int COLUMNS = 0; |
104 | private static final int TABLE = 1; |
||
105 | private static final int WHERE = 2; |
||
106 | private static final int ORDER = 3; |
||
107 | private static final int ORDER_MODE = 4; |
||
108 | private static final int LIMIT = 5; |
||
109 | 44738 | jjdelcerro | |
110 | 46088 | jjdelcerro | @Override
|
111 | public Object call(Interpreter interpreter, Codes args) throws Exception { |
||
112 | |||
113 | String storeName = this.getTableName(args, TABLE); |
||
114 | Code columns = getTupleOrNull(args, COLUMNS); |
||
115 | Code where = this.getWhereCode(args, WHERE);
|
||
116 | Number limit = (Number) getObject(interpreter, args, LIMIT); |
||
117 | |||
118 | Callable order = getTupleOrNull(args, ORDER);
|
||
119 | Callable order_mode = getTupleOrNull(args, ORDER_MODE);
|
||
120 | FeatureQueryOrder queryOrder = null;
|
||
121 | if (order != null || order_mode != null) { |
||
122 | for (int n = 0; n < order.parameters().size(); n++) { |
||
123 | String member = (String) interpreter.run(order.parameters().get(n)); |
||
124 | Boolean mode = (Boolean) interpreter.run(order_mode.parameters().get(n)); |
||
125 | if (queryOrder == null) { |
||
126 | queryOrder = new DefaultFeatureQueryOrder();
|
||
127 | 44750 | jjdelcerro | } |
128 | 46088 | jjdelcerro | queryOrder.add(member, mode); |
129 | } |
||
130 | 45127 | jjdelcerro | } |
131 | 46100 | jjdelcerro | FeatureStore featureStore; |
132 | 46088 | jjdelcerro | try {
|
133 | featureStore = this.getFeatureStore(storeName);
|
||
134 | if (featureStore == null) { |
||
135 | throw new ExpressionRuntimeException("Cant locate the feature store '" + storeName + "' in function '" + this.name() + "'."); |
||
136 | } |
||
137 | List<Feature> features;
|
||
138 | FeatureQuery query = featureStore.createFeatureQuery(); |
||
139 | if (where != null) { |
||
140 | Code where2 = removeOuterTablesReferences(interpreter, where); |
||
141 | ExpressionEvaluator filter = new DefaultFeatureExpressionEvaluator(where2.toString());
|
||
142 | filter.toSymbolTable().addSymbolTable(interpreter.getSymbolTable()); |
||
143 | query.addFilter(filter); |
||
144 | } |
||
145 | if (queryOrder != null) { |
||
146 | query.getOrder().copyFrom(queryOrder); |
||
147 | } |
||
148 | if (limit != null) { |
||
149 | query.setLimit(limit.longValue()); |
||
150 | } |
||
151 | |||
152 | // FIXME: add columns to query.addAttributeName()
|
||
153 | query.retrievesAllAttributes(); |
||
154 | features = featureStore.getFeatures(query); |
||
155 | return features;
|
||
156 | |||
157 | } catch (ExpressionRuntimeException ex) {
|
||
158 | throw ex;
|
||
159 | } catch (Exception ex) { |
||
160 | 46100 | jjdelcerro | throw new ExpressionRuntimeException("Problems calling '" + this.name() + "' function", ex); |
161 | 45127 | jjdelcerro | } |
162 | 44750 | jjdelcerro | } |
163 | |||
164 | 46088 | jjdelcerro | @Override
|
165 | public Code optimize(Optimizer optimizer, Callable caller) { |
||
166 | return caller; // Don't optimize SELECT |
||
167 | } |
||
168 | 44750 | jjdelcerro | |
169 | 46505 | fdiaz | @Override
|
170 | public ExpressionBuilder.Value toValue(ExpressionBuilder builder, Codes args) {
|
||
171 | try {
|
||
172 | SQLBuilder sqlBuilder = (SQLBuilder) builder.getProperty("SQLBUILDER");
|
||
173 | if(sqlBuilder == null){ |
||
174 | return super.toValue(builder, args); |
||
175 | } |
||
176 | SQLBuilder.SelectBuilder select = sqlBuilder.createSelectBuilder(); |
||
177 | |||
178 | String storeName = this.getTableName(args, TABLE); |
||
179 | Callable columns = getTupleOrNull(args, COLUMNS);
|
||
180 | Code where = this.getWhereCode(args, WHERE);
|
||
181 | Callable order = getTupleOrNull(args, ORDER);
|
||
182 | Callable order_mode = getTupleOrNull(args, ORDER_MODE);
|
||
183 | Code limit = args.get(LIMIT); |
||
184 | |||
185 | if (storeName != null) { |
||
186 | select.from().table().name(storeName); |
||
187 | } |
||
188 | |||
189 | if (columns != null) { |
||
190 | 46517 | fdiaz | if(columns.parameters().isEmpty()){
|
191 | select.column().all(); |
||
192 | } else {
|
||
193 | for (Code column : columns.parameters()) {
|
||
194 | if (column instanceof Code.Identifier) { |
||
195 | String tableName = select.from().table().getName();
|
||
196 | String columnName = ((Code.Identifier) column).name();
|
||
197 | String builderTable = (String) builder.getProperty("Table"); |
||
198 | FeatureType featureType = null;
|
||
199 | if(StringUtils.equalsIgnoreCase(builderTable, tableName)){
|
||
200 | featureType = (FeatureType) builder.getProperty("FeatureType");
|
||
201 | } else {
|
||
202 | DataManager dataManager = DALLocator.getDataManager(); |
||
203 | featureType = dataManager.getStoresRepository().getFeatureType(tableName); |
||
204 | } |
||
205 | if(featureType == null){ |
||
206 | select.column().name( |
||
207 | select.from().table(), |
||
208 | columnName |
||
209 | ); |
||
210 | } else if(featureType.get(columnName) != null) { |
||
211 | select.column().name( |
||
212 | select.from().table(), |
||
213 | columnName |
||
214 | ); |
||
215 | } else {
|
||
216 | select.column().name( |
||
217 | columnName |
||
218 | ).table(null);
|
||
219 | } |
||
220 | } |
||
221 | 46505 | fdiaz | } |
222 | } |
||
223 | } |
||
224 | |||
225 | if (where != null) { |
||
226 | select.where().value(where.toValue(builder)); |
||
227 | } |
||
228 | |||
229 | if (limit != null) { |
||
230 | select.limit(((Number) ((Code.Constant) limit).value()).longValue());
|
||
231 | } |
||
232 | |||
233 | if (order != null || order_mode != null) { |
||
234 | for (int n = 0; n < order.parameters().size(); n++) { |
||
235 | Code member = order.parameters().get(n); |
||
236 | Code.Constant mode = (Code.Constant) order_mode.parameters().get(n); |
||
237 | select.order_by().value(member.toValue(builder)).ascending((boolean) mode.value());
|
||
238 | } |
||
239 | } |
||
240 | return select;
|
||
241 | } catch (Exception ex) { |
||
242 | return super.toValue(builder, args); |
||
243 | } |
||
244 | } |
||
245 | |||
246 | 44738 | jjdelcerro | } |