Skip to content

Commit e2364f0

Browse files
committed
Java 17 and more date methods.
1 parent 4979539 commit e2364f0

File tree

6 files changed

+86
-48
lines changed

6 files changed

+86
-48
lines changed

README.MD

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Lambda2sql (lambda) -> "sql"
22
==========
33

4-
**Please note:** This is a Java 13 library so make sure you have at least Java 13 installed when using it.
4+
**Please note:** This is a Java 11 library so make sure you have at least Java 13 installed when using it.
55

66
Convert Java 8 lambdas to SQL statements.
77

@@ -77,7 +77,7 @@ You can include the Maven dependency:
7777
<dependency>
7878
<groupId>com.github.collinalpert</groupId>
7979
<artifactId>lambda2sql</artifactId>
80-
<version>2.4.0</version>
80+
<version>2.5.0</version>
8181
</dependency>
8282
```
8383

pom.xml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<groupId>com.github.collinalpert</groupId>
88
<artifactId>lambda2sql</artifactId>
9-
<version>2.4.0</version>
9+
<version>2.5.0</version>
1010
<packaging>jar</packaging>
1111

1212
<name>lambda2sql</name>
@@ -34,7 +34,7 @@
3434
<scm>
3535
<connection>scm:git:git://github.com/CollinAlpert/lambda2sql.git</connection>
3636
<developerConnection>scm:git:ssh://github.com:CollinAlpert/lambda2sql.git</developerConnection>
37-
<url>http://github.com/CollinAlpert/lambda2sql/tree/master</url>
37+
<url>https://github.com/CollinAlpert/lambda2sql/tree/master</url>
3838
</scm>
3939

4040
<distributionManagement>
@@ -49,7 +49,7 @@
4949
</distributionManagement>
5050

5151
<properties>
52-
<java-version>13</java-version>
52+
<java-version>11</java-version>
5353
<jdk.version>${java-version}</jdk.version>
5454
<maven.compiler.release>${java-version}</maven.compiler.release>
5555
<maven.compiler.source>${java-version}</maven.compiler.source>
@@ -61,13 +61,13 @@
6161
<dependency>
6262
<groupId>com.github.collinalpert</groupId>
6363
<artifactId>expressions</artifactId>
64-
<version>2.6.1</version>
64+
<version>2.7.0</version>
6565
</dependency>
6666

6767
<dependency>
6868
<groupId>org.junit.jupiter</groupId>
6969
<artifactId>junit-jupiter-api</artifactId>
70-
<version>5.7.0</version>
70+
<version>5.8.0-M1</version>
7171
<scope>test</scope>
7272
</dependency>
7373

@@ -113,7 +113,7 @@
113113
<plugin>
114114
<groupId>org.apache.maven.plugins</groupId>
115115
<artifactId>maven-javadoc-plugin</artifactId>
116-
<version>3.2.0</version>
116+
<version>3.3.0</version>
117117
<configuration>
118118
<additionalOptions>-html5</additionalOptions>
119119
</configuration>

src/main/java/com/github/collinalpert/lambda2sql/Lambda2Sql.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public class Lambda2Sql {
2222
* @return A {@link String} describing the SQL where condition.
2323
*/
2424
public static String toSql(SerializedFunctionalInterface functionalInterface, String tableName, boolean withBackticks) {
25-
var lambdaExpression = LambdaExpression.parse(functionalInterface);
25+
LambdaExpression lambdaExpression = LambdaExpression.parse(functionalInterface);
2626
return lambdaExpression.accept(new SqlVisitor(tableName, withBackticks)).toString();
2727
}
2828

src/main/java/com/github/collinalpert/lambda2sql/SqlFunctions.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package com.github.collinalpert.lambda2sql;
22

33
/**
4+
* This class contains placeholder functions which can be used within an expression to make use of the respective SQL function.
5+
*
46
* @author Collin Alpert
57
*/
68
public class SqlFunctions {

src/main/java/com/github/collinalpert/lambda2sql/SqlVisitor.java

Lines changed: 71 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,11 @@ public class SqlVisitor implements ExpressionVisitor<StringBuilder> {
2929
try {
3030
operatorMethods.put(String.class.getDeclaredMethod("equals", Object.class), ExpressionType.Equal);
3131
operatorMethods.put(Object.class.getDeclaredMethod("equals", Object.class), ExpressionType.Equal);
32-
operatorMethods.put(LocalDate.class.getDeclaredMethod("isAfter", ChronoLocalDate.class), ExpressionType.GreaterThan);
32+
3333
operatorMethods.put(LocalTime.class.getDeclaredMethod("isAfter", LocalTime.class), ExpressionType.GreaterThan);
34+
operatorMethods.put(LocalDate.class.getDeclaredMethod("isAfter", ChronoLocalDate.class), ExpressionType.GreaterThan);
3435
operatorMethods.put(LocalDateTime.class.getDeclaredMethod("isAfter", ChronoLocalDateTime.class), ExpressionType.GreaterThan);
36+
3537
operatorMethods.put(LocalDate.class.getDeclaredMethod("isBefore", ChronoLocalDate.class), ExpressionType.LessThan);
3638
operatorMethods.put(LocalTime.class.getDeclaredMethod("isBefore", LocalTime.class), ExpressionType.LessThan);
3739
operatorMethods.put(LocalDateTime.class.getDeclaredMethod("isBefore", ChronoLocalDateTime.class), ExpressionType.LessThan);
@@ -52,7 +54,7 @@ public class SqlVisitor implements ExpressionVisitor<StringBuilder> {
5254
/**
5355
* More complex methods that can be used on Java objects inside the lambda expressions.
5456
*/
55-
private final Map<Member, TriFunction<Expression, Expression, Boolean, StringBuilder>> complexMethods;
57+
private final Map<Member, TriFunction<Expression, Expression, Boolean, StringBuilder>> javaMethods;
5658

5759
private final StringBuilder sb;
5860
private Expression body;
@@ -70,33 +72,61 @@ private SqlVisitor(String tableName, boolean withBackticks, Expression body, Lin
7072
this.sb = new StringBuilder();
7173
this.parameterConsumptionCount = new HashMap<>();
7274

73-
this.complexMethods = new HashMap<>(32, 1);
75+
this.javaMethods = new HashMap<>(1 << 6, 1);
7476
try {
75-
this.complexMethods.put(String.class.getDeclaredMethod("startsWith", String.class), this::stringStartsWith);
76-
this.complexMethods.put(String.class.getDeclaredMethod("endsWith", String.class), this::stringEndsWith);
77-
this.complexMethods.put(String.class.getDeclaredMethod("contains", CharSequence.class), this::stringContains);
78-
this.complexMethods.put(String.class.getDeclaredMethod("length"), (string, argument, isNegated) -> applySqlFunction(string, "LENGTH"));
79-
80-
this.complexMethods.put(List.class.getDeclaredMethod("contains", Object.class), this::listContains);
81-
this.complexMethods.put(ArrayList.class.getDeclaredMethod("contains", Object.class), this::listContains);
82-
this.complexMethods.put(LinkedList.class.getDeclaredMethod("contains", Object.class), this::listContains);
83-
84-
this.complexMethods.put(LocalTime.class.getDeclaredMethod("getSecond"), (date, argument, isNegated) -> applySqlFunction(date, "SECOND"));
85-
this.complexMethods.put(LocalDateTime.class.getDeclaredMethod("getSecond"), (date, argument, isNegated) -> applySqlFunction(date, "SECOND"));
86-
this.complexMethods.put(LocalTime.class.getDeclaredMethod("getMinute"), (date, argument, isNegated) -> applySqlFunction(date, "MINUTE"));
87-
this.complexMethods.put(LocalDateTime.class.getDeclaredMethod("getMinute"), (date, argument, isNegated) -> applySqlFunction(date, "MINUTE"));
88-
this.complexMethods.put(LocalTime.class.getDeclaredMethod("getHour"), (date, argument, isNegated) -> applySqlFunction(date, "HOUR"));
89-
this.complexMethods.put(LocalDateTime.class.getDeclaredMethod("getHour"), (date, argument, isNegated) -> applySqlFunction(date, "HOUR"));
90-
this.complexMethods.put(LocalDate.class.getDeclaredMethod("getDayOfWeek"), (date, argument, isNegated) -> applySqlFunction(date, "DAYOFWEEK"));
91-
this.complexMethods.put(LocalDateTime.class.getDeclaredMethod("getDayOfWeek"), (date, argument, isNegated) -> applySqlFunction(date, "DAYOFWEEK"));
92-
this.complexMethods.put(LocalDate.class.getDeclaredMethod("getDayOfMonth"), (date, argument, isNegated) -> applySqlFunction(date, "DAY"));
93-
this.complexMethods.put(LocalDateTime.class.getDeclaredMethod("getDayOfWeek"), (date, argument, isNegated) -> applySqlFunction(date, "DAY"));
94-
this.complexMethods.put(LocalDate.class.getDeclaredMethod("getDayOfYear"), (date, argument, isNegated) -> applySqlFunction(date, "DAYOFYEAR"));
95-
this.complexMethods.put(LocalDateTime.class.getDeclaredMethod("getDayOfYear"), (date, argument, isNegated) -> applySqlFunction(date, "DAYOFYEAR"));
96-
this.complexMethods.put(LocalDate.class.getDeclaredMethod("getMonthValue"), (date, argument, isNegated) -> applySqlFunction(date, "MONTH"));
97-
this.complexMethods.put(LocalDateTime.class.getDeclaredMethod("getMonthValue"), (date, argument, isNegated) -> applySqlFunction(date, "MONTH"));
98-
this.complexMethods.put(LocalDate.class.getDeclaredMethod("getYear"), (date, argument, isNegated) -> applySqlFunction(date, "YEAR"));
99-
this.complexMethods.put(LocalDateTime.class.getDeclaredMethod("getYear"), (date, argument, isNegated) -> applySqlFunction(date, "YEAR"));
77+
this.javaMethods.put(String.class.getDeclaredMethod("startsWith", String.class), this::stringStartsWith);
78+
this.javaMethods.put(String.class.getDeclaredMethod("endsWith", String.class), this::stringEndsWith);
79+
this.javaMethods.put(String.class.getDeclaredMethod("contains", CharSequence.class), this::stringContains);
80+
this.javaMethods.put(String.class.getDeclaredMethod("length"), applySqlFunction("LENGTH"));
81+
this.javaMethods.put(String.class.getDeclaredMethod("toLowerCase"), applySqlFunction("UPPER"));
82+
this.javaMethods.put(String.class.getDeclaredMethod("toUpperCase"), applySqlFunction("LOWER"));
83+
84+
this.javaMethods.put(List.class.getDeclaredMethod("contains", Object.class), this::listContains);
85+
this.javaMethods.put(ArrayList.class.getDeclaredMethod("contains", Object.class), this::listContains);
86+
this.javaMethods.put(LinkedList.class.getDeclaredMethod("contains", Object.class), this::listContains);
87+
88+
this.javaMethods.put(LocalTime.class.getDeclaredMethod("getSecond"), applySqlFunction("SECOND"));
89+
this.javaMethods.put(LocalDateTime.class.getDeclaredMethod("getSecond"), applySqlFunction("SECOND"));
90+
this.javaMethods.put(OffsetTime.class.getDeclaredMethod("getSecond"), applySqlFunction("SECOND"));
91+
this.javaMethods.put(OffsetDateTime.class.getDeclaredMethod("getSecond"), applySqlFunction("SECOND"));
92+
this.javaMethods.put(ZonedDateTime.class.getDeclaredMethod("getSecond"), applySqlFunction("SECOND"));
93+
94+
this.javaMethods.put(LocalTime.class.getDeclaredMethod("getMinute"), applySqlFunction("MINUTE"));
95+
this.javaMethods.put(LocalDateTime.class.getDeclaredMethod("getMinute"), applySqlFunction("MINUTE"));
96+
this.javaMethods.put(OffsetTime.class.getDeclaredMethod("getMinute"), applySqlFunction("MINUTE"));
97+
this.javaMethods.put(OffsetDateTime.class.getDeclaredMethod("getMinute"), applySqlFunction("MINUTE"));
98+
this.javaMethods.put(ZonedDateTime.class.getDeclaredMethod("getMinute"), applySqlFunction("MINUTE"));
99+
100+
this.javaMethods.put(LocalTime.class.getDeclaredMethod("getHour"), applySqlFunction("HOUR"));
101+
this.javaMethods.put(LocalDateTime.class.getDeclaredMethod("getHour"), applySqlFunction("HOUR"));
102+
this.javaMethods.put(OffsetTime.class.getDeclaredMethod("getHour"), applySqlFunction("HOUR"));
103+
this.javaMethods.put(OffsetDateTime.class.getDeclaredMethod("getHour"), applySqlFunction("HOUR"));
104+
this.javaMethods.put(ZonedDateTime.class.getDeclaredMethod("getHour"), applySqlFunction("HOUR"));
105+
106+
this.javaMethods.put(LocalDate.class.getDeclaredMethod("getDayOfWeek"), applySqlFunction("DAYOFWEEK"));
107+
this.javaMethods.put(LocalDateTime.class.getDeclaredMethod("getDayOfWeek"), applySqlFunction("DAYOFWEEK"));
108+
this.javaMethods.put(OffsetDateTime.class.getDeclaredMethod("getDayOfWeek"), applySqlFunction("DAYOFWEEK"));
109+
this.javaMethods.put(ZonedDateTime.class.getDeclaredMethod("getDayOfWeek"), applySqlFunction("DAYOFWEEK"));
110+
111+
this.javaMethods.put(LocalDate.class.getDeclaredMethod("getDayOfMonth"), applySqlFunction("DAY"));
112+
this.javaMethods.put(LocalDateTime.class.getDeclaredMethod("getDayOfWeek"), applySqlFunction("DAY"));
113+
this.javaMethods.put(OffsetDateTime.class.getDeclaredMethod("getDayOfWeek"), applySqlFunction("DAY"));
114+
this.javaMethods.put(ZonedDateTime.class.getDeclaredMethod("getDayOfWeek"), applySqlFunction("DAY"));
115+
116+
this.javaMethods.put(LocalDate.class.getDeclaredMethod("getDayOfYear"), applySqlFunction("DAYOFYEAR"));
117+
this.javaMethods.put(LocalDateTime.class.getDeclaredMethod("getDayOfYear"), applySqlFunction("DAYOFYEAR"));
118+
this.javaMethods.put(OffsetDateTime.class.getDeclaredMethod("getDayOfYear"), applySqlFunction("DAYOFYEAR"));
119+
this.javaMethods.put(ZonedDateTime.class.getDeclaredMethod("getDayOfYear"), applySqlFunction("DAYOFYEAR"));
120+
121+
this.javaMethods.put(LocalDate.class.getDeclaredMethod("getMonthValue"), applySqlFunction("MONTH"));
122+
this.javaMethods.put(LocalDateTime.class.getDeclaredMethod("getMonthValue"), applySqlFunction("MONTH"));
123+
this.javaMethods.put(OffsetDateTime.class.getDeclaredMethod("getMonthValue"), applySqlFunction("MONTH"));
124+
this.javaMethods.put(ZonedDateTime.class.getDeclaredMethod("getMonthValue"), applySqlFunction("MONTH"));
125+
126+
this.javaMethods.put(LocalDate.class.getDeclaredMethod("getYear"), applySqlFunction("YEAR"));
127+
this.javaMethods.put(LocalDateTime.class.getDeclaredMethod("getYear"), applySqlFunction("YEAR"));
128+
this.javaMethods.put(OffsetDateTime.class.getDeclaredMethod("getYear"), applySqlFunction("YEAR"));
129+
this.javaMethods.put(ZonedDateTime.class.getDeclaredMethod("getYear"), applySqlFunction("YEAR"));
100130
} catch (NoSuchMethodException e) {
101131
e.printStackTrace();
102132
}
@@ -184,7 +214,7 @@ public StringBuilder visit(ConstantExpression e) {
184214
return sb.append("'").append(escapeString(e.getValue().toString())).append("'");
185215
}
186216

187-
return sb.append(e.getValue().toString());
217+
return sb.append(e.getValue());
188218
}
189219

190220
/**
@@ -205,7 +235,7 @@ public StringBuilder visit(InvocationExpression e) {
205235
.map(ConstantExpression.class::cast)
206236
.collect(Collectors.toList());
207237
if (!list.isEmpty()) {
208-
arguments.push(list);
238+
this.arguments.push(list);
209239
}
210240
}
211241

@@ -219,7 +249,7 @@ public StringBuilder visit(InvocationExpression e) {
219249
}
220250

221251
if (e.getTarget().getExpressionType() == ExpressionType.MethodAccess && !e.getArguments().isEmpty()) {
222-
javaMethodParameter = e.getArguments().get(0);
252+
this.javaMethodParameter = e.getArguments().get(0);
223253
}
224254

225255
return e.getTarget().accept(this);
@@ -261,8 +291,9 @@ public StringBuilder visit(MemberExpression e) {
261291
return Expression.binary(operatorMethods.get(e.getMember()), e.getInstance(), this.javaMethodParameter).accept(this);
262292
}
263293

264-
if (this.complexMethods.containsKey(e.getMember())) {
265-
return sb.append(this.complexMethods.get(e.getMember()).apply(e.getInstance(), this.javaMethodParameter, false));
294+
var javaMethodReplacer = this.javaMethods.get(e.getMember());
295+
if (javaMethodReplacer != null) {
296+
return sb.append(javaMethodReplacer.apply(e.getInstance(), this.javaMethodParameter, false));
266297
}
267298

268299
var nameArray = e.getMember().getName().replaceAll("^(get)", "").toCharArray();
@@ -320,8 +351,8 @@ public StringBuilder visit(UnaryExpression e) {
320351
var memberExpression = (MemberExpression) invocationExpression.getTarget();
321352
if (operatorMethods.containsKey(memberExpression.getMember())) {
322353
return Expression.logicalNot(Expression.binary(operatorMethods.get(memberExpression.getMember()), memberExpression.getInstance(), invocationExpression.getArguments().get(0))).accept(this);
323-
} else if (complexMethods.containsKey(memberExpression.getMember())) {
324-
return sb.append(complexMethods.get(memberExpression.getMember()).apply(memberExpression.getInstance(), invocationExpression.getArguments().get(0), true));
354+
} else if (this.javaMethods.containsKey(memberExpression.getMember())) {
355+
return sb.append(this.javaMethods.get(memberExpression.getMember()).apply(memberExpression.getInstance(), invocationExpression.getArguments().get(0), true));
325356
} else {
326357
sb.append("!");
327358
}
@@ -348,15 +379,16 @@ private StringBuilder stringContains(Expression string, Expression argument, boo
348379
}
349380

350381
private StringBuilder listContains(Expression list, Expression argument, boolean isNegated) {
351-
List l = (List) arguments.pop().get(((ParameterExpression) list).getIndex()).getValue();
382+
@SuppressWarnings("unchecked")
383+
List<Object> l = (List<Object>) this.arguments.pop().get(((ParameterExpression) list).getIndex()).getValue();
352384
var joiner = new StringJoiner(", ", "(", ")");
353385
l.forEach(x -> joiner.add(x.toString()));
354386

355-
return argument.accept(new SqlVisitor(this.tableName, this.withBackticks, this.body, this.arguments)).append(isNegated ? " NOT" : "").append(" IN ").append(joiner.toString());
387+
return argument.accept(new SqlVisitor(this.tableName, this.withBackticks, this.body, this.arguments)).append(isNegated ? " NOT" : "").append(" IN ").append(joiner);
356388
}
357389

358-
private StringBuilder applySqlFunction(Expression date, String field) {
359-
return new StringBuilder().append(field).append("(").append(date.accept(new SqlVisitor(this.tableName, this.withBackticks, this.body, this.arguments))).append(')');
390+
private TriFunction<Expression, Expression, Boolean, StringBuilder> applySqlFunction(String field) {
391+
return (value, argument, isNegated) -> new StringBuilder().append(field).append("(").append(value.accept(new SqlVisitor(this.tableName, this.withBackticks, this.body, this.arguments))).append(')');
360392
}
361393

362394
//endregion

src/test/java/com/github/collinalpert/lambda2sql/test/Lambda2SqlTest.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,11 @@ void testLastParameterNull() {
224224
void testMultipleSameParameter() {
225225
String s = "Steve";
226226
SqlPredicate<IPerson> p = x -> x.getName() == s || x.getLastName() == s;
227+
SqlPredicate<IPerson> p2 = x -> x.getName() == s || x.getName() == s && x.isActive();
228+
SqlPredicate<IPerson> p3 = x -> x.getName() == s || x.getLastName() == s && x.isActive();
227229
assertPredicateEqual("`person`.`name` = 'Steve' OR `person`.`lastName` = 'Steve'", p);
230+
assertPredicateEqual("`person`.`name` = 'Steve' OR `person`.name` = 'Steve' AND `person`.`isActive`", p2);
231+
assertPredicateEqual("`person`.`name` = 'Steve' OR `person`.`lastName` = 'Steve' AND `person`.`isActive`", p3);
228232
}
229233

230234
@Test

0 commit comments

Comments
 (0)