Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.dal / org.gvsig.fmap.dal.db / org.gvsig.fmap.dal.db.mdb / src / main / java / org / gvsig / fmap / dal / store / mdb / MDBSQLBuilder.java @ 47606

History | View | Annotate | Download (32 KB)

1
package org.gvsig.fmap.dal.store.mdb;
2

    
3
import java.sql.Clob;
4
import java.sql.PreparedStatement;
5
import java.sql.SQLException;
6
import java.sql.Timestamp;
7
import java.text.MessageFormat;
8
import java.util.ArrayList;
9
import java.util.Date;
10
import java.util.List;
11
import java.util.Objects;
12
import org.apache.commons.codec.binary.Hex;
13
import org.apache.commons.lang3.mutable.MutableBoolean;
14
import org.apache.commons.lang3.tuple.Pair;
15
import org.gvsig.expressionevaluator.ExpressionBuilder;
16
import org.gvsig.expressionevaluator.ExpressionBuilder.Parameter;
17
import org.gvsig.expressionevaluator.Formatter;
18
import org.gvsig.expressionevaluator.GeometryExpressionBuilderHelper;
19
import org.gvsig.expressionevaluator.GeometryExpressionBuilderHelper.GeometryParameter;
20
import org.gvsig.fmap.dal.DataTypes;
21
import org.gvsig.fmap.dal.SQLBuilder;
22
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
23
import org.gvsig.fmap.dal.feature.FeatureType;
24
import org.gvsig.fmap.dal.feature.spi.FeatureProvider;
25
import org.gvsig.fmap.dal.feature.spi.SQLBuilderBase;
26
import org.gvsig.fmap.dal.store.mdb.expressionbuilderformatter.MDBFormatter;
27
import org.gvsig.fmap.dal.store.jdbc2.spi.JDBCSQLBuilderBase;
28
import org.gvsig.fmap.geom.Geometry;
29
import org.gvsig.fmap.geom.exception.CreateGeometryException;
30
import org.gvsig.tools.dispose.Disposable;
31
import org.hsqldb.jdbc.JDBCClob;
32

    
33
public class MDBSQLBuilder extends JDBCSQLBuilderBase {
34

    
35
    protected Formatter formatter = null;
36
    
37
    public MDBSQLBuilder(MDBHelper helper) {
38
        super(helper);
39
        
40
        this.defaultSchema = "";
41
        this.supportSchemas = false;
42
        this.allowAutomaticValues = true;
43
        this.geometrySupportType = this.helper.getGeometrySupportType();
44
        this.hasSpatialFunctions = this.helper.hasSpatialFunctions();
45

    
46
        this.STMT_DELETE_GEOMETRY_COLUMN_FROM_TABLE_schema_table = null;
47
        this.STMT_DELETE_GEOMETRY_COLUMN_FROM_TABLE_table = null;
48
         
49
        this.STMT_UPDATE_TABLE_STATISTICS_table = "";
50

    
51
        this.type_boolean = "BOOLEAN";
52
        this.type_byte = "TINYINT";
53
        this.type_bytearray = "BLOB";
54
        this.type_geometry = "CLOB";
55
        this.type_char = "CHAR";
56
        this.type_date = "DATETIME";
57
        this.type_double = "FLOAT"; 
58
        this.type_decimal_ps = "DECIMAL({0,Number,##########},{1,Number,##########})";
59
        this.type_decimal_p = "DECIMAL({0,Number,##########})";
60
        this.type_float = "REAL";
61
        this.type_int = "INTEGER";
62
        this.type_long = "DECIMAL(19,0)";
63
        this.type_string = "VARCHAR";
64
        this.type_string_p = "VARCHAR({0,Number,##########})";
65
        this.type_time = "DATETIME";
66
        this.type_timestamp = "DATETIME";
67
        this.type_version = "VARCHAR";
68
        this.type_URI = "VARCHAR";
69
        this.type_URL = "VARCHAR";
70
        this.type_FILE = "VARCHAR";
71
        this.type_FOLDER = "VARCHAR";             
72
    }
73

    
74
    @Override
75
    public Formatter formatter() {
76
        if( this.formatter==null ) {
77
            this.formatter = new MDBFormatter(this);
78
        }
79
        return this.formatter;
80
    }
81

    
82
    public class MDBTableNameBuilderBase extends TableNameBuilderBase {
83

    
84
        @Override
85
        public boolean has_database() {
86
            return false;
87
        }
88
        
89
    }
90

    
91
    public class MDBCreateIndexBuilder extends CreateIndexBuilderBase {
92
    
93
        @Override
94
        public List<String> toStrings(Formatter formatter) {
95
            StringBuilder builder = new StringBuilder();
96
            builder.append("CREATE ");
97
            if( this.isUnique ) {
98
                builder.append("UNIQUE ");
99
            }
100
            if( this.isSpatial ) {
101
                builder.append("SPATIAL ");
102
            }
103
            builder.append("INDEX ");
104
            if( this.ifNotExist ) {
105
                builder.append("IF NOT EXISTS ");
106
            }
107
            builder.append(as_identifier(this.indexName));
108
            builder.append(" ON ");
109
            builder.append(this.table.toString(formatter));
110
            builder.append(" ( ");
111
            boolean is_first_column = true;
112
            for( String column : this.columns) {
113
                if( is_first_column ) {
114
                    is_first_column = false;
115
                } else {
116
                    builder.append(", ");
117
                }
118
                builder.append(as_identifier(column));
119
            }
120
            builder.append(" )");
121
            
122
            List<String> sqls = new ArrayList<>();
123
            sqls.add(builder.toString());
124
            return sqls;
125
        }
126

    
127
    }
128
        
129
    protected class MDBAlterTableBuilderBase extends AlterTableBuilderBase {
130
        
131
        public MDBAlterTableBuilderBase(SQLBuilderBase sqlbuilder) {
132
            super(sqlbuilder);
133
        }
134
        
135
        @Override
136
        public List<String> toStrings(Formatter formatter) {
137
            List<String> sqls = new ArrayList<>();
138
            if( this.isEmpty() ) {
139
                return sqls;
140
            }
141
            for (String column : drops) {
142
                StringBuilder builder = new StringBuilder();
143
                builder.append("ALTER TABLE ");
144
                builder.append(this.table.toString(formatter));
145
                builder.append(" DROP COLUMN IF EXISTS ");
146
                builder.append(as_identifier(column)); 
147
                sqls.add(builder.toString());
148
            }
149
            for (ColumnDescriptor column : adds) {
150
                StringBuilder builder = new StringBuilder();
151
                builder.append("ALTER TABLE ");
152
                builder.append(this.table.toString(formatter));
153
                builder.append(" ADD COLUMN ");
154
                builder.append(as_identifier(column.getName())); 
155
                builder.append(" ");
156
                if( column.getType() == DataTypes.INT && column.isAutomatic() ) {
157
                    builder.append(" SERIAL");
158
                } else {
159
                    builder.append(
160
                        sqltype(
161
                            column.getType(), 
162
                            column.getSize(),
163
                            column.getPrecision(), 
164
                            column.getScale(), 
165
                            column.getGeometryType(), 
166
                            column.getGeometrySubtype()
167
                        )
168
                    );
169
                }
170
                if (column.getDefaultValue() == null) {
171
                    if (column.allowNulls()) {
172
                        builder.append(" DEFAULT NULL");
173
                    }
174
                } else {
175
                    builder.append(" DEFAULT '");
176
                    builder.append(Objects.toString(column.getDefaultValue(),""));
177
                    builder.append("'");
178
                }
179
                if (column.allowNulls()) {
180
                    builder.append(" NULL");
181
                } else {
182
                    builder.append(" NOT NULL");
183
                }
184
                if (column.isPrimaryKey()) {
185
                    builder.append(" PRIMARY KEY");
186
                }
187
                sqls.add(builder.toString());
188
                
189
//                if( column.isGeometry() ) {
190
//                    String constraint_name = "constraint_" + this.table().getName() + "_" + column.getName()+"_geom";
191
//                    String sql;
192
//                    if( column.getGeometrySRSId()==null ) {
193
//                      sql = MessageFormat.format(
194
//                            "ALTER TABLE \"{0}\".\"{1}\" ADD CONSTRAINT IF NOT EXISTS \"{2}\" CHECK NVL2(\"{3}\", ST_GeometryTypeCode(\"{3}\") = {4,number,###} AND ST_CoordDim(\"{3}\") = {5,number,###}, TRUE)",
195
//                            this.table().getSchema(),
196
//                            this.table().getName(),
197
//                            constraint_name,
198
//                            column.getName(),
199
//                            sqlgeometrytype(column.getGeometryType(),column.getGeometrySubtype()),
200
//                            sqlgeometrynumdimension(column.getGeometryType(),column.getGeometrySubtype()),
201
//                            column.getGeometrySRSId() 
202
//                      );
203
//                    } else {
204
//                      sql = MessageFormat.format(
205
//                            "ALTER TABLE \"{0}\".\"{1}\" ADD CONSTRAINT IF NOT EXISTS \"{2}\" CHECK NVL2(\"{3}\", ST_GeometryTypeCode(\"{3}\") = {4,number,###} AND ST_CoordDim(\"{3}\") = {5,number,###} AND ST_SRID(\"{3}\") = {6,number,#####}, TRUE)",
206
//                            this.table().getSchema(),
207
//                            this.table().getName(),
208
//                            constraint_name,
209
//                            column.getName(),
210
//                            sqlgeometrytype(column.getGeometryType(),column.getGeometrySubtype()),
211
//                            sqlgeometrynumdimension(column.getGeometryType(),column.getGeometrySubtype()),
212
//                            column.getGeometrySRSId() 
213
//                      );
214
//                    }
215
//                    sqls.add(sql);
216
//                }
217
            }
218
            for (ColumnDescriptor column : alters) {
219
                StringBuilder builder = new StringBuilder();
220
                builder.append("ALTER TABLE ");
221
                builder.append(this.table.toString(formatter));
222
                builder.append(" ALTER COLUMN ");
223
                builder.append(as_identifier(column.getName())); 
224
                builder.append(" ");
225
                builder.append(
226
                    sqltype(
227
                        column.getType(), 
228
                        column.getSize(),
229
                        column.getPrecision(), 
230
                        column.getScale(), 
231
                        column.getGeometryType(), 
232
                        column.getGeometrySubtype()
233
                    )
234
                );
235
                if (column.getDefaultValue() == null) {
236
                    if (column.allowNulls()) {
237
                        builder.append(" DEFAULT NULL");
238
                    }
239
                } else {
240
                    builder.append(" DEFAULT '");
241
                    builder.append(column.getDefaultValue().toString());
242
                    builder.append("'");
243
                }
244
                if( column.isAutomatic() ) {
245
                    builder.append(" AUTO_INCREMENT");
246
                }
247
                sqls.add(builder.toString());
248
//                if( column.isGeometry() ) {
249
//                    String sql;
250
//                    String constraint_name = "constraint_" + this.table().getName() + "_" + column.getName()+"_dim";
251
//                    sql = MessageFormat.format(
252
//                        "ALTER TABLE \"{0}\".\"{1}\" ADD CONSTRAINT IF NOT EXISTS \"{2}\" CHECK ST_CoordDim(\"{3}\") = {4}",
253
//                        this.table().getSchema(),
254
//                        this.table().getName(),
255
//                        constraint_name,
256
//                        column.getName(),
257
//                        sqlgeometrynumdimension(column.getGeometryType(),column.getGeometrySubtype())
258
//                    );
259
//                    sqls.add(sql);
260
//                }
261
            }
262
            for (Pair<String,String> pair : renames) {
263
                StringBuilder builder = new StringBuilder();
264
                builder.append("ALTER TABLE ");
265
                builder.append(this.table.toString(formatter));
266
                builder.append(" RENAME COLUMN ");
267
                builder.append(as_identifier(pair.getLeft())); 
268
                builder.append(" TO ");
269
                builder.append(as_identifier(pair.getRight())); 
270
                sqls.add(builder.toString());
271
            }
272
            return sqls;
273
        }
274

    
275
    }
276

    
277
    protected class MDBCreateTableBuilder extends CreateTableBuilderBase {
278

    
279
        @Override
280
        public List<String> toStrings(Formatter formatter) {
281

    
282
            List<String> sqls = new ArrayList<>();
283
            StringBuilder builder = new StringBuilder();
284

    
285
            builder.append("CREATE TABLE ");
286
            builder.append(this.table.toString(formatter));
287
            builder.append(" (");
288
            boolean first = true;
289
            for (ColumnDescriptor column : columns) {
290

    
291
                if (first) {
292
                    first = false;
293
                } else {
294
                    builder.append(", ");
295
                }
296
                builder.append(as_identifier(column.getName()));
297
                builder.append(" ");
298
                if( column.isGeometry() ) {
299
                    builder.append(type_geometry);
300
                } else {
301
                    builder.append(
302
                        sqltype(
303
                            column.getType(), 
304
                            column.getSize(),
305
                            column.getPrecision(), 
306
                            column.getScale(), 
307
                            column.getGeometryType(), 
308
                            column.getGeometrySubtype()
309
                        )
310
                    );
311
                }
312
                if (column.isPrimaryKey()) {
313
                    builder.append(" PRIMARY KEY");
314
                    if( column.isAutomatic() ) {
315
                        builder.append(" AUTO_INCREMENT");
316
                    }
317
                } else {
318
                    if( column.isAutomatic() ) {
319
                        builder.append(" AUTO_INCREMENT");
320
                    }
321
                    if (column.getDefaultValue() == null) {
322
                        if (column.allowNulls()) {
323
                            builder.append(" DEFAULT NULL");
324
                        }
325
                    } else {
326
                        if( column.getType() == DataTypes.DATE ) {
327
                            builder.append(" DEFAULT ( TIMESTAMP '");
328
                            Date d = (Date) column.getDefaultValue();
329
                            builder.append(MessageFormat.format( "{0,date,yyyy-MM-dd HH:mm:ss.S}",d));
330
                            builder.append("' )");
331
                        } else {
332
                            builder.append(" DEFAULT '");
333
                            builder.append(Objects.toString(column.getDefaultValue(),""));
334
                            builder.append("'");
335
                        }
336
                    }                    
337
                }
338
                if (!column.allowNulls()) {
339
                    builder.append(" NOT NULL");
340
                }
341
            }
342
            builder.append(" )");
343
            sqls.add(builder.toString());
344
            return sqls;
345
        }
346
    }
347
    
348
    public class MDBInsertColumnBuilderBase extends InsertColumnBuilderBase {
349
        @Override
350
       public String toString(Formatter<ExpressionBuilder.Value> formatter) {
351
            if( formatter!=null && formatter.canApply(this) ) {
352
                return formatter.format(this);
353
            }
354
            return this.value.toString(formatter);
355
        }
356
    }
357
    
358
    public class MDBInsertBuilderBase extends InsertBuilderBase {
359
        @Override
360
        public String toString(Formatter formatter) {
361
            return super.toString(formatter);
362
        }
363
    }
364
    
365
    public class MDBSelectColumnBuilderBase extends SelectColumnBuilderBase {
366

    
367
        public MDBSelectColumnBuilderBase(SQLBuilder sqlbuilder) {
368
            super(sqlbuilder);
369
        }
370
        
371
        @Override
372
        public String toString(Formatter formatter) {
373
            return super.toString(formatter);
374
        }
375
    }
376
        
377
    public class MDBSelectBuilderBase extends SelectBuilderBase {
378
        
379
        @Override
380
        public String toString(Formatter formatter) {
381
            StringBuilder builder = new StringBuilder();
382
            if( !isValid(builder) ) {
383
                throw new IllegalStateException(builder.toString());
384
            }
385
            builder.append("SELECT ");
386
            if( this.distinct ) {
387
                builder.append("DISTINCT ");
388
            }
389
            boolean first = true;
390
            for (SelectColumnBuilder column : columns) {
391
                if (first) {
392
                    first = false;
393
                } else {
394
                    builder.append(", ");
395
                }
396
                
397
                builder.append(column.toString(formatter));
398
            }
399

    
400
            if ( this.has_from() ) {
401
                builder.append(" FROM ");
402
                builder.append(this.from.toString(formatter));
403
            }
404
            if ( this.has_where() ) {
405
                builder.append(" WHERE ");
406
                builder.append(this.where.toString(formatter));
407
            }
408
            if( this.has_group_by() ) {
409
                builder.append(" GROUP BY ");
410
                builder.append(this.groupColumn.get(0).toString(formatter));
411
                for (int i = 1; i < groupColumn.size(); i++) {
412
                    builder.append(", ");
413
                    builder.append(this.groupColumn.get(i).toString(formatter));
414
                }
415
            }
416
            if( this.has_order_by() ) {
417
                builder.append(" ORDER BY ");
418
                first = true;
419
                for (OrderByBuilder item : this.order_by) {
420
                    if (first) {
421
                        first = false;
422
                    } else {
423
                        builder.append(", ");
424
                    }
425
                    builder.append(item.toString(formatter));                    
426
                }   
427
            }
428
            
429
            if ( this.has_limit() && this.has_offset() ) {
430
                builder.append(" LIMIT ");
431
                builder.append(this.limit);
432
                builder.append(" OFFSET ");
433
                builder.append(this.offset);
434
                
435
            } else if ( this.has_limit()) {
436
                builder.append(" LIMIT ");
437
                builder.append(this.limit);
438

    
439
            } else if ( this.has_offset() ) {
440
                builder.append(" LIMIT -1 OFFSET ");
441
                builder.append(this.offset);    
442
            }
443
            return builder.toString();
444

    
445
        }
446
    }
447

    
448
    @Override
449
    public Object sqlgeometrydimension(int type, int subtype) {
450
        //'XY' or 2: 2D points, identified by X and Y coordinates
451
        //'XYM': 2D points, identified by X and Y coordinates. Each point stores an M-value (measure) as well
452
        //'XYZ' or 3: 3D points, identified by X, Y and Z coordinates
453
        //'XYZM' or 4: 3D points, identified by X, Y and Z coordinates. Each point stores an M-value (measure) as well
454
        switch(subtype) {
455
            case Geometry.SUBTYPES.GEOM2D:
456
            default:
457
                return "XY";
458
            case Geometry.SUBTYPES.GEOM2DM:
459
                return "XYM";
460
            case Geometry.SUBTYPES.GEOM3D:
461
                return "XYZ";
462
            case Geometry.SUBTYPES.GEOM3DM:
463
                return "XYZM";
464
        }
465
    }
466

    
467
    @Override
468
    public String sqltype(int type, int size, int precision, int scale, int geomtype, int geomSubtype) {
469
        if( type!=DataTypes.GEOMETRY ) {
470
            return super.sqltype(type, size, precision, scale, geomtype, geomSubtype);
471
        }
472
        return this.type_geometry;
473
    }
474
    
475
    @Override
476
    public Object sqlgeometrytype(int geomtype, int geomsubtype) {
477
        //
478
        // https://github.com/orbisgis/h2gis/wiki/1.-Spatial-data#geometry-columns-view
479
        //
480
        switch(geomtype) {
481
        case Geometry.TYPES.POINT:
482
            return 1; 
483
        case Geometry.TYPES.MULTIPOINT:
484
            return 4; 
485
        case Geometry.TYPES.LINE:
486
            return 2; 
487
        case Geometry.TYPES.MULTILINE:
488
            return 5; 
489
        case Geometry.TYPES.POLYGON:
490
            return 3; 
491
        case Geometry.TYPES.MULTIPOLYGON:
492
            return 6;
493
        case Geometry.TYPES.GEOMETRY:
494
        default:
495
            return 0; // "GEOMETRY";
496
        }
497
    }
498
    
499
    public Object sqlgeometrynumdimension(int type, int subtype) {
500
        int dimensions=2;
501
        switch(subtype) {
502
        case Geometry.SUBTYPES.GEOM3D:
503
            dimensions = 3;
504
            break;
505
        case Geometry.SUBTYPES.GEOM2D:
506
            dimensions = 2;
507
            break;
508
        case Geometry.SUBTYPES.GEOM2DM:
509
            dimensions = 2; // ??????
510
            break;
511
        case Geometry.SUBTYPES.GEOM3DM:
512
            dimensions = 3; // ??????
513
            break;
514
        }
515
        return dimensions;
516
    }
517
    
518
    @Override
519
    public MDBHelper getHelper() {
520
        return (MDBHelper) this.helper;
521
    }
522
   
523
    @Override
524
    public Disposable setParameters(PreparedStatement st, FeatureProvider feature) {
525
        try {
526
            FeatureType featureType = feature.getType();
527
            List<Object> values = new ArrayList<>();
528
            List<Parameter> parameters = this.parametersWithoutSRS();
529
            for (Parameter parameter : parameters) {
530
                if (parameter.is_constant()) {
531
                    values.add(parameter.value());
532
                } else {
533
                    String name = parameter.name();
534
                    FeatureAttributeDescriptor descriptor = featureType.getAttributeDescriptor(name);
535
                    switch( descriptor.getType() ) {
536
                    case DataTypes.DATE:
537
                        Date value = (Date)(feature.get(name));
538
                        if( value == null ) {
539
                            values.add(null);
540
                        } else {
541
                            values.add(new java.sql.Date(value.getTime()));
542
                        }
543
                        break;
544
                    case DataTypes.GEOMETRY:
545
                        Geometry geom = this.forceGeometryType(
546
                            descriptor.getGeomType(),
547
                            (Geometry)(feature.get(name))
548
                        );
549
                        values.add(geom);
550
                        break;
551
                    default:
552
                        values.add(feature.get(name));
553
                        break;
554
                    }
555
                }
556
            }
557
            return this.setStatementParameters(st, values, this.geometry_support_type());
558
        } catch (SQLException | CreateGeometryException ex) {
559
            String f = "unknow";
560
            try {
561
                f = feature.toString();
562
            } catch (Exception ex2) {
563
                // Do nothing
564
            }
565
            throw new RuntimeException("Can't set parameters to prepared statement from the feature (" + f + ")", ex);
566
        }
567
    }
568

    
569
    public List<Parameter> parametersWithoutSRS() {
570
        final List<Parameter>  params = new ArrayList<>();
571
        MutableBoolean skipNextParameter = new MutableBoolean(false);
572
        this.accept((ExpressionBuilder.Visitable value1) -> {
573
            if (skipNextParameter.isTrue()) {
574
                skipNextParameter.setFalse();
575
                return;
576
            }
577
            if (value1 instanceof GeometryExpressionBuilderHelper.GeometryParameter) {
578
                GeometryParameter g = (GeometryParameter) value1;
579
                if (g.srs()!= null) {
580
                    skipNextParameter.setTrue();
581
                }
582
                
583
            }
584
          params.add((Parameter) value1);
585
        }, new ExpressionBuilder.ClassVisitorFilter(Parameter.class));
586
        return params;
587
    }
588
//.
589
//    public List<Parameter> parametersWithoutSRS() { // aqui hay que eliminar el srs. Visitor de tipo GeometryParameterBase, si ese tiene srs. si lo tiene y es de tipo Parametro debe saltarselo
590
//        final List<Parameter> params = new ArrayList<>();
591
//        this.accept(new ExpressionBuilder.Visitor() {
592
//            @Override
593
//            public void visit(ExpressionBuilder.Visitable value) {
594
//                params.add((Parameter) value);
595
//            }
596
//        }, new ExpressionBuilder.ClassVisitorFilter(Parameter.class));
597
//        return params;
598
//    }
599

    
600
    @Override
601
    public InsertColumnBuilderBase createInsertColumnBuilder() {
602
        return new MDBInsertColumnBuilderBase();
603
    }
604
        
605
    @Override
606
    public InsertBuilderBase createInsertBuilder() {
607
        return new MDBInsertBuilderBase();
608
    }
609

    
610
    @Override
611
    public AlterTableBuilder createAlterTableBuilder() {
612
        return new MDBAlterTableBuilderBase(this);
613
    }
614
            
615
    @Override
616
    public TableNameBuilder createTableNameBuilder() {
617
        return new MDBTableNameBuilderBase();
618
    }
619
    
620
    @Override
621
    protected CreateTableBuilder createCreateTableBuilder() {
622
        return new MDBCreateTableBuilder();
623
    }
624

    
625
    @Override
626
    public SelectBuilder createSelectBuilder() {
627
        return new MDBSelectBuilderBase();
628
    }
629

    
630
    @Override
631
    protected SelectColumnBuilder createSelectColumnBuilder() {
632
        //super.createSelectColumnBuilder().; // SelectColumnBuilderBase, override el metodo toString
633
        return new MDBSelectColumnBuilderBase(this);
634
    }
635
    
636
    @Override
637
    public CreateIndexBuilder createCreateIndexBuilder() {
638
        return new MDBCreateIndexBuilder();
639
    }
640
    
641
    @Override
642
    public String as_identifier(String id) {
643
        if (id.startsWith("[")) {
644
            return id;
645
        }
646
        return "["+id+"]";
647
    }
648
    
649
    @Override
650
    public Disposable setStatementParameters(
651
            PreparedStatement st,
652
            List values,
653
            GeometryExpressionBuilderHelper.GeometrySupportType geometrySupportType) throws SQLException {
654

    
655
        //
656
        DisposableClobs disposableClobs = new DisposableClobs();
657
        //
658
        if (values == null) {
659
            return disposableClobs;
660
        }
661
        if (true || LOGGER.isDebugEnabled()) {
662
            StringBuilder debug = new StringBuilder();
663
            debug.append("st.set(");
664
            try {
665
                byte[] bytes;
666
                int columnIndex = 1;
667
                for (Object value : values) {
668
                    if (value instanceof Geometry) {
669
                        switch (geometrySupportType) {
670
                            case WKT:
671
                                value = ((Geometry) value).convertToWKT();
672
                                debug.append("/*");
673
                                debug.append(columnIndex);
674
                                debug.append("*/ ");
675
                                debug.append(as_string(value));
676
                                debug.append(", ");
677
                                break;
678
                            case NATIVE:
679
                            case WKB:
680
                                bytes = ((Geometry) value).convertToWKB();
681
                                debug.append("/*");
682
                                debug.append(columnIndex);
683
                                debug.append("*/ ");
684
                                debug.append(as_string(bytes));
685
                                debug.append(", ");
686
                                break;
687
                            case EWKB:
688
                                bytes = ((Geometry) value).convertToEWKB();
689
                                debug.append("/*");
690
                                debug.append(columnIndex);
691
                                debug.append("*/ ");
692
                                debug.append(as_string(bytes));
693
                                debug.append(", ");
694
                                break;
695
                        }
696
                    } else {
697
                        debug.append("/*");
698
                        debug.append(columnIndex);
699
                        debug.append("*/ ");
700
                        if (value instanceof String) {
701
                            debug.append(as_string(value));
702
                        } else if (value instanceof Boolean) {
703
                            debug.append(((Boolean) value) ? constant_true : constant_false);
704
                        } else {
705
                            debug.append(value);
706
                        }
707
                        debug.append(", ");
708
                    }
709
                    columnIndex++;
710
                }
711
                debug.append(")");
712
                LOGGER.debug(debug.toString());
713
            } catch (Exception ex) {
714
            }
715
        }
716
        byte[] bytes;
717
        char[] hexGeomEwkb;
718
        int columnIndex = 1;
719
        Object theValue;
720
        Clob cl;
721
        try {
722
            for (Object value : values) {
723
                theValue = value;
724

    
725
                if (value instanceof Geometry) {
726
                    switch (geometrySupportType) {
727
                        case WKT:
728
                            value = ((Geometry) value).convertToWKT();
729
                            st.setObject(columnIndex, value);
730
                            break;
731
                        case NATIVE:
732
                        case WKB:
733
                            bytes = ((Geometry) value).convertToWKB();
734
                            cl = disposableClobs.add(bytes);
735
                            st.setClob(columnIndex, cl);
736
                            break;
737

    
738
                        case EWKB:
739
                            bytes = ((Geometry) value).convertToEWKB();
740
                            cl = disposableClobs.add(bytes);
741
                            st.setClob(columnIndex, cl);
742
                            break;
743

    
744

    
745
                    }
746
                } else if (value instanceof Date) {
747
                    // Access solo soporta timestamp
748
                    value = new Timestamp(((Date) value).getTime());
749
                    st.setObject(columnIndex, value);
750
                } else {
751
                    if (value == null) {
752
                        st.setNull(columnIndex, java.sql.Types.BIT);
753
                    } else {
754
                        st.setObject(columnIndex, value);
755
                    }
756
                }
757
                columnIndex++;
758
            }
759
            return disposableClobs;
760
        } catch (Exception ex) {
761
            throw new SQLException("Can't set values for the prepared statement.", ex);
762
        }
763
    }
764

    
765
    @Override
766
    public List<Object> getParameters(FeatureProvider feature) {
767
        try {
768
            FeatureType type = feature.getType();
769
            List<Object> values = new ArrayList<>();
770
            Object value;
771
            for (Parameter parameter : this.parameters()) {
772
                if (parameter.is_constant()) {
773
                    value = parameter.value();
774
                    values.add(value);
775
                } else {
776
                    String name = parameter.name();
777
                    value = feature.get(name);
778
                    FeatureAttributeDescriptor attrDesc = type.getAttributeDescriptor(name);
779
                    switch (attrDesc.getType()) {
780
                        case org.gvsig.fmap.dal.DataTypes.BOOLEAN:
781
                            if (value == null) {
782
                                value = false;
783
                            }
784
                            values.add(value);
785
                            break;
786
                        case org.gvsig.fmap.dal.DataTypes.DATE:
787
                            if (value == null) {
788
                                values.add(null);
789
                            } else {
790
                                values.add(new java.sql.Date(((Date) value).getTime()));
791
                            }
792
                            break;
793
                        case org.gvsig.fmap.dal.DataTypes.GEOMETRY:
794
                            Geometry geom = this.forceGeometryType(
795
                                    attrDesc.getGeomType(),
796
                                    (Geometry) value
797
                            );
798
                            values.add(geom);
799
                            break;
800
                        default:
801
                            values.add(value);
802
                            break;
803
                    }
804
                }
805
            }
806
            return values;
807
        } catch (Exception ex) {
808
            String f = "unknow";
809
            try {
810
                f = feature.toString();
811
            } catch (Exception ex2) {
812
                // Do nothing
813
            }
814
            throw new RuntimeException("Can't get parameters to prepared statement from the feature (" + f + ")", ex);
815
        }
816
    }
817

    
818

    
819
        public class DisposableClobs implements Disposable {
820

    
821
        private final List<Clob> clobList = new ArrayList<>();
822

    
823
        public Clob add(byte[] bytes) throws SQLException {
824
            char[] hexGeom = Hex.encodeHex(bytes);
825
            String strHexGeo = new String(hexGeom);
826
            JDBCClob clob = new JDBCClob(strHexGeo);
827
            clobList.add(clob);
828
            return clob;
829
        }
830

    
831
        @Override
832
        public void dispose() {
833
            clobList.forEach((Clob clob) -> {
834
                try {
835
                    clob.free();
836
                } catch (SQLException ex) {
837
                }
838
            });
839
        }
840

    
841
    }    
842
}