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

History | View | Annotate | Download (9.57 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
        }
143
        
144
        select.from().table()
145
                .database(this.table.getDatabase())
146
                .schema(this.table.getSchema())
147
                .name(this.table.getTable());
148
        select.from().subquery(this.table.getSubquery());
149
        
150
        Evaluator filter = query==null? null:query.getFilter();
151
        if( filter != null ) {
152
            String sqlfilter = filter.getSQL();
153
            if( ! StringUtils.isEmpty(sqlfilter) ) {
154
                if( this.helper.supportFilter(this.storeType, filter) ) {
155
                    select.where().set(expbuilder.toValue(sqlfilter));
156
                }
157
            }
158
        }
159
        if( ! StringUtils.isEmpty(baseFilter) ) {
160
            select.where().and(expbuilder.toValue(baseFilter));
161
        }
162
        
163
        FeatureQueryOrder order = query==null? null:query.getOrder();
164
        if( order != null ) {
165
            for( FeatureQueryOrderMember member : order.members() ) {
166
                if( member.hasEvaluator() ) {
167
                    String sqlorder = member.getEvaluator().getSQL();
168
                    if( ! StringUtils.isEmpty(sqlorder) ) {
169
                        select.order_by().custom(sqlorder);
170
                    }
171
                } else {
172
                    select.order_by()
173
                            .column(member.getAttributeName())
174
                            .ascending(member.getAscending());
175
                }
176
            }
177
        }
178
        if( !StringUtils.isEmpty(baseOrder) ) {
179
            select.order_by().custom(baseOrder);
180
        }
181
        if( !select.has_order_by() ) {        
182
          // Si no tenemos order by comprobamos si lo necesitamos y lo a?adimos.
183
          if( offset>0 || (offset==0 && limit>0) ) {
184
              // No tengo claro que (offset==0 && limit>0) sea lo mas correcto,
185
              // Pero cuando se va a paginar y se pide la primera pagina offset es
186
              // 0 y limit>0, y si no ordenamos ya esa primera pagina los resultados
187
              // que se obtienen no son correctos, ya que la primera pagina se saca
188
              // sin ordenar y el resto ordenadas.
189
              // Probablemente deberiamos tener alguna otra forma de detectar que
190
              // estamos paginanado ya que asi no distinguimo si solo queremos 
191
              // obtener los primeros elementos sin importarnos su orden.
192
              if( primaryKeys.isEmpty() ) {
193
                // Muy probablemente si no tiene pk sea una vista, asi que 
194
                // pasaremos de ordenar y esperemos que la vista este ya ordenada.
195
                select.disable_check_order_and_offset();
196
              } else {
197
                for(String attrName : primaryKeys ) {
198
                    // Se precisa indicar un orden para usar OFFSET.
199
                    select.order_by().column(sqlbuilder.as_identifier(attrName)).ascending();
200
                }
201
              }
202
          }            
203
        }        
204
        if( limit > 0 ) {
205
            select.limit(limit);
206
        } else {
207
            select.limit(query==null? null:query.getLimit());
208
        }
209
        if( offset>0 ) {
210
            select.offset(offset);
211
        }        
212
        sqlbuilder.setProperties(
213
                null, 
214
                PROP_FEATURE_TYPE, this.storeType,
215
                PROP_TABLE, table
216
        );        
217
        this.helper.processSpecialFunctions(sqlbuilder, storeType, extraColumnNames);
218
        String sql = sqlbuilder.toString();
219
        return sql;
220
    }
221
    
222
    public ResultSetEntry createResultSet() throws DataException {
223
        List<FeatureAttributeDescriptor> columns = new ArrayList<>();
224
        List<String> extraColumnNames = new ArrayList<>();
225

    
226
        JDBCSQLBuilderBase sqlbuilder = createSQLBuilder();
227
        String sql = this.getSQL(sqlbuilder, columns, extraColumnNames);
228
        
229
        ResultSetEntry resultSetEntry = this.helper.getResulSetControler().create(
230
                sql, fetchSize, 
231
                columns.toArray(new FeatureAttributeDescriptor[columns.size()]),
232
                extraColumnNames.toArray(new String[extraColumnNames.size()])
233
        );
234
        return resultSetEntry;
235
    }
236

    
237
}