Statistics
| Revision:

svn-gvsig-desktop / trunk / libraries / libDataSourceDBBaseDrivers / src / org / gvsig / data / datastores / vectorial / db / jdbc / postgresql / PostgresqlFeaturesWriter.java @ 20029

History | View | Annotate | Download (16.4 KB)

1
package org.gvsig.data.datastores.vectorial.db.jdbc.postgresql;
2

    
3
import java.io.ByteArrayOutputStream;
4
import java.io.File;
5
import java.io.IOException;
6
import java.io.PrintStream;
7
import java.io.RandomAccessFile;
8
import java.io.UnsupportedEncodingException;
9
import java.nio.channels.WritableByteChannel;
10
import java.sql.Connection;
11
import java.sql.DatabaseMetaData;
12
import java.sql.PreparedStatement;
13
import java.sql.ResultSet;
14
import java.sql.SQLException;
15
import java.sql.Statement;
16
import java.sql.Types;
17
import java.util.Iterator;
18

    
19
import org.gvsig.data.datastores.vectorial.ISelectiveWriter;
20
import org.gvsig.data.datastores.vectorial.db.DBAttributeDescriptor;
21
import org.gvsig.data.datastores.vectorial.db.DBFeatureType;
22
import org.gvsig.data.datastores.vectorial.db.jdbc.JDBCAttributeDescriptor;
23
import org.gvsig.data.datastores.vectorial.db.jdbc.JDBCFeaturesWriter;
24
import org.gvsig.data.datastores.vectorial.db.jdbc.JDBCTypes;
25
import org.gvsig.data.exception.InitializeException;
26
import org.gvsig.data.exception.InitializeWriterException;
27
import org.gvsig.data.exception.OpenException;
28
import org.gvsig.data.exception.ReadException;
29
import org.gvsig.data.exception.WriteException;
30
import org.gvsig.data.vectorial.IFeature;
31
import org.gvsig.data.vectorial.IFeatureAttributeDescriptor;
32
import org.gvsig.data.vectorial.IFeatureStore;
33
import org.gvsig.data.vectorial.IFeatureType;
34

    
35
import com.iver.cit.gvsig.fmap.core.FShape;
36
import com.iver.cit.gvsig.fmap.core.GeneralPathX;
37
import com.iver.cit.gvsig.fmap.core.IGeometry;
38
import com.iver.cit.gvsig.fmap.core.IGeometry3D;
39
import com.iver.cit.gvsig.fmap.core.ShapeFactory;
40
import com.vividsolutions.jts.io.WKBWriter;
41

    
42
class PostgresqlFeaturesWriter extends JDBCFeaturesWriter implements ISelectiveWriter {
43
        DBFeatureType featureType;
44
        boolean bCreateTable=false;
45
        private String toEncode;
46
        PostgresqlStore store;
47
        PostgresqlStoreParameters parameters;
48

    
49
        private PreparedStatement insertSt;
50
        private PreparedStatement updateSt;
51

    
52
        private static WKBWriter wkbWriter = new WKBWriter();
53

    
54
        PostgresqlFeaturesWriter(){
55
        }
56

    
57
        public void init(IFeatureStore store) {
58
                this.store = (PostgresqlStore)store;
59
                this.parameters=(PostgresqlStoreParameters)store.getParameters();
60

    
61
                this.featureType = (DBFeatureType)this.store.getDefaultFeatureType();
62
                conex = this.store.getConnection();
63

    
64
        }
65

    
66
        public void postProcess() throws OpenException, WriteException {
67
                try {
68
                        conex.commit();
69
                } catch (SQLException e) {
70
                        throw new WriteException(this.store.getName(),e);
71
                }
72
        }
73

    
74
        public void cancelActions() throws WriteException{
75
                try {
76
                        conex.rollback();
77
                } catch (SQLException e) {
78
                        throw new WriteException(this.store.getName(),e);
79
                }
80
        }
81

    
82

    
83
        public void preProcess() throws OpenException, InitializeWriterException {
84
                //??????????????????????????
85
                // ATENTION: We will transform (in PostGIS class; doubleQuote())
86
        // to UTF-8 strings. Then, we tell the PostgreSQL server
87
        // that we will use UTF-8, and it can translate
88
        // to its charset
89
        // Note: we have to translate to UTF-8 because
90
        // the server cannot manage UTF-16
91
                //??????????????????????????
92
                Statement st;
93

    
94

    
95
                try {
96
                        conex.setAutoCommit(false);
97
                        st = conex.createStatement();
98

    
99
                        if (bCreateTable) {
100
                                dropTableIfExist();
101

    
102
                                String sqlCreate = getSqlCreateSpatialTable(featureType);
103
                                System.out.println("sqlCreate =" + sqlCreate);
104
                                st.execute(sqlCreate);
105

    
106
//                                conex.commit();
107
                        }
108

    
109
//                        fieldManager = new JdbcFieldManager(((ConnectionJDBC)conex).getConnection(), lyrDef.getTableName());
110

    
111
                } catch (SQLException e) {
112
                        e.printStackTrace();
113
//                        throw new InitializeWriterException(getName(),e);
114
                }
115

    
116
//        ResultSet rsAux;
117
//                try {
118
////                                conex.setAutoCommit(false);
119
////                        alterTable();
120
//
121
////                        rsAux = st.executeQuery("SHOW server_encoding;");
122
////                rsAux.next();
123
////                String serverEncoding = rsAux.getString(1);
124
////                System.out.println("Server encoding = " + serverEncoding);
125
//                // st.execute("SET CLIENT_ENCODING TO 'UNICODE';");
126
//                // Intentamos convertir nuestras cadenas a ese encode.
127
////                setEncoding(serverEncoding);
128
//                } catch (SQLException e) {
129
//                        throw new InitializeWriterException("H2",e);
130
//                }
131

    
132
        }
133

    
134
        public void deleteFeature(IFeature feature) throws WriteException {
135
                Statement st;
136
                String sqlDelete = getSqlDeleteFeature(featureType, feature);
137
                System.out.println("sql = " + sqlDelete);
138
                try {
139
                        st = this.conex.createStatement();
140
                        st.execute(sqlDelete);
141
                } catch (SQLException e) {
142
                        throw new WriteException(this.store.getName(),e);
143
                }
144

    
145
        }
146

    
147
        public void insertFeature(IFeature feature) throws WriteException {
148

    
149
                DBFeatureType ftype = (DBFeatureType)feature.getType();
150

    
151
                try {
152
                        PreparedStatement ps=this.getInsertFeatureStatement(ftype);
153
                        Iterator it = ftype.iterator();
154

    
155
                        int index= 1;
156
                        while (it.hasNext()){
157
                                JDBCAttributeDescriptor fad=(JDBCAttributeDescriptor)it.next();
158
                                if (fad.isReadOnly() || fad.isAutoIncrement())
159
                                        continue;
160

    
161

    
162
                                loadValueInPreparedStatement(ps, index, fad, feature);
163
                                index++;
164
                        }
165
//                        ps.setObject(index, feature.get(ftype.getFieldIdIndex()));
166

    
167
                        ps.execute();
168

    
169
                } catch (SQLException e) {
170
                        throw new WriteException(this.store.getName(),e);
171
                }
172
        }
173

    
174
        private PreparedStatement getInsertFeatureStatement(DBFeatureType ftype) throws SQLException {
175
                if (this.insertSt == null){
176
                        StringBuffer fields = new StringBuffer();
177
                        StringBuffer values = new StringBuffer();
178
                        StringBuffer sql = new StringBuffer();
179

    
180
                        Iterator iter = ftype.iterator();
181
                        while (iter.hasNext()){
182
                                DBAttributeDescriptor fad=(DBAttributeDescriptor)iter.next();
183
                                String name = fad.getName();
184
                                if (fad.isReadOnly() || fad.isAutoIncrement())
185
                                        continue;
186
                                fields.append(name+",");
187
                                values.append("?,");
188

    
189
                        }
190
                        sql.append("INSERT INTO "+ftype.getTableID()+" (");
191
                        sql.append(fields.substring(0, fields.length()-1));
192
                        sql.append(") VALUES (");
193
                        sql.append(values.substring(0, values.length()-1));
194
                        sql.append(")");
195

    
196
                        this.insertSt= this.conex.prepareStatement(sql.toString());
197
                        System.out.println(sql.toString());
198
                } else{
199
                        this.insertSt.clearParameters();
200
                }
201
                return this.insertSt;
202

    
203
        }
204

    
205
        public void updateFeatureType(IFeatureType featureType) {
206
                this.featureType=(DBFeatureType)featureType;
207
        }
208

    
209
        /**
210
         * @param createTable
211
         *            The bCreateTable to set.
212
         */
213
        public void setCreateTable(boolean createTable) {
214
                bCreateTable = createTable;
215
        }
216
        boolean dropTableIfExist() throws SQLException{
217
                if (!this.existTable(parameters.getSchema(), parameters.getTableName())){
218
                        return false;
219
                }
220
                Statement st = conex.createStatement();
221
                st.execute("DROP TABLE " + parameters.tableID() + ";");
222
                st.close();
223
                return false;
224
        }
225
        private boolean existTable(String schema, String tableName) throws SQLException{
226
                boolean exists =false;
227
                DatabaseMetaData metadata = conex.getMetaData();
228

    
229
                ResultSet rs = metadata.getTables(null, schema, tableName, null);
230

    
231
                exists = !rs.isAfterLast();
232
                rs.close();
233

    
234
                return exists;
235
        }
236

    
237
        public void updateFeature(IFeature oldFeature, IFeature feature) throws WriteException, ReadException {
238

    
239
                DBFeatureType ftype = (DBFeatureType)feature.getType();
240

    
241
                try {
242
                        PreparedStatement ps=this.getUpdateFeatureStatement(ftype);
243
                        Iterator it = ftype.iterator();
244

    
245
                        int index= 1;
246
                        while (it.hasNext()){
247
                                JDBCAttributeDescriptor fad=(JDBCAttributeDescriptor)it.next();
248
                                if (fad.isPrimaryKey())
249
                                        continue;
250
                                loadValueInPreparedStatement(ps, index, fad, feature);
251
                                index++;
252
                        }
253

    
254
                        loadPkInPreparedStatement(ps, index, ftype, feature);
255

    
256
                        ps.execute();
257

    
258
                } catch (SQLException e) {
259
                        throw new WriteException(this.store.getName(),e);
260
                }
261
        }
262

    
263
        public void deleteAttribute(IFeatureAttributeDescriptor attribute) throws WriteException {
264
                try {
265
                        Statement st = conex.createStatement();
266
                        String sql = "ALTER TABLE " + parameters.tableID() + " DROP COLUMN "
267
                                + attribute.getName() + ";";
268
                        st.execute(sql);
269
                } catch (SQLException e) {
270
                        throw new WriteException(this.store.getName(),e);
271
                }
272
        }
273

    
274
        public void updateAttribute(IFeatureAttributeDescriptor oldAttribute, IFeatureAttributeDescriptor attribute) throws WriteException, ReadException {
275
                try {
276
                        Statement st = conex.createStatement();
277
                        String sql = "ALTER TABLE " + parameters.tableID() + " RENAME COLUMN "
278
                        + oldAttribute.getName() + " TO " + attribute.getName() + ";";
279
                        st.execute(sql);
280
                } catch (SQLException e) {
281
                        throw new WriteException(this.store.getName(),e);
282
                }
283
        }
284

    
285
        public void insertAttribute(IFeatureAttributeDescriptor attribute) throws WriteException {
286
                try {
287
                        Statement st = conex.createStatement();
288

    
289
                        String sql = "ALTER TABLE "
290
                                + parameters.tableID()
291
                                + " ADD COLUMN "
292
                                + attribute.getName()
293
                                + " "
294
                                + JDBCTypes.fieldTypeToString(attribute.getDataType())
295
                                + " "
296
                                + "DEFAULT " + attribute.getDefaultValue()
297
                                + ";";
298
                        st.execute(sql);
299
                } catch (SQLException e) {
300
                        throw new WriteException(this.store.getName(),e);
301
                }
302
        }
303

    
304
        public String getSqlCreateSpatialTable(DBFeatureType featureType) {
305

    
306
                String resul;
307
                /* boolean bExistGID = false;
308
                for (int i = 0; i < dbLayerDef.getFieldNames().length; i++) {
309
                        if (dbLayerDef.getFieldNames()[i].equalsIgnoreCase("gid")) {
310
                                bExistGID = true;
311
                                break;
312
                        }
313
                } */
314
                /* if (bExistGID) // Usamos el existente y no a?adimos ninguno nosotros
315
                        resul = "CREATE TABLE " + dbLayerDef.getTableName() + " (";
316
                else */
317
                // FJP: NUEVO: NO TOLERAMOS CAMPOS QUE SE LLAMEN GID. Lo reservamos para uso nuestro.
318
                resul = "CREATE TABLE " + this.parameters.tableID()
319
                                        + " ( " + featureType.getFieldId() +" serial PRIMARY KEY ";
320
                int j=0;
321
                for (int i = 0; i < featureType.size(); i++) {
322
                        IFeatureAttributeDescriptor fad=(IFeatureAttributeDescriptor)this.featureType.get(i);
323
                        String fieldType = fad.getDataType();
324
                        String strType = JDBCTypes.fieldTypeToString(fieldType);
325
                        /*
326
                         * if (fieldType == Types.VARCHAR) strType = strType + "(" +
327
                         * fieldsDescr[i].getFieldLength() + ")";
328
                         */
329
                        if (fad.getName().equalsIgnoreCase(featureType.getFieldId()))
330
                                continue;
331
                        resul = resul + ", " + fad.getName() + " "        + strType;
332
                        j++;
333
                }
334
                resul = resul + ");";
335
                return resul;
336
        }
337

    
338
        /** @deprecated ???
339
        *
340
        */
341
        public void setEncoding(String toEncode){
342
                if (toEncode.compareToIgnoreCase("SQL_ASCII") == 0){
343
                   this.toEncode = "ASCII";
344
                  } else {
345
                          this.toEncode = toEncode;
346
                  }
347
        }
348

    
349
        /** @deprecated ???
350
        *
351
        */
352
        public String getEncoding() {
353
                return toEncode;
354
        }
355

    
356
        /** @deprecated ???
357
        *
358
        */
359
        public boolean canWriteGeometry(int gvSIGgeometryType) {
360
                switch (gvSIGgeometryType) {
361
                case FShape.POINT:
362
                        return true;
363
                case FShape.LINE:
364
                        return true;
365
                case FShape.POLYGON:
366
                        return true;
367
                case FShape.ARC:
368
                        return false;
369
                case FShape.ELLIPSE:
370
                        return false;
371
                case FShape.MULTIPOINT:
372
                        return true;
373
                case FShape.TEXT:
374
                        return false;
375
                }
376
                return false;
377
        }
378

    
379

    
380
        /** @deprecated ???
381
        *
382
        */
383
        protected String addQuotes(Object value) {
384
                String retString;
385

    
386
                if (value != null) {
387
                        retString = "'" + doubleQuote(value) + "'";
388

    
389
                } else {
390
                        retString = "null";
391
                }
392

    
393
                return retString;
394
        }
395

    
396
        /** @deprecated ???
397
        *
398
        */
399
        private String doubleQuote(Object obj) {
400
                String aux = obj.toString().replaceAll("'", "''");
401
                StringBuffer strBuf = new StringBuffer(aux);
402
                ByteArrayOutputStream out = new ByteArrayOutputStream(strBuf.length());
403
                PrintStream printStream = new PrintStream(out);
404
                printStream.print(aux);
405
                String aux2 = "ERROR";
406
                try {
407
                        aux2 = out.toString(toEncode);
408
                        System.out.println(aux + " " + aux2);
409
                } catch (UnsupportedEncodingException e) {
410
                        // TODO Auto-generated catch block
411
                        e.printStackTrace();
412
                }
413

    
414
                return aux2;
415
        }
416

    
417
        private PreparedStatement getUpdateFeatureStatement(DBFeatureType dbFeatureType) throws SQLException{
418
                if (this.updateSt == null){
419
                        StringBuffer sqlBuf = new StringBuffer("UPDATE "
420
                                        + this.parameters.tableID() + " SET");
421
                        String sql = null;
422

    
423
                        Iterator iter = dbFeatureType.iterator();
424
                        while (iter.hasNext()){
425
                                IFeatureAttributeDescriptor fad=(IFeatureAttributeDescriptor)iter.next();
426
                                String name = fad.getName();
427
                                // El campo gid no lo actualizamos.
428
                                if (fad.isPrimaryKey())
429
                                        continue;
430
                                sqlBuf.append(" " + name + " = ? ,");
431

    
432
                        }
433
                        sqlBuf.deleteCharAt(sqlBuf.lastIndexOf(","));
434
                        sqlBuf.append(" WHERE ");
435
                        sqlBuf.append(getFliterForIDForPStatement(dbFeatureType));
436
                        sql = sqlBuf.toString();
437

    
438

    
439
                        this.updateSt= this.conex.prepareStatement(sql);
440
                } else{
441
                        this.updateSt.clearParameters();
442
                }
443
                return this.updateSt;
444

    
445
        }
446

    
447
        public String getSqlDeleteFeature(DBFeatureType dbFeatureType, IFeature feature) {
448
                StringBuffer sqlBuf = new StringBuffer("DELETE FROM "
449
                                + this.parameters.tableID() + " WHERE ");
450
                String sql = null;
451
                sqlBuf.append(PostgresqlStoreUtils.getFilterForID(dbFeatureType, feature));
452
                sql = sqlBuf.toString();
453

    
454
                return sql;
455
        }
456

    
457
        public static void create(PostgresqlStoreParameters parameters, IFeatureType featureType)throws InitializeWriterException, InitializeException {
458
                Connection con = PostgresqlStoreUtils.getConnection(parameters.getUrl(), parameters.getUser(), parameters.getPassw());
459

    
460
                StringBuffer sb=new StringBuffer();
461
                sb.append("CREATE TABLE ");
462
                sb.append(parameters.tableID());
463
                sb.append(" (");
464
                sb.append("id int, ");
465
                for (int i=0 ; i<featureType.size() ; i++){
466
                        IFeatureAttributeDescriptor descriptor=(IFeatureAttributeDescriptor)featureType.get(i);
467
                        String type = descriptor.getDataType();
468

    
469
                        if (type.equals(IFeatureAttributeDescriptor.TYPE_BOOLEAN)){
470
                                sb.append(descriptor.getName());
471
                                sb.append(" bit, ");
472
                        }else if (type.equals(IFeatureAttributeDescriptor.TYPE_BYTE)){
473
                                sb.append(descriptor.getName());
474
                                sb.append(" byte, ");
475
                        }else if (type.equals(IFeatureAttributeDescriptor.TYPE_DATE)){
476
                                sb.append(descriptor.getName());
477
                                sb.append(" date, ");
478
                        }else if (type.equals(IFeatureAttributeDescriptor.TYPE_DOUBLE)){
479
                                sb.append(descriptor.getName());
480
                                sb.append(" double, ");
481
                        }else if (type.equals(IFeatureAttributeDescriptor.TYPE_FLOAT)){
482
                                sb.append(descriptor.getName());
483
                                sb.append(" float, ");
484
                        }else if (type.equals(IFeatureAttributeDescriptor.TYPE_INT)){
485
                                sb.append(descriptor.getName());
486
                                sb.append(" int, ");
487
                        }else if (type.equals(IFeatureAttributeDescriptor.TYPE_LONG)){
488
                                sb.append(descriptor.getName());
489
                                sb.append(" bigint, ");
490
                        }else if (type.equals(IFeatureAttributeDescriptor.TYPE_STRING)){
491
                                sb.append(descriptor.getName());
492
                                sb.append(" varchar, ");
493
                        }else if (type.equals(IFeatureAttributeDescriptor.TYPE_GEOMETRY)){
494
                                sb.append(descriptor.getName());
495
                                sb.append(" other, ");
496
                        }else {
497
                                System.out.print(" ---- " + "TYPE UNKNOWN");
498
                        }
499
                }
500
                String createTable=sb.toString();
501
                createTable=createTable.substring(0, createTable.length()-2);
502
                createTable+=")";
503

    
504
                try{
505
                        Statement st=con.createStatement();
506
                        st.execute(createTable);
507
                        st.close();
508
                }
509
                catch(SQLException except){
510
                        throw new InitializeWriterException(parameters.getDataStoreName(),except);
511

    
512
                }
513
        }
514

    
515
        protected void loadPkInPreparedStatement(PreparedStatement ps,int paramIndex,DBFeatureType fType,IFeature feature) throws java.sql.SQLException{
516
                if (fType.getFieldsId().length != 1)
517
                        throw new UnsupportedOperationException("ID fields > 1");
518
                String id =fType.getFieldsId()[0];
519
                loadValueInPreparedStatement(ps, paramIndex, (JDBCAttributeDescriptor)fType.get(fType.getFieldIndex(id)), feature);
520
        }
521
        protected void loadValueInPreparedStatement(PreparedStatement ps,int paramIndex,JDBCAttributeDescriptor attr,IFeature feature) throws java.sql.SQLException{
522
                Object value = feature.get(attr.ordinal());
523
                if (value == null){
524
                        ps.setNull(paramIndex, attr.getSqlType());
525
                        return;
526
                }
527

    
528
                if (attr.getDataType() == IFeatureAttributeDescriptor.TYPE_GEOMETRY){
529
                        IGeometry geom =(IGeometry)feature.get(attr.ordinal());
530
                        ps.setBytes(
531
                                paramIndex,        wkbWriter.write(geom.toJTSGeometry())
532
                        );
533
                        return;
534
                }
535
                ps.setObject(paramIndex, feature.get(attr.ordinal()));
536
        }
537

    
538
        protected static String getFliterForIDForPStatement(DBFeatureType fType) {
539
                if (fType.getFieldsId().length != 1)
540
                        throw new UnsupportedOperationException("ID fields > 1");
541
                String id =fType.getFieldsId()[0];
542
                return id + " = ?";
543
        }
544
}