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 @ 47606

History | View | Annotate | Download (25.4 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.type.GeometryType;
28
import org.gvsig.tools.dataTypes.DataTypeUtils;
29
import org.gvsig.tools.dispose.Disposable;
30

    
31
public class H2SpatialSQLBuilder extends JDBCSQLBuilderBase {
32

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

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

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

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

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

    
93
    public class H2SpatialTableNameBuilderBase extends TableNameBuilderBase {
94

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

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

    
138
    }
139

    
140
    protected class H2SpatialAlterTableBuilderBase extends AlterTableBuilderBase {
141

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

    
200
    protected class H2SpatialCreateTableBuilder extends CreateTableBuilderBase {
201

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

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

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

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

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

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

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

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

    
396
        }
397
    }
398

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

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

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

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

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

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

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