Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.plugin / org.gvsig.h2spatial / org.gvsig.h2spatial.h2gis132 / org.gvsig.h2spatial.h2gis132.provider / src / main / java / org / gvsig / fmap / dal / store / h2 / H2SpatialSQLBuilder.java @ 47474

History | View | Annotate | Download (25.5 KB)

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

    
3
import java.sql.PreparedStatement;
4
import java.sql.SQLException;
5
import java.sql.Time;
6
import java.sql.Timestamp;
7
import java.text.MessageFormat;
8
import java.util.ArrayList;
9
import java.util.Collections;
10
import java.util.Date;
11
import java.util.List;
12
import java.util.Objects;
13
import org.cresques.cts.IProjection;
14
import org.gvsig.expressionevaluator.ExpressionBuilder;
15
import org.gvsig.expressionevaluator.ExpressionBuilder.Parameter;
16
import org.gvsig.expressionevaluator.ExpressionUtils;
17
import org.gvsig.expressionevaluator.Formatter;
18
import org.gvsig.expressionevaluator.GeometryExpressionBuilderHelper;
19
import org.gvsig.fmap.dal.DataTypes;
20
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
21
import org.gvsig.fmap.dal.feature.FeatureType;
22
import org.gvsig.fmap.dal.feature.spi.FeatureProvider;
23
import org.gvsig.fmap.dal.feature.spi.SQLBuilderBase;
24
import org.gvsig.fmap.dal.store.h2.expressionbuilderformatter.H2SpatialFormatter;
25
import org.gvsig.fmap.dal.store.jdbc2.spi.JDBCSQLBuilderBase;
26
import org.gvsig.fmap.geom.Geometry;
27
import org.gvsig.fmap.geom.exception.CreateGeometryException;
28
import org.gvsig.fmap.geom.type.GeometryType;
29
import org.gvsig.tools.dataTypes.DataTypeUtils;
30
import org.gvsig.tools.dispose.Disposable;
31

    
32
public class H2SpatialSQLBuilder extends JDBCSQLBuilderBase {
33

    
34
    protected Formatter formatter = null;
35
    
36
    public H2SpatialSQLBuilder(H2SpatialHelper helper) {
37
        super(helper);
38
        
39
        //
40
        // H2/H2GIS SQL functions reference list
41
        //
42
        // http://www.h2database.com/html/functions.html
43
        // http://www.h2gis.org/docs/1.3/functions/
44
        //
45
        // http://www.h2database.com/html/grammar.html
46
        //
47
        // http://www.h2database.com/html/datatypes.html
48
        //
49
        //
50

    
51
        
52
        this.defaultSchema = "PUBLIC";
53
        this.supportSchemas = true;
54
        this.allowAutomaticValues = true;
55
        this.geometrySupportType = this.helper.getGeometrySupportType();
56
        this.hasSpatialFunctions = this.helper.hasSpatialFunctions();
57

    
58
        this.STMT_DELETE_GEOMETRY_COLUMN_FROM_TABLE_schema_table = null;
59
        this.STMT_DELETE_GEOMETRY_COLUMN_FROM_TABLE_table = null;
60
         
61
        this.STMT_UPDATE_TABLE_STATISTICS_table = "ANALYZE SAMPLE_SIZE 0";
62

    
63
        this.type_boolean = "BOOLEAN";
64
        this.type_byte = "TINYINT";
65
        this.type_bytearray = "BLOB";
66
        this.type_geometry = "GEOMETRY";
67
        this.type_char = "CHAR";
68
        this.type_date = "DATE";
69
        this.type_double = "DOUBLE"; 
70
        this.type_decimal_ps = "DECIMAL({0,Number,##########},{1,Number,##########})";
71
        this.type_decimal_p = "DECIMAL({0,Number,##########})";
72
        this.type_float = "REAL";
73
        this.type_int = "INTEGER";
74
        this.type_long = "BIGINT";
75
        this.type_string = "CLOB";
76
        this.type_string_p = "VARCHAR({0,Number,##########})";
77
        this.type_time = "TIME";
78
        this.type_timestamp = "TIMESTAMP";
79
        this.type_version = "VARCHAR";
80
        this.type_URI = "VARCHAR";
81
        this.type_URL = "VARCHAR";
82
        this.type_FILE = "VARCHAR";
83
        this.type_FOLDER = "VARCHAR";        
84
    }
85

    
86
    @Override
87
    public Formatter formatter() {
88
        if( this.formatter==null ) {
89
            this.formatter = new H2SpatialFormatter(this);
90
        }
91
        return this.formatter;
92
    }
93

    
94
    public class H2SpatialTableNameBuilderBase extends TableNameBuilderBase {
95

    
96
        @Override
97
        public boolean has_database() {
98
            return false;
99
        }
100
        
101
    }
102

    
103
    public class H2SpatialCreateIndexBuilder extends CreateIndexBuilderBase {
104
    
105
        @Override
106
        public List<String> toStrings(Formatter formatter) {
107
            StringBuilder builder = new StringBuilder();
108
            builder.append("CREATE ");
109
            if( this.isUnique ) {
110
                builder.append("UNIQUE ");
111
            }
112
            if( this.isSpatial ) {
113
                builder.append("SPATIAL ");
114
            }
115
            builder.append("INDEX ");
116
            if( this.ifNotExist ) {
117
                builder.append("IF NOT EXISTS ");
118
            }
119
            builder.append(as_identifier(this.indexName));
120
            builder.append(" ON ");
121
            builder.append(this.table.toString(formatter));
122
            builder.append(" ( ");
123
            boolean is_first_column = true;
124
            for( String column : this.columns) {
125
                if( is_first_column ) {
126
                    is_first_column = false;
127
                } else {
128
                    builder.append(", ");
129
                }
130
                builder.append(as_identifier(column));
131
            }
132
            builder.append(" )");
133
            
134
            List<String> sqls = new ArrayList<>();
135
            sqls.add(builder.toString());
136
            return sqls;
137
        }
138

    
139
    }
140

    
141
    protected class H2SpatialAlterTableBuilderBase extends AlterTableBuilderBase {
142

    
143
        public H2SpatialAlterTableBuilderBase(SQLBuilderBase sqlbuilder) {
144
            super(sqlbuilder);
145
        }
146
        
147
        @Override
148
        protected List<String> alter_column_add_geometry_constraint_sqls(Formatter<ExpressionBuilder.Value> formatter, ColumnDescriptor column) {
149
            String constraint_name = this.getConstrainName("GEOM", column.getName());
150
            String sql;
151
            if (column.getGeometrySRSId() == null) {
152
                if ((int) sqlgeometrytype(column.getGeometryType(), column.getGeometrySubtype()) == 0) {
153
                    sql = MessageFormat.format(
154
                            "ALTER TABLE \"{0}\".\"{1}\" ADD CONSTRAINT IF NOT EXISTS \"{2}\" CHECK NVL2(\"{3}\", ST_CoordDim(\"{3}\") = {4,number,###}, TRUE)",
155
                            this.table().getSchema(),
156
                            this.table().getName(),
157
                            constraint_name,
158
                            column.getName(),
159
                            (int) sqlgeometrynumdimension(column.getGeometryType(), column.getGeometrySubtype())
160
                    );
161
                } else {
162
                    sql = MessageFormat.format(
163
                            "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)",
164
                            this.table().getSchema(),
165
                            this.table().getName(),
166
                            constraint_name,
167
                            column.getName(),
168
                            (int) sqlgeometrytype(column.getGeometryType(), column.getGeometrySubtype()),
169
                            (int) sqlgeometrynumdimension(column.getGeometryType(), column.getGeometrySubtype())
170
                    );
171
                }
172
            } else {
173
                if ((int) sqlgeometrytype(column.getGeometryType(), column.getGeometrySubtype()) == 0) {
174
                    sql = MessageFormat.format(
175
                            "ALTER TABLE \"{0}\".\"{1}\" ADD CONSTRAINT IF NOT EXISTS \"{2}\" CHECK NVL2(\"{3}\", ST_CoordDim(\"{3}\") = {4,number,###} AND ST_SRID(\"{3}\") = {5,number,#####}, TRUE)",
176
                            this.table().getSchema(),
177
                            this.table().getName(),
178
                            constraint_name,
179
                            column.getName(),
180
                            (int) sqlgeometrynumdimension(column.getGeometryType(), column.getGeometrySubtype()),
181
                            (int) column.getGeometrySRSId()
182
                    );
183
                } else {
184
                    sql = MessageFormat.format(
185
                            "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)",
186
                            this.table().getSchema(),
187
                            this.table().getName(),
188
                            constraint_name,
189
                            column.getName(),
190
                            (int) sqlgeometrytype(column.getGeometryType(), column.getGeometrySubtype()),
191
                            (int) sqlgeometrynumdimension(column.getGeometryType(), column.getGeometrySubtype()),
192
                            (int) column.getGeometrySRSId()
193
                    );
194
                }
195
            }
196
            return Collections.singletonList(sql);
197
        }
198
        
199
    }
200

    
201
    protected class H2SpatialCreateTableBuilder extends CreateTableBuilderBase {
202

    
203
        @Override
204
        public List<String> toStrings(Formatter formatter) {
205

    
206
            List<String> sqls = new ArrayList<>();
207
            StringBuilder builder = new StringBuilder();
208

    
209
            builder.append("CREATE TABLE ");
210
            builder.append(this.table.toString(formatter));
211
            builder.append(" (");
212
            boolean first = true;
213
            for (ColumnDescriptor column : columns) {
214

    
215
                if (first) {
216
                    first = false;
217
                } else {
218
                    builder.append(", ");
219
                }
220
                builder.append(as_identifier(column.getName()));
221
                builder.append(" ");
222
                builder.append(
223
                    sqltype(
224
                        column.getType(), 
225
                        column.getSize(),
226
                        column.getPrecision(), 
227
                        column.getScale(), 
228
                        column.getGeometryType(), 
229
                        column.getGeometrySubtype()
230
                    )
231
                );
232
                if( column.isGeometry() ) {
233
                    //
234
                    // https://github.com/orbisgis/h2gis/wiki/1.-Spatial-data#geometry-columns-view
235
                    // https://github.com/orbisgis/h2gis/blob/master/h2gis-functions/src/main/java/org/h2gis/functions/spatial/type/GeometryTypeFromConstraint.java
236
                    //
237
                    if (column.getGeometrySRSId() == null) {
238
                        if ((int) sqlgeometrytype(column.getGeometryType(), column.getGeometrySubtype()) == 0) {
239
                            builder.append(
240
                                    MessageFormat.format(
241
                                            " CHECK NVL2(\"{0}\", ST_CoordDim(\"{0}\") = {1}, TRUE)",
242
                                            column.getName(),
243
                                            sqlgeometrynumdimension(column.getGeometryType(), column.getGeometrySubtype()))
244
                            );
245
                        } else {
246
                            builder.append(
247
                                    MessageFormat.format(
248
                                            " CHECK NVL2(\"{0}\", ST_GeometryTypeCode(\"{0}\") = {1} AND ST_CoordDim(\"{0}\") = {2}, TRUE)",
249
                                            column.getName(),
250
                                            sqlgeometrytype(column.getGeometryType(), column.getGeometrySubtype()),
251
                                            sqlgeometrynumdimension(column.getGeometryType(), column.getGeometrySubtype()))
252
                            );
253
                        }
254
                    } else {
255
                        if ((int) sqlgeometrytype(column.getGeometryType(), column.getGeometrySubtype()) == 0) {
256
                            builder.append(
257
                                    MessageFormat.format(
258
                                            " CHECK NVL2(\"{0}\", ST_CoordDim(\"{0}\") = {1,number,###} AND ST_SRID(\"{0}\") = {2,number,#####}, TRUE)",
259
                                            column.getName(),
260
                                            (int) sqlgeometrynumdimension(column.getGeometryType(), column.getGeometrySubtype()),
261
                                            (int) column.getGeometrySRSId()
262
                                    )
263
                            );
264

    
265
                        } else {
266
                            builder.append(
267
                                    MessageFormat.format(
268
                                            " CHECK NVL2(\"{0}\", ST_GeometryTypeCode(\"{0}\") = {1,number,###} AND ST_CoordDim(\"{0}\") = {2,number,###} AND ST_SRID(\"{0}\") = {3,number,#####}, TRUE)",
269
                                            column.getName(),
270
                                            (int) sqlgeometrytype(column.getGeometryType(), column.getGeometrySubtype()),
271
                                            (int) sqlgeometrynumdimension(column.getGeometryType(), column.getGeometrySubtype()),
272
                                            (int) column.getGeometrySRSId()
273
                                    )
274
                            );
275
                        }
276
                    }
277
                } else {
278
                    if (column.isPrimaryKey()) {
279
                        builder.append(" PRIMARY KEY");
280
                        if( column.isAutomatic() ) {
281
                            builder.append(" AUTO_INCREMENT");
282
                        }
283
                    } else {
284
                        if( column.isAutomatic() ) {
285
                            builder.append(" AUTO_INCREMENT");
286
                        }
287
                        if (column.getDefaultValue() == null || 
288
                                ExpressionUtils.isDynamicText(Objects.toString(column.getDefaultValue(), null))) {
289
                            if (column.allowNulls()) {
290
                                builder.append(" DEFAULT NULL");
291
                            }
292
                        } else {
293
                            switch(column.getType()) {
294
                                case DataTypes.TIMESTAMP:
295
                                    builder.append(" DEFAULT ( TIMESTAMP '");
296
                                    Timestamp dtimestamp = (Timestamp) DataTypeUtils.toTimestamp(column.getDefaultValue());
297
                                    builder.append(MessageFormat.format( "{0,date,yyyy-MM-dd HH:mm:ss.S}",dtimestamp));
298
                                    builder.append("' )");
299
                                    break;
300
                                case DataTypes.TIME:
301
                                    builder.append(" DEFAULT ( TIME '");
302
                                    Time dtime = (Time) DataTypeUtils.toTime(column.getDefaultValue());
303
                                    builder.append(MessageFormat.format( "{0,date,HH:mm:ss}",dtime));
304
                                    builder.append("' )");
305
                                    break;
306
                                case DataTypes.DATE:
307
                                    builder.append(" DEFAULT ( DATE '");
308
                                    java.sql.Date ddate = (java.sql.Date) DataTypeUtils.toDate(column.getDefaultValue());
309
                                    builder.append(MessageFormat.format( "{0,date,yyyy-MM-dd}",ddate));
310
                                    builder.append("' )");
311
                                    break;
312
                                default:
313
                                    builder.append(" DEFAULT '");
314
                                    builder.append(Objects.toString(column.getDefaultValue(),""));
315
                                    builder.append("'");
316
                            }
317
                        }
318
                    }
319
                }
320
                if (!column.allowNulls()) {
321
                    builder.append(" NOT NULL");
322
                }
323
            }
324
            builder.append(" )");
325
            sqls.add(builder.toString());
326
            return sqls;
327
        }
328
    }
329

    
330
    public class H2SpatialSelectBuilderBase extends SelectBuilderBase {
331
        
332
        @Override
333
        public String toString(Formatter formatter) {
334
            StringBuilder builder = new StringBuilder();
335
            if( !isValid(builder) ) {
336
                throw new IllegalStateException(builder.toString());
337
            }
338
            builder.append("SELECT ");
339
            if( this.distinct ) {
340
                builder.append("DISTINCT ");
341
            }
342
            boolean first = true;
343
            for (SelectColumnBuilder column : columns) {
344
                if (first) {
345
                    first = false;
346
                } else {
347
                    builder.append(", ");
348
                }
349
                builder.append(column.toString(formatter));
350
            }
351

    
352
            if ( this.has_from() ) {
353
                builder.append(" FROM ");
354
                builder.append(this.from.toString(formatter));
355
            }
356
            if ( this.has_where() ) {
357
                builder.append(" WHERE ");
358
                builder.append(this.where.toString(formatter));
359
            }
360
            if( this.has_group_by() ) {
361
                builder.append(" GROUP BY ");
362
                builder.append(this.groupColumn.get(0).toString(formatter));
363
                for (int i = 1; i < groupColumn.size(); i++) {
364
                    builder.append(", ");
365
                    builder.append(this.groupColumn.get(i).toString(formatter));
366
                }
367
            }
368
            if( this.has_order_by() ) {
369
                builder.append(" ORDER BY ");
370
                first = true;
371
                for (OrderByBuilder item : this.order_by) {
372
                    if (first) {
373
                        first = false;
374
                    } else {
375
                        builder.append(", ");
376
                    }
377
                    builder.append(item.toString(formatter));                    
378
                }   
379
            }
380
            
381
            if ( this.has_limit() && this.has_offset() ) {
382
                builder.append(" LIMIT ");
383
                builder.append(this.limit);
384
                builder.append(" OFFSET ");
385
                builder.append(this.offset);
386
                
387
            } else if ( this.has_limit()) {
388
                builder.append(" LIMIT ");
389
                builder.append(this.limit);
390

    
391
            } else if ( this.has_offset() ) {
392
                builder.append(" LIMIT -1 OFFSET ");
393
                builder.append(this.offset);    
394
            }
395
            return builder.toString();
396

    
397
        }
398
    }
399

    
400
    @Override
401
    public Object sqlgeometrydimension(int type, int subtype) {
402
        //'XY' or 2: 2D points, identified by X and Y coordinates
403
        //'XYM': 2D points, identified by X and Y coordinates. Each point stores an M-value (measure) as well
404
        //'XYZ' or 3: 3D points, identified by X, Y and Z coordinates
405
        //'XYZM' or 4: 3D points, identified by X, Y and Z coordinates. Each point stores an M-value (measure) as well
406
        switch(subtype) {
407
            case Geometry.SUBTYPES.GEOM2D:
408
            default:
409
                return "XY";
410
            case Geometry.SUBTYPES.GEOM2DM:
411
                return "XYM";
412
            case Geometry.SUBTYPES.GEOM3D:
413
                return "XYZ";
414
            case Geometry.SUBTYPES.GEOM3DM:
415
                return "XYZM";
416
        }
417
    }
418

    
419
    @Override
420
    public String sqltype(int type, int size, int precision, int scale, int geomtype, int geomSubtype) {
421
        if( type!=DataTypes.GEOMETRY ) {
422
            return super.sqltype(type, size, precision, scale, geomtype, geomSubtype);
423
        }
424
        return "GEOMETRY("+sqlgeometrytype(geomtype, geomSubtype)+")";
425
    }
426
    
427
    @Override
428
    public Object sqlgeometrytype(int geomtype, int geomsubtype) {
429
        //
430
        // https://github.com/orbisgis/h2gis/wiki/1.-Spatial-data#geometry-columns-view
431
        //
432
        switch(geomtype) {
433
        case Geometry.TYPES.POINT:
434
            return 1; 
435
        case Geometry.TYPES.MULTIPOINT:
436
            return 4; 
437
        case Geometry.TYPES.LINE:
438
            return 2; 
439
        case Geometry.TYPES.MULTILINE:
440
            return 5; 
441
        case Geometry.TYPES.POLYGON:
442
            return 3; 
443
        case Geometry.TYPES.MULTIPOLYGON:
444
            return 6;
445
        case Geometry.TYPES.GEOMETRY:
446
        default:
447
            return 0; // "GEOMETRY";
448
        }
449
    }
450
    
451
    public Object sqlgeometrynumdimension(int type, int subtype) {
452
        int dimensions=2;
453
        switch(subtype) {
454
        case Geometry.SUBTYPES.GEOM3D:
455
            dimensions = 3;
456
            break;
457
        case Geometry.SUBTYPES.GEOM2D:
458
            dimensions = 2;
459
            break;
460
        case Geometry.SUBTYPES.GEOM2DM:
461
            dimensions = 2; // ??????
462
            break;
463
        case Geometry.SUBTYPES.GEOM3DM:
464
            dimensions = 3; // ??????
465
            break;
466
        }
467
        return dimensions;
468
    }
469
    
470
    @Override
471
    public H2SpatialHelper getHelper() {
472
        return (H2SpatialHelper) this.helper;
473
    }
474
   
475
    @Override
476
    public Disposable setParameters(PreparedStatement st, FeatureProvider feature) {
477
        String name = null;
478
        try {
479
            FeatureType featureType = feature.getType();
480
            List<Object> values = new ArrayList<>();
481
            for (Parameter parameter : this.parameters()) {
482
                if (parameter.is_constant()) {
483
                    values.add(parameter.value());
484
                } else {
485
                    name = parameter.name();
486
                    FeatureAttributeDescriptor descriptor = featureType.getAttributeDescriptor(name);
487
                    switch( descriptor.getType() ) {
488
                    case DataTypes.DATE:
489
                        Date value = (Date)(feature.get(name));
490
                        if( value == null ) {
491
                            values.add(null);
492
                        } else {
493
                            values.add(new java.sql.Date(value.getTime()));
494
                        }
495
                        break;
496
                    case DataTypes.GEOMETRY:
497
                        Geometry geom = this.forceGeometryType(
498
                            descriptor.getGeomType(),
499
                            (Geometry)(feature.get(name))
500
                        );
501
                        values.add(geom);
502
                        break;
503
                    default:
504
                        values.add(feature.get(name));
505
                        break;
506
                    }
507
                }
508
            }
509
            return this.setStatementParameters(st, values, this.geometry_support_type());
510
        } catch (Exception ex) {
511
            String f = "unknow";
512
            try {
513
                f = feature.toString();
514
            } catch (Exception ex2) {
515
                // Do nothing
516
            }
517
            throw new RuntimeException("Can't set parameters to prepared statement from the feature (" + f + ")", ex);
518
        }
519
    }
520

    
521
    @Override
522
    protected AlterTableBuilder createAlterTableBuilder() {
523
        return new H2SpatialAlterTableBuilderBase(this);
524
    }
525
            
526
    @Override
527
    public TableNameBuilder createTableNameBuilder() {
528
        return new H2SpatialTableNameBuilderBase();
529
    }
530
    
531
    @Override
532
    protected CreateTableBuilder createCreateTableBuilder() {
533
        return new H2SpatialCreateTableBuilder();
534
    }
535

    
536
    @Override
537
    public SelectBuilder createSelectBuilder() {
538
        return new H2SpatialSelectBuilderBase();
539
    }
540

    
541
    @Override
542
    protected CreateIndexBuilder createCreateIndexBuilder() {
543
        return new H2SpatialCreateIndexBuilder();
544
    }
545

    
546
    @Override
547
    @SuppressWarnings("Convert2Lambda")
548
    public Disposable setStatementParameters(
549
        PreparedStatement st, 
550
        List values,
551
        List<Integer> types, //Can be null
552
        GeometryExpressionBuilderHelper.GeometrySupportType geometrySupportType) throws SQLException {
553
        
554
        if (values == null) {
555
            return new Disposable() {
556
                @Override
557
                public void dispose() {
558
                }
559
            };
560
        }
561
        if( LOGGER.isDebugEnabled() ) {
562
            debug_setStatementParameters(st, values, types, geometrySupportType);
563
        }
564
        byte[] bytes;
565
        int columnIndex = 1;
566
        try {
567
            for (Object value : values) {
568
                if (value instanceof Geometry) {
569
                    switch(geometrySupportType) {
570
                        case WKT:
571
                            value = ((Geometry) value).convertToWKT();
572
                            st.setObject(columnIndex, value);
573
                            break;
574
                        case NATIVE:
575
                        case WKB: 
576
                            bytes = toWKB((Geometry) value);
577
                            st.setBytes(columnIndex, bytes);
578
                            break;
579
                        case EWKB:
580
                            bytes = ((Geometry) value).convertToEWKB();
581
                            st.setBytes(columnIndex, bytes);
582
                            break;
583
                    }
584
                } else {
585
                    if(types == null){
586
                        st.setObject(columnIndex, value);
587
                    } else {
588
                        setStatementValue(st, columnIndex, types.get(columnIndex-1), value);
589
                    }
590
                        
591
                }
592
                columnIndex++;
593
            }
594
            return new Disposable() {
595
                @Override
596
                public void dispose() {
597
                }
598
            };
599
        } catch(Exception ex) {
600
            throw new SQLException("Can't set values for the prepared statement.", ex);
601
        }        
602
    }
603
    
604
    private byte[] toWKB(Geometry geom) throws Exception {
605
        GeometryType geomtype = geom.getGeometryType();
606
        if( !geomtype.hasM() && !geomtype.hasZ() ) {
607
            return geom.convertToWKB();
608
        }
609
        com.vividsolutions.jts.geom.Geometry  geom_jts = (com.vividsolutions.jts.geom.Geometry) geom.convertTo("jts");
610
        IProjection proj = geom.getProjection();
611
        if( proj != null ) {
612
            geom_jts.setSRID((int) this.srs_id(proj));
613
        }
614
        com.vividsolutions.jts.io.WKBWriter writer = new com.vividsolutions.jts.io.WKBWriter(geomtype.hasZ()?3:2,true);
615
        byte[] bytes = writer.write(geom_jts);
616
        return bytes;
617
    }
618

    
619
    @Override
620
    public int getMaxRecomendedSQLLength() {
621
        return 10240;
622
    }
623
    
624
}