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

History | View | Annotate | Download (12.5 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.store.jdbc2.JDBCHelper;
17
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCExecuteSQLException;
18
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCSQLException;
19
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCUpdateWithoutChangesException;
20
import org.gvsig.fmap.dal.store.jdbc2.spi.JDBCSQLBuilderBase;
21
import org.gvsig.fmap.dal.store.jdbc2.JDBCUtils;
22

    
23
public class PerformChangesOperation extends AbstractConnectionOperation {
24

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
336
}