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 / jdbc / JDBCStoreProviderWriter.java @ 40559
History | View | Annotate | Download (22.3 KB)
1 | 40559 | jjdelcerro | /**
|
---|---|---|---|
2 | * gvSIG. Desktop Geographic Information System.
|
||
3 | *
|
||
4 | * Copyright (C) 2007-2013 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 | 40435 | jjdelcerro | /* gvSIG. Geographic Information System of the Valencian Government
|
25 | *
|
||
26 | * Copyright (C) 2007-2008 Infrastructures and Transports Department
|
||
27 | * of the Valencian Government (CIT)
|
||
28 | *
|
||
29 | * This program is free software; you can redistribute it and/or
|
||
30 | * modify it under the terms of the GNU General Public License
|
||
31 | * as published by the Free Software Foundation; either version 2
|
||
32 | * of the License, or (at your option) any later version.
|
||
33 | *
|
||
34 | * This program is distributed in the hope that it will be useful,
|
||
35 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
36 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
37 | * GNU General Public License for more details.
|
||
38 | *
|
||
39 | * You should have received a copy of the GNU General Public License
|
||
40 | * along with this program; if not, write to the Free Software
|
||
41 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||
42 | * MA 02110-1301, USA.
|
||
43 | *
|
||
44 | */
|
||
45 | |||
46 | /*
|
||
47 | * AUTHORS (In addition to CIT):
|
||
48 | * 2009 IVER T.I {{Task}}
|
||
49 | */
|
||
50 | |||
51 | /**
|
||
52 | *
|
||
53 | */
|
||
54 | package org.gvsig.fmap.dal.store.jdbc; |
||
55 | |||
56 | import java.sql.Connection; |
||
57 | import java.sql.PreparedStatement; |
||
58 | import java.sql.SQLException; |
||
59 | import java.sql.Statement; |
||
60 | import java.util.ArrayList; |
||
61 | import java.util.Arrays; |
||
62 | import java.util.Iterator; |
||
63 | import java.util.List; |
||
64 | |||
65 | import org.gvsig.fmap.dal.exception.DataException; |
||
66 | import org.gvsig.fmap.dal.exception.InitializeException; |
||
67 | import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor; |
||
68 | import org.gvsig.fmap.dal.feature.FeatureRules; |
||
69 | import org.gvsig.fmap.dal.feature.FeatureType; |
||
70 | import org.gvsig.fmap.dal.feature.exception.PerformEditingException; |
||
71 | import org.gvsig.fmap.dal.feature.spi.FeatureProvider; |
||
72 | import org.gvsig.fmap.dal.feature.spi.FeatureReferenceProviderServices; |
||
73 | import org.gvsig.fmap.dal.spi.DataStoreProviderServices; |
||
74 | import org.gvsig.fmap.dal.store.db.FeatureTypeHelper; |
||
75 | import org.gvsig.fmap.dal.store.jdbc.exception.JDBCExecutePreparedSQLException; |
||
76 | import org.gvsig.fmap.dal.store.jdbc.exception.JDBCExecuteSQLException; |
||
77 | import org.gvsig.fmap.dal.store.jdbc.exception.JDBCPreparingSQLException; |
||
78 | import org.gvsig.fmap.dal.store.jdbc.exception.JDBCSQLException; |
||
79 | import org.gvsig.fmap.dal.store.jdbc.exception.JDBCUpdateWithoutChangesException; |
||
80 | import org.gvsig.tools.dynobject.DynObject; |
||
81 | import org.slf4j.Logger; |
||
82 | import org.slf4j.LoggerFactory; |
||
83 | |||
84 | /**
|
||
85 | * @author jmvivo
|
||
86 | *
|
||
87 | */
|
||
88 | public class JDBCStoreProviderWriter extends JDBCStoreProvider { |
||
89 | |||
90 | final static private Logger logger = LoggerFactory |
||
91 | .getLogger(JDBCStoreProviderWriter.class); |
||
92 | |||
93 | |||
94 | protected String appendModeSql; |
||
95 | protected List<FeatureAttributeDescriptor> appendModeAttributes; |
||
96 | |||
97 | |||
98 | public JDBCStoreProviderWriter(JDBCStoreParameters params,
|
||
99 | DataStoreProviderServices storeServices) |
||
100 | throws InitializeException {
|
||
101 | super(params, storeServices);
|
||
102 | } |
||
103 | |||
104 | protected JDBCStoreProviderWriter(JDBCStoreParameters params,
|
||
105 | DataStoreProviderServices storeServices, DynObject metadata) |
||
106 | throws InitializeException {
|
||
107 | super(params, storeServices, metadata);
|
||
108 | } |
||
109 | |||
110 | |||
111 | |||
112 | protected void addToListFeatureValues(FeatureProvider featureProvider, |
||
113 | FeatureAttributeDescriptor attrOfList, |
||
114 | FeatureAttributeDescriptor attr, List<Object> values) throws DataException { |
||
115 | if (attr == null) { |
||
116 | if (attrOfList.isPrimaryKey()) {
|
||
117 | throw new RuntimeException("pk attribute '" |
||
118 | + attrOfList.getName() + "' not found in feature");
|
||
119 | } |
||
120 | values.add(helper |
||
121 | .dalValueToJDBC(attr, attrOfList.getDefaultValue())); |
||
122 | } else {
|
||
123 | values.add(helper.dalValueToJDBC(attr, featureProvider.get(attr |
||
124 | .getIndex()))); |
||
125 | } |
||
126 | |||
127 | } |
||
128 | |||
129 | protected void addToListFeatureValues(FeatureProvider featureProvider, |
||
130 | List<FeatureAttributeDescriptor> attributes, List<Object> values) throws DataException { |
||
131 | FeatureAttributeDescriptor attr, attrOfList; |
||
132 | FeatureType fType = featureProvider.getType(); |
||
133 | for (int i = 0; i < attributes.size(); i++) { |
||
134 | attrOfList = (FeatureAttributeDescriptor) attributes.get(i); |
||
135 | attr = fType.getAttributeDescriptor(attrOfList.getName()); |
||
136 | addToListFeatureValues(featureProvider, attrOfList, attr, values); |
||
137 | } |
||
138 | } |
||
139 | |||
140 | protected void appendToSQLPreparedPkWhereClause(StringBuilder sql, |
||
141 | List<FeatureAttributeDescriptor> pkAttributes) {
|
||
142 | sql.append(" Where ");
|
||
143 | FeatureAttributeDescriptor attr; |
||
144 | for (int i = 0; i < pkAttributes.size() - 1; i++) { |
||
145 | attr = (FeatureAttributeDescriptor) pkAttributes.get(i); |
||
146 | sql.append(helper.escapeFieldName(attr.getName())); |
||
147 | sql.append(" = ? AND ");
|
||
148 | } |
||
149 | attr = (FeatureAttributeDescriptor) pkAttributes.get(pkAttributes |
||
150 | .size() - 1);
|
||
151 | sql.append(helper.escapeFieldName(attr.getName())); |
||
152 | sql.append(" = ? ");
|
||
153 | } |
||
154 | |||
155 | protected void executeRemovePreparedStatement(Connection conn, String sql, |
||
156 | List<FeatureAttributeDescriptor> attributes, Iterator<FeatureReferenceProviderServices> featureReferences) throws DataException { |
||
157 | PreparedStatement st;
|
||
158 | try {
|
||
159 | st = conn.prepareStatement(sql); |
||
160 | } catch (SQLException e) { |
||
161 | throw new JDBCPreparingSQLException(sql, e); |
||
162 | } |
||
163 | try {
|
||
164 | List<Object> values = new ArrayList<Object>(); |
||
165 | FeatureReferenceProviderServices featureRef; |
||
166 | // FeatureType featureType;
|
||
167 | while (featureReferences.hasNext()) {
|
||
168 | st.clearParameters(); |
||
169 | featureRef = featureReferences.next(); |
||
170 | values.clear(); |
||
171 | // featureType = this.getFeatureStore()
|
||
172 | // .getFeatureType(featureRef.getFeatureTypeId());
|
||
173 | |||
174 | Iterator<FeatureAttributeDescriptor> iter = attributes.iterator();
|
||
175 | FeatureAttributeDescriptor attr; |
||
176 | while (iter.hasNext()) {
|
||
177 | attr = iter.next(); |
||
178 | values.add( helper.dalValueToJDBC(attr, featureRef |
||
179 | .getKeyValue(attr.getName()))); |
||
180 | } |
||
181 | |||
182 | for (int i = 0; i < values.size(); i++) { |
||
183 | st.setObject(i + 1, values.get(i));
|
||
184 | } |
||
185 | try {
|
||
186 | int nAffected =st.executeUpdate();
|
||
187 | if (nAffected == 0) { |
||
188 | throw new JDBCUpdateWithoutChangesException(sql, values); |
||
189 | } |
||
190 | if (nAffected > 1){ |
||
191 | logger.warn("Remove statement affectst to {} rows: {}",
|
||
192 | nAffected, sql); |
||
193 | } |
||
194 | |||
195 | } catch (SQLException e) { |
||
196 | throw new JDBCExecutePreparedSQLException(sql, values, e); |
||
197 | } |
||
198 | |||
199 | } |
||
200 | } catch (SQLException e) { |
||
201 | throw new JDBCSQLException(e); |
||
202 | } finally {
|
||
203 | try {st.close();} catch (SQLException e) { }; |
||
204 | } |
||
205 | |||
206 | } |
||
207 | |||
208 | protected void executeUpdatePreparedStatement(Connection conn, String sql, |
||
209 | List<FeatureAttributeDescriptor> attributes, Iterator<FeatureProvider> featureProviders) throws DataException { |
||
210 | PreparedStatement st;
|
||
211 | try {
|
||
212 | st = conn.prepareStatement(sql); |
||
213 | } catch (SQLException e) { |
||
214 | throw new JDBCPreparingSQLException(sql, e); |
||
215 | } |
||
216 | try {
|
||
217 | List<Object> values = new ArrayList<Object>(); |
||
218 | FeatureProvider featureProvider; |
||
219 | while (featureProviders.hasNext()) {
|
||
220 | st.clearParameters(); |
||
221 | featureProvider = (FeatureProvider) featureProviders.next(); |
||
222 | values.clear(); |
||
223 | addToListFeatureValues(featureProvider, attributes, values); |
||
224 | for (int i = 0; i < values.size(); i++) { |
||
225 | st.setObject(i + 1, values.get(i));
|
||
226 | } |
||
227 | try {
|
||
228 | if (st.executeUpdate() == 0) { |
||
229 | throw new JDBCUpdateWithoutChangesException(sql, values); |
||
230 | } |
||
231 | } catch (SQLException e) { |
||
232 | throw new JDBCExecutePreparedSQLException(sql, values, e); |
||
233 | } |
||
234 | |||
235 | } |
||
236 | } catch (SQLException e) { |
||
237 | throw new JDBCSQLException(e); |
||
238 | } finally {
|
||
239 | try {st.close();} catch (SQLException e) { }; |
||
240 | } |
||
241 | |||
242 | } |
||
243 | |||
244 | protected void performDeletes(Connection conn, Iterator<FeatureReferenceProviderServices> deleteds, List<FeatureAttributeDescriptor> pkAttributes) |
||
245 | throws DataException {
|
||
246 | |||
247 | if (pkAttributes.size() < 0) { |
||
248 | throw new RuntimeException("Operation requires missing pk"); |
||
249 | } |
||
250 | |||
251 | // ************ Prepare SQL ****************
|
||
252 | StringBuilder sqlb = new StringBuilder(); |
||
253 | sqlb.append("Delete from ");
|
||
254 | sqlb.append(getJDBCParameters().tableID()); |
||
255 | appendToSQLPreparedPkWhereClause(sqlb, pkAttributes); |
||
256 | String sql = sqlb.toString();
|
||
257 | // ************ Prepare SQL (end) ****************
|
||
258 | |||
259 | executeRemovePreparedStatement(conn, sql, pkAttributes, deleteds); |
||
260 | } |
||
261 | |||
262 | protected String getSqlStatementAddField(FeatureAttributeDescriptor attr, |
||
263 | List<String> additionalStatement) throws DataException { |
||
264 | StringBuilder strb = new StringBuilder(); |
||
265 | strb.append("ADD ");
|
||
266 | strb.append(this.helper.getSqlFieldDescription(attr));
|
||
267 | return strb.toString();
|
||
268 | } |
||
269 | |||
270 | protected String getSqlStatementDropField(FeatureAttributeDescriptor attr,List<String> additionalStatement) { |
||
271 | // DROP [ COLUMN ] column
|
||
272 | return " DROP COLUMN " |
||
273 | + this.helper.escapeFieldName(attr.getName());
|
||
274 | |||
275 | } |
||
276 | |||
277 | public boolean supportsAppendMode() { |
||
278 | return true; |
||
279 | } |
||
280 | |||
281 | public void endAppend() throws DataException { |
||
282 | appendModeSql = null;
|
||
283 | appendModeAttributes = null;
|
||
284 | } |
||
285 | |||
286 | protected List<String> getSqlStatementAlterField( |
||
287 | FeatureAttributeDescriptor attrOrg, |
||
288 | FeatureAttributeDescriptor attrTrg, List<String> additionalStatement) |
||
289 | throws DataException {
|
||
290 | //
|
||
291 | List<String> actions = new ArrayList<String>(); |
||
292 | StringBuilder strb;
|
||
293 | if (attrOrg.getDataType() != attrTrg.getDataType()) {
|
||
294 | // ALTER COLUMN {col} TYPE {type} character varying(35)
|
||
295 | strb = new StringBuilder(); |
||
296 | strb.append("ALTER COLUMN ");
|
||
297 | strb.append(helper.escapeFieldName(attrTrg.getName())); |
||
298 | strb.append(" ");
|
||
299 | strb.append(helper.getSqlColumnTypeDescription(attrTrg)); |
||
300 | |||
301 | actions.add(strb.toString()); |
||
302 | } |
||
303 | |||
304 | if (attrOrg.allowNull() != attrTrg.allowNull()) {
|
||
305 | // ALTER [ COLUMN ] column { SET | DROP } NOT NULL
|
||
306 | |||
307 | strb = new StringBuilder(); |
||
308 | strb.append("ALTER COLUMN ");
|
||
309 | strb.append(helper.escapeFieldName(attrTrg.getName())); |
||
310 | strb.append(' ');
|
||
311 | if (attrTrg.allowNull()) {
|
||
312 | strb.append("SET ");
|
||
313 | } else {
|
||
314 | strb.append("DROP ");
|
||
315 | } |
||
316 | strb.append("NOT NULL");
|
||
317 | actions.add(strb.toString()); |
||
318 | } |
||
319 | |||
320 | if (attrOrg.getDefaultValue() != attrTrg.getDefaultValue()) {
|
||
321 | if (attrTrg.getDefaultValue() == null) { |
||
322 | // ALTER [ COLUMN ] column DROP DEFAULT
|
||
323 | |||
324 | strb = new StringBuilder(); |
||
325 | strb.append("ALTER COLUMN ");
|
||
326 | strb.append(helper.escapeFieldName(attrTrg.getName())); |
||
327 | strb.append(" DROP DEFAULT");
|
||
328 | actions.add(strb.toString()); |
||
329 | } else if (!attrTrg.getDefaultValue().equals( |
||
330 | attrOrg.getDefaultValue())) { |
||
331 | // ALTER [ COLUMN ] column DROP DEFAULT
|
||
332 | |||
333 | strb = new StringBuilder(); |
||
334 | strb.append("ALTER COLUMN ");
|
||
335 | strb.append(helper.escapeFieldName(attrTrg.getName())); |
||
336 | strb.append(" SET DEFAULT");
|
||
337 | strb.append(helper.dalValueToJDBC(attrTrg, attrTrg |
||
338 | .getDefaultValue())); |
||
339 | actions.add(strb.toString()); |
||
340 | } |
||
341 | } |
||
342 | |||
343 | return actions;
|
||
344 | } |
||
345 | |||
346 | protected void performUpdateTable(Connection conn, FeatureType original, |
||
347 | FeatureType target) throws DataException {
|
||
348 | |||
349 | /*
|
||
350 | *
|
||
351 | * ALTER TABLE [ ONLY ] name [ * ] action [, ... ]
|
||
352 | */
|
||
353 | |||
354 | List<String> toDrop = new ArrayList<String>(); |
||
355 | List<String> toAdd = new ArrayList<String>(); |
||
356 | List<String> toAlter = new ArrayList<String>(); |
||
357 | |||
358 | List<String> additionalStatement = new ArrayList<String>(); |
||
359 | |||
360 | FeatureAttributeDescriptor attrOrg; |
||
361 | FeatureAttributeDescriptor attrTrg; |
||
362 | Iterator<FeatureAttributeDescriptor> attrs = FeatureTypeHelper.iterator(original);
|
||
363 | while (attrs.hasNext()) {
|
||
364 | attrOrg = (FeatureAttributeDescriptor) attrs.next(); |
||
365 | attrTrg = target.getAttributeDescriptor(attrOrg.getName()); |
||
366 | if (attrTrg == null) { |
||
367 | toDrop.add(getSqlStatementDropField(attrOrg, |
||
368 | additionalStatement)); |
||
369 | } else {
|
||
370 | toAlter.addAll(getSqlStatementAlterField(attrOrg, attrTrg,additionalStatement)); |
||
371 | } |
||
372 | |||
373 | } |
||
374 | attrs = FeatureTypeHelper.iterator(target); |
||
375 | while (attrs.hasNext()) {
|
||
376 | attrTrg = (FeatureAttributeDescriptor) attrs.next(); |
||
377 | if (original.getAttributeDescriptor(attrTrg.getName()) == null) { |
||
378 | toAdd.add(getSqlStatementAddField(attrTrg, |
||
379 | additionalStatement)); |
||
380 | } |
||
381 | } |
||
382 | |||
383 | StringBuilder sqlb = new StringBuilder(); |
||
384 | |||
385 | sqlb.append("ALTER TABLE ");
|
||
386 | sqlb.append(getJDBCParameters().tableID()); |
||
387 | sqlb.append(' ');
|
||
388 | |||
389 | List<String> actions = new ArrayList<String>(); |
||
390 | actions.addAll(toDrop); |
||
391 | actions.addAll(toAlter); |
||
392 | actions.addAll(toAdd); |
||
393 | |||
394 | Iterator<String> it = actions.iterator(); |
||
395 | while (it.hasNext()) {
|
||
396 | if (it.next() == null) { |
||
397 | it.remove(); |
||
398 | } |
||
399 | } |
||
400 | |||
401 | it = additionalStatement.iterator(); |
||
402 | while (it.hasNext()) {
|
||
403 | if (it.next() == null) { |
||
404 | it.remove(); |
||
405 | } |
||
406 | } |
||
407 | |||
408 | if (actions.size() < 1) { |
||
409 | return;
|
||
410 | } |
||
411 | |||
412 | helper.stringJoin(actions, ", ", sqlb);
|
||
413 | |||
414 | String sql = sqlb.toString();
|
||
415 | |||
416 | Statement st = null; |
||
417 | |||
418 | try {
|
||
419 | st = conn.createStatement(); |
||
420 | } catch (SQLException e1) { |
||
421 | throw new JDBCSQLException(e1); |
||
422 | } |
||
423 | try {
|
||
424 | st.execute(sql); |
||
425 | Iterator<String> iter = additionalStatement.iterator(); |
||
426 | while (iter.hasNext()) {
|
||
427 | sql = (String) iter.next();
|
||
428 | st.execute(sql); |
||
429 | } |
||
430 | } catch (SQLException e1) { |
||
431 | throw new JDBCExecuteSQLException(sql, e1); |
||
432 | } finally {
|
||
433 | try {
|
||
434 | st.close(); |
||
435 | } catch (Exception e) { |
||
436 | logger.error("Exception closing statement", e);
|
||
437 | } |
||
438 | ; |
||
439 | } |
||
440 | |||
441 | } |
||
442 | |||
443 | |||
444 | private void perfomInsert(Connection conn, PreparedStatement insertSt, |
||
445 | String sql, FeatureProvider feature, List<FeatureAttributeDescriptor> attributes) |
||
446 | throws DataException {
|
||
447 | |||
448 | try {
|
||
449 | insertSt.clearParameters(); |
||
450 | List<Object> values = new ArrayList<Object>(); |
||
451 | addToListFeatureValues(feature, attributes, values); |
||
452 | // FeatureAttributeDescriptor attr;
|
||
453 | int j = 1; |
||
454 | for (int i = 0; i < values.size(); i++) { |
||
455 | insertSt.setObject(j, values.get(i)); |
||
456 | j++; |
||
457 | } |
||
458 | if (logger.isDebugEnabled()) {
|
||
459 | logger.debug("Executing insert. sql={} value={}", new Object[] { |
||
460 | sql, values }); |
||
461 | } |
||
462 | try {
|
||
463 | insertSt.execute(); |
||
464 | } catch (SQLException e) { |
||
465 | throw new JDBCExecutePreparedSQLException(sql, values, e); |
||
466 | } |
||
467 | |||
468 | } catch (SQLException e1) { |
||
469 | throw new JDBCSQLException(e1); |
||
470 | } |
||
471 | } |
||
472 | |||
473 | public void append(final FeatureProvider featureProvider) throws DataException { |
||
474 | TransactionalAction action = new TransactionalAction() {
|
||
475 | public Object action(Connection conn) throws DataException { |
||
476 | |||
477 | PreparedStatement st;
|
||
478 | try {
|
||
479 | st = conn.prepareStatement(appendModeSql); |
||
480 | } catch (SQLException e) { |
||
481 | throw new JDBCPreparingSQLException(appendModeSql, e); |
||
482 | } |
||
483 | try {
|
||
484 | perfomInsert(conn, st, appendModeSql, featureProvider, |
||
485 | appendModeAttributes); |
||
486 | } finally {
|
||
487 | try {
|
||
488 | st.close(); |
||
489 | } catch (SQLException e) { |
||
490 | } |
||
491 | ; |
||
492 | } |
||
493 | return null; |
||
494 | } |
||
495 | |||
496 | public boolean continueTransactionAllowed() { |
||
497 | return false; |
||
498 | } |
||
499 | }; |
||
500 | try {
|
||
501 | this.helper.doConnectionAction(action);
|
||
502 | |||
503 | resetCount(); |
||
504 | |||
505 | } catch (Exception e) { |
||
506 | throw new PerformEditingException(this.getProviderName(), e); |
||
507 | } |
||
508 | } |
||
509 | |||
510 | protected void prepareAttributeForUpdate(FeatureAttributeDescriptor attr, |
||
511 | List<String> values) { |
||
512 | values.add(helper.escapeFieldName(attr.getName()) + " = ?");
|
||
513 | } |
||
514 | |||
515 | protected void prepareAttributeForInsert(FeatureAttributeDescriptor attr, |
||
516 | List<String> fields, List<String> values) { |
||
517 | |||
518 | fields.add(helper.escapeFieldName(attr.getName())); |
||
519 | values.add("?");
|
||
520 | |||
521 | } |
||
522 | |||
523 | |||
524 | protected void prepareSQLAndAttributeListForInsert(StringBuilder sqlb, |
||
525 | List<FeatureAttributeDescriptor> attributes) throws DataException { |
||
526 | /*
|
||
527 | * INSERT INTO table [ ( column [, ...] ) ] { DEFAULT VALUES | VALUES (
|
||
528 | * { expression | DEFAULT } [, ...] ) [, ...] | query } [ RETURNING * |
|
||
529 | * output_expression [ AS output_name ] [, ...] ]
|
||
530 | */
|
||
531 | |||
532 | sqlb.append("INSERT INTO ");
|
||
533 | sqlb.append(getJDBCParameters().tableID()); |
||
534 | |||
535 | sqlb.append(" (");
|
||
536 | |||
537 | FeatureType type = this.getFeatureStore().getDefaultFeatureType();
|
||
538 | |||
539 | List<String> fields = new ArrayList<String>(); |
||
540 | List<String> values = new ArrayList<String>(); |
||
541 | |||
542 | Iterator<FeatureAttributeDescriptor> iter = FeatureTypeHelper.iterator(type);
|
||
543 | FeatureAttributeDescriptor attr; |
||
544 | while (iter.hasNext()) {
|
||
545 | attr = iter.next(); |
||
546 | if (attr.isAutomatic() || attr.isReadOnly()) {
|
||
547 | continue;
|
||
548 | } |
||
549 | attributes.add(attr); |
||
550 | prepareAttributeForInsert(attr, fields, values); |
||
551 | |||
552 | } |
||
553 | if (attributes.size() < 1) { |
||
554 | throw new RuntimeException("no fields to set"); |
||
555 | } |
||
556 | |||
557 | helper.stringJoin(fields, ", ", sqlb);
|
||
558 | |||
559 | sqlb.append(") VALUES (");
|
||
560 | helper.stringJoin(values, ", ", sqlb);
|
||
561 | |||
562 | sqlb.append(") ");
|
||
563 | |||
564 | } |
||
565 | |||
566 | |||
567 | protected void performInserts(Connection conn, Iterator<FeatureProvider> inserteds) |
||
568 | throws DataException {
|
||
569 | |||
570 | StringBuilder sqlb = new StringBuilder(); |
||
571 | List<FeatureAttributeDescriptor> attrs = new ArrayList<FeatureAttributeDescriptor>(); |
||
572 | |||
573 | prepareSQLAndAttributeListForInsert(sqlb, attrs); |
||
574 | |||
575 | String sql = sqlb.toString();
|
||
576 | PreparedStatement st;
|
||
577 | try {
|
||
578 | st = conn.prepareStatement(sql); |
||
579 | } catch (SQLException e) { |
||
580 | throw new JDBCPreparingSQLException(sql, e); |
||
581 | } |
||
582 | try {
|
||
583 | while (inserteds.hasNext()) {
|
||
584 | perfomInsert(conn, st, sql, inserteds.next(), |
||
585 | attrs); |
||
586 | } |
||
587 | } finally {
|
||
588 | try {st.close();} catch (SQLException e) {logger.error("Error closing statement", e);}; |
||
589 | } |
||
590 | } |
||
591 | |||
592 | protected void performUpdates(Connection conn, Iterator<FeatureProvider> updateds, |
||
593 | List<FeatureAttributeDescriptor> pkAttributes) throws DataException { |
||
594 | /*
|
||
595 | * UPDATE [ ONLY ] table [ [ AS ] alias ] SET { column = { expression |
|
||
596 | * DEFAULT } | ( column [, ...] ) = ( { expression | DEFAULT } [, ...] )
|
||
597 | * } [, ...] [ FROM fromlist ] [ WHERE condition ] [ RETURNING * |
|
||
598 | * output_expression [ AS output_name ] [, ...] ]
|
||
599 | */
|
||
600 | |||
601 | if (pkAttributes.size() < 0) { |
||
602 | throw new RuntimeException("Operation requires missing pk"); |
||
603 | } |
||
604 | |||
605 | // ************ Prepare SQL ****************
|
||
606 | |||
607 | StringBuilder sqlb = new StringBuilder(); |
||
608 | sqlb.append("UPDATE ");
|
||
609 | sqlb.append(getJDBCParameters().tableID()); |
||
610 | |||
611 | sqlb.append(" SET ");
|
||
612 | |||
613 | List<String> values = new ArrayList<String>(); |
||
614 | |||
615 | FeatureType type = this.getFeatureStore().getDefaultFeatureType();
|
||
616 | |||
617 | Iterator<FeatureAttributeDescriptor> iter = FeatureTypeHelper.iterator(type);
|
||
618 | FeatureAttributeDescriptor attr; |
||
619 | List<FeatureAttributeDescriptor> updateAttrs = new ArrayList<FeatureAttributeDescriptor>(); |
||
620 | while (iter.hasNext()) {
|
||
621 | attr = iter.next(); |
||
622 | if (attr.isPrimaryKey() || attr.isAutomatic() || attr.isReadOnly()) {
|
||
623 | continue;
|
||
624 | } |
||
625 | updateAttrs.add(attr); |
||
626 | prepareAttributeForUpdate(attr, values); |
||
627 | |||
628 | } |
||
629 | if (updateAttrs.size() < 1) { |
||
630 | throw new RuntimeException("no fields to set"); |
||
631 | } |
||
632 | |||
633 | helper.stringJoin(values, ", ", sqlb);
|
||
634 | |||
635 | sqlb.append(' ');
|
||
636 | appendToSQLPreparedPkWhereClause(sqlb, pkAttributes); |
||
637 | |||
638 | String sql = sqlb.toString();
|
||
639 | // ************ Prepare SQL (end) ****************
|
||
640 | |||
641 | updateAttrs.addAll(pkAttributes); |
||
642 | |||
643 | executeUpdatePreparedStatement(conn, sql, updateAttrs, updateds); |
||
644 | } |
||
645 | |||
646 | |||
647 | public void beginAppend() throws DataException { |
||
648 | StringBuilder sqlb = new StringBuilder(); |
||
649 | List<FeatureAttributeDescriptor> attrs = new ArrayList<FeatureAttributeDescriptor>(); |
||
650 | |||
651 | prepareSQLAndAttributeListForInsert(sqlb, attrs); |
||
652 | |||
653 | appendModeSql = sqlb.toString(); |
||
654 | appendModeAttributes = attrs; |
||
655 | } |
||
656 | |||
657 | |||
658 | protected TransactionalAction getPerformChangesAction(
|
||
659 | final Iterator<FeatureReferenceProviderServices> deleteds, |
||
660 | final Iterator<FeatureProvider> inserteds, |
||
661 | final Iterator<FeatureProvider> updateds, |
||
662 | final Iterator<FeatureTypeChanged> featureTypesChanged) { |
||
663 | |||
664 | TransactionalAction action = new TransactionalAction() {
|
||
665 | |||
666 | public Object action(Connection conn) throws DataException { |
||
667 | |||
668 | if (featureTypesChanged.hasNext()) {
|
||
669 | |||
670 | FeatureTypeChanged item = featureTypesChanged.next(); |
||
671 | performUpdateTable(conn, item.getSource(), item.getTarget()); |
||
672 | } |
||
673 | |||
674 | List<FeatureAttributeDescriptor> pkAttributes = null; |
||
675 | if (deleteds.hasNext() || updateds.hasNext()) {
|
||
676 | pkAttributes = Arrays.asList(getFeatureStore()
|
||
677 | .getDefaultFeatureType() |
||
678 | .getPrimaryKey()); |
||
679 | } |
||
680 | |||
681 | if (deleteds.hasNext()) {
|
||
682 | performDeletes(conn, deleteds, pkAttributes); |
||
683 | } |
||
684 | |||
685 | if (updateds.hasNext()) {
|
||
686 | performUpdates(conn, updateds, pkAttributes); |
||
687 | } |
||
688 | |||
689 | if (inserteds.hasNext()) {
|
||
690 | performInserts(conn, inserteds); |
||
691 | } |
||
692 | |||
693 | return null; |
||
694 | } |
||
695 | |||
696 | public boolean continueTransactionAllowed() { |
||
697 | return false; |
||
698 | } |
||
699 | |||
700 | }; |
||
701 | |||
702 | return action;
|
||
703 | |||
704 | } |
||
705 | |||
706 | @SuppressWarnings("unchecked") |
||
707 | public void performChanges(Iterator deleteds, Iterator inserteds, |
||
708 | Iterator updateds, Iterator featureTypesChanged) |
||
709 | throws PerformEditingException {
|
||
710 | |||
711 | boolean countChanged = deleteds.hasNext() || inserteds.hasNext();
|
||
712 | |||
713 | try {
|
||
714 | this.helper.doConnectionAction(getPerformChangesAction(deleteds,
|
||
715 | inserteds, updateds, featureTypesChanged)); |
||
716 | |||
717 | /*
|
||
718 | * Get rules before initializing feature type
|
||
719 | */
|
||
720 | FeatureRules old_rules = getFeatureStore().getDefaultFeatureType().getRules(); |
||
721 | |||
722 | /*
|
||
723 | * This initialization loses the feature type rules
|
||
724 | */
|
||
725 | this.initFeatureType();
|
||
726 | |||
727 | /*
|
||
728 | * Get new feature type, clear rules and add
|
||
729 | * the ones saved previously
|
||
730 | */
|
||
731 | FeatureType ft = getFeatureStore().getDefaultFeatureType(); |
||
732 | FeatureRules new_rules = ft.getRules(); |
||
733 | new_rules.clear(); |
||
734 | for (int i=0; i<old_rules.size(); i++) { |
||
735 | new_rules.add(old_rules.getRule(i)); |
||
736 | } |
||
737 | // ===================================================
|
||
738 | |||
739 | if (countChanged) {
|
||
740 | resetCount(); |
||
741 | } |
||
742 | |||
743 | } catch (Exception e) { |
||
744 | throw new PerformEditingException(this.getProviderName(), e); |
||
745 | } |
||
746 | } |
||
747 | |||
748 | |||
749 | public boolean allowWrite() { |
||
750 | if (directSQLMode) {
|
||
751 | return false; |
||
752 | } |
||
753 | if (getJDBCParameters().getPkFields() == null |
||
754 | || getJDBCParameters().getPkFields().length > 0) {
|
||
755 | FeatureType ft = null;
|
||
756 | try {
|
||
757 | ft = this.getFeatureStore().getDefaultFeatureType();
|
||
758 | } catch (DataException e) {
|
||
759 | logger.error("Excepton get default Feature Type", e);
|
||
760 | } |
||
761 | |||
762 | if (ft == null) { |
||
763 | return false; |
||
764 | } |
||
765 | FeatureAttributeDescriptor attr; |
||
766 | Iterator<FeatureAttributeDescriptor> iter = FeatureTypeHelper.iterator(ft);
|
||
767 | while (iter.hasNext()) {
|
||
768 | attr = (FeatureAttributeDescriptor) iter.next(); |
||
769 | if (attr.isPrimaryKey()) {
|
||
770 | return true; |
||
771 | } |
||
772 | } |
||
773 | return false; |
||
774 | |||
775 | } else {
|
||
776 | return true; |
||
777 | } |
||
778 | } |
||
779 | } |