Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.dal / org.gvsig.fmap.dal.db / org.gvsig.fmap.dal.db.jdbc / src / main / java / org / gvsig / fmap / dal / store / jdbc2 / spi / operations / PerformChangesOperation.java @ 43377

History | View | Annotate | Download (12.6 KB)

1
package org.gvsig.fmap.dal.store.jdbc2.spi.operations;
2

    
3
import java.sql.Connection;
4
import java.sql.PreparedStatement;
5
import java.sql.SQLException;
6
import java.sql.Statement;
7
import java.util.Iterator;
8
import org.gvsig.fmap.dal.DataTypes;
9
import org.gvsig.fmap.dal.exception.DataException;
10
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
11
import org.gvsig.fmap.dal.feature.FeatureType;
12
import org.gvsig.fmap.dal.feature.spi.FeatureProvider;
13
import org.gvsig.fmap.dal.feature.spi.FeatureReferenceProviderServices;
14
import org.gvsig.fmap.dal.feature.spi.FeatureStoreProvider;
15
import org.gvsig.fmap.dal.feature.spi.SQLBuilderBase;
16
import org.gvsig.fmap.dal.resource.exception.AccessResourceException;
17
import org.gvsig.fmap.dal.store.jdbc2.JDBCHelper;
18
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCExecuteSQLException;
19
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCSQLException;
20
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCUpdateWithoutChangesException;
21
import org.gvsig.fmap.dal.store.jdbc2.spi.JDBCSQLBuilderBase;
22
import org.gvsig.fmap.dal.store.jdbc2.JDBCUtils;
23

    
24
public class PerformChangesOperation extends AbstractConnectionWritableOperation {
25

    
26
    protected String dbName;
27
    protected String schemaName;
28
    protected String tableName;
29
    protected FeatureType featureType;
30
    protected Iterator<FeatureReferenceProviderServices> deleteds;
31
    protected Iterator<FeatureStoreProvider.FeatureTypeChanged> featureTypesChanged;
32
    protected Iterator<FeatureProvider> updateds;
33
    protected Iterator<FeatureProvider> inserteds;
34

    
35
    protected boolean typeChanged = false;
36
    
37
    public PerformChangesOperation(JDBCHelper helper) {
38
        this(helper, null, null, null, null, null, null, null, null);
39
    }
40

    
41
    public PerformChangesOperation(JDBCHelper helper,
42
            String dbName,
43
            String schemaName,
44
            String tableName,
45
            FeatureType featureType,
46
            Iterator<FeatureReferenceProviderServices> deleteds,
47
            Iterator<FeatureProvider> inserteds,
48
            Iterator<FeatureProvider> updateds,
49
            Iterator<FeatureStoreProvider.FeatureTypeChanged> featureTypesChanged) {
50
        super(helper);
51
        this.dbName = dbName;
52
        this.deleteds = deleteds;
53
        this.inserteds = inserteds;
54
        this.updateds = updateds;
55
        this.schemaName = schemaName;
56
        this.tableName = tableName;
57
        this.featureType = featureType;
58
        this.featureTypesChanged = featureTypesChanged;
59
    }
60

    
61
    public boolean isTypeChanged() {
62
        return typeChanged;
63
    }
64

    
65
    @Override
66
    public final Object perform(Connection conn) throws DataException {
67
        if (featureTypesChanged.hasNext()) {
68
            FeatureStoreProvider.FeatureTypeChanged item = featureTypesChanged.next();
69
            this.performUpdateTable(conn, dbName, schemaName, tableName, item.getSource(), item.getTarget());
70
            typeChanged = true;
71
        } else {
72
            typeChanged = false;
73
        }
74
        if (deleteds.hasNext()) {
75
            performDeletes(conn, dbName, schemaName, tableName, featureType, deleteds);
76
        }
77
        if (updateds.hasNext()) {
78
            performUpdates(conn, dbName, schemaName, tableName, featureType, updateds);
79
        }
80
        if (inserteds.hasNext()) {
81
            performInserts(conn, dbName, schemaName, tableName, featureType, inserteds);
82
        }
83
        return true;
84
    }
85
    
86
    protected JDBCSQLBuilderBase buildDeleteSQL(
87
            String database,
88
            String schema,
89
            String table,
90
            FeatureType type
91
        ) {
92
        JDBCSQLBuilderBase sqlbuilder = createSQLBuilder();
93
        sqlbuilder.delete().table().database(database).schema(schema).name(table);
94
        for (FeatureAttributeDescriptor attr : type) {
95
            if (attr.isPrimaryKey()) {
96
                sqlbuilder.delete().where().and(
97
                        sqlbuilder.eq(
98
                                sqlbuilder.column(attr.getName()),
99
                                sqlbuilder.parameter(attr.getName()).as_variable()
100
                        )
101
                );
102
            }
103
        }
104
        if (!sqlbuilder.delete().has_where() ) {
105
            throw new RuntimeException("Operation requires missing pk");
106
        }
107
        return sqlbuilder;
108
    }
109

    
110
    public void performDeletes(Connection conn,
111
            String database,
112
            String schema,
113
            String table,
114
            FeatureType type,
115
            Iterator<FeatureReferenceProviderServices> deleteds) throws DataException {
116

    
117
        JDBCSQLBuilderBase sqlbuilder = buildDeleteSQL(database, schema, table, type);
118

    
119
        PreparedStatement st = null;
120
        String sql = sqlbuilder.delete().toString();
121
        try {
122
            st = conn.prepareStatement(sql);
123
            while (deleteds.hasNext()) {
124
                FeatureProvider featureProvider = (FeatureProvider) deleteds.next();
125
                sqlbuilder.setParameters(st, featureProvider);
126
                int nAffected = JDBCUtils.executeUpdate(st,sql);
127
                if (nAffected == 0) {
128
                    throw new JDBCUpdateWithoutChangesException(
129
                            sqlbuilder.delete().toString(),
130
                            null
131
                    );
132
                }
133
                if (nAffected > 1) {
134
                    logger.warn("Remove statement affectst to {} rows ( {} )",
135
                            nAffected, sql
136
                    );
137
                }
138
            }
139
        } catch (SQLException e) {
140
            throw new JDBCSQLException(e);
141
        } finally {
142
            JDBCUtils.closeQuietly(st);
143
        }
144
    }
145
    
146
    protected JDBCSQLBuilderBase buildInsertSQL(
147
            String database,
148
            String schema,
149
            String table,
150
            FeatureType type
151
        ) {
152
        JDBCSQLBuilderBase sqlbuilder = createSQLBuilder();
153

    
154
        sqlbuilder.insert().table().database(database).schema(schema).name(table);
155
        for (FeatureAttributeDescriptor attr : type) {
156
            if( attr.isAutomatic() ) {
157
                continue;
158
            }
159
            if (attr.getType() == DataTypes.GEOMETRY) {
160
                sqlbuilder.insert().column().name(attr.getName()).with_value(
161
                    sqlbuilder.parameter(attr.getName()).as_geometry_variable().srs(
162
                        sqlbuilder.parameter().value(attr.getSRS()).as_constant()
163
                    )
164
                );
165
            } else {
166
                sqlbuilder.insert().column().name(attr.getName()).with_value(
167
                        sqlbuilder.parameter(attr.getName())
168
                );
169
            }
170
        }
171
        return sqlbuilder;
172
    }
173

    
174
    public void performInserts(Connection conn,
175
            String database,
176
            String schema,
177
            String table,
178
            FeatureType type,
179
            Iterator<FeatureProvider> inserteds) throws DataException {
180
        JDBCSQLBuilderBase sqlbuilder = buildInsertSQL(database, schema, table, type);
181

    
182
        PreparedStatement st;
183
        String sql = sqlbuilder.insert().toString();
184
        try {
185
            st = conn.prepareStatement(sql);
186
            while (inserteds.hasNext()) {
187
                FeatureProvider feature = inserteds.next();
188
                sqlbuilder.setParameters(st, feature);
189
                if (JDBCUtils.executeUpdate(st,sql) == 0) {
190
                    throw new JDBCExecuteSQLException(
191
                            sqlbuilder.insert().toString(),
192
                            null
193
                    );
194
                }
195

    
196
            }
197
        } catch (JDBCExecuteSQLException ex) {
198
            throw ex;
199
        } catch (Exception ex) {
200
            throw new JDBCExecuteSQLException(sql,ex);
201
        }
202
    }
203

    
204
    protected JDBCSQLBuilderBase buildUpdateSQL(
205
            String database,
206
            String schema,
207
            String table,
208
            FeatureType type
209
        ) {
210
        JDBCSQLBuilderBase sqlbuilder = createSQLBuilder();
211

    
212
        sqlbuilder.update().table().database(database).schema(schema).name(table);
213
        for (FeatureAttributeDescriptor attr : type) {
214
            if (attr.isPrimaryKey()) {
215
                sqlbuilder.update().where().and(
216
                        sqlbuilder.eq(
217
                                sqlbuilder.column(attr.getName()),
218
                                sqlbuilder.parameter(attr.getName()).as_variable()
219
                        )
220
                );
221
            } if ( ! attr.isAutomatic() &&  !attr.isReadOnly() ) {
222
                if (attr.getType() == DataTypes.GEOMETRY) {
223
                    sqlbuilder.update().column().name(attr.getName()).with_value(
224
                        sqlbuilder.parameter(attr.getName()).as_geometry_variable().srs(
225
                            sqlbuilder.parameter().value(attr.getSRS()).as_constant()
226
                        )
227
                    );
228
                } else {
229
                    sqlbuilder.update().column().name(attr.getName()).with_value(
230
                        sqlbuilder.parameter(attr.getName()).as_variable()
231
                    );
232
                }
233
            }
234
        }
235
        if (!sqlbuilder.update().has_where() ) {
236
            throw new RuntimeException("Operation requires missing pk");
237
        }
238
        return sqlbuilder;
239
    }
240
    
241
    public void performUpdates(Connection conn,
242
            String database,
243
            String schema,
244
            String table,
245
            FeatureType type,
246
            Iterator<FeatureProvider> updateds) throws DataException {
247

    
248
        JDBCSQLBuilderBase sqlbuilder = buildUpdateSQL(database, schema, table, type);
249
        
250
        PreparedStatement st = null;
251
        String sql = sqlbuilder.update().toString();
252
        try {
253
            st = conn.prepareStatement(sql);
254
            while (updateds.hasNext()) {
255
                FeatureProvider featureProvider = (FeatureProvider) updateds.next();
256
                sqlbuilder.setParameters(st, featureProvider);
257
                if (JDBCUtils.executeUpdate(st,sql) == 0) {
258
                    throw new JDBCUpdateWithoutChangesException(sql,null);
259
                }
260
            }
261
        } catch (SQLException e) {
262
            throw new JDBCSQLException(e);
263
        } finally {
264
            JDBCUtils.closeQuietly(st);
265
        }
266
    }
267

    
268
    protected JDBCSQLBuilderBase buildUpdateTableSQL(
269
            String database,
270
            String schema,
271
            String table,
272
            FeatureType original,
273
            FeatureType target
274
        ) {
275
        JDBCSQLBuilderBase sqlbuilder = createSQLBuilder();
276
        sqlbuilder.update().table().database(database).schema(schema).name(table);
277

    
278
        for (FeatureAttributeDescriptor attrOrgiginal : original) {
279
            FeatureAttributeDescriptor attrTarget = target.getAttributeDescriptor(
280
                    attrOrgiginal.getName()
281
            );
282
            if (attrTarget == null) {
283
                sqlbuilder.alter_table().drop_column(attrOrgiginal.getName());
284
            } else {
285
                sqlbuilder.alter_table().alter_column(
286
                        attrTarget.getName(),
287
                        attrTarget.getType(),
288
                        attrTarget.getPrecision(),
289
                        attrTarget.getSize(),
290
                        attrTarget.isPrimaryKey(),
291
                        attrTarget.isIndexed(),
292
                        attrTarget.allowNull(),
293
                        attrTarget.isAutomatic(),
294
                        attrTarget.getDefaultValue()
295
                );
296
            }
297
        }
298
        for (FeatureAttributeDescriptor attrTarget : target) {
299
            if (original.getAttributeDescriptor(attrTarget.getName()) == null) {
300
                sqlbuilder.alter_table().add_column(
301
                        attrTarget.getName(),
302
                        attrTarget.getType(),
303
                        attrTarget.getPrecision(),
304
                        attrTarget.getSize(),
305
                        attrTarget.isPrimaryKey(),
306
                        attrTarget.isIndexed(),
307
                        attrTarget.allowNull(),
308
                        attrTarget.isAutomatic(),
309
                        attrTarget.getDefaultValue()
310
                );
311
            }
312
        }
313
        return sqlbuilder;
314
    }
315

    
316
    public void performUpdateTable(Connection conn,
317
            String database,
318
            String schema,
319
            String table,
320
            FeatureType original,
321
            FeatureType target) throws DataException {
322

    
323
        SQLBuilderBase sqlbuilder = buildUpdateTableSQL(null, null, table, original, target);
324
        Statement st = null;
325
        try {
326
            st = conn.createStatement();
327
            for (String sql : sqlbuilder.alter_table().toStrings()) {
328
                JDBCUtils.execute(st, sql);
329
            }
330
        } catch (SQLException e) {
331
            throw new JDBCSQLException(e);
332
        } finally {
333
            JDBCUtils.closeQuietly(st);
334
        }
335
    }
336

    
337
}