Closed IslandOfCode closed 6 years ago
Il problema sembra essere causato da un errore nel meccanismo di gestione delle condizioni multiple.
Il metodo visitClauseFilter
si occupa di eseguire la clausola filter, usando un doppio ciclo for:
Questo secondo ciclio è qui di seguito evidenziato
for(int e=0;e<ctx.expr().size();e++) {
VTLObj ret = this.visit(ctx.expr(e));
if(ret==null)
continue;
if(ret instanceof Scalar) { //se uno scalare
Scalar s = (Scalar)ret;
if(s.getScalarType().equals(Scalar.SCALARTYPE.Boolean)) {
if(s.asBoolean()) {// true
nds.setPoint(dp);
}
continue;
}
}
throw new IllegalArgumentException("FILTER need a boolean result for the expression.");
}
Si noti l'if più interno:
if(s.asBoolean()) {// true
nds.setPoint(dp);
}
Palesemente non va bene, perchè così basta che la prima condizione sia vera per creare un'ambiguità nel resto del codice.
Si conseguenza si va a semplificare il codice, andando a cercare una condizione che ritorni false. In quel caso il Datapoint viene scartato. Se invece tutte le condizioni ritornano true, allora si aggiunge il Datapoint al DataSet risultate.
La correzzione in un seguente commento.
Allora, prima di tutto creiamo una variabile booleano condition settata a true di default. Poi si passa a valutare condizione per condizione. Se una di esse è false (o per qualche motivo a ritornato un null), allora si spezza il ciclo.
if(ret instanceof Scalar) { //se uno scalare
Scalar s = (Scalar)ret;
if(s.getScalarType().equals(Scalar.SCALARTYPE.Boolean)) { //se un booleano
if(!s.asBoolean()) {// false
condition = false;
break;
}
//vado alla condizione successiva
continue;
}
}
Subito dopo il ciclo for, un semplice if controlla se condition è uguale a true, nel qual caso inserisce il Datapoint nel Dataset. In caso contrario, passa al successivo DataPoint.
if(condition) {
nds.setPoint(dp);
}
Adesso la clausola filter può gestire tutte le condizioni che si vuole, basta ricordarsi che esse vanno considerate tutte in AND tra di loro!
Questa clausola ha un comportamento anomalo quando gli si viene specificata più di una condizione da verificare.
Ipotiziamo di avere un DataSet con due colonne: A (Integer) e B (Stringa). Se applichiamo una condizione singola, come:
filter(A>0)
oppurefilter(B<>null)
non ci sono problemi.Se invece applico due condizioni:
filter(A>0, B<>null)
ritorna quasi tutte le righe.Dico quasi perchè sembra che alcune vengano comunque scartate.