added null support to parsing

This commit is contained in:
wea_ondara
2022-07-11 22:03:40 +02:00
parent 8bb2265abd
commit a267d7034b
10 changed files with 83 additions and 14 deletions

View File

@@ -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) {

View File

@@ -33,6 +33,7 @@ public class BinaryExpression implements Expression {
// OR("OR"),
// AND("AND"),
IN("IN"),
IS("IS"),
;
private final String string;

View File

@@ -8,6 +8,7 @@ public interface Expression {
BINARY,
CONSTANT,
FIELD,
NULL,
OR,
PARAMETER,
SELECT,

View 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";
}
}

View File

@@ -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();
}

View File

@@ -16,7 +16,11 @@ public class UnaryExpression implements Expression {
@Override
public String toString() {
return operator + " (" + expr + ")";
if (expr instanceof ConstantExpression) {
return operator + " " + expr;
} else {
return operator + " (" + expr + ")";
}
}
@AllArgsConstructor

View File

@@ -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()) {

View File

@@ -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++) {

View File

@@ -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);

View File

@@ -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();
}
}