added null support to parsing
This commit is contained in:
@@ -4,6 +4,7 @@ import jef.expressions.BinaryExpression;
|
||||
import jef.expressions.ConstantExpression;
|
||||
import jef.expressions.Expression;
|
||||
import jef.expressions.FieldExpression;
|
||||
import jef.expressions.NullExpression;
|
||||
import jef.expressions.ParameterExpression;
|
||||
import jef.expressions.SelectExpression;
|
||||
import jef.expressions.TableExpression;
|
||||
@@ -198,6 +199,8 @@ class FilterMethodVisitor extends MethodVisitor {
|
||||
case Opcodes.IF_ICMPLE:
|
||||
case Opcodes.IF_ICMPGT:
|
||||
case Opcodes.IF_ICMPLT:
|
||||
case Opcodes.IFNULL:
|
||||
case Opcodes.IFNONNULL:
|
||||
handleLextLabel();
|
||||
condStack.add(new Cond(opcode, label, varStack));
|
||||
varStack = new Stack<>();
|
||||
@@ -311,19 +314,15 @@ class FilterMethodVisitor extends MethodVisitor {
|
||||
switch (cond.opcode) {
|
||||
case Opcodes.IFEQ:
|
||||
expr = right;
|
||||
// expr = new Expression.TernaryExpression(right, cond.e1, cond.e2);
|
||||
break;
|
||||
case Opcodes.IFNE:
|
||||
expr = right;
|
||||
|
||||
// expr = new Expression.TernaryExpression(right, cond.e1, cond.e2);
|
||||
// if (expr instanceof Expression.TernaryExpression texpr
|
||||
// && texpr.getWhenFalse() == Expression.ConstantExpression.I0) {
|
||||
// expr = new Expression.BinaryExpression(texpr.getCond(), texpr.getWhenTrue(), "AND");
|
||||
// }
|
||||
// wrapInTernary = false;
|
||||
|
||||
expr = new UnaryExpression(expr, UnaryExpression.Operator.NOT);
|
||||
expr = new UnaryExpression(right, UnaryExpression.Operator.NOT);
|
||||
break;
|
||||
case Opcodes.IFNULL:
|
||||
expr = new BinaryExpression(right, new UnaryExpression(NullExpression.INSTANCE, UnaryExpression.Operator.NOT), BinaryExpression.Operator.IS);
|
||||
break;
|
||||
case Opcodes.IFNONNULL:
|
||||
expr = new BinaryExpression(right, NullExpression.INSTANCE, BinaryExpression.Operator.IS);
|
||||
break;
|
||||
|
||||
default: {
|
||||
@@ -430,7 +429,9 @@ class FilterMethodVisitor extends MethodVisitor {
|
||||
183, "INVOKESPECIAL",
|
||||
184, "INVOKESTATIC",
|
||||
185, "INVOKEINTERFACE",
|
||||
186, "INVOKEDYNAMIC"
|
||||
186, "INVOKEDYNAMIC",
|
||||
198, "IFNULL",
|
||||
199, "IFNONNULL"
|
||||
);
|
||||
|
||||
private static Map<Integer, String> createOpsMap(Object... o) {
|
||||
|
||||
@@ -33,6 +33,7 @@ public class BinaryExpression implements Expression {
|
||||
// OR("OR"),
|
||||
// AND("AND"),
|
||||
IN("IN"),
|
||||
IS("IS"),
|
||||
;
|
||||
private final String string;
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ public interface Expression {
|
||||
BINARY,
|
||||
CONSTANT,
|
||||
FIELD,
|
||||
NULL,
|
||||
OR,
|
||||
PARAMETER,
|
||||
SELECT,
|
||||
|
||||
19
src/main/java/jef/expressions/NullExpression.java
Normal file
19
src/main/java/jef/expressions/NullExpression.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package jef.expressions;
|
||||
|
||||
public class NullExpression extends ConstantExpression {
|
||||
public static final NullExpression INSTANCE = new NullExpression();
|
||||
|
||||
private NullExpression() {
|
||||
super(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType() {
|
||||
return Type.NULL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "NULL";
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package jef.expressions;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Getter
|
||||
@@ -28,7 +29,7 @@ public class ParameterExpression extends ConstantExpression implements Expressio
|
||||
} else if (this.value == null) {
|
||||
return "null";
|
||||
} else if (this.value instanceof Collection) {
|
||||
return "(" + ((Collection) this.value).stream().map(Object::toString).collect(Collectors.joining(",")) + ")";
|
||||
return "(" + ((Collection<?>) this.value).stream().map(Objects::toString).collect(Collectors.joining(",")) + ")";
|
||||
}
|
||||
return value.toString();
|
||||
}
|
||||
|
||||
@@ -16,8 +16,12 @@ public class UnaryExpression implements Expression {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (expr instanceof ConstantExpression) {
|
||||
return operator + " " + expr;
|
||||
} else {
|
||||
return operator + " (" + expr + ")";
|
||||
}
|
||||
}
|
||||
|
||||
@AllArgsConstructor
|
||||
public enum Operator {
|
||||
|
||||
@@ -5,6 +5,7 @@ import jef.expressions.BinaryExpression;
|
||||
import jef.expressions.ConstantExpression;
|
||||
import jef.expressions.Expression;
|
||||
import jef.expressions.FieldExpression;
|
||||
import jef.expressions.NullExpression;
|
||||
import jef.expressions.OrExpression;
|
||||
import jef.expressions.ParameterExpression;
|
||||
import jef.expressions.SelectExpression;
|
||||
@@ -24,6 +25,7 @@ public abstract class ExpressionModifier {
|
||||
case BINARY -> modifyBinary((BinaryExpression) expr);
|
||||
case CONSTANT -> modifyConstant((ConstantExpression) expr);
|
||||
case FIELD -> modifyField((FieldExpression) expr);
|
||||
case NULL -> modifyNull((NullExpression) expr);
|
||||
case OR -> modifyOr((OrExpression) expr);
|
||||
case PARAMETER -> modifyParameter((ParameterExpression) expr);
|
||||
case SELECT -> modifySelect((SelectExpression) expr);
|
||||
@@ -55,6 +57,10 @@ public abstract class ExpressionModifier {
|
||||
return expr;
|
||||
}
|
||||
|
||||
public Expression modifyNull(NullExpression expr) {
|
||||
return expr;
|
||||
}
|
||||
|
||||
public Expression modifyOr(OrExpression expr) {
|
||||
var exprs = new ArrayList<Expression>(expr.getExprs().size());
|
||||
for (Expression e : expr.getExprs()) {
|
||||
|
||||
@@ -4,6 +4,7 @@ import jef.expressions.AndExpression;
|
||||
import jef.expressions.BinaryExpression;
|
||||
import jef.expressions.ConstantExpression;
|
||||
import jef.expressions.FieldExpression;
|
||||
import jef.expressions.NullExpression;
|
||||
import jef.expressions.OrExpression;
|
||||
import jef.expressions.ParameterExpression;
|
||||
import jef.expressions.SelectExpression;
|
||||
@@ -50,6 +51,11 @@ public class DebugExpressionVisitor extends ExpressionVisitor {
|
||||
System.out.println(i() + expr.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitNull(NullExpression expr) {
|
||||
System.out.println(i() + expr.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitOr(OrExpression expr) {
|
||||
for (int i = 0; i < expr.getExprs().size(); i++) {
|
||||
|
||||
@@ -5,6 +5,7 @@ import jef.expressions.BinaryExpression;
|
||||
import jef.expressions.ConstantExpression;
|
||||
import jef.expressions.Expression;
|
||||
import jef.expressions.FieldExpression;
|
||||
import jef.expressions.NullExpression;
|
||||
import jef.expressions.OrExpression;
|
||||
import jef.expressions.ParameterExpression;
|
||||
import jef.expressions.SelectExpression;
|
||||
@@ -20,6 +21,7 @@ public abstract class ExpressionVisitor {
|
||||
case BINARY -> visitBinary((BinaryExpression) expr);
|
||||
case CONSTANT -> visitConstant((ConstantExpression) expr);
|
||||
case FIELD -> visitField((FieldExpression) expr);
|
||||
case NULL -> visitNull((NullExpression) expr);
|
||||
case OR -> visitOr((OrExpression) expr);
|
||||
case PARAMETER -> visitParameter((ParameterExpression) expr);
|
||||
case SELECT -> visitSelect((SelectExpression) expr);
|
||||
@@ -48,6 +50,9 @@ public abstract class ExpressionVisitor {
|
||||
public void visitField(FieldExpression expr) {
|
||||
}
|
||||
|
||||
public void visitNull(NullExpression expr) {
|
||||
}
|
||||
|
||||
public void visitOr(OrExpression expr) {
|
||||
for (Expression e : expr.getExprs()) {
|
||||
visit(e);
|
||||
|
||||
@@ -5,6 +5,7 @@ import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class FilterOpTest {
|
||||
@@ -111,6 +112,7 @@ public class FilterOpTest {
|
||||
.toString();
|
||||
Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE a.b = 1337 OR a.b = 420 OR a.b IN (1,3)", act);
|
||||
|
||||
|
||||
act = new DBSet<TestClass>("table1")
|
||||
.filter(e -> e.b == 1337 || s.contains(e.b) || e.b == 420)
|
||||
.toString();
|
||||
@@ -133,6 +135,28 @@ public class FilterOpTest {
|
||||
Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE (a.b = 1337 OR a.b = 420) AND a.b IN (1,3)", act);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testObject() {
|
||||
String act;
|
||||
var s = Arrays.asList(null, new Object());
|
||||
act = new DBSet<TestClass>("table1")
|
||||
.filter(e -> e.o == null)
|
||||
.toString();
|
||||
Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE a.o IS NULL", act);
|
||||
|
||||
|
||||
act = new DBSet<TestClass>("table1")
|
||||
.filter(e -> e.o != null)
|
||||
.toString();
|
||||
Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE a.o IS NOT NULL", act);
|
||||
|
||||
|
||||
act = new DBSet<TestClass>("table1")
|
||||
.filter(e -> e.o != null || s.contains(e.o))
|
||||
.toString();
|
||||
Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE a.o IS NOT NULL OR a.o IN (NULL)", act);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
|
||||
@@ -140,5 +164,6 @@ public class FilterOpTest {
|
||||
|
||||
public static class TestClass implements Serializable {
|
||||
public int b = 1;
|
||||
public Object o = new Object();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user