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 / JDBCStoreProviderBase.java @ 45614

History | View | Annotate | Download (24.7 KB)

1
/**
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
package org.gvsig.fmap.dal.store.jdbc2.spi;
25

    
26
import java.text.MessageFormat;
27
import java.util.Arrays;
28
import java.util.Collections;
29
import java.util.Iterator;
30
import java.util.List;
31
import org.apache.commons.lang3.BooleanUtils;
32
import org.apache.commons.lang3.StringUtils;
33
import org.cresques.cts.IProjection;
34
import org.gvsig.expressionevaluator.Expression;
35
import org.gvsig.fmap.dal.DALLocator;
36
import org.gvsig.fmap.dal.DataManager;
37
import org.gvsig.fmap.dal.DataServerExplorer;
38
import org.gvsig.fmap.dal.DataStore;
39
import org.gvsig.fmap.dal.DataStoreNotification;
40
import org.gvsig.fmap.dal.DataTypes;
41
import org.gvsig.fmap.dal.exception.CloseException;
42
import org.gvsig.fmap.dal.exception.DataException;
43
import org.gvsig.fmap.dal.exception.InitializeException;
44
import org.gvsig.fmap.dal.exception.OpenException;
45
import org.gvsig.fmap.dal.exception.ReadException;
46
import org.gvsig.fmap.dal.feature.EditableFeatureAttributeDescriptor;
47
import org.gvsig.fmap.dal.feature.EditableFeatureType;
48
import org.gvsig.fmap.dal.feature.FeatureQuery;
49
import org.gvsig.fmap.dal.feature.FeatureRule;
50
import org.gvsig.fmap.dal.feature.FeatureRules;
51
import org.gvsig.fmap.dal.feature.FeatureStore;
52
import org.gvsig.fmap.dal.feature.FeatureType;
53
import org.gvsig.fmap.dal.feature.spi.AbstractFeatureStoreProvider;
54
import org.gvsig.fmap.dal.feature.spi.FeatureProvider;
55
import org.gvsig.fmap.dal.feature.spi.FeatureReferenceProviderServices;
56
import org.gvsig.fmap.dal.feature.spi.FeatureSetProvider;
57
import org.gvsig.fmap.dal.resource.ResourceParameters;
58
import org.gvsig.fmap.dal.resource.exception.AccessResourceException;
59
import org.gvsig.fmap.dal.resource.exception.ResourceException;
60
import org.gvsig.fmap.dal.resource.spi.AbstractResource;
61
import org.gvsig.fmap.dal.resource.spi.ResourceConsumer;
62
import org.gvsig.fmap.dal.resource.spi.ResourceProvider;
63
import org.gvsig.fmap.dal.spi.DataStoreProviderServices;
64
import org.gvsig.fmap.dal.store.jdbc.JDBCServerExplorerParameters;
65
import org.gvsig.fmap.dal.store.jdbc.JDBCStoreParameters;
66
import org.gvsig.fmap.dal.store.jdbc2.JDBCHelper;
67
import org.gvsig.fmap.dal.store.jdbc2.JDBCStoreProvider;
68
import org.gvsig.fmap.dal.store.jdbc2.JDBCUtils;
69
import org.gvsig.fmap.dal.store.jdbc2.OperationsFactory;
70
import org.gvsig.fmap.dal.store.jdbc2.ResulSetControler;
71
import org.gvsig.fmap.dal.store.jdbc2.impl.JDBCSetProvider;
72
import org.gvsig.fmap.dal.store.jdbc2.spi.operations.AppendOperation;
73
import org.gvsig.fmap.dal.store.jdbc2.spi.operations.CalculateEnvelopeOfColumnOperation;
74
import org.gvsig.fmap.dal.store.jdbc2.spi.operations.CanModifyTableOperation;
75
import org.gvsig.fmap.dal.store.jdbc2.spi.operations.CountOperation;
76
import org.gvsig.fmap.dal.store.jdbc2.spi.operations.DeletePassThroughOperation;
77
import org.gvsig.fmap.dal.store.jdbc2.spi.operations.FetchFeatureProviderByReferenceOperation;
78
import org.gvsig.fmap.dal.store.jdbc2.spi.operations.FetchFeatureTypeOperation;
79
import org.gvsig.fmap.dal.store.jdbc2.spi.operations.PerformChangesOperation;
80
import org.gvsig.fmap.dal.store.jdbc2.spi.operations.UpdatePassThroughOperation;
81
import org.gvsig.fmap.geom.Geometry;
82
import org.gvsig.fmap.geom.primitive.Envelope;
83
import org.gvsig.tools.dynobject.DynField;
84
import org.gvsig.tools.dynobject.DynObject;
85
import org.gvsig.tools.dynobject.exception.DynFieldNotFoundException;
86
import org.gvsig.tools.exception.BaseException;
87
import org.slf4j.Logger;
88
import org.slf4j.LoggerFactory;
89

    
90
@SuppressWarnings("UseSpecificCatch")
91
public class JDBCStoreProviderBase
92
        extends AbstractFeatureStoreProvider
93
        implements ResourceConsumer, JDBCStoreProvider {
94

    
95
    final static protected Logger LOGGER = LoggerFactory.getLogger(JDBCStoreProviderBase.class);
96

    
97
    public class CountValue implements CalculatedValue<Long> {
98
        
99
        private Long value = null;
100

    
101
        @Override
102
        public void calculate() {
103
            try {
104
                JDBCStoreParameters params = getParameters();
105
                CountOperation count = getOperations().createCount(
106
                        getFeatureStore().getDefaultFeatureType(),
107
                        getOperations().createTableReference(params),
108
                        params.getBaseFilter(),
109
                        null
110
                );            
111
                this.value = (Long) count.perform();
112
            } catch (DataException ex) {
113
                throw new RuntimeException("Can't calculate count",ex);
114
            }
115
        }
116
        
117
        @Override
118
        public void reset() {
119
            this.value = null;
120
        }
121
        
122
        @Override
123
        public Long get() {
124
            if( this.value == null ) {
125
                this.calculate();
126
            }
127
            return this.value;
128
        }
129
    } 
130
    
131
    public class EnvelopeValue implements CalculatedValue<Envelope> {
132
        
133
        private Envelope value = null;
134
        private boolean needCalculate = true;
135

    
136
        @Override
137
        public void calculate() {
138
            FeatureStore featureStore;
139
            FeatureType featureType;
140
            try {
141
                featureStore = getFeatureStore();
142
                if (featureStore == null) {
143
                    return;
144
                }
145
                featureType = featureStore.getDefaultFeatureType();
146
                if (featureType == null) {
147
                    return;
148
                }
149
            } catch (Exception ex) {
150
                throw new RuntimeException("Can't calculate envelope.", ex);
151
            }
152
            try {
153
                value = null;
154
                String columnName = featureType.getDefaultGeometryAttributeName();
155
                if( columnName==null ) {
156
                    return;
157
                }
158
                IProjection crs = getFeatureStore()
159
                        .getDefaultFeatureType()
160
                        .getDefaultSRS();
161
                JDBCStoreParameters params = getParameters();
162
                CalculateEnvelopeOfColumnOperation calculateEnvelopeOfColumn = 
163
                    getOperations().createCalculateEnvelopeOfColumn(
164
                        getFeatureStore().getDefaultFeatureType(),
165
                        getOperations().createTableReference(params),
166
                        columnName, 
167
                        params.getBaseFilter(), 
168
                        params.getWorkingArea(), 
169
                        crs
170
                    );
171
                value = (Envelope) calculateEnvelopeOfColumn.perform();
172
                
173
            } catch(Exception ex) {
174
                throw new RuntimeException("Can't calculate envelope.", ex);
175
            } finally {
176
               needCalculate = false;
177
            }
178
        }
179
        
180
        @Override
181
        public void reset() {
182
            this.value = null;
183
            this.needCalculate = true;
184
        }
185
        
186
        @Override
187
        public synchronized Envelope get() {
188
            if( needCalculate ) {
189
                this.calculate();
190
            }
191
            return this.value;
192
        }
193
    } 
194
        
195
    public class AllowWriteValue implements CalculatedValue<Boolean> {
196
        
197
        private Boolean value = null;
198

    
199
        @Override
200
        public void calculate() {
201
            try {
202
                JDBCStoreParameters params = getParameters();
203
                CanModifyTableOperation canModifyTable = 
204
                    getOperations().createCanModifyTableOperation(
205
                        getOperations().createTableReference(params)
206
                    );
207
                this.value = (boolean) canModifyTable.perform();
208
            } catch(Exception ex) {
209
                throw new RuntimeException("Can't determine if allow write.", ex);
210
            }
211
        }
212
        
213
        @Override
214
        public void reset() {
215
            this.value = null;
216
        }
217
        
218
        @Override
219
        public Boolean get() {
220
            if( this.value == null ) {
221
                this.calculate();
222
            }
223
            return this.value;
224
        }
225
    } 
226
    
227
    protected final JDBCHelper helper;
228

    
229
    protected CalculatedValue<Long> count = null;
230
    
231
    protected CalculatedValue<Envelope> envelope = null;
232

    
233
    protected CalculatedValue<Boolean> allowWrite = null;
234

    
235
    protected AppendOperation appendOperation = null;
236
    
237
    @SuppressWarnings({"OverridableMethodCallInConstructor", "CallToThreadStartDuringObjectConstruction"})
238
    protected JDBCStoreProviderBase(
239
            JDBCStoreParameters params,
240
            DataStoreProviderServices storeServices,
241
            DynObject metadata,
242
            JDBCHelper helper
243
    ) throws InitializeException {
244
        super(params, storeServices, metadata);
245
        this.helper = helper;
246
        this.initializeFeatureType();
247
        try {
248
            if( BooleanUtils.isTrue((Boolean) params.getDynValue("precalculateEnvelope"))  ) {
249
                FeatureType featureType = this.getStoreServices().getDefaultFeatureType();
250
                if( !StringUtils.isEmpty(featureType.getDefaultGeometryAttributeName()) ) {
251
                    Thread thread = new Thread(() -> {
252
                        LOGGER.trace("Precalculating envelope of '"+getSourceId()+"'.");
253
                        getEnvelopeValue().get();
254
                    }, "PrecalculateEnvelopeOfDBTable");
255
                    thread.start();
256
                    Thread.sleep(1);
257
                }
258
           }
259
        } catch(Exception ex) {
260
            LOGGER.warn("Probems precalculating the envelope of table '"+this.getSourceId()+"'.", ex);
261
        }
262
    }
263

    
264
    @Override
265
    public JDBCStoreParameters getParameters() {
266
        return (JDBCStoreParameters) super.getParameters();
267
    }  
268

    
269
    @Override
270
    public JDBCHelper getHelper() {
271
        return helper;
272
    }
273
    
274
    public OperationsFactory getOperations() {
275
        return this.getHelper().getOperations();
276
    }
277
    
278
    @Override
279
    public String getProviderName() {
280
        return this.getHelper().getProviderName();
281
    }
282
    
283
    @Override
284
    public int getOIDType() {
285
        return DataTypes.UNKNOWN;
286
    }
287

    
288
    @Override
289
    public Object createNewOID() {
290
        return null;
291
    }
292
    
293
    @Override
294
    public boolean allowAutomaticValues() {
295
        return this.getHelper().allowAutomaticValues();
296
    }
297

    
298
    @Override
299
    public boolean allowWrite() {
300
        return this.getAllowWriteValue().get();
301
    }
302
    
303
    @Override
304
    public Object getDynValue(String name) throws DynFieldNotFoundException {
305
        try {
306
            if (DataStore.METADATA_ENVELOPE.equalsIgnoreCase(name)) {
307
                Envelope env = this.getEnvelope();
308
                if (env != null) {
309
                    return env;
310
                }
311
            } else if (DataStore.METADATA_CRS.equalsIgnoreCase(name)) {
312
                IProjection proj;
313
                proj = this.getFeatureStore().getDefaultFeatureType().getDefaultSRS();
314
                if (proj != null) {
315
                    return proj;
316
                }
317
            }
318
        } catch (DataException e) {
319
            throw new RuntimeException(e);
320
        }
321
        return super.getDynValue(name);
322
    }
323

    
324
    @Override
325
    public CalculatedValue<Long> getCountValue() {
326
        if( this.count == null ) {
327
            this.count = new CountValue();
328
        }
329
        return this.count;
330
    }
331

    
332
    @Override
333
    public CalculatedValue<Envelope> getEnvelopeValue() {
334
        if( this.envelope == null ) {
335
            this.envelope = new EnvelopeValue();
336
        }
337
        return this.envelope;
338
    }
339
    
340
    @Override
341
    public CalculatedValue<Boolean> getAllowWriteValue() {
342
        if( this.allowWrite == null ) {
343
            this.allowWrite = new AllowWriteValue();
344
        }
345
        return this.allowWrite;
346
    }
347
    
348
    @Override
349
    public long getFeatureCount() throws DataException {
350
        return this.getCountValue().get();
351
    }
352
    
353
    @Override
354
    public boolean closeResourceRequested(ResourceProvider resource) {
355
        ResulSetControler resulSetControler = this.getHelper().getResulSetControler();
356
        resulSetControler.pack();
357
        return resulSetControler.getOpenCount() == 0;
358
    }
359

    
360
    @Override
361
    public void close() throws CloseException {
362
        JDBCUtils.closeQuietly(this.getHelper());
363
    }
364

    
365
    @Override
366
    public void resourceChanged(ResourceProvider resource) {
367
        this.getStoreServices().notifyChange(
368
                DataStoreNotification.RESOURCE_CHANGED,
369
                resource
370
        );
371
    }
372

    
373
    @Override
374
    public DataServerExplorer getExplorer() throws ReadException {
375
        DataManager manager = DALLocator.getDataManager();
376
        JDBCServerExplorerParameters exParams;
377
        JDBCStoreParameters params = getParameters();
378
        try {
379
            exParams = this.getHelper().createServerExplorerParameters();
380
            DynField[] fields = exParams.getDynClass().getDynFields();
381
            for (DynField field : fields) {
382
                try {
383
                    exParams.setDynValue(field.getName(), params.getDynValue(field.getName()));
384
                } catch(Exception ex) {
385
                    // Ignore
386
                }
387
            }
388
            exParams.setHost(params.getHost());
389
            exParams.setPort(params.getPort());
390
            exParams.setDBName(params.getDBName());
391
            exParams.setUser(params.getUser());
392
            exParams.setPassword(params.getPassword());
393
            exParams.setUrl(params.getUrl());
394
            exParams.setCatalog(params.getCatalog());
395
            exParams.setSchema(params.getSchema());
396
            exParams.setJDBCDriverClassName(params.getJDBCDriverClassName());
397

    
398
            return manager.openServerExplorer(exParams.getExplorerName(), exParams);
399
        } catch (Exception e) {
400
            throw new ReadException(this.getProviderName(), e);
401
        }
402
    }
403

    
404
    @Override
405
    protected void doDispose() throws BaseException {
406
        this.close();
407
        this.getHelper().dispose();
408
        super.doDispose();
409
    }
410

    
411
    @Override
412
    public String getSourceId() {
413
        try {
414
            return this.getHelper().getSourceId(this.getParameters());
415
        } catch(Exception ex) {
416
            return "unknow";
417
        }
418
    }
419

    
420
    @Override
421
    public String getName() {
422
        return this.getParameters().getTable();
423
    }
424

    
425
    @Override
426
    public String getFullName() {
427
        return this.getHelper().getSourceId(this.getParameters());
428
    }
429

    
430
    private static class DummyResource extends AbstractResource {
431

    
432
        private final String name;
433

    
434
        DummyResource(String name) throws InitializeException {
435
            super((ResourceParameters)null);
436
            this.name = name;
437
        }
438
        
439
        @Override
440
        public String getName() throws AccessResourceException {
441
            return MessageFormat.format("DummyResource({0})",
442
                                new Object[] { this.name });
443
        }
444

    
445
        @Override
446
        public Object get() throws AccessResourceException {
447
            return null;
448
        }
449

    
450
        @Override
451
        public boolean isThis(ResourceParameters parameters) throws ResourceException {
452
            return true;
453
        }
454
        
455
    }
456
    
457
    @Override
458
    public ResourceProvider getResource() {
459
        ResourceProvider r = getHelper().getResource();
460
        if( r == null ) {
461
            try {
462
                r = new DummyResource(this.getName());
463
            } catch (InitializeException ex) {
464
                LOGGER.warn("Can't create DummyResource",ex);
465
                // Do nothing
466
            }
467
        }
468
        return r;
469
    }
470

    
471
    @Override
472
    public void open() throws OpenException {
473

    
474
    }
475

    
476
    @Override
477
    public FeatureSetProvider createSet(
478
            FeatureQuery query,
479
            FeatureType featureType
480
        ) throws DataException {
481
        
482
        FeatureSetProvider set = new JDBCSetProvider(
483
                this,
484
                this.getHelper(), 
485
                query, 
486
                featureType
487
        );
488
        
489
        return set;
490
    }
491

    
492
    protected void initializeFeatureType() {
493
        EditableFeatureType type = this.getStoreServices().createFeatureType(getName());
494
        JDBCStoreParameters params = this.getParameters();
495
        List<String> primaryKeys = null;
496
        if( params.getPkFields() != null ) {
497
            primaryKeys = Arrays.asList(params.getPkFields());
498
        }
499
        FetchFeatureTypeOperation fetchFeatureType = 
500
             this.getOperations().createFetchFeatureType(
501
                type,
502
                this.getOperations().createTableReference(params),
503
                primaryKeys,
504
                params.getDefaultGeometryField(),
505
                params.getCRS()
506
            );
507
        fetchFeatureType.perform();
508

    
509
        if (!StringUtils.isBlank(params.getDefaultGeometryField())) {
510
            if (!params.getDefaultGeometryField().equalsIgnoreCase(type.getDefaultGeometryAttributeName())) {
511
                if (type.getAttributeDescriptor(params.getDefaultGeometryField()) != null) {
512
                    type.setDefaultGeometryAttributeName(params.getDefaultGeometryField());
513
                } else {
514
                    type.setDefaultGeometryAttributeName(null);
515
                }
516
                if (type.getDefaultGeometryAttribute() != null) {
517
                    EditableFeatureAttributeDescriptor attr = (EditableFeatureAttributeDescriptor) type.getDefaultGeometryAttribute();
518
                    attr.setGeometryType(Geometry.TYPES.GEOMETRY, Geometry.SUBTYPES.GEOM2D);
519
                }
520
            } else {
521
                type.setDefaultGeometryAttributeName(null);
522
            }
523
        }
524
        
525
        FeatureType defaultType = type.getNotEditableCopy();
526
        this.getHelper().setProviderFeatureType(defaultType);
527
        List<FeatureType> types = Collections.singletonList(defaultType);
528
        this.getStoreServices().setFeatureTypes(types, defaultType);
529
    }
530

    
531
    @Override
532
    protected FeatureProvider internalGetFeatureProviderByReference(
533
            FeatureReferenceProviderServices reference, 
534
            FeatureType featureType
535
        ) throws DataException {
536
        JDBCStoreParameters params = this.getParameters();
537
        FetchFeatureProviderByReferenceOperation fetchFeatureProviderByReference = 
538
            this.getOperations().createFetchFeatureProviderByReference(
539
                reference, 
540
                featureType, 
541
                this.getOperations().createTableReference(params)
542
            );
543
        FeatureProvider feature = (FeatureProvider) fetchFeatureProviderByReference.perform();
544
        return feature;
545
    }
546
    
547
    @Override
548
    public Envelope getEnvelope() throws DataException {
549
        return this.getEnvelopeValue().get();
550
    }
551

    
552
    @Override
553
    public void performChanges(Iterator deleteds, Iterator inserteds,
554
                    Iterator updateds, Iterator featureTypesChanged)
555
                    throws DataException {
556

    
557
        FeatureType type = this.getFeatureStore().getDefaultFeatureType();
558
        JDBCStoreParameters params = this.getParameters();
559
        PerformChangesOperation performChanges = this.getOperations().createPerformChanges(
560
                this.getOperations().createTableReference(params),
561
                type, 
562
                deleteds, 
563
                inserteds, 
564
                updateds, 
565
                featureTypesChanged
566
        );
567
        performChanges.perform();
568
        if( performChanges.isTypeChanged() ) {
569
            // Get rules before initializing feature type
570
            FeatureRules saved_rules = getFeatureStore().getDefaultFeatureType().getRules();
571

    
572
             // This initialization loses the feature type rules
573
            this.initializeFeatureType();
574

    
575
            // Get new feature type, clear rules and add the ones saved previously
576
            FeatureType featureType = getFeatureStore().getDefaultFeatureType();
577
            FeatureRules rules = featureType.getRules();
578
            rules.clear();
579
            for (FeatureRule rule : saved_rules) {
580
                rules.add(rule);
581
            }
582
        }
583
        this.getCountValue().reset();
584
        this.getEnvelopeValue().reset();
585
    }    
586
    
587
    @Override
588
    public boolean supportsAppendMode() {
589
        return true;
590
    }
591

    
592
    protected AppendOperation getAppendOperation() throws DataException {
593
        if( this.appendOperation == null ) {
594
            FeatureType type = this.getFeatureStore().getDefaultFeatureType();
595
            JDBCStoreParameters params = this.getParameters();
596
            this.appendOperation = this.getOperations().createAppend(
597
                this.getOperations().createTableReference(params),
598
                type 
599
            );
600
        }
601
        return this.appendOperation;
602
    }
603
    
604
    @Override
605
    public void endAppend() throws DataException {
606
        this.getAppendOperation().end();
607
    }
608

    
609
    @Override
610
    public void abortAppend() throws DataException {
611
        this.getAppendOperation().abort();
612
    }
613
    
614
    @Override
615
    public void beginAppend() throws DataException {
616
        this.getAppendOperation().begin();
617
    }
618

    
619
    @Override
620
    public void append(final FeatureProvider featureProvider) throws DataException {
621
        this.getAppendOperation().append(featureProvider);
622
    }    
623
    
624
    @Override
625
    public boolean canWriteGeometry(int geometryType, int geometrySubtype)
626
            throws DataException {
627
        return this.getHelper().canWriteGeometry(geometryType,geometrySubtype);
628
    }
629

    
630
    @Override
631
    public boolean supportsPassThroughMode() {
632
        return true;
633
    }
634

    
635
    @Override
636
    public void passThroughInsert(FeatureProvider featureProvider) throws DataException {
637
        FeatureType type = this.getFeatureStore().getDefaultFeatureType();
638
        JDBCStoreParameters params = this.getParameters();
639
        PerformChangesOperation performChanges = this.getOperations().createPerformChanges(
640
                this.getOperations().createTableReference(params),
641
                type, 
642
                Collections.emptyIterator(), 
643
                Collections.singletonList(featureProvider).iterator(),
644
                Collections.emptyIterator(), 
645
                Collections.emptyIterator()
646
        );
647
        performChanges.perform();
648
    }
649

    
650
    @Override
651
    public void passThroughUpdate(FeatureProvider featureProvider) throws DataException {
652
        FeatureType type = this.getFeatureStore().getDefaultFeatureType();
653
        JDBCStoreParameters params = this.getParameters();
654
        PerformChangesOperation performChanges = this.getOperations().createPerformChanges(
655
                this.getOperations().createTableReference(params),
656
                type, 
657
                Collections.emptyIterator(), 
658
                Collections.emptyIterator(), 
659
                Collections.singletonList(featureProvider).iterator(),
660
                Collections.emptyIterator()
661
        );
662
        performChanges.perform();
663
    }
664
    
665
    @Override
666
    public void passThroughUpdate(Object[] parameters, Expression filter){
667
        JDBCStoreParameters params = this.getParameters();
668
        UpdatePassThroughOperation operation = this.getOperations().createUpdatePassThroughOperation(
669
                this.getOperations().createTableReference(params),
670
                parameters,
671
                filter
672
        );
673
        operation.perform();
674
    }
675

    
676
    @Override
677
    public void passThroughDelete(FeatureReferenceProviderServices featureReference) throws DataException {
678
        FeatureType type = this.getFeatureStore().getDefaultFeatureType();
679
        JDBCStoreParameters params = this.getParameters();
680
        PerformChangesOperation performChanges = this.getOperations().createPerformChanges(
681
                this.getOperations().createTableReference(params),
682
                type, 
683
                Collections.singletonList(featureReference).iterator(),
684
                Collections.emptyIterator(), 
685
                Collections.emptyIterator(), 
686
                Collections.emptyIterator()
687
        );
688
        performChanges.perform();
689
    }
690
    
691
    public void passThroughDelete(Expression expression) throws DataException {
692
        JDBCStoreParameters params = this.getParameters();
693
        DeletePassThroughOperation operation = this.getOperations().createDeletePassThroughOperation(
694
                this.getOperations().createTableReference(params),
695
                expression
696
        );
697
        operation.perform();
698
    }
699
}