added getter support in precidates
This commit is contained in:
@@ -18,11 +18,14 @@ import org.objectweb.asm.MethodVisitor;
|
|||||||
import org.objectweb.asm.Opcodes;
|
import org.objectweb.asm.Opcodes;
|
||||||
import org.objectweb.asm.Type;
|
import org.objectweb.asm.Type;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.Stack;
|
import java.util.Stack;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
@@ -80,7 +83,7 @@ class FilterMethodVisitor extends MethodVisitor {
|
|||||||
@Override
|
@Override
|
||||||
public void visitMethodInsn(int opcode, String owner, String name, String descriptor, boolean isInterface) {
|
public void visitMethodInsn(int opcode, String owner, String name, String descriptor, boolean isInterface) {
|
||||||
System.out.println("method insn: " + ops.getOrDefault(opcode, "" + opcode) + ", " + owner + ", " + name + ", " + descriptor);
|
System.out.println("method insn: " + ops.getOrDefault(opcode, "" + opcode) + ", " + owner + ", " + name + ", " + descriptor);
|
||||||
if (opcode == Opcodes.INVOKESTATIC) {
|
if (opcode == Opcodes.INVOKESTATIC && name.equals("valueOf")) {
|
||||||
//ignore boxed primitive types
|
//ignore boxed primitive types
|
||||||
var boxedPrimitiveClasses = Set.of("java/lang/Boolean", "java/lang/Integer", "java/lang/Long", "java/lang/Float", "java/lang/Double");
|
var boxedPrimitiveClasses = Set.of("java/lang/Boolean", "java/lang/Integer", "java/lang/Long", "java/lang/Float", "java/lang/Double");
|
||||||
if (boxedPrimitiveClasses.contains(owner)) {
|
if (boxedPrimitiveClasses.contains(owner)) {
|
||||||
@@ -89,18 +92,34 @@ class FilterMethodVisitor extends MethodVisitor {
|
|||||||
//do something
|
//do something
|
||||||
throw new RuntimeException("method insn: unsupported opcode " + ops.getOrDefault(opcode, "" + opcode));
|
throw new RuntimeException("method insn: unsupported opcode " + ops.getOrDefault(opcode, "" + opcode));
|
||||||
}
|
}
|
||||||
} else if (opcode == Opcodes.INVOKEINTERFACE) {
|
} else if (opcode == Opcodes.INVOKEINTERFACE || opcode == Opcodes.INVOKEVIRTUAL) {
|
||||||
try {
|
try {
|
||||||
if (name.equals("contains")
|
if (name.equals("contains")
|
||||||
&& owner.startsWith("java/util/")
|
&& owner.startsWith("java/util/")
|
||||||
&& Collection.class.isAssignableFrom(Class.forName(owner.replace("/", ".")))) {
|
&& Collection.class.isAssignableFrom(Class.forName(owner.replace("/", ".")))) {
|
||||||
var element = varStack.pop();
|
var element = varStack.pop();
|
||||||
var collection = varStack.pop();
|
var collection = varStack.pop();
|
||||||
// System.out.println("element: " + element);
|
|
||||||
// System.out.println("collection: " + collection);
|
|
||||||
varStack.push(new BinaryExpression(element, collection, BinaryExpression.Operator.IN));
|
varStack.push(new BinaryExpression(element, collection, BinaryExpression.Operator.IN));
|
||||||
|
} else if (name.startsWith("get") && name.length() > 3 && descriptor.startsWith("()")) { //hacky getter support, TODO replace this with proper getter eval later
|
||||||
|
var field = findField(owner, name);
|
||||||
|
if (field.isPresent()) {
|
||||||
|
var v = varStack.pop();
|
||||||
|
if (v instanceof ParameterExpression p) {
|
||||||
|
if (p.isInput()) {
|
||||||
|
varStack.push(new FieldExpression(field.get().getName(), descriptor.substring(2)));
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("method insn: getter support only to predicate parameter");
|
||||||
}
|
}
|
||||||
} catch (ClassNotFoundException e) {
|
} else {
|
||||||
|
throw new RuntimeException("method insn: getter support expected ParameterExpression but found" + v.getClass().getSimpleName());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("method insn: could not find field for getter " + name + " in " + owner);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("method insn: unsupported function " + name + " in " + owner);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
throw new RuntimeException("method insn: ", e);
|
throw new RuntimeException("method insn: ", e);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -447,4 +466,19 @@ class FilterMethodVisitor extends MethodVisitor {
|
|||||||
System.out.println("-------------------> " + new WhereExpression(new SelectExpression(List.of("*"), new TableExpression("dummy"), ""), varStack.peek()));
|
System.out.println("-------------------> " + new WhereExpression(new SelectExpression(List.of("*"), new TableExpression("dummy"), ""), varStack.peek()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Optional<Field> findField(String owner, String name) throws Exception {
|
||||||
|
var cls = Class.forName(owner.replace("/", "."));
|
||||||
|
String fieldname = name.substring(3, 4).toLowerCase(Locale.ROOT) + name.substring(4);
|
||||||
|
var field = cls.getDeclaredField(fieldname);
|
||||||
|
if (field != null) {
|
||||||
|
return Optional.of(field);
|
||||||
|
}
|
||||||
|
for (Field declaredField : cls.getDeclaredFields()) {
|
||||||
|
if (declaredField.getName().equalsIgnoreCase(fieldname)) {
|
||||||
|
return Optional.of(declaredField);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package jef.operations;
|
package jef.operations;
|
||||||
|
|
||||||
import jef.DBSet;
|
import jef.DBSet;
|
||||||
|
import lombok.Getter;
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
@@ -207,10 +208,15 @@ public class FilterOpTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test() {
|
public void testMemberViaGetter() {
|
||||||
|
String act;
|
||||||
|
act = new DBSet<TestClass>("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 implements Serializable {
|
public static class TestClass implements Serializable {
|
||||||
public int i = 1;
|
public int i = 1;
|
||||||
public Object o = new Object();
|
public Object o = new Object();
|
||||||
|
|||||||
Reference in New Issue
Block a user