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 / jdbc / JDBCSetProvider.java @ 40596

History | View | Annotate | Download (10.5 KB)

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

    
26
import java.util.ArrayList;
27
import java.util.Arrays;
28
import java.util.Iterator;
29
import java.util.List;
30
import java.util.NoSuchElementException;
31

    
32
import org.gvsig.fmap.dal.DataTypes;
33
import org.gvsig.fmap.dal.exception.DataException;
34
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
35
import org.gvsig.fmap.dal.feature.FeatureQuery;
36
import org.gvsig.fmap.dal.feature.FeatureQueryOrder;
37
import org.gvsig.fmap.dal.feature.FeatureType;
38
import org.gvsig.fmap.dal.feature.FeatureQueryOrder.FeatureQueryOrderMember;
39
import org.gvsig.fmap.dal.feature.spi.AbstractFeatureSetProvider;
40
import org.gvsig.tools.evaluator.Evaluator;
41
import org.gvsig.tools.evaluator.EvaluatorFieldValue;
42
import org.gvsig.tools.evaluator.EvaluatorFieldsInfo;
43
import org.gvsig.tools.exception.BaseException;
44
import org.slf4j.Logger;
45
import org.slf4j.LoggerFactory;
46

    
47
/**
48
 * @author jmvivo
49
 *
50
 */
51
public class JDBCSetProvider extends AbstractFeatureSetProvider {
52

    
53
        final static private Logger logger = LoggerFactory
54
                        .getLogger(JDBCSetProvider.class);
55

    
56
        protected String filter;
57
        protected String order;
58
        protected Long size = null;
59
        protected Boolean isEmpty = null;
60

    
61
        protected List resultSetIDReferenced;
62

    
63
        private JDBCHelper helper = null;
64

    
65
        private int defaultFetchSize = 1000;
66

    
67
        private long limit = -1l;
68

    
69
    private boolean directSQLMode;
70

    
71
        public JDBCSetProvider(JDBCStoreProvider store, FeatureQuery query,
72
                        FeatureType featureType) throws DataException {
73
                super(store, query, featureType);
74
                this.helper = store.getHelper();
75
                this.resultSetIDReferenced = new ArrayList();
76
                this.directSQLMode =  store.isDirectSQLMode();
77
        
78
                if (query.hasFilter() && this.canFilter()) {
79
                        setFilter(query.getFilter());
80
                } else {
81
                        setFilter(null);
82
                }
83

    
84
                if (query.hasOrder() && canOrder()) {
85
                        setOrder(query.getOrder());
86
                } else {
87
                        setOrder(null);
88
                }
89

    
90
                if (query != null) {
91
                        limit = query.getLimit();
92
                }
93
        }
94

    
95
        /**
96
         * @return the defaultFetchSize
97
         */
98
        public int getDefaultFetchSize() {
99
                return defaultFetchSize;
100
        }
101

    
102
        /**
103
         * @param defaultFetchSize
104
         *            the defaultFetchSize to set
105
         */
106
        public void setDefaultFetchSize(int defaultFetchSize) {
107
                this.defaultFetchSize = defaultFetchSize;
108
        }
109

    
110
        protected String getSqlForEvaluator(Evaluator filter) {
111
                if (filter == null) {
112
                        return null;
113
                }
114
                EvaluatorFieldsInfo info = filter.getFieldsInfo();
115
                String filterString = filter.getSQL();
116
                if (info == null) {
117
                        return filterString;
118
                }
119
                String[] filterNames = info.getFieldNames();
120
                String[] finalNames = new String[filterNames.length];
121
                EvaluatorFieldValue[] fValues;
122

    
123
                List values = new ArrayList();
124

    
125
                FeatureAttributeDescriptor attr;
126
                for (int i = 0; i < filterNames.length; i++) {
127
                        attr = getFeatureType().getAttributeDescriptor(filterNames[i]);
128
                        if (attr == null) {
129
                                finalNames[i] = filterNames[i];
130
                                continue;
131
                        }
132
                        finalNames[i] = getEscapedFieldName(attr.getName());
133

    
134
                }
135

    
136
                for (int i = 0; i < filterNames.length; i++) {
137
                        if (!filterNames[i].equals(finalNames[i])) {
138
                                filterString.replaceAll("\\b" + filterNames[i] + "\\b",
139
                                                finalNames[i]);
140
                        }
141
                }
142

    
143
                return filterString;
144
        }
145

    
146

    
147
        protected String getEscapedFieldName(String fieldName) {
148
                if (helper == null) {
149
                        helper = getJDBCStoreProvider().getHelper();
150
                }
151
                return helper.escapeFieldName(fieldName);
152
        }
153

    
154

    
155
        protected void setOrder(FeatureQueryOrder order) {
156
                if (order == null || order.size() == 0) {
157
                        this.order = null;
158
                        return;
159
                }
160

    
161
                StringBuilder buffer = new StringBuilder();
162
                Iterator iter = order.iterator();
163
                FeatureQueryOrderMember menber;
164
                while (true) {
165
                        menber = (FeatureQueryOrderMember) iter.next();
166
                        if (menber.hasEvaluator()) {
167
                                buffer.append(getSqlForEvaluator(menber.getEvaluator()));
168
                        } else {
169
                                buffer.append(getEscapedFieldName(menber.getAttributeName()));
170
                        }
171
                        if (menber.getAscending()) {
172
                                buffer.append(" ASC");
173
                        } else {
174
                                buffer.append(" DESC");
175
                        }
176
                        if (iter.hasNext()) {
177
                                buffer.append(", ");
178
                        } else {
179
                                buffer.append(' ');
180
                                break;
181
                        }
182
                }
183

    
184
                this.order = buffer.toString();
185
        }
186

    
187
        protected void setFilter(Evaluator filter) {
188
                this.filter = getSqlForEvaluator(filter);
189
        }
190

    
191

    
192

    
193
        /* (non-Javadoc)
194
         * @see org.gvsig.fmap.dal.feature.spi.FeatureSetProvider#canFilter()
195
         */
196
        public boolean canFilter() {
197
                Evaluator filter = getQuery().getFilter();
198
                if (directSQLMode){
199
                    return false;
200
                }
201
                if (filter != null) {
202
                        if (filter.getSQL() == null || filter.getSQL().length() == 0) {
203
                                return false;
204
                        } else {
205
                                // TODO Check Geom fields if
206
                                EvaluatorFieldsInfo fInfo = filter.getFieldsInfo();
207
                                if (fInfo == null || fInfo.getFieldNames() == null) {
208
                                        return true;
209
                                }
210
                                Iterator names = Arrays.asList(fInfo.getFieldNames())
211
                                                .iterator();
212
                                String name;
213
                                int type;
214
                                while (names.hasNext()) {
215
                                        name = (String) names.next();
216
                                        type =
217
                                                        this.getFeatureType()
218
                                                                        .getAttributeDescriptor(name)
219
                                                        .getType();
220
                                        if (type == DataTypes.GEOMETRY
221
                                                        && !this.helper.supportsGeometry()) {
222
                                                return false;
223
                                        }
224

    
225

    
226

    
227
                                }
228

    
229
                                return true;
230
                        }
231

    
232
                } else{
233
                        return false;
234
                }
235
        }
236

    
237
        /* (non-Javadoc)
238
         * @see org.gvsig.fmap.dal.feature.spi.FeatureSetProvider#canIterateFromIndex()
239
         */
240
        public boolean canIterateFromIndex() {
241
                return helper.supportOffset();
242
        }
243

    
244
        /* (non-Javadoc)
245
         * @see org.gvsig.fmap.dal.feature.spi.FeatureSetProvider#canOrder()
246
         */
247
        public boolean canOrder() {
248
            if (directSQLMode){
249
                return false;
250
            }
251
                // TODO Check Geom fields if postgis not are available
252
                FeatureQuery query = getQuery();
253
                if (query.hasOrder()) {
254
                        Iterator iter = query.getOrder().iterator();
255
                        FeatureQueryOrderMember menber;
256
                        String sql;
257
                        while (iter.hasNext()){
258
                                menber = (FeatureQueryOrderMember) iter.next();
259
                                if (menber.hasEvaluator()){
260
                                        sql = menber.getEvaluator().getSQL();
261
                                        if (sql == null || sql.length() == 0) {
262
                                                return false;
263
                                        }
264
                                }
265
                        }
266
                }
267
                return true;
268
        }
269

    
270
        private JDBCStoreProvider getJDBCStoreProvider() {
271
                return (JDBCStoreProvider) getStore();
272
        }
273

    
274
        @Override
275
        protected void doDispose() throws BaseException {
276
                if (resultSetIDReferenced != null) {
277
                        Iterator iter = resultSetIDReferenced.iterator();
278
                        Integer resID;
279
                        while (iter.hasNext()) {
280
                                resID = (Integer) iter.next();
281
                                if (resID != null) {
282
                                        logger.warn(
283
                                                "ResultSet (ID {}) not closed on dispose, will close",
284
                                                resID);
285
                                        try {
286
                                                getJDBCStoreProvider().closeResulset(resID.intValue());
287
                                        } catch (DataException e) {
288
                                                logger.error("Close resulset Exception", e);
289
                                        }
290
                                }
291
                                iter.remove();
292
                        }
293
                }
294
                resultSetIDReferenced = null;
295
                filter = null;
296
                order = null;
297
                size = null;
298
                isEmpty = null;
299
        }
300

    
301
        protected String getSQL(long fromIndex) throws DataException {
302
                return getJDBCStoreProvider().compoundSelect(getFeatureType(), filter,
303
                                order, limit, fromIndex);
304

    
305
        }
306

    
307
        /* (non-Javadoc)
308
         * @see org.gvsig.fmap.dal.feature.spi.FeatureSetProvider#getSize()
309
         */
310
        public long getSize() throws DataException {
311
                if (size == null) {
312
                        size = new Long(getJDBCStoreProvider().getCount(filter));
313
                }
314
                return size.longValue();
315
        }
316

    
317
        /* (non-Javadoc)
318
         * @see org.gvsig.fmap.dal.feature.spi.FeatureSetProvider#isEmpty()
319
         */
320
        public boolean isEmpty() throws DataException {
321
                JDBCStoreProvider store = getJDBCStoreProvider();
322
                if (isEmpty == null) {
323
                        if (size == null) {
324
                                String sql =
325
                                                store.compoundSelect(getFeatureType(), filter, null, 1,
326
                                                                0);
327
                                int rsID = store.createResultSet(sql, getFetchSize());
328
                                isEmpty = new Boolean(!store.resulsetNext(rsID));
329
                                store.closeResulset(rsID);
330
                        } else {
331
                                isEmpty = new Boolean(size.longValue() < 1);
332
                        }
333
                }
334
                return isEmpty.booleanValue();
335
        }
336

    
337
        protected int getFetchSize() {
338
                long pageSize = -1;
339
                if (getQuery() != null) {
340
                        pageSize = getQuery().getPageSize();
341
                        pageSize =
342
                                        pageSize > Integer.MAX_VALUE ? Integer.MAX_VALUE : pageSize;
343
                }
344
                return (pageSize > 0 ? (int) pageSize : defaultFetchSize);
345
        }
346

    
347
        protected JDBCIterator createFastIterator(long index) throws DataException {
348
                if (isEmpty != null && isEmpty.booleanValue()) {
349
                        return new EmptyJDBCIterator(getJDBCStoreProvider());
350
                }
351
                int rsID =
352
                                getJDBCStoreProvider().createResultSet(getSQL(index),
353
                                                getFetchSize());
354
                return createDefaultFastIterator(rsID);
355
        }
356

    
357
        protected JDBCIterator createDefaultFastIterator(int resultSetID)
358
                        throws DataException {
359
                return new JDBCFastIterator(getJDBCStoreProvider(), this,
360
                                getFeatureType(), resultSetID);
361
        }
362

    
363
        protected JDBCIterator createIterator(long index) throws DataException {
364
        if (isEmpty != null && isEmpty.booleanValue()) {
365
            return new EmptyJDBCIterator(getJDBCStoreProvider());
366
        }
367
        int rsID =
368
                getJDBCStoreProvider().createResultSet(getSQL(index),
369
                        getFetchSize());
370
        return createDefaultIterator(rsID);
371
        }
372

    
373
        protected JDBCIterator createDefaultIterator(int resultSetID)
374
                        throws DataException {
375
                return new JDBCIterator(getJDBCStoreProvider(), this, getFeatureType(),
376
                                resultSetID);
377
        }
378

    
379
        public void addResulsetReference(int resulsetID) {
380
                this.resultSetIDReferenced.add(new Integer(resulsetID));
381
        }
382

    
383
        public void removeResulsetReference(int resulsetID) {
384
                this.resultSetIDReferenced.remove(new Integer(resulsetID));
385
        }
386

    
387
        private class EmptyJDBCIterator extends JDBCIterator {
388

    
389
                protected EmptyJDBCIterator(JDBCStoreProvider store) throws DataException {
390
                        super(store, null, null, -1);
391
                }
392

    
393
                @Override
394
                protected boolean internalHasNext() {
395
                        return false;
396
                }
397

    
398
                @Override
399
                protected Object internalNext() {
400
                        throw new NoSuchElementException();
401
                }
402

    
403
                @Override
404
                protected void doDispose() throws BaseException {
405
                        // nothing to do
406
                }
407

    
408
        }
409

    
410
}