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

History | View | Annotate | Download (8.63 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.fmap.dal.exception.DataException;
10
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
11
import org.gvsig.fmap.dal.feature.FeatureQuery;
12
import org.gvsig.fmap.dal.feature.FeatureQueryOrder;
13
import org.gvsig.fmap.dal.feature.FeatureQueryOrder.FeatureQueryOrderMember;
14
import org.gvsig.fmap.dal.feature.FeatureType;
15
import org.gvsig.fmap.dal.store.jdbc2.JDBCHelper;
16
import org.gvsig.fmap.dal.store.jdbc2.OperationsFactory.TableReference;
17
import org.gvsig.fmap.dal.store.jdbc2.ResulSetControler.ResultSetEntry;
18
import org.gvsig.fmap.dal.store.jdbc2.spi.JDBCSQLBuilderBase;
19
import static org.gvsig.fmap.dal.store.jdbc2.spi.JDBCSQLBuilderBase.PROP_FEATURE_TYPE;
20
import static org.gvsig.fmap.dal.store.jdbc2.spi.JDBCSQLBuilderBase.PROP_TABLE;
21
import org.gvsig.fmap.geom.DataTypes;
22
import org.gvsig.tools.evaluator.Evaluator;
23

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

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

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

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

    
206
        String sql = sqlbuilder.toString();
207
        ResultSetEntry resultSetEntry = this.helper.getResulSetControler().create(
208
                sql, fetchSize, 
209
                columns.toArray(new FeatureAttributeDescriptor[columns.size()]),
210
                extraColumnNames
211
        );
212
        return resultSetEntry;
213
    }
214

    
215
}