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 / ResultSetForSetProviderOperation.java @ 44198

History | View | Annotate | Download (8.24 KB)

1
package org.gvsig.fmap.dal.store.jdbc2.spi.operations;
2

    
3
import java.sql.Connection;
4
import java.util.ArrayList;
5
import java.util.List;
6
import org.apache.commons.lang3.ArrayUtils;
7
import org.apache.commons.lang3.StringUtils;
8
import org.gvsig.expressionevaluator.ExpressionBuilder;
9
import org.gvsig.expressionevaluator.ExpressionBuilder.Variable;
10
import org.gvsig.fmap.dal.exception.DataException;
11
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
12
import org.gvsig.fmap.dal.feature.FeatureQuery;
13
import org.gvsig.fmap.dal.feature.FeatureQueryOrder;
14
import org.gvsig.fmap.dal.feature.FeatureQueryOrder.FeatureQueryOrderMember;
15
import org.gvsig.fmap.dal.feature.FeatureType;
16
import org.gvsig.fmap.dal.store.jdbc2.JDBCHelper;
17
import org.gvsig.fmap.dal.store.jdbc2.OperationsFactory.TableReference;
18
import org.gvsig.fmap.dal.store.jdbc2.ResulSetControler.ResultSetEntry;
19
import org.gvsig.fmap.dal.store.jdbc2.spi.JDBCSQLBuilderBase;
20
import static org.gvsig.fmap.dal.store.jdbc2.spi.JDBCSQLBuilderBase.PROP_FEATURE_TYPE;
21
import static org.gvsig.fmap.dal.store.jdbc2.spi.JDBCSQLBuilderBase.PROP_TABLE;
22
import org.gvsig.fmap.geom.DataTypes;
23
import org.gvsig.tools.evaluator.Evaluator;
24

    
25
public class ResultSetForSetProviderOperation extends AbstractConnectionOperation {
26
    private final TableReference table;
27
    private final String baseFilter;
28
    private final String baseOrder;
29
    private final FeatureType storeType;
30
    private final FeatureType setType;
31
    private final FeatureQuery query;
32
    private final long limit;
33
    private final long offset;
34
    private final int fetchSize;
35

    
36
    public ResultSetForSetProviderOperation(
37
            JDBCHelper helper,
38
            TableReference table,
39
            String baseFilter,
40
            String baseOrder,
41
            FeatureQuery query,
42
            FeatureType storeType,
43
            FeatureType setType,
44
            long limit,
45
            long offset,
46
            int fetchSize
47
        ) {
48
        super(helper);
49
        this.table = table;
50
        this.baseFilter = baseFilter;
51
        this.baseOrder = baseOrder;
52
        this.storeType = storeType;
53
        this.setType = setType;
54
        this.query = query;
55
        this.limit = limit;
56
        this.offset = offset;
57
        this.fetchSize = fetchSize; 
58
    }
59

    
60
    @Override
61
    protected Object perform_operation() throws Exception {
62
        ResultSetEntry rs = createResultSet(
63
                table, baseFilter, baseOrder, storeType, setType, query, 
64
                limit, offset, fetchSize);
65
        return rs;
66
    }
67
    
68
    @Override
69
    public Object perform(Connection conn) throws DataException {
70
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
71
    }
72
    
73
    public ResultSetEntry createResultSet(
74
            TableReference table,
75
            String baseFilter,
76
            String baseOrder,
77
            FeatureType storeType,
78
            FeatureType setType,
79
            FeatureQuery query,
80
            long limit,
81
            long offset,
82
            int fetchSize
83
        ) throws DataException {
84
        List<FeatureAttributeDescriptor> columns = new ArrayList<>();
85
        
86
        double tolerance = -1 ; //query.getScale();
87
        JDBCSQLBuilderBase sqlbuilder = createSQLBuilder();
88
        ExpressionBuilder expbuilder = sqlbuilder.expression();
89
        
90
        List<String> primaryKeys = new ArrayList<>();
91
        for(FeatureAttributeDescriptor attr : storeType.getPrimaryKey() ) {
92
            primaryKeys.add(attr.getName());
93
        }
94
        List<String> forcedColumns = new ArrayList<>(primaryKeys);
95

    
96
        String[] constantsAttributeNames = null;
97
        if(query !=null && query.hasConstantsAttributeNames() ) {
98
            constantsAttributeNames = query.getConstantsAttributeNames();
99
        }
100
        for(FeatureAttributeDescriptor attr : setType ) {
101
            if( ArrayUtils.contains(constantsAttributeNames, attr.getName()) ) {
102
                continue;
103
            }
104
            if( attr.isPrimaryKey() ) {
105
                forcedColumns.remove(attr.getName());
106
            }
107
            if( attr.getType() == DataTypes.GEOMETRY ) {
108
                sqlbuilder.select().column().name(attr.getName()).as_geometry();
109
//                if( tolerance<=0 || !sqlbuilder.getConfig().has_functionality(Config.ST_Simplify)) {
110
//                    sqlbuilder.select().column().name(attr.getName()).as_geometry();
111
//                } else {
112
//                    sqlbuilder.select().column().value(
113
//                        sqlbuilder.ST_Simplify( 
114
//                            sqlbuilder.column(attr.getName()),
115
//                            sqlbuilder.constant(tolerance)
116
//                        )
117
//                    ).as_geometry();
118
//                }
119
                columns.add(attr);
120
            } else {
121
                sqlbuilder.select().column().name(attr.getName());
122
                columns.add(attr);
123
            }
124
        }
125
        for(String attrName : forcedColumns ) {
126
            sqlbuilder.select().column().name(attrName);
127
            columns.add(setType.getAttributeDescriptor(attrName));
128
        }
129
        
130
        sqlbuilder.select().from().table()
131
                .database(this.table.getDatabase())
132
                .schema(this.table.getSchema())
133
                .name(this.table.getTable());
134
        sqlbuilder.select().from().subquery(this.table.getSubquery());
135
        
136
        Evaluator filter = query==null? null:query.getFilter();
137
        if( filter != null ) {
138
            String sqlfilter = filter.getSQL();
139
            if( ! StringUtils.isEmpty(sqlfilter) ) {
140
                if( this.helper.supportFilter(this.storeType, filter) ) {
141
                    sqlbuilder.select().where().set(expbuilder.toValue(sqlfilter));
142
                }
143
            }
144
        }
145
        if( ! StringUtils.isEmpty(baseFilter) ) {
146
            sqlbuilder.select().where().and(expbuilder.toValue(baseFilter));
147
        }
148
        
149
        FeatureQueryOrder order = query==null? null:query.getOrder();
150
        if( order != null ) {
151
            for( FeatureQueryOrderMember member : order.members() ) {
152
                if( member.hasEvaluator() ) {
153
                    String sqlorder = member.getEvaluator().getSQL();
154
                    if( ! StringUtils.isEmpty(sqlorder) ) {
155
                        sqlbuilder.select().order_by()
156
                                .custom(sqlorder);
157
                    }
158
                } else {
159
                    
160
                    sqlbuilder.select().order_by()
161
                            .column(member.getAttributeName())
162
                            .ascending(member.getAscending());
163
                }
164
            }
165
        }
166
        if( !StringUtils.isEmpty(baseOrder) ) {
167
            sqlbuilder.select().order_by().custom(baseOrder);
168
        }
169
        if( offset>0 || (offset==0 && limit>0) ) {
170
            // No tengo claro que (offset==0 && limit>0) sea lo mas correcto,
171
            // Pero cuando se va a paginar y se pide la primera pagina offset es
172
            // 0 y limit>0, y si no ordenamos ya esa primera pagina los resultados
173
            // que se obtienen no son correctos, ya que la primera pagina se saca
174
            // sin ordenar y el resto ordenadas.
175
            // Probablemente deberiamos tener alguna otra forma de detectar que
176
            // estamos paginanado ya que asi no distinguimo si solo queremos 
177
            // obtener los primeros elementos sin importarnos su orden.
178
            for(String attrName : primaryKeys ) {
179
                // Se precisa indicar un orden para usar OFFSET.
180
                sqlbuilder.select().order_by().column(sqlbuilder.as_identifier(attrName)).ascending();
181
            }
182
        }        
183
        if( limit > 0 ) {
184
            sqlbuilder.select().limit(limit);
185
        } else {
186
            sqlbuilder.select().limit(query==null? null:query.getLimit());
187
        }
188
        if( offset>0 ) {
189
            sqlbuilder.select().offset(offset);
190
        }
191
        sqlbuilder.setProperties(
192
                Variable.class, 
193
                PROP_FEATURE_TYPE, this.storeType,
194
                PROP_TABLE, table
195
        );
196
        String sql = sqlbuilder.toString();
197
        ResultSetEntry resultSetEntry = this.helper.getResulSetControler().create(
198
                sql, fetchSize, columns.toArray(new FeatureAttributeDescriptor[columns.size()])
199
        );
200
        return resultSetEntry;
201
    }
202

    
203
}