Revision 46505 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/ResultSetForSetProviderOperation.java

View differences:

ResultSetForSetProviderOperation.java
28 28
import java.util.List;
29 29
import java.util.Map;
30 30
import org.apache.commons.lang3.ArrayUtils;
31
import org.apache.commons.lang3.BooleanUtils;
32 31
import org.apache.commons.lang3.StringUtils;
33 32
import org.gvsig.expressionevaluator.Code;
34 33
import org.gvsig.expressionevaluator.Expression;
35 34
import org.gvsig.expressionevaluator.ExpressionBuilder;
36 35
import static org.gvsig.expressionevaluator.ExpressionBuilder.FUNCTION_LET;
37 36
import org.gvsig.expressionevaluator.ExpressionUtils;
37
import org.gvsig.expressionevaluator.GeometryExpressionBuilder;
38 38
import org.gvsig.fmap.dal.SQLBuilder;
39
import org.gvsig.fmap.dal.SQLBuilder.Column;
39 40
import org.gvsig.fmap.dal.SQLBuilder.OrderByBuilder;
40 41
import org.gvsig.fmap.dal.SQLBuilder.SelectBuilder;
41 42
import org.gvsig.fmap.dal.exception.DataException;
......
48 49
import org.gvsig.fmap.dal.feature.FeatureQueryOrder;
49 50
import org.gvsig.fmap.dal.feature.FeatureQueryOrder.FeatureQueryOrderMember;
50 51
import org.gvsig.fmap.dal.feature.FeatureType;
52
import org.gvsig.fmap.dal.feature.SQLBuilder_save;
51 53
import org.gvsig.fmap.dal.store.jdbc2.JDBCConnection;
52 54
import org.gvsig.fmap.dal.store.jdbc2.JDBCHelper;
53
import org.gvsig.fmap.dal.store.jdbc2.JDBCServerExplorer;
54 55
import static org.gvsig.fmap.dal.store.jdbc2.JDBCServerExplorer.QUERY_DONT_ADD_PRIMARY_KEY_IN_THE_ORDER;
55 56
import org.gvsig.fmap.dal.store.jdbc2.OperationsFactory.TableReference;
56 57
import org.gvsig.fmap.dal.store.jdbc2.ResulSetControler.ResultSetEntry;
58
import static org.gvsig.fmap.dal.store.jdbc2.spi.JDBCHelperBase.DONT_ADD_TABLE_NAME_TO_COLUMNS;
57 59
import org.gvsig.fmap.dal.store.jdbc2.spi.JDBCSQLBuilderBase;
58 60
import static org.gvsig.fmap.dal.store.jdbc2.spi.JDBCSQLBuilderBase.PROP_FEATURE_TYPE;
59 61
import static org.gvsig.fmap.dal.store.jdbc2.spi.JDBCSQLBuilderBase.PROP_JDBCHELPER;
......
128 130
        double tolerance = -1; //query.getScale(); 
129 131
        ExpressionBuilder expbuilder = sqlbuilder.expression();
130 132
        SelectBuilder select = sqlbuilder.select();
131
        ArrayList<ExpressionBuilder.Value> valuesToRemoveFeatureType = new ArrayList<>();
133
        select.from().table()
134
                .database(this.table.getDatabase())
135
                .schema(this.table.getSchema())
136
                .name(this.table.getTable());
137
        select.from().subquery(this.table.getSubquery());
138

  
139

  
140
        List<ExpressionBuilder.Value> valuesToRemoveFeatureType = new ArrayList<>();
132 141
        
133 142
        if( shouldUseACustomSelect() ) {
134
            String sql = table.getSubquery();
135
            if( StringUtils.containsAny(sql, "${where_filter}", "${and_filter}") ) {
136
                Evaluator filter = query.getFilter();
137
                if (filter != null) {
138
                    String sqlfilter = filter.getSQL();
139
                    if (!StringUtils.isEmpty(sqlfilter)) {
140
                        if (this.helper.supportFilter(this.storeType, filter)) {
141
                            select.where().set(expbuilder.toValue(sqlfilter));
142
                        }
143
            return processCustomSelect(select, expbuilder, sqlbuilder, valuesToRemoveFeatureType, columns);
144
        }
145
        
146

  
147
        Map<String, EditableFeatureAttributeDescriptor> allExtraColumns = getAllExtraColumns(this.setType, this.query);
148

  
149
        List<String> primaryKeys = new ArrayList<>();
150
        for (FeatureAttributeDescriptor attr : storeType.getPrimaryKey()) {
151
            primaryKeys.add(attr.getName());
152
        }
153
        
154
        //Don't change order of this processes
155
        process1_SimpleFields(helper, setType, query, sqlbuilder, select, columns, primaryKeys, extraColumnNames);
156
        process2_ComputedFields(helper, setType, query, sqlbuilder, select, extraColumnNames);
157
        process3_Where(helper, storeType, query, sqlbuilder, select);
158
        process4_Aggregates(this.table, this.setType, this.query, allExtraColumns, sqlbuilder, select, extraColumnNames);
159
        process5_GroupBys(this.table, this.setType, this.query, allExtraColumns, sqlbuilder, select, extraColumnNames);
160
        process6_OrderBy(storeType, setType, query, allExtraColumns, sqlbuilder, select, primaryKeys, extraColumnNames, valuesToRemoveFeatureType);
161
        
162
        if (!StringUtils.isEmpty(baseFilter)) {
163
            select.where().and(expbuilder.toValue(baseFilter));
164
        }
165

  
166
        if (!StringUtils.isEmpty(baseOrder)) {
167
            select.order_by().custom(baseOrder);
168
        }
169

  
170
        
171
        if (limit > 0) {
172
            select.limit(limit);
173
        } else {
174
            select.limit(query == null ? null : query.getLimit());
175
        }
176
        if (offset > 0) {
177
            select.offset(offset);
178
        }
179
        sqlbuilder.setProperties(
180
                null,
181
                PROP_FEATURE_TYPE, this.storeType,
182
                PROP_TABLE, table,
183
                PROP_SYMBOLTABLE, this.query==null? null:this.query.getSymbolTable(),
184
                PROP_JDBCHELPER, this.helper,
185
                PROP_QUERY, this.query
186
        );
187
        for (ExpressionBuilder.Value value : valuesToRemoveFeatureType) {
188
            value.setProperty(PROP_FEATURE_TYPE, null);
189
        }
190
	this.helper.expandCalculedColumns(sqlbuilder);
191
        this.helper.processSpecialFunctions(sqlbuilder, storeType, extraColumnNames);
192
        String sql = sqlbuilder.toString();
193
        LOGGER.debug(sql);
194
        return sql;
195
    }
196

  
197
    private String processCustomSelect(SelectBuilder select, ExpressionBuilder expbuilder, JDBCSQLBuilderBase sqlbuilder, List<ExpressionBuilder.Value> valuesToRemoveFeatureType, List<FeatureAttributeDescriptor> columns) {
198
        String sql = table.getSubquery();
199
        if( StringUtils.containsAny(sql, "${where_filter}", "${and_filter}") ) {
200
            Evaluator filter = query.getFilter();
201
            if (filter != null) {
202
                String sqlfilter = filter.getSQL();
203
                if (!StringUtils.isEmpty(sqlfilter)) {
204
                    if (this.helper.supportFilter(this.storeType, filter)) {
205
                        select.where().set(expbuilder.toValue(sqlfilter));
143 206
                    }
144 207
                }
145
                if (!StringUtils.isEmpty(baseFilter)) {
146
                    select.where().and(expbuilder.toValue(baseFilter));
147
                }
148 208
            }
149
            if( StringUtils.containsAny(sql, "${order_by_orderspec}", "${comma_orderspec}") ) {
150
                FeatureQueryOrder order = query.getOrder();
151
                if (order != null) {
152
                    for (FeatureQueryOrderMember member : order.members()) {
153
                        String attrName = member.getAttributeName();
154
                        ExpressionBuilder.Variable col = expbuilder.column(attrName);
155
                        select.order_by().value(col).ascending(member.getAscending());
156
                    }
157
                }
209
            if (!StringUtils.isEmpty(baseFilter)) {
210
                select.where().and(expbuilder.toValue(baseFilter));
158 211
            }
159
            if( select.has_where() || select.has_order_by() ) {
160
                sqlbuilder.setProperties(
161
                        null,
162
                        PROP_FEATURE_TYPE, this.storeType,
163
                        PROP_TABLE, table,
164
                        PROP_SYMBOLTABLE, this.query==null? null:this.query.getSymbolTable(),
165
                        PROP_JDBCHELPER, this.helper,
166
                        PROP_QUERY, this.query
167
                );
168
                for (ExpressionBuilder.Value value : valuesToRemoveFeatureType) {
169
                    value.setProperty(PROP_FEATURE_TYPE, null);
212
        }
213
        if( StringUtils.containsAny(sql, "${order_by_orderspec}", "${comma_orderspec}") ) {
214
            FeatureQueryOrder order = query.getOrder();
215
            if (order != null) {
216
                for (FeatureQueryOrderMember member : order.members()) {
217
                    String attrName = member.getAttributeName();
218
                    ExpressionBuilder.Variable col = expbuilder.column(attrName);
219
                    select.order_by().value(col).ascending(member.getAscending());
170 220
                }
171
                if( select.has_where()) {
172
                    String s = select.where().toString();
173
                    sql = StringUtils.replace(sql, "${where_filter}", "WHERE " + s);
174
                    sql = StringUtils.replace(sql, "${and_filter}", "AND (" + s + ")");
175
                }
176
                if( select.has_order_by() ) {
177
                    String s = select.order_by().toString();
178
                    sql = StringUtils.replace(sql, "${order_by_orderspec}", "ORDER BY " + s);
179
                    sql = StringUtils.replace(sql, "${comma_orderspec}", ", "+ s);
180
                }
181 221
            }
182
            for (FeatureAttributeDescriptor attr : storeType) {
183
                columns.add(attr);
222
        }
223
        if( select.has_where() || select.has_order_by() ) {
224
            sqlbuilder.setProperties(
225
                    null,
226
                    PROP_FEATURE_TYPE, this.storeType,
227
                    PROP_TABLE, table,
228
                    PROP_SYMBOLTABLE, this.query==null? null:this.query.getSymbolTable(),
229
                    PROP_JDBCHELPER, this.helper,
230
                    PROP_QUERY, this.query
231
            );
232
            for (ExpressionBuilder.Value value : valuesToRemoveFeatureType) {
233
                value.setProperty(PROP_FEATURE_TYPE, null);
184 234
            }
185
            return sql;
235
            if( select.has_where()) {
236
                String s = select.where().toString();
237
                sql = StringUtils.replace(sql, "${where_filter}", "WHERE " + s);
238
                sql = StringUtils.replace(sql, "${and_filter}", "AND (" + s + ")");
239
            }
240
            if( select.has_order_by() ) {
241
                String s = select.order_by().toString();
242
                sql = StringUtils.replace(sql, "${order_by_orderspec}", "ORDER BY " + s);
243
                sql = StringUtils.replace(sql, "${comma_orderspec}", ", "+ s);
244
            }
186 245
        }
187
        
188

  
189
        Map<String, EditableFeatureAttributeDescriptor> allExtraColumns = new HashMap<>();
190
        for (EditableFeatureAttributeDescriptor column : this.setType.getExtraColumns().getColumns()) {
191
            allExtraColumns.put(column.getName(), column);
246
        for (FeatureAttributeDescriptor attr : storeType) {
247
            columns.add(attr);
192 248
        }
193
        if(query != null){
194
            for (EditableFeatureAttributeDescriptor column : this.query.getExtraColumn().getColumns()) {
195
                allExtraColumns.put(column.getName(), column);
196
            }
249
        return sql;
250
    }
251
    
252
    public static void process1_SimpleFields(
253
            JDBCHelper helper, 
254
            FeatureType setType, 
255
            FeatureQuery query, 
256
            SQLBuilder sqlbuilder, 
257
            SelectBuilder select, 
258
            List<FeatureAttributeDescriptor> columns,
259
            List<String> primaryKeys,
260
            List<String> extraColumnNames
261
        ){
262
        if(!select.from().table().has_name()){
263
            throw new IllegalStateException("Need table in FROM.");
197 264
        }
198

  
199
        List<String> primaryKeys = new ArrayList<>();
200
        for (FeatureAttributeDescriptor attr : storeType.getPrimaryKey()) {
201
            primaryKeys.add(attr.getName());
202
        }
265
        
266
        GeometryExpressionBuilder expbuilder = sqlbuilder.expression();
267
        
203 268
        List<String> forcedColumns = new ArrayList<>(primaryKeys);
204 269

  
205 270
        String[] constantsAttributeNames = null;
206 271
        if (query != null && query.hasConstantsAttributeNames()) {
207 272
            constantsAttributeNames = query.getConstantsAttributeNames();
208 273
        }
274
        
209 275
        for (FeatureAttributeDescriptor attr : setType) {
210 276
            if (attr.isComputed()) {
211 277
                // Campos calculados se a?aden despues para asegurarnos que
......
218 284
            if (attr.isPrimaryKey()) {
219 285
                forcedColumns.remove(attr.getName());
220 286
            }
221
            if (query != null && (query.hasGroupByColumns() || query.hasAggregateFunctions()) )  {
222
                String aggregate = query.getAggregate(this.table.getTable(), attr.getName());                
223
                if (aggregate == null) {
224
                    if (this.query.isAGroupByColumn(attr.getName()) ) {
225
                        select.column().name(attr.getName());
226
                    } else if (aggregate == null) {
227
                        select.column().value(expbuilder.constant(null)).as(attr.getName());
228
                    }                    
229
                } else {
230
                    select.column()
231
                            .value(ExpressionUtils.compile(aggregate).toValue(expbuilder))
232
                            .as(attr.getName());
233
                }
234
            } else {
287
//            if (query != null)  {
288
//                if(query.hasGroupByColumns() || query.hasAggregateFunctions()){
289
//                    if (query.isAGroupByColumn(attr.getName()) ) {
290
//                        select.column().name(attr.getName());
291
//                    } else {
292
//                        select.column().value(expbuilder.constant(null)).as(attr.getName());
293
//                    }                    
294
//                } else {
295
//                    if (attr.getType() == DataTypes.GEOMETRY) {
296
//                        select.column().name(attr.getName()).as_geometry();
297
//                    } else {
298
//                        select.column().name(attr.getName());
299
//                    }
300
//                }
301
//            } else {
235 302
                if (attr.getType() == DataTypes.GEOMETRY) {
236 303
                    select.column().name(attr.getName()).as_geometry();
237
                    //                if( tolerance<=0 || !sqlbuilder.getConfig().has_functionality(Config.ST_Simplify)) {
238
                    //                    select.column().name(attr.getName()).as_geometry();
239
                    //                } else {
240
                    //                    select.column().value(
241
                    //                        sqlbuilder.ST_Simplify( 
242
                    //                            sqlbuilder.column(attr.getName()),
243
                    //                            sqlbuilder.constant(tolerance)
244
                    //                        )
245
                    //                    ).as_geometry();
246
                    //                }
247 304
                } else {
248 305
                    select.column().name(attr.getName());
249 306
                }
250
            }
307
//            }
251 308
            columns.add(attr);
252 309
        }
253

  
310
        
254 311
        if (query == null || !query.hasGroupByColumns()) {
255 312
            for (String attrName : forcedColumns) {
256 313
                select.column().name(attrName);
......
263 320
                }
264 321
            }
265 322
        }
266
        
267
        // Despues de a?adir los campos reales, se a?aden los campos calculados
323
    }
324

  
325
    public static void process2_ComputedFields(JDBCHelper helper, FeatureType setType, FeatureQuery query, SQLBuilder sqlbuilder, SelectBuilder select, List<String> extraColumnNames){
326
        //No procesamos los campos calculados que tengan un agregado, 
327
        //ya se encargar? de ello el m?todo processAggregatesAndGroupBys
328
        if(!select.from().table().has_name()){
329
            throw new IllegalStateException("Need table in FROM.");
330
        }
331
//        En las columnas del select, si hay funciones de agregado en el select o un GROUP BY
332
//        los campos calculados que no lleven funci?n de agregado no deben incluir el nombre de tabla
333

  
334
        GeometryExpressionBuilder expbuilder = sqlbuilder.expression();
268 335
        for (FeatureAttributeDescriptor attr : setType) {
269 336
            if (attr.isComputed()) {
270 337
                if (attr.getRelationType() == DynField.RELATION_TYPE_NONE) {
......
272 339
                    if (attrEmulator instanceof FeatureAttributeEmulatorExpression) {
273 340
                        FeatureAttributeEmulatorExpression x = (FeatureAttributeEmulatorExpression) attrEmulator;
274 341
                        Expression exp = x.getExpression();
275

  
276
                        if (query != null && (query.hasGroupByColumns() || query.hasAggregateFunctions())) {
277
                            String aggregate = query.getAggregate(this.table.getTable(), attr.getName());
278
                            if (this.query.isAGroupByColumn(attr.getName())) {
279
                                if (!select.has_column(attr.getName())) {
280
                                    select.column().value(exp.getCode().toValue()).as(attr.getName());
281
                                }
342
                        
343
//                        if(query == null || !query.isAggregate(attr.getName())){
344
                            if (exp != null && !exp.isEmpty() && helper.supportExpression(setType, exp.getPhrase())) {
345
                                Code code = exp.getCode();
346
                                ExpressionBuilder.Value value = code.toValue(expbuilder);
347
                                select.column()
348
                                        .name(attr.getName())
349
                                        .value(value)
350
                                        .as(attr.getName());
282 351
                                if (extraColumnNames != null && !extraColumnNames.contains(attr.getName())) {
283 352
                                    extraColumnNames.add(attr.getName());
284 353
                                }
285
                            } else if (aggregate == null) {
286
                                select.column().value(expbuilder.constant(null)).as(attr.getName());
287
                                
288
                                if (extraColumnNames != null && !extraColumnNames.contains(attr.getName())) {
289
                                    extraColumnNames.add(attr.getName());
354
                                if(query != null && (query.hasGroupByColumns() || query.hasAggregateFunctions())){
355
                                    sqlbuilder.setProperties(value, null, DONT_ADD_TABLE_NAME_TO_COLUMNS, true);
290 356
                                }
291
                            } else {
292
                                String fn = this.query.getAggregateFunctions().get(attr.getName());
293
                                ExpressionBuilder.Function aggregateExp = expbuilder.function(fn, exp.getCode().toValue());
294
                                if (!select.has_column(attr.getName())) {
295
                                    select.column().value(aggregateExp).as(attr.getName());
296
                                }
297
                                if (extraColumnNames != null && !extraColumnNames.contains(attr.getName())) {
298
                                    extraColumnNames.add(attr.getName());
299
                                }
300 357
                            }
301
                        } else {
302
                            if (exp != null && !exp.isEmpty() && this.helper.supportExpression(setType, exp.getPhrase())) {
358
//                        }
359
                    }
360
                }
361
            }
362
        }
363
        
364
        if (query != null) {
365
            FeatureExtraColumns extraColumns = query.getExtraColumn();
366
            if (extraColumns != null && !extraColumns.isEmpty()) {
367
                for (EditableFeatureAttributeDescriptor attr : extraColumns.getColumns()) {
368
                    if (!attr.isComputed()) {
369
                        continue;
370
                    }
371
                    FeatureAttributeEmulator attrEmulator = attr.getFeatureAttributeEmulator();
372
                    if (attrEmulator instanceof FeatureAttributeEmulatorExpression) {
373
                        FeatureAttributeEmulatorExpression x = (FeatureAttributeEmulatorExpression) attrEmulator;
374
                        Expression exp = x.getExpression();
375
//                        if(!query.isAggregate(attr.getName())){
376
                            if (exp != null && !exp.isEmpty() && helper.supportExpression(setType, exp.getPhrase())) {
303 377
                                Code code = exp.getCode();
378
                                ExpressionBuilder.Value value = code.toValue(expbuilder);
304 379
                                select.column()
305
                                        .value(code.toValue(expbuilder))
380
                                        .name(attr.getName())
381
                                        .value(value)
306 382
                                        .as(attr.getName());
307
                                if (extraColumnNames != null && !extraColumnNames.contains(attr.getName())) {
383
                                if (extraColumnNames!=null && !extraColumnNames.contains(attr.getName())) {
308 384
                                    extraColumnNames.add(attr.getName());
309 385
                                }
386
                                if(query.hasGroupByColumns() || query.hasAggregateFunctions()){
387
                                    sqlbuilder.setProperties(value, null, DONT_ADD_TABLE_NAME_TO_COLUMNS, true);
388
                                }
310 389
                            }
311

  
312
                        }
390
//                        }
313 391
                    }
314 392
                }
315 393
            }
316 394
        }
317 395
        
318
        if (query != null && (query.hasAggregateFunctions() ||  query.hasGroupByColumns())) { 
319
            // Hay que tener en cuenta que puede haber un MAX(CAMPO) sin que se especifique un GROUP BY
320
            if (query.hasAggregateFunctions() ) {
321
                for (Map.Entry<String, String> entry : query.getAggregateFunctions().entrySet()) {
322
                    Expression exp;
323
                    FeatureAttributeDescriptor attr = allExtraColumns.get(entry.getKey());
324
                    if (attr == null) {
325
                        attr = this.setType.getAttributeDescriptorFromAll(entry.getKey());
326
                    }
327
                    if (attr == null) {
328
                            exp = ExpressionUtils.createExpression(entry.getKey());
329
                            Code code = exp.getCode();
330
                            if (!(code instanceof Code.Callable)) {
331
                                throw new RuntimeException("Not able to use aggregate function with this expression(1): " + entry.getKey());
332
                            }
333
                            Code.Callable callable = (Code.Callable) code;
334
                            if (!callable.name().equalsIgnoreCase(FUNCTION_LET)) {
335
                                throw new RuntimeException("Not able to use aggregate function with this expression(2): " + entry.getKey());
336
                            }
337
                            String name = ((Code.Identifier) callable.parameters().get(0)).name();
338
                            ExpressionBuilder.Value aggregate = callable.parameters().get(1).toValue();
396
    }
339 397

  
340
                            ExpressionBuilder.Function aggregateExp = expbuilder.function(entry.getValue(), aggregate);
398
    public static Map<String, EditableFeatureAttributeDescriptor> getAllExtraColumns(FeatureType setType, FeatureQuery query) {
399
        Map<String, EditableFeatureAttributeDescriptor> allExtraColumns = new HashMap<>();
400
        for (EditableFeatureAttributeDescriptor column : setType.getExtraColumns().getColumns()) {
401
            allExtraColumns.put(column.getName(), column);
402
        }
403
        if(query != null){
404
            for (EditableFeatureAttributeDescriptor column : query.getExtraColumn().getColumns()) {
405
                allExtraColumns.put(column.getName(), column);
406
            }
407
        }
408
        return allExtraColumns;
409
    }
341 410

  
342
                            select.remove_column(name);
343
                            select.column().value(aggregateExp).as(name);
344
                    } else if( attr.getFeatureAttributeEmulator()!=null ) {
345
                        exp = ((FeatureAttributeEmulatorExpression) attr.getFeatureAttributeEmulator()).getExpression();
346
                        ExpressionBuilder.Function aggregateExp = expbuilder.function(entry.getValue(), exp.getCode().toValue());
347
                        if (!select.has_column(attr.getName())) {
348
                            select.column().value(aggregateExp).as(attr.getName());
349
                        }
350
                        if (extraColumnNames != null && !extraColumnNames.contains(attr.getName())) {
351
                            extraColumnNames.add(attr.getName());
352
                        }
353
                    }
411
    public static void process4_Aggregates(TableReference table, FeatureType setType, FeatureQuery query, Map<String, EditableFeatureAttributeDescriptor> allExtraColumns, SQLBuilder sqlbuilder, SelectBuilder select, List<String> extraColumnNames) throws RuntimeException {
412
        if(query == null){
413
            return;
414
        }
415
        if(!select.from().table().has_name()){
416
            throw new IllegalStateException("Need table in FROM.");
417
        }
418
        GeometryExpressionBuilder expbuilder = sqlbuilder.expression();
419
        // Hay que tener en cuenta que puede haber un MAX(CAMPO) sin que se especifique un GROUP BY
420
        if (query.hasAggregateFunctions() ) {
421
            for (FeatureAttributeDescriptor attr : setType) {
422
                if (query.isAggregate(attr.getName()) ) {
423
                    continue;
354 424
                }
425
//                if (!query.isAGroupByColumn(attr.getName()) && select.has_column(attr.getName()) ) {
426
                if (select.has_column(attr.getName()) ) {
427
                    select.column(attr.getName()).value(expbuilder.constant(null)).as(attr.getName());
428
                }
355 429
            }
356
            if (query.hasGroupByColumns()) { // if tiene agrupacion
357
                for (String attrName : query.getGroupByColumns()) {
358
                    if (allExtraColumns.get(attrName) != null) { //from setType and query
359
                        EditableFeatureAttributeDescriptor attr = allExtraColumns.get(attrName);
360
                        ExpressionBuilder.Variable col = expbuilder.column(attrName);
361
                        select.group_by(col);
362
                        Expression exp = ((FeatureAttributeEmulatorExpression) attr.getFeatureAttributeEmulator()).getExpression();
363
                        if (!select.has_column(attrName)) {
364
                            select.column().value(exp.getCode().toValue()).as(attrName);
365
                        }
366
                        if (extraColumnNames!=null && !extraColumnNames.contains(attr.getName())) {
367
                            extraColumnNames.add(attrName);
368
                        }
369
                    } else if (setType.get(attrName) != null && setType.getAttributeDescriptor(attrName).isComputed()) {
370
                        FeatureAttributeDescriptor attr = setType.getAttributeDescriptor(attrName);
371
                        ExpressionBuilder.Variable col = expbuilder.column(attrName);
372
                        select.group_by(col);
373
                        Expression exp = ((FeatureAttributeEmulatorExpression) attr.getFeatureAttributeEmulator()).getExpression();
374
                        if (!select.has_column(attrName)) {
375
                            select.column().value(exp.getCode().toValue()).as(attrName);
376
                        }
377
                        if (extraColumnNames!=null && !extraColumnNames.contains(attr.getName())) {
378
                            extraColumnNames.add(attrName);
379
                        }
380
                    } else if (setType.get(attrName) == null) {
381
                        try {
382
                            Code code = ExpressionUtils.compile(attrName);
383
                            select.group_by(code.toValue());
384
                        } catch (Exception ex) {
385
                            throw new RuntimeException("Not able to create column by expression in groupby query", ex);
386
                        }
430
            for (FeatureAttributeDescriptor attr : query.getExtraColumns()) {
431
                if (query.isAggregate(attr.getName()) ) {
432
                    continue;
433
                }
434
//                if (!query.isAGroupByColumn(attr.getName()) && select.has_column(attr.getName()) ) {
435
                if (select.has_column(attr.getName()) ) {
436
                    select.column(attr.getName()).value(expbuilder.constant(null)).as(attr.getName());
437
                }
438
            }
439

  
440
            
441
            for (Map.Entry<String, String> entry : query.getAggregateFunctions().entrySet()) {
442
                Expression exp;
443
                FeatureAttributeDescriptor attr = allExtraColumns.get(entry.getKey());
444
                if (attr == null) {
445
                    attr = setType.getAttributeDescriptorFromAll(entry.getKey());
446
                }
447
                if (attr == null) {
448
                    //Aggregate_expression AS name -> name:=aggregate_expression
449
                    exp = ExpressionUtils.createExpression(entry.getKey());
450
                    Code code = exp.getCode();
451
                    if (!(code instanceof Code.Callable)) {
452
                        throw new RuntimeException("Not able to use aggregate function with this expression(1): " + entry.getKey());
453
                    }
454
                    Code.Callable callable = (Code.Callable) code;
455
                    if (!callable.name().equalsIgnoreCase(FUNCTION_LET)) {
456
                        throw new RuntimeException("Not able to use aggregate function with this expression(2): " + entry.getKey());
457
                    }
458
                    String name = ((Code.Identifier) callable.parameters().get(0)).name();
459
                    ExpressionBuilder.Value aggregate = callable.parameters().get(1).toValue();
460
                    
461
                    ExpressionBuilder.Function aggregateExp = expbuilder.function(entry.getValue(), aggregate);
462
                    
463
                    select.column(name).value(aggregateExp).as(name);
464
                } else {
465
                    SQLBuilder.SelectColumnBuilder column = select.column(attr.getName());
466
                    if(column.getValue() != null){
467
                        ExpressionBuilder.Function aggregateExp = expbuilder.function(entry.getValue(), column.getValue());
468
                        sqlbuilder.setProperties(aggregateExp, null, DONT_ADD_TABLE_NAME_TO_COLUMNS, false);
469
                        column.value(aggregateExp).as(column.getName());
387 470
                    } else {
388
                        ExpressionBuilder.Function atrcolumn = expbuilder.getattr(this.table.getTable(), attrName);
389
                        select.group_by(atrcolumn);
471
                        ExpressionBuilder.Function aggregateExp = expbuilder.function(
472
                                entry.getValue(), 
473
                                sqlbuilder.column(select.from().table(), column.getName()) 
474
                        );
475
                        column.value(aggregateExp).as(column.getName());
390 476
                    }
391 477
                }
392 478
            }
393
        } else {
394
            if (this.query != null) {
395
                FeatureExtraColumns extraColumns = this.query.getExtraColumn();
396
                if (extraColumns != null && !extraColumns.isEmpty()) {
397
                    for (EditableFeatureAttributeDescriptor attr : extraColumns.getColumns()) {
398
                        if (!attr.isComputed()) {
399
                            continue;
400
                        }
401
                        FeatureAttributeEmulator attrEmulator = attr.getFeatureAttributeEmulator();
402
                        if (attrEmulator instanceof FeatureAttributeEmulatorExpression) {
403
                            FeatureAttributeEmulatorExpression x = (FeatureAttributeEmulatorExpression) attrEmulator;
404
                            Expression exp = x.getExpression();
405
                            if (exp != null && !exp.isEmpty() && this.helper.supportExpression(setType, exp.getPhrase())) {
406
                                Code code = exp.getCode();
407
                                select.column()
408
                                        .value(code.toValue(expbuilder))
409
                                        .as(attr.getName());
410
                                if (extraColumnNames!=null && !extraColumnNames.contains(attr.getName())) {
411
                                    extraColumnNames.add(attr.getName());
412
                                }
413
                            }
414
                        }
479
        }
480
    }
481
    
482
    public static void process5_GroupBys(TableReference table, FeatureType setType, FeatureQuery query, Map<String, EditableFeatureAttributeDescriptor> allExtraColumns, SQLBuilder sqlbuilder, SelectBuilder select, List<String> extraColumnNames) throws RuntimeException {
483
        if(query == null){
484
            return;
485
        }
486
        if(!select.from().table().has_name()){
487
            throw new IllegalStateException("Need table in FROM.");
488
        }
489
        if (query.hasGroupByColumns()) { // if tiene agrupacion
490
            GeometryExpressionBuilder expbuilder = sqlbuilder.expression();
491
            for (FeatureAttributeDescriptor attr : setType) {
492
                if (query.isAggregate(attr.getName()) ) {
493
                    continue;
494
                }
495
                if (!query.isAGroupByColumn(attr.getName()) && select.has_column(attr.getName()) ) {
496
                    select.column(attr.getName()).value(expbuilder.constant(null)).as(attr.getName());
497
                }
498
            }
499
            for (FeatureAttributeDescriptor attr : query.getExtraColumns()) {
500
                if (query.isAggregate(attr.getName()) ) {
501
                    continue;
502
                }
503
                if (!query.isAGroupByColumn(attr.getName()) && select.has_column(attr.getName()) ) {
504
                    select.column(attr.getName()).value(expbuilder.constant(null)).as(attr.getName());
505
                }
506
            }
507

  
508
            for (String attrName : query.getGroupByColumns()) {
509
                if (allExtraColumns.get(attrName) == null && setType.get(attrName) == null) {
510
                    try {
511
                        Code code = ExpressionUtils.compile(attrName);
512
                        select.group_by(code.toValue());
513
                    } catch (Exception ex) {
514
                        throw new RuntimeException("Not able to create column by expression in groupby query", ex);
415 515
                    }
516
                } else {
517
                    ExpressionBuilder.Variable col = sqlbuilder.column(select.from().table(),attrName);
518
                    select.group_by(col);
416 519
                }
417 520
            }
418 521
        }
419

  
420
        select.from().table()
421
                .database(this.table.getDatabase())
422
                .schema(this.table.getSchema())
423
                .name(this.table.getTable());
424
        select.from().subquery(this.table.getSubquery());
425

  
426
        Evaluator filter = query == null ? null : query.getFilter();
522
    }
523
    
524
    public static void process3_Where(
525
            JDBCHelper helper, 
526
            FeatureType storeType, 
527
            FeatureQuery query, 
528
            SQLBuilder sqlbuilder,
529
            SelectBuilder select
530
        ) {
531
        if(query == null){
532
            return;
533
        }
534
        if(!select.from().table().has_name()){
535
            throw new IllegalStateException("Need table in FROM.");
536
        }
537
        GeometryExpressionBuilder expbuilder = sqlbuilder.expression();
538
        
539
        Evaluator filter = query.getFilter();
427 540
        if (filter != null) {
428 541
            String sqlfilter = filter.getSQL();
429 542
            if (!StringUtils.isEmpty(sqlfilter)) {
430
                if (this.helper.supportFilter(this.storeType, filter)) {
543
                if (helper.supportFilter(storeType, filter)) {
431 544
                    select.where().set(expbuilder.toValue(sqlfilter));
432 545
                }
433 546
            }
434 547
        }
435
        if (!StringUtils.isEmpty(baseFilter)) {
436
            select.where().and(expbuilder.toValue(baseFilter));
548
    }
549
    
550
    public static void process6_OrderBy(
551
            FeatureType storeType, 
552
            FeatureType setType, 
553
            FeatureQuery query, 
554
            Map<String, EditableFeatureAttributeDescriptor> allExtraColumns, 
555
            SQLBuilder sqlbuilder,
556
            SelectBuilder select, 
557
            List<String> primaryKeys,
558
            List<String> extraColumnNames,
559
            List<ExpressionBuilder.Value> valuesToRemoveFeatureType
560
        ) {
561
        if(!select.from().table().has_name()){
562
            throw new IllegalStateException("Need table in FROM.");
437 563
        }
564
        GeometryExpressionBuilder expbuilder = sqlbuilder.expression();
438 565

  
439
        FeatureQueryOrder order = query == null ? null : query.getOrder();
440
        if (order != null) {
441
            for (FeatureQueryOrderMember member : order.members()) {
442
                String attrName = member.getAttributeName();
443
                if (member.hasEvaluator()) {
444
                    // Order-by una expression en el query
445
                    String sqlorder = member.getEvaluator().getSQL();
446
                    select.order_by()
447
                            .value(expbuilder.toValue(sqlorder))
448
                            .ascending(member.getAscending());
449
                } else {
450
                    int nullsMode = OrderByBuilder.MODE_NULLS_LAST;
451
                    if (allExtraColumns.get(attrName) != null) {
452
                        // Order-by por una columna extra
453
                        Expression exp = ((FeatureAttributeEmulatorExpression) allExtraColumns.get(attrName).getFeatureAttributeEmulator()).getExpression();
454
                        if (!select.has_column(attrName)) {
455
                            select.column().value(exp.getCode().toValue()).as(attrName);
566
        
567
        if (query != null) {
568
            FeatureQueryOrder order = query.getOrder();
569
            if (order != null) {
570
                for (FeatureQueryOrderMember member : order.members()) {
571
                    String attrName = member.getAttributeName();
572
                    FeatureAttributeDescriptor attr = setType.getAttributeDescriptorFromAll(attrName);
573
                    if(attr == null){
574
                        attr = allExtraColumns.get(attrName);
575
                    }
576
                    if (member.hasEvaluator()) {
577
                        // Order-by una expression en el query
578
                        String sqlorder = member.getEvaluator().getSQL();
579
                        select.order_by()
580
                                .value(expbuilder.toValue(sqlorder))
581
                                .ascending(member.getAscending());
582
                    } else {
583
                        int nullsMode = OrderByBuilder.MODE_NULLS_LAST;
584
                        Column col = null;
585
                        if (attr != null && attr.isComputed()) {
586
                            // Order-by por una columna extra o por un campo calculado del set/store
587
                            Expression exp = ((FeatureAttributeEmulatorExpression) attr.getFeatureAttributeEmulator()).getExpression();
588
                            if (!select.has_column(attrName)) {
589
                                select.column().value(exp.getCode().toValue()).as(attrName);
590
                            }
591
                            if (extraColumnNames != null && !extraColumnNames.contains(attrName)) {
592
                                extraColumnNames.add(attrName);
593
                            }
594
                            col = sqlbuilder.column(attrName);
595
                        } else {
596
                            if (attr != null && (!attr.allowNull() || attr.isPrimaryKey())) {
597
                                // Puede ser costoso ordenar los nulos al principio o final, asi que
598
                                // si el campo no admite nulos pasamos de indicarselo.
599
                                nullsMode = OrderByBuilder.MODE_NULLS_NOT_SPECIFIED;
600
                            }
601
                            col = sqlbuilder.column(select.from().table(), attrName);
456 602
                        }
457
                        if (extraColumnNames!=null && !extraColumnNames.contains(attrName)) {
458
                            extraColumnNames.add(attrName);
603
                        
604
                        if(select.has_group_by() || select.has_aggregate_functions()){
605
                            col.table(null);
606
                            sqlbuilder.setProperties(col, null, DONT_ADD_TABLE_NAME_TO_COLUMNS, true);
459 607
                        }
460
                    } else if (setType.get(attrName) != null && setType.getAttributeDescriptor(attrName).isComputed()) {
461
                        // Order-by por un campo calculado del set/store
462
                        Expression exp = ((FeatureAttributeEmulatorExpression) setType.getAttributeDescriptor(attrName).getFeatureAttributeEmulator()).getExpression();
463
                        if (!select.has_column(attrName)) {
464
                            select.column().value(exp.getCode().toValue()).as(attrName);
608
                        
609
                        boolean expand = false;
610
                        
611
                        if((attr != null && !query.isAggregate(attrName))){
612
                            if(select.has_aggregate_functions()){
613
                                expand = true;
614
                            } else {
615
                                expand = false;
616
                            }
617
                        } else {
618
                          expand = false;  
465 619
                        }
466
                        if (extraColumnNames!=null && !extraColumnNames.contains(attrName)) {
467
                            extraColumnNames.add(attrName);
620
                        
621
                        if(select.isGroupBy(col.name())) {
622
                            expand = false;
623
                        } 
624
                        
625
                        if(!expand){
626
                            // En el OrderBy no queremos que se sustituya el nombre del campo calculado
627
                            // por su expresion. Se encarga el formater y lo evitamos quitandole el ftype
628
                            // al value.
629
                            valuesToRemoveFeatureType.add(col);
468 630
                        }
469
                    } else {
470
                        // Order-by por un campo del store
471
                        FeatureAttributeDescriptor attr = storeType.getAttributeDescriptor(attrName);
472
                        if( attr!=null && (!attr.allowNull() || attr.isPrimaryKey()) ) {
473
                            // Puede ser costoso ordenar los nulos al principio o final, asi que
474
                            // si el campo no admite nulos pasamos de indicarselo.
475
                            nullsMode = OrderByBuilder.MODE_NULLS_NOT_SPECIFIED;
476
                        }
631
                        
632
                        
633
                        
634
                        
635
//                        if(!select.has_group_by() || select.isGroupBy(col.name()) || (attr != null && query.isAggregate(attrName))){ 
636
//                            // En el OrderBy no queremos que se sustituya el nombre del campo calculado
637
//                            // por su expresion. Se encarga el formater y lo evitamos quitandole el ftype
638
//                            // al value.
639
//                            valuesToRemoveFeatureType.add(col);
640
//                        }
641
                        select.order_by().value(col).ascending(member.getAscending()).nulls(nullsMode);
477 642
                    }
478
                    ExpressionBuilder.Variable col = expbuilder.column(attrName);
479
					
480
                    // En el OrderBy no queremos que se sustituya el nombre del campo calculado
481
                    // por su expresion. Se encarga el formater y lo evitamos quitandole el ftype
482
                    // al value.
483
                    valuesToRemoveFeatureType.add(col);
484
                    select.order_by().value(col).ascending(member.getAscending()).nulls(nullsMode);
485 643
                }
486 644
            }
487 645
        }
488

  
489
        if (!StringUtils.isEmpty(baseOrder)) {
490
            select.order_by().custom(baseOrder);
491
        }
492

  
493
        if (select.has_group_by()) { // && isPaginated()) {
494
            // Cuando paginamos debemos ordenar por las columnas del groupby.
495
            // Ordenamos siempre para obtener el mismo resultado cuando paginamos
496
            // y no paginamos.
497
            for (ExpressionBuilder.Value group : select.getGroups()) {
498
                if (select.getOrderBy(group) == null) {
499
                    ExpressionBuilder.Value v = (ExpressionBuilder.Value) CloneableUtils.cloneQuietly(group);
500
                    select.order_by().value(v).ascending().nulls(OrderByBuilder.MODE_NULLS_LAST);
501
                    valuesToRemoveFeatureType.add(v);
646
        if(!select.has_order_by()) {
647
            // Si no hay orden y hay grupos ordenaremos por estos
648
            if (select.has_group_by()) { // && isPaginated()) {
649
                // Cuando paginamos debemos ordenar por las columnas del groupby.
650
                // Ordenamos siempre para obtener el mismo resultado cuando paginamos
651
                // y no paginamos.
652
                for (ExpressionBuilder.Value group : select.getGroups()) {
653
                    if (select.getOrderBy(group) == null) {
654
                        ExpressionBuilder.Value v = (ExpressionBuilder.Value) CloneableUtils.cloneQuietly(group);
655
                        if (v instanceof Column) {
656
                            ((Column) v).table(null);
657
                        }
658
                        select.order_by().value(v).ascending().nulls(OrderByBuilder.MODE_NULLS_LAST);
659
                        valuesToRemoveFeatureType.add(v);
660
                    }
502 661
                }
503 662
            }
504 663
        }
505
        
664

  
506 665
        if (primaryKeys.isEmpty()) {
507 666
            // Muy probablemente si no tiene pk sea una vista, asi que 
508 667
            // pasaremos de ordenar y esperemos que la vista este ya ordenada.
509 668
            select.disable_check_order_and_offset();
510 669
        } else {
511
            if (query == null || !(query.hasAggregateFunctions() ||  query.hasGroupByColumns())) { 
670
            if (query == null || !(query.hasAggregateFunctions() || query.hasGroupByColumns())) {
512 671
                // Siempre ordenamos por la clave primaria
513
                Object x = query==null? null:query.getQueryParameter(QUERY_DONT_ADD_PRIMARY_KEY_IN_THE_ORDER);
514
                if( x==null || !DataTypeUtils.toBoolean(x) ) {
672
                Object x = query == null ? null : query.getQueryParameter(QUERY_DONT_ADD_PRIMARY_KEY_IN_THE_ORDER);
673
                if (x == null || !DataTypeUtils.toBoolean(x)) {
515 674
                    for (String attrName : primaryKeys) {
516 675
                        if (select.getOrderBy(attrName) == null) {
676
                            ExpressionBuilder.Variable col = sqlbuilder.column(select.from().table(),attrName);
517 677
                            select.order_by()
518
                                    .column(attrName)
678
                                    .value(col) //column(attrName)
519 679
                                    .ascending()
520 680
                                    .nulls(OrderByBuilder.MODE_NULLS_NOT_SPECIFIED)
521 681
                                    ;
......
531 691
            }
532 692
        }
533 693

  
534
        if (limit > 0) {
535
            select.limit(limit);
536
        } else {
537
            select.limit(query == null ? null : query.getLimit());
538
        }
539
        if (offset > 0) {
540
            select.offset(offset);
541
        }
542
        sqlbuilder.setProperties(
543
                null,
544
                PROP_FEATURE_TYPE, this.storeType,
545
                PROP_TABLE, table,
546
                PROP_SYMBOLTABLE, this.query==null? null:this.query.getSymbolTable(),
547
                PROP_JDBCHELPER, this.helper,
548
                PROP_QUERY, this.query
549
        );
550
        for (ExpressionBuilder.Value value : valuesToRemoveFeatureType) {
551
            value.setProperty(PROP_FEATURE_TYPE, null);
552
        }
553
	this.helper.expandCalculedColumns(sqlbuilder);
554
        this.helper.processSpecialFunctions(sqlbuilder, storeType, extraColumnNames);
555
        String sql = sqlbuilder.toString();
556
        return sql;
557 694
    }
558 695
    
559 696
    private boolean isPaginated() {

Also available in: Unified diff