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.h2 / src / main / java / org / gvsig / fmap / dal / store / h2 / H2Helper.java @ 41719

History | View | Annotate | Download (34 KB)

1
/* gvSIG. Geographic Information System of the Valencian Government
2
 *
3
 * Copyright (C) 2007-2008 Infrastructures and Transports Department
4
 * of the Valencian Government (CIT)
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 2
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
 */
22

    
23
/*
24
 * AUTHORS (In addition to CIT):
25
 * 2009 IVER T.I   {{Task}}
26
 */
27
/**
28
 *
29
 */
30
package org.gvsig.fmap.dal.store.h2;
31

    
32
import java.sql.Connection;
33
import java.sql.PreparedStatement;
34
import java.sql.ResultSet;
35
import java.sql.ResultSetMetaData;
36
import java.sql.SQLException;
37
import java.sql.Statement;
38
import java.util.ArrayList;
39
import java.util.Comparator;
40
import java.util.Iterator;
41
import java.util.List;
42
import java.util.Map;
43
import java.util.Properties;
44
import java.util.TreeMap;
45
import java.util.TreeSet;
46

    
47
import org.cresques.cts.IProjection;
48
import org.slf4j.Logger;
49
import org.slf4j.LoggerFactory;
50

    
51
import org.gvsig.fmap.crs.CRSFactory;
52
import org.gvsig.fmap.dal.DALLocator;
53
import org.gvsig.fmap.dal.DataTypes;
54
import org.gvsig.fmap.dal.NewDataStoreParameters;
55
import org.gvsig.fmap.dal.exception.DataException;
56
import org.gvsig.fmap.dal.exception.InitializeException;
57
import org.gvsig.fmap.dal.exception.ReadException;
58
import org.gvsig.fmap.dal.exception.WriteException;
59
import org.gvsig.fmap.dal.feature.EditableFeatureAttributeDescriptor;
60
import org.gvsig.fmap.dal.feature.EditableFeatureType;
61
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
62
import org.gvsig.fmap.dal.feature.FeatureType;
63
import org.gvsig.fmap.dal.feature.exception.CreateGeometryException;
64
import org.gvsig.fmap.dal.feature.exception.UnsupportedDataTypeException;
65
import org.gvsig.fmap.dal.resource.ResourceAction;
66
import org.gvsig.fmap.dal.resource.spi.ResourceManagerProviderServices;
67
import org.gvsig.fmap.dal.store.jdbc.ConnectionAction;
68
import org.gvsig.fmap.dal.store.jdbc.JDBCHelper;
69
import org.gvsig.fmap.dal.store.jdbc.JDBCHelperUser;
70
import org.gvsig.fmap.dal.store.jdbc.JDBCNewStoreParameters;
71
import org.gvsig.fmap.dal.store.jdbc.JDBCStoreParameters;
72
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCException;
73
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCExecutePreparedSQLException;
74
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCExecuteSQLException;
75
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCPreparingSQLException;
76
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCSQLException;
77
import org.gvsig.fmap.geom.Geometry;
78
import org.gvsig.fmap.geom.primitive.Envelope;
79
import org.gvsig.tools.ToolsLocator;
80
import org.gvsig.tools.exception.BaseException;
81

    
82
/**
83
 * @author jmvivo
84
 *
85
 */
86
public class H2Helper extends JDBCHelper {
87

    
88
    private static Logger logger = LoggerFactory
89
            .getLogger(H2Helper.class);
90

    
91
    private Map pgSR2SRSID = new TreeMap();
92
    private Map srsID2pgSR = new TreeMap();
93

    
94
    private static Properties beforePostgis13 = null;
95
    private int[] postGISVersion = {0, 0, 0};
96
    private boolean versionSet = false;
97

    
98
    H2Helper(JDBCHelperUser consumer,
99
            H2ConnectionParameters params)
100
            throws InitializeException {
101

    
102
        super(consumer, params);
103
    }
104

    
105
    protected void initializeResource() throws InitializeException {
106
        ResourceManagerProviderServices manager = (ResourceManagerProviderServices) DALLocator
107
                .getResourceManager();
108
        H2Resource resource = (H2Resource) manager
109
                .createAddResource(
110
                        H2Resource.NAME, new Object[]{
111
                            params.getUrl(), params.getHost(),
112
                            params.getPort(), params.getDBName(), params.getUser(),
113
                            params.getPassword(),
114
                            params.getJDBCDriverClassName(),
115
                            ((H2ConnectionParameters) params).getUseSSL()});
116
        this.setResource(resource);
117
    }
118

    
119
    protected String getDefaultSchema(Connection conn)
120
            throws JDBCException {
121
        if ( defaultSchema == null ) {
122
            String sql = "Select current_schema()";
123
            ResultSet rs = null;
124
            Statement st = null;
125
            String schema = null;
126
            try {
127
                st = conn.createStatement();
128
                try {
129
                    rs = JDBCHelper.executeQuery(st, sql);
130
                } catch (java.sql.SQLException e) {
131
                    throw new JDBCExecuteSQLException(sql, e);
132
                }
133
                rs.next();
134
                schema = rs.getString(1);
135
            } catch (java.sql.SQLException e) {
136
                throw new JDBCSQLException(e);
137
            } finally {
138
                try {
139
                    rs.close();
140
                } catch (Exception e) {
141
                    logger.error("Exception clossing resulset", e);
142
                };
143
                try {
144
                    st.close();
145
                } catch (Exception e) {
146
                    logger.error("Exception clossing statement", e);
147
                };
148
                rs = null;
149
                st = null;
150
            }
151
            defaultSchema = schema;
152
        }
153

    
154
        return defaultSchema;
155
    }
156

    
157
    public Envelope getFullEnvelopeOfField(
158
            JDBCStoreParameters storeParams,
159
            String geometryAttrName, Envelope limit)
160
            throws DataException {
161

    
162
        StringBuilder strb = new StringBuilder();
163
        strb.append("Select " + getFunctionName("ST_AsBinary") + "("
164
                + getFunctionName("ST_Extent") + "(");
165
        strb.append(escapeFieldName(geometryAttrName));
166
        strb.append(")) from ");
167

    
168
        if ( storeParams.getSQL() != null
169
                && storeParams.getSQL().trim().length() > 0 ) {
170
            strb.append('(');
171
            strb.append(storeParams.getSQL());
172
            strb.append(") as _subquery_alias_ ");
173
        } else {
174
            strb.append(storeParams.tableID());
175
        }
176

    
177
        if ( limit != null || (storeParams.getBaseFilter() != null
178
                && storeParams.getBaseFilter().trim().length() > 0) ) {
179
            strb.append(" where  ");
180

    
181
            if ( limit != null ) {
182
                strb.append(" ( " + getFunctionName("ST_Intersects") + "("
183
                        + getFunctionName("ST_GeomFromText") + "('");
184
                String workAreaWkt = null;
185
                try {
186
                    workAreaWkt = limit.getGeometry().convertToWKT();
187
                } catch (Exception e) {
188
                    throw new CreateGeometryException(e);
189
                }
190
                strb.append(workAreaWkt);
191
                strb.append("', ");
192

    
193
                IProjection proj = storeParams.getCRS();
194
                int sridInt = this.getProviderSRID(proj);
195
                if ( sridInt == -1 ) {
196
                    throw new CreateGeometryException(
197
                            new Exception("CRS is null or unknown."));
198
                } else {
199
                    strb.append(Integer.toString(sridInt));
200
                }
201
                strb.append("), " + getFunctionName("ST_Envelope") + "(");
202
                strb.append(escapeFieldName(geometryAttrName));
203
                strb.append(")) ) ");
204

    
205
            }
206
            if ( storeParams.getBaseFilter() != null && storeParams.getBaseFilter().trim().length() > 0 ) {
207
                if ( limit != null ) {
208
                    strb.append(" and ");
209
                }
210
                strb.append(" ( ");
211
                strb.append(storeParams.getBaseFilter());
212
                strb.append(" ) ");
213
            }
214

    
215
        }
216

    
217
        final String sql = strb.toString();
218

    
219
        this.open();
220

    
221
        return (Envelope) getResource().execute(new ResourceAction() {
222
            public String toString() {
223
                return "getEnvelope";
224
            }
225

    
226
            public Object run() throws Exception {
227
                ResultSet rs = null;
228
                Statement st = null;
229
                Connection conn = null;
230
                Envelope fullEnvelope = null;
231

    
232
                Envelope emptyEnv
233
                        = geomManager.createEnvelope(Geometry.SUBTYPES.GEOM2D);
234

    
235
                try {
236

    
237
                    conn = getConnection();
238
                    st = conn.createStatement();
239
                    try {
240
                        rs = JDBCHelper.executeQuery(st, sql);
241
                    } catch (java.sql.SQLException e) {
242
                        throw new JDBCExecuteSQLException(sql, e);
243
                    }
244
                    if ( !rs.next() ) {
245
                        return emptyEnv;
246
                    }
247

    
248
                    byte[] data = rs.getBytes(1);
249
                    if ( data == null ) {
250
                        return emptyEnv;
251
                    }
252

    
253
                    Geometry geom = geomManager.createFrom(data);
254

    
255
                    fullEnvelope = geom.getEnvelope();
256

    
257
                    return fullEnvelope;
258
                } catch (java.sql.SQLException e) {
259
                    throw new JDBCSQLException(e);
260
                } catch (BaseException e) {
261
                    throw new ReadException(user.getProviderName(), e);
262
                } finally {
263
                    try {
264
                        rs.close();
265
                    } catch (Exception e) {
266
                    }
267
                    try {
268
                        st.close();
269
                    } catch (Exception e) {
270
                    }
271
                    try {
272
                        conn.close();
273
                    } catch (Exception e) {
274
                    }
275
                    rs = null;
276
                    st = null;
277
                    conn = null;
278
                }
279
            }
280
        });
281
    }
282

    
283
    @Override
284
    protected boolean supportsGeometry() {
285
        return true;
286
    }
287

    
288
    /**
289
     * Fill <code>featureType</code> geometry attributes with SRS and ShapeType
290
     * information stored in the table GEOMETRY_COLUMNS
291
     *
292
     * @param conn
293
     * @param rsMetadata
294
     * @param featureType
295
     * @throws ReadException
296
     */
297
    protected void loadSRS_and_shapeType(Connection conn,
298
            ResultSetMetaData rsMetadata, EditableFeatureType featureType,
299
            String baseSchema, String baseTable)
300
            throws JDBCException {
301

    
302
        Statement st = null;
303
        ResultSet rs = null;
304
        try {
305
            // Sacamos la lista de los attributos geometricos
306
            EditableFeatureAttributeDescriptor attr;
307
            List geoAttrs = new ArrayList();
308

    
309
            Iterator iter = featureType.iterator();
310
            while ( iter.hasNext() ) {
311
                attr = (EditableFeatureAttributeDescriptor) iter.next();
312
                if ( attr.getType() == DataTypes.GEOMETRY ) {
313
                    geoAttrs.add(attr);
314
                }
315
            }
316
            if ( geoAttrs.size() < 1 ) {
317
                return;
318
            }
319

    
320
                        // preparamos un set con las lista de tablas de origen
321
            // de los campos
322
            class TableId {
323

    
324
                public String schema = null;
325
                public String table = null;
326
                public String field = null;
327

    
328
                public void appendToSQL(StringBuilder strb) {
329
                    if ( schema == null || schema.length() == 0 ) {
330
                        strb
331
                                .append("( F_TABLE_SCHEMA = current_schema() AND F_TABLE_NAME = '");
332
                    } else {
333
                        strb.append("( F_TABLE_SCHEMA = '");
334
                        strb.append(schema);
335
                        strb.append("' AND F_TABLE_NAME = '");
336
                    }
337
                    strb.append(table);
338
                    strb.append("' AND F_GEOMETRY_COLUMN = '");
339
                    strb.append(field);
340
                    strb.append("' )");
341
                }
342

    
343
            }
344
            Comparator cmp = new Comparator() {
345
                public int compare(Object arg0, Object arg1) {
346
                    TableId a0 = (TableId) arg0;
347
                    TableId a1 = (TableId) arg1;
348

    
349
                    int aux = a0.field.compareTo(a1.field);
350
                    if ( aux != 0 ) {
351
                        return aux;
352
                    }
353

    
354
                    aux = a0.table.compareTo(a1.table);
355
                    if ( aux != 0 ) {
356
                        return aux;
357
                    }
358

    
359
                    if ( a0.schema == null ) {
360
                        if ( a1.schema == null ) {
361
                            aux = 0;
362
                        } else {
363
                            aux = -1;
364
                        }
365
                    } else {
366
                        if ( a1.schema == null ) {
367
                            aux = -1;
368
                        } else {
369
                            aux = a0.schema.compareTo(a1.schema);
370
                        }
371
                    }
372
                    return aux;
373
                }
374
            };
375
            TreeSet set = new TreeSet(cmp);
376
            TableId tableId;
377
            iter = geoAttrs.iterator();
378
            int rsIndex;
379
            while ( iter.hasNext() ) {
380
                attr = (EditableFeatureAttributeDescriptor) iter.next();
381
                tableId = new TableId();
382
                rsIndex = attr.getIndex() + 1;
383

    
384
                if ( baseSchema == null && baseTable == null ) {
385
                    tableId.schema = rsMetadata.getSchemaName(rsIndex);
386
                    tableId.table = rsMetadata.getTableName(rsIndex);
387
                    tableId.field = rsMetadata.getColumnName(rsIndex);
388
                } else {
389
                    tableId.schema = baseSchema;
390
                    tableId.table = baseTable;
391
                    tableId.field = rsMetadata.getColumnName(rsIndex);
392
                }
393
                if ( tableId.table == null || tableId.table.length() == 0 ) {
394
                                        // Si no tiene tabla origen (viene de algun calculo por ej.)
395
                    // lo saltamos ya que no estara en la tabla GEOMETRY_COLUMNS
396
                    continue;
397
                }
398
                set.add(tableId);
399
            }
400

    
401
            if ( set.size() == 0 ) {
402
                return;
403
            }
404

    
405
            // Preparamos una sql para que nos saque el resultado
406
            StringBuilder strb = new StringBuilder();
407
            strb.append("Select geometry_columns.*,auth_name || ':' || auth_srid as SRSID ");
408
            strb.append("from geometry_columns left join spatial_ref_sys on ");
409
            strb.append("geometry_columns.srid = spatial_ref_sys.srid WHERE ");
410
            iter = set.iterator();
411
            for ( int i = 0; i < set.size() - 1; i++ ) {
412
                tableId = (TableId) iter.next();
413
                tableId.appendToSQL(strb);
414
                strb.append(" OR ");
415
            }
416
            tableId = (TableId) iter.next();
417
            tableId.appendToSQL(strb);
418
            String sql = strb.toString();
419

    
420
            st = conn.createStatement();
421
            try {
422
                rs = JDBCHelper.executeQuery(st, sql);
423
            } catch (SQLException e) {
424
                throw new JDBCExecuteSQLException(sql, e);
425
            }
426
            String srsID;
427
            int pgSrid;
428
            int geometryType;
429
            int geometrySubtype;
430
            String geomTypeStr;
431
            int dimensions;
432
            IProjection srs;
433

    
434
            while ( rs.next() ) {
435
                srsID = rs.getString("SRSID");
436
                pgSrid = rs.getInt("SRID");
437
                geomTypeStr = rs.getString("TYPE").toUpperCase();
438
                geometryType = Geometry.TYPES.GEOMETRY;
439
                if ( geomTypeStr.startsWith("POINT") ) {
440
                    geometryType = Geometry.TYPES.POINT;
441
                } else if ( geomTypeStr.startsWith("LINESTRING") ) {
442
                    geometryType = Geometry.TYPES.CURVE;
443
                } else if ( geomTypeStr.startsWith("POLYGON") ) {
444
                    geometryType = Geometry.TYPES.SURFACE;
445
                } else if ( geomTypeStr.startsWith("MULTIPOINT") ) {
446
                    geometryType = Geometry.TYPES.MULTIPOINT;
447
                } else if ( geomTypeStr.startsWith("MULTILINESTRING") ) {
448
                    geometryType = Geometry.TYPES.MULTICURVE;
449
                } else if ( geomTypeStr.startsWith("MULTIPOLYGON") ) {
450
                    geometryType = Geometry.TYPES.MULTISURFACE;
451
                }
452
                dimensions = rs.getInt("coord_dimension");
453
                geometrySubtype = Geometry.SUBTYPES.GEOM2D;
454
                if ( dimensions > 2 ) {
455
                    if ( dimensions == 3 ) {
456
                        if ( geomTypeStr.endsWith("M") ) {
457
                            geometrySubtype = Geometry.SUBTYPES.GEOM2DM;
458
                        } else {
459
                            geometrySubtype = Geometry.SUBTYPES.GEOM3D;
460
                        }
461

    
462
                    } else {
463
                        geometrySubtype = Geometry.SUBTYPES.GEOM3DM;
464
                    }
465
                }
466
                addToPgSRToSRSID(pgSrid, srsID);
467

    
468
                iter = geoAttrs.iterator();
469
                while ( iter.hasNext() ) {
470
                    attr = (EditableFeatureAttributeDescriptor) iter.next();
471
                    rsIndex = attr.getIndex() + 1;
472
                    if ( !rsMetadata.getColumnName(rsIndex).equals(
473
                            rs.getString("f_geometry_column")) ) {
474
                        continue;
475
                    }
476

    
477
                    if ( baseSchema == null && baseTable == null ) {
478

    
479
                        if ( !rsMetadata.getTableName(rsIndex).equals(
480
                                rs.getString("f_table_name")) ) {
481
                            continue;
482
                        }
483
                        String curSchema = rs.getString("f_table_schema");
484
                        String metaSchema = rsMetadata
485
                                .getSchemaName(rsIndex);
486
                        if ( !metaSchema.equals(curSchema) ) {
487
                            if ( metaSchema.length() == 0
488
                                    && metaSchema == getDefaultSchema(conn) ) {
489
                            } else {
490
                                continue;
491
                            }
492
                        }
493
                    }
494
                    attr.setGeometryType(geometryType);
495
                    attr.setGeometrySubType(geometrySubtype);
496
                    if ( srsID != null && srsID.length() > 0 ) {
497
                        attr.setSRS(CRSFactory.getCRS(srsID));
498
                    }
499
                    iter.remove();
500
                }
501
                iter = geoAttrs.iterator();
502
                while ( iter.hasNext() ) {
503
                    attr = (EditableFeatureAttributeDescriptor) iter.next();
504
                    attr.setSRS(null);
505
                    attr.setGeometryType(Geometry.TYPES.GEOMETRY);
506

    
507
                }
508
            }
509

    
510
        } catch (java.sql.SQLException e) {
511
            throw new JDBCSQLException(e);
512
        } finally {
513
            try {
514
                rs.close();
515
            } catch (Exception e) {
516
            };
517
            try {
518
                st.close();
519
            } catch (Exception e) {
520
            };
521
        }
522

    
523
    }
524

    
525
    public String getSqlColumnTypeDescription(FeatureAttributeDescriptor attr) {
526
        if ( attr.getType() == DataTypes.GEOMETRY ) {
527
            return "geometry";
528
        }
529
        return super.getSqlColumnTypeDescription(attr);
530
    }
531

    
532
    public int getPostgisGeomDimensions(int geometrySubType) {
533
        switch (geometrySubType) {
534
        case Geometry.SUBTYPES.GEOM2D:
535
            return 2;
536
        case Geometry.SUBTYPES.GEOM2DM:
537
        case Geometry.SUBTYPES.GEOM3D:
538
            return 3;
539

    
540
        case Geometry.SUBTYPES.GEOM3DM:
541
            return 4;
542
        default:
543
            throw new UnsupportedDataTypeException(
544
                    ToolsLocator.getDataTypesManager().getTypeName(DataTypes.GEOMETRY),
545
                    DataTypes.GEOMETRY);
546
        }
547
    }
548

    
549
    public String getPostgisGeomType(int geometryType, int geometrySubType) {
550
        String pgGeomType;
551
        switch (geometryType) {
552
        case Geometry.TYPES.GEOMETRY:
553
            pgGeomType = "GEOMETRY";
554
            break;
555
        case Geometry.TYPES.POINT:
556
            pgGeomType = "POINT";
557
            break;
558
        case Geometry.TYPES.CURVE:
559
            pgGeomType = "LINESTRING";
560
            break;
561
        case Geometry.TYPES.SURFACE:
562
            pgGeomType = "POLYGON";
563
            break;
564
        case Geometry.TYPES.MULTIPOINT:
565
            pgGeomType = "MULTIPOINT";
566
            break;
567
        case Geometry.TYPES.MULTICURVE:
568
            pgGeomType = "MULTILINESTRING";
569
            break;
570
        case Geometry.TYPES.MULTISURFACE:
571
            pgGeomType = "MULTIPOLYGON";
572
            break;
573
        default:
574
            logger.warn("Can't determine PostGIS geometry type, use GEOMETRY.");
575
            pgGeomType = "GEOMETRY";
576
        }
577
        if ( geometrySubType == Geometry.SUBTYPES.GEOM2DM
578
                || geometrySubType == Geometry.SUBTYPES.GEOM3DM ) {
579
            pgGeomType = pgGeomType + "M";
580
        } /* else  if (geometrySubType == Geometry.SUBTYPES.GEOM3D) {
581
         throw new UnsupportedGeometryException(geometryType,
582
         geometrySubType);
583
         /
584
         } */
585

    
586
        return pgGeomType;
587
    }
588

    
589
    public int getProviderSRID(String srs) {
590
        if ( srs != null ) {
591
            Integer pgSRID = (Integer) srsID2pgSR.get(srs);
592
            if ( pgSRID != null ) {
593
                return pgSRID.intValue();
594
            }
595

    
596
            return searchpgSRID(srs);
597

    
598
        }
599
        return -1;
600
    }
601

    
602
    public int getProviderSRID(IProjection srs) {
603
        if ( srs != null ) {
604
            Integer pgSRID = (Integer) srsID2pgSR.get(srs.getAbrev());
605
            if ( pgSRID != null ) {
606
                return pgSRID.intValue();
607
            }
608

    
609
            return searchpgSRID(srs);
610

    
611
        }
612
        return -1;
613
    }
614

    
615
    private int searchpgSRID(final IProjection srs) {
616
        if ( srs == null ) {
617
            return -1;
618
        }
619
        return searchpgSRID(srs.getAbrev());
620
    }
621

    
622
    private int searchpgSRID(final String srsID) {
623
        if ( srsID == null ) {
624
            return -1;
625
        }
626

    
627
        ConnectionAction action = new ConnectionAction() {
628

    
629
            public Object action(Connection conn) throws DataException {
630

    
631
                String[] abrev = srsID.split(":");
632
                StringBuilder sqlb = new StringBuilder();
633
                sqlb.append("select srid from spatial_ref_sys where ");
634
                if ( abrev.length > 1 ) {
635
                    sqlb.append("auth_name = ? and ");
636
                }
637
                sqlb.append("auth_srid = ?");
638

    
639
                String sql = sqlb.toString();
640
                PreparedStatement st;
641
                try {
642
                    st = conn.prepareStatement(sql);
643
                } catch (SQLException e) {
644
                    throw new JDBCPreparingSQLException(sql, e);
645
                }
646
                ResultSet rs = null;
647
                try {
648
                    int i = 0;
649
                    if ( abrev.length > 1 ) {
650
                        st.setString(i + 1, abrev[i]);
651
                        i++;
652
                    }
653
                    st.setInt(i + 1, Integer.parseInt(abrev[i]));
654

    
655
                    try {
656
                        rs = JDBCHelper.executeQuery(st, sql);
657

    
658
                    } catch (SQLException e) {
659
                        throw new JDBCExecutePreparedSQLException(sql, abrev, e);
660
                    }
661

    
662
                    if ( !rs.next() ) {
663
                        return null;
664
                    }
665

    
666
                    return new Integer(rs.getInt(1));
667

    
668
                } catch (SQLException e) {
669
                    throw new JDBCSQLException(e);
670
                } finally {
671
                    try {
672
                        rs.close();
673
                    } catch (Exception e) {
674
                    };
675
                    try {
676
                        st.close();
677
                    } catch (Exception e) {
678
                    };
679
                }
680

    
681
            }
682

    
683
        };
684

    
685
        Integer pgSRSID = null;
686
        try {
687
            pgSRSID = (Integer) doConnectionAction(action);
688
        } catch (Exception e) {
689
            logger.error("Excetion searching pgSRS", e);
690
            return -1;
691
        }
692

    
693
        if ( pgSRSID != null ) {
694
            addToPgSRToSRSID(pgSRSID.intValue(), srsID);
695
            return pgSRSID.intValue();
696
        }
697
        return -1;
698

    
699
    }
700

    
701
    private void addToPgSRToSRSID(int pgSRID, String srsId) {
702
        if ( pgSRID < 0 || srsId == null || srsId.length() == 0 ) {
703
            return;
704
        }
705
        Integer pgSRIDInteger = new Integer(pgSRID);
706
        pgSR2SRSID.put(pgSRIDInteger, srsId);
707
        srsID2pgSR.put(srsId, pgSRIDInteger);
708
    }
709

    
710
    public List<String> getSqlGeometyFieldAdd(FeatureAttributeDescriptor attr,
711
            String table, String schema) {
712
                    // SELECT AddGeometryColumn({schema}, {table}, {field}, {srid}(int),
713
        // {geomType}(Str), {dimensions}(int))
714

    
715
                    // gemoType:
716
                    /*
717
         * POINT, LINESTRING, POLYGON, MULTIPOINT, MULTILINESTRING,
718
         * MULTIPOLYGON, GEOMETRYCOLLECTION POINTM, LINESTRINGM, POLYGONM,
719
         * MULTIPOINTM, MULTILINESTRINGM, MULTIPOLYGONM, GEOMETRYCOLLECTIONM
720
         */
721
        List<String> sqls = new ArrayList<String>();
722

    
723
        StringBuilder strb = new StringBuilder();
724
        strb.append("SELECT AddGeometryColumn('");
725
        if ( schema != null && schema.length() > 0 ) {
726
            strb.append(schema);
727
            strb.append("', '");
728
        }
729
        strb.append(table);
730
        strb.append("', '");
731
        strb.append(attr.getName().toLowerCase());
732
        strb.append("', ");
733
        strb.append(getProviderSRID(attr.getSRS()));
734
        strb.append(", '");
735

    
736
        strb.append(getPostgisGeomType(
737
                attr.getGeometryType(),
738
                attr.getGeometrySubType()
739
        )
740
        );
741
        strb.append("', ");
742
        strb.append(getPostgisGeomDimensions(attr.getGeometrySubType()));
743
        strb.append(")");
744

    
745
        sqls.add(strb.toString());
746

    
747
        return sqls;
748
    }
749

    
750
    public String getSqlFieldName(FeatureAttributeDescriptor attribute) {
751
        if ( attribute.getType() == DataTypes.GEOMETRY ) {
752
            return getFunctionName("ST_AsBinary") + "("
753
                    + super.getSqlFieldName(attribute) + ")";
754
        }
755
        return super.getSqlFieldName(attribute);
756
    }
757

    
758
    protected EditableFeatureAttributeDescriptor createAttributeFromJDBC(
759
            EditableFeatureType type, Connection conn,
760
            ResultSetMetaData rsMetadata, int colIndex) throws SQLException {
761
        if ( rsMetadata.getColumnType(colIndex) == java.sql.Types.OTHER ) {
762
            if ( rsMetadata.getColumnTypeName(colIndex).equalsIgnoreCase(
763
                    "geometry") ) {
764
                EditableFeatureAttributeDescriptor attr = type.add(rsMetadata.getColumnName(colIndex),
765
                        DataTypes.GEOMETRY);
766
                // Set default values for geometry type
767
                attr.setGeometryType(Geometry.TYPES.GEOMETRY);
768
                attr.setGeometrySubType(Geometry.SUBTYPES.GEOM2D);
769
                return attr;
770

    
771
            }
772
        }
773

    
774
        return super.createAttributeFromJDBC(type, conn, rsMetadata, colIndex);
775
    }
776

    
777
    public List getAdditionalSqlToCreate(NewDataStoreParameters ndsp,
778
            FeatureType fType) {
779
        FeatureAttributeDescriptor attr;
780
        Iterator iter = fType.iterator();
781
        List result = new ArrayList();
782
        H2NewStoreParameters pgNdsp = (H2NewStoreParameters) ndsp;
783
        while ( iter.hasNext() ) {
784
            attr = (FeatureAttributeDescriptor) iter.next();
785
            if ( attr.getType() == DataTypes.GEOMETRY ) {
786
                result.addAll(getSqlGeometyFieldAdd(attr, pgNdsp.getTable(),
787
                        pgNdsp
788
                        .getSchema()));
789
            }
790
            if ( attr.isIndexed() ) {
791
                result.add(getCreateIndexStatement((JDBCNewStoreParameters) ndsp, attr));
792
            }
793
            if ( attr.isAutomatic() ) {
794
                // A?adimos los GRANT para la secuencia asociada a la tabla.
795
                String table = "\"" + pgNdsp.getSchema() + "\".\"" + pgNdsp.getTable() + "_" + attr.getName() + "_seq\" ";
796
                result.addAll(this.createGrantStatements(pgNdsp, table));
797
            }
798
        }
799

    
800
        return result;
801
    }
802

    
803
    protected String getCreateIndexStatement(JDBCNewStoreParameters params, FeatureAttributeDescriptor attr) {
804
        String indexName = "idx_" + params.getTable() + "_" + attr.getName();
805

    
806
        String statement = "CREATE ";
807
        if ( !attr.allowIndexDuplicateds() ) {
808
            statement += " UNIQUE ";
809
        }
810
        statement += "INDEX \"" + indexName + "\" ";
811
        statement += "ON " + params.tableID() + " ";
812
        if ( attr.getType() == DataTypes.GEOMETRY ) {
813
            statement += " USING GIST ";
814
            statement += "( \"" + attr.getName() + "\")";
815
        } else {
816
            statement += "( \"" + attr.getName() + "\"";
817
            if ( attr.isIndexAscending() ) {
818
                statement += " ASC )";
819
            } else {
820
                statement += " DESC )";
821
            }
822
        }
823
        return statement;
824
    }
825

    
826
    public String getSqlFieldDescription(FeatureAttributeDescriptor attr)
827
            throws DataException {
828
        if ( attr.getType() == DataTypes.GEOMETRY ) {
829
            return null;
830
        }
831
        return super.getSqlFieldDescription(attr);
832
    }
833

    
834
    public boolean allowAutomaticValues() {
835
        return Boolean.TRUE;
836
    }
837

    
838
    public boolean supportOffset() {
839
        return true;
840
    }
841

    
842
    public boolean supportsUnion() {
843
        return true;
844
    }
845

    
846
    public String escapeFieldName(String field) {
847
        /*
848
         if (!reservedWord(field) && 
849
         field.matches("[a-z][a-z0-9_]*")) {
850
         return field;
851
         }
852
         */
853
        String quote = getIdentifierQuoteString();
854
        return quote + field + quote;
855
    }
856

    
857
    protected EditableFeatureAttributeDescriptor createAttributeFromJDBCNativeType(
858
            EditableFeatureType fType, ResultSetMetaData rsMetadata, int colIndex)
859
            throws SQLException {
860

    
861
        EditableFeatureAttributeDescriptor column;
862

    
863
        String nativeType = rsMetadata.getColumnTypeName(colIndex);
864

    
865
        if ( nativeType.startsWith("int") ) {
866
            column = fType.add(rsMetadata.getColumnName(colIndex),
867
                    DataTypes.INT);
868
            column.setAdditionalInfo("SQLType", new Integer(rsMetadata
869
                    .getColumnType(colIndex)));
870
            column.setAdditionalInfo("SQLTypeName", rsMetadata
871
                    .getColumnTypeName(colIndex));
872
            return column;
873
        }
874
        return super.createAttributeFromJDBCNativeType(fType, rsMetadata, colIndex);
875
    }
876

    
877
    public Object dalValueToJDBC(
878
            FeatureAttributeDescriptor attributeDescriptor, Object object)
879
            throws WriteException {
880
        if ( "int2".equals(attributeDescriptor.getAdditionalInfo("SQLTypeName")) ) {
881
            return new Short(String.valueOf(object));
882
        }
883

    
884
        return super.dalValueToJDBC(attributeDescriptor, object);
885
    }
886

    
887
    // =======================================
888
    public String getFunctionName(String newFuncName) {
889

    
890
        if ( !versionSet ) {
891
            postGISVersion = getPostgisVersion();
892
            versionSet = true;
893
        }
894
        return getFunctionNameForVersion(newFuncName, postGISVersion);
895
    }
896

    
897
    private String getFunctionNameForVersion(String newFuncName, int[] pv) {
898

    
899
        if ( newFuncName == null || pv == null ) {
900
            return newFuncName;
901
        }
902

    
903
        if ( pv.length < 2 ) {
904
            // cannot compare
905
            return newFuncName;
906
        }
907

    
908
        if ( pv[0] > 1 ) {
909
            return newFuncName;
910
        }
911

    
912
        if ( pv[0] == 1 && pv[1] >= 3 ) {
913
            return newFuncName;
914
        }
915

    
916
        Properties pp = this.getBeforePostgis13Properties();
917
        String k = newFuncName.toLowerCase();
918
        String v = pp.getProperty(k);
919
        if ( v == null ) {
920
            return newFuncName;
921
        } else {
922
            return v;
923
        }
924
    }
925

    
926
    private int[] getPostgisVersion() {
927

    
928
        String sql = "SELECT PostGIS_Lib_Version()";
929
        ResultSet rs = null;
930
        Statement st = null;
931
        String v = null;
932
        Connection conn = null;
933
        try {
934
            conn = this.getConnection();
935
            st = conn.createStatement();
936
            rs = JDBCHelper.executeQuery(st, sql);
937
            rs.next();
938
            v = rs.getString(1);
939
            if ( v == null ) {
940
                throw new Exception("Returned version is NULL");
941
            }
942
        } catch (Exception exc) {
943
            logger.error("Unable to get Postgis version: " + exc.getMessage(), exc);
944
            return null;
945
        } finally {
946
            try {
947
                rs.close();
948
            } catch (Exception e) {
949
            };
950
            try {
951
                st.close();
952
            } catch (Exception e) {
953
            };
954
            try {
955
                conn.close();
956
            } catch (Exception e) {
957
            };
958
        }
959

    
960
        String[] vv = v.split("\\.");
961
        int[] resp = new int[3];
962
        try {
963
            for ( int i = 0; i < 3; i++ ) {
964
                resp[i] = Integer.parseInt(vv[i]);
965
            }
966
        } catch (Exception exc) {
967
            logger.error("Unable to parse version: " + v, exc);
968
            return null;
969
        }
970
        return resp;
971
    }
972

    
973
    protected Properties getBeforePostgis13Properties() {
974
        if ( beforePostgis13 == null ) {
975

    
976
            beforePostgis13 = new Properties();
977
            // Left side MUST be in lower case
978
            // Right side will be used if Postgis version < 1.3
979
            beforePostgis13.setProperty("st_intersects", "Intersects");
980
            beforePostgis13.setProperty("st_extent", "Extent");
981
            beforePostgis13.setProperty("st_envelope", "Envelope");
982
            beforePostgis13.setProperty("st_asbinary", "AsBinary");
983
            beforePostgis13.setProperty("st_geomfromtext", "GeomFromText");
984
            beforePostgis13.setProperty("st_geomfromwkb", "GeomFromWKB");
985
        }
986
        return beforePostgis13;
987
    }
988

    
989
}