Statistics
| Revision:

svn-gvsig-desktop / branches / v2_0_0_prep / libraries / libFMap_daldb / src / org / gvsig / fmap / dal / store / postgresql / PostgreSQLStoreProviderWriter.java @ 28676

History | View | Annotate | Download (23.2 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
package org.gvsig.fmap.dal.store.postgresql;
29

    
30
import java.sql.Connection;
31
import java.sql.PreparedStatement;
32
import java.sql.SQLException;
33
import java.sql.Statement;
34
import java.util.ArrayList;
35
import java.util.Arrays;
36
import java.util.Collections;
37
import java.util.Iterator;
38
import java.util.List;
39

    
40
import org.gvsig.fmap.dal.DataTypes;
41
import org.gvsig.fmap.dal.exception.DataException;
42
import org.gvsig.fmap.dal.exception.InitializeException;
43
import org.gvsig.fmap.dal.feature.Feature;
44
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
45
import org.gvsig.fmap.dal.feature.FeatureType;
46
import org.gvsig.fmap.dal.feature.exception.PerformEditingException;
47
import org.gvsig.fmap.dal.feature.spi.FeatureData;
48
import org.gvsig.fmap.dal.feature.spi.FeatureReferenceProviderServices;
49
import org.gvsig.fmap.dal.store.jdbc.JDBCExecutePreparedSQLException;
50
import org.gvsig.fmap.dal.store.jdbc.JDBCExecuteSQLException;
51
import org.gvsig.fmap.dal.store.jdbc.JDBCPreparingSQLException;
52
import org.gvsig.fmap.dal.store.jdbc.JDBCSQLException;
53
import org.gvsig.fmap.dal.store.jdbc.JDBCUpdateWithoutChangesException;
54
import org.gvsig.fmap.dal.store.postgresql.PostgreSQLHelper.TransactionalAction;
55
import org.gvsig.fmap.geom.Geometry;
56
import org.slf4j.Logger;
57
import org.slf4j.LoggerFactory;
58

    
59
public class PostgreSQLStoreProviderWriter extends PostgreSQLStoreProvider {
60

    
61
        final static private Logger logger = LoggerFactory
62
                        .getLogger(PostgreSQLStoreProvider.class);
63
        private String sqlForAppend;
64
        private List attrsForAppendMode;
65

    
66

    
67
        public PostgreSQLStoreProviderWriter() {
68
                super();
69
        }
70

    
71
        public PostgreSQLStoreProviderWriter(PostgreSQLStoreParameters params)
72
                        throws InitializeException {
73
                super(params);
74
        }
75

    
76
        public boolean allowWrite() {
77
                if (directSQLMode) {
78
                        return false;
79
                }
80
                if (params.getPkFields() == null || params.getPkFields().length > 0) {
81
                        FeatureType ft = null;
82
                        try {
83
                                ft = this.store.getDefaultFeatureType();
84
                        } catch (DataException e) {
85
                                logger.error("Excepton get default Feature Type", e);
86
                        }
87

    
88
                        if (ft == null) {
89
                                return false;
90
                        }
91
                        FeatureAttributeDescriptor attr;
92
                        Iterator iter = ft.iterator();
93
                        while (iter.hasNext()){
94
                                attr = (FeatureAttributeDescriptor) iter.next();
95
                                if (attr.isPrimaryKey()){
96
                                        return true;
97
                                }
98
                        }
99
                        return false;
100

    
101
                } else {
102
                        return true;
103
                }
104
        }
105

    
106

    
107
        public boolean canWriteGeometry(int geometryType) throws DataException {
108
                FeatureAttributeDescriptor geomAttr = this.store
109
                                .getDefaultFeatureType().getAttributeDescriptor(
110
                                                this.store.getDefaultFeatureType()
111
                                                                .getDefaultGeometryAttributeName());
112
                if (geomAttr == null) {
113
                        return false;
114
                }
115
                switch (geomAttr.getGeometryType()) {
116
                case Geometry.TYPES.GEOMETRY:
117
                        return true;
118

    
119
                case Geometry.TYPES.MULTISURFACE:
120
                        return geometryType == Geometry.TYPES.MULTISURFACE
121
                                        || geometryType == Geometry.TYPES.SURFACE;
122

    
123
                case Geometry.TYPES.MULTIPOINT:
124
                        return geometryType == Geometry.TYPES.MULTIPOINT
125
                                        || geometryType == Geometry.TYPES.POINT;
126

    
127
                case Geometry.TYPES.MULTICURVE:
128
                        return geometryType == Geometry.TYPES.MULTICURVE
129
                                        || geometryType == Geometry.TYPES.CURVE;
130

    
131
                case Geometry.TYPES.MULTISOLID:
132
                        return geometryType == Geometry.TYPES.MULTISOLID
133
                                        || geometryType == Geometry.TYPES.SOLID;
134

    
135
                default:
136
                        return geometryType == geomAttr.getGeometryType();
137
                }
138

    
139
        }
140

    
141
        public boolean allowAutomaticValues() {
142
                return true;
143
        }
144

    
145
        public void performEditing(final Iterator deleteds,
146
                        final Iterator inserteds, final Iterator updateds,
147
                        final Iterator originalFeatureTypesUpdated)
148
                        throws PerformEditingException {
149

    
150
                boolean countChanged = deleteds.hasNext() || inserteds.hasNext();
151

    
152

    
153
                TransactionalAction action = new TransactionalAction() {
154

    
155
                        public Object action(Connection conn) throws DataException {
156

    
157
                                if (originalFeatureTypesUpdated.hasNext()) {
158
                                        FeatureType original = (FeatureType) originalFeatureTypesUpdated
159
                                                        .next();
160
                                        FeatureType target = store.getFeatureType(original.getId());
161
                                        performUpdateTable(conn, original, target);
162
                                }
163

    
164
                                List pkAttributes = null;
165

    
166
                                if (deleteds.hasNext()) {
167
                                        pkAttributes = getPkAttributes();
168
                                        performDeletes(conn, deleteds, pkAttributes);
169
                                }
170

    
171
                                if (updateds.hasNext()) {
172
                                        if (pkAttributes == null) {
173
                                                pkAttributes = getPkAttributes();
174
                                        }
175
                                        performUpdates(conn, updateds, pkAttributes);
176
                                }
177

    
178
                                if (inserteds.hasNext()) {
179
                                        performInserts(conn, inserteds);
180
                                }
181

    
182
                                return null;
183
                        }
184

    
185
                        public boolean continueTransactionAllowed() {
186
                                return false;
187
                        }
188

    
189
                };
190
                try {
191
                        this.helper.doConnectionAction(action);
192

    
193
                        this.initFeatureType();
194
                        if (countChanged) {
195
                                resetCount();
196
                        }
197

    
198

    
199
                } catch (Exception e) {
200
                        throw new PerformEditingException(this.getName(), e);
201
                }
202
        }
203

    
204
        private List getPkAttributes() throws DataException {
205
                ArrayList list = new ArrayList();
206
                Iterator iter = this.store.getDefaultFeatureType().iterator();
207
                FeatureAttributeDescriptor attr;
208
                while (iter.hasNext()) {
209
                        attr = (FeatureAttributeDescriptor) iter.next();
210
                        if (attr.isPrimaryKey()) {
211
                                list.add(attr);
212
                        }
213
                }
214

    
215
                return Collections.unmodifiableList(list);
216
        }
217

    
218
        private void appendToSQLPreparedPkWhereClause(StringBuilder sql,
219
                        List pkAttributes) {
220
                sql.append(" Where ");
221
                FeatureAttributeDescriptor attr;
222
                for (int i = 0; i < pkAttributes.size() - 1; i++) {
223
                        attr = (FeatureAttributeDescriptor) pkAttributes.get(i);
224
                        sql.append(helper.escapeFieldName(attr.getName()));
225
                        sql.append(" = ? AND ");
226
                }
227
                attr = (FeatureAttributeDescriptor) pkAttributes.get(pkAttributes
228
                                .size() - 1);
229
                sql.append(helper.escapeFieldName(attr.getName()));
230
                sql.append(" = ? ");
231
        }
232

    
233
        private void addToListFeatureValues(Feature feature, List attributes,
234
                        List values) throws DataException {
235
                FeatureAttributeDescriptor attr, attrOfList;
236
                FeatureType fType = feature.getType();
237
                for (int i = 0; i < attributes.size(); i++) {
238
                        attrOfList = (FeatureAttributeDescriptor) attributes.get(i);
239
                        attr = fType.getAttributeDescriptor(attrOfList.getName());
240
                        if (attr == null) {
241
                                if (attrOfList.isPrimaryKey()) {
242
                                        // FIXME excepton
243
                                        throw new RuntimeException("pk attribute '"
244
                                                        + attrOfList.getName() + "' not found in feature");
245
                                }
246
                                values.add(helper.dalValueToJDBC(attr, attrOfList
247
                                                .getDefaultValue()));
248
                        } else {
249
                                values.add(helper.dalValueToJDBC(attr, feature.get(attr
250
                                                .getIndex())));
251
                        }
252
                }
253
        }
254

    
255
        private void addToListFeatureValues(FeatureData featureData,
256
                        List attributes, List values) throws DataException {
257
                FeatureAttributeDescriptor attr, attrOfList;
258
                FeatureType fType = featureData.getType();
259
                for (int i = 0; i < attributes.size(); i++) {
260
                        attrOfList = (FeatureAttributeDescriptor) attributes.get(i);
261
                        attr = fType.getAttributeDescriptor(attrOfList.getName());
262
                        if (attr == null) {
263
                                if (attrOfList.isPrimaryKey()) {
264
                                        // FIXME excepton
265
                                        throw new RuntimeException("pk attribute '"
266
                                                        + attrOfList.getName() + "' not found in feature");
267
                                }
268
                                values.add(helper.dalValueToJDBC(attr, attrOfList
269
                                                .getDefaultValue()));
270
                        } else {
271
                                values.add(helper.dalValueToJDBC(attr, featureData.get(attr
272
                                                .getIndex())));
273
                                if (attr.getDataType() == DataTypes.GEOMETRY) {
274
                                        values.add(helper.getPostgisSRID(attr.getSRS()));
275
                                }
276
                        }
277
                }
278
        }
279

    
280
        private void performDeletes(Connection conn, Iterator deleteds,
281
                        List pkAttributes) throws DataException {
282

    
283
                if (pkAttributes.size() < 0) {
284
                        // FIXME Exception
285
                        throw new RuntimeException("Operation requires missing pk");
286
                }
287

    
288
                // ************ Prepare SQL ****************
289
                StringBuilder sqlb = new StringBuilder();
290
                sqlb.append("Delete from ");
291
                sqlb.append(params.tableID());
292
                appendToSQLPreparedPkWhereClause(sqlb, pkAttributes);
293
                String sql = sqlb.toString();
294
                // ************ Prepare SQL (end) ****************
295

    
296
                executeRemovePreparedStatement(conn, sql, pkAttributes, deleteds);
297
        }
298

    
299
        private void performUpdates(Connection conn, Iterator updateds,
300
                        List pkAttributes) throws DataException {
301
                /*
302
                 * UPDATE [ ONLY ] table [ [ AS ] alias ] SET { column = { expression |
303
                 * DEFAULT } | ( column [, ...] ) = ( { expression | DEFAULT } [, ...] )
304
                 * } [, ...] [ FROM fromlist ] [ WHERE condition ] [ RETURNING * |
305
                 * output_expression [ AS output_name ] [, ...] ]
306
                 */
307

    
308
                if (pkAttributes.size() < 0) {
309
                        // FIXME Exception
310
                        throw new RuntimeException("Operation requires missing pk");
311
                }
312

    
313
                // ************ Prepare SQL ****************
314
                StringBuilder sqlb = new StringBuilder();
315
                sqlb.append("UPDATE ");
316
                sqlb.append(params.tableID());
317

    
318
                sqlb.append(" SET (");
319

    
320
                FeatureType type = this.store.getDefaultFeatureType();
321

    
322
                Iterator iter = type.iterator();
323
                FeatureAttributeDescriptor attr;
324
                List updateAttrs = new ArrayList();
325
                while (iter.hasNext()) {
326
                        attr = (FeatureAttributeDescriptor) iter.next();
327
                        if (attr.isPrimaryKey() || attr.isAutomatic() || attr.isReadOnly()) {
328
                                continue;
329
                        }
330
                        updateAttrs.add(attr);
331

    
332
                }
333
                if (updateAttrs.size() < 1) {
334
                        // FIXME exception
335
                        throw new RuntimeException("no fields to set");
336
                }
337

    
338
                for (int i = 0; i < updateAttrs.size() - 1; i++) {
339
                        attr = (FeatureAttributeDescriptor) updateAttrs.get(i);
340
                        sqlb.append(helper.escapeFieldName(attr.getName()));
341
                        sqlb.append(", ");
342
                }
343
                attr = (FeatureAttributeDescriptor) updateAttrs
344
                                .get(updateAttrs.size() - 1);
345
                sqlb.append(helper.escapeFieldName(attr.getName()));
346

    
347
                sqlb.append(") = (");
348
                for (int i = 0; i < updateAttrs.size() - 1; i++) {
349
                        attr = (FeatureAttributeDescriptor) updateAttrs.get(i);
350
                        if (attr.getDataType() == DataTypes.GEOMETRY) {
351
                                sqlb.append("GeomFromWKB(?, ?), ");
352
                        } else {
353
                                sqlb.append("?, ");
354
                        }
355
                }
356
                attr = (FeatureAttributeDescriptor) updateAttrs
357
                                .get(updateAttrs.size() - 1);
358
                if (attr.getDataType() == DataTypes.GEOMETRY) {
359
                        sqlb.append("GeomFromWKB(?, ?) ");
360
                } else {
361
                        sqlb.append("? ");
362
                }
363

    
364
                sqlb.append(") ");
365
                appendToSQLPreparedPkWhereClause(sqlb, pkAttributes);
366

    
367
                String sql = sqlb.toString();
368
                // ************ Prepare SQL (end) ****************
369

    
370
                updateAttrs.addAll(pkAttributes);
371

    
372
                try {
373
                        executeUpdatePreparedStatement(conn, sql, updateAttrs, updateds);
374
                } catch (Exception e) {
375
                        // TODO Auto-generated catch block
376
                        e.printStackTrace();
377
                }
378
        }
379

    
380
        private void executeRemovePreparedStatement(Connection conn, String sql,
381
                        List attributes, Iterator featureReferences) throws DataException {
382
                PreparedStatement st;
383
                try {
384
                        st = conn.prepareStatement(sql);
385
                } catch (SQLException e) {
386
                        throw new JDBCPreparingSQLException(sql, e);
387
                }
388
                try {
389
                        List values = new ArrayList();
390
                        FeatureReferenceProviderServices featureRef;
391
                        FeatureType featureType;
392
                        while (featureReferences.hasNext()) {
393
                                st.clearParameters();
394
                                featureRef = (FeatureReferenceProviderServices) featureReferences
395
                                                .next();
396
                                values.clear();
397
                                featureType = this.store.getFeatureType(featureRef
398
                                                .getFeatureTypeId());
399

    
400
                                Iterator iter = attributes.iterator();
401
                                FeatureAttributeDescriptor attr;
402
                                while (iter.hasNext()) {
403
                                        attr = (FeatureAttributeDescriptor) iter.next();
404
                                        values.add(helper.dalValueToJDBC(attr, featureRef
405
                                                        .getKeyValue(attr.getName())));
406
                                }
407

    
408
                                for (int i = 0; i < values.size(); i++) {
409
                                        st.setObject(i + 1, values.get(i));
410
                                }
411
                                try {
412
                                        int nAffected =st.executeUpdate();
413
                                        if (nAffected == 0) {
414
                                                throw new JDBCUpdateWithoutChangesException(sql, values);
415
                                        }
416
                                        if (nAffected > 1){
417
                                                logger.warn("Remove statement affectst to {} rows: {}",
418
                                                                nAffected, sql);
419
                                        }
420

    
421
                                } catch (SQLException e) {
422
                                        throw new JDBCExecutePreparedSQLException(sql, values, e);
423
                                }
424

    
425
                        }
426
                } catch (SQLException e) {
427
                        throw new JDBCSQLException(e);
428
                } finally {
429
                        try {st.close();} catch (SQLException e) {        };
430
                }
431

    
432
        }
433

    
434
        private void executeUpdatePreparedStatement(Connection conn, String sql,
435
                        List attributes, Iterator featureDatas) throws DataException {
436
                PreparedStatement st;
437
                try {
438
                        st = conn.prepareStatement(sql);
439
                } catch (SQLException e) {
440
                        throw new JDBCPreparingSQLException(sql, e);
441
                }
442
                try {
443
                        List values = new ArrayList();
444
                        FeatureData featureData;
445
                        while (featureDatas.hasNext()) {
446
                                st.clearParameters();
447
                                featureData = (FeatureData) featureDatas.next();
448
                                values.clear();
449
                                addToListFeatureValues(featureData, attributes, values);
450
                                for (int i = 0; i < values.size(); i++) {
451
                                        st.setObject(i + 1, values.get(i));
452
                                }
453
                                try {
454
                                        if (st.executeUpdate() == 0) {
455
                                                throw new JDBCUpdateWithoutChangesException(sql, values);
456
                                        }
457
                                } catch (SQLException e) {
458
                                        throw new JDBCExecutePreparedSQLException(sql, values, e);
459
                                }
460

    
461
                        }
462
                } catch (SQLException e) {
463
                        throw new JDBCSQLException(e);
464
                } finally {
465
                        try {st.close();} catch (SQLException e) {        };
466
                }
467

    
468
        }
469

    
470
        private void performInserts(Connection conn, Iterator inserteds)
471
                        throws DataException {
472

    
473
                StringBuilder sqlb = new StringBuilder();
474
                List attrs = new ArrayList();
475

    
476
                prepareSQLAndAttributeListForInser(sqlb, attrs);
477

    
478
                String sql = sqlb.toString();
479
                PreparedStatement st;
480
                try {
481
                        st = conn.prepareStatement(sql);
482
                } catch (SQLException e) {
483
                        throw new JDBCPreparingSQLException(sql, e);
484
                }
485
                try {
486
                        while (inserteds.hasNext()) {
487
                                perfomInsert(conn, st, sql, (FeatureData) inserteds.next(),
488
                                                attrs);
489
                        }
490
                } finally {
491
                        try {
492
                                st.close();
493
                        } catch (SQLException e) {
494
                        }
495
                        ;
496
                }
497
        }
498

    
499
        private void prepareSQLAndAttributeListForInser(StringBuilder sqlb,
500
                        List attributes) throws DataException {
501
                /*
502
                 * INSERT INTO table [ ( column [, ...] ) ] { DEFAULT VALUES | VALUES (
503
                 * { expression | DEFAULT } [, ...] ) [, ...] | query } [ RETURNING * |
504
                 * output_expression [ AS output_name ] [, ...] ]
505
                 */
506

    
507
                sqlb.append("INSERT INTO ");
508
                sqlb.append(params.tableID());
509

    
510
                sqlb.append(" (");
511

    
512
                FeatureType type = this.store.getDefaultFeatureType();
513

    
514
                Iterator iter = type.iterator();
515
                FeatureAttributeDescriptor attr;
516
                while (iter.hasNext()) {
517
                        attr = (FeatureAttributeDescriptor) iter.next();
518
                        if (attr.isAutomatic() || attr.isReadOnly()) {
519
                                continue;
520
                        }
521
                        attributes.add(attr);
522

    
523
                }
524
                if (attributes.size() < 1) {
525
                        // FIXME exception
526
                        throw new RuntimeException("no fields to set");
527
                }
528

    
529
                for (int i = 0; i < attributes.size() - 1; i++) {
530
                        attr = (FeatureAttributeDescriptor) attributes.get(i);
531
                        sqlb.append(helper.escapeFieldName(attr.getName()));
532
                        sqlb.append(", ");
533
                }
534
                attr = (FeatureAttributeDescriptor) attributes
535
                                .get(attributes.size() - 1);
536
                sqlb.append(helper.escapeFieldName(attr.getName()));
537

    
538
                sqlb.append(") VALUES (");
539
                for (int i = 0; i < attributes.size() - 1; i++) {
540
                        attr = (FeatureAttributeDescriptor) attributes.get(i);
541
                        if (attr.getDataType() == DataTypes.GEOMETRY) {
542
                                sqlb.append("GeomFromWKB(?,?), ");
543
                        } else {
544
                                sqlb.append("?, ");
545
                        }
546
                }
547
                attr = (FeatureAttributeDescriptor) attributes
548
                                .get(attributes.size() - 1);
549
                if (attr.getDataType() == DataTypes.GEOMETRY) {
550
                        sqlb.append("GeomFromWKB(?,?) ");
551
                } else {
552
                        sqlb.append("? ");
553
                }
554

    
555
                sqlb.append(") ");
556

    
557
        }
558

    
559
        private void perfomInsert(Connection conn, PreparedStatement insertSt,
560
                        String sql, FeatureData feature, List attributes)
561
                        throws DataException {
562

    
563
                try {
564
                        insertSt.clearParameters();
565
                        List values = new ArrayList();
566
                        addToListFeatureValues(feature, attributes, values);
567
                        FeatureAttributeDescriptor attr;
568
                        int j = 1;
569
                        for (int i = 0; i < values.size(); i++) {
570
                                insertSt.setObject(j, values.get(i));
571
                                j++;
572
                        }
573
                        if (logger.isDebugEnabled()) {
574
                                logger.debug("Executing insert. sql={} value={}", new Object[] {
575
                                                sql,
576
                                                values });
577
                        }
578
                        try {
579
                                insertSt.execute();
580
                        } catch (SQLException e) {
581
                                throw new JDBCExecutePreparedSQLException(sql, values, e);
582
                        }
583

    
584
                } catch (SQLException e1) {
585
                        throw new JDBCSQLException(e1);
586
                }
587
        }
588

    
589
        private void performUpdateTable(Connection conn, FeatureType original,
590
                        FeatureType target) throws DataException {
591

    
592
                /*
593
                 *
594
                 * ALTER TABLE [ ONLY ] name [ * ] action [, ... ]
595
                 */
596

    
597

    
598
                List toDrop = new ArrayList();
599
                List toAdd = new ArrayList();
600
                List toAlter = new ArrayList();
601

    
602
                List sqlgeomColumnsChanges = new ArrayList();
603

    
604
                FeatureAttributeDescriptor attrOrg;
605
                FeatureAttributeDescriptor attrTrg;
606
                Iterator attrs = original.iterator();
607
                while (attrs.hasNext()) {
608
                        attrOrg = (FeatureAttributeDescriptor) attrs.next();
609
                        attrTrg = target.getAttributeDescriptor(attrOrg.getName());
610
                        if (attrTrg == null) {
611
                                toDrop.add(getSqlActionDropField(attrOrg));
612
                                if (attrOrg.getDataType() == DataTypes.GEOMETRY) {
613
                                        sqlgeomColumnsChanges.add(getSqlGeometyFieldDrop(attrOrg));
614
                                }
615
                        } else {
616
                                toAlter.addAll(getSqlActionsAlterField(attrOrg, attrTrg,
617
                                                sqlgeomColumnsChanges));
618
                        }
619

    
620
                }
621
                attrs = target.iterator();
622
                while (attrs.hasNext()) {
623
                        attrTrg = (FeatureAttributeDescriptor) attrs.next();
624
                        if (original.getAttributeDescriptor(attrTrg.getName()) == null) {
625
                                if (attrTrg.getDataType() == DataTypes.GEOMETRY) {
626
                                        sqlgeomColumnsChanges.add(helper.getSqlGeometyFieldAdd(
627
                                                        attrTrg, params.getTable(), params.getSchema()));
628
                                } else {
629
                                        toAdd.add(getSqlActionAddField(attrTrg));
630
                                }
631
                        }
632
                }
633

    
634
                StringBuilder sqlb = new StringBuilder();
635

    
636
                sqlb.append("ALTER TABLE ");
637
                sqlb.append(params.tableID());
638
                sqlb.append(' ');
639

    
640
                List actions = new ArrayList();
641
                actions.addAll(toDrop);
642
                actions.addAll(toAlter);
643
                actions.addAll(toAdd);
644

    
645
                if (actions.size() < 1) {
646
                        return;
647
                }
648

    
649
                for (int i = 0; i < actions.size() - 1; i++) {
650
                        sqlb.append(actions.get(i));
651
                        sqlb.append(", ");
652
                }
653
                sqlb.append(actions.get(actions.size() - 1));
654

    
655

    
656
                String sql = sqlb.toString();
657

    
658
                Statement st = null;
659

    
660
                try {
661
                        st = conn.createStatement();
662
                } catch (SQLException e1) {
663
                        throw new JDBCSQLException(e1);
664
                }
665
                try{
666
                        st.execute(sql);
667
                        Iterator iter = sqlgeomColumnsChanges.iterator();
668
                        while (iter.hasNext()) {
669
                                sql = (String) iter.next();
670
                                st.execute(sql);
671
                        }
672
                } catch (SQLException e1) {
673
                        throw new JDBCExecuteSQLException(sql, e1);
674
                } finally{
675
                        try { st.close(); } catch (Exception e) { logger.error("Exception closing statement", e); };
676
                }
677

    
678
        }
679

    
680
        private Object getSqlGeometyFieldDrop(FeatureAttributeDescriptor attr) {
681
                StringBuilder strb = new StringBuilder();
682

    
683
                strb.append("Delete from geometry_columns where f_geometry_column = '");
684
                strb.append(attr.getName());
685
                strb.append("' and f_table_nam = '");
686
                strb.append(params.getTable());
687
                strb.append("' and f_table_schema = ");
688
                if (params.getSchema() == null || params.getSchema().length() == 0) {
689
                        strb.append("current_schema()");
690
                } else {
691
                        strb.append("'");
692
                        strb.append(params.getSchema());
693
                        strb.append("'");
694
                }
695
                if (params.getCatalog() != null && params.getCatalog().length() > 0) {
696
                        strb.append(" and f_table_catalog = '");
697
                        strb.append(params.getCatalog());
698
                        strb.append("'");
699
                }
700
                return strb.toString();
701
        }
702

    
703

    
704
        private String getSqlActionDropField(FeatureAttributeDescriptor attr) {
705
                // DROP [ COLUMN ] column
706
                return " DROP COLUMN " + this.helper.escapeFieldName(attr.getName());
707
        }
708

    
709
        private List getSqlActionsAlterField(FeatureAttributeDescriptor attrOrg,
710
                        FeatureAttributeDescriptor attrTrg, List sqlgeomColumnsChanges)
711
                        throws DataException {
712
                //
713
                List actions = new ArrayList();
714
                StringBuilder strb;
715
                if (attrOrg.getDataType() != attrTrg.getDataType()) {
716
                        // ALTER COLUMN {col} TYPE {type} character varying(35)
717
                        strb = new StringBuilder();
718
                        strb.append("ALTER COLUMN ");
719
                        strb.append(helper.escapeFieldName(attrTrg.getName()));
720
                        strb.append(" ");
721
                        strb.append(helper.getSqlColumnTypeDescription(attrTrg));
722

    
723
                        actions.add(strb.toString());
724
                        if (attrOrg.getDataType() == DataTypes.GEOMETRY) {
725
                                sqlgeomColumnsChanges.add(getSqlGeometyFieldDrop(attrOrg));
726
                        }
727
                        if (attrTrg.getDataType() == DataTypes.GEOMETRY) {
728
                                sqlgeomColumnsChanges.addAll(Arrays.asList(helper
729
                                                .getSqlGeometyFieldAdd(attrTrg, params.getTable(),
730
                                                                params.getSchema())));
731
                        }
732
                }
733
                if (attrOrg.getDataType() == attrTrg.getDataType()
734
                                && attrTrg.getDataType() == DataTypes.GEOMETRY) {
735
                        // TODO Checks SRS and GeomType/Subtype
736
                }
737

    
738
                if (attrOrg.allowNull() != attrTrg.allowNull()) {
739
                        // ALTER [ COLUMN ] column { SET | DROP } NOT NULL
740

    
741
                        strb = new StringBuilder();
742
                        strb.append("ALTER COLUMN ");
743
                        strb.append(helper.escapeFieldName(attrTrg.getName()));
744
                        strb.append(' ');
745
                        if (attrTrg.allowNull()) {
746
                                strb.append("SET ");
747
                        } else {
748
                                strb.append("DROP ");
749
                        }
750
                        strb.append("NOT NULL");
751
                        actions.add(strb.toString());
752
                }
753

    
754
                if (attrOrg.getDefaultValue() != attrTrg.getDefaultValue()) {
755
                        if (attrTrg.getDefaultValue() == null) {
756
                                // ALTER [ COLUMN ] column DROP DEFAULT
757

    
758
                                strb = new StringBuilder();
759
                                strb.append("ALTER COLUMN ");
760
                                strb.append(helper.escapeFieldName(attrTrg.getName()));
761
                                strb.append(" DROP DEFAULT");
762
                                actions.add(strb.toString());
763
                        } else if (!attrTrg.getDefaultValue().equals(
764
                                        attrOrg.getDefaultValue())) {
765
                                // ALTER [ COLUMN ] column DROP DEFAULT
766

    
767
                                strb = new StringBuilder();
768
                                strb.append("ALTER COLUMN ");
769
                                strb.append(helper.escapeFieldName(attrTrg.getName()));
770
                                strb.append(" SET DEFAULT");
771
                                strb.append(helper.dalValueToJDBC(attrTrg, attrTrg
772
                                                .getDefaultValue()));
773
                                actions.add(strb.toString());
774
                        }
775
                }
776

    
777
                return actions;
778
        }
779

    
780
        private String getSqlActionAddField(FeatureAttributeDescriptor attr)
781
                        throws DataException {
782
                StringBuilder strb = new StringBuilder();
783
                strb.append("ADD ");
784
                this.helper.addSqlFiledDescription(attr, strb);
785
                return strb.toString();
786
        }
787

    
788
        public boolean supportsAppendMode() {
789
                return true;
790
        }
791

    
792
        public void endAppend() throws DataException {
793
                this.loadMetadata();
794
        }
795

    
796
        public void append(final FeatureData featureData) throws DataException {
797
                TransactionalAction action = new TransactionalAction() {
798
                        public Object action(Connection conn) throws DataException {
799

    
800
                                PreparedStatement st;
801
                                try {
802
                                        st = conn.prepareStatement(sqlForAppend);
803
                                } catch (SQLException e) {
804
                                        throw new JDBCPreparingSQLException(sqlForAppend, e);
805
                                }
806
                                try {
807
//                                        perfomInsert(conn, st, sqlForAppend, featureData, attrsForAppendMode);
808
                                } finally {
809
                                        try {st.close();} catch (SQLException e) {        };
810
                                }
811
                                return null;
812
                        }
813

    
814
                        public boolean continueTransactionAllowed() {
815
                                return false;
816
                        }
817
                };
818
                try {
819
                        this.helper.doConnectionAction(action);
820

    
821
                        resetCount();
822

    
823
                } catch (Exception e) {
824
                        throw new PerformEditingException(this.getName(), e);
825
                }
826
        }
827

    
828
        public void beginAppend() throws DataException {
829
                StringBuilder sqlb = new StringBuilder();
830
                List attrs = new ArrayList();
831

    
832
                prepareSQLAndAttributeListForInser(sqlb, attrs);
833

    
834
                sqlForAppend = sqlb.toString();
835
                attrsForAppendMode = attrs;
836
        }
837

    
838
}