diff --git a/core/src/main/java/jef/query/QueryBuilder.java b/core/src/main/java/jef/query/QueryBuilder.java index 88e4654..b62febe 100644 --- a/core/src/main/java/jef/query/QueryBuilder.java +++ b/core/src/main/java/jef/query/QueryBuilder.java @@ -47,7 +47,8 @@ public class QueryBuilder extends ExpressionVisitor { } public void visitField(FieldExpression expr) { - if (expr.getSchema() != null && !expr.getSchema().isBlank()) { + if (expr.getSchema() != null && !expr.getSchema().isBlank() + && expr.getTable() != null && !expr.getTable().isBlank()) { query += "`" + expr.getSchema() + "`."; } if (expr.getTable() != null && !expr.getTable().isBlank()) { @@ -92,7 +93,8 @@ public class QueryBuilder extends ExpressionVisitor { for (int i = 0; i < expr.getSorts().size(); i++) { query += " "; var sort = expr.getSorts().get(i); - if (sort.getExpr().getSchema() != null && !sort.getExpr().getSchema().isBlank()) { + if (sort.getExpr().getSchema() != null && !sort.getExpr().getSchema().isBlank() + && sort.getExpr().getTable() != null && !sort.getExpr().getTable().isBlank()) { query += "`" + sort.getExpr().getSchema() + "`."; } if (sort.getExpr().getTable() != null && !sort.getExpr().getTable().isBlank()) { @@ -135,7 +137,7 @@ public class QueryBuilder extends ExpressionVisitor { if (wrap) { query += ")"; } - if (expr.getFromAlias().length() > 0 && expr.getFromAlias().charAt(0) >= 'a') { + if (expr.getFromAlias().length() > 0 && expr.getFromAlias().charAt(0) >= 'a') {//TODO this is bad check query += " " + expr.getFromAlias(); } } diff --git a/core/src/test/java/jef/query/QueryBuilderTest.java b/core/src/test/java/jef/query/QueryBuilderTest.java index c642490..13e3eaa 100644 --- a/core/src/test/java/jef/query/QueryBuilderTest.java +++ b/core/src/test/java/jef/query/QueryBuilderTest.java @@ -1,96 +1,201 @@ package jef.query; -import jef.DbSet; +import jef.expressions.AndExpression; +import jef.expressions.BinaryExpression; +import jef.expressions.ConstantExpression; +import jef.expressions.FieldExpression; +import jef.expressions.IntermediateFieldExpression; +import jef.expressions.LimitExpression; +import jef.expressions.NullExpression; +import jef.expressions.OrExpression; +import jef.expressions.OrderExpression; +import jef.expressions.ParameterExpression; +import jef.expressions.SelectExpression; +import jef.expressions.TableExpression; +import jef.expressions.TernaryExpression; +import jef.expressions.UnaryExpression; +import jef.expressions.WhereExpression; import jef.serializable.SerializableObject; import lombok.Getter; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; +import java.util.Arrays; import java.util.List; class QueryBuilderTest { @Test - public void testAnd() { + void visitAnd() { var v = new QueryBuilder(); - v.visit(new DbSet<>(TestClass.class, "table1") - .filter(e -> e.i == 0 && e.i == 1) - .getExpression()); - Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE `a`.`i` = 0 AND `a`.`i` = 1", v.getQuery()); + v.visitAnd(new AndExpression(ConstantExpression.V0, ConstantExpression.V1)); + Assertions.assertEquals("0 AND 1", v.getQuery()); } @Test - public void testBinary() { + void visitBinary() { var v = new QueryBuilder(); - v.visit(new DbSet<>(TestClass.class, "table1") - .filter(e -> e.i == 0) - .getExpression()); - Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE `a`.`i` = 0", v.getQuery()); + v.visitBinary(new BinaryExpression(ConstantExpression.V0, ConstantExpression.V1, BinaryExpression.Operator.EQ)); + Assertions.assertEquals("0 = 1", v.getQuery()); } @Test - public void testConstant() { + void visitConstant() { var v = new QueryBuilder(); - v.visit(new DbSet<>(TestClass.class, "table1") - .filter(e -> true) - .getExpression()); - Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE 1", v.getQuery()); + v.visitConstant(ConstantExpression.V0); + Assertions.assertEquals("0", v.getQuery()); } @Test - public void testLimit() { + void visitField() { var v = new QueryBuilder(); - v.visit(new DbSet<>(TestClass.class, "table1") - .filter(e -> e.i == 0 && e.i == 1) - .skip(3).limit(5) - .getExpression()); - Assertions.assertEquals("SELECT * FROM (SELECT * FROM (SELECT * FROM `table1`) a WHERE `a`.`i` = 0 AND `a`.`i` = 1) b OFFSET 3 LIMIT 5", v.getQuery()); + v.visitField(new FieldExpression("schema", "table", "name", null)); + Assertions.assertEquals("`schema`.`table`.`name`", v.getQuery()); + + v = new QueryBuilder(); + v.visitField(new FieldExpression(null, "table", "name", null)); + Assertions.assertEquals("`table`.`name`", v.getQuery()); + + v = new QueryBuilder(); + v.visitField(new FieldExpression("schema", null, "name", null)); + Assertions.assertEquals("`name`", v.getQuery()); + + v = new QueryBuilder(); + v.visitField(new FieldExpression(null, null, "name", null)); + Assertions.assertEquals("`name`", v.getQuery()); } @Test - public void testNull() { + void visitIntermediateField() { var v = new QueryBuilder(); - v.visit(new DbSet<>(TestClass.class, "table1") - .filter(e -> e.o == null) - .getExpression()); - Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE `a`.`o` IS NULL", v.getQuery()); + v.visitIntermediateField(new IntermediateFieldExpression("value", null)); + Assertions.assertEquals("value", v.getQuery()); } @Test - public void testParameter() { - var s = List.of(1, 3); + void visitLimit() { var v = new QueryBuilder(); - v.visit(new DbSet<>(TestClass.class, "table1") - .filter(e -> s.contains(e.i)) - .getExpression()); - Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE `a`.`i` IN (1, 3)", v.getQuery()); + v.visitLimit(new LimitExpression(ConstantExpression.V0, 3L, 5L)); + Assertions.assertEquals("0 OFFSET 3 LIMIT 5", v.getQuery()); } @Test - public void testOr() { + void visitNull() { var v = new QueryBuilder(); - v.visit(new DbSet<>(TestClass.class, "table1") - .filter(e -> e.i == 0 || e.i == 1) - .getExpression()); - Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE `a`.`i` = 0 OR `a`.`i` = 1", v.getQuery()); + v.visitNull(NullExpression.INSTANCE); + Assertions.assertEquals("NULL", v.getQuery()); } @Test - public void testOrder() { + void visitOr() { var v = new QueryBuilder(); - v.visit(new DbSet<>(TestClass.class, "table1") - .filter(e -> e.i == 0 && e.i == 1) - .sorted(e -> e.getI()).thenSortedDescending(e -> e.getD()) - .getExpression()); - Assertions.assertEquals("SELECT * FROM (SELECT * FROM (SELECT * FROM `table1`) a WHERE `a`.`i` = 0 AND `a`.`i` = 1) b ORDER BY `b`.`i` ASC, `b`.`d` DESC", v.getQuery()); + v.visitOr(new OrExpression(ConstantExpression.V0, ConstantExpression.V1)); + Assertions.assertEquals("0 OR 1", v.getQuery()); } @Test - public void testUnary() { + void visitOrder() { + //multiple sorts var v = new QueryBuilder(); - v.visit(new DbSet<>(TestClass.class, "table1") - .filter(e -> e.o != null) - .getExpression()); - Assertions.assertEquals("SELECT * FROM (SELECT * FROM `table1`) a WHERE `a`.`o` IS NOT NULL", v.getQuery()); + v.visitOrder(new OrderExpression(ConstantExpression.V0, List.of( + new OrderExpression.Sort(new FieldExpression(null, null, "name1", null), OrderExpression.SortDirection.ASCENDING), + new OrderExpression.Sort(new FieldExpression(null, null, "name2", null), OrderExpression.SortDirection.DESCENDING)))); + Assertions.assertEquals("0 ORDER BY `name1` ASC, `name2` DESC", v.getQuery()); + + //with schema and table + v = new QueryBuilder(); + v.visitOrder(new OrderExpression(ConstantExpression.V0, List.of( + new OrderExpression.Sort(new FieldExpression("schema", "table", "name", null), OrderExpression.SortDirection.ASCENDING)))); + Assertions.assertEquals("0 ORDER BY `schema`.`table`.`name` ASC", v.getQuery()); + + //with table + v = new QueryBuilder(); + v.visitOrder(new OrderExpression(ConstantExpression.V0, List.of( + new OrderExpression.Sort(new FieldExpression(null, "table", "name", null), OrderExpression.SortDirection.ASCENDING)))); + Assertions.assertEquals("0 ORDER BY `table`.`name` ASC", v.getQuery()); + + //with schema + v = new QueryBuilder(); + v.visitOrder(new OrderExpression(ConstantExpression.V0, List.of( + new OrderExpression.Sort(new FieldExpression("schema", null, "name", null), OrderExpression.SortDirection.ASCENDING)))); + Assertions.assertEquals("0 ORDER BY `name` ASC", v.getQuery()); + + //without schema and table + v = new QueryBuilder(); + v.visitOrder(new OrderExpression(ConstantExpression.V0, List.of( + new OrderExpression.Sort(new FieldExpression(null, null, "name", null), OrderExpression.SortDirection.ASCENDING)))); + Assertions.assertEquals("0 ORDER BY `name` ASC", v.getQuery()); + } + + @Test + void visitParameter() { + //isInput + var v = new QueryBuilder(); + v.visitParameter(new ParameterExpression(0, null, true, null)); + Assertions.assertEquals("param #0", v.getQuery()); + + //value == null + v = new QueryBuilder(); + v.visitParameter(new ParameterExpression(0, null, false, null)); + Assertions.assertEquals("NULL", v.getQuery()); + + //value == null + v = new QueryBuilder(); + v.visitParameter(new ParameterExpression(0, Arrays.asList(null, "value"), false, null)); + Assertions.assertEquals("(NULL, value)", v.getQuery()); + + //value == null + var v2 = new QueryBuilder(); + Assertions.assertThrows(UnsupportedOperationException.class, () -> v2.visitParameter(new ParameterExpression(0, "value", false, null))); + } + + @Test + void visitSelect() { + //select from non table expr + var v = new QueryBuilder(); + v.visitSelect(new SelectExpression(List.of( + new FieldExpression(null, null, "name", null), + new FieldExpression(null, null, "name2", null) + ), ConstantExpression.V0, "alias")); + Assertions.assertEquals("SELECT `name`, `name2` FROM (0) alias", v.getQuery()); + + v = new QueryBuilder(); + v.visitSelect(new SelectExpression(List.of( + new FieldExpression(null, null, "name", null), + new FieldExpression(null, null, "name2", null) + ), new TableExpression("table"), "alias")); + Assertions.assertEquals("SELECT `name`, `name2` FROM `table` alias", v.getQuery()); + } + + @Test + void visitTable() { + var v = new QueryBuilder(); + v.visitTable(new TableExpression("table")); + Assertions.assertEquals("`table`", v.getQuery()); + } + + @Test + void visitTernary() { + var v = new QueryBuilder(); + v.visitTernary(new TernaryExpression(ConstantExpression.V0, ConstantExpression.V1, ConstantExpression.V2)); + Assertions.assertEquals("IF(0, 1, 2)", v.getQuery()); + } + + @Test + void visitUnary() { + var v = new QueryBuilder(); + v.visitUnary(new UnaryExpression(NullExpression.INSTANCE, UnaryExpression.Operator.NOT)); + Assertions.assertEquals("NOT NULL", v.getQuery()); + + v = new QueryBuilder(); + v.visitUnary(new UnaryExpression(new BinaryExpression(ConstantExpression.V0, ConstantExpression.V1, BinaryExpression.Operator.EQ), UnaryExpression.Operator.NOT)); + Assertions.assertEquals("NOT (0 = 1)", v.getQuery()); + } + + @Test + void visitWhere() { + var v = new QueryBuilder(); + v.visitWhere(new WhereExpression(ConstantExpression.V0, ConstantExpression.V1)); + Assertions.assertEquals("0 WHERE 1", v.getQuery()); } @Getter