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

History | View | Annotate | Download (8.6 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
        return rs;
63
    }
64
    
65
    @Override
66
    public Object perform(Connection conn) throws DataException {
67
        throw new UnsupportedOperationException("Not supported yet."); 
68
    }
69

    
70
    public String getSQL() {
71
        List<FeatureAttributeDescriptor> columns = new ArrayList<>();
72
        JDBCSQLBuilderBase sqlbuilder = createSQLBuilder();
73
        String sql = this.getSQL(sqlbuilder, columns);
74
        return sql;
75
    }
76
    
77
    public String getSQL(JDBCSQLBuilderBase sqlbuilder, List<FeatureAttributeDescriptor> columns) {
78
        double tolerance = -1 ; //query.getScale();
79
        ExpressionBuilder expbuilder = sqlbuilder.expression();
80
        
81
        List<String> primaryKeys = new ArrayList<>();
82
        for(FeatureAttributeDescriptor attr : storeType.getPrimaryKey() ) {
83
            primaryKeys.add(attr.getName());
84
        }
85
        List<String> forcedColumns = new ArrayList<>(primaryKeys);
86

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

    
214
}