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

History | View | Annotate | Download (9.77 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
                }
206
              }
207
          }            
208
        }        
209
        if( limit > 0 ) {
210
            select.limit(limit);
211
        } else {
212
            select.limit(query==null? null:query.getLimit());
213
        }
214
        if( offset>0 ) {
215
            select.offset(offset);
216
        }        
217
        sqlbuilder.setProperties(
218
                null, 
219
                PROP_FEATURE_TYPE, this.storeType,
220
                PROP_TABLE, table
221
        );        
222
        this.helper.processSpecialFunctions(sqlbuilder, storeType, extraColumnNames);
223
        String sql = sqlbuilder.toString();
224
        return sql;
225
    }
226
    
227
    public ResultSetEntry createResultSet() throws DataException {
228
        List<FeatureAttributeDescriptor> columns = new ArrayList<>();
229
        List<String> extraColumnNames = new ArrayList<>();
230

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

    
242
}