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

History | View | Annotate | Download (19.5 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.JDBCHelper;
46
import org.gvsig.fmap.dal.store.jdbc2.JDBCUtils;
47
import org.gvsig.fmap.geom.Geometry;
48
import org.gvsig.fmap.geom.GeometryLocator;
49
import org.gvsig.fmap.geom.GeometryManager;
50
import org.gvsig.fmap.geom.aggregate.MultiLine;
51
import org.gvsig.fmap.geom.aggregate.MultiPoint;
52
import org.gvsig.fmap.geom.aggregate.MultiPolygon;
53
import org.gvsig.fmap.geom.exception.CreateGeometryException;
54
import org.gvsig.fmap.geom.primitive.Primitive;
55
import org.gvsig.fmap.geom.type.GeometryType;
56
import org.gvsig.tools.ToolsLocator;
57
import org.gvsig.tools.dataTypes.DataType;
58
import org.gvsig.tools.dataTypes.DataTypes;
59
import org.gvsig.tools.dataTypes.DataTypesManager;
60
import org.gvsig.tools.dispose.Disposable;
61

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

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

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

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

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

    
293
    public Disposable setStatementParameters(
294
        PreparedStatement st, 
295
        List values,
296
        GeometrySupportType geometrySupportType) throws SQLException {
297
        
298
        return setStatementParameters(st, values, null, geometrySupportType);
299
    }
300
    
301
    public Disposable setStatementParameters(
302
        PreparedStatement st, 
303
        List values,
304
        List<Integer> types, //Can be null
305
        GeometrySupportType geometrySupportType) throws SQLException {
306
        
307
        if (values == null) {
308
            return new Disposable() {
309
                @Override
310
                public void dispose() {
311
                }
312
            };
313
        }
314
        if( LOGGER.isDebugEnabled() ) {
315
            StringBuilder debug = new StringBuilder();
316
            debug.append("[");
317
            debug.append(JDBCUtils.getConnId(st));
318
            debug.append("] st.set(");
319
            try {
320
                byte[] bytes;
321
                int columnIndex = 1;
322
                for (Object value : values) {
323
                    if (value instanceof Geometry) {
324
                        switch(geometrySupportType) {
325
                            case WKT:
326
                                value = ((Geometry) value).convertToWKT();
327
                                debug.append("/*");
328
                                debug.append(columnIndex);
329
                                debug.append("*/ ");
330
                                debug.append(as_string(value));
331
                                debug.append(", ");
332
                                break;
333
                            case NATIVE:
334
                            case WKB: 
335
                                bytes = ((Geometry) value).convertToWKB();
336
                                debug.append("/*");
337
                                debug.append(columnIndex);
338
                                debug.append("*/ ");
339
                                debug.append(as_string(bytes));
340
                                debug.append(", ");
341
                                break;
342
                            case EWKB:
343
                                bytes = ((Geometry) value).convertToEWKB();
344
                                debug.append("/*");
345
                                debug.append(columnIndex);
346
                                debug.append("*/ ");
347
                                debug.append(as_string(bytes));
348
                                debug.append(", ");
349
                                break;
350
                        }
351
                    } else {
352
                        debug.append("/*");
353
                        debug.append(columnIndex);
354
                        debug.append("*/ ");
355
                        if( value instanceof String ) {
356
                            debug.append(as_string(value));
357
                        } else if( value instanceof Boolean ) {
358
                            debug.append( ((Boolean)value)? constant_true:constant_false );
359
                        } else {
360
                            debug.append(value);
361
                        }
362
                        debug.append(", ");
363
                    }
364
                    columnIndex++;
365
                }
366
                debug.append(")");
367
                LOGGER.debug(debug.toString());
368
            } catch(Exception ex) {
369
            }        
370
        }
371
        byte[] bytes;
372
        int columnIndex = 1;
373
        try {
374
            for (Object value : values) {
375
                if (value instanceof Geometry) {
376
                    switch(geometrySupportType) {
377
                        case WKT:
378
                            value = ((Geometry) value).convertToWKT();
379
                            st.setObject(columnIndex, value);
380
                            break;
381
                        case NATIVE:
382
                        case WKB: 
383
                            bytes = ((Geometry) value).convertToWKB();
384
                            st.setBytes(columnIndex, bytes);
385
                            break;
386
                        case EWKB:
387
                            bytes = ((Geometry) value).convertToEWKB();
388
                            st.setBytes(columnIndex, bytes);
389
                            break;
390
                    }
391
                } else {
392
                    if(types == null){
393
                        st.setObject(columnIndex, value);
394
                    } else {
395
                        setStatementValue(st, columnIndex, types.get(columnIndex-1), value);
396
                    }
397
                        
398
                }
399
                columnIndex++;
400
            }
401
            return new Disposable() {
402
                @Override
403
                public void dispose() {
404
                }
405
            };
406
        } catch(Exception ex) {
407
            throw new SQLException("Can't set values for the prepared statement.", ex);
408
        }        
409
    }
410

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