Statistics
| Revision:

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

History | View | Annotate | Download (27 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.math.BigDecimal;
48
import java.nio.ByteBuffer;
49
import java.sql.Connection;
50
import java.sql.Date;
51
import java.sql.ResultSet;
52
import java.sql.ResultSetMetaData;
53
import java.sql.SQLException;
54
import java.sql.Statement;
55
import java.sql.Timestamp;
56
import java.sql.Types;
57
import java.util.ArrayList;
58
import java.util.Hashtable;
59

    
60
import org.apache.log4j.Logger;
61
import org.postgis.PGbox2d;
62
import org.postgis.PGbox3d;
63

    
64
import com.hardcode.gdbms.driver.exceptions.InitializeWriterException;
65
import com.hardcode.gdbms.driver.exceptions.ReadDriverException;
66
import com.hardcode.gdbms.engine.data.edition.DataWare;
67
import com.hardcode.gdbms.engine.values.Value;
68
import com.hardcode.gdbms.engine.values.ValueFactory;
69
import com.iver.andami.messages.NotificationManager;
70
import com.iver.cit.gvsig.fmap.SqlDriveExceptionType;
71
import com.iver.cit.gvsig.fmap.core.FShape;
72
import com.iver.cit.gvsig.fmap.core.ICanReproject;
73
import com.iver.cit.gvsig.fmap.core.IGeometry;
74
import com.iver.cit.gvsig.fmap.drivers.ConnectionJDBC;
75
import com.iver.cit.gvsig.fmap.drivers.DBException;
76
import com.iver.cit.gvsig.fmap.drivers.DBLayerDefinition;
77
import com.iver.cit.gvsig.fmap.drivers.DefaultJDBCDriver;
78
import com.iver.cit.gvsig.fmap.drivers.DriverAttributes;
79
import com.iver.cit.gvsig.fmap.drivers.IConnection;
80
import com.iver.cit.gvsig.fmap.drivers.IFeatureIterator;
81
import com.iver.cit.gvsig.fmap.drivers.WKBParser2;
82
import com.iver.cit.gvsig.fmap.drivers.XTypes;
83
import com.iver.cit.gvsig.fmap.edition.IWriteable;
84
import com.iver.cit.gvsig.fmap.edition.IWriter;
85

    
86
/**
87
 * @author FJP
88
 *
89
 * TODO To change the template for this generated type comment go to Window -
90
 * Preferences - Java - Code Generation - Code and Comments
91
 */
92
public class PostGisDriver extends DefaultJDBCDriver implements ICanReproject, IWriteable {
93
        private static Logger logger = Logger.getLogger(PostGisDriver.class
94
                        .getName());
95

    
96
        private static int FETCH_SIZE = 5000;
97

    
98
        // To avoid problems when using wkb_cursor with same layer.
99
        // I mean, when you add twice or more the same layer using
100
        // the same connection
101

    
102
        private static int CURSOR_ID = 0;
103

    
104
        private int myCursorId;
105

    
106
        private PostGISWriter writer = new PostGISWriter();
107

    
108
        private WKBParser2 parser = new WKBParser2();
109

    
110
        private int fetch_min = -1;
111

    
112
        private int fetch_max = -1;
113

    
114
        private String sqlOrig;
115

    
116
        /**
117
         * Used by setAbsolutePosition
118
         */
119
        private String sqlTotal;
120

    
121
        private String strEPSG = null;
122

    
123
        private String originalEPSG = null;
124

    
125
        private Rectangle2D fullExtent = null;
126

    
127
        private String strAux;
128

    
129
        private String completeWhere;
130

    
131
        private String provCursorName = null;
132

    
133
        int numProvCursors = 0;
134

    
135
        boolean bShapeTypeRevised = false;
136

    
137
        private int actual_position;
138

    
139
        static {
140
                try {
141
                        Class.forName("org.postgresql.Driver");
142
                } catch (ClassNotFoundException e) {
143
                        throw new RuntimeException(e);
144
                }
145
        }
146

    
147
        /**
148
         *
149
         */
150
        public PostGisDriver() {
151
                // To avoid problems when using wkb_cursor with same layer.
152
                // I mean, when you add twice or more the same layer using
153
                // the same connection
154
                CURSOR_ID++;
155
                myCursorId = CURSOR_ID;
156
        }
157

    
158
        /*
159
         * (non-Javadoc)
160
         *
161
         * @see com.iver.cit.gvsig.fmap.drivers.VectorialDriver#getDriverAttributes()
162
         */
163
        public DriverAttributes getDriverAttributes() {
164
                return null;
165
        }
166

    
167
        /*
168
         * (non-Javadoc)
169
         *
170
         * @see com.hardcode.driverManager.Driver#getName()
171
         */
172
        public String getName() {
173
                return "PostGIS JDBC Driver";
174
        }
175

    
176
        /**
177
         * @throws ReadDriverException
178
         * @see com.iver.cit.gvsig.fmap.layers.ReadableVectorial#getShape(int)
179
         */
180
        public IGeometry getShape(int index) throws ReadDriverException {
181
                IGeometry geom = null;
182
                boolean resul;
183
                try {
184
                        setAbsolutePosition(index);
185
                        // strAux = rs.getString(1);
186
                        // geom = parser.read(strAux);
187
                        if (rs != null) {
188
                                byte[] data = rs.getBytes(1);
189
                                if (data == null) // null geometry.
190
                                        return null;
191
                                geom = parser.parse(data);
192
                        }
193
                } catch (SQLException e) {
194
                        throw new ReadDriverException(this.getName(),e);
195
                }
196

    
197
                return geom;
198
        }
199

    
200
        /**
201
         * First, the geometry field. After, the rest of fields
202
         *
203
         * @return
204
         */
205
        /*
206
         * public String getTotalFields() { String strAux = "AsBinary(" +
207
         * getLyrDef().getFieldGeometry() + ")"; String[] fieldNames =
208
         * getLyrDef().getFieldNames(); for (int i=0; i< fieldNames.length; i++) {
209
         * strAux = strAux + ", " + fieldNames[i]; } return strAux; }
210
         */
211

    
212
        /**
213
         * Antes de llamar a esta funci?n hay que haber fijado el workingArea si se
214
         * quiere usar.
215
         *
216
         * @param conn
217
         * @throws DBException
218
         */
219
        public void setData(IConnection conn, DBLayerDefinition lyrDef) throws DBException {
220
                this.conn = conn;
221
                // TODO: Deber?amos poder quitar Conneciton de la llamada y meterlo
222
                // en lyrDef desde el principio.
223

    
224
                lyrDef.setConnection(conn);
225
                setLyrDef(lyrDef);
226

    
227
                getTableEPSG_and_shapeType();
228

    
229
                getLyrDef().setSRID_EPSG(originalEPSG);
230

    
231
                try {
232
                        ((ConnectionJDBC)conn).getConnection().setAutoCommit(false);
233
                        sqlOrig = "SELECT " + getTotalFields() + " FROM "
234
                                        + getLyrDef().getComposedTableName() + " ";
235
                                        // + getLyrDef().getWhereClause();
236
                        if (canReproject(strEPSG)) {
237
                                completeWhere = getCompoundWhere(sqlOrig, workingArea, strEPSG);
238
                        } else {
239
                                completeWhere = getCompoundWhere(sqlOrig, workingArea,
240
                                                originalEPSG);
241
                        }
242
                        // completeWhere = getLyrDef().getWhereClause() + completeWhere;
243

    
244
                        String sqlAux = sqlOrig + completeWhere + " ORDER BY "
245
                        + getLyrDef().getFieldID();
246

    
247
                        sqlTotal = sqlAux;
248
                        logger.info("Cadena SQL:" + sqlAux);
249
                        st = ((ConnectionJDBC)conn).getConnection().createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
250
                                        ResultSet.CONCUR_READ_ONLY);
251
                        // st.setFetchSize(FETCH_SIZE);
252
                        myCursorId++;
253
                        st.execute("declare " + getTableName() + myCursorId + "_wkb_cursor binary scroll cursor with hold for " + sqlAux);
254
                        rs = st.executeQuery("fetch forward " + FETCH_SIZE
255
                                        + " in " + getTableName() + myCursorId + "_wkb_cursor");
256
                        fetch_min = 0;
257
                        fetch_max = FETCH_SIZE - 1;
258
                        actual_position = 0;
259
                        metaData = rs.getMetaData();
260
                        doRelateID_FID();
261

    
262
                        writer.setCreateTable(false);
263
                        writer.setWriteAll(false);
264
                        writer.initialize(lyrDef);
265

    
266

    
267
                } catch (SQLException e) {
268
                        throw new DBException(e);
269
                } catch (InitializeWriterException e) {
270
                        throw new DBException(e);
271
                }
272
        }
273

    
274
        /**
275
         * @see com.iver.cit.gvsig.fmap.layers.ReadableVectorial#getFullExtent()
276
         */
277
        public Rectangle2D getFullExtent() throws ReadDriverException {
278
                if (fullExtent == null) {
279
                        try {
280
                                Statement s = ((ConnectionJDBC)conn).getConnection().createStatement();
281
                                ResultSet r = s.executeQuery("SELECT extent("
282
                                                + getLyrDef().getFieldGeometry()
283
                                                + ") AS FullExtent FROM " + getLyrDef().getComposedTableName()
284
                                                + " " + getCompleteWhere());
285
                                r.next();
286
                                String strAux = r.getString(1);
287
                                System.out.println("fullExtent = " + strAux);
288
                                if (strAux == null)
289
                                {
290
                                        logger.debug("La capa " + getLyrDef().getName() + " no tiene FULLEXTENT");
291
                                        return null;
292
                                }
293
                                if (strAux.startsWith("BOX3D")) {
294
                                        PGbox3d regeom = new PGbox3d(strAux);
295
                                        double x = regeom.getLLB().x;
296
                                        double y = regeom.getLLB().y;
297
                                        double w = regeom.getURT().x - x;
298
                                        double h = regeom.getURT().y - y;
299
                                        fullExtent = new Rectangle2D.Double(x, y, w, h);
300
                                } else {
301
                                        PGbox2d regeom = new PGbox2d(strAux);
302
                                        double x = regeom.getLLB().x;
303
                                        double y = regeom.getLLB().y;
304
                                        double w = regeom.getURT().x - x;
305
                                        double h = regeom.getURT().y - y;
306
                                        fullExtent = new Rectangle2D.Double(x, y, w, h);
307
                                }
308
                        } catch (SQLException e) {
309
                                throw new ReadDriverException(this.getName(),e);
310
                        }
311

    
312
                }
313
                return fullExtent;
314
        }
315

    
316
        /*
317
         * (non-Javadoc)
318
         *
319
         * @see com.iver.cit.gvsig.fmap.drivers.VectorialDatabaseDriver#getGeometryIterator(java.lang.String)
320
         */
321
        public IFeatureIterator getFeatureIterator(String sql) throws ReadDriverException {
322
                PostGisFeatureIterator geomIterator = null;
323
                try {
324
                        // st = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
325
                        // ResultSet.CONCUR_READ_ONLY);
326

    
327

    
328
                        if (provCursorName != null) {
329
                                /* st.execute("BEGIN");
330
                                st.execute("CLOSE " + provCursorName);
331
                                bCursorActivo = false;
332
                                st.execute("COMMIT"); */
333
                                numProvCursors++;
334
                        }
335
                        // st.execute("BEGIN");
336
                        provCursorName = getTableName() + myCursorId + "wkb_cursor_prov_" + System.currentTimeMillis() + "" + numProvCursors;
337

    
338
                        // st.execute("BEGIN");
339
                        bCursorActivo = true;
340
                        // ResultSet rs = st.executeQuery(sql);
341
                        geomIterator = new PostGisFeatureIterator(((ConnectionJDBC)conn).getConnection(), provCursorName, sql);
342
                        geomIterator.setLyrDef(getLyrDef());
343
                } catch (SQLException e) {
344
//                        e.printStackTrace();
345
//                        e.printStackTrace();
346
//                        SqlDriveExceptionType type = new SqlDriveExceptionType();
347
//            type.setDriverName("PostGIS Driver");
348
//            type.setSql(sql);
349
//            type.setLayerName(getTableName());
350
//            type.setSchema(null);
351
            throw new ReadDriverException("PostGIS Driver",e);
352
//                        throw new DriverException(e);
353
                        // return null;
354
                }
355

    
356
                return geomIterator;
357
        }
358

    
359
        public IFeatureIterator getFeatureIterator(Rectangle2D r, String strEPSG)
360
                        throws ReadDriverException {
361
                if (workingArea != null)
362
                        r = r.createIntersection(workingArea);
363

    
364
                String sqlAux;
365
                if (canReproject(strEPSG)) {
366
                        sqlAux = sqlOrig + getCompoundWhere(sqlOrig, r, strEPSG);
367
                } else {
368
                        sqlAux = sqlOrig + getCompoundWhere(sqlOrig, r, originalEPSG);
369
                }
370

    
371
                System.out.println("SqlAux getFeatureIterator = " + sqlAux);
372

    
373
                return getFeatureIterator(sqlAux);
374
        }
375

    
376
        /**
377
         * Le pasas el rect?ngulo que quieres pedir. La primera vez es el
378
         * workingArea, y las siguientes una interseccion de este rectangulo con el
379
         * workingArea
380
         *
381
         * @param r
382
         * @param strEPSG
383
         * @return
384
         */
385
        private String getCompoundWhere(String sql, Rectangle2D r, String strEPSG) {
386
                if (r == null)
387
                        return getWhereClause();
388

    
389
                double xMin = r.getMinX();
390
                double yMin = r.getMinY();
391
                double xMax = r.getMaxX();
392
                double yMax = r.getMaxY();
393
                String wktBox = "GeometryFromText('LINESTRING(" + xMin + " " + yMin
394
                                + ", " + xMax + " " + yMin + ", " + xMax + " " + yMax + ", "
395
                                + xMin + " " + yMax + ")', " + strEPSG + ")";
396
                String sqlAux;
397
                if (getWhereClause().indexOf("WHERE") != -1)
398
                        sqlAux = getWhereClause() + " AND " + getLyrDef().getFieldGeometry() + " && " + wktBox;
399
                else
400
                        sqlAux = "WHERE " + getLyrDef().getFieldGeometry() + " && "
401
                                        + wktBox;
402
                return sqlAux;
403
        }
404

    
405
        /**
406
         * @see com.iver.cit.gvsig.fmap.drivers.IVectorialDatabaseDriver#getConnectionStringBeginning()
407
         */
408
        public String getConnectionStringBeginning() {
409
                return "jdbc:postgresql:";
410
        }
411

    
412
        /*
413
         * (non-Javadoc)
414
         *
415
         * @see com.iver.cit.gvsig.fmap.drivers.DefaultDBDriver#getFieldValue(long,
416
         *      int)
417
         */
418
        public Value getFieldValue(long rowIndex, int idField)
419
                        throws ReadDriverException {
420
                boolean resul;
421
                // EL ABSOLUTE NO HACE QUE SE VUELVAN A LEER LAS
422
                // FILAS, ASI QUE MONTAMOS ESTA HISTORIA PARA QUE
423
                // LO HAGA
424
                // System.out.println("getShape " + index);
425
                int index = (int) (rowIndex);
426
                try {
427
                        setAbsolutePosition(index);
428
                        int fieldId = idField + 2;
429
                        byte[] byteBuf = rs.getBytes(fieldId);
430
                        if (byteBuf == null)
431
                                return ValueFactory.createNullValue();
432
                        else {
433
                                ByteBuffer buf = ByteBuffer.wrap(byteBuf);
434
                                if (metaData.getColumnType(fieldId) == Types.VARCHAR)
435
                                        return ValueFactory.createValue(rs.getString(fieldId));
436
                                if (metaData.getColumnType(fieldId) == Types.FLOAT)
437
                                        return ValueFactory.createValue(buf.getFloat());
438
                                if (metaData.getColumnType(fieldId) == Types.DOUBLE)
439
                                        return ValueFactory.createValue(buf.getDouble());
440
                                if (metaData.getColumnType(fieldId) == Types.REAL)
441
                                     return ValueFactory.createValue(buf.getFloat());
442
                                if (metaData.getColumnType(fieldId) == Types.INTEGER)
443
                                        return ValueFactory.createValue(buf.getInt());
444
                                if (metaData.getColumnType(fieldId) == Types.BIGINT)
445
                                        return ValueFactory.createValue(buf.getLong());
446
                                if (metaData.getColumnType(fieldId) == Types.BIT)
447
                                        // TODO
448
                                        return ValueFactory.createValue(rs.getBoolean(fieldId));
449
                                if (metaData.getColumnType(fieldId) == Types.DATE)
450
                                {
451
                        long daysAfter2000 = buf.getInt() + 1;
452
                        long msecs = daysAfter2000*24*60*60*1000;
453
                        long real_msecs_date1 = (long) (XTypes.NUM_msSecs2000 + msecs);
454
                        Date realDate1 = new Date(real_msecs_date1);
455
                                        return ValueFactory.createValue(realDate1);
456
                                }
457
                                if (metaData.getColumnType(fieldId) == Types.TIME)
458
                                {
459
                                        // TODO:
460
                                        // throw new RuntimeException("TIME type not implemented yet");
461
                                        return ValueFactory.createValue("NOT IMPLEMENTED YET");
462
                                }
463
                                if (metaData.getColumnType(fieldId) == Types.TIMESTAMP)
464
                                {
465
                                        double segsReferredTo2000 = buf.getDouble();
466
                                        long real_msecs = (long) (XTypes.NUM_msSecs2000 + segsReferredTo2000*1000);
467
                                        Timestamp valTimeStamp = new Timestamp(real_msecs);
468
                                        return ValueFactory.createValue(valTimeStamp);
469
                                }
470

    
471
                                if (metaData.getColumnType(fieldId) == Types.NUMERIC) {
472
                                        // System.out.println(metaData.getColumnName(fieldId) + " "
473
                                        // + metaData.getColumnClassName(fieldId));
474
                                        short ndigits = buf.getShort();
475
                                        short weight = buf.getShort();
476
                                        short sign = buf.getShort();
477
                                        short dscale = buf.getShort();
478
                                        String strAux;
479
                                        if (sign == 0)
480
                                                strAux = "+";
481
                                        else
482
                                                strAux = "-";
483

    
484
                                        for (int iDigit = 0; iDigit < ndigits; iDigit++) {
485
                                                short digit = buf.getShort();
486
                                                strAux = strAux + digit;
487
                                                if (iDigit == weight)
488
                                                        strAux = strAux + ".";
489

    
490
                                        }
491
                                        strAux = strAux + "0";
492
                                        BigDecimal dec;
493
                                        dec = new BigDecimal(strAux);
494
                                        // System.out.println(ndigits + "_" + weight + "_" + dscale
495
                                        // + "_" + strAux);
496
                                        // System.out.println(strAux + " Big= " + dec);
497
                                        return ValueFactory.createValue(dec.doubleValue());
498
                                }
499

    
500
                        }
501
                } catch (SQLException e) {
502
                        throw new ReadDriverException("PostGIS Driver",e);
503
                }
504
                return ValueFactory.createNullValue();
505

    
506
        }
507

    
508
        public void open() {
509
                /*
510
                 * try { st = conn.createStatement(); st.setFetchSize(2000); if
511
                 * (bCursorActivo) close(); st.execute("declare wkb_cursor binary cursor
512
                 * for " + sqlOrig); rs = st.executeQuery("fetch forward all in
513
                 * wkb_cursor"); // st.execute("BEGIN"); bCursorActivo = true; } catch
514
                 * (SQLException e) { e.printStackTrace(); throw new
515
                 * com.iver.cit.gvsig.fmap.DriverException(e); }
516
                 */
517

    
518
        }
519

    
520
        private void setAbsolutePosition(int index) throws SQLException {
521
                // TODO: USAR LIMIT Y ORDER BY, Y HACERLO TAMBI?N PARA
522
                // MYSQL
523

    
524
                // EL ABSOLUTE NO HACE QUE SE VUELVAN A LEER LAS
525
                // FILAS, ASI QUE MONTAMOS ESTA HISTORIA PARA QUE
526
                // LO HAGA
527
                // System.out.println("getShape " + index + " fetchMin=" + fetch_min + "
528
                // fetchMax=" + fetch_max);
529

    
530
                if ((index >= fetch_min) && (index <= fetch_max))
531
                {
532
                        // Est? en el intervalo, as? que lo podemos posicionar
533

    
534
                }
535
                else
536
                {
537
                        // calculamos el intervalo correcto
538
                        fetch_min = (index / FETCH_SIZE) * FETCH_SIZE;
539
                        fetch_max = fetch_min +  FETCH_SIZE;
540
                        // y cogemos ese cacho
541
                        rs.close();
542
                        st.executeQuery("fetch absolute " + fetch_min
543
                                        + " in " + getTableName() + myCursorId + "_wkb_cursor");
544

    
545
                        rs = st.executeQuery("fetch forward " + FETCH_SIZE
546
                                        + " in " + getTableName() + myCursorId + "_wkb_cursor");
547

    
548
                }
549
                rs.absolute(index - fetch_min + 1);
550
                actual_position = index;
551

    
552
        }
553

    
554
        /**
555
         * @see com.iver.cit.gvsig.fmap.drivers.IVectorialDatabaseDriver#getGeometryField(java.lang.String)
556
         */
557
        public String getGeometryField(String fieldName) {
558
                return "ASBINARY(" + fieldName + ", 'XDR')";
559
        }
560

    
561
        /**
562
         * @see com.hardcode.gdbms.engine.data.driver.ObjectDriver#getPrimaryKeys()
563
         */
564
        public int[] getPrimaryKeys() {
565
                // TODO Auto-generated method stub
566
                return null;
567
        }
568

    
569
        /**
570
         * @see com.iver.cit.gvsig.fmap.drivers.IVectorialJDBCDriver#getDefaultPort()
571
         */
572
        public int getDefaultPort() {
573
                return 5432;
574
        }
575

    
576
        /**
577
         * @see com.hardcode.gdbms.engine.data.driver.ObjectDriver#write(com.hardcode.gdbms.engine.data.edition.DataWare)
578
         */
579
        public void write(DataWare arg0) {
580
                // TODO Auto-generated method stub
581

    
582
        }
583

    
584
        /*
585
         * (non-Javadoc)
586
         *
587
         * @see com.iver.cit.gvsig.fmap.core.ICanReproject#getSourceProjection()
588
         */
589
        public String getSourceProjection() {
590
                if (originalEPSG == null)
591
                        getTableEPSG_and_shapeType();
592
                return originalEPSG;
593
        }
594

    
595
        /**
596
         * Las tablas con geometr?as est?n en la tabla GEOMETRY_COLUMNS y de
597
         * ah? sacamos en qu? proyecci?n est?n.
598
         * El problema es que si el usuario hace una vista de esa
599
         * tabla, no estar? dada de alta aqu? y entonces gvSIG
600
         * no se entera en qu? proyecci?n est? trabajando (y le
601
         * ponemos un -1 como mal menor). El -1 implica que luego
602
         * no podremos reproyectar al vuelo desde la base de datos.
603
         * OJO: ES SENSIBLE A MAYUSCULAS / MINUSCULAS!!!
604
         */
605
        private void getTableEPSG_and_shapeType() {
606
                try {
607
                        Statement stAux = ((ConnectionJDBC)conn).getConnection().createStatement();
608

    
609
//                        String sql = "SELECT * FROM GEOMETRY_COLUMNS WHERE F_TABLE_NAME = '"
610
//                                        + getTableName() + "' AND F_GEOMETRY_COLUMN = '" + getLyrDef().getFieldGeometry() + "'";
611
                        String sql;
612
                        if (getLyrDef().getSchema() == null || getLyrDef().getSchema().equals("")){
613
                                sql = "SELECT * FROM GEOMETRY_COLUMNS WHERE F_TABLE_SCHEMA = 'public' AND F_TABLE_NAME = '"
614
                                        + getLyrDef().getTableName() + "' AND F_GEOMETRY_COLUMN = '" + getLyrDef().getFieldGeometry() + "'";
615
                        }else{
616
                                sql = "SELECT * FROM GEOMETRY_COLUMNS WHERE F_TABLE_SCHEMA = '"+ getLyrDef().getSchema() + "' AND F_TABLE_NAME = '"
617
                                                + getLyrDef().getTableName() + "' AND F_GEOMETRY_COLUMN = '" + getLyrDef().getFieldGeometry() + "'";
618
                        }
619

    
620
                        ResultSet rs = stAux.executeQuery(sql);
621
                        rs.next();
622
                        originalEPSG = "" + rs.getInt("SRID");
623
                        String geometryType = rs.getString("TYPE");
624
                        int shapeType = FShape.MULTI;
625
                        if (geometryType.compareToIgnoreCase("POINT") == 0)
626
                                shapeType = FShape.POINT;
627
                        if (geometryType.compareToIgnoreCase("LINESTRING") == 0)
628
                                shapeType = FShape.LINE;
629
                        if (geometryType.compareToIgnoreCase("POLYGON") == 0)
630
                                shapeType = FShape.POLYGON;
631
                        if (geometryType.compareToIgnoreCase("MULTIPOINT") == 0)
632
                                shapeType = FShape.POINT;
633
                        if (geometryType.compareToIgnoreCase("MULTILINESTRING") == 0)
634
                                shapeType = FShape.LINE;
635
                        if (geometryType.compareToIgnoreCase("MULTIPOLYGON") == 0)
636
                                shapeType = FShape.POLYGON;
637

    
638
                        getLyrDef().setShapeType(shapeType);
639
                        rs.close();
640
                } catch (SQLException e) {
641
                        // TODO Auto-generated catch block
642
                        originalEPSG = "-1";
643
                        logger.error(e);
644
                        e.printStackTrace();
645
                }
646

    
647
        }
648

    
649
        /*
650
         * (non-Javadoc)
651
         *
652
         * @see com.iver.cit.gvsig.fmap.core.ICanReproject#getDestProjection()
653
         */
654
        public String getDestProjection() {
655
                return strEPSG;
656
        }
657

    
658
        /*
659
         * (non-Javadoc)
660
         *
661
         * @see com.iver.cit.gvsig.fmap.core.ICanReproject#setDestProjection(java.lang.String)
662
         */
663
        public void setDestProjection(String toEPSG) {
664
                this.strEPSG = toEPSG;
665
        }
666

    
667
        /*
668
         * (non-Javadoc)
669
         *
670
         * @see com.iver.cit.gvsig.fmap.core.ICanReproject#canReproject(java.lang.String)
671
         */
672
        public boolean canReproject(String toEPSGdestinyProjection) {
673
                // TODO POR AHORA, REPROYECTA SIEMPRE gvSIG.
674
                return false;
675
        }
676

    
677
        /*
678
         * (non-Javadoc)
679
         *
680
         * @see com.iver.cit.gvsig.fmap.drivers.DefaultDBDriver#doRelateID_FID()
681
         */
682
        protected void doRelateID_FID() throws DBException {
683
                hashRelate = new Hashtable();
684
                try {
685
                        String strSQL = "SELECT " + getLyrDef().getFieldID() + " FROM "
686
                                        + getLyrDef().getComposedTableName() + " ";
687
                                        // + getLyrDef().getWhereClause();
688
                        if (canReproject(strEPSG)) {
689
                                strSQL = strSQL
690
                                                + getCompoundWhere(strSQL, workingArea, strEPSG);
691
                        } else {
692
                                strSQL = strSQL
693
                                                + getCompoundWhere(strSQL, workingArea, originalEPSG);
694
                        }
695
                        strSQL = strSQL + " ORDER BY " + getLyrDef().getFieldID();
696
                        Statement s = ((ConnectionJDBC)getConnection()).getConnection().createStatement(
697
                                        ResultSet.TYPE_SCROLL_INSENSITIVE,
698
                                        ResultSet.CONCUR_READ_ONLY);
699
                        int fetchSize = 5000;
700
                        ResultSet r = s.executeQuery(strSQL);
701
                        int id = 0;
702
                        String gid;
703
                        while (r.next()) {
704
                                gid = r.getString(1);
705
                                Value aux = ValueFactory.createValue(gid);
706
                                hashRelate.put(aux, new Integer(id));
707
                                // System.out.println("ASOCIANDO CLAVE " + aux + " CON VALOR " + id);
708
                                id++;
709
                                // System.out.println("Row " + id + ":" + strAux);
710
                        }
711
                        s.close();
712
                        numReg = id;
713

    
714
                        /*
715
                         * for (int index = 0; index < getShapeCount(); index++) { Value aux =
716
                         * getFieldValue(index, idFID_FieldName-2); hashRelate.put(aux, new
717
                         * Integer(index)); // System.out.println("Row " + index + " clave=" +
718
                         * aux); }
719
                         */
720
                        /*
721
                         * int index = 0;
722
                         *
723
                         * while (rs.next()) { Value aux = getFieldValue(index,
724
                         * idFID_FieldName-2); hashRelate.put(aux, new Integer(index));
725
                         * index++; System.out.println("Row " + index + " clave=" + aux); }
726
                         * numReg = index;
727
                         */
728
                        // rs.beforeFirst();
729
                        /*
730
                         * } catch (com.hardcode.gdbms.engine.data.driver.DriverException e) { //
731
                         * TODO Auto-generated catch block e.printStackTrace();
732
                         */
733
                } catch (SQLException e) {
734
                        throw new DBException(e);
735
                }
736
        }
737

    
738
        public String getSqlTotal() {
739
                return sqlTotal;
740
        }
741

    
742
        /**
743
         * @return Returns the completeWhere.
744
         */
745
        public String getCompleteWhere() {
746
                return completeWhere;
747
        }
748

    
749
        /*
750
         * (non-Javadoc)
751
         *
752
         * @see com.iver.cit.gvsig.fmap.drivers.DefaultDBDriver#close()
753
         */
754
        public void close() {
755
                super.close();
756
                /*
757
                 * if (bCursorActivo) { try { // st =
758
                 * conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
759
                 * ResultSet.CONCUR_READ_ONLY); st.execute("CLOSE wkb_cursor_prov"); //
760
                 * st.close(); } catch (SQLException e) { // TODO Auto-generated catch
761
                 * block e.printStackTrace(); } bCursorActivo = false; }
762
                 */
763

    
764
        }
765

    
766
        /*
767
         * (non-Javadoc)
768
         *
769
         * @see com.iver.cit.gvsig.fmap.drivers.VectorialDatabaseDriver#getFeatureIterator(java.awt.geom.Rectangle2D,
770
         *      java.lang.String, java.lang.String[])
771
         */
772
        public IFeatureIterator getFeatureIterator(Rectangle2D r, String strEPSG,
773
                        String[] alphaNumericFieldsNeeded) throws ReadDriverException {
774
                String sqlAux = null;
775
                try {
776
                        if (workingArea != null)
777
                                r = r.createIntersection(workingArea);
778
                        // if (getLyrDef()==null){
779
                        // load();
780
                        // throw new DriverException("Fallo de la conexi?n");
781
                        // }
782
                        String strAux = getGeometryField(getLyrDef().getFieldGeometry());
783

    
784
                        boolean found = false;
785
                        if (alphaNumericFieldsNeeded != null) {
786
                                for (int i = 0; i < alphaNumericFieldsNeeded.length; i++) {
787
                                        strAux = strAux + ", " + alphaNumericFieldsNeeded[i];
788
                                        if (alphaNumericFieldsNeeded[i].equals(getLyrDef()
789
                                                        .getFieldID()))
790
                                                found = true;
791
                                }
792
                        }
793
                        // Nos aseguramos de pedir siempre el campo ID
794
                        if (found == false)
795
                                strAux = strAux + ", " + getLyrDef().getFieldID();
796

    
797
                        String sqlProv = "SELECT " + strAux + " FROM "
798
                                        + getLyrDef().getComposedTableName() + " ";
799
                                        // + getLyrDef().getWhereClause();
800

    
801

    
802
                        if (canReproject(strEPSG)) {
803
                                sqlAux = sqlProv + getCompoundWhere(sqlProv, r, strEPSG);
804
                        } else {
805
                                sqlAux = sqlProv + getCompoundWhere(sqlProv, r, originalEPSG);
806
                        }
807

    
808
                        System.out.println("SqlAux getFeatureIterator = " + sqlAux);
809

    
810
                        return getFeatureIterator(sqlAux);
811
                } catch (Exception e) {
812
//                        e.printStackTrace();
813
//                        SqlDriveExceptionType type = new SqlDriveExceptionType();
814
//            type.setDriverName("PostGIS Driver");
815
//            type.setSql(sqlAux);
816
//            type.setLayerName(getTableName());
817
//            type.setSchema(null);
818
            throw new ReadDriverException("PostGIS Driver",e);
819

    
820
//                        throw new DriverException(e);
821
                }
822
        }
823

    
824
        /* public void preProcess() throws EditionException {
825
                writer.preProcess();
826
        }
827

828
        public void process(IRowEdited row) throws EditionException {
829
                writer.process(row);
830
        }
831

832
        public void postProcess() throws EditionException {
833
                writer.postProcess();
834
        }
835

836
        public String getCapability(String capability) {
837
                return writer.getCapability(capability);
838
        }
839

840
        public void setCapabilities(Properties capabilities) {
841
                writer.setCapabilities(capabilities);
842
        }
843

844
        public boolean canWriteAttribute(int sqlType) {
845
                return writer.canWriteAttribute(sqlType);
846
        }
847

848
        public boolean canWriteGeometry(int gvSIGgeometryType) {
849
                return writer.canWriteGeometry(gvSIGgeometryType);
850
        }
851

852
        public void initialize(ITableDefinition layerDef) throws EditionException {
853
                writer.setCreateTable(false);
854
                writer.setWriteAll(false);
855
                // Obtenemos el DBLayerDefinition a partir del driver
856

857
                DBLayerDefinition dbLyrDef = getLyrDef();
858

859

860
                writer.initialize(dbLyrDef);
861
        }
862
*/
863
        public boolean isWritable() {
864
                return true;
865
        }
866

    
867
        public IWriter getWriter() {
868
                return writer;
869
        }
870

    
871
        public String[] getGeometryFieldsCandidates(IConnection conn, String table_name) throws DBException {
872
                ArrayList list = new ArrayList();
873
                try{
874
                Statement stAux = ((ConnectionJDBC)conn).getConnection().createStatement();
875
                 String[] tokens = table_name.split("\\u002E", 2);
876
        String sql;
877
        if (tokens.length > 1)
878
        {
879
                sql = "select * from GEOMETRY_COLUMNS WHERE F_TABLE_SCHEMA = '"
880
                 + tokens[0] + "' AND F_TABLE_NAME = '" +
881
            tokens[1] + "'";
882
        }
883
        else
884
        {
885
                sql = "select * from GEOMETRY_COLUMNS" +
886
            " where F_TABLE_NAME = " + "'" + table_name + "'";
887

    
888
        }
889

    
890
//                String sql = "SELECT * FROM GEOMETRY_COLUMNS WHERE F_TABLE_NAME = '"
891
//                                + table_name + "'";
892

    
893
                ResultSet rs = stAux.executeQuery(sql);
894
                while (rs.next())
895
                {
896
                        String geomCol = rs.getString("F_GEOMETRY_COLUMN");
897
                        list.add(geomCol);
898
                }
899
                rs.close(); stAux.close();
900
                } catch (SQLException e) {
901
                        throw new DBException(e);
902
                }
903
                return (String[]) list.toArray(new String[0]);
904
        }
905
//        public String[] getTableFields(IConnection conex, String table) throws DBException {
906
//                try{
907
//                Statement st = ((ConnectionJDBC)conex).getConnection().createStatement();
908
//        // ResultSet rs = dbmd.getTables(catalog, null, dbLayerDefinition.getTable(), null);
909
//                ResultSet rs = st.executeQuery("select * from " + table + " LIMIT 1");
910
//                ResultSetMetaData rsmd = rs.getMetaData();
911
//
912
//                String[] ret = new String[rsmd.getColumnCount()];
913
//
914
//                for (int i = 0; i < ret.length; i++) {
915
//                        ret[i] = rsmd.getColumnName(i+1);
916
//                }
917
//
918
//                return ret;
919
//                }catch (SQLException e) {
920
//                        throw new DBException(e);
921
//                }
922
//        }
923

    
924
}