From 23e046ef7ea630ed3e53549823d0f1dde49ceb4e Mon Sep 17 00:00:00 2001 From: wea_ondara Date: Wed, 27 Jul 2022 15:27:59 +0200 Subject: [PATCH] move asm related tests from FilterOpTest to OptimizedAsmParser testcase --- src/main/java/jef/asm/OptimizedAsmParser.java | 42 ++++ .../IntermediateFieldExpression.java | 2 +- src/main/java/jef/operations/FilterOp.java | 11 +- .../java/jef/asm/OptimizedAsmParserTest.java | 170 ++++++++++++++++ .../java/jef/operations/FilterOpTest.java | 189 +----------------- 5 files changed, 217 insertions(+), 197 deletions(-) create mode 100644 src/main/java/jef/asm/OptimizedAsmParser.java create mode 100644 src/test/java/jef/asm/OptimizedAsmParserTest.java diff --git a/src/main/java/jef/asm/OptimizedAsmParser.java b/src/main/java/jef/asm/OptimizedAsmParser.java new file mode 100644 index 0000000..78c21c8 --- /dev/null +++ b/src/main/java/jef/asm/OptimizedAsmParser.java @@ -0,0 +1,42 @@ +package jef.asm; + +import jef.expressions.Expression; +import jef.expressions.modifier.ExpressionOptimizerBottomUp; +import jef.expressions.modifier.IConst0Fixer; +import jef.expressions.modifier.TableAliasInjector; +import jef.expressions.modifier.TernaryRewriter; +import jef.serializable.SerializableFunction; +import jef.serializable.SerializablePredicate; +import lombok.Getter; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.Opcodes; + +import java.io.InputStream; +import java.io.Serializable; +import java.lang.invoke.SerializedLambda; +import java.util.stream.IntStream; + +@Getter +public class OptimizedAsmParser extends AsmParser{ + + public OptimizedAsmParser(SerializablePredicate predicate) { + super(predicate); + } + + public OptimizedAsmParser(SerializableFunction function) { + super(function); + } + + public Expression parse() throws AsmParseException { + var expr = super.parse(); + + System.out.println(expr); + expr = new TernaryRewriter().modify(expr); + System.out.println(expr); + expr = new IConst0Fixer().modify(expr); + System.out.println(expr); + expr = new ExpressionOptimizerBottomUp().modify(expr); + + return expr; + } +} diff --git a/src/main/java/jef/expressions/IntermediateFieldExpression.java b/src/main/java/jef/expressions/IntermediateFieldExpression.java index 09c35ac..34c5733 100644 --- a/src/main/java/jef/expressions/IntermediateFieldExpression.java +++ b/src/main/java/jef/expressions/IntermediateFieldExpression.java @@ -23,6 +23,6 @@ public class IntermediateFieldExpression extends ConstantExpression implements S @Override public String toString() { - return name; + return "`" + name + "`"; } } diff --git a/src/main/java/jef/operations/FilterOp.java b/src/main/java/jef/operations/FilterOp.java index d8b30b9..e7c61ab 100644 --- a/src/main/java/jef/operations/FilterOp.java +++ b/src/main/java/jef/operations/FilterOp.java @@ -3,6 +3,7 @@ package jef.operations; import jef.Queryable; import jef.asm.AsmParseException; import jef.asm.AsmParser; +import jef.asm.OptimizedAsmParser; import jef.expressions.Expression; import jef.expressions.SelectExpression; import jef.expressions.WhereExpression; @@ -27,20 +28,14 @@ public class FilterOp implements Queryable, Operation public FilterOp(Queryable queryable, SerializablePredicate predicate) { this.queryable = queryable; this.predicate = predicate; - var parser = new AsmParser(predicate); + var parser = new OptimizedAsmParser(predicate); Expression expr; try { expr = parser.parse(); } catch (AsmParseException e) { throw new RuntimeException(e); } - System.out.println(expr); - expr = new TernaryRewriter().modify(expr); - System.out.println(expr); - expr = new IConst0Fixer().modify(expr); - System.out.println(expr); -// expr = new ExpressionOptimizer().modify(expr); - expr = new ExpressionOptimizerBottomUp().modify(expr); + expr = new TableAliasInjector(getTableAlias()).modify(expr);//TODO this does not work together with expression optimization this.predicateExpr = expr; //TODO optimize whole expression diff --git a/src/test/java/jef/asm/OptimizedAsmParserTest.java b/src/test/java/jef/asm/OptimizedAsmParserTest.java new file mode 100644 index 0000000..8b513d6 --- /dev/null +++ b/src/test/java/jef/asm/OptimizedAsmParserTest.java @@ -0,0 +1,170 @@ +package jef.asm; + +import jef.serializable.SerializableObject; +import jef.serializable.SerializablePredicate; +import lombok.Getter; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import java.util.List; + +public class OptimizedAsmParserTest { + + @Test + public void testTrue() throws AsmParseException { + String act; + + act = new OptimizedAsmParser((SerializablePredicate) (TestClass e) -> true).parse().toString(); + Assertions.assertEquals("1", act); + } + + @Test + public void testCompareWithEntityMember() throws AsmParseException { + String act; + act = new OptimizedAsmParser((SerializablePredicate) (TestClass e) -> e.i == 1).parse().toString(); + Assertions.assertEquals("`i` = 1", act); + + + act = new OptimizedAsmParser((SerializablePredicate) (TestClass e) -> e.i != 1).parse().toString(); + Assertions.assertEquals("`i` <> 1", act); + + + act = new OptimizedAsmParser((SerializablePredicate) (TestClass e) -> e.i < 1).parse().toString(); + Assertions.assertEquals("`i` < 1", act); + + + act = new OptimizedAsmParser((SerializablePredicate) (TestClass e) -> e.i > 1).parse().toString(); + Assertions.assertEquals("`i` > 1", act); + + + act = new OptimizedAsmParser((SerializablePredicate) (TestClass e) -> e.i <= 1).parse().toString(); + Assertions.assertEquals("`i` <= 1", act); + + + act = new OptimizedAsmParser((SerializablePredicate) (TestClass e) -> e.i >= 1).parse().toString(); + Assertions.assertEquals("`i` >= 1", act); + + + act = new OptimizedAsmParser((SerializablePredicate) (TestClass e) -> e.i == 1337).parse().toString(); + Assertions.assertEquals("`i` = 1337", act); + } + + @Test + public void testContainsWithEntityMember() throws AsmParseException { + var s = List.of(1, 3); + String act; + act = new OptimizedAsmParser((SerializablePredicate) (TestClass e) -> s.contains(e.i)).parse().toString(); + Assertions.assertEquals("`i` IN (1, 3)", act); + + + //TODO +// act = new OptimizedAsmParser((SerializablePredicate) (TestClass e) -> List.of(1, 3).contains(e.i)).parse().toString(); +// Assertions.assertEquals("`i` IN (1, 3)", act); + } + + @Test + public void testComplexExpression() throws AsmParseException { + String act; + var s = List.of(1, 3); + act = new OptimizedAsmParser((SerializablePredicate) (TestClass e) -> s.contains(e.i) && e.i == 1337).parse().toString(); + Assertions.assertEquals("`i` IN (1, 3) AND `i` = 1337", act); + + + act = new OptimizedAsmParser((SerializablePredicate) (TestClass e) -> s.contains(e.i) && e.i == 1337 && e.i == 420).parse().toString(); + Assertions.assertEquals("`i` IN (1, 3) AND `i` = 1337 AND `i` = 420", act); + + + act = new OptimizedAsmParser((SerializablePredicate) (TestClass e) -> e.i == 1337 || e.i != 420 || s.contains(e.i)).parse().toString(); + Assertions.assertEquals("`i` = 1337 OR `i` <> 420 OR `i` IN (1, 3)", act); + + + act = new OptimizedAsmParser((SerializablePredicate) (TestClass e) -> e.i == 1337 || e.i == 420 || s.contains(e.i)).parse().toString(); + Assertions.assertEquals("`i` = 1337 OR `i` = 420 OR `i` IN (1, 3)", act); + + + act = new OptimizedAsmParser((SerializablePredicate) (TestClass e) -> e.i == 1337 || s.contains(e.i) || e.i == 420).parse().toString(); + Assertions.assertEquals("`i` = 1337 OR `i` IN (1, 3) OR `i` = 420", act); + } + + @Test + public void testComplexExpressionMixedAndOr() throws AsmParseException { + String act; + var s = List.of(1, 3); + act = new OptimizedAsmParser((SerializablePredicate) (TestClass e) -> s.contains(e.i) && (e.i == 1337 || e.i == 420)).parse().toString(); + Assertions.assertEquals("`i` IN (1, 3) AND (`i` = 1337 OR `i` = 420)", act); + + +// act = new OptimizedAsmParser((SerializablePredicate)(TestClass e) -> (e.i == 1337 || e.i == 420) && s.contains(e.i)).toString(); +// Assertions.assertEquals("(`i` = 1337 OR `i` = 420) AND `i` IN (1, 3)", act); +// //actually produced, it's not wrong but the expression is weird +// Assertions.assertEquals("`i` <> 1337 AND `i` = 420 AND `i` IN (1, 3) OR `i` = 1337 AND `i` IN (1, 3)", act); + } + + @Test + public void testObject() throws AsmParseException { + String act; + var s = Arrays.asList(null, 4); + act = new OptimizedAsmParser((SerializablePredicate) (TestClass e) -> e.o == null).parse().toString(); + Assertions.assertEquals("`o` IS NULL", act); + + + act = new OptimizedAsmParser((SerializablePredicate) (TestClass e) -> e.o != null).parse().toString(); + Assertions.assertEquals("`o` IS NOT NULL", act); + + + act = new OptimizedAsmParser((SerializablePredicate) (TestClass e) -> e.o != null || s.contains(e.o)).parse().toString(); + Assertions.assertEquals("`o` IS NOT NULL OR `o` IN (NULL, 4)", act); + } + + @Test + public void testFloatingPoint() throws AsmParseException { + String act; + var s = Arrays.asList(null, 2); + act = new OptimizedAsmParser((SerializablePredicate) (TestClass e) -> e.d == 3.14d).parse().toString(); + Assertions.assertEquals("`d` = 3.14", act); + + + act = new OptimizedAsmParser((SerializablePredicate) (TestClass e) -> e.f == 3.14f).parse().toString(); + Assertions.assertEquals("`f` = 3.14", act); + + + act = new OptimizedAsmParser((SerializablePredicate) (TestClass e) -> e.d != 1d || e.f != 1 || s.contains(e.d)).parse().toString(); + Assertions.assertEquals("`d` <> 1 OR `f` <> 1 OR `d` IN (NULL, 2)", act); + } + + @Test + public void testIDFLConst() throws AsmParseException { + String act; + act = new OptimizedAsmParser((SerializablePredicate) (TestClass e) -> e.i == 0 || e.i == 1 || e.i == 2 || e.i == 3 || e.i == 4 || e.i == 5).parse().toString(); + Assertions.assertEquals("`i` = 0 OR `i` = 1 OR `i` = 2 OR `i` = 3 OR `i` = 4 OR `i` = 5", act); + + + act = new OptimizedAsmParser((SerializablePredicate) (TestClass e) -> e.d == 0D || e.d == 1D).parse().toString(); + Assertions.assertEquals("`d` = 0 OR `d` = 1", act); + + + act = new OptimizedAsmParser((SerializablePredicate) (TestClass e) -> e.f == 0F || e.f == 1F || e.f == 2F).parse().toString(); + Assertions.assertEquals("`f` = 0 OR `f` = 1 OR `f` = 2", act); + + + act = new OptimizedAsmParser((SerializablePredicate) (TestClass e) -> e.l == 0L || e.l == 1L).parse().toString(); + Assertions.assertEquals("`l` = 0 OR `l` = 1", act); + } + + @Test + public void testMemberViaGetter() throws AsmParseException { + String act; + act = new OptimizedAsmParser((SerializablePredicate) (TestClass e) -> e.getI() == 1337).parse().toString(); + Assertions.assertEquals("`i` = 1337", act); + } + + @Getter + public static class TestClass extends SerializableObject { + public int i = 1; + public Object o = new Object(); + public double d; + public float f; + public long l; + } +} \ No newline at end of file diff --git a/src/test/java/jef/operations/FilterOpTest.java b/src/test/java/jef/operations/FilterOpTest.java index 5e540b6..0c849a4 100644 --- a/src/test/java/jef/operations/FilterOpTest.java +++ b/src/test/java/jef/operations/FilterOpTest.java @@ -12,7 +12,7 @@ import java.util.List; public class FilterOpTest { @Test - public void testTrue() { + public void testSimple() { String act; act = new DbSet<>(TestClass.class, "table1") .filter(e -> true) @@ -20,61 +20,6 @@ public class FilterOpTest { Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE 1", act); } - @Test - public void testCompareWithEntityMember() { - String act; - act = new DbSet<>(TestClass.class, "table1") - .filter(e -> e.i == 1) - .toString(); - Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE `a`.`i` = 1", act); - - - act = new DbSet<>(TestClass.class, "table1") - .filter(e -> e.i != 1) - .toString(); - Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE `a`.`i` <> 1", act); - - - act = new DbSet<>(TestClass.class, "table1") - .filter(e -> e.i < 1) - .toString(); - Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE `a`.`i` < 1", act); - - - act = new DbSet<>(TestClass.class, "table1") - .filter(e -> e.i > 1) - .toString(); - Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE `a`.`i` > 1", act); - - - act = new DbSet<>(TestClass.class, "table1") - .filter(e -> e.i <= 1) - .toString(); - Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE `a`.`i` <= 1", act); - - - act = new DbSet<>(TestClass.class, "table1") - .filter(e -> e.i >= 1) - .toString(); - Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE `a`.`i` >= 1", act); - - - act = new DbSet<>(TestClass.class, "table1") - .filter(e -> e.i == 1337) - .toString(); - Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE `a`.`i` = 1337", act); - } - - @Test - public void testContainsWithEntityMember() { - var s = List.of(1, 3); - String act; - act = new DbSet<>(TestClass.class, "table1") - .filter(e -> s.contains(e.i)) - .toString(); - Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE `a`.`i` IN (1, 3)", act); - } - @Test public void testMultipleFilter() { String act; @@ -86,138 +31,6 @@ public class FilterOpTest { Assertions.assertEquals("SELECT * FROM (SELECT * FROM (SELECT * FROM `table1`) a WHERE `a`.`i` IN (1, 3)) b WHERE `b`.`i` = 1337", act); } - @Test - public void testComplexExpression() { - String act; - var s = List.of(1, 3); - act = new DbSet<>(TestClass.class, "table1") - .filter(e -> s.contains(e.i) && e.i == 1337) - .toString(); - Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE `a`.`i` IN (1, 3) AND `a`.`i` = 1337", act); - - - act = new DbSet<>(TestClass.class, "table1") - .filter(e -> s.contains(e.i) && e.i == 1337 && e.i == 420) - .toString(); - Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE `a`.`i` IN (1, 3) AND `a`.`i` = 1337 AND `a`.`i` = 420", act); - - - act = new DbSet<>(TestClass.class, "table1") - .filter(e -> e.i == 1337 || e.i != 420 || s.contains(e.i)) - .toString(); - Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE `a`.`i` = 1337 OR `a`.`i` <> 420 OR `a`.`i` IN (1, 3)", act); - - - act = new DbSet<>(TestClass.class, "table1") - .filter(e -> e.i == 1337 || e.i == 420 || s.contains(e.i)) - .toString(); - Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE `a`.`i` = 1337 OR `a`.`i` = 420 OR `a`.`i` IN (1, 3)", act); - - - act = new DbSet<>(TestClass.class, "table1") - .filter(e -> e.i == 1337 || s.contains(e.i) || e.i == 420) - .toString(); - Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE `a`.`i` = 1337 OR `a`.`i` IN (1, 3) OR `a`.`i` = 420", act); - } - - @Test - public void testComplexExpressionMixedAndOr() { - String act; - var s = List.of(1, 3); - act = new DbSet<>(TestClass.class, "table1") - .filter(e -> s.contains(e.i) && (e.i == 1337 || e.i == 420)) - .toString(); - Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE `a`.`i` IN (1, 3) AND (`a`.`i` = 1337 OR `a`.`i` = 420)", act); - - -// act = new DbSet<>(TestClass.class, "table1") -// .filter(e -> (e.i == 1337 || e.i == 420) && s.contains(e.i)) -// .toString(); -// Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE (`a`.`i` = 1337 OR `a`.`i` = 420) AND `a`.`i` IN (1, 3)", act); -// //actually produced, it's not wrong but the expression is weird -// Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE `a`.`i` <> 1337 AND `a`.`i` = 420 AND `a`.`i` IN (1, 3) OR `a`.`i` = 1337 AND `a`.`i` IN (1, 3)", act); - } - - @Test - public void testObject() { - String act; - var s = Arrays.asList(null, 4); - act = new DbSet<>(TestClass.class, "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.class, "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.class, "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, 4)", act); - } - - @Test - public void testFloatingPoint() { - String act; - var s = Arrays.asList(null, 2); - act = new DbSet<>(TestClass.class, "table1") - .filter(e -> e.d == 3.14d) - .toString(); - Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE `a`.`d` = 3.14", act); - - - act = new DbSet<>(TestClass.class, "table1") - .filter(e -> e.f == 3.14f) - .toString(); - Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE `a`.`f` = 3.14", act); - - - act = new DbSet<>(TestClass.class, "table1") - .filter(e -> e.d != 1d || e.f != 1 || s.contains(e.d)) - .toString(); - Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE `a`.`d` <> 1 OR `a`.`f` <> 1 OR `a`.`d` IN (NULL, 2)", act); - } - - @Test - public void testIDFLConst() { - String act; - act = new DbSet<>(TestClass.class, "table1") - .filter(e -> e.i == 0 || e.i == 1 || e.i == 2 || e.i == 3 || e.i == 4 || e.i == 5) - .toString(); - Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE `a`.`i` = 0 OR `a`.`i` = 1 OR `a`.`i` = 2 OR `a`.`i` = 3 OR `a`.`i` = 4 OR `a`.`i` = 5", act); - - - act = new DbSet<>(TestClass.class, "table1") - .filter(e -> e.d == 0D || e.d == 1D) - .toString(); - Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE `a`.`d` = 0 OR `a`.`d` = 1", act); - - - act = new DbSet<>(TestClass.class, "table1") - .filter(e -> e.f == 0F || e.f == 1F || e.f == 2F) - .toString(); - Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE `a`.`f` = 0 OR `a`.`f` = 1 OR `a`.`f` = 2", act); - - - act = new DbSet<>(TestClass.class, "table1") - .filter(e -> e.l == 0L || e.l == 1L) - .toString(); - Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE `a`.`l` = 0 OR `a`.`l` = 1", act); - } - - @Test - public void testMemberViaGetter() { - String act; - act = new DbSet<>(TestClass.class, "table1") - .filter(e -> e.getI() == 1337) - .toString(); - Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE `a`.`i` = 1337", act); - } - @Getter public static class TestClass extends SerializableObject { public int i = 1;