Revision 44403

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/JDBCHelperBase.java
83 83

  
84 84
    private JDBCConnectionParameters connectionParameters;
85 85

  
86
    private JDBCStoreProvider store;    
87
    
86
    private JDBCStoreProvider store;
87

  
88 88
    protected OperationsFactory operationsFactory = null;
89
    
89

  
90 90
    protected SRSSolver srssolver;
91
    
91

  
92 92
    public JDBCHelperBase(JDBCConnectionParameters connectionParameters) {
93 93
        this.connectionParameters = connectionParameters;
94
        
94

  
95 95
        // If a particular treatment is required to convert SRS to the 
96 96
        // BBDD format, overwrite JDBCSRSsBase and use it instead of JDBCSRSsDumb.
97 97
        this.srssolver = new SRSSolverDumb(this);
......
101 101
            ResourceConsumer helperClient,
102 102
            JDBCConnectionParameters connectionParameters,
103 103
            JDBCStoreProvider store
104
        ) {
104
    ) {
105 105
        this.store = store;
106 106
        this.helperClient = helperClient;
107 107
        this.connectionParameters = connectionParameters;
108
        initializeResource(connectionParameters);        
108
        initializeResource(connectionParameters);
109 109
    }
110
    
110

  
111 111
    protected String getResourceType() {
112 112
        return JDBCResource.NAME;
113 113
    }
......
116 116
    public String getProviderName() {
117 117
        return JDBCLibrary.NAME;
118 118
    }
119
        
119

  
120 120
    @Override
121 121
    public GeometrySupportType getGeometrySupportType() {
122 122
        // El proveedor generico de JDBC guadara las geoemtrias como WKT
......
134 134
    public boolean allowNestedOperations() {
135 135
        return false;
136 136
    }
137
    
137

  
138 138
    @Override
139 139
    public boolean canWriteGeometry(int geometryType, int geometrySubtype) {
140 140
        // Como va a guardar las geometrias en WKT, puede escribirlas todas.
......
161 161
        // Asumimos que la BBDD soporta OFFSET
162 162
        return true;
163 163
    }
164
    
164

  
165 165
    @Override
166 166
    public String getQuoteForStrings() {
167 167
        return QUOTE_FOR_USE_IN_STRINGS;
168 168
    }
169 169

  
170 170
    protected boolean supportCaller(Code.Caller caller) {
171
        if( StringUtils.equalsIgnoreCase(caller.name(), "FOREING_VALUE") ) {
171
        if (StringUtils.equalsIgnoreCase(caller.name(), "FOREING_VALUE")) {
172 172
            return true;
173 173
        }
174 174
        Function function = caller.function();
175
        if( function==null ) {
175
        if (function == null) {
176 176
            return false;
177 177
        }
178
        if( !function.isSQLCompatible() ) {
178
        if (!function.isSQLCompatible()) {
179 179
            return false;
180 180
        }
181
        if( !this.hasSpatialFunctions() ) {
182
            if( StringUtils.equalsIgnoreCase(function.group(),Function.GROUP_OGC) ) {
181
        if (!this.hasSpatialFunctions()) {
182
            if (StringUtils.equalsIgnoreCase(function.group(), Function.GROUP_OGC)) {
183 183
                return false;
184 184
            }
185 185
        }
186 186
        return true;
187 187
    }
188
    
188

  
189 189
    @Override
190 190
    public boolean supportFilter(final FeatureType type, Evaluator filter) {
191 191
        // No podemos filtrar cuando:
......
198 198
        // Un proveedor especifico podria sobreescribir el metodo,
199 199
        // para hilar mas fino al comprobar si soporta el filtro o no.
200 200
        //
201
        
201

  
202 202
        if (this.useSubquery()) {
203 203
            // Se esta usando una subquery en los parametros de acceso a la
204 204
            // BBDD, asi que no podemos filtrar.
......
229 229
                @Override
230 230
                public void visit(Object code_obj) throws VisitCanceledException, BaseException {
231 231
                    Code code = (Code) code_obj;
232
                    switch(code.code()) {
232
                    switch (code.code()) {
233 233
                        case Code.CALLER:
234 234
                            Code.Caller caller = (Code.Caller) code;
235
                            if( !supportCaller(caller) ) {
235
                            if (!supportCaller(caller)) {
236 236
                                isCompatible.setValue(false);
237 237
                                throw new VisitCanceledException();
238 238
                            }
239 239
                            break;
240
                            
240

  
241 241
                        case Code.IDENTIFIER:
242 242
                            Code.Identifier identifier = (Code.Identifier) code;
243
                            if( type!=null ) {
243
                            if (type != null) {
244 244
                                FeatureAttributeDescriptor attrdesc = type.getAttributeDescriptor(identifier.name());
245
                                if( attrdesc!=null ) {
246
                                    if( attrdesc.isComputed() ) {
245
                                if (attrdesc != null) {
246
                                    if (attrdesc.isComputed()) {
247 247
                                        isCompatible.setValue(false);
248 248
                                        throw new VisitCanceledException();
249 249
                                    }
......
259 259
        } catch (Exception ex) {
260 260
            LOGGER.warn("Can't calculate if is SQL compatible.", ex);
261 261
        }
262
        
262

  
263 263
        return isCompatible.booleanValue();
264 264
    }
265
    
265

  
266 266
    @Override
267 267
    public boolean supportOrder(FeatureType type, FeatureQueryOrder order) {
268 268
        if (this.useSubquery()) {
......
271 271
        if (order == null) {
272 272
            return true;
273 273
        }
274
        for( FeatureQueryOrder.FeatureQueryOrderMember member : order.members() ) {
274
        for (FeatureQueryOrder.FeatureQueryOrderMember member : order.members()) {
275 275
            if (member.hasEvaluator()) {
276
                if( !this.supportFilter(type, member.getEvaluator()) ) {
276
                if (!this.supportFilter(type, member.getEvaluator())) {
277 277
                    return false;
278 278
                }
279
            }            
279
            }
280 280
        }
281 281
        return true;
282 282
    }
283
    
283

  
284 284
    @Override
285 285
    public OperationsFactory getOperations() {
286
        if (this.operationsFactory== null) {
286
        if (this.operationsFactory == null) {
287 287
            this.operationsFactory = new OperationsFactoryBase(this);
288 288
        }
289 289
        return operationsFactory;
290 290
    }
291
    
291

  
292 292
    protected void initializeResource(JDBCConnectionParameters params) {
293 293
//        Object[] resourceParams = new Object[]{
294 294
//            params.getUrl(),
......
320 320
    public String getSourceId() {
321 321
        return this.store.getSourceId();
322 322
    }
323
    
323

  
324 324
    @Override
325 325
    public JDBCResource getResource() {
326 326
        return null;
......
349 349

  
350 350
    @Override
351 351
    public void closeConnection(Connection connection) {
352
        if( connection != null ) {
353
            LOGGER.debug("Clossing connection "+connection.hashCode());
352
        if (connection != null) {
353
            LOGGER.debug("Clossing connection " + connection.hashCode());
354 354
            try {
355 355
                connection.close();
356
            } catch(Exception ex) {
356
            } catch (Exception ex) {
357 357
                LOGGER.warn("Can't close connection.", ex);
358 358
            }
359
       }
359
        }
360 360
    }
361 361

  
362 362
    @Override
363 363
    public void closeConnectionQuietly(Connection connection) {
364
        if( connection != null ) {
365
            LOGGER.debug("Clossing connection quietly "+connection.hashCode());
364
        if (connection != null) {
365
            LOGGER.debug("Clossing connection quietly " + connection.hashCode());
366 366
            try {
367 367
                connection.close();
368
            } catch(Exception ex) {
368
            } catch (Exception ex) {
369 369
                LOGGER.warn("Can't close connection.", ex);
370 370
            }
371
       }
371
        }
372 372
    }
373
    
373

  
374 374
    @Override
375 375
    protected void doDispose() throws BaseException {
376 376
        JDBCUtils.closeQuietly(this);
......
427 427
                        break;
428 428
                    default:
429 429
                        value = rs.getObject(rsIndex++);
430
                        if( value instanceof Blob ) {
431
                            Blob blob = (Blob)value;
430
                        if (value instanceof Blob) {
431
                            Blob blob = (Blob) value;
432 432
                            value = blob.getBytes(0, (int) blob.length());
433 433
                            blob.free();
434 434
                        }
435 435
                }
436 436
                feature.set(column.getIndex(), value);
437 437
            }
438
            if( ArrayUtils.isNotEmpty(extraValueNames) ) {
438
            if (ArrayUtils.isNotEmpty(extraValueNames)) {
439 439
                feature.setExtraValueNames(extraValueNames);
440 440
                for (int index = 0; index < extraValueNames.length; index++) {
441 441
                    value = rs.getObject(rsIndex++);
442
                    if( value instanceof Blob ) {
443
                        Blob blob = (Blob)value;
442
                    if (value instanceof Blob) {
443
                        Blob blob = (Blob) value;
444 444
                        value = blob.getBytes(0, (int) blob.length());
445 445
                        blob.free();
446 446
                    }
......
494 494
    public FeatureProvider createFeature(FeatureType featureType) throws DataException {
495 495
        return this.store.getStoreServices().createDefaultFeatureProvider(featureType);
496 496
    }
497
    
497

  
498 498
    @Override
499 499
    public boolean useSubquery() {
500
        if( this.store == null ) {
500
        if (this.store == null) {
501 501
            return false;
502 502
        }
503 503
        return !StringUtils.isEmpty(this.store.getParameters().getSQL());
504
    }  
505
    
504
    }
505

  
506 506
    @Override
507 507
    public SRSSolver getSRSSolver() {
508 508
        return this.srssolver;
509 509
    }
510
    
510

  
511 511
    @Override
512 512
    public JDBCStoreProvider createProvider(
513
            JDBCStoreParameters parameters, 
513
            JDBCStoreParameters parameters,
514 514
            DataStoreProviderServices providerServices
515
        ) throws InitializeException {
516
        
515
    ) throws InitializeException {
516

  
517 517
        JDBCStoreProviderBase theStore = new JDBCStoreProviderBase(
518
                parameters, 
519
                providerServices, 
518
                parameters,
519
                providerServices,
520 520
                DBHelper.newMetadataContainer(JDBCLibrary.NAME),
521 521
                this
522 522
        );
......
526 526

  
527 527
    @Override
528 528
    public JDBCServerExplorer createServerExplorer(
529
            JDBCServerExplorerParameters parameters, 
529
            JDBCServerExplorerParameters parameters,
530 530
            DataServerExplorerProviderServices providerServices
531
        ) throws InitializeException {
532
        
531
    ) throws InitializeException {
532

  
533 533
        JDBCServerExplorer explorer = new JDBCServerExplorerBase(
534
                parameters, 
535
                providerServices, 
534
                parameters,
535
                providerServices,
536 536
                this
537 537
        );
538 538
        this.initialize(explorer, parameters, null);
......
556 556

  
557 557
    @Override
558 558
    public String getSourceId(JDBCStoreParameters parameters) {
559
        return parameters.getHost() + ":" +
560
               parameters.getDBName() + ":" + 
561
               parameters.getSchema()+ ":" + 
562
               parameters.tableID();
559
        return parameters.getHost() + ":"
560
                + parameters.getDBName() + ":"
561
                + parameters.getSchema() + ":"
562
                + parameters.tableID();
563 563
    }
564 564

  
565 565
    @Override
566 566
    public boolean isThreadSafe() {
567 567
        return true;
568 568
    }
569
    
569

  
570 570
    @Override
571 571
    public String[] replaceForeingValueFunction(SQLBuilder sqlbuilder, FeatureType type) {
572 572
        // See test SQLBuilderTest->testForeingValue()
573 573
        final ExpressionBuilder where = sqlbuilder.select().where();
574
        if( where == null || where.isEmpty() ) {
574
        if (where == null || where.isEmpty()) {
575 575
            return null;
576 576
        }
577 577
        final SQLBuilder.TableNameBuilder table = sqlbuilder.select().from().table();
578 578
        final ExpressionBuilder expbuilder = sqlbuilder.expression();
579
        
579

  
580 580
        final List<String> foreing_value_args = new ArrayList<>();
581 581
        final List<ExpressionBuilder.Value[]> value_replacements = new ArrayList<>();
582 582

  
......
588 588
            public void visit(ExpressionBuilder.Visitable value) {
589 589
                // Requiere que sea la funcion "FOREING_VALUE con un solo 
590 590
                // argumento que sea una constante de tipo string.
591
                if( !(value instanceof ExpressionBuilder.Function) ) {
591
                if (!(value instanceof ExpressionBuilder.Function)) {
592 592
                    return;
593 593
                }
594 594
                ExpressionBuilder.Function function = (ExpressionBuilder.Function) value;
595
                if( !StringUtils.equalsIgnoreCase(function.name(), "FOREING_VALUE") ) {
595
                if (!StringUtils.equalsIgnoreCase(function.name(), "FOREING_VALUE")) {
596 596
                    return;
597 597
                }
598
                if( function.parameters().size()!=1 ) {
598
                if (function.parameters().size() != 1) {
599 599
                    return;
600
                } 
600
                }
601 601
                ExpressionBuilder.Value arg = function.parameters().get(0);
602
                if( !(arg instanceof ExpressionBuilder.Constant) ) {
602
                if (!(arg instanceof ExpressionBuilder.Constant)) {
603 603
                    return;
604 604
                }
605 605
                Object arg_value = ((ExpressionBuilder.Constant) arg).value();
606
                if( !(arg_value instanceof CharSequence) ) {
606
                if (!(arg_value instanceof CharSequence)) {
607 607
                    return;
608 608
                }
609 609
                String foreing_value_arg = arg_value.toString();
610 610
                String[] foreingNameParts = StringUtils.split(foreing_value_arg, "[.]");
611
                if( foreingNameParts.length!=2 ) {
611
                if (foreingNameParts.length != 2) {
612 612
                    // De momento solo tratamos joins entre dos tablas.
613 613
                    return;
614 614
                }
615 615
                String columnNameLocal = foreingNameParts[0];
616 616
                String columnNameForeing = foreingNameParts[1];
617 617
                FeatureAttributeDescriptor attr = type.getAttributeDescriptor(columnNameLocal);
618
                if( !attr.isForeingKey() ) {
618
                if (!attr.isForeingKey()) {
619 619
                    // Uhm... si el argumento no referencia a un campo que es
620 620
                    // clave ajena no lo procesamos. 
621 621
                    // ? Deberiamos lanzar un error ?
......
626 626
                ForeingKey foreingKey = attr.getForeingKey();
627 627
                SQLBuilder.TableNameBuilder foreingTable = sqlbuilder.createTableNameBuilder()
628 628
                        .database(table.getDatabase())
629
                        .schema(table.getSchema()) 
629
                        .schema(table.getSchema())
630 630
                        .name(foreingKey.getTableName());
631 631
                // Reemplzaremos la funcion FOREING_VALUE, por el acceso al campo
632 632
                // que toca de la tabla a la que referencia la clave ajena.
633 633
                ExpressionBuilder.Variable function_replacement = sqlbuilder.column(foreingTable, columnNameForeing);
634 634
                value_replacements.add(
635
                    new ExpressionBuilder.Value[] {
636
                        function,
637
                        function_replacement
638
                    }
635
                        new ExpressionBuilder.Value[]{
636
                            function,
637
                            function_replacement
638
                        }
639 639
                );
640 640
                foreing_value_args.add(foreing_value_arg);
641 641
            }
642 642
        }, null);
643
            
643

  
644 644
        // Si no habia ningun llamada a la funcion FOREING_VALUE, no hay que
645 645
        // hacer nada.
646
        if( foreing_value_args.isEmpty() ) {
646
        if (foreing_value_args.isEmpty()) {
647 647
            return null;
648 648
        }
649 649

  
......
653 653
        // Para las columnas que puedan dar conflicto se prepara un reemplazo 
654 654
        // de estas que tenga el nombre de tabla.
655 655
        for (ExpressionBuilder.Variable variable : sqlbuilder.variables()) {
656
            if( variable instanceof SQLBuilderBase.ColumnBase ) {
656
            if (variable instanceof SQLBuilderBase.ColumnBase) {
657 657
                continue;
658 658
            }
659 659
            for (String foreingName : foreing_value_args) {
660 660
                String[] foreingNameParts = foreingName.split("[.]");
661
                if( foreingNameParts.length != 2) {
661
                if (foreingNameParts.length != 2) {
662 662
                    continue;
663 663
                }
664 664
                String columnNameLocal = foreingNameParts[0];
665 665
                String columnNameForeing = foreingNameParts[1];
666
                if( !StringUtils.equalsIgnoreCase(variable.name(), columnNameForeing) ) {
667
                    continue;
666
                if (StringUtils.equalsIgnoreCase(variable.name(), columnNameForeing)
667
                        || StringUtils.equalsIgnoreCase(variable.name(), columnNameLocal)) {
668
                    ExpressionBuilder.Variable variable_replacement = sqlbuilder.column(
669
                            table,
670
                            variable.name()
671
                    );
672
                    value_replacements.add(
673
                            new ExpressionBuilder.Value[]{
674
                                variable,
675
                                variable_replacement
676
                            }
677
                    );
668 678
                }
669
                ExpressionBuilder.Variable variable_replacement = sqlbuilder.column(
670
                    table, 
671
                    variable.name()
672
                );
673
                value_replacements.add(
674
                    new ExpressionBuilder.Value[] {
675
                        variable,
676
                        variable_replacement
677
                    }
678
                );
679 679
            }
680 680
        }
681
        
681

  
682 682
        // Realizamos los reemplazos calculados previamente (value_replacements).
683 683
        for (ExpressionBuilder.Value[] replaceValue : value_replacements) {
684 684
            ExpressionBuilder.Value target = replaceValue[0];
685 685
            ExpressionBuilder.Value replacement = replaceValue[1];
686
            sqlbuilder.select().replace(target, replacement);    
686
            sqlbuilder.select().replace(target, replacement);
687 687
        }
688 688

  
689 689
        // A?adimos a la SQL los "LEFT JOIN" que toca para poder acceder
......
692 692
        // como columnas de la SQL para poder acceder a ellos si fuese necesario.
693 693
        for (String foreingName : foreing_value_args) {
694 694
            String[] foreingNameParts = foreingName.split("[.]");
695
            if( foreingNameParts.length != 2) {
695
            if (foreingNameParts.length != 2) {
696 696
                continue;
697 697
            }
698 698
            String columnNameLocal = foreingNameParts[0];
699 699
            String columnNameForeing = foreingNameParts[1];
700 700
            FeatureAttributeDescriptor attr = type.getAttributeDescriptor(columnNameLocal);
701
            if( attr.isForeingKey() ) {
701
            if (attr.isForeingKey()) {
702 702
                ForeingKey foreingKey = attr.getForeingKey();
703 703
                SQLBuilder.TableNameBuilder foreingTable = sqlbuilder.createTableNameBuilder()
704 704
                        .database(table.getDatabase())
705
                        .schema(table.getSchema()) 
705
                        .schema(table.getSchema())
706 706
                        .name(foreingKey.getTableName());
707 707
                SQLBuilder.TableNameBuilder mainTable = sqlbuilder.createTableNameBuilder()
708 708
                        .database(table.getDatabase())
709
                        .schema(table.getSchema()) 
709
                        .schema(table.getSchema())
710 710
                        .name(table.getName());
711 711

  
712 712
                sqlbuilder.select().from()
713
                    .left_join(
714
                        foreingTable,
715
                        expbuilder.eq(
716
                                sqlbuilder.column(mainTable, columnNameLocal),
717
                                sqlbuilder.column(foreingTable,foreingKey.getCodeName()) 
718
                        )
719
                    );
720
                sqlbuilder.select().column().name(foreingTable,columnNameForeing);
713
                        .left_join(
714
                                foreingTable,
715
                                expbuilder.eq(
716
                                        sqlbuilder.column(mainTable, columnNameLocal),
717
                                        sqlbuilder.column(foreingTable, foreingKey.getCodeName())
718
                                )
719
                        );
720
                sqlbuilder.select().column().name(foreingTable, columnNameForeing);
721 721
            }
722 722
        }
723 723

  

Also available in: Unified diff