Statistics
| Revision:

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

History | View | Annotate | Download (30 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.JDBCNewStoreParameters;
73
import org.gvsig.fmap.dal.store.jdbc.JDBCStoreParameters;
74
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCException;
75
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCExecutePreparedSQLException;
76
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCExecuteSQLException;
77
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCPreparingSQLException;
78
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCSQLException;
79
import org.gvsig.fmap.geom.Geometry;
80
import org.gvsig.fmap.geom.primitive.Envelope;
81
import org.gvsig.tools.ToolsLocator;
82
import org.gvsig.tools.exception.BaseException;
83

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

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

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

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

    
104
                super(consumer, params);
105
        }
106

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

    
121

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

    
149
                return defaultSchema;
150
        }
151

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

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

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

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

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

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

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

    
210
        }
211

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

    
214
        this.open();
215

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

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

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

    
230
                try {
231

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

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

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

    
250
                    fullEnvelope = geom.getEnvelope();
251

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

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

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

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

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

    
315

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

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

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

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

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

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

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

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

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

    
425

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

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

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

    
474

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

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

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

    
503
                                                } else {
504

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

    
534
                                }
535
                        }
536

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

    
544
        }
545

    
546

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

    
554

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

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

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

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

    
618
                        return searchpgSRID(srs);
619

    
620
                }
621
                return -1;
622
        }
623

    
624

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

    
632
                        return searchpgSRID(srs);
633

    
634
                }
635
                return -1;
636
        }
637

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

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

    
650
                ConnectionAction action = new ConnectionAction(){
651

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

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

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

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

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

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

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

    
698
                        }
699

    
700
                };
701

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

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

    
716
        }
717

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

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

    
732
                    // gemoType:
733
                    /*
734
             * POINT, LINESTRING, POLYGON, MULTIPOINT, MULTILINESTRING,
735
             * MULTIPOLYGON, GEOMETRYCOLLECTION POINTM, LINESTRINGM, POLYGONM,
736
             * MULTIPOINTM, MULTILINESTRINGM, MULTIPOLYGONM, GEOMETRYCOLLECTIONM
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(getProviderSRID(attr.getSRS()));
751
            strb.append(", '");
752

    
753
            strb.append(getPostgisGeomType(
754
                    attr.getGeometryType(),
755
                    attr.getGeometrySubType()
756
            )
757
            );
758
            strb.append("', ");
759
            strb.append(getPostgisGeomDimensions(attr.getGeometrySubType()));
760
            strb.append(")");
761

    
762
            sqls.add(strb.toString());
763

    
764
            return sqls;
765
        }
766

    
767
        public String getSqlFieldName(FeatureAttributeDescriptor attribute) {
768
                if (attribute.getType() == DataTypes.GEOMETRY) {
769
                        return getFunctionName("ST_AsBinary") + "("
770
                            + super.getSqlFieldName(attribute) + ")";
771
                }
772
                return super.getSqlFieldName(attribute);
773
        }
774

    
775
        protected EditableFeatureAttributeDescriptor createAttributeFromJDBC(
776
                        EditableFeatureType type, Connection conn,
777
                        ResultSetMetaData rsMetadata, int colIndex) throws SQLException {
778
                if (rsMetadata.getColumnType(colIndex) == java.sql.Types.OTHER) {
779
                        if (rsMetadata.getColumnTypeName(colIndex).equalsIgnoreCase(
780
                                        "geometry")) {
781
                                EditableFeatureAttributeDescriptor attr = type.add(rsMetadata.getColumnName(colIndex),
782
                                                DataTypes.GEOMETRY);
783
                                // Set default values for geometry type
784
                                attr.setGeometryType(Geometry.TYPES.GEOMETRY);
785
                                attr.setGeometrySubType(Geometry.SUBTYPES.GEOM2D);
786
                                return attr;
787

    
788
                        }
789
                }
790

    
791
                return super.createAttributeFromJDBC(type, conn, rsMetadata, colIndex);
792
        }
793

    
794
        public List getAdditionalSqlToCreate(NewDataStoreParameters ndsp,
795
                        FeatureType fType) {
796
                FeatureAttributeDescriptor attr;
797
                Iterator iter = fType.iterator();
798
                List result = new ArrayList();
799
                PostgreSQLNewStoreParameters pgNdsp = (PostgreSQLNewStoreParameters) ndsp;
800
                while (iter.hasNext()){
801
                        attr = (FeatureAttributeDescriptor) iter.next();
802
                        if (attr.getType() == DataTypes.GEOMETRY){
803
                                result.addAll(getSqlGeometyFieldAdd(attr, pgNdsp.getTable(),
804
                                                pgNdsp
805
                                                .getSchema()));
806
                        }
807
                        if( attr.isIndexed() ) {
808
                            result.add(getCreateIndexStatement((JDBCNewStoreParameters) ndsp, attr));
809
                        }
810
                }
811

    
812
                return result;
813
        }
814

    
815
        protected String getCreateIndexStatement(JDBCNewStoreParameters params,FeatureAttributeDescriptor attr ) {
816
            String indexName = "idx_"+params.getTable()+"_"+attr.getName();
817
            
818
            String statement = "CREATE ";
819
            if( !attr.allowIndexDuplicateds() ) {
820
                statement += " UNIQUE ";
821
            }
822
            statement += "INDEX \""+indexName+"\" ";
823
            statement += "ON " + params.tableID() + " ";
824
            if( attr.getType()==DataTypes.GEOMETRY ) {
825
                statement += " USING GIST ";
826
                statement += "( \"" + attr.getName()+ "\")";
827
            } else {
828
                statement += "( \"" + attr.getName()+ "\"";
829
                if( attr.isIndexAscending() ) {
830
                    statement += " ASC )";
831
                } else {
832
                    statement += " DESC )";
833
                }
834
            }
835
            return statement;
836
        }
837
        
838
        public String getSqlFieldDescription(FeatureAttributeDescriptor attr)
839
                        throws DataException {
840
                if (attr.getType() == DataTypes.GEOMETRY){
841
                        return null;
842
                }
843
                return super.getSqlFieldDescription(attr);
844
        }
845

    
846

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

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

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

    
874
        EditableFeatureAttributeDescriptor column;
875

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

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

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

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

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

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

    
941

    
942
    private int[] getPostgisVersion() {
943

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

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

    
999

    
1000
}