Skip to content

Commit f33df36

Browse files
authored
Merge pull request #453 from domaframework/like-operand
Accept a CharSequence value as a LIKE predicate operand
2 parents 2c0a2ab + c2941e9 commit f33df36

File tree

6 files changed

+102
-67
lines changed

6 files changed

+102
-67
lines changed

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -127,12 +127,12 @@ public void accept(Visitor visitor) {
127127

128128
class Like implements Criterion {
129129
public final Operand.Prop left;
130-
public final Operand right;
130+
public final CharSequence right;
131131
public final LikeOption option;
132132

133-
public Like(Operand.Prop left, Operand right, LikeOption option) {
133+
public Like(Operand.Prop left, CharSequence right, LikeOption option) {
134134
this.left = Objects.requireNonNull(left);
135-
this.right = Objects.requireNonNull(right);
135+
this.right = right;
136136
this.option = Objects.requireNonNull(option);
137137
}
138138

@@ -144,12 +144,12 @@ public void accept(Visitor visitor) {
144144

145145
class NotLike implements Criterion {
146146
public final Operand.Prop left;
147-
public final Operand right;
147+
public final CharSequence right;
148148
public final LikeOption option;
149149

150-
public NotLike(Operand.Prop left, Operand right, LikeOption option) {
150+
public NotLike(Operand.Prop left, CharSequence right, LikeOption option) {
151151
this.left = Objects.requireNonNull(left);
152-
this.right = Objects.requireNonNull(right);
152+
this.right = right;
153153
this.option = Objects.requireNonNull(option);
154154
}
155155

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

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -42,29 +42,24 @@ public <PROPERTY> void isNotNull(PropertyMetamodel<PROPERTY> propertyMetamodel)
4242
add(new Criterion.IsNotNull(new Operand.Prop(propertyMetamodel)));
4343
}
4444

45-
public <PROPERTY> void like(PropertyMetamodel<PROPERTY> left, PROPERTY right) {
45+
public void like(PropertyMetamodel<?> left, CharSequence right) {
4646
Objects.requireNonNull(left);
47-
add(
48-
new Criterion.Like(
49-
new Operand.Prop(left), new Operand.Param(left, right), LikeOption.none()));
47+
add(new Criterion.Like(new Operand.Prop(left), right, LikeOption.none()));
5048
}
5149

52-
public <PROPERTY> void like(PropertyMetamodel<PROPERTY> left, PROPERTY right, LikeOption option) {
50+
public void like(PropertyMetamodel<?> left, CharSequence right, LikeOption option) {
5351
Objects.requireNonNull(left);
54-
add(new Criterion.Like(new Operand.Prop(left), new Operand.Param(left, right), option));
52+
add(new Criterion.Like(new Operand.Prop(left), right, option));
5553
}
5654

57-
public <PROPERTY> void notLike(PropertyMetamodel<PROPERTY> left, PROPERTY right) {
55+
public void notLike(PropertyMetamodel<?> left, CharSequence right) {
5856
Objects.requireNonNull(left);
59-
add(
60-
new Criterion.NotLike(
61-
new Operand.Prop(left), new Operand.Param(left, right), LikeOption.none()));
57+
add(new Criterion.NotLike(new Operand.Prop(left), right, LikeOption.none()));
6258
}
6359

64-
public <PROPERTY> void notLike(
65-
PropertyMetamodel<PROPERTY> left, PROPERTY right, LikeOption option) {
60+
public void notLike(PropertyMetamodel<?> left, CharSequence right, LikeOption option) {
6661
Objects.requireNonNull(left);
67-
add(new Criterion.NotLike(new Operand.Prop(left), new Operand.Param(left, right), option));
62+
add(new Criterion.NotLike(new Operand.Prop(left), right, option));
6863
}
6964

7065
public <PROPERTY> void between(

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

Lines changed: 38 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -277,57 +277,50 @@ private void isNotNull(Operand.Prop prop) {
277277
buf.appendSql(" is not null");
278278
}
279279

280-
private void like(Operand.Prop left, Operand right, LikeOption option, boolean not) {
280+
private void like(Operand.Prop left, CharSequence right, LikeOption option, boolean not) {
281281
column(left);
282282
if (not) {
283283
buf.appendSql(" not");
284284
}
285285
buf.appendSql(" like ");
286-
right.accept(
287-
new OperandVisitor() {
286+
String value = right == null ? null : right.toString();
287+
ExpressionFunctions functions = config.getDialect().getExpressionFunctions();
288+
option.accept(
289+
new LikeOption.Visitor() {
288290
@Override
289-
public Void visit(Operand.Param param) {
290-
InParameter<?> parameter = param.createInParameter(config);
291-
Object value = parameter.getWrapper().get();
292-
if (value == null) {
293-
return super.visit(param);
294-
}
295-
ExpressionFunctions functions = config.getDialect().getExpressionFunctions();
296-
option.accept(
297-
new LikeOption.Visitor() {
298-
@Override
299-
public void visit(LikeOption.None none) {
300-
param(param);
301-
}
302-
303-
@Override
304-
public void visit(LikeOption.Escape escape) {
305-
appendNewValue(functions::escape, escape.escapeChar);
306-
}
307-
308-
@Override
309-
public void visit(LikeOption.Prefix prefix) {
310-
appendNewValue(functions::prefix, prefix.escapeChar);
311-
}
312-
313-
@Override
314-
public void visit(LikeOption.Infix infix) {
315-
appendNewValue(functions::infix, infix.escapeChar);
316-
}
317-
318-
@Override
319-
public void visit(LikeOption.Suffix suffix) {
320-
appendNewValue(functions::suffix, suffix.escapeChar);
321-
}
322-
323-
private void appendNewValue(
324-
BiFunction<String, Character, String> function, char escapeChar) {
325-
String newValue = function.apply(value.toString(), escapeChar);
326-
param(new BasicInParameter<>(() -> new StringWrapper(newValue)));
327-
buf.appendSql(" escape '" + escapeChar + "'");
328-
}
329-
});
330-
return null;
291+
public void visit(LikeOption.None none) {
292+
addParam(value);
293+
}
294+
295+
@Override
296+
public void visit(LikeOption.Escape escape) {
297+
appendNewValue(functions::escape, escape.escapeChar);
298+
}
299+
300+
@Override
301+
public void visit(LikeOption.Prefix prefix) {
302+
appendNewValue(functions::prefix, prefix.escapeChar);
303+
}
304+
305+
@Override
306+
public void visit(LikeOption.Infix infix) {
307+
appendNewValue(functions::infix, infix.escapeChar);
308+
}
309+
310+
@Override
311+
public void visit(LikeOption.Suffix suffix) {
312+
appendNewValue(functions::suffix, suffix.escapeChar);
313+
}
314+
315+
private void appendNewValue(
316+
BiFunction<String, Character, String> function, char escapeChar) {
317+
String newValue = function.apply(value, escapeChar);
318+
addParam(newValue);
319+
buf.appendSql(" escape '" + escapeChar + "'");
320+
}
321+
322+
private void addParam(String value) {
323+
param(new BasicInParameter<>(() -> new StringWrapper(value)));
331324
}
332325
});
333326
}

test-criteria/src/main/java/example/Address.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
@Entity(metamodel = @Metamodel)
88
public class Address {
99
@Id private Integer addressId;
10-
private String street;
10+
private Street street;
1111
private Integer version;
1212

1313
public Integer getAddressId() {
@@ -18,11 +18,11 @@ public void setAddressId(Integer addressId) {
1818
this.addressId = addressId;
1919
}
2020

21-
public String getStreet() {
21+
public Street getStreet() {
2222
return street;
2323
}
2424

25-
public void setStreet(String street) {
25+
public void setStreet(Street street) {
2626
this.street = street;
2727
}
2828

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package example;
2+
3+
import org.seasar.doma.Domain;
4+
5+
@Domain(valueType = String.class)
6+
public class Street implements CharSequence {
7+
private final String value;
8+
9+
public Street(String value) {
10+
this.value = value;
11+
}
12+
13+
public String getValue() {
14+
return value;
15+
}
16+
17+
@Override
18+
public int length() {
19+
return value.length();
20+
}
21+
22+
@Override
23+
public char charAt(int index) {
24+
return value.charAt(index);
25+
}
26+
27+
@Override
28+
public CharSequence subSequence(int start, int end) {
29+
return value.subSequence(start, end);
30+
}
31+
}

test-criteria/src/test/java/example/EntityqlSelectTest.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,22 @@ void where_exists_subQuery() {
200200
assertEquals(6, list.size());
201201
}
202202

203+
@Test
204+
void where_like() {
205+
Address_ a = new Address_();
206+
207+
List<Address> list = entityql.from(a).where(c -> c.like(a.street, "%1")).fetch();
208+
assertEquals(2, list.size());
209+
}
210+
211+
@Test
212+
void where_like_null() {
213+
Address_ a = new Address_();
214+
215+
List<Address> list = entityql.from(a).where(c -> c.like(a.street, null)).fetch();
216+
assertEquals(0, list.size());
217+
}
218+
203219
@Test
204220
void innerJoin() {
205221
Employee_ e = new Employee_();

0 commit comments

Comments
 (0)