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

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

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

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

    
61
    @Override
62
    protected Object perform_operation() throws Exception {
63
        ResultSetEntry rs = createResultSet();
64
        return rs;
65
    }
66
    
67
    @Override
68
    public Object perform(Connection conn) throws DataException {
69
        throw new UnsupportedOperationException("Not supported yet."); 
70
    }
71

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

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

    
232
        JDBCSQLBuilderBase sqlbuilder = createSQLBuilder();
233
        String sql = this.getSQL(sqlbuilder, columns, extraColumnNames);
234
        
235
        ResultSetEntry resultSetEntry = this.helper.getResulSetControler().create(
236
                sql, fetchSize, 
237
                columns.toArray(new FeatureAttributeDescriptor[columns.size()]),
238
                extraColumnNames.toArray(new String[extraColumnNames.size()])
239
        );
240
        return resultSetEntry;
241
    }
242

    
243
}