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 / AppendOperation.java @ 47779

History | View | Annotate | Download (11 KB)

1 45065 jjdelcerro
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2020 gvSIG Association.
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 3
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
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24 43020 jjdelcerro
package org.gvsig.fmap.dal.store.jdbc2.spi.operations;
25
26
import java.sql.PreparedStatement;
27
import java.sql.SQLException;
28 45534 fdiaz
import java.sql.Statement;
29 44678 jjdelcerro
import java.util.Collections;
30
import java.util.List;
31 44644 jjdelcerro
import org.gvsig.expressionevaluator.GeometryExpressionBuilder;
32 43020 jjdelcerro
import org.gvsig.fmap.dal.exception.DataException;
33
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
34 47779 fdiaz
import static org.gvsig.fmap.dal.feature.FeatureStore.SUBMODE_MERGE;
35
import static org.gvsig.fmap.dal.feature.FeatureStore.SUBMODE_NONE;
36 43020 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureType;
37
import org.gvsig.fmap.dal.feature.exception.AlreadyEditingException;
38
import org.gvsig.fmap.dal.feature.spi.FeatureProvider;
39
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCPreparingSQLException;
40 46315 jjdelcerro
import org.gvsig.fmap.dal.store.jdbc2.JDBCConnection;
41 43020 jjdelcerro
import org.gvsig.fmap.dal.store.jdbc2.JDBCHelper;
42
import org.gvsig.fmap.dal.store.jdbc2.JDBCUtils;
43 44058 jjdelcerro
import org.gvsig.fmap.dal.store.jdbc2.OperationsFactory.TableReference;
44 43020 jjdelcerro
import org.gvsig.fmap.dal.store.jdbc2.spi.JDBCSQLBuilderBase;
45 46315 jjdelcerro
import org.gvsig.fmap.geom.DataTypes;
46 43629 jjdelcerro
import org.gvsig.tools.dispose.Disposable;
47
import org.gvsig.tools.dispose.DisposeUtils;
48 45533 jjdelcerro
import org.slf4j.LoggerFactory;
49 43020 jjdelcerro
50
51 47779 fdiaz
@SuppressWarnings("UseSpecificCatch")
52 43020 jjdelcerro
public class AppendOperation {
53 45533 jjdelcerro
    protected static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(AppendOperation.class);
54 45507 jjdelcerro
55 46315 jjdelcerro
    protected JDBCConnection connection = null;
56 43020 jjdelcerro
    protected final JDBCHelper helper;
57 44058 jjdelcerro
    protected final TableReference table;
58 43020 jjdelcerro
    protected final FeatureType type;
59
60
    protected JDBCSQLBuilderBase sqlbuilder = null;
61 44644 jjdelcerro
    protected GeometryExpressionBuilder expbuilder;
62 44198 jjdelcerro
63 43020 jjdelcerro
    protected PreparedStatement preparedStatement;
64 44678 jjdelcerro
    protected String insertSQL;
65 45507 jjdelcerro
    protected int batchCount;
66 45694 fdiaz
    private int batchSize; //No es final para facilitar la depuracion
67 45533 jjdelcerro
    private final Disposable[] disposableParameters;
68 43020 jjdelcerro
69
    public AppendOperation(
70
            JDBCHelper helper,
71 44058 jjdelcerro
            TableReference table,
72 43020 jjdelcerro
            FeatureType type
73
        ) {
74
        this.helper = helper;
75
        this.table = table;
76
        this.type = type;
77 45507 jjdelcerro
        this.batchSize = this.helper.getConnectionParameters().getBatchSize();
78 45533 jjdelcerro
        if( this.batchSize>0 ) {
79
            this.disposableParameters = new Disposable[this.batchSize];
80
        } else {
81
            this.disposableParameters = null;
82
        }
83 43020 jjdelcerro
    }
84 47779 fdiaz
85
    public void begin(int submode) throws DataException {
86 43020 jjdelcerro
        if (this.sqlbuilder != null) {
87
            throw new AlreadyEditingException(this.helper.getSourceId());
88
        }
89
90
        try {
91 43377 jjdelcerro
            this.connection = this.helper.getConnectionWritable();
92 47779 fdiaz
            switch(submode) {
93
                case SUBMODE_MERGE:
94
                    this.insertSQL = this.getMergeSQL();
95
                    break;
96
                case SUBMODE_NONE:
97
                default:
98
                    this.insertSQL = this.getInsertSQL();
99
                    break;
100
            }
101 43020 jjdelcerro
102 47779 fdiaz
            if( this.connection != null ) { // Not in test mode ???
103
              this.preparedStatement = this.connection.prepareStatement(insertSQL);
104
              this.connection.begin();
105
              for (String sql : this.getPreviousSQLs()) {
106
                  this.connection.execute(sql);
107
              }
108
            }
109
110
        } catch (SQLException ex) {
111
            throw new JDBCPreparingSQLException(this.sqlbuilder.toString(),ex);
112
        }
113
114
    }
115
116
    protected String getInsertSQL() {
117 43020 jjdelcerro
            this.sqlbuilder = this.helper.createSQLBuilder();
118 44198 jjdelcerro
            this.expbuilder = this.sqlbuilder.expression();
119 43020 jjdelcerro
120 44058 jjdelcerro
            this.sqlbuilder.insert().table()
121
                    .database(this.table.getDatabase())
122
                    .schema(this.table.getSchema())
123
                    .name(this.table.getTable()
124
            );
125 43020 jjdelcerro
            for (FeatureAttributeDescriptor attr : type) {
126 44324 jjdelcerro
                if( attr.isAutomatic() || attr.isComputed() ) {
127 43020 jjdelcerro
                    continue;
128
                }
129
                if (attr.getType() == DataTypes.GEOMETRY) {
130 45008 omartinez
                        this.sqlbuilder.insert().column().name(attr.getName()).with_value(
131
                            expbuilder.parameter(attr.getName()).as_geometry_variable().srs(
132
                                    expbuilder.parameter().value(attr.getSRS())
133
                            )
134
                        );
135
                    } else {
136
                        this.sqlbuilder.insert().column().name(attr.getName()).with_value(
137 44198 jjdelcerro
                        expbuilder.parameter(attr.getName()).as_variable()
138 43020 jjdelcerro
                    );
139
                }
140
            }
141
142 47779 fdiaz
            return this.sqlbuilder.insert().toString();
143
    }
144
145
    protected String getMergeSQL() {
146
            this.sqlbuilder = this.helper.createSQLBuilder();
147
            this.expbuilder = this.sqlbuilder.expression();
148
149
            this.sqlbuilder.merge().table()
150
                    .database(this.table.getDatabase())
151
                    .schema(this.table.getSchema())
152
                    .name(this.table.getTable()
153
            );
154
            for (FeatureAttributeDescriptor pk : type.getPrimaryKey()) {
155
                this.sqlbuilder.merge().key(pk.getName());
156 44678 jjdelcerro
            }
157 43020 jjdelcerro
158 47779 fdiaz
            for (FeatureAttributeDescriptor attr : type) {
159
                if( attr.isAutomatic() || attr.isComputed() ) {
160
                    continue;
161
                }
162
                if (attr.getType() == DataTypes.GEOMETRY) {
163
                        this.sqlbuilder.merge().column().name(attr.getName()).with_value(
164
                            expbuilder.parameter(attr.getName()).as_geometry_variable().srs(
165
                                    expbuilder.parameter().value(attr.getSRS())
166
                            )
167
                        );
168
                    } else {
169
                        this.sqlbuilder.merge().column().name(attr.getName()).with_value(
170
                        expbuilder.parameter(attr.getName()).as_variable()
171
                    );
172
                }
173
            }
174 43020 jjdelcerro
175 47779 fdiaz
            return this.sqlbuilder.merge().toString();
176 43020 jjdelcerro
    }
177 47779 fdiaz
178 43377 jjdelcerro
    protected void clean() {
179 45533 jjdelcerro
        if( this.batchCount > 0 ) {
180
            this.clearBatch();
181
        }
182 43020 jjdelcerro
        JDBCUtils.closeQuietly(this.preparedStatement);
183 46492 jjdelcerro
        if( this.connection!=null ) {
184
            this.connection.closeQuietly();
185
            this.connection = null;
186
        }
187 43020 jjdelcerro
        this.preparedStatement = null;
188
        this.sqlbuilder = null;
189 44678 jjdelcerro
        this.insertSQL = null;
190 43020 jjdelcerro
    }
191
192 43377 jjdelcerro
    public void end() {
193
        try {
194 44678 jjdelcerro
            if( this.connection == null ) {
195
              return; // In test mode ???
196
            }
197 45507 jjdelcerro
            if( this.batchCount > 0 ) {
198 45533 jjdelcerro
                this.executeBatch();
199 45507 jjdelcerro
            }
200 43377 jjdelcerro
            this.connection.commit();
201 44678 jjdelcerro
            for (String sql : this.getPostSQLs()) {
202 46315 jjdelcerro
              this.connection.execute(sql);
203 44678 jjdelcerro
            }
204 46315 jjdelcerro
        } catch (Exception ex) {
205 43377 jjdelcerro
            try {
206
                this.connection.rollback();
207 46315 jjdelcerro
            } catch (Exception ex1) {
208 43377 jjdelcerro
            }
209
            throw new RuntimeException("Can't commit transaction", ex);
210
        } finally {
211
            clean();
212
        }
213 43020 jjdelcerro
    }
214
215 43377 jjdelcerro
    public void abort() {
216
        try {
217 44678 jjdelcerro
            if( this.connection == null ) {
218
              return; // In test mode ???
219
            }
220 45533 jjdelcerro
            if( this.batchCount > 0 ) {
221
                this.clearBatch();
222
            }
223 43377 jjdelcerro
            this.connection.rollback();
224 44678 jjdelcerro
            for (String sql : this.getPostSQLs()) {
225 46315 jjdelcerro
              this.connection.execute(sql);
226 44678 jjdelcerro
            }
227 46315 jjdelcerro
        } catch (Exception ex) {
228
            LOGGER.debug("",ex);
229 44678 jjdelcerro
        } finally {
230
          clean();
231 43377 jjdelcerro
        }
232
    }
233 44678 jjdelcerro
234
    public String getSQL() { // For test
235
      return this.insertSQL;
236
    }
237 43377 jjdelcerro
238 44678 jjdelcerro
    public List<String> getPreviousSQLs() {
239
      return Collections.EMPTY_LIST;
240
    }
241
242
    public List<String> getPostSQLs() {
243
      return Collections.EMPTY_LIST;
244
    }
245
246
    public List<Object> getSQLParameters(FeatureProvider feature) {
247
      return this.sqlbuilder.getParameters(feature);
248
    }
249
250 45507 jjdelcerro
    @SuppressWarnings("UseSpecificCatch")
251 43020 jjdelcerro
    public void append(FeatureProvider feature) throws DataException {
252
        try {
253 45533 jjdelcerro
            if( this.batchSize>0 ) {
254
                this.addBatch(feature);
255
                if( this.batchCount >= this.batchSize ) {
256
                    this.executeBatch();
257
                }
258
            } else {
259
                Disposable theParametersDisposable = null;
260
                try {
261
                    theParametersDisposable = this.sqlbuilder.setParameters(this.preparedStatement, feature);
262
                    int n = JDBCUtils.executeUpdate(this.preparedStatement,this.insertSQL);
263
                    if( n<1 ) {
264
                        throw new RuntimeException("Can't insert feature (n="+n+").");
265
                    }
266
                } finally {
267
                    DisposeUtils.disposeQuietly(theParametersDisposable);
268
                }
269 45507 jjdelcerro
            }
270 43377 jjdelcerro
        } catch(Exception ex) {
271
            throw new RuntimeException("Can't insert feature.", ex);
272 43020 jjdelcerro
        }
273 45533 jjdelcerro
    }
274
275
    private void addBatch(FeatureProvider feature) throws SQLException {
276
        Disposable theParametersDisposable = this.sqlbuilder.setParameters(this.preparedStatement, feature);
277
        JDBCUtils.addBatch(this.preparedStatement,this.insertSQL);
278
        this.disposableParameters[this.batchCount++] = theParametersDisposable;
279
    }
280
281
    private void executeBatch() throws SQLException {
282
        int[] status = JDBCUtils.executeBatch(this.preparedStatement,this.insertSQL);
283
        this.clearBatch();
284
        for (int n : status) {
285 45534 fdiaz
            if( n<=Statement.EXECUTE_FAILED ) { //-3
286 45533 jjdelcerro
                throw new RuntimeException("Can't insert feature (n="+n+").");
287 45507 jjdelcerro
            }
288 43377 jjdelcerro
        }
289 43020 jjdelcerro
    }
290 45533 jjdelcerro
291
    private void clearBatch() {
292
        try {
293
            this.preparedStatement.clearParameters();
294
            this.preparedStatement.clearBatch();
295
            for (int i = 0; i < this.batchCount && i < this.disposableParameters.length; i++) {
296
                DisposeUtils.dispose(this.disposableParameters[i]);
297
                this.disposableParameters[i] = null;
298
            }
299
            this.batchCount = 0;
300
        } catch (SQLException ex) {
301
            LOGGER.warn("Can't clear batch statement", ex);
302
        }
303
    }
304 43020 jjdelcerro
}