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.jdbc / src / main / java / org / gvsig / fmap / dal / store / jdbc2 / spi / JDBCSQLBuilderBase.java @ 47779

History | View | Annotate | Download (19.7 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2020 gvSIG Association.
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 3
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24
package org.gvsig.fmap.dal.store.jdbc2.spi;
25

    
26
import java.math.BigDecimal;
27
import java.sql.Connection;
28
import java.sql.PreparedStatement;
29
import java.sql.SQLException;
30
import java.sql.Time;
31
import java.sql.Timestamp;
32
import java.util.ArrayList;
33
import java.util.Date;
34
import java.util.List;
35
import java.util.Objects;
36
import org.cresques.cts.IProjection;
37
import org.gvsig.expressionevaluator.ExpressionBuilder.Parameter;
38
import org.gvsig.expressionevaluator.GeometryExpressionBuilderHelper.GeometrySupportType;
39
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
40
import org.gvsig.fmap.dal.feature.FeatureReference;
41
import org.gvsig.fmap.dal.feature.FeatureType;
42
import org.gvsig.fmap.dal.feature.spi.FeatureProvider;
43
import org.gvsig.fmap.dal.feature.spi.FeatureReferenceProviderServices;
44
import org.gvsig.fmap.dal.feature.spi.SQLBuilderBase;
45
import org.gvsig.fmap.dal.store.jdbc2.JDBCConnection;
46
import org.gvsig.fmap.dal.store.jdbc2.JDBCHelper;
47
import org.gvsig.fmap.dal.store.jdbc2.JDBCUtils;
48
import org.gvsig.fmap.geom.Geometry;
49
import org.gvsig.fmap.geom.GeometryLocator;
50
import org.gvsig.fmap.geom.GeometryManager;
51
import org.gvsig.fmap.geom.aggregate.MultiLine;
52
import org.gvsig.fmap.geom.aggregate.MultiPoint;
53
import org.gvsig.fmap.geom.aggregate.MultiPolygon;
54
import org.gvsig.fmap.geom.exception.CreateGeometryException;
55
import org.gvsig.fmap.geom.primitive.Primitive;
56
import org.gvsig.fmap.geom.type.GeometryType;
57
import org.gvsig.tools.ToolsLocator;
58
import org.gvsig.tools.dataTypes.DataType;
59
import org.gvsig.tools.dataTypes.DataTypes;
60
import org.gvsig.tools.dataTypes.DataTypesManager;
61
import org.gvsig.tools.dispose.Disposable;
62

    
63
@SuppressWarnings("UseSpecificCatch")
64
public class JDBCSQLBuilderBase extends SQLBuilderBase {
65

    
66
    private GeometryManager geometryManager = null;
67
    protected final JDBCHelper helper;
68
    
69
    public JDBCSQLBuilderBase(JDBCHelper helper) {
70
        super();
71
        this.helper = helper;
72
    }
73
    
74
    public JDBCHelper getHelper() {
75
        return helper;
76
    }
77
    
78
    protected GeometryManager getGeometryManager() {
79
        if (this.geometryManager == null) {
80
            this.geometryManager = GeometryLocator.getGeometryManager();
81
        }
82
        return this.geometryManager;
83
    }
84
    
85
    @Override
86
    public Object srs_id(IProjection projection) {
87
        JDBCConnection conn = null;
88
        try {
89
            conn = this.helper.getConnection();
90
            SRSSolver solver = this.helper.getSRSSolver();
91
            Object srscode = solver.getDatabaseCode(conn, projection);
92
//            logger.debug("database code srs {}, type {}, srssolver {}.", 
93
//                new Object[] { 
94
//                    srscode, 
95
//                    srscode==null? "null":srscode.getClass().getSimpleName(), 
96
//                    solver
97
//                }
98
//            );
99
            return srscode;
100
        } catch (Exception ex) {
101
            throw new RuntimeException("Can't locate database code for SRS '"+projection.getAbrev()+"'.", ex);
102
        } finally {
103
            conn.closeQuietly();
104
        }
105
    }
106
    
107
    public void setParameters(PreparedStatement st) {
108
        try {
109
            int columnIndex = 1;
110
            for (Parameter parameter : this.parameters()) {
111
                st.setObject(columnIndex++, parameter.value());
112
            }
113
        } catch (Exception ex) {
114
            String p = "unknow";
115
            try {
116
                p =  this.parameters().toString();
117
            } catch (Exception ex2) {
118
                // Do nothing
119
            }
120
            throw new RuntimeException("Can't set parameters to prepared statement from parameters (" + p + ")", ex);
121
        }
122
    }
123

    
124
    public List<Object> getParameters(FeatureProvider feature) {
125
        return getParameters(feature, null);
126
    }
127
    public List<Object> getParameters(FeatureProvider feature, List<Integer> types) {
128
        try {
129
            DataTypesManager dataTypesManager = ToolsLocator.getDataTypesManager();
130
            FeatureType type = feature.getType();
131
            List<Object> values = new ArrayList<>();
132
            Object value;
133
            for (Parameter parameter : this.parameters()) {
134
                if (parameter.is_constant()) {
135
                    value = parameter.value();
136
                    values.add(value);
137
                    if(types != null) {
138
                        if (value == null) {
139
                            types.add(org.gvsig.fmap.dal.DataTypes.OBJECT);
140
                        } else {
141
                            DataType dataType = dataTypesManager.getDataType(value.getClass());
142
                            types.add(dataType.getType());
143
                        }
144
                    }
145
                    
146
                } else {
147
                    String name = parameter.name();
148
                    value = feature.get(name);
149
                    FeatureAttributeDescriptor attrDesc = type.getAttributeDescriptor(name);
150
                    switch( attrDesc.getType() ) {
151
                    case org.gvsig.fmap.dal.DataTypes.DATE:
152
                        if( value == null ) {
153
                            values.add(null);
154
                        } else {
155
                            values.add(new java.sql.Date(((Date)value).getTime()));
156
                        }
157
                        if (types != null) {
158
                            types.add(org.gvsig.fmap.dal.DataTypes.DATE);
159
                        }
160
                        
161
                        break;
162
                    case org.gvsig.fmap.dal.DataTypes.GEOMETRY:
163
                        Geometry geom = this.forceGeometryType(
164
                            attrDesc.getGeomType(),
165
                            (Geometry)value
166
                        );
167
                        values.add(geom);
168
                        if (types != null) {
169
                            types.add(org.gvsig.fmap.dal.DataTypes.GEOMETRY);
170
                        }
171
                        break;
172
                    default:
173
                        values.add(value);
174
                        if (types != null) {
175
                            types.add(attrDesc.getDataType().getType());
176
                        }
177

    
178
                        break;
179
                    }
180
                }
181
            }
182
            return  values;
183
        } catch (Exception ex) {
184
            String f = "unknow";
185
            try {
186
                f = feature.toString();
187
            } catch (Exception ex2) {
188
                // Do nothing
189
            }
190
            throw new RuntimeException("Can't get parameters to prepared statement from the feature (" + f + ")", ex);
191
        }
192
    }
193

    
194
    public Disposable setParameters(PreparedStatement st, FeatureProvider feature) {
195
        try {
196
            List<Integer> types = new ArrayList<>();
197
            
198
            List<Object> values = this.getParameters(feature, types);
199
            return this.setStatementParameters(st, values, types, this.geometry_support_type());
200
        } catch (Exception ex) {
201
            String f = "unknow";
202
            try {
203
                f = feature.toString();
204
            } catch (Exception ex2) {
205
                // Do nothing
206
            }
207
            throw new RuntimeException("Can't set parameters to prepared statement from the feature (" + f + ")", ex);
208
        }
209
    }
210
    
211
    protected Geometry forceGeometryType(GeometryType geomtype, Geometry geom) throws CreateGeometryException {
212
        if( geom == null ) {
213
            return null;
214
        }
215
        switch( geomtype.getType() ) {
216
        case Geometry.TYPES.MULTIPOLYGON:
217
            if( geom.getType()==Geometry.TYPES.POLYGON ) {
218
                MultiPolygon x = getGeometryManager().createMultiPolygon(geomtype.getSubType());
219
                x.addPrimitive((Primitive) geom);
220
                geom = x;
221
            }
222
            break;
223
        case Geometry.TYPES.MULTILINE:
224
            if( geom.getType()==Geometry.TYPES.LINE ) {
225
                MultiLine x = getGeometryManager().createMultiLine(geomtype.getSubType());
226
                x.addPrimitive((Primitive) geom);
227
                geom = x;
228
            }
229
            break;
230
        case Geometry.TYPES.MULTIPOINT:
231
            if( geom.getType()==Geometry.TYPES.POINT ) {
232
                MultiLine x = getGeometryManager().createMultiLine(geomtype.getSubType());
233
                x.addPrimitive((Primitive) geom);
234
                geom = x;
235
            }
236
            break;
237
        case Geometry.TYPES.POLYGON:
238
            if( geom.getType()==Geometry.TYPES.MULTIPOLYGON ) {
239
                MultiPolygon x = (MultiPolygon) geom;
240
                if( x.getPrimitivesNumber()==1 ) {
241
                    geom = x.getPrimitiveAt(0);
242
                }
243
            }
244
            break;
245
        case Geometry.TYPES.LINE:
246
            if( geom.getType()==Geometry.TYPES.MULTILINE ) {
247
                MultiLine x = (MultiLine) geom;
248
                if( x.getPrimitivesNumber()==1 ) {
249
                    geom = x.getPrimitiveAt(0);
250
                }
251
            }
252
            break;
253
        case Geometry.TYPES.POINT:
254
            if( geom.getType()==Geometry.TYPES.MULTIPOINT ) {
255
                MultiPoint x = (MultiPoint) geom;
256
                if( x.getPrimitivesNumber()==1 ) {
257
                    geom = x.getPrimitiveAt(0);
258
                }
259
            }
260
        }
261
        return geom;
262
    }
263
    
264
    public Disposable setParameters(PreparedStatement st, FeatureReference reference) {
265
        try {
266
            
267
            List<Object> values = new ArrayList<>();
268
            for (Parameter parameter : this.parameters()) {
269
                if (parameter.is_constant()) {
270
                    values.add(parameter.value());
271
                } else {
272
                    String name = parameter.name();
273
                    values.add(((FeatureReferenceProviderServices)reference).getKeyValue(name));
274
                }
275
            }
276
            return this.setStatementParameters(st, values, null, this.geometry_support_type());
277
        } catch (Exception ex) {
278
            String f = "unknow";
279
            try {
280
                f = reference.toString();
281
            } catch (Exception ex2) {
282
                // Do nothing
283
            }
284
            throw new RuntimeException("Can't set parameters to prepared statement from the feature (" + f + ")", ex);
285
        }
286
    }
287

    
288
    public Disposable setStatementParameters(
289
        PreparedStatement st, 
290
        List values,
291
        GeometrySupportType geometrySupportType) throws SQLException {
292
        
293
        return setStatementParameters(st, values, null, geometrySupportType);
294
    }
295
    
296
    public Disposable setStatementParameters(
297
        PreparedStatement st, 
298
        List values,
299
        List<Integer> types, //Can be null
300
        GeometrySupportType geometrySupportType) throws SQLException {
301
        
302
        if (values == null) {
303
            return new Disposable() {
304
                @Override
305
                public void dispose() {
306
                }
307
            };
308
        }
309
        if( LOGGER.isDebugEnabled() ) {
310
            debug_setStatementParameters(st, values, types, geometrySupportType);
311
        }
312
        byte[] bytes;
313
        int columnIndex = 1;
314
        try {
315
            for (Object value : values) {
316
                if (value instanceof Geometry) {
317
                    switch(geometrySupportType) {
318
                        case WKT:
319
                            value = ((Geometry) value).convertToWKT();
320
                            st.setObject(columnIndex, value);
321
                            break;
322
                        case NATIVE:
323
                            bytes = getNativeBytes(st.getConnection(),(Geometry) value);
324
                            st.setBytes(columnIndex, bytes);
325
                            break;
326
                        case WKB: 
327
                            bytes = ((Geometry) value).convertToWKB();
328
                            st.setBytes(columnIndex, bytes);
329
                            break;
330
                        case EWKB:
331
                            bytes = ((Geometry) value).convertToEWKB();
332
                            st.setBytes(columnIndex, bytes);
333
                            break;
334
                    }
335
                } else {
336
                    if(types == null){
337
                        st.setObject(columnIndex, value);
338
                    } else {
339
                        setStatementValue(st, columnIndex, types.get(columnIndex-1), value);
340
                    }
341
                        
342
                }
343
                columnIndex++;
344
            }
345
            return new Disposable() {
346
                @Override
347
                public void dispose() {
348
                }
349
            };
350
        } catch(Exception ex) {
351
            throw new SQLException("Can't set values for the prepared statement.", ex);
352
        }        
353
    }
354
    
355
    protected byte[] getNativeBytes(Connection conn, Geometry geometry) throws Exception {
356
        byte[] bytes = geometry.convertToWKB();
357
        return bytes;
358
    }
359

    
360
    protected void debug_setStatementParameters(
361
        PreparedStatement st, 
362
        List values,
363
        List<Integer> types, //Can be null
364
        GeometrySupportType geometrySupportType) throws SQLException {
365
        
366
        StringBuilder debug = new StringBuilder();
367
        debug.append("[");
368
        debug.append(JDBCUtils.getConnId(st));
369
        debug.append("] st.set(");
370
        try {
371
            byte[] bytes;
372
            int columnIndex = 1;
373
            for (Object value : values) {
374
                if (value instanceof Geometry) {
375
                    switch(geometrySupportType) {
376
                        case WKT:
377
                            value = ((Geometry) value).convertToWKT();
378
                            debug.append("/*");
379
                            debug.append(columnIndex);
380
                            debug.append("*/ ");
381
                            debug.append(as_string(value));
382
                            debug.append(", ");
383
                            break;
384
                        case NATIVE:
385
                        case WKB: 
386
                            bytes = ((Geometry) value).convertToWKB();
387
                            debug.append("/*");
388
                            debug.append(columnIndex);
389
                            debug.append("*/ ");
390
                            debug.append(as_string(bytes));
391
                            debug.append(", ");
392
                            break;
393
                        case EWKB:
394
                            bytes = ((Geometry) value).convertToEWKB();
395
                            debug.append("/*");
396
                            debug.append(columnIndex);
397
                            debug.append("*/ ");
398
                            debug.append(as_string(bytes));
399
                            debug.append(", ");
400
                            break;
401
                    }
402
                } else {
403
                    debug.append("/*");
404
                    debug.append(columnIndex);
405
                    debug.append("*/ ");
406
                    if( value instanceof String ) {
407
                        debug.append(as_string(value));
408
                    } else if( value instanceof Boolean ) {
409
                        debug.append( ((Boolean)value)? constant_true:constant_false );
410
                    } else {
411
                        debug.append(value);
412
                    }
413
                    debug.append(", ");
414
                }
415
                columnIndex++;
416
            }
417
            debug.append(")");
418
            LOGGER.debug(debug.toString());
419
        } catch(Exception ex) {
420
        }        
421
    }
422

    
423
    protected void setStatementValue(PreparedStatement st, int columnIndex, int type, Object value) throws SQLException {
424
        switch (type){
425
            case DataTypes.BOOLEAN:
426
                if(value == null){
427
                    st.setNull(columnIndex, java.sql.Types.BIT);
428
                } else {
429
                    st.setBoolean(columnIndex, (boolean) value);
430
                }
431
                break;
432
            case DataTypes.INTEGER:
433
                if(value == null){
434
                    st.setNull(columnIndex, java.sql.Types.INTEGER);
435
                } else {
436
                    st.setInt(columnIndex, (int) value);
437
                }
438
                break;
439
            case DataTypes.BYTE:
440
                if(value == null){
441
                    st.setNull(columnIndex, java.sql.Types.TINYINT);
442
                } else {
443
                    st.setByte(columnIndex, (byte) value);
444
                }
445
                break;
446
            case DataTypes.LONG:
447
                if(value == null){
448
                    st.setNull(columnIndex, java.sql.Types.BIGINT);
449
                } else {
450
                    st.setLong(columnIndex, (long) value);
451
                }
452
                break;
453
            case DataTypes.FLOAT:
454
                if(value == null){
455
                    st.setNull(columnIndex, java.sql.Types.REAL);
456
                } else {
457
                    st.setFloat(columnIndex, (float) value);
458
                }
459
                break;
460
            case DataTypes.DOUBLE:
461
                if(value == null){
462
                    st.setNull(columnIndex, java.sql.Types.DOUBLE);
463
                } else {
464
                    st.setDouble(columnIndex, (double) value);
465
                }
466
                break;
467
            case DataTypes.DECIMAL:
468
                if(value == null){
469
                    st.setNull(columnIndex, java.sql.Types.DECIMAL);
470
                } else {
471
                    st.setBigDecimal(columnIndex, (BigDecimal) value);
472
                }
473
                break;
474
            case DataTypes.URL:
475
            case DataTypes.URI:
476
            case DataTypes.FILE:
477
                value = Objects.toString(value, null);
478
            case DataTypes.STRING:
479
                if(value == null){
480
                    st.setNull(columnIndex, java.sql.Types.VARCHAR);
481
                } else {
482
                    st.setString(columnIndex, (String) value);
483
                }
484
                break;
485
            case DataTypes.TIMESTAMP:
486
                if(value == null){
487
                    st.setNull(columnIndex, java.sql.Types.TIMESTAMP);
488
                } else {
489
                    st.setTimestamp(columnIndex, (Timestamp) value);
490
                }
491
                break;
492
            case DataTypes.TIME:
493
                if(value == null){
494
                    st.setNull(columnIndex, java.sql.Types.TIME);
495
                } else {
496
                    st.setTime(columnIndex, (Time) value);
497
                }
498
                break;
499
            case DataTypes.DATE:
500
                if(value == null){
501
                    st.setNull(columnIndex, java.sql.Types.DATE);
502
                } else {
503
                    st.setDate(columnIndex, (java.sql.Date)value);
504
                }
505
                break;
506
            case DataTypes.BYTEARRAY:
507
                if(value == null){
508
                    st.setNull(columnIndex, java.sql.Types.BINARY);
509
                } else {
510
                    st.setBytes(columnIndex, (byte[]) value);
511
                }
512
                break;
513
            default:
514
                st.setObject(columnIndex, value);
515
                LOGGER.debug("Attention, using a statement.setObject");
516
        }
517
    }
518
}