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 @ 44369

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

    
206
}