Statistics
| Revision:

root / trunk / extensions / extJDBC / src / com / iver / cit / gvsig / fmap / drivers / jdbc / postgis / PostGisDriver.java @ 3207

History | View | Annotate | Download (17.8 KB)

1
/*
2
 * Created on 04-mar-2005
3
 *
4
 * gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
5
 * 
6
 * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
7
 * 
8
 * This program is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU General Public License
10
 * as published by the Free Software Foundation; either version 2
11
 * of the License, or (at your option) any later version.
12
 *  
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 * 
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program; if not, write to the Free Software
20
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21
 *  
22
 * For more information, contact:
23
 *
24
 *  Generalitat Valenciana
25
 *   Conselleria d'Infraestructures i Transport
26
 *   Av. Blasco Ib??ez, 50
27
 *   46010 VALENCIA
28
 *   SPAIN
29
 *
30
 *      +34 963862235
31
 *   gvsig@gva.es
32
 *      www.gvsig.gva.es
33
 * 
34
 *    or
35
 * 
36
 *   IVER T.I. S.A
37
 *   Salamanca 50
38
 *   46005 Valencia
39
 *   Spain
40
 * 
41
 *   +34 963163400
42
 *   dac@iver.es
43
 */
44
package com.iver.cit.gvsig.fmap.drivers.jdbc.postgis;
45

    
46
import java.awt.geom.Rectangle2D;
47
import java.io.IOException;
48
import java.nio.ByteBuffer;
49
import java.sql.Connection;
50
import java.sql.PreparedStatement;
51
import java.sql.ResultSet;
52
import java.sql.SQLException;
53
import java.sql.Statement;
54
import java.sql.Types;
55
import java.util.Hashtable;
56

    
57
import org.apache.log4j.Logger;
58
import org.postgis.PGbox2d;
59
import org.postgis.PGbox3d;
60

    
61
import com.hardcode.gdbms.engine.data.edition.DataWare;
62
import com.hardcode.gdbms.engine.values.Value;
63
import com.hardcode.gdbms.engine.values.ValueFactory;
64
import com.iver.andami.messages.NotificationManager;
65
import com.iver.cit.gvsig.fmap.DriverException;
66
import com.iver.cit.gvsig.fmap.core.ICanReproject;
67
import com.iver.cit.gvsig.fmap.core.IGeometry;
68
import com.iver.cit.gvsig.fmap.drivers.DefaultDBDriver;
69
import com.iver.cit.gvsig.fmap.drivers.DriverAttributes;
70
import com.iver.cit.gvsig.fmap.drivers.IFeatureIterator;
71
import com.iver.cit.gvsig.fmap.drivers.jdbc.WKBParser;
72

    
73
/**
74
 * @author FJP
75
 *
76
 * TODO To change the template for this generated type comment go to
77
 * Window - Preferences - Java - Code Generation - Code and Comments
78
 */
79
public class PostGisDriver extends DefaultDBDriver implements ICanReproject {
80
    private static Logger logger = Logger.getLogger(PostGisDriver.class.getName());
81
    
82
    private static int FETCH_SIZE = 5000;
83
    private WKBParser parser = new WKBParser();
84
    private int fetch_min=-1;
85
    private int fetch_max=-1;
86
    
87
    private String strEPSG = null;
88
    private String originalEPSG = null;
89
    
90
    private Rectangle2D fullExtent = null;
91
    private String strAux;
92
    static {
93
            try {
94
                        Class.forName("org.postgresql.Driver");
95
                } catch (ClassNotFoundException e) {
96
                        throw new RuntimeException(e);
97
                }
98
    }    
99
    
100
    /**
101
     * 
102
     */
103
    public PostGisDriver() {
104
    }
105
    /* (non-Javadoc)
106
     * @see com.iver.cit.gvsig.fmap.drivers.VectorialDriver#getDriverAttributes()
107
     */
108
    public DriverAttributes getDriverAttributes() {
109
        return null;
110
    }
111

    
112
    /* (non-Javadoc)
113
     * @see com.hardcode.driverManager.Driver#getName()
114
     */
115
    public String getName() {
116
        return "PostGIS JDBC Driver";
117
    }
118
    
119
        /**
120
         * @see com.iver.cit.gvsig.fmap.layers.ReadableVectorial#getShape(int)
121
         */
122
        public IGeometry getShape(int index) {
123
            IGeometry geom = null;
124
            boolean resul;
125
                try {
126
                setAbsolutePosition(index);
127
                    // strAux = rs.getString(1);                
128
                    // geom = parser.read(strAux);
129
                    byte[] data = rs.getBytes(1);                
130
                    geom = parser.parse(data);
131
                    
132
            } catch (SQLException e) {
133
                e.printStackTrace();
134
            }
135
                
136
            return geom;
137
        }
138
        /**
139
     * Antes de llamar a esta funci?n hay que haber fijado el 
140
     * workingArea si se quiere usar.
141
         * @param conn
142
         * @param tableName
143
         * @param fields OJO: EL PRIMER CAMPO HA DE SER EL DE GEOMETRIA
144
         * @param whereClause
145
         */
146
        public void setData(Connection conn, String tableName, String fields, String whereClause, int id_FID_field)
147
        {
148
            this.conn = conn;            
149
            this.tableName = tableName;
150
            this.fields = fields;
151
            this.whereClause = whereClause;
152
            this.sqlOrig = "SELECT " + fields + " FROM " + tableName + " " + whereClause;
153
        this.idFID_FieldName = id_FID_field;
154
        
155
        getTableEPSG();
156
        
157
            try {
158
            String sqlAux = null;
159
            if (canReproject(strEPSG))
160
            {
161
                sqlAux = getCompoundWhere(workingArea, strEPSG);
162
            }
163
            else
164
            {
165
                sqlAux = getCompoundWhere(workingArea, originalEPSG);                
166
            }
167
            logger.info("Cadena SQL:" + sqlAux);
168
                st = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
169
                // st.setFetchSize(FETCH_SIZE);
170
                st.execute("declare wkb_cursor binary cursor for " + sqlOrig);
171
                rs = st.executeQuery("fetch forward " + FETCH_SIZE + " in wkb_cursor");
172
                // st.execute("begin"); 
173
                // bCursorActivo = true; 
174
                // rs = st.executeQuery(sqlOrig);
175
            fetch_min = 0;
176
            fetch_max = FETCH_SIZE-1;
177
            metaData = rs.getMetaData();
178
            doRelateID_FID();
179
            
180
        } catch (SQLException e) {
181
            NotificationManager.addError("Error al conectar a la base de datos.",e);
182
        }
183
        }
184
        
185
        /**
186
         * @see com.iver.cit.gvsig.fmap.layers.ReadableVectorial#getFullExtent()
187
         */
188
        public Rectangle2D getFullExtent(){
189
            if (fullExtent == null)
190
            {
191
                try
192
            {
193
                    Statement s = conn.createStatement();                    
194
                    ResultSet r = s.executeQuery("SELECT extent(the_geom) AS FullExtent FROM " + tableName);
195
                    r.next();
196
                    String strAux = r.getString(1);
197
                    System.out.println("fullExtent = " + strAux);
198
                                if (strAux.startsWith("BOX3D"))
199
                                {
200
                                        PGbox3d regeom = new PGbox3d(strAux);
201
                            double x = regeom.getLLB().x;
202
                            double y = regeom.getLLB().y;
203
                            double w = regeom.getURT().x -x;
204
                            double h = regeom.getURT().y - y;
205
                        fullExtent = new Rectangle2D.Double(x, y, w, h);                            
206
                                }
207
                                else
208
                                {
209
                                        PGbox2d regeom = new PGbox2d(strAux);
210
                            double x = regeom.getLLB().x;
211
                            double y = regeom.getLLB().y;
212
                            double w = regeom.getURT().x -x;
213
                            double h = regeom.getURT().y - y;
214
                        fullExtent = new Rectangle2D.Double(x, y, w, h);                                                                    
215
                                }
216
            }
217
                catch (SQLException e)
218
                {
219
                    System.err.println(e.getMessage());
220
                }
221
                
222
            }
223
            return fullExtent;
224
        }
225
    /* (non-Javadoc)
226
     * @see com.iver.cit.gvsig.fmap.drivers.VectorialDatabaseDriver#getGeometryIterator(java.lang.String)
227
     */
228
    public IFeatureIterator getFeatureIterator(String sql) throws com.iver.cit.gvsig.fmap.DriverException {
229
        PostGisFeatureIterator geomIterator = null;
230
        try {
231
            st = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
232
            // st.setFetchSize(2000);
233
            if (bCursorActivo)
234
            {
235
                st.execute("CLOSE wkb_cursor_prov");
236
                bCursorActivo = false;
237
            }
238

    
239
                st.execute("declare wkb_cursor_prov binary cursor for " + sql);
240
                ResultSet rs = st.executeQuery("fetch forward " + FETCH_SIZE + " in wkb_cursor_prov");
241
            // st.execute("BEGIN");
242
            bCursorActivo = true;
243
            // ResultSet rs = st.executeQuery(sql);
244
            geomIterator = new PostGisFeatureIterator(rs, st);
245
        } catch (SQLException e) {
246
            e.printStackTrace();
247
            throw new com.iver.cit.gvsig.fmap.DriverException(e);
248
        }
249
            
250
        return geomIterator;
251
    }
252
        
253
    public IFeatureIterator getFeatureIterator(Rectangle2D r, String strEPSG) throws DriverException {
254
        if (workingArea != null)
255
            r = r.createIntersection(workingArea);
256
        
257
        String sqlAux;
258
        if (canReproject(strEPSG))
259
        {
260
            sqlAux = getCompoundWhere(r, strEPSG);
261
        }
262
        else
263
        {
264
            sqlAux = getCompoundWhere(r, originalEPSG);                
265
        }
266
        
267
        System.out.println("SqlAux getFeatureIterator = " + sqlAux);
268

    
269
        return getFeatureIterator(sqlAux);
270
    }
271
    /**
272
     * Le pasas el rect?ngulo que quieres pedir. La primera
273
     * vez es el workingArea, y las siguientes una interseccion
274
     * de este rectangulo con el workingArea
275
     * @param r
276
     * @param strEPSG
277
     * @return
278
     */
279
    private String getCompoundWhere(Rectangle2D r, String strEPSG) {
280
        if (r==null)
281
            return this.sqlOrig;
282
        
283
        double xMin = r.getMinX();
284
        double yMin = r.getMinY();
285
        double xMax = r.getMaxX();
286
        double yMax = r.getMaxY();
287
        String wktBox = "GeometryFromText('LINESTRING(" + xMin + " " + yMin + ", "
288
                + xMax + " " + yMin + ", "
289
                + xMax + " " + yMax + ", "
290
                + xMin + " " + yMax + ")', "
291
                + strEPSG + ")";
292
        String sqlAux;
293
        if (getWhereClause().startsWith("WHERE")) 
294
            sqlAux = sqlOrig + " the_geom && " + wktBox;
295
        else
296
            sqlAux = sqlOrig + "WHERE the_geom && " + wktBox;
297
        return sqlAux;
298
    }
299
        /**
300
         * @see com.iver.cit.gvsig.fmap.drivers.VectorialDatabaseDriver#getConnectionStringBeginning()
301
         */
302
        public String getConnectionStringBeginning() {
303
                return "jdbc:postgresql:";
304
        }
305
    /* (non-Javadoc)
306
     * @see com.iver.cit.gvsig.fmap.drivers.DefaultDBDriver#getFieldValue(long, int)
307
     */
308
    public Value getFieldValue(long rowIndex, int idField) throws com.hardcode.gdbms.engine.data.driver.DriverException {
309
        boolean resul;
310
            // EL ABSOLUTE NO HACE QUE SE VUELVAN A LEER LAS
311
            // FILAS, ASI QUE MONTAMOS ESTA HISTORIA PARA QUE
312
            // LO HAGA
313
            // System.out.println("getShape " + index);
314
        int index = (int) (rowIndex);
315
        try
316
        {
317
            setAbsolutePosition(index);
318
            int fieldId = idField+2;
319
            byte[] byteBuf = rs.getBytes(fieldId);
320
            if (byteBuf == null)
321
                return  ValueFactory.createNullValue();
322
            else
323
            {
324
                ByteBuffer buf = ByteBuffer.wrap(byteBuf);
325
                if (metaData.getColumnType(fieldId) == Types.VARCHAR)
326
                    return  ValueFactory.createValue(rs.getString(fieldId));
327
                if (metaData.getColumnType(fieldId) == Types.FLOAT)
328
                    return ValueFactory.createValue(buf.getFloat());
329
                if (metaData.getColumnType(fieldId) == Types.DOUBLE)
330
                    return ValueFactory.createValue(buf.getDouble());
331
                if (metaData.getColumnType(fieldId) == Types.INTEGER)
332
                    return ValueFactory.createValue(buf.getInt());
333
                if (metaData.getColumnType(fieldId) == Types.BIGINT)
334
                    return ValueFactory.createValue(buf.getLong());
335
                if (metaData.getColumnType(fieldId) == Types.BIT)
336
                    // TODO
337
                    return ValueFactory.createValue(rs.getBoolean(fieldId));
338
                if (metaData.getColumnType(fieldId) == Types.DATE)
339
                    // TODO
340
                    return  ValueFactory.createValue(rs.getDate(fieldId));
341
            }
342
        }
343
        catch(SQLException e)
344
        {
345
            throw new com.hardcode.gdbms.engine.data.driver.DriverException(e.getMessage());
346
        }
347
        return ValueFactory.createNullValue();
348
            
349
    }
350
    public void open()  throws com.iver.cit.gvsig.fmap.DriverException {
351
        /* try {
352
            st = conn.createStatement();
353
            st.setFetchSize(2000);
354
            if (bCursorActivo)
355
                close();
356
            st.execute("declare wkb_cursor binary cursor for " + sqlOrig);
357
            rs = st.executeQuery("fetch forward all in wkb_cursor");
358
            // st.execute("BEGIN");
359
            bCursorActivo = true;
360
        } catch (SQLException e) {
361
            e.printStackTrace();
362
            throw new com.iver.cit.gvsig.fmap.DriverException(e);
363
        } */
364
        
365
    }
366
    
367
    private void setAbsolutePosition(int index) throws SQLException
368
    {
369
        // EL ABSOLUTE NO HACE QUE SE VUELVAN A LEER LAS
370
        // FILAS, ASI QUE MONTAMOS ESTA HISTORIA PARA QUE
371
        // LO HAGA
372
        // System.out.println("getShape " + index + " fetchMin=" + fetch_min + " fetchMax=" + fetch_max);
373
        if (index < fetch_min)
374
        {
375
            // rs.close();
376
            st.execute("CLOSE wkb_cursor");
377
            st.execute("declare wkb_cursor binary cursor for " + sqlOrig);
378
            rs = st.executeQuery("fetch forward " + FETCH_SIZE + " in wkb_cursor");
379
            
380
            // rs.beforeFirst();           
381
            
382
            // rs = st.executeQuery(sqlOrig);
383
            fetch_min = 0;
384
            fetch_max = FETCH_SIZE-1;
385
        }
386
        while (index > fetch_max)
387
        {
388
            rs = st.executeQuery("fetch forward " + FETCH_SIZE + " in wkb_cursor");
389
            // rs.next();
390
            /* rs.afterLast();
391
            // forzamos una carga
392
            rs.next(); */
393
            fetch_min = fetch_max+1;
394
            fetch_max = fetch_min + FETCH_SIZE -1;
395
            // System.out.println("fetchSize = " + rs.getFetchSize() + " " + fetch_min + "-" + fetch_max);
396
        } 
397
        rs.absolute(index - fetch_min + 1);
398
        
399
        // rs.absolute(index+1);
400
        
401
    }
402
        /**
403
         * @see com.iver.cit.gvsig.fmap.drivers.VectorialDatabaseDriver#getGeometryField(java.lang.String)
404
         */
405
        public String getGeometryField(String fieldName) {
406
                return "ASBINARY(" + fieldName + ", 'XDR')";
407
        }
408
    /**
409
     * @see com.hardcode.gdbms.engine.data.driver.ObjectDriver#getPrimaryKeys()
410
     */
411
    public int[] getPrimaryKeys() throws com.hardcode.gdbms.engine.data.driver.DriverException {
412
        // TODO Auto-generated method stub
413
        return null;
414
    }
415
    /**
416
     * @see com.iver.cit.gvsig.fmap.drivers.VectorialJDBCDriver#getDefaultPort()
417
     */
418
    public int getDefaultPort() {
419
        return 5432;
420
    }
421
    /**
422
     * @see com.hardcode.gdbms.engine.data.driver.ObjectDriver#write(com.hardcode.gdbms.engine.data.edition.DataWare)
423
     */
424
    public void write(DataWare arg0) throws com.hardcode.gdbms.engine.data.driver.DriverException {
425
        // TODO Auto-generated method stub
426
        
427
    }
428
    /* (non-Javadoc)
429
     * @see com.iver.cit.gvsig.fmap.core.ICanReproject#getSourceProjection()
430
     */
431
    public String getSourceProjection() {
432
        if (originalEPSG == null)
433
            getTableEPSG();
434
        return originalEPSG;
435
    }
436
    
437
    private void getTableEPSG()
438
    {
439
        try {
440
            Statement stAux = conn.createStatement();
441

    
442
            String sql = "SELECT * FROM GEOMETRY_COLUMNS WHERE F_TABLE_NAME = '" +
443
                getTableName() + "';";
444
            ResultSet rs = stAux.executeQuery(sql);
445
            rs.next();
446
            originalEPSG = "" + rs.getInt("SRID");
447
            rs.close();
448
        } catch (SQLException e) {
449
            // TODO Auto-generated catch block
450
            e.printStackTrace();
451
        }
452
        
453
    }
454
    
455
    /* (non-Javadoc)
456
     * @see com.iver.cit.gvsig.fmap.core.ICanReproject#getDestProjection()
457
     */
458
    public String getDestProjection() {
459
        return strEPSG;
460
    }
461
    /* (non-Javadoc)
462
     * @see com.iver.cit.gvsig.fmap.core.ICanReproject#setDestProjection(java.lang.String)
463
     */
464
    public void setDestProjection(String toEPSG) {
465
        this.strEPSG = toEPSG;
466
    }
467
    /* (non-Javadoc)
468
     * @see com.iver.cit.gvsig.fmap.core.ICanReproject#canReproject(java.lang.String)
469
     */
470
    public boolean canReproject(String toEPSGdestinyProjection) {
471
        // TODO POR AHORA, REPROYECTA SIEMPRE gvSIG.
472
        return false;
473
    }
474
    /* (non-Javadoc)
475
     * @see com.iver.cit.gvsig.fmap.drivers.DefaultDBDriver#doRelateID_FID()
476
     */
477
    protected void doRelateID_FID()
478
    {
479
        hashRelate = new Hashtable();
480
        try {
481
            String strSQL = "select gid from " + getTableName();
482
            
483
            Statement s = getConnection().createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
484
            int fetchSize = 5000;
485
            ResultSet r = s.executeQuery(strSQL);
486
            int id=0;
487
            int gid;
488
            while( r.next() ) 
489
            { 
490
              gid = r.getInt(1);
491
              id++;
492
              Value aux = ValueFactory.createValue(gid);
493
              hashRelate.put(aux, new Integer(gid));             
494
              
495
              // System.out.println("Row " + id + ":" + strAux); 
496
            } 
497
            s.close();
498
            numReg = id;
499
            
500
            /* for (int index = 0; index < getShapeCount(); index++)
501
            {
502
                Value aux = getFieldValue(index, idFID_FieldName-2);
503
                hashRelate.put(aux, new Integer(index));             
504
                // System.out.println("Row " + index + " clave=" + aux);
505
            }*/
506
/*             int index = 0;
507
            
508
            while (rs.next())
509
            {
510
                Value aux = getFieldValue(index, idFID_FieldName-2);
511
                hashRelate.put(aux, new Integer(index));
512
                index++;
513
                System.out.println("Row " + index + " clave=" + aux);                 
514
            }
515
            numReg = index; */
516
            // rs.beforeFirst();
517
        /* } catch (com.hardcode.gdbms.engine.data.driver.DriverException e) {
518
            // TODO Auto-generated catch block
519
            e.printStackTrace(); */
520
        } catch (SQLException e) {
521
            // TODO Auto-generated catch block
522
            e.printStackTrace();
523
        }          
524
    }
525
    
526
    
527
}