Statistics
| Revision:

root / branches / v2_0_0_prep / libraries / libFMap_daldb / src / org / gvsig / fmap / dal / store / postgresql / PostgreSQLStoreProviderWriter.java @ 28661

History | View | Annotate | Download (22.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.exception.OpenException;
44
import org.gvsig.fmap.dal.feature.Feature;
45
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
46
import org.gvsig.fmap.dal.feature.FeatureType;
47
import org.gvsig.fmap.dal.feature.exception.PerformEditingException;
48
import org.gvsig.fmap.dal.feature.spi.FeatureData;
49
import org.gvsig.fmap.dal.feature.spi.FeatureReferenceProviderServices;
50
import org.gvsig.fmap.dal.resource.exception.ResourceBeginException;
51
import org.gvsig.fmap.dal.store.jdbc.JDBCExecutePreparedSQLException;
52
import org.gvsig.fmap.dal.store.jdbc.JDBCExecuteSQLException;
53
import org.gvsig.fmap.dal.store.jdbc.JDBCPreparingSQLException;
54
import org.gvsig.fmap.dal.store.jdbc.JDBCSQLException;
55
import org.gvsig.fmap.dal.store.jdbc.JDBCUpdateWithoutChangesException;
56
import org.gvsig.fmap.dal.store.postgresql.PostgreSQLHelper.TransactionalAction;
57
import org.gvsig.fmap.geom.Geometry;
58
import org.slf4j.Logger;
59
import org.slf4j.LoggerFactory;
60

    
61
public class PostgreSQLStoreProviderWriter extends PostgreSQLStoreProvider {
62

    
63
        final static private Logger logger = LoggerFactory
64
                        .getLogger(PostgreSQLStoreProvider.class);
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
                try {
153
                        this.open();
154
                } catch (OpenException e2) {
155
                        throw new PerformEditingException(this.getName(), e2);
156
                }
157
                try {
158
                        this.resourceBegin();
159
                } catch (ResourceBeginException e2) {
160
                        throw new PerformEditingException(this.getName(), e2);
161
                }
162

    
163
                TransactionalAction action = new TransactionalAction() {
164

    
165
                        public Object action(Connection conn) throws DataException {
166

    
167
                                if (originalFeatureTypesUpdated.hasNext()) {
168
                                        FeatureType original = (FeatureType) originalFeatureTypesUpdated
169
                                                        .next();
170
                                        FeatureType target = store.getFeatureType(original.getId());
171
                                        performUpdateTable(conn, original, target);
172
                                }
173

    
174
                                List pkAttributes = null;
175

    
176
                                if (deleteds.hasNext()) {
177
                                        pkAttributes = getPkAttributes();
178
                                        performDeletes(conn, deleteds, pkAttributes);
179
                                }
180

    
181
                                if (updateds.hasNext()) {
182
                                        if (pkAttributes == null) {
183
                                                pkAttributes = getPkAttributes();
184
                                        }
185
                                        performUpdates(conn, updateds, pkAttributes);
186
                                }
187

    
188
                                if (inserteds.hasNext()) {
189
                                        performInserts(conn, inserteds);
190
                                }
191

    
192
                                return null;
193
                        }
194

    
195
                        public boolean continueTransactionAllowed() {
196
                                return false;
197
                        }
198

    
199
                };
200
                try {
201
                        this.helper.doConnectionAction(action);
202

    
203
                        if (countChanged) {
204
                                resetCount();
205
                        }
206

    
207
                } catch (Exception e) {
208
                        throw new PerformEditingException(this.getName(), e);
209
                } finally {
210
                        this.resourceEnd();
211
                }
212
        }
213

    
214
        private List getPkAttributes() throws DataException {
215
                ArrayList list = new ArrayList();
216
                Iterator iter = this.store.getDefaultFeatureType().iterator();
217
                FeatureAttributeDescriptor attr;
218
                while (iter.hasNext()) {
219
                        attr = (FeatureAttributeDescriptor) iter.next();
220
                        if (attr.isPrimaryKey()) {
221
                                list.add(attr);
222
                        }
223
                }
224

    
225
                return Collections.unmodifiableList(list);
226
        }
227

    
228
        private void appendToSQLPreparedPkWhereClause(StringBuilder sql,
229
                        List pkAttributes) {
230
                sql.append(" Where ");
231
                FeatureAttributeDescriptor attr;
232
                for (int i = 0; i < pkAttributes.size() - 1; i++) {
233
                        attr = (FeatureAttributeDescriptor) pkAttributes.get(i);
234
                        sql.append(helper.escapeFieldName(attr.getName()));
235
                        sql.append(" = ? AND ");
236
                }
237
                attr = (FeatureAttributeDescriptor) pkAttributes.get(pkAttributes
238
                                .size() - 1);
239
                sql.append(helper.escapeFieldName(attr.getName()));
240
                sql.append(" = ? ");
241
        }
242

    
243
        private void addToListFeatureValues(Feature feature, List attributes,
244
                        List values) throws DataException {
245
                FeatureAttributeDescriptor attr, attrOfList;
246
                FeatureType fType = feature.getType();
247
                for (int i = 0; i < attributes.size(); i++) {
248
                        attrOfList = (FeatureAttributeDescriptor) attributes.get(i);
249
                        attr = fType.getAttributeDescriptor(attrOfList.getName());
250
                        if (attr == null) {
251
                                if (attrOfList.isPrimaryKey()) {
252
                                        // FIXME excepton
253
                                        throw new RuntimeException("pk attribute '"
254
                                                        + attrOfList.getName() + "' not found in feature");
255
                                }
256
                                values.add(helper.dalValueToJDBC(attr, attrOfList
257
                                                .getDefaultValue()));
258
                        } else {
259
                                values.add(helper.dalValueToJDBC(attr, feature.get(attr
260
                                                .getIndex())));
261
                        }
262
                }
263
        }
264

    
265
        private void addToListFeatureValues(FeatureData featureData,
266
                        List attributes, List values) throws DataException {
267
                FeatureAttributeDescriptor attr, attrOfList;
268
                FeatureType fType = featureData.getType();
269
                for (int i = 0; i < attributes.size(); i++) {
270
                        attrOfList = (FeatureAttributeDescriptor) attributes.get(i);
271
                        attr = fType.getAttributeDescriptor(attrOfList.getName());
272
                        if (attr == null) {
273
                                if (attrOfList.isPrimaryKey()) {
274
                                        // FIXME excepton
275
                                        throw new RuntimeException("pk attribute '"
276
                                                        + attrOfList.getName() + "' not found in feature");
277
                                }
278
                                values.add(helper.dalValueToJDBC(attr, attrOfList
279
                                                .getDefaultValue()));
280
                        } else {
281
                                values.add(helper.dalValueToJDBC(attr, featureData.get(attr
282
                                                .getIndex())));
283
                                if (attr.getDataType() == DataTypes.GEOMETRY) {
284
                                        values.add(helper.getPostgisSRID(attr.getSRS()));
285
                                }
286
                        }
287
                }
288
        }
289

    
290
        private void performDeletes(Connection conn, Iterator deleteds,
291
                        List pkAttributes) throws DataException {
292

    
293
                if (pkAttributes.size() < 0) {
294
                        // FIXME Exception
295
                        throw new RuntimeException("Operation requires missing pk");
296
                }
297

    
298
                // ************ Prepare SQL ****************
299
                StringBuilder sqlb = new StringBuilder();
300
                sqlb.append("Delete from ");
301
                sqlb.append(params.tableID());
302
                appendToSQLPreparedPkWhereClause(sqlb, pkAttributes);
303
                String sql = sqlb.toString();
304
                // ************ Prepare SQL (end) ****************
305

    
306
                executeRemovePreparedStatement(conn, sql, pkAttributes, deleteds);
307
        }
308

    
309
        private void performUpdates(Connection conn, Iterator updateds,
310
                        List pkAttributes) throws DataException {
311
                /*
312
                 * UPDATE [ ONLY ] table [ [ AS ] alias ] SET { column = { expression |
313
                 * DEFAULT } | ( column [, ...] ) = ( { expression | DEFAULT } [, ...] )
314
                 * } [, ...] [ FROM fromlist ] [ WHERE condition ] [ RETURNING * |
315
                 * output_expression [ AS output_name ] [, ...] ]
316
                 */
317

    
318
                if (pkAttributes.size() < 0) {
319
                        // FIXME Exception
320
                        throw new RuntimeException("Operation requires missing pk");
321
                }
322

    
323
                // ************ Prepare SQL ****************
324
                StringBuilder sqlb = new StringBuilder();
325
                sqlb.append("UPDATE ");
326
                sqlb.append(params.tableID());
327

    
328
                sqlb.append(" SET (");
329

    
330
                FeatureType type = this.store.getDefaultFeatureType();
331

    
332
                Iterator iter = type.iterator();
333
                FeatureAttributeDescriptor attr;
334
                List updateAttrs = new ArrayList();
335
                while (iter.hasNext()) {
336
                        attr = (FeatureAttributeDescriptor) iter.next();
337
                        if (attr.isPrimaryKey() || attr.isAutomatic() || attr.isReadOnly()) {
338
                                continue;
339
                        }
340
                        updateAttrs.add(attr);
341

    
342
                }
343
                if (updateAttrs.size() < 1) {
344
                        // FIXME exception
345
                        throw new RuntimeException("no fields to set");
346
                }
347

    
348
                for (int i = 0; i < updateAttrs.size() - 1; i++) {
349
                        attr = (FeatureAttributeDescriptor) updateAttrs.get(i);
350
                        sqlb.append(helper.escapeFieldName(attr.getName()));
351
                        sqlb.append(", ");
352
                }
353
                attr = (FeatureAttributeDescriptor) updateAttrs
354
                                .get(updateAttrs.size() - 1);
355
                sqlb.append(helper.escapeFieldName(attr.getName()));
356

    
357
                sqlb.append(") = (");
358
                for (int i = 0; i < updateAttrs.size() - 1; i++) {
359
                        attr = (FeatureAttributeDescriptor) updateAttrs.get(i);
360
                        if (attr.getDataType() == DataTypes.GEOMETRY) {
361
                                sqlb.append("GeomFromWKB(?, ?), ");
362
                        } else {
363
                                sqlb.append("?, ");
364
                        }
365
                }
366
                attr = (FeatureAttributeDescriptor) updateAttrs
367
                                .get(updateAttrs.size() - 1);
368
                if (attr.getDataType() == DataTypes.GEOMETRY) {
369
                        sqlb.append("GeomFromWKB(?, ?) ");
370
                } else {
371
                        sqlb.append("? ");
372
                }
373

    
374
                sqlb.append(") ");
375
                appendToSQLPreparedPkWhereClause(sqlb, pkAttributes);
376

    
377
                String sql = sqlb.toString();
378
                // ************ Prepare SQL (end) ****************
379

    
380
                updateAttrs.addAll(pkAttributes);
381

    
382
                try {
383
                        executeUpdatePreparedStatement(conn, sql, updateAttrs, updateds);
384
                } catch (Exception e) {
385
                        // TODO Auto-generated catch block
386
                        e.printStackTrace();
387
                }
388
        }
389

    
390
        private void executeRemovePreparedStatement(Connection conn, String sql,
391
                        List attributes, Iterator featureReferences) throws DataException {
392
                PreparedStatement st;
393
                try {
394
                        st = conn.prepareStatement(sql);
395
                } catch (SQLException e) {
396
                        throw new JDBCPreparingSQLException(sql, e);
397
                }
398
                try {
399
                        List values = new ArrayList();
400
                        FeatureReferenceProviderServices featureRef;
401
                        FeatureType featureType;
402
                        while (featureReferences.hasNext()) {
403
                                st.clearParameters();
404
                                featureRef = (FeatureReferenceProviderServices) featureReferences
405
                                                .next();
406
                                values.clear();
407
                                featureType = this.store.getFeatureType(featureRef
408
                                                .getFeatureTypeId());
409

    
410
                                Iterator iter = attributes.iterator();
411
                                FeatureAttributeDescriptor attr;
412
                                while (iter.hasNext()) {
413
                                        attr = (FeatureAttributeDescriptor) iter.next();
414
                                        values.add(helper.dalValueToJDBC(attr, featureRef
415
                                                        .getKeyValue(attr.getName())));
416
                                }
417

    
418
                                for (int i = 0; i < values.size(); i++) {
419
                                        st.setObject(i + 1, values.get(i));
420
                                }
421
                                try {
422
                                        int nAffected =st.executeUpdate();
423
                                        if (nAffected == 0) {
424
                                                throw new JDBCUpdateWithoutChangesException(sql, values);
425
                                        }
426
                                        if (nAffected > 1){
427
                                                logger.warn("Remove statement affectst to {} rows: {}",
428
                                                                nAffected, sql);
429
                                        }
430

    
431
                                } catch (SQLException e) {
432
                                        throw new JDBCExecutePreparedSQLException(sql, values, e);
433
                                }
434

    
435
                        }
436
                } catch (SQLException e) {
437
                        throw new JDBCSQLException(e);
438
                } finally {
439
                        try {st.close();} catch (SQLException e) {        };
440
                }
441

    
442
        }
443

    
444
        private void executeUpdatePreparedStatement(Connection conn, String sql,
445
                        List attributes, Iterator featureDatas) throws DataException {
446
                PreparedStatement st;
447
                try {
448
                        st = conn.prepareStatement(sql);
449
                } catch (SQLException e) {
450
                        throw new JDBCPreparingSQLException(sql, e);
451
                }
452
                try {
453
                        List values = new ArrayList();
454
                        FeatureData featureData;
455
                        while (featureDatas.hasNext()) {
456
                                st.clearParameters();
457
                                featureData = (FeatureData) featureDatas.next();
458
                                values.clear();
459
                                addToListFeatureValues(featureData, attributes, values);
460
                                for (int i = 0; i < values.size(); i++) {
461
                                        st.setObject(i + 1, values.get(i));
462
                                }
463
                                try {
464
                                        if (st.executeUpdate() == 0) {
465
                                                throw new JDBCUpdateWithoutChangesException(sql, values);
466
                                        }
467
                                } catch (SQLException e) {
468
                                        throw new JDBCExecutePreparedSQLException(sql, values, e);
469
                                }
470

    
471
                        }
472
                } catch (SQLException e) {
473
                        throw new JDBCSQLException(e);
474
                } finally {
475
                        try {st.close();} catch (SQLException e) {        };
476
                }
477

    
478
        }
479

    
480
        private void performInserts(Connection conn, Iterator inserteds)
481
                        throws DataException {
482

    
483
                StringBuilder sqlb = new StringBuilder();
484
                List attrs = new ArrayList();
485

    
486
                prepareSQLAndAttributeListForInser(sqlb, attrs);
487

    
488
                String sql = sqlb.toString();
489
                PreparedStatement st;
490
                try {
491
                        st = conn.prepareStatement(sql);
492
                } catch (SQLException e) {
493
                        throw new JDBCPreparingSQLException(sql, e);
494
                }
495
                try {
496
                        while (inserteds.hasNext()) {
497
                                perfomInsert(conn, st, sql, (FeatureData) inserteds.next(),
498
                                                attrs);
499
                        }
500
                } finally {
501
                        try {
502
                                st.close();
503
                        } catch (SQLException e) {
504
                        }
505
                        ;
506
                }
507
        }
508

    
509
        private void prepareSQLAndAttributeListForInser(StringBuilder sqlb,
510
                        List attributes) throws DataException {
511
                /*
512
                 * INSERT INTO table [ ( column [, ...] ) ] { DEFAULT VALUES | VALUES (
513
                 * { expression | DEFAULT } [, ...] ) [, ...] | query } [ RETURNING * |
514
                 * output_expression [ AS output_name ] [, ...] ]
515
                 */
516

    
517
                sqlb.append("INSERT INTO ");
518
                sqlb.append(params.tableID());
519

    
520
                sqlb.append(" (");
521

    
522
                FeatureType type = this.store.getDefaultFeatureType();
523

    
524
                Iterator iter = type.iterator();
525
                FeatureAttributeDescriptor attr;
526
                while (iter.hasNext()) {
527
                        attr = (FeatureAttributeDescriptor) iter.next();
528
                        if (attr.isAutomatic() || attr.isReadOnly()) {
529
                                continue;
530
                        }
531
                        attributes.add(attr);
532

    
533
                }
534
                if (attributes.size() < 1) {
535
                        // FIXME exception
536
                        throw new RuntimeException("no fields to set");
537
                }
538

    
539
                for (int i = 0; i < attributes.size() - 1; i++) {
540
                        attr = (FeatureAttributeDescriptor) attributes.get(i);
541
                        sqlb.append(helper.escapeFieldName(attr.getName()));
542
                        sqlb.append(", ");
543
                }
544
                attr = (FeatureAttributeDescriptor) attributes
545
                                .get(attributes.size() - 1);
546
                sqlb.append(helper.escapeFieldName(attr.getName()));
547

    
548
                sqlb.append(") VALUES (");
549
                for (int i = 0; i < attributes.size() - 1; i++) {
550
                        attr = (FeatureAttributeDescriptor) attributes.get(i);
551
                        if (attr.getDataType() == DataTypes.GEOMETRY) {
552
                                sqlb.append("GeomFromWKB(?,?), ");
553
                        } else {
554
                                sqlb.append("?, ");
555
                        }
556
                }
557
                attr = (FeatureAttributeDescriptor) attributes
558
                                .get(attributes.size() - 1);
559
                if (attr.getDataType() == DataTypes.GEOMETRY) {
560
                        sqlb.append("GeomFromWKB(?,?) ");
561
                } else {
562
                        sqlb.append("? ");
563
                }
564

    
565
                sqlb.append(") ");
566

    
567
        }
568

    
569
        private void perfomInsert(Connection conn, PreparedStatement insertSt,
570
                        String sql, FeatureData feature, List attributes)
571
                        throws DataException {
572

    
573
                try {
574
                        insertSt.clearParameters();
575
                        List values = new ArrayList();
576
                        addToListFeatureValues(feature, attributes, values);
577
                        FeatureAttributeDescriptor attr;
578
                        int j = 1;
579
                        for (int i = 0; i < values.size(); i++) {
580
                                insertSt.setObject(j, values.get(i));
581
                                j++;
582
                        }
583
                        if (logger.isDebugEnabled()) {
584
                                logger.debug("Executing insert. sql={} value={}", new Object[] {
585
                                                sql,
586
                                                values });
587
                        }
588
                        try {
589
                                insertSt.execute();
590
                        } catch (SQLException e) {
591
                                throw new JDBCExecutePreparedSQLException(sql, values, e);
592
                        }
593

    
594
                } catch (SQLException e1) {
595
                        throw new JDBCSQLException(e1);
596
                }
597
        }
598

    
599
        private void performUpdateTable(Connection conn, FeatureType original,
600
                        FeatureType target) throws DataException {
601

    
602
                /*
603
                 *
604
                 * ALTER TABLE [ ONLY ] name [ * ] action [, ... ]
605
                 */
606

    
607

    
608
                List toDrop = new ArrayList();
609
                List toAdd = new ArrayList();
610
                List toAlter = new ArrayList();
611

    
612
                List sqlgeomColumnsChanges = new ArrayList();
613

    
614
                FeatureAttributeDescriptor attrOrg;
615
                FeatureAttributeDescriptor attrTrg;
616
                String actionAlter;
617
                Iterator attrs = original.iterator();
618
                while (attrs.hasNext()) {
619
                        attrOrg = (FeatureAttributeDescriptor) attrs.next();
620
                        attrTrg = target.getAttributeDescriptor(attrOrg.getName());
621
                        if (attrTrg == null) {
622
                                toDrop.add(getSqlActionDropField(attrOrg));
623
                                if (attrOrg.getDataType() == DataTypes.GEOMETRY) {
624
                                        sqlgeomColumnsChanges.add(getSqlGeometyFieldDrop(attrOrg));
625
                                }
626
                        } else {
627
                                actionAlter = getSqlActionAlterField(attrOrg, attrTrg,
628
                                                sqlgeomColumnsChanges);
629
                        }
630

    
631
                }
632
                attrs = target.iterator();
633
                while (attrs.hasNext()) {
634
                        attrTrg = (FeatureAttributeDescriptor) attrs.next();
635
                        if (target.getAttributeDescriptor(attrTrg.getName()) == null) {
636
                                toAdd.add(getSqlActionAddField(attrTrg));
637
                        }
638
                }
639

    
640
                StringBuilder sqlb = new StringBuilder();
641

    
642
                sqlb.append("ALTER TABLE ");
643
                sqlb.append(params.tableID());
644
                sqlb.append(' ');
645

    
646
                List actions = new ArrayList();
647
                actions.addAll(toDrop);
648
                actions.addAll(toAlter);
649
                actions.addAll(toAdd);
650

    
651
                if (actions.size() < 1) {
652
                        return;
653
                }
654

    
655
                for (int i = 0; i < actions.size() - 1; i++) {
656
                        sqlb.append(actions.get(i));
657
                        sqlb.append(", ");
658
                }
659
                sqlb.append(actions.size() - 1);
660

    
661

    
662
                String sql = sqlb.toString();
663

    
664
                Statement st = null;
665

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

    
684
        }
685

    
686
        private Object getSqlGeometyFieldDrop(FeatureAttributeDescriptor attr) {
687
                StringBuilder strb = new StringBuilder();
688

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

    
709

    
710
        private String getSqlActionDropField(FeatureAttributeDescriptor attr) {
711
                // DROP [ COLUMN ] column
712
                return " DROP COLUMN " + this.helper.escapeFieldName(attr.getName());
713
        }
714

    
715
        private String getSqlActionAlterField(FeatureAttributeDescriptor attrOrg,
716
                        FeatureAttributeDescriptor attrTrg, List sqlgeomColumnsChanges)
717
                        throws DataException {
718
                //
719
                List actions = new ArrayList();
720
                StringBuilder strb;
721
                if (attrOrg.getDataType() != attrTrg.getDataType()) {
722
                        // ALTER COLUMN {col} TYPE {type} character varying(35)
723
                        strb = new StringBuilder();
724
                        strb.append("ALTER COLUMN ");
725
                        strb.append(helper.escapeFieldName(attrTrg.getName()));
726
                        strb.append(" ");
727
                        strb.append(helper.getSqlColumnTypeDescription(attrTrg));
728

    
729
                        actions.add(strb.toString());
730
                        if (attrOrg.getDataType() == DataTypes.GEOMETRY) {
731
                                sqlgeomColumnsChanges.add(getSqlGeometyFieldDrop(attrOrg));
732
                        }
733
                        if (attrTrg.getDataType() == DataTypes.GEOMETRY) {
734
                                sqlgeomColumnsChanges.addAll(Arrays.asList(helper
735
                                                .getSqlGeometyFieldAdd(attrTrg, params.getTable(),
736
                                                                params.getSchema())));
737
                        }
738
                }
739
                if (attrOrg.getDataType() == attrTrg.getDataType()
740
                                && attrTrg.getDataType() == DataTypes.GEOMETRY) {
741
                        // TODO Checks SRS and GeomType/Subtype
742
                }
743

    
744
                if (attrOrg.allowNull() != attrTrg.allowNull()) {
745
                        // ALTER [ COLUMN ] column { SET | DROP } NOT NULL
746

    
747
                        strb = new StringBuilder();
748
                        strb.append("ALTER COLUMN ");
749
                        strb.append(helper.escapeFieldName(attrTrg.getName()));
750
                        strb.append(' ');
751
                        if (attrTrg.allowNull()) {
752
                                strb.append("SET ");
753
                        } else {
754
                                strb.append("DROP ");
755
                        }
756
                        strb.append("NOT NULL");
757
                        actions.add(strb.toString());
758
                }
759

    
760
                if (attrOrg.getDefaultValue() != attrTrg.getDefaultValue()) {
761
                        if (attrTrg.getDefaultValue() == null) {
762
                                // ALTER [ COLUMN ] column DROP DEFAULT
763

    
764
                                strb = new StringBuilder();
765
                                strb.append("ALTER COLUMN ");
766
                                strb.append(helper.escapeFieldName(attrTrg.getName()));
767
                                strb.append(" DROP DEFAULT");
768
                                actions.add(strb.toString());
769
                        } else if (!attrTrg.getDefaultValue().equals(
770
                                        attrOrg.getDefaultValue())) {
771
                                // ALTER [ COLUMN ] column DROP DEFAULT
772

    
773
                                strb = new StringBuilder();
774
                                strb.append("ALTER COLUMN ");
775
                                strb.append(helper.escapeFieldName(attrTrg.getName()));
776
                                strb.append(" SET DEFAULT");
777
                                strb.append(helper.dalValueToJDBC(attrTrg, attrTrg
778
                                                .getDefaultValue()));
779
                                actions.add(strb.toString());
780
                        }
781
                }
782

    
783
                return "";
784
        }
785

    
786
        private String getSqlActionAddField(FeatureAttributeDescriptor attr) {
787
                StringBuilder strb = new StringBuilder();
788
                strb.append("ADD ");
789
                this.helper.addSqlFiledDescription(attr, strb);
790
                return strb.toString();
791
        }
792

    
793
}