Statistics
| Revision:

root / trunk / org.gvsig.postgresql / org.gvsig.postgresql.provider / src / main / java / org / gvsig / fmap / dal / store / postgresql / PostgreSQLHelper.java @ 64

History | View | Annotate | Download (29.3 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
 */
31
package org.gvsig.fmap.dal.store.postgresql;
32

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

    
48
import org.cresques.cts.IProjection;
49
import org.postgresql.PGResultSetMetaData;
50
import org.slf4j.Logger;
51
import org.slf4j.LoggerFactory;
52

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

    
83
/**
84
 * @author jmvivo
85
 *
86
 */
87
public class PostgreSQLHelper extends JDBCHelper {
88

    
89
        private static Logger logger = LoggerFactory
90
                        .getLogger(PostgreSQLHelper.class);
91

    
92
        private Map pgSR2SRSID = new TreeMap();
93
        private Map srsID2pgSR = new TreeMap();
94
        
95
        private static Properties beforePostgis13 = null;
96
    private int[] postGISVersion = { 0,0,0 };
97
    private boolean versionSet = false;
98

    
99
        PostgreSQLHelper(JDBCHelperUser consumer,
100
                        PostgreSQLConnectionParameters params)
101
                        throws InitializeException {
102

    
103
                super(consumer, params);
104
        }
105

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

    
120

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

    
148
                return defaultSchema;
149
        }
150

    
151
    public Envelope getFullEnvelopeOfField(
152
            JDBCStoreParameters storeParams,
153
            String geometryAttrName, Envelope limit)
154
            throws DataException {
155

    
156
        StringBuilder strb = new StringBuilder();
157
        strb.append("Select " + getFunctionName("ST_AsBinary") + "("
158
                + getFunctionName("ST_Extent") + "(");
159
        strb.append(escapeFieldName(geometryAttrName));
160
        strb.append(")) from ");
161

    
162
        if (storeParams.getSQL() != null
163
                && storeParams.getSQL().trim().length() > 0) {
164
            strb.append('(');
165
            strb.append(storeParams.getSQL());
166
            strb.append(") as _subquery_alias_ ");
167
        } else {
168
            strb.append(storeParams.tableID());
169
        }
170

    
171
        if (limit != null || (storeParams.getBaseFilter() != null
172
                && storeParams.getBaseFilter().trim().length() > 0)) {
173
            strb.append(" where  ");
174

    
175
            if (limit != null) {
176
                strb.append(" ( " + getFunctionName("ST_Intersects") + "("
177
                        + getFunctionName("ST_GeomFromText") + "('");
178
                String workAreaWkt = null;
179
                try {
180
                    workAreaWkt = limit.getGeometry().convertToWKT();
181
                } catch (Exception e) {
182
                    throw new CreateGeometryException(e);
183
                }
184
                strb.append(workAreaWkt);
185
                strb.append("', ");
186

    
187
                IProjection proj = storeParams.getCRS();
188
                int sridInt = this.getProviderSRID(proj);
189
                if (sridInt == -1) {
190
                    throw new CreateGeometryException(
191
                            new Exception("CRS is null or unknown."));
192
                } else {
193
                    strb.append(Integer.toString(sridInt));
194
                }
195
                strb.append("), " + getFunctionName("ST_Envelope") + "(");
196
                strb.append(escapeFieldName(geometryAttrName));
197
                strb.append(")) ) ");
198

    
199
            }
200
            if (storeParams.getBaseFilter() != null && storeParams.getBaseFilter().trim().length() > 0) {
201
                if (limit != null) {
202
                    strb.append(" and ");
203
                }
204
                strb.append(" ( ");
205
                strb.append(storeParams.getBaseFilter());
206
                strb.append(" ) ");
207
            }
208

    
209
        }
210

    
211
        final String sql = strb.toString();
212

    
213
        this.open();
214

    
215
        return (Envelope) getResource().execute(new ResourceAction() {
216
            public String toString() {
217
                return "getEnvelope";
218
            }
219

    
220
            public Object run() throws Exception {
221
                ResultSet rs = null;
222
                Statement st = null;
223
                Connection conn = null;
224
                Envelope fullEnvelope = null;
225

    
226
                Envelope emptyEnv
227
                        = geomManager.createEnvelope(Geometry.SUBTYPES.GEOM2D);
228

    
229
                try {
230

    
231
                    conn = getConnection();
232
                    st = conn.createStatement();
233
                    try {
234
                        rs = JDBCHelper.executeQuery(st, sql);
235
                    } catch (java.sql.SQLException e) {
236
                        throw new JDBCExecuteSQLException(sql, e);
237
                    }
238
                    if (!rs.next()) {
239
                        return emptyEnv;
240
                    }
241

    
242
                    byte[] data = rs.getBytes(1);
243
                    if (data == null) {
244
                        return emptyEnv;
245
                    }
246

    
247
                    Geometry geom = geomManager.createFrom(data);
248

    
249
                    fullEnvelope = geom.getEnvelope();
250

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

    
277
        @Override
278
        protected boolean supportsGeometry() {
279
                return true;
280
        }
281

    
282
        /**
283
         * Fill <code>featureType</code> geometry attributes with SRS and ShapeType
284
         * information stored in the table GEOMETRY_COLUMNS
285
         *
286
         * @param conn
287
         * @param rsMetadata
288
         * @param featureType
289
         * @throws ReadException
290
         */
291
        protected void loadSRS_and_shapeType(Connection conn,
292
                        ResultSetMetaData rsMetadata, EditableFeatureType featureType,
293
                        String baseSchema, String baseTable)
294
                        throws JDBCException {
295

    
296
                Statement st = null;
297
                ResultSet rs = null;
298
                try {
299
                        // Sacamos la lista de los attributos geometricos
300
                        EditableFeatureAttributeDescriptor attr;
301
                        List geoAttrs = new ArrayList();
302

    
303
                        Iterator iter = featureType.iterator();
304
                        while (iter.hasNext()) {
305
                                attr = (EditableFeatureAttributeDescriptor) iter.next();
306
                                if (attr.getType() == DataTypes.GEOMETRY) {
307
                                        geoAttrs.add(attr);
308
                                }
309
                        }
310
                        if (geoAttrs.size() < 1) {
311
                                return;
312
                        }
313

    
314

    
315
                        // preparamos un set con las lista de tablas de origen
316
                        // de los campos
317
                        class TableId {
318
                                public String schema=null;
319
                                public String table=null;
320
                                public String field = null;
321

    
322
                                public void appendToSQL(StringBuilder strb) {
323
                                        if (schema == null || schema.length() == 0) {
324
                                                strb
325
                                                                .append("( F_TABLE_SCHEMA = current_schema() AND F_TABLE_NAME = '");
326
                                        } else {
327
                                                strb.append("( F_TABLE_SCHEMA = '");
328
                                                strb.append(schema);
329
                                                strb.append("' AND F_TABLE_NAME = '");
330
                                        }
331
                                        strb.append(table);
332
                                        strb.append("' AND F_GEOMETRY_COLUMN = '");
333
                                        strb.append(field);
334
                                        strb.append("' )");
335
                                }
336

    
337
                        }
338
                        Comparator cmp = new Comparator(){
339
                                public int compare(Object arg0, Object arg1) {
340
                                        TableId a0 = (TableId) arg0;
341
                                        TableId a1 = (TableId) arg1;
342

    
343
                                        int aux = a0.field.compareTo(a1.field);
344
                                        if (aux != 0) {
345
                                            return aux;
346
                                        }
347

    
348
                                        aux = a0.table.compareTo(a1.table);
349
                    if (aux != 0) {
350
                        return aux;
351
                    }
352
                                        
353
                    if (a0.schema == null) {
354
                        if (a1.schema == null) {
355
                            aux = 0;
356
                        } else {
357
                            aux = -1;
358
                        }
359
                    } else {
360
                        if (a1.schema == null) {
361
                            aux = -1;
362
                        } else {
363
                            aux = a0.schema.compareTo(a1.schema);
364
                        }
365
                    }
366
                                        return aux;
367
                                }
368
                        };
369
                        TreeSet set = new TreeSet(cmp);
370
                        TableId tableId;
371
                        iter = geoAttrs.iterator();
372
                        int rsIndex;
373
                        while (iter.hasNext()) {
374
                                attr = (EditableFeatureAttributeDescriptor) iter.next();
375
                                tableId = new TableId();
376
                                rsIndex = attr.getIndex() + 1;
377

    
378
                                if (baseSchema == null && baseTable == null) {
379
                                        if (rsMetadata instanceof PGResultSetMetaData) {
380
                                                tableId.schema = ((PGResultSetMetaData) rsMetadata)
381
                                                                .getBaseSchemaName(rsIndex);
382
                                                tableId.table = ((PGResultSetMetaData) rsMetadata)
383
                                                                .getBaseTableName(rsIndex);
384
                                                tableId.field = ((PGResultSetMetaData) rsMetadata)
385
                                                                .getBaseColumnName(rsIndex);
386

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

    
405
                        if (set.size() == 0) {
406
                                return;
407
                        }
408

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

    
424

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

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

    
467
                                        } else {
468
                                                geometrySubtype = Geometry.SUBTYPES.GEOM3DM;
469
                                        }
470
                                }
471
                                addToPgSRToSRSID(pgSrid, srsID);
472

    
473

    
474
                                iter = geoAttrs.iterator();
475
                                while (iter.hasNext()) {
476
                                        attr = (EditableFeatureAttributeDescriptor) iter.next();
477
                                        rsIndex = attr.getIndex() + 1;
478
                                        if (!rsMetadata.getColumnName(rsIndex).equals(
479
                                                        rs.getString("f_geometry_column"))) {
480
                                                continue;
481
                                        }
482

    
483
                                        if (baseSchema == null && baseTable == null) {
484

    
485
                                                if (rsMetadata instanceof PGResultSetMetaData) {
486
                                                        if (!((PGResultSetMetaData) rsMetadata)
487
                                                                        .getBaseTableName(rsIndex).equals(
488
                                                                                        rs.getString("f_table_name"))) {
489
                                                                continue;
490
                                                        }
491
                                                        String curSchema = rs.getString("f_table_schema");
492
                                                        String metaSchema = ((PGResultSetMetaData) rsMetadata)
493
                                                                        .getBaseSchemaName(rsIndex);
494
                                                        if (!metaSchema.equals(curSchema)) {
495
                                                                if (metaSchema.length() == 0
496
                                                                                && metaSchema == getDefaultSchema(conn)) {
497
                                                                } else {
498
                                                                        continue;
499
                                                                }
500
                                                        }
501

    
502
                                                } else {
503

    
504
                                                        if (!rsMetadata.getTableName(rsIndex).equals(
505
                                                                        rs.getString("f_table_name"))) {
506
                                                                continue;
507
                                                        }
508
                                                        String curSchema = rs.getString("f_table_schema");
509
                                                        String metaSchema = rsMetadata
510
                                                                        .getSchemaName(rsIndex);
511
                                                        if (!metaSchema.equals(curSchema)) {
512
                                                                if (metaSchema.length() == 0
513
                                                                                && metaSchema == getDefaultSchema(conn)) {
514
                                                                } else {
515
                                                                        continue;
516
                                                                }
517
                                                        }
518
                                                }
519
                                        }
520
                                        attr.setGeometryType(geometryType);
521
                                        attr.setGeometrySubType(geometrySubtype);
522
                                        if (srsID != null && srsID.length() > 0) {
523
                                                attr.setSRS(CRSFactory.getCRS(srsID));
524
                                        }
525
                                        iter.remove();
526
                                }
527
                                iter = geoAttrs.iterator();
528
                                while (iter.hasNext()) {
529
                                        attr = (EditableFeatureAttributeDescriptor) iter.next();
530
                                        attr.setSRS(null);
531
                                        attr.setGeometryType(Geometry.TYPES.GEOMETRY);
532

    
533
                                }
534
                        }
535

    
536
                } catch (java.sql.SQLException e) {
537
                        throw new JDBCSQLException(e);
538
                } finally {
539
                        try {rs.close();} catch (Exception e) {        };
540
                        try {st.close();} catch (Exception e) {        };
541
                }
542

    
543
        }
544

    
545

    
546
        public String getSqlColumnTypeDescription(FeatureAttributeDescriptor attr) {
547
                if (attr.getType() == DataTypes.GEOMETRY) {
548
                        return "geometry";
549
                }
550
                return super.getSqlColumnTypeDescription(attr);
551
        }
552

    
553

    
554
        public int getPostgisGeomDimensions(int geometrySubType) {
555
                switch (geometrySubType) {
556
                case Geometry.SUBTYPES.GEOM2D:
557
                        return 2;
558
                case Geometry.SUBTYPES.GEOM2DM:
559
                case Geometry.SUBTYPES.GEOM3D:
560
                        return 3;
561

    
562
                case Geometry.SUBTYPES.GEOM3DM:
563
                        return 4;
564
                default:
565
                        throw new UnsupportedDataTypeException(
566
                                        ToolsLocator.getDataTypesManager().getTypeName(DataTypes.GEOMETRY),
567
                                        DataTypes.GEOMETRY);
568
                }
569
        }
570

    
571
        public String getPostgisGeomType(int geometryType, int geometrySubType) {
572
                String pgGeomType;
573
                switch (geometryType) {
574
                case Geometry.TYPES.GEOMETRY:
575
                        pgGeomType = "GEOMETRY";
576
                        break;
577
                case Geometry.TYPES.POINT:
578
                        pgGeomType = "POINT";
579
                        break;
580
                case Geometry.TYPES.CURVE:
581
                        pgGeomType = "LINESTRING";
582
                        break;
583
                case Geometry.TYPES.SURFACE:
584
                        pgGeomType = "POLYGON";
585
                        break;
586
                case Geometry.TYPES.MULTIPOINT:
587
                        pgGeomType = "MULTIPOINT";
588
                        break;
589
                case Geometry.TYPES.MULTICURVE:
590
                        pgGeomType = "MULTILINESTRING";
591
                        break;
592
                case Geometry.TYPES.MULTISURFACE:
593
                        pgGeomType = "MULTIPOLYGON";
594
                        break;
595
                default:
596
                    logger.warn("Can't determine PostGIS geometry type, use GEOMETRY.");
597
                    pgGeomType = "GEOMETRY";
598
                }
599
                if (geometrySubType == Geometry.SUBTYPES.GEOM2DM
600
                                || geometrySubType == Geometry.SUBTYPES.GEOM3DM) {
601
                        pgGeomType = pgGeomType + "M";
602
                } /* else  if (geometrySubType == Geometry.SUBTYPES.GEOM3D) {
603
                        throw new UnsupportedGeometryException(geometryType,
604
                                        geometrySubType);
605
                   /
606
                } */
607
                return pgGeomType;
608
        }
609

    
610
        public int getProviderSRID(String srs) {
611
                if (srs != null) {
612
                        Integer pgSRID = (Integer) srsID2pgSR.get(srs);
613
                        if (pgSRID != null) {
614
                                return pgSRID.intValue();
615
                        }
616

    
617
                        return searchpgSRID(srs);
618

    
619
                }
620
                return -1;
621
        }
622

    
623

    
624
        public int getProviderSRID(IProjection srs) {
625
                if (srs != null) {
626
                        Integer pgSRID = (Integer) srsID2pgSR.get(srs.getAbrev());
627
                        if (pgSRID != null) {
628
                                return pgSRID.intValue();
629
                        }
630

    
631
                        return searchpgSRID(srs);
632

    
633
                }
634
                return -1;
635
        }
636

    
637
        private int searchpgSRID(final IProjection srs) {
638
                if (srs == null) {
639
                        return -1;
640
                }
641
                return searchpgSRID(srs.getAbrev());
642
        }
643

    
644
        private int searchpgSRID(final String srsID) {
645
                if (srsID == null) {
646
                        return -1;
647
                }
648

    
649
                ConnectionAction action = new ConnectionAction(){
650

    
651
                        public Object action(Connection conn) throws DataException {
652

    
653
                                String[] abrev = srsID.split(":");
654
                                StringBuilder sqlb = new StringBuilder();
655
                                sqlb.append("select srid from spatial_ref_sys where ");
656
                                if (abrev.length > 1) {
657
                                        sqlb.append("auth_name = ? and ");
658
                                }
659
                                sqlb.append("auth_srid = ?");
660

    
661
                                String sql = sqlb.toString();
662
                                PreparedStatement st;
663
                                try {
664
                                        st = conn.prepareStatement(sql);
665
                                } catch (SQLException e){
666
                                        throw new JDBCPreparingSQLException(sql,e);
667
                                }
668
                                ResultSet rs = null;
669
                                try{
670
                                        int i=0;
671
                                        if (abrev.length > 1){
672
                                                st.setString(i+1, abrev[i]);
673
                                                i++;
674
                                        }
675
                                        st.setInt(i + 1, Integer.parseInt(abrev[i]));
676

    
677
                                        try{
678
                                                rs = JDBCHelper.executeQuery(st,sql); 
679
                                                
680
                                        } catch (SQLException e){
681
                                                throw new JDBCExecutePreparedSQLException(sql, abrev, e);
682
                                        }
683

    
684
                                        if (!rs.next()) {
685
                                                return null;
686
                                        }
687

    
688
                                        return new Integer(rs.getInt(1));
689

    
690
                                } catch (SQLException e){
691
                                        throw new JDBCSQLException(e);
692
                                } finally{
693
                                        try {rs.close(); } catch (Exception e) {};
694
                                        try {st.close(); } catch (Exception e) {};
695
                                }
696

    
697
                        }
698

    
699
                };
700

    
701
                Integer pgSRSID = null;
702
                try {
703
                        pgSRSID = (Integer) doConnectionAction(action);
704
                } catch (Exception e) {
705
                        logger.error("Excetion searching pgSRS", e);
706
                        return -1;
707
                }
708

    
709
                if (pgSRSID != null) {
710
                        addToPgSRToSRSID(pgSRSID.intValue(), srsID);
711
                        return pgSRSID.intValue();
712
                }
713
                return -1;
714

    
715
        }
716

    
717
        private void addToPgSRToSRSID(int pgSRID, String srsId) {
718
                if (pgSRID < 0 || srsId == null || srsId.length() == 0) {
719
                        return;
720
                }
721
                Integer pgSRIDInteger = new Integer(pgSRID);
722
                pgSR2SRSID.put(pgSRIDInteger, srsId);
723
                srsID2pgSR.put(srsId, pgSRIDInteger);
724
        }
725

    
726
        public List<String> getSqlGeometyFieldAdd(FeatureAttributeDescriptor attr,
727
                        String table, String schema) {
728
                // SELECT AddGeometryColumn({schema}, {table}, {field}, {srid}(int),
729
                // {geomType}(Str), {dimensions}(int))
730

    
731
                // gemoType:
732
                /*
733
                 * POINT, LINESTRING, POLYGON, MULTIPOINT, MULTILINESTRING,
734
                 * MULTIPOLYGON, GEOMETRYCOLLECTION POINTM, LINESTRINGM, POLYGONM,
735
                 * MULTIPOINTM, MULTILINESTRINGM, MULTIPOLYGONM, GEOMETRYCOLLECTIONM
736
                 */
737

    
738
                List<String> sqls = new ArrayList<String>();
739

    
740
                StringBuilder strb = new StringBuilder();
741
                strb.append("SELECT AddGeometryColumn('");
742
                if (schema != null && schema.length() > 0) {
743
                        strb.append(schema);
744
                        strb.append("', '");
745
                }
746
                strb.append(table);
747
                strb.append("', '");
748
                strb.append(attr.getName().toLowerCase());
749
                strb.append("', ");
750
                // strb.append("-1");
751
                strb.append(getProviderSRID(attr.getSRS()));
752
                strb.append(", '");
753
                
754
                // ===========================================================================
755
            // TODO Improve this. Keep in mind that MULTIPOLYGON will not accept POLYGON
756
//        strb.append("GEOMETRY");
757
            
758
                strb.append( getPostgisGeomType(
759
                        attr.getGeometryType(), 
760
                        attr
761
                        .getGeometrySubType()
762
                )
763
        );
764
        // ===========================================================================
765
                strb.append("', ");
766
                strb.append(getPostgisGeomDimensions(attr.getGeometrySubType()));
767
                strb.append(")");
768

    
769

    
770
                sqls.add(strb.toString());
771

    
772
                /*ALTER TABLE muni10000_peq_test DROP CONSTRAINT enforce_srid_the_geom;*/
773
                /*
774
                strb = new StringBuilder();
775
                strb.append("Alter table ");
776
                if (schema != null && schema.length() > 0) {
777
                        strb.append(schema);
778
                        strb.append(".");
779
                }
780
                strb.append("f_table_name = '");
781
                strb.append(table);
782
                strb.append("' AND f_geometry_column = '");
783
                strb.append(attr.getName());
784
                strb.append("' AND srid = -1");
785

786

787
                sqls.add(strb.toString());
788
                */
789
                return sqls;
790
        }
791

    
792
        public String getSqlFieldName(FeatureAttributeDescriptor attribute) {
793
                if (attribute.getType() == DataTypes.GEOMETRY) {
794
                        return getFunctionName("ST_AsBinary") + "("
795
                            + super.getSqlFieldName(attribute) + ")";
796
                }
797
                return super.getSqlFieldName(attribute);
798
        }
799

    
800
        protected EditableFeatureAttributeDescriptor createAttributeFromJDBC(
801
                        EditableFeatureType type, Connection conn,
802
                        ResultSetMetaData rsMetadata, int colIndex) throws SQLException {
803
                if (rsMetadata.getColumnType(colIndex) == java.sql.Types.OTHER) {
804
                        if (rsMetadata.getColumnTypeName(colIndex).equalsIgnoreCase(
805
                                        "geometry")) {
806
                                EditableFeatureAttributeDescriptor attr = type.add(rsMetadata.getColumnName(colIndex),
807
                                                DataTypes.GEOMETRY);
808
                                // Set default values for geometry type
809
                                attr.setGeometryType(Geometry.TYPES.GEOMETRY);
810
                                attr.setGeometrySubType(Geometry.SUBTYPES.GEOM2D);
811
                                return attr;
812

    
813
                        }
814
                }
815

    
816
                return super.createAttributeFromJDBC(type, conn, rsMetadata, colIndex);
817
        }
818

    
819
        public List getAdditionalSqlToCreate(NewDataStoreParameters ndsp,
820
                        FeatureType fType) {
821
                FeatureAttributeDescriptor attr;
822
                Iterator iter = fType.iterator();
823
                List result = new ArrayList();
824
                PostgreSQLNewStoreParameters pgNdsp = (PostgreSQLNewStoreParameters) ndsp;
825
                while (iter.hasNext()){
826
                        attr = (FeatureAttributeDescriptor) iter.next();
827
                        if (attr.getType() == DataTypes.GEOMETRY){
828
                                result.addAll(getSqlGeometyFieldAdd(attr, pgNdsp.getTable(),
829
                                                pgNdsp
830
                                                .getSchema()));
831
                        }
832
                }
833

    
834
                return result;
835
        }
836

    
837
        public String getSqlFieldDescription(FeatureAttributeDescriptor attr)
838
                        throws DataException {
839
                if (attr.getType() == DataTypes.GEOMETRY){
840
                        return null;
841
                }
842
                return super.getSqlFieldDescription(attr);
843
        }
844

    
845

    
846
        public boolean allowAutomaticValues() {
847
                return Boolean.TRUE;
848
        }
849

    
850
        public boolean supportOffset() {
851
                return true;
852
        }
853

    
854
        public boolean supportsUnion() {
855
                return true;
856
        }
857
        
858
        public String escapeFieldName(String field) {
859
                /*
860
                if (!reservedWord(field) && 
861
                                field.matches("[a-z][a-z0-9_]*")) {
862
                        return field;
863
                }
864
                */
865
                String quote = getIdentifierQuoteString();
866
                return quote + field + quote;
867
        }
868
        
869
    protected EditableFeatureAttributeDescriptor createAttributeFromJDBCNativeType(
870
        EditableFeatureType fType, ResultSetMetaData rsMetadata, int colIndex)
871
        throws SQLException {
872

    
873
        EditableFeatureAttributeDescriptor column;
874

    
875
        String nativeType = rsMetadata.getColumnTypeName(colIndex);
876

    
877
        if (nativeType.startsWith("int")) {
878
            column = fType.add(rsMetadata.getColumnName(colIndex),
879
                DataTypes.INT);
880
            column.setAdditionalInfo("SQLType", new Integer(rsMetadata
881
                .getColumnType(colIndex)));
882
            column.setAdditionalInfo("SQLTypeName", rsMetadata
883
                .getColumnTypeName(colIndex));
884
            return column;
885
        }
886
        return super.createAttributeFromJDBCNativeType(fType, rsMetadata, colIndex);
887
    }
888

    
889
    public Object dalValueToJDBC(
890
        FeatureAttributeDescriptor attributeDescriptor, Object object)
891
        throws WriteException {
892
           if ("int2".equals(attributeDescriptor.getAdditionalInfo("SQLTypeName"))) {
893
                return new Short(String.valueOf(object));
894
            }
895

    
896
        return super.dalValueToJDBC(attributeDescriptor, object);
897
    }
898
    
899
    // =======================================
900
    
901

    
902
    public String getFunctionName(String newFuncName) {
903
        
904
        if (!versionSet) {
905
            postGISVersion = getPostgisVersion();
906
            versionSet = true;
907
        }
908
        return getFunctionNameForVersion(newFuncName, postGISVersion);
909
    }
910

    
911
    private String getFunctionNameForVersion(String newFuncName, int[] pv) {
912
        
913
        if (newFuncName == null || pv == null) {
914
            return newFuncName;
915
        }
916
        
917
        if (pv.length < 2) {
918
            // cannot compare
919
            return newFuncName;
920
        }
921
        
922
        if (pv[0] > 1) {
923
            return newFuncName;
924
        }
925
        
926
        if (pv[0] == 1 && pv[1] >= 3) {
927
            return newFuncName;
928
        }
929
        
930
        Properties pp = this.getBeforePostgis13Properties();
931
        String k = newFuncName.toLowerCase();
932
        String v = pp.getProperty(k);
933
        if (v == null) {
934
            return newFuncName;
935
        } else {
936
            return v;
937
        }
938
    }
939

    
940

    
941
    private int[] getPostgisVersion() {
942

    
943
        String sql = "SELECT PostGIS_Lib_Version()";
944
        ResultSet rs = null;
945
        Statement st = null;
946
        String v = null;
947
        Connection conn = null;
948
        try {
949
            conn = this.getConnection();
950
            st = conn.createStatement();
951
            rs = JDBCHelper.executeQuery(st,sql); 
952
            rs.next();
953
            v = rs.getString(1);
954
            if (v == null) {
955
                throw new Exception("Returned version is NULL");
956
            }
957
        } catch (Exception exc) {
958
            logger.error("Unable to get Postgis version: " + exc.getMessage(), exc);
959
            return null;
960
        } finally {
961
            try { rs.close(); } catch (Exception e) {};
962
            try { st.close(); } catch (Exception e) {};
963
            try { conn.close(); } catch (Exception e) {};
964
        }
965

    
966
        String[] vv = v.split("\\.");
967
        int[] resp = new int[3];
968
        try {
969
            for (int i=0; i<3; i++) {
970
                resp[i] = Integer.parseInt(vv[i]);
971
            }
972
        } catch (Exception exc) {
973
            logger.error("Unable to parse version: " + v, exc);
974
            return null;
975
        }
976
        return resp;
977
    }
978
    
979
    
980
    
981
    protected Properties getBeforePostgis13Properties() {
982
        if (beforePostgis13 == null) {
983
            
984
            beforePostgis13 = new Properties();
985
            // Left side MUST be in lower case
986
            // Right side will be used if Postgis version < 1.3
987
            beforePostgis13.setProperty("st_intersects", "Intersects");
988
            beforePostgis13.setProperty("st_extent", "Extent");
989
            beforePostgis13.setProperty("st_envelope", "Envelope");
990
            beforePostgis13.setProperty("st_asbinary", "AsBinary");
991
            beforePostgis13.setProperty("st_geomfromtext", "GeomFromText");
992
            beforePostgis13.setProperty("st_geomfromwkb", "GeomFromWKB");
993
        }
994
        return beforePostgis13;
995
    }
996
    
997

    
998

    
999
}