Skip to content

Commit 31f0906

Browse files
authored
Merge pull request #431 from domaframework/string-functions
Add some string expressions:
2 parents 4dd591a + c54627f commit 31f0906

File tree

4 files changed

+249
-22
lines changed

4 files changed

+249
-22
lines changed

doma-core/src/main/java/org/seasar/doma/jdbc/criteria/expression/Expressions.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,36 @@ public static <PROPERTY> StringExpression.Concat<PROPERTY> concat(
142142
return new StringExpression.Concat<>(left, new Operand.Prop(left), new Operand.Prop(right));
143143
}
144144

145+
public static <PROPERTY> StringExpression.Lower<PROPERTY> lower(
146+
PropertyMetamodel<PROPERTY> propertyMetamodel) {
147+
Objects.requireNonNull(propertyMetamodel);
148+
return new StringExpression.Lower<>(propertyMetamodel);
149+
}
150+
151+
public static <PROPERTY> StringExpression.Ltrim<PROPERTY> ltrim(
152+
PropertyMetamodel<PROPERTY> propertyMetamodel) {
153+
Objects.requireNonNull(propertyMetamodel);
154+
return new StringExpression.Ltrim<>(propertyMetamodel);
155+
}
156+
157+
public static <PROPERTY> StringExpression.Rtrim<PROPERTY> rtrim(
158+
PropertyMetamodel<PROPERTY> propertyMetamodel) {
159+
Objects.requireNonNull(propertyMetamodel);
160+
return new StringExpression.Rtrim<>(propertyMetamodel);
161+
}
162+
163+
public static <PROPERTY> StringExpression.Trim<PROPERTY> trim(
164+
PropertyMetamodel<PROPERTY> propertyMetamodel) {
165+
Objects.requireNonNull(propertyMetamodel);
166+
return new StringExpression.Trim<>(propertyMetamodel);
167+
}
168+
169+
public static <PROPERTY> StringExpression.Upper<PROPERTY> upper(
170+
PropertyMetamodel<PROPERTY> propertyMetamodel) {
171+
Objects.requireNonNull(propertyMetamodel);
172+
return new StringExpression.Upper<>(propertyMetamodel);
173+
}
174+
145175
public static <PROPERTY> AggregateFunction.Avg<PROPERTY> avg(
146176
PropertyMetamodel<PROPERTY> propertyMetamodel) {
147177
Objects.requireNonNull(propertyMetamodel);

doma-core/src/main/java/org/seasar/doma/jdbc/criteria/expression/StringExpression.java

Lines changed: 141 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,61 @@
77

88
public interface StringExpression<PROPERTY> extends PropertyMetamodel<PROPERTY> {
99

10-
abstract class AbstractStringExpression<PROPERTY> implements StringExpression<PROPERTY> {
10+
abstract class OneArgumentStringExpression<PROPERTY> implements StringExpression<PROPERTY> {
11+
private final String name;
12+
public final PropertyMetamodel<?> argument;
13+
14+
protected OneArgumentStringExpression(String name, PropertyMetamodel<?> argument) {
15+
this.name = Objects.requireNonNull(name);
16+
this.argument = Objects.requireNonNull(argument);
17+
}
18+
19+
@Override
20+
public String getName() {
21+
return name;
22+
}
23+
24+
@Override
25+
public Class<?> asClass() {
26+
return argument.asClass();
27+
}
28+
29+
@Override
30+
public EntityPropertyType<?, ?> asType() {
31+
return argument.asType();
32+
}
33+
34+
@Override
35+
public boolean equals(Object o) {
36+
if (this == o) return true;
37+
if (!(o instanceof StringExpression.OneArgumentStringExpression)) return false;
38+
OneArgumentStringExpression<?> that = (OneArgumentStringExpression<?>) o;
39+
return argument.equals(that.argument);
40+
}
41+
42+
@Override
43+
public int hashCode() {
44+
return Objects.hash(argument);
45+
}
46+
}
47+
48+
abstract class TwoArgumentsStringExpression<PROPERTY> implements StringExpression<PROPERTY> {
49+
private final String name;
1150
private final PropertyMetamodel<?> propertyMetamodel;
12-
public final Operand left;
13-
public final Operand right;
51+
public final Operand first;
52+
public final Operand second;
1453

15-
protected AbstractStringExpression(
16-
PropertyMetamodel<?> propertyMetamodel, Operand left, Operand right) {
54+
protected TwoArgumentsStringExpression(
55+
String name, PropertyMetamodel<?> propertyMetamodel, Operand first, Operand second) {
56+
this.name = Objects.requireNonNull(name);
1757
this.propertyMetamodel = Objects.requireNonNull(propertyMetamodel);
18-
this.left = Objects.requireNonNull(left);
19-
this.right = Objects.requireNonNull(right);
58+
this.first = Objects.requireNonNull(first);
59+
this.second = Objects.requireNonNull(second);
60+
}
61+
62+
@Override
63+
public String getName() {
64+
return name;
2065
}
2166

2267
@Override
@@ -32,28 +77,98 @@ public Class<?> asClass() {
3277
@Override
3378
public boolean equals(Object o) {
3479
if (this == o) return true;
35-
if (!(o instanceof StringExpression.AbstractStringExpression)) return false;
36-
AbstractStringExpression<?> that = (AbstractStringExpression<?>) o;
80+
if (!(o instanceof StringExpression.TwoArgumentsStringExpression)) return false;
81+
TwoArgumentsStringExpression<?> that = (TwoArgumentsStringExpression<?>) o;
3782
return propertyMetamodel.equals(that.propertyMetamodel)
38-
&& left.equals(that.left)
39-
&& right.equals(that.right);
83+
&& first.equals(that.first)
84+
&& second.equals(that.second);
4085
}
4186

4287
@Override
4388
public int hashCode() {
44-
return Objects.hash(propertyMetamodel, left, right);
89+
return Objects.hash(propertyMetamodel, first, second);
4590
}
4691
}
4792

48-
class Concat<PROPERTY> extends AbstractStringExpression<PROPERTY> {
93+
class Concat<PROPERTY> extends TwoArgumentsStringExpression<PROPERTY> {
4994

5095
public Concat(PropertyMetamodel<?> propertyMetamodel, Operand left, Operand right) {
51-
super(propertyMetamodel, left, right);
96+
super("concat", propertyMetamodel, left, right);
5297
}
5398

5499
@Override
55-
public String getName() {
56-
return "concat";
100+
public void accept(PropertyMetamodel.Visitor visitor) {
101+
if (visitor instanceof StringExpression.Visitor) {
102+
StringExpression.Visitor v = (StringExpression.Visitor) visitor;
103+
v.visit(this);
104+
}
105+
}
106+
}
107+
108+
class Lower<PROPERTY> extends OneArgumentStringExpression<PROPERTY> {
109+
110+
public Lower(PropertyMetamodel<?> propertyMetamodel) {
111+
super("lower", propertyMetamodel);
112+
}
113+
114+
@Override
115+
public void accept(PropertyMetamodel.Visitor visitor) {
116+
if (visitor instanceof StringExpression.Visitor) {
117+
StringExpression.Visitor v = (StringExpression.Visitor) visitor;
118+
v.visit(this);
119+
}
120+
}
121+
}
122+
123+
class Ltrim<PROPERTY> extends OneArgumentStringExpression<PROPERTY> {
124+
125+
public Ltrim(PropertyMetamodel<?> propertyMetamodel) {
126+
super("ltrim", propertyMetamodel);
127+
}
128+
129+
@Override
130+
public void accept(PropertyMetamodel.Visitor visitor) {
131+
if (visitor instanceof StringExpression.Visitor) {
132+
StringExpression.Visitor v = (StringExpression.Visitor) visitor;
133+
v.visit(this);
134+
}
135+
}
136+
}
137+
138+
class Rtrim<PROPERTY> extends OneArgumentStringExpression<PROPERTY> {
139+
140+
public Rtrim(PropertyMetamodel<?> propertyMetamodel) {
141+
super("rtrim", propertyMetamodel);
142+
}
143+
144+
@Override
145+
public void accept(PropertyMetamodel.Visitor visitor) {
146+
if (visitor instanceof StringExpression.Visitor) {
147+
StringExpression.Visitor v = (StringExpression.Visitor) visitor;
148+
v.visit(this);
149+
}
150+
}
151+
}
152+
153+
class Trim<PROPERTY> extends OneArgumentStringExpression<PROPERTY> {
154+
155+
public Trim(PropertyMetamodel<?> propertyMetamodel) {
156+
super("trim", propertyMetamodel);
157+
}
158+
159+
@Override
160+
public void accept(PropertyMetamodel.Visitor visitor) {
161+
if (visitor instanceof StringExpression.Visitor) {
162+
StringExpression.Visitor v = (StringExpression.Visitor) visitor;
163+
v.visit(this);
164+
}
165+
}
166+
}
167+
168+
class Upper<PROPERTY> extends OneArgumentStringExpression<PROPERTY> {
169+
170+
public Upper(PropertyMetamodel<?> propertyMetamodel) {
171+
super("upper", propertyMetamodel);
57172
}
58173

59174
@Override
@@ -67,5 +182,15 @@ public void accept(PropertyMetamodel.Visitor visitor) {
67182

68183
interface Visitor {
69184
void visit(StringExpression.Concat<?> concat);
185+
186+
void visit(StringExpression.Lower<?> lower);
187+
188+
void visit(StringExpression.Ltrim<?> ltrim);
189+
190+
void visit(StringExpression.Rtrim<?> rtrim);
191+
192+
void visit(StringExpression.Trim<?> trim);
193+
194+
void visit(StringExpression.Upper<?> upper);
70195
}
71196
}

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

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -514,7 +514,34 @@ public void visit(ArithmeticExpression.Mod<?> mod) {
514514
public void visit(StringExpression.Concat<?> concat) {
515515
CriteriaBuilder criteriaBuilder = config.getDialect().getCriteriaBuilder();
516516
criteriaBuilder.concat(
517-
buf, () -> concat.left.accept(operandVisitor), () -> concat.right.accept(operandVisitor));
517+
buf,
518+
() -> concat.first.accept(operandVisitor),
519+
() -> concat.second.accept(operandVisitor));
520+
}
521+
522+
@Override
523+
public void visit(StringExpression.Lower<?> lower) {
524+
oneArgumentFunction(lower.getName(), lower.argument);
525+
}
526+
527+
@Override
528+
public void visit(StringExpression.Ltrim<?> ltrim) {
529+
oneArgumentFunction(ltrim.getName(), ltrim.argument);
530+
}
531+
532+
@Override
533+
public void visit(StringExpression.Rtrim<?> rtrim) {
534+
oneArgumentFunction(rtrim.getName(), rtrim.argument);
535+
}
536+
537+
@Override
538+
public void visit(StringExpression.Trim<?> trim) {
539+
oneArgumentFunction(trim.getName(), trim.argument);
540+
}
541+
542+
@Override
543+
public void visit(StringExpression.Upper<?> upper) {
544+
oneArgumentFunction(upper.getName(), upper.argument);
518545
}
519546

520547
@Override
@@ -529,7 +556,7 @@ public void visit(LiteralExpression.IntLiteral intLiteral) {
529556

530557
@Override
531558
public void visit(AggregateFunction.Avg<?> avg) {
532-
aggregateFunction(avg.getName(), avg.argument());
559+
oneArgumentFunction(avg.getName(), avg.argument());
533560
}
534561

535562
@Override
@@ -545,17 +572,17 @@ public void visit(AggregateFunction.Count count) {
545572

546573
@Override
547574
public void visit(AggregateFunction.Max<?> max) {
548-
aggregateFunction(max.getName(), max.argument());
575+
oneArgumentFunction(max.getName(), max.argument());
549576
}
550577

551578
@Override
552579
public void visit(AggregateFunction.Min<?> min) {
553-
aggregateFunction(min.getName(), min.argument());
580+
oneArgumentFunction(min.getName(), min.argument());
554581
}
555582

556583
@Override
557584
public void visit(AggregateFunction.Sum<?> sum) {
558-
aggregateFunction(sum.getName(), sum.argument());
585+
oneArgumentFunction(sum.getName(), sum.argument());
559586
}
560587

561588
@Override
@@ -571,7 +598,7 @@ private void binaryOperator(String operator, Operand left, Operand right) {
571598
buf.appendSql(")");
572599
}
573600

574-
private void aggregateFunction(String name, PropertyMetamodel<?> argument) {
601+
private void oneArgumentFunction(String name, PropertyMetamodel<?> argument) {
575602
buf.appendSql(name);
576603
buf.appendSql("(");
577604
argument.accept(this);

doma-core/src/test/java/org/seasar/doma/jdbc/criteria/NativeSqlSelectTest.java

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,14 @@
66
import static org.seasar.doma.jdbc.criteria.expression.Expressions.count;
77
import static org.seasar.doma.jdbc.criteria.expression.Expressions.countDistinct;
88
import static org.seasar.doma.jdbc.criteria.expression.Expressions.literal;
9+
import static org.seasar.doma.jdbc.criteria.expression.Expressions.lower;
10+
import static org.seasar.doma.jdbc.criteria.expression.Expressions.ltrim;
911
import static org.seasar.doma.jdbc.criteria.expression.Expressions.max;
1012
import static org.seasar.doma.jdbc.criteria.expression.Expressions.min;
13+
import static org.seasar.doma.jdbc.criteria.expression.Expressions.rtrim;
1114
import static org.seasar.doma.jdbc.criteria.expression.Expressions.sum;
15+
import static org.seasar.doma.jdbc.criteria.expression.Expressions.trim;
16+
import static org.seasar.doma.jdbc.criteria.expression.Expressions.upper;
1217

1318
import java.math.BigDecimal;
1419
import java.util.Arrays;
@@ -1134,6 +1139,46 @@ public Dialect getDialect() {
11341139
assertEquals("select (t0_.NAME + 'a') from EMP t0_", sql.getFormattedSql());
11351140
}
11361141

1142+
@Test
1143+
void expression_lower() {
1144+
Emp_ e = new Emp_();
1145+
Buildable<?> stmt = nativeSql.from(e).select(lower(e.name));
1146+
Sql<?> sql = stmt.asSql();
1147+
assertEquals("select lower(t0_.NAME) from EMP t0_", sql.getFormattedSql());
1148+
}
1149+
1150+
@Test
1151+
void expression_ltrim() {
1152+
Emp_ e = new Emp_();
1153+
Buildable<?> stmt = nativeSql.from(e).select(ltrim(e.name));
1154+
Sql<?> sql = stmt.asSql();
1155+
assertEquals("select ltrim(t0_.NAME) from EMP t0_", sql.getFormattedSql());
1156+
}
1157+
1158+
@Test
1159+
void expression_rtrim() {
1160+
Emp_ e = new Emp_();
1161+
Buildable<?> stmt = nativeSql.from(e).select(rtrim(e.name));
1162+
Sql<?> sql = stmt.asSql();
1163+
assertEquals("select rtrim(t0_.NAME) from EMP t0_", sql.getFormattedSql());
1164+
}
1165+
1166+
@Test
1167+
void expression_trim() {
1168+
Emp_ e = new Emp_();
1169+
Buildable<?> stmt = nativeSql.from(e).select(trim(e.name));
1170+
Sql<?> sql = stmt.asSql();
1171+
assertEquals("select trim(t0_.NAME) from EMP t0_", sql.getFormattedSql());
1172+
}
1173+
1174+
@Test
1175+
void expression_upper() {
1176+
Emp_ e = new Emp_();
1177+
Buildable<?> stmt = nativeSql.from(e).select(upper(e.name));
1178+
Sql<?> sql = stmt.asSql();
1179+
assertEquals("select upper(t0_.NAME) from EMP t0_", sql.getFormattedSql());
1180+
}
1181+
11371182
@Test
11381183
void expression_stringLiteral() {
11391184
Emp_ e = new Emp_();

0 commit comments

Comments
 (0)