added order by support
This commit is contained in:
@@ -1,9 +1,11 @@
|
|||||||
package jef;
|
package jef;
|
||||||
|
|
||||||
import jef.expressions.Expression;
|
import jef.expressions.Expression;
|
||||||
import jef.operations.CountOp;
|
import jef.expressions.OrderExpression;
|
||||||
import jef.operations.FilterOp;
|
import jef.operations.FilterOp;
|
||||||
import jef.operations.LimitOp;
|
import jef.operations.LimitOp;
|
||||||
|
import jef.operations.SortOp;
|
||||||
|
import jef.serializable.SerializableFunction;
|
||||||
import jef.serializable.SerializablePredicate;
|
import jef.serializable.SerializablePredicate;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
@@ -93,14 +95,19 @@ public interface Queryable<T extends Serializable> {
|
|||||||
// return null;
|
// return null;
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// default Queryable<T> sorted() {
|
// default SortOp<T> sorted() {//TODO sort by id
|
||||||
// return null;
|
// return new SortOp(this);
|
||||||
// }
|
// }
|
||||||
//
|
|
||||||
// default Queryable<T> sorted(Comparator<? super T> comparator) {
|
default <R> SortOp<T> sorted(SerializableFunction<? super T, R> fieldSelector) {
|
||||||
// return null;
|
return new SortOp<T>(this, fieldSelector, OrderExpression.SortDirection.ASCENDING);
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
|
default <R> SortOp<T> sortedDescending(SerializableFunction<? super T, R> fieldSelector) {
|
||||||
|
return new SortOp<T>(this, fieldSelector, OrderExpression.SortDirection.DESCENDING);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
// default Queryable<T> peek(Consumer<? super T> consumer) {
|
// default Queryable<T> peek(Consumer<? super T> consumer) {
|
||||||
// return null;
|
// return null;
|
||||||
// }
|
// }
|
||||||
|
|||||||
@@ -1,21 +1,27 @@
|
|||||||
package jef.asm;
|
package jef.asm;
|
||||||
|
|
||||||
import jef.expressions.Expression;
|
import jef.expressions.Expression;
|
||||||
|
import jef.serializable.SerializableFunction;
|
||||||
import jef.serializable.SerializablePredicate;
|
import jef.serializable.SerializablePredicate;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.objectweb.asm.ClassReader;
|
import org.objectweb.asm.ClassReader;
|
||||||
import org.objectweb.asm.Opcodes;
|
import org.objectweb.asm.Opcodes;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.io.Serializable;
|
||||||
import java.lang.invoke.SerializedLambda;
|
import java.lang.invoke.SerializedLambda;
|
||||||
import java.util.stream.IntStream;
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
public class PredicateParser {
|
public class AsmParser {
|
||||||
private final SerializablePredicate<?> predicate;
|
private final Serializable lambda;
|
||||||
|
|
||||||
public PredicateParser(SerializablePredicate<?> predicate) {
|
public AsmParser(SerializablePredicate<?> predicate) {
|
||||||
this.predicate = predicate;
|
this.lambda = predicate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AsmParser(SerializableFunction<?, ?> function) {
|
||||||
|
this.lambda = function;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Expression parse() throws AsmParseException {
|
public Expression parse() throws AsmParseException {
|
||||||
@@ -27,7 +33,7 @@ public class PredicateParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Expression parseExpression() throws Exception {
|
private Expression parseExpression() throws Exception {
|
||||||
var cls = predicate.getClass();
|
var cls = lambda.getClass();
|
||||||
var loader = cls.getClassLoader();
|
var loader = cls.getClassLoader();
|
||||||
InputStream is;
|
InputStream is;
|
||||||
// System.out.println(cls);
|
// System.out.println(cls);
|
||||||
@@ -42,7 +48,7 @@ public class PredicateParser {
|
|||||||
var x = cls.getDeclaredMethod("writeReplace");
|
var x = cls.getDeclaredMethod("writeReplace");
|
||||||
// System.out.println(x);
|
// System.out.println(x);
|
||||||
x.setAccessible(true);
|
x.setAccessible(true);
|
||||||
var serlambda = (SerializedLambda) x.invoke(predicate);
|
var serlambda = (SerializedLambda) x.invoke(lambda);
|
||||||
Object[] args = IntStream.range(0, serlambda.getCapturedArgCount()).mapToObj(serlambda::getCapturedArg).toArray();
|
Object[] args = IntStream.range(0, serlambda.getCapturedArgCount()).mapToObj(serlambda::getCapturedArg).toArray();
|
||||||
// System.out.println(serlambda);
|
// System.out.println(serlambda);
|
||||||
|
|
||||||
@@ -38,7 +38,7 @@ class FilterMethodVisitor extends MethodVisitor {
|
|||||||
private final String[] parameterClasses;
|
private final String[] parameterClasses;
|
||||||
private final Object[] args;
|
private final Object[] args;
|
||||||
private final Consumer<Expression> exprConsumer;
|
private final Consumer<Expression> exprConsumer;
|
||||||
private Expression prediacteExpr;
|
private Expression lambdaExpr;
|
||||||
|
|
||||||
protected FilterMethodVisitor(int api, String descriptor, Object[] args, Consumer<Expression> exprConsumer) {
|
protected FilterMethodVisitor(int api, String descriptor, Object[] args, Consumer<Expression> exprConsumer) {
|
||||||
super(api);
|
super(api);
|
||||||
@@ -153,7 +153,7 @@ class FilterMethodVisitor extends MethodVisitor {
|
|||||||
case Opcodes.ICONST_3 -> varStack.push(ConstantExpression.V3);
|
case Opcodes.ICONST_3 -> varStack.push(ConstantExpression.V3);
|
||||||
case Opcodes.ICONST_4 -> varStack.push(ConstantExpression.V4);
|
case Opcodes.ICONST_4 -> varStack.push(ConstantExpression.V4);
|
||||||
case Opcodes.ICONST_5 -> varStack.push(ConstantExpression.V5);
|
case Opcodes.ICONST_5 -> varStack.push(ConstantExpression.V5);
|
||||||
case Opcodes.IRETURN -> {
|
case Opcodes.IRETURN, Opcodes.LRETURN, Opcodes.FRETURN, Opcodes.DRETURN, Opcodes.ARETURN -> {
|
||||||
//collapse conditions
|
//collapse conditions
|
||||||
for (int i = condStack.size() - 1; i >= 0; i--) {
|
for (int i = condStack.size() - 1; i >= 0; i--) {
|
||||||
condStack.get(i).e1 = varStack.pop();
|
condStack.get(i).e1 = varStack.pop();
|
||||||
@@ -161,7 +161,7 @@ class FilterMethodVisitor extends MethodVisitor {
|
|||||||
evalCond(condStack.get(i));
|
evalCond(condStack.get(i));
|
||||||
}
|
}
|
||||||
// condStack.clear();
|
// condStack.clear();
|
||||||
prediacteExpr = varStack.pop();
|
lambdaExpr = varStack.pop();
|
||||||
}
|
}
|
||||||
case Opcodes.FCMPL, Opcodes.FCMPG, Opcodes.DCMPL, Opcodes.DCMPG, Opcodes.LCMP -> {
|
case Opcodes.FCMPL, Opcodes.FCMPG, Opcodes.DCMPL, Opcodes.DCMPG, Opcodes.LCMP -> {
|
||||||
var var2 = varStack.pop();
|
var var2 = varStack.pop();
|
||||||
@@ -386,7 +386,7 @@ class FilterMethodVisitor extends MethodVisitor {
|
|||||||
System.out.println("end");
|
System.out.println("end");
|
||||||
|
|
||||||
super.visitEnd();
|
super.visitEnd();
|
||||||
exprConsumer.accept(prediacteExpr);
|
exprConsumer.accept(lambdaExpr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -445,6 +445,10 @@ class FilterMethodVisitor extends MethodVisitor {
|
|||||||
169, "RET",
|
169, "RET",
|
||||||
|
|
||||||
172, "IRETURN",
|
172, "IRETURN",
|
||||||
|
173, "LRETURN",
|
||||||
|
174, "FRETURN",
|
||||||
|
175, "DRETURN",
|
||||||
|
176, "ARETURN",
|
||||||
|
|
||||||
//field
|
//field
|
||||||
180, "GETFIELD",
|
180, "GETFIELD",
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ public interface Expression {
|
|||||||
LIMIT,
|
LIMIT,
|
||||||
NULL,
|
NULL,
|
||||||
OR,
|
OR,
|
||||||
|
ORDER,
|
||||||
PARAMETER,
|
PARAMETER,
|
||||||
SELECT,
|
SELECT,
|
||||||
TABLE,
|
TABLE,
|
||||||
|
|||||||
53
src/main/java/jef/expressions/OrderExpression.java
Normal file
53
src/main/java/jef/expressions/OrderExpression.java
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
package jef.expressions;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class OrderExpression implements Expression {
|
||||||
|
private final Expression expr;
|
||||||
|
private final List<Sort> sorts;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type getType() {
|
||||||
|
return Type.ORDER;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Priority getPriority() {
|
||||||
|
return Priority.UNDEFINED;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
var ret = expr.toString();
|
||||||
|
if (!sorts.isEmpty()) {
|
||||||
|
var sortStrings = new ArrayList<String>(sorts.size());
|
||||||
|
for (Sort sort : sorts) {
|
||||||
|
sortStrings.add(sort.getExpr() + " " + sort.getDirection().getS());
|
||||||
|
}
|
||||||
|
ret += " ORDER BY " + String.join(", ", sortStrings);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
public static class Sort {
|
||||||
|
private final FieldExpression expr;
|
||||||
|
private final SortDirection direction;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
public enum SortDirection {
|
||||||
|
ASCENDING("ASC"),
|
||||||
|
DESCENDING("DESC"),
|
||||||
|
;
|
||||||
|
private final String s;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,6 +9,7 @@ import jef.expressions.IntermediateFieldExpression;
|
|||||||
import jef.expressions.LimitExpression;
|
import jef.expressions.LimitExpression;
|
||||||
import jef.expressions.NullExpression;
|
import jef.expressions.NullExpression;
|
||||||
import jef.expressions.OrExpression;
|
import jef.expressions.OrExpression;
|
||||||
|
import jef.expressions.OrderExpression;
|
||||||
import jef.expressions.ParameterExpression;
|
import jef.expressions.ParameterExpression;
|
||||||
import jef.expressions.SelectExpression;
|
import jef.expressions.SelectExpression;
|
||||||
import jef.expressions.TableExpression;
|
import jef.expressions.TableExpression;
|
||||||
@@ -31,6 +32,7 @@ public abstract class ExpressionModifier {
|
|||||||
case LIMIT -> modifyLimit((LimitExpression) expr);
|
case LIMIT -> modifyLimit((LimitExpression) expr);
|
||||||
case NULL -> modifyNull((NullExpression) expr);
|
case NULL -> modifyNull((NullExpression) expr);
|
||||||
case OR -> modifyOr((OrExpression) expr);
|
case OR -> modifyOr((OrExpression) expr);
|
||||||
|
case ORDER -> modifyOrder((OrderExpression) expr);
|
||||||
case PARAMETER -> modifyParameter((ParameterExpression) expr);
|
case PARAMETER -> modifyParameter((ParameterExpression) expr);
|
||||||
case SELECT -> modifySelect((SelectExpression) expr);
|
case SELECT -> modifySelect((SelectExpression) expr);
|
||||||
case TABLE -> modifyTable((TableExpression) expr);
|
case TABLE -> modifyTable((TableExpression) expr);
|
||||||
@@ -85,6 +87,10 @@ public abstract class ExpressionModifier {
|
|||||||
return expr;
|
return expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Expression modifyOrder(OrderExpression expr) {
|
||||||
|
return expr;
|
||||||
|
}
|
||||||
|
|
||||||
public Expression modifySelect(SelectExpression expr) {
|
public Expression modifySelect(SelectExpression expr) {
|
||||||
return new SelectExpression(expr.getFields(), modify(expr.getFrom()), expr.getFromAlias());
|
return new SelectExpression(expr.getFields(), modify(expr.getFrom()), expr.getFromAlias());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import jef.expressions.IntermediateFieldExpression;
|
|||||||
import jef.expressions.LimitExpression;
|
import jef.expressions.LimitExpression;
|
||||||
import jef.expressions.NullExpression;
|
import jef.expressions.NullExpression;
|
||||||
import jef.expressions.OrExpression;
|
import jef.expressions.OrExpression;
|
||||||
|
import jef.expressions.OrderExpression;
|
||||||
import jef.expressions.ParameterExpression;
|
import jef.expressions.ParameterExpression;
|
||||||
import jef.expressions.SelectExpression;
|
import jef.expressions.SelectExpression;
|
||||||
import jef.expressions.TableExpression;
|
import jef.expressions.TableExpression;
|
||||||
@@ -16,6 +17,7 @@ import jef.expressions.UnaryExpression;
|
|||||||
import jef.expressions.WhereExpression;
|
import jef.expressions.WhereExpression;
|
||||||
import jef.expressions.selectable.SelectableExpression;
|
import jef.expressions.selectable.SelectableExpression;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@@ -87,6 +89,18 @@ public class DebugExpressionVisitor extends ExpressionVisitor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitOrder(OrderExpression expr) {
|
||||||
|
visit(expr.getExpr());
|
||||||
|
if (!expr.getSorts().isEmpty()) {
|
||||||
|
var sortStrings = new ArrayList<String>(expr.getSorts().size());
|
||||||
|
for (OrderExpression.Sort sort : expr.getSorts()) {
|
||||||
|
sortStrings.add(sort.getExpr() + " " + sort.getDirection().getS());
|
||||||
|
}
|
||||||
|
System.out.println(i() + " ORDER BY " + String.join(", ", sortStrings));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitParameter(ParameterExpression expr) {
|
public void visitParameter(ParameterExpression expr) {
|
||||||
if (expr.getValue() instanceof Collection c) {
|
if (expr.getValue() instanceof Collection c) {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import jef.expressions.IntermediateFieldExpression;
|
|||||||
import jef.expressions.LimitExpression;
|
import jef.expressions.LimitExpression;
|
||||||
import jef.expressions.NullExpression;
|
import jef.expressions.NullExpression;
|
||||||
import jef.expressions.OrExpression;
|
import jef.expressions.OrExpression;
|
||||||
|
import jef.expressions.OrderExpression;
|
||||||
import jef.expressions.ParameterExpression;
|
import jef.expressions.ParameterExpression;
|
||||||
import jef.expressions.SelectExpression;
|
import jef.expressions.SelectExpression;
|
||||||
import jef.expressions.TableExpression;
|
import jef.expressions.TableExpression;
|
||||||
@@ -27,6 +28,7 @@ public abstract class ExpressionVisitor {
|
|||||||
case LIMIT -> visitLimit((LimitExpression) expr);
|
case LIMIT -> visitLimit((LimitExpression) expr);
|
||||||
case NULL -> visitNull((NullExpression) expr);
|
case NULL -> visitNull((NullExpression) expr);
|
||||||
case OR -> visitOr((OrExpression) expr);
|
case OR -> visitOr((OrExpression) expr);
|
||||||
|
case ORDER -> visitOrder((OrderExpression) expr);
|
||||||
case PARAMETER -> visitParameter((ParameterExpression) expr);
|
case PARAMETER -> visitParameter((ParameterExpression) expr);
|
||||||
case SELECT -> visitSelect((SelectExpression) expr);
|
case SELECT -> visitSelect((SelectExpression) expr);
|
||||||
case TABLE -> visitTable((TableExpression) expr);
|
case TABLE -> visitTable((TableExpression) expr);
|
||||||
@@ -70,6 +72,9 @@ public abstract class ExpressionVisitor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void visitOrder(OrderExpression expr) {
|
||||||
|
}
|
||||||
|
|
||||||
public void visitParameter(ParameterExpression expr) {
|
public void visitParameter(ParameterExpression expr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package jef.operations;
|
|||||||
|
|
||||||
import jef.Queryable;
|
import jef.Queryable;
|
||||||
import jef.asm.AsmParseException;
|
import jef.asm.AsmParseException;
|
||||||
import jef.asm.PredicateParser;
|
import jef.asm.AsmParser;
|
||||||
import jef.expressions.Expression;
|
import jef.expressions.Expression;
|
||||||
import jef.expressions.SelectExpression;
|
import jef.expressions.SelectExpression;
|
||||||
import jef.expressions.WhereExpression;
|
import jef.expressions.WhereExpression;
|
||||||
@@ -26,7 +26,7 @@ public class FilterOp<T extends Serializable> implements Queryable<T>, Operation
|
|||||||
public FilterOp(Queryable<T> queryable, SerializablePredicate<? super T> predicate) {
|
public FilterOp(Queryable<T> queryable, SerializablePredicate<? super T> predicate) {
|
||||||
this.queryable = queryable;
|
this.queryable = queryable;
|
||||||
this.predicate = predicate;
|
this.predicate = predicate;
|
||||||
var parser = new PredicateParser(predicate);
|
var parser = new AsmParser(predicate);
|
||||||
Expression expr;
|
Expression expr;
|
||||||
try {
|
try {
|
||||||
expr = parser.parse();
|
expr = parser.parse();
|
||||||
|
|||||||
82
src/main/java/jef/operations/SortOp.java
Normal file
82
src/main/java/jef/operations/SortOp.java
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
package jef.operations;
|
||||||
|
|
||||||
|
import jef.Queryable;
|
||||||
|
import jef.asm.AsmParseException;
|
||||||
|
import jef.asm.AsmParser;
|
||||||
|
import jef.expressions.Expression;
|
||||||
|
import jef.expressions.FieldExpression;
|
||||||
|
import jef.expressions.OrderExpression;
|
||||||
|
import jef.expressions.SelectExpression;
|
||||||
|
import jef.expressions.modifier.ExpressionOptimizerBottomUp;
|
||||||
|
import jef.expressions.modifier.IConst0Fixer;
|
||||||
|
import jef.expressions.modifier.TableAliasInjector;
|
||||||
|
import jef.expressions.modifier.TernaryRewriter;
|
||||||
|
import jef.expressions.selectable.DatabaseSelectAllExpression;
|
||||||
|
import jef.serializable.SerializableFunction;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class SortOp<T extends Serializable> implements Queryable<T> {
|
||||||
|
private final Queryable<T> queryable;
|
||||||
|
private final List<OrderExpression.Sort> sorts = new ArrayList<>();
|
||||||
|
|
||||||
|
public SortOp(Queryable<T> queryable, SerializableFunction<? super T, ?> fieldSelector, OrderExpression.SortDirection direction) {
|
||||||
|
this.queryable = queryable;
|
||||||
|
var f = parseFunction(fieldSelector);
|
||||||
|
this.sorts.add(new OrderExpression.Sort(f, direction));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getTableAlias() {
|
||||||
|
return String.valueOf((char) (queryable.getTableAlias().charAt(0) + (char) 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Expression getExpression() {
|
||||||
|
return new OrderExpression(new SelectExpression(List.of(new DatabaseSelectAllExpression()), queryable.getExpression(), getTableAlias()), sorts);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return getExpression().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public SortOp<T> thenSorted(SerializableFunction<? super T, ?> fieldSelector) {
|
||||||
|
var f = parseFunction(fieldSelector);
|
||||||
|
this.sorts.add(new OrderExpression.Sort(f, OrderExpression.SortDirection.ASCENDING));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SortOp<T> thenSortedDescending(SerializableFunction<? super T, ?> fieldSelector) {
|
||||||
|
var f = parseFunction(fieldSelector);
|
||||||
|
this.sorts.add(new OrderExpression.Sort(f, OrderExpression.SortDirection.DESCENDING));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private FieldExpression parseFunction(SerializableFunction<? super T, ?> fieldSelector) {
|
||||||
|
var parser = new AsmParser(fieldSelector);
|
||||||
|
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);
|
||||||
|
if (expr instanceof FieldExpression f) {
|
||||||
|
return f;
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException(expr + " is not a field");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
37
src/test/java/jef/operations/SortOpTest.java
Normal file
37
src/test/java/jef/operations/SortOpTest.java
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
package jef.operations;
|
||||||
|
|
||||||
|
import jef.DBSet;
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
class SortOpTest {
|
||||||
|
@Test
|
||||||
|
public void test() {
|
||||||
|
String act;
|
||||||
|
act = new DBSet<FilterOpTest.TestClass>("table1")
|
||||||
|
.sorted(e -> e.getI()).thenSorted(e -> e.getD()).thenSorted(e -> e.getF()).thenSorted(e -> e.getL()).thenSorted(e -> e.getO())
|
||||||
|
.toString();
|
||||||
|
Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a ORDER BY `a`.`i` ASC, `a`.`d` ASC, `a`.`f` ASC, `a`.`l` ASC, `a`.`o` ASC", act);
|
||||||
|
|
||||||
|
|
||||||
|
act = new DBSet<FilterOpTest.TestClass>("table1")
|
||||||
|
.sortedDescending(e -> e.getI()).thenSortedDescending(e -> e.getD()).thenSortedDescending(e -> e.getF())
|
||||||
|
/**/.thenSortedDescending(e -> e.getL()).thenSortedDescending(e -> e.getO())
|
||||||
|
.toString();
|
||||||
|
Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a ORDER BY `a`.`i` DESC, `a`.`d` DESC, `a`.`f` DESC, `a`.`l` DESC, `a`.`o` DESC", act);
|
||||||
|
|
||||||
|
//alternating patterns
|
||||||
|
act = new DBSet<FilterOpTest.TestClass>("table1")
|
||||||
|
.sortedDescending(e -> e.getI()).thenSorted(e -> e.getD()).thenSortedDescending(e -> e.getF()).thenSorted(e -> e.getL())
|
||||||
|
/**/.thenSortedDescending(e -> e.getO())
|
||||||
|
.toString();
|
||||||
|
Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a ORDER BY `a`.`i` DESC, `a`.`d` ASC, `a`.`f` DESC, `a`.`l` ASC, `a`.`o` DESC", act);
|
||||||
|
|
||||||
|
|
||||||
|
act = new DBSet<FilterOpTest.TestClass>("table1")
|
||||||
|
.sorted(e -> e.getI()).thenSortedDescending(e -> e.getD()).thenSorted(e -> e.getF()).thenSortedDescending(e -> e.getL())
|
||||||
|
/**/.thenSorted(e -> e.getO())
|
||||||
|
.toString();
|
||||||
|
Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a ORDER BY `a`.`i` ASC, `a`.`d` DESC, `a`.`f` ASC, `a`.`l` DESC, `a`.`o` ASC", act);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user