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

History | View | Annotate | Download (19.4 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 static 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.SQLBuilderBase;
43
import org.gvsig.fmap.dal.feature.spi.FeatureProvider;
44
import org.gvsig.fmap.dal.feature.spi.FeatureReferenceProviderServices;
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
                        case WKB: 
324
                            bytes = ((Geometry) value).convertToWKB();
325
                            st.setBytes(columnIndex, bytes);
326
                            break;
327
                        case EWKB:
328
                            bytes = ((Geometry) value).convertToEWKB();
329
                            st.setBytes(columnIndex, bytes);
330
                            break;
331
                    }
332
                } else {
333
                    if(types == null){
334
                        st.setObject(columnIndex, value);
335
                    } else {
336
                        setStatementValue(st, columnIndex, types.get(columnIndex-1), value);
337
                    }
338
                        
339
                }
340
                columnIndex++;
341
            }
342
            return new Disposable() {
343
                @Override
344
                public void dispose() {
345
                }
346
            };
347
        } catch(Exception ex) {
348
            throw new SQLException("Can't set values for the prepared statement.", ex);
349
        }        
350
    }
351

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

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