Skip to content

Commit 6bbcb1d

Browse files
authored
Create UserDefinedCriteria (#1345)
2 parents ebcac7d + 13b01f8 commit 6bbcb1d

File tree

12 files changed

+686
-0
lines changed

12 files changed

+686
-0
lines changed

doma-core/src/main/java/org/seasar/doma/jdbc/criteria/context/Criterion.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
import java.util.Collections;
1919
import java.util.List;
2020
import java.util.Objects;
21+
import java.util.function.Consumer;
22+
import org.seasar.doma.jdbc.criteria.declaration.UserDefinedCriteriaContext;
2123
import org.seasar.doma.jdbc.criteria.option.LikeOption;
2224
import org.seasar.doma.jdbc.criteria.tuple.Tuple2;
2325
import org.seasar.doma.jdbc.criteria.tuple.Tuple3;
@@ -448,6 +450,20 @@ public void accept(Visitor visitor) {
448450
}
449451
}
450452

453+
class UserDefined implements Criterion {
454+
public final Consumer<UserDefinedCriteriaContext.Builder> builderBlock;
455+
456+
public UserDefined(Consumer<UserDefinedCriteriaContext.Builder> builderBlock) {
457+
Objects.requireNonNull(builderBlock);
458+
this.builderBlock = builderBlock;
459+
}
460+
461+
@Override
462+
public void accept(Visitor visitor) {
463+
visitor.visit(this);
464+
}
465+
}
466+
451467
interface Visitor {
452468
void visit(Eq criterion);
453469

@@ -504,5 +520,7 @@ interface Visitor {
504520
void visit(Or criterion);
505521

506522
void visit(Not criterion);
523+
524+
void visit(UserDefined criterion);
507525
}
508526
}

doma-core/src/main/java/org/seasar/doma/jdbc/criteria/declaration/ComparisonDeclaration.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -903,6 +903,25 @@ public void or(Runnable block) {
903903
runBlock(block, Criterion.Or::new);
904904
}
905905

906+
/**
907+
* Add a declaring a user-defined extension.
908+
*
909+
* @param <EXTENSION> the type of the user-defined extension
910+
* @param construct function that generates user-defined extension.
911+
* @param extensionBlock block that can use user-defined extension.
912+
* @throws NullPointerException if {@code construct} or {@code extensionBlock} is null
913+
*/
914+
public <EXTENSION> void extension(
915+
Function<UserDefinedCriteriaContext, EXTENSION> construct,
916+
Consumer<EXTENSION> extensionBlock) {
917+
Objects.requireNonNull(construct);
918+
Objects.requireNonNull(extensionBlock);
919+
920+
var extension =
921+
construct.apply(builderBlock -> this.add(new Criterion.UserDefined(builderBlock)));
922+
extensionBlock.accept(extension);
923+
}
924+
906925
/**
907926
* Add a {@code NOT} operator.
908927
*
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*
2+
* Copyright Doma Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.seasar.doma.jdbc.criteria.declaration;
17+
18+
import java.util.function.Consumer;
19+
import org.seasar.doma.jdbc.criteria.metamodel.PropertyMetamodel;
20+
import org.seasar.doma.jdbc.dialect.Dialect;
21+
22+
/** Represents a user-defined comparison criteria declaration. */
23+
@FunctionalInterface
24+
public interface UserDefinedCriteriaContext {
25+
/**
26+
* Adds a user-defined operation to the criteria declaration by accepting a function that
27+
* configures the provided {@code Builder}.
28+
*
29+
* @param builderBlock a {@link Consumer} used to configure the {@code Builder} for appending SQL
30+
* code, expressions, or other operations
31+
*/
32+
void add(Consumer<Builder> builderBlock);
33+
34+
interface Builder {
35+
/**
36+
* Appends SQL code to the declaration.
37+
*
38+
* @param sql the SQL code to be appended
39+
*/
40+
void appendSql(String sql);
41+
42+
/**
43+
* cutback SQL.
44+
*
45+
* @param length the length to cutback the SQL code
46+
*/
47+
void cutBackSql(int length);
48+
49+
/**
50+
* Append a expression.
51+
*
52+
* @param propertyMetamodel the {@link PropertyMetamodel} to be added as a expression in the
53+
* declaration
54+
*/
55+
void appendExpression(PropertyMetamodel<?> propertyMetamodel);
56+
57+
/**
58+
* Appends a parameter.
59+
*
60+
* @param propertyMetamodel the {@link PropertyMetamodel} to be added as a expression in the
61+
* declaration
62+
* @param value the value of the property
63+
* @param <PROPERTY> the type of the property
64+
*/
65+
<PROPERTY> void appendParameter(PropertyMetamodel<PROPERTY> propertyMetamodel, PROPERTY value);
66+
67+
/**
68+
* Represents the specific database dialect. This is utilized to modify user-defined expressions
69+
* based on the dialect in use.
70+
*/
71+
Dialect getDialect();
72+
}
73+
}

doma-core/src/main/java/org/seasar/doma/jdbc/criteria/query/BuilderSupport.java

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.util.Objects;
2121
import java.util.Optional;
2222
import java.util.function.BiFunction;
23+
import java.util.function.Consumer;
2324
import java.util.function.Function;
2425
import org.seasar.doma.DomaException;
2526
import org.seasar.doma.expr.ExpressionFunctions;
@@ -36,6 +37,7 @@
3637
import org.seasar.doma.jdbc.criteria.context.SelectContext;
3738
import org.seasar.doma.jdbc.criteria.context.SetOperationContext;
3839
import org.seasar.doma.jdbc.criteria.context.WithContext;
40+
import org.seasar.doma.jdbc.criteria.declaration.UserDefinedCriteriaContext;
3941
import org.seasar.doma.jdbc.criteria.expression.AggregateFunction;
4042
import org.seasar.doma.jdbc.criteria.expression.AliasExpression;
4143
import org.seasar.doma.jdbc.criteria.expression.ArithmeticExpression;
@@ -49,6 +51,7 @@
4951
import org.seasar.doma.jdbc.criteria.option.LikeOption;
5052
import org.seasar.doma.jdbc.criteria.tuple.Tuple2;
5153
import org.seasar.doma.jdbc.criteria.tuple.Tuple3;
54+
import org.seasar.doma.jdbc.dialect.Dialect;
5255
import org.seasar.doma.jdbc.entity.EntityPropertyType;
5356
import org.seasar.doma.jdbc.entity.EntityType;
5457
import org.seasar.doma.jdbc.entity.Property;
@@ -65,6 +68,7 @@ public class BuilderSupport {
6568
private final PropertyMetamodelVisitor propertyMetamodelVisitor;
6669
private final UserDefinedExpressionDeclarationItemVisitor
6770
userDefinedExpressionDeclarationItemVisitor;
71+
private final UserDefinedCriteriaContextBuilder userDefinedCriteriaContextBuilder;
6872

6973
public BuilderSupport(
7074
Config config,
@@ -79,6 +83,7 @@ public BuilderSupport(
7983
this.propertyMetamodelVisitor = new PropertyMetamodelVisitor();
8084
this.userDefinedExpressionDeclarationItemVisitor =
8185
new UserDefinedExpressionDeclarationItemVisitor();
86+
this.userDefinedCriteriaContextBuilder = new UserDefinedCriteriaContextBuilder();
8287
}
8388

8489
public void with(List<WithContext> withContexts) {
@@ -424,6 +429,11 @@ public void visit(Criterion.Not criterion) {
424429
not(criterion.criterionList);
425430
}
426431

432+
@Override
433+
public void visit(Criterion.UserDefined criterion) {
434+
extension(criterion.builderBlock);
435+
}
436+
427437
private void comparison(Operand.Prop left, Operand right, String op) {
428438
column(left);
429439
buf.appendSql(" " + op + " ");
@@ -690,6 +700,10 @@ private void not(List<Criterion> criterionList) {
690700
buf.appendSql(")");
691701
}
692702
}
703+
704+
private void extension(Consumer<UserDefinedCriteriaContext.Builder> builderBlock) {
705+
builderBlock.accept(userDefinedCriteriaContextBuilder);
706+
}
693707
}
694708

695709
class PropertyMetamodelVisitor
@@ -924,4 +938,37 @@ public void visit(UserDefinedExpression.DeclarationItem.CutbackSql cutbackSql) {
924938
buf.cutBackSql(cutbackSql.get());
925939
}
926940
}
941+
942+
class UserDefinedCriteriaContextBuilder implements UserDefinedCriteriaContext.Builder {
943+
@Override
944+
public void appendSql(String sql) {
945+
Objects.requireNonNull(sql);
946+
buf.appendSql(sql);
947+
}
948+
949+
@Override
950+
public void cutBackSql(int length) {
951+
buf.cutBackSql(length);
952+
}
953+
954+
@Override
955+
public void appendExpression(PropertyMetamodel<?> propertyMetamodel) {
956+
Objects.requireNonNull(propertyMetamodel);
957+
propertyMetamodel.accept(propertyMetamodelVisitor);
958+
}
959+
960+
@Override
961+
public <PROPERTY> void appendParameter(
962+
PropertyMetamodel<PROPERTY> propertyMetamodel, PROPERTY value) {
963+
Objects.requireNonNull(propertyMetamodel);
964+
var param = new Operand.Param(propertyMetamodel, value);
965+
var parameter = param.createInParameter(config);
966+
param(parameter);
967+
}
968+
969+
@Override
970+
public Dialect getDialect() {
971+
return config.getDialect();
972+
}
973+
}
927974
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Copyright Doma Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.seasar.doma.jdbc.criteria;
17+
18+
import org.seasar.doma.jdbc.criteria.declaration.UserDefinedCriteriaContext;
19+
import org.seasar.doma.jdbc.criteria.metamodel.PropertyMetamodel;
20+
21+
record MyExtension(UserDefinedCriteriaContext context) {
22+
public void likeMultiple(PropertyMetamodel<String> propertyMetamodel, String... patterns) {
23+
context.add(
24+
(b) -> {
25+
for (String pattern : patterns) {
26+
b.appendExpression(propertyMetamodel);
27+
b.appendSql(" like ");
28+
b.appendParameter(propertyMetamodel, "%" + pattern + "%");
29+
b.appendSql(" or ");
30+
}
31+
b.cutBackSql(4);
32+
});
33+
}
34+
35+
public void eq2(PropertyMetamodel<String> propertyMetamodel, String pattern) {
36+
context.add(
37+
(b) -> {
38+
b.appendExpression(propertyMetamodel);
39+
b.appendSql(" = ");
40+
b.appendParameter(propertyMetamodel, pattern);
41+
});
42+
}
43+
}

0 commit comments

Comments
 (0)