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 @ 43629

History | View | Annotate | Download (13.1 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.FeatureReference;
12
import org.gvsig.fmap.dal.feature.FeatureType;
13
import org.gvsig.fmap.dal.feature.spi.FeatureProvider;
14
import org.gvsig.fmap.dal.feature.spi.FeatureReferenceProviderServices;
15
import org.gvsig.fmap.dal.feature.spi.FeatureStoreProvider;
16
import org.gvsig.fmap.dal.feature.spi.SQLBuilderBase;
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
import org.gvsig.tools.dispose.Disposable;
24
import org.gvsig.tools.dispose.DisposeUtils;
25

    
26
public class PerformChangesOperation extends AbstractConnectionWritableOperation {
27

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

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

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

    
63
    public boolean isTypeChanged() {
64
        return typeChanged;
65
    }
66

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

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

    
119
        JDBCSQLBuilderBase sqlbuilder = buildDeleteSQL(database, schema, table, type);
120

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

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

    
178
    public void performInserts(Connection conn,
179
            String database,
180
            String schema,
181
            String table,
182
            FeatureType type,
183
            Iterator<FeatureProvider> inserteds) throws DataException {
184
        JDBCSQLBuilderBase sqlbuilder = buildInsertSQL(database, schema, table, type);
185

    
186
        PreparedStatement st;
187
        Disposable paramsDisposer = null;
188
        String sql = sqlbuilder.insert().toString();
189
        try {
190
            st = conn.prepareStatement(sql);
191
            while (inserteds.hasNext()) {
192
                FeatureProvider feature = inserteds.next();
193
                paramsDisposer = sqlbuilder.setParameters(st, feature);
194
                try {
195
                    if (JDBCUtils.executeUpdate(st,sql) == 0) {
196
                        throw new JDBCExecuteSQLException(
197
                                sqlbuilder.insert().toString(),
198
                                null
199
                        );
200
                    }
201
                } finally {
202
                    DisposeUtils.disposeQuietly(paramsDisposer);
203
                }
204
            }
205
        } catch (JDBCExecuteSQLException ex) {
206
            throw ex;
207
        } catch (Exception ex) {
208
            throw new JDBCExecuteSQLException(sql,ex);
209
        }
210
    }
211

    
212
    protected JDBCSQLBuilderBase buildUpdateSQL(
213
            String database,
214
            String schema,
215
            String table,
216
            FeatureType type
217
        ) {
218
        JDBCSQLBuilderBase sqlbuilder = createSQLBuilder();
219

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

    
256
        JDBCSQLBuilderBase sqlbuilder = buildUpdateSQL(database, schema, table, type);
257
        
258
        PreparedStatement st = null;
259
        Disposable paramsDisposer = null;
260
        String sql = sqlbuilder.update().toString();
261
        try {
262
            st = conn.prepareStatement(sql);
263
            while (updateds.hasNext()) {
264
                FeatureProvider featureProvider = (FeatureProvider) updateds.next();
265
                paramsDisposer = sqlbuilder.setParameters(st, featureProvider);
266
                if (JDBCUtils.executeUpdate(st,sql) == 0) {
267
                    throw new JDBCUpdateWithoutChangesException(sql,null);
268
                }
269
            }
270
        } catch (SQLException e) {
271
            throw new JDBCSQLException(e);
272
        } finally {
273
            JDBCUtils.closeQuietly(st);
274
            DisposeUtils.disposeQuietly(paramsDisposer);
275
        }
276
    }
277

    
278
    protected JDBCSQLBuilderBase buildUpdateTableSQL(
279
            String database,
280
            String schema,
281
            String table,
282
            FeatureType original,
283
            FeatureType target
284
        ) {
285
        JDBCSQLBuilderBase sqlbuilder = createSQLBuilder();
286
        sqlbuilder.update().table().database(database).schema(schema).name(table);
287

    
288
        for (FeatureAttributeDescriptor attrOrgiginal : original) {
289
            FeatureAttributeDescriptor attrTarget = target.getAttributeDescriptor(
290
                    attrOrgiginal.getName()
291
            );
292
            if (attrTarget == null) {
293
                sqlbuilder.alter_table().drop_column(attrOrgiginal.getName());
294
            } else {
295
                sqlbuilder.alter_table().alter_column(
296
                        attrTarget.getName(),
297
                        attrTarget.getType(),
298
                        attrTarget.getPrecision(),
299
                        attrTarget.getSize(),
300
                        attrTarget.isPrimaryKey(),
301
                        attrTarget.isIndexed(),
302
                        attrTarget.allowNull(),
303
                        attrTarget.isAutomatic(),
304
                        attrTarget.getDefaultValue()
305
                );
306
            }
307
        }
308
        for (FeatureAttributeDescriptor attrTarget : target) {
309
            if (original.getAttributeDescriptor(attrTarget.getName()) == null) {
310
                sqlbuilder.alter_table().add_column(
311
                        attrTarget.getName(),
312
                        attrTarget.getType(),
313
                        attrTarget.getPrecision(),
314
                        attrTarget.getSize(),
315
                        attrTarget.isPrimaryKey(),
316
                        attrTarget.isIndexed(),
317
                        attrTarget.allowNull(),
318
                        attrTarget.isAutomatic(),
319
                        attrTarget.getDefaultValue()
320
                );
321
            }
322
        }
323
        return sqlbuilder;
324
    }
325

    
326
    public void performUpdateTable(Connection conn,
327
            String database,
328
            String schema,
329
            String table,
330
            FeatureType original,
331
            FeatureType target) throws DataException {
332

    
333
        SQLBuilderBase sqlbuilder = buildUpdateTableSQL(null, null, table, original, target);
334
        Statement st = null;
335
        try {
336
            st = conn.createStatement();
337
            for (String sql : sqlbuilder.alter_table().toStrings()) {
338
                JDBCUtils.execute(st, sql);
339
            }
340
        } catch (SQLException e) {
341
            throw new JDBCSQLException(e);
342
        } finally {
343
            JDBCUtils.closeQuietly(st);
344
        }
345
    }
346

    
347
}