Revision 46010 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/JDBCHelperBase.java
JDBCHelperBase.java | ||
---|---|---|
31 | 31 |
import java.util.ArrayList; |
32 | 32 |
import java.util.HashSet; |
33 | 33 |
import java.util.List; |
34 |
import java.util.function.Predicate; |
|
34 | 35 |
import org.apache.commons.io.IOUtils; |
35 | 36 |
import org.apache.commons.lang3.ArrayUtils; |
36 | 37 |
import org.apache.commons.lang3.StringUtils; |
37 | 38 |
import org.apache.commons.lang3.mutable.MutableBoolean; |
38 | 39 |
import org.gvsig.expressionevaluator.Code; |
40 |
import org.gvsig.expressionevaluator.Expression; |
|
39 | 41 |
import org.gvsig.expressionevaluator.ExpressionBuilder; |
42 |
import static org.gvsig.expressionevaluator.ExpressionBuilder.FUNCTION_$$CONSTANT; |
|
43 |
import static org.gvsig.expressionevaluator.ExpressionBuilder.FUNCTION_$$IDENTIFIER; |
|
40 | 44 |
import org.gvsig.expressionevaluator.ExpressionEvaluatorLocator; |
41 | 45 |
import org.gvsig.expressionevaluator.ExpressionEvaluatorManager; |
42 | 46 |
import org.gvsig.expressionevaluator.Function; |
... | ... | |
48 | 52 |
import org.gvsig.fmap.dal.SQLBuilder; |
49 | 53 |
import org.gvsig.fmap.dal.exception.DataException; |
50 | 54 |
import org.gvsig.fmap.dal.exception.InitializeException; |
55 |
import org.gvsig.fmap.dal.expressionevaluator.FeatureAttributeEmulatorExpression; |
|
51 | 56 |
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor; |
57 |
import org.gvsig.fmap.dal.feature.FeatureAttributeEmulator; |
|
52 | 58 |
import org.gvsig.fmap.dal.feature.FeatureQueryOrder; |
53 | 59 |
import org.gvsig.fmap.dal.feature.FeatureType; |
54 | 60 |
import org.gvsig.fmap.dal.feature.ForeingKey; |
... | ... | |
85 | 91 |
import org.gvsig.tools.evaluator.Evaluator; |
86 | 92 |
import org.gvsig.tools.exception.BaseException; |
87 | 93 |
import org.gvsig.tools.exception.NotYetImplemented; |
94 |
import org.gvsig.tools.visitor.FilteredVisitable; |
|
88 | 95 |
import org.gvsig.tools.visitor.VisitCanceledException; |
89 | 96 |
import org.gvsig.tools.visitor.Visitor; |
90 | 97 |
import org.slf4j.Logger; |
... | ... | |
237 | 244 |
} |
238 | 245 |
|
239 | 246 |
@Override |
247 |
@SuppressWarnings("Convert2Lambda") |
|
240 | 248 |
public boolean supportFilter(final FeatureType type, Evaluator filter) { |
241 | 249 |
if (filter == null) { |
242 | 250 |
// No hay que filtrar nada, asi que se p?ede. |
243 | 251 |
return true; |
244 | 252 |
} |
245 | 253 |
String sql = filter.getSQL(); |
246 |
return this.supportExpression(type, sql); |
|
247 |
} |
|
248 |
|
|
249 |
@Override |
|
250 |
public boolean supportExpression(final FeatureType type, String sql) { |
|
251 |
// No podemos filtrar cuando: |
|
252 |
// - Hay una subquery especificada en los parametros |
|
253 |
// - Si hay un filtro y el getSQL devuelbe null. |
|
254 |
// - Si se esta usando alguna funcion no-sql en el getSQL |
|
255 |
// - Si se estan usando funciones OGC y no soportamos funciones espaciales |
|
256 |
// - Si se esta usando algun campo calculado en la expresion de filtro. |
|
257 |
// |
|
258 |
// Un proveedor especifico podria sobreescribir el metodo, |
|
259 |
// para hilar mas fino al comprobar si soporta el filtro o no. |
|
260 |
// |
|
261 |
|
|
262 |
if (this.useSubquery()) { |
|
263 |
// Se esta usando una subquery en los parametros de acceso a la |
|
264 |
// BBDD, asi que no podemos filtrar. |
|
265 |
return false; |
|
266 |
} |
|
267 | 254 |
if (StringUtils.isEmpty(sql)) { |
268 | 255 |
// Hay un filtro, pero la SQL es null, con lo que no podemos |
269 | 256 |
// filtrar por el. |
270 | 257 |
return false; |
271 | 258 |
} |
259 |
return this.supportExpression(type, sql); |
|
260 |
} |
|
261 |
|
|
262 |
@Override |
|
263 |
@SuppressWarnings("Convert2Lambda") |
|
264 |
public boolean supportExpression(final FeatureType type, String sql) { |
|
265 |
// La expression no es valida si: |
|
266 |
// - Hay una subquery especificada en los parametros |
|
267 |
// - Si la sql es null. |
|
268 |
// - Si se esta usando alguna funcion no-sql en el getSQL |
|
269 |
// - Si se esta invocando a metodos de un objeto |
|
270 |
// - Si se estan usando funciones OGC y no soportamos funciones espaciales |
|
271 |
// - Si se esta usando algun campo calculado en la expresion de filtro. |
|
272 |
// |
|
273 |
// Un proveedor especifico podria sobreescribir el metodo, |
|
274 |
// para hilar mas fino al comprobar si soporta el filtro o no. |
|
275 |
// |
|
272 | 276 |
|
273 |
// Ahora vamos a comprobar que las funciones que se usan son |
|
274 |
// compatibles sql, y que no se usan funciones OGC si el |
|
275 |
// proveedor dice que no soporta funciones espaciales. |
|
276 |
// Tambien comprobaremos que el filtro no usa ningun campo calculado. |
|
277 |
final MutableBoolean isCompatible = new MutableBoolean(true); |
|
278 |
ExpressionEvaluatorManager manager = ExpressionEvaluatorLocator.getManager(); |
|
279 |
Code code = manager.compile(sql); |
|
280 |
SymbolTable symbolTable = manager.createSymbolTable(); |
|
281 |
code.link(symbolTable); |
|
282 |
try { |
|
283 |
code.accept(new Visitor() { |
|
284 |
@Override |
|
285 |
public void visit(Object code_obj) throws VisitCanceledException, BaseException { |
|
286 |
Code code = (Code) code_obj; |
|
287 |
switch (code.code()) { |
|
288 |
case Code.CALLABLE: |
|
289 |
Code.Callable caller = (Code.Callable) code; |
|
290 |
if (!supportCaller(caller)) { |
|
291 |
isCompatible.setValue(false); |
|
292 |
throw new VisitCanceledException(); |
|
293 |
} |
|
294 |
break; |
|
277 |
if (StringUtils.isEmpty(sql)) { |
|
278 |
return false; |
|
279 |
} |
|
295 | 280 |
|
296 |
case Code.IDENTIFIER: |
|
297 |
Code.Identifier identifier = (Code.Identifier) code; |
|
298 |
if (type != null) { |
|
299 |
FeatureAttributeDescriptor attrdesc = type.getAttributeDescriptor(identifier.name()); |
|
300 |
if (attrdesc != null) { |
|
301 |
if (attrdesc.isComputed()) { |
|
302 |
isCompatible.setValue(false); |
|
303 |
throw new VisitCanceledException(); |
|
304 |
} |
|
281 |
if (this.useSubquery()) { |
|
282 |
// Se esta usando una subquery en los parametros de acceso a la |
|
283 |
// BBDD, asi que no podemos filtrar. |
|
284 |
return false; |
|
285 |
} |
|
286 |
|
|
287 |
// Ahora vamos a comprobar que las funciones que se usan son |
|
288 |
// compatibles sql, y que no se usan funciones OGC si el |
|
289 |
// proveedor dice que no soporta funciones espaciales. |
|
290 |
// Tambien comprobaremos que el filtro no usa ningun campo calculado. |
|
291 |
final MutableBoolean isCompatible = new MutableBoolean(true); |
|
292 |
ExpressionEvaluatorManager manager = ExpressionEvaluatorLocator.getManager(); |
|
293 |
Code code = manager.compile(sql); |
|
294 |
SymbolTable symbolTable = manager.createSymbolTable(); |
|
295 |
code.link(symbolTable); |
|
296 |
try { |
|
297 |
code.accept(new Visitor() { |
|
298 |
@Override |
|
299 |
public void visit(Object code_obj) throws VisitCanceledException, BaseException { |
|
300 |
Code code1 = (Code) code_obj; |
|
301 |
switch (code1.code()) { |
|
302 |
case Code.CALLABLE: |
|
303 |
Code.Callable caller = (Code.Callable) code1; |
|
304 |
if (!supportCaller(caller)) { |
|
305 |
isCompatible.setValue(false); |
|
306 |
throw new VisitCanceledException(); |
|
307 |
} |
|
308 |
break; |
|
309 |
case Code.METHOD: |
|
310 |
isCompatible.setValue(false); |
|
311 |
throw new VisitCanceledException(); |
|
312 |
case Code.IDENTIFIER: |
|
313 |
Code.Identifier identifier = (Code.Identifier) code1; |
|
314 |
if (type != null) { |
|
315 |
FeatureAttributeDescriptor attrdesc = type.getAttributeDescriptor(identifier.name()); |
|
316 |
if (attrdesc != null) { |
|
317 |
if (attrdesc.isComputed()) { |
|
318 |
FeatureAttributeEmulator emulator = attrdesc.getFeatureAttributeEmulator(); |
|
319 |
if (!(emulator instanceof FeatureAttributeEmulatorExpression)) { |
|
320 |
isCompatible.setValue(false); |
|
321 |
throw new VisitCanceledException(); |
|
322 |
} |
|
323 |
Expression expr = ((FeatureAttributeEmulatorExpression) emulator).getExpression(); |
|
324 |
if (!supportExpression(type, expr.getPhrase())) { |
|
325 |
isCompatible.setValue(false); |
|
326 |
throw new VisitCanceledException(); |
|
327 |
} |
|
328 |
} |
|
329 |
} |
|
330 |
} |
|
331 |
break; |
|
332 |
} |
|
305 | 333 |
} |
306 |
} |
|
307 |
break; |
|
308 |
} |
|
334 |
}, new Predicate<FilteredVisitable>() { |
|
335 |
@Override |
|
336 |
public boolean test(FilteredVisitable code0) { |
|
337 |
if (code0 instanceof Code.Callable) { |
|
338 |
String name = ((Code.Callable) code0).name(); |
|
339 |
return StringUtils.equalsIgnoreCase(name, FUNCTION_$$CONSTANT) |
|
340 |
|| StringUtils.equalsIgnoreCase(name, FUNCTION_$$IDENTIFIER); |
|
341 |
} |
|
342 |
return false; |
|
343 |
} |
|
344 |
}); |
|
345 |
|
|
346 |
} catch (VisitCanceledException ex) { |
|
347 |
// Do nothing |
|
348 |
} catch (Exception ex) { |
|
349 |
LOGGER.warn("Can't calculate if is SQL compatible.", ex); |
|
309 | 350 |
} |
310 |
}); |
|
311 | 351 |
|
312 |
} catch (VisitCanceledException ex) { |
|
313 |
// Do nothing |
|
314 |
} catch (Exception ex) { |
|
315 |
LOGGER.warn("Can't calculate if is SQL compatible.", ex); |
|
352 |
return isCompatible.booleanValue(); |
|
316 | 353 |
} |
317 | 354 |
|
318 |
return isCompatible.booleanValue(); |
|
319 |
} |
|
320 |
|
|
321 | 355 |
@Override |
322 | 356 |
public boolean supportOrder(FeatureType type, FeatureQueryOrder order) { |
323 | 357 |
if (this.useSubquery()) { |
... | ... | |
657 | 691 |
replaceExistsFunction(sqlbuilder, type, extra_column_names); |
658 | 692 |
} |
659 | 693 |
|
694 |
@SuppressWarnings("Convert2Lambda") |
|
660 | 695 |
private void replaceExistsFunction( |
661 | 696 |
SQLBuilder sqlbuilder, |
662 | 697 |
FeatureType type, |
... | ... | |
716 | 751 |
} |
717 | 752 |
} |
718 | 753 |
|
754 |
@SuppressWarnings("Convert2Lambda") |
|
719 | 755 |
protected void replaceForeingValueFunction( |
720 | 756 |
SQLBuilder sqlbuilder, |
721 | 757 |
FeatureType type, |
... | ... | |
815 | 851 |
// Para las columnas que puedan dar conflicto se prepara un reemplazo |
816 | 852 |
// de estas que tenga el nombre de tabla. |
817 | 853 |
for (ExpressionBuilder.Variable variable : sqlbuilder.variables()) { |
818 |
if (variable instanceof SQLBuilderBase.ColumnBase) { |
|
854 |
if (variable == null || variable instanceof SQLBuilderBase.ColumnBase) {
|
|
819 | 855 |
continue; |
820 | 856 |
} |
821 | 857 |
for (String foreingName : foreing_value_args) { |
Also available in: Unified diff