Revision 46401

View differences:

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
35 35
import org.gvsig.expressionevaluator.ExpressionBuilder;
36 36
import static org.gvsig.expressionevaluator.ExpressionBuilder.FUNCTION_LET;
37 37
import org.gvsig.expressionevaluator.ExpressionUtils;
38
import org.gvsig.fmap.dal.SQLBuilder;
39
import org.gvsig.fmap.dal.SQLBuilder.OrderByBuilder;
38 40
import org.gvsig.fmap.dal.SQLBuilder.SelectBuilder;
39 41
import org.gvsig.fmap.dal.exception.DataException;
40 42
import org.gvsig.fmap.dal.expressionevaluator.FeatureAttributeEmulatorExpression;
......
437 439
            for (FeatureQueryOrderMember member : order.members()) {
438 440
                String attrName = member.getAttributeName();
439 441
                if (member.hasEvaluator()) {
442
                    // Order-by una expression en el query
440 443
                    String sqlorder = member.getEvaluator().getSQL();
441 444
                    select.order_by()
442 445
                            .value(expbuilder.toValue(sqlorder))
443 446
                            .ascending(member.getAscending());
444 447
                } else {
448
                    int nullsMode = OrderByBuilder.MODE_NULLS_LAST;
445 449
                    if (allExtraColumns.get(attrName) != null) {
450
                        // Order-by por una columna extra
446 451
                        Expression exp = ((FeatureAttributeEmulatorExpression) allExtraColumns.get(attrName).getFeatureAttributeEmulator()).getExpression();
447 452
                        if (!select.has_column(attrName)) {
448 453
                            select.column().value(exp.getCode().toValue()).as(attrName);
......
451 456
                            extraColumnNames.add(attrName);
452 457
                        }
453 458
                    } else if (setType.get(attrName) != null && setType.getAttributeDescriptor(attrName).isComputed()) {
459
                        // Order-by por un campo calculado del set/store
454 460
                        Expression exp = ((FeatureAttributeEmulatorExpression) setType.getAttributeDescriptor(attrName).getFeatureAttributeEmulator()).getExpression();
455 461
                        if (!select.has_column(attrName)) {
456 462
                            select.column().value(exp.getCode().toValue()).as(attrName);
......
458 464
                        if (extraColumnNames!=null && !extraColumnNames.contains(attrName)) {
459 465
                            extraColumnNames.add(attrName);
460 466
                        }
467
                    } else {
468
                        // Order-by por un campo del store
469
                        FeatureAttributeDescriptor attr = storeType.getAttributeDescriptor(attrName);
470
                        if( attr!=null && (!attr.allowNull() || attr.isPrimaryKey()) ) {
471
                            // Puede ser costoso ordenar los nulos al principio o final, asi que
472
                            // si el campo no admite nulos pasamos de indicarselo.
473
                            nullsMode = OrderByBuilder.MODE_NULLS_NOT_SPECIFIED;
474
                        }
461 475
                    }
462 476
                    ExpressionBuilder.Variable col = expbuilder.column(attrName);
463 477
					
464
                    // En el groupBy no queremos que se sustituya el nombre del campo calculado
478
                    // En el OrderBy no queremos que se sustituya el nombre del campo calculado
465 479
                    // por su expresion. Se encarga el formater y lo evitamos quitandole el ftype
466 480
                    // al value.
467 481
                    valuesToRemoveFeatureType.add(col);
468
                    select.order_by().value(col).ascending(member.getAscending());
469
//                    select.order_by()
470
//                            .column(member.getAttributeName())
471
//                            .ascending(member.getAscending());
482
                    select.order_by().value(col).ascending(member.getAscending()).nulls(nullsMode);
472 483
                }
473 484
            }
474 485
        }
......
484 495
            for (ExpressionBuilder.Value group : select.getGroups()) {
485 496
                if (select.getOrderBy(group) == null) {
486 497
                    ExpressionBuilder.Value v = (ExpressionBuilder.Value) CloneableUtils.cloneQuietly(group);
487
                    select.order_by().value(v).ascending();
498
                    select.order_by().value(v).ascending().nulls(OrderByBuilder.MODE_NULLS_LAST);
488 499
                    valuesToRemoveFeatureType.add(v);
489 500
                }
490 501
            }
......
500 511
            if( x==null || !DataTypeUtils.toBoolean(x) ) {
501 512
                for (String attrName : primaryKeys) {
502 513
                    if (select.getOrderBy(attrName) == null) {
503
                        select.order_by().column(attrName).ascending();
514
                        select.order_by()
515
                                .column(attrName)
516
                                .ascending()
517
                                .nulls(OrderByBuilder.MODE_NULLS_NOT_SPECIFIED)
518
                                ;
519
                        // No tengo claro que pasa si se esta agrupando, y no se ha
520
                        // incluido en el agrupamiento al PK. En ese caso el select
521
                        // que se genera tendria una pinta tal que asi:
522
                        //   SELECT NULL as pk, ... ORDER BY pk ASC
523
                        // Probablemente en ese caso no tendriamos que meter la PK
524
                        // en el order-by ya que creo que no cambiaria el resultado.
504 525
                    }
505 526
                }
506 527
            }
trunk/org.gvsig.desktop/org.gvsig.desktop.compat.cdc/org.gvsig.fmap.dal/org.gvsig.fmap.dal.api/src/main/java/org/gvsig/fmap/dal/SQLBuilder.java
191 191
    }
192 192

  
193 193
    public interface OrderByBuilder extends StatementPart {
194

  
194
        
195
        public static int MODE_NULLS_FIRST = 0;
196
        public static int MODE_NULLS_LAST = 1;
197
        public static int MODE_NULLS_NOT_SPECIFIED = 2;
198
        
195 199
        public OrderByBuilder column(String name);
196 200
        
197 201
        public boolean isColumn(String name);
......
208 212
        public OrderByBuilder ascending();
209 213

  
210 214
        public OrderByBuilder descending();
215
        
216
        public OrderByBuilder nulls(int mode);
211 217

  
212 218
        public OrderByBuilder custom(String order);
219
        
220
        public int getNullsMode();
213 221
    }
214 222

  
215 223
    public interface SelectBuilder extends Statement {
trunk/org.gvsig.desktop/org.gvsig.desktop.compat.cdc/org.gvsig.fmap.dal/org.gvsig.fmap.dal.spi/src/main/java/org/gvsig/fmap/dal/feature/spi/SQLBuilderBase.java
914 914
        protected Value value;
915 915
        protected String custom;
916 916
        protected boolean ascending;
917
        protected int nullsMode;
917 918

  
918 919
        public OrderByBuilderBase() {
919 920
            this.ascending = true;
921
            this.nullsMode = MODE_NULLS_LAST;
920 922
        }
921 923
        
922 924
        @Override
......
989 991
        }
990 992

  
991 993
        @Override
994
        public OrderByBuilder nulls(int mode) {
995
            this.nullsMode = mode;
996
            return this;
997
        }
998

  
999
        @Override
1000
        public int getNullsMode() {
1001
            return this.nullsMode;
1002
        }
1003

  
1004
        @Override
992 1005
        public String toString() {
993 1006
            return this.toString(formatter());
994 1007
        }
......
1001 1014
            if (!StringUtils.isEmpty(this.custom)) {
1002 1015
                return this.custom;
1003 1016
            }
1017
            String order_s = this.value.toString(formatter);
1004 1018
            if (this.ascending) {
1005
                return this.value.toString(formatter) + " ASC NULLS LAST";
1019
                order_s += " ASC";
1020
            } else {
1021
                order_s += " DESC";
1006 1022
            }
1007
            return this.value.toString(formatter) + " DESC NULLS FIRST";
1023
            switch(this.nullsMode) {
1024
                case MODE_NULLS_NOT_SPECIFIED:
1025
                    break;
1026
                case MODE_NULLS_FIRST:
1027
                    order_s += " NULLS FIRST";
1028
                    break;
1029
                case MODE_NULLS_LAST:
1030
                default:
1031
                    order_s += " NULLS LAST";
1032
                    break;
1033
            }
1034
            return order_s;
1008 1035
        }
1009 1036
    }
1010 1037

  

Also available in: Unified diff