Skip to content

Commit c341978

Browse files
committed
Make constants more flexible so they can appear
With the refactoring of the functions, we now allow constants to appear anywhere in a column list. Previously they could not appear as the first column.
1 parent 8a7bed9 commit c341978

File tree

8 files changed

+216
-12
lines changed

8 files changed

+216
-12
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ This log will detail notable changes to MyBatis Dynamic SQL. Full details are av
66

77
GitHub milestone: [https://github.com/mybatis/mybatis-dynamic-sql/issues?q=milestone%3A1.1.5+](https://github.com/mybatis/mybatis-dynamic-sql/issues?q=milestone%3A1.1.5+)
88

9+
### General Announcements
10+
11+
This release includes a significant refactoring of the classes in the "org.mybatis.dynamic.sql.select.function" package. The new classes are more consistent and flexible and should be compatible with existing code at the source level (meaning that code should be recompiled for the new version of the library).
12+
13+
If you have written your own set of functions to extend the library, you will notice that the base classes 'AbstractFunction" and "AbstractMultipleColumnArithmeticFunction" are now deprecated. Their replacement classes are "AbstractUniTypeFunction" and "OperatorFunction" respectively.
14+
915
### Added
1016

1117
- Added a general insert statement that does not require a separate record class to hold values for the insert. ([#201](https://github.com/mybatis/mybatis-dynamic-sql/issues/201))

src/main/java/org/mybatis/dynamic/sql/BindableColumn.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,13 @@ public interface BindableColumn<T> extends BasicColumn {
3838
@Override
3939
BindableColumn<T> as(String alias);
4040

41-
Optional<JDBCType> jdbcType();
41+
default Optional<JDBCType> jdbcType() {
42+
return Optional.empty();
43+
}
4244

43-
Optional<String> typeHandler();
45+
default Optional<String> typeHandler() {
46+
return Optional.empty();
47+
}
4448

4549
default Optional<RenderingStrategy> renderingStrategy() {
4650
return Optional.empty();

src/main/java/org/mybatis/dynamic/sql/Constant.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright 2016-2018 the original author or authors.
2+
* Copyright 2016-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -20,7 +20,7 @@
2020

2121
import org.mybatis.dynamic.sql.render.TableAliasCalculator;
2222

23-
public class Constant implements BasicColumn {
23+
public class Constant<T> implements BindableColumn<T> {
2424

2525
private String alias;
2626
private String value;
@@ -40,13 +40,13 @@ public String renderWithTableAlias(TableAliasCalculator tableAliasCalculator) {
4040
}
4141

4242
@Override
43-
public Constant as(String alias) {
44-
Constant copy = new Constant(value);
43+
public Constant<T> as(String alias) {
44+
Constant<T> copy = new Constant<>(value);
4545
copy.alias = alias;
4646
return copy;
4747
}
4848

49-
public static Constant of(String value) {
50-
return new Constant(value);
49+
public static <T> Constant<T> of(String value) {
50+
return new Constant<>(value);
5151
}
5252
}

src/main/java/org/mybatis/dynamic/sql/SqlBuilder.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ static Sum sum(BasicColumn column) {
258258
}
259259

260260
// constants
261-
static Constant constant(String constant) {
261+
static <T> Constant<T> constant(String constant) {
262262
return Constant.of(constant);
263263
}
264264

@@ -292,7 +292,7 @@ static <T> Concatenate<T> concatenate(BindableColumn<T> firstColumn, BasicColumn
292292
return Concatenate.concatenate(firstColumn, secondColumn, subsequentColumns);
293293
}
294294

295-
static <T> OperatorFunction<T> operatorFunction(String operator, BindableColumn<T> firstColumn, BasicColumn secondColumn,
295+
static <T> OperatorFunction<T> applyOperator(String operator, BindableColumn<T> firstColumn, BasicColumn secondColumn,
296296
BasicColumn... subsequentColumns) {
297297
return OperatorFunction.of(operator, firstColumn, secondColumn, subsequentColumns);
298298
}

src/main/java/org/mybatis/dynamic/sql/StringConstant.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright 2016-2018 the original author or authors.
2+
* Copyright 2016-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -20,7 +20,7 @@
2020

2121
import org.mybatis.dynamic.sql.render.TableAliasCalculator;
2222

23-
public class StringConstant implements BasicColumn {
23+
public class StringConstant implements BindableColumn<String> {
2424

2525
private String alias;
2626
private String value;

src/test/java/examples/animal/data/AnimalDataTest.java

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -767,6 +767,36 @@ void testStringConstant() {
767767
}
768768
}
769769

770+
@Test
771+
void testDeprecatedAdd() {
772+
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
773+
AnimalDataMapper mapper = sqlSession.getMapper(AnimalDataMapper.class);
774+
775+
SelectStatementProvider selectStatement = select(id, animalName, DeprecatedAdd.of(bodyWeight, brainWeight).as("calculated_weight"))
776+
.from(animalData, "a")
777+
.where(DeprecatedAdd.of(bodyWeight, brainWeight), isGreaterThan(10000.0))
778+
.build()
779+
.render(RenderingStrategies.MYBATIS3);
780+
781+
String expected = "select a.id, a.animal_name, (a.body_weight + a.brain_weight) as calculated_weight "
782+
+ "from AnimalData a "
783+
+ "where (a.body_weight + a.brain_weight) > #{parameters.p1,jdbcType=DOUBLE}";
784+
785+
List<Map<String, Object>> animals = mapper.generalSelect(selectStatement);
786+
787+
assertAll(
788+
() -> assertThat(selectStatement.getSelectStatement()).isEqualTo(expected),
789+
() -> assertThat(animals).hasSize(3),
790+
() -> assertThat(animals.get(0)).containsEntry("ANIMAL_NAME", "African elephant"),
791+
() -> assertThat(animals.get(0)).containsEntry("CALCULATED_WEIGHT", 12366.0),
792+
() -> assertThat(animals.get(1)).containsEntry("ANIMAL_NAME", "Dipliodocus"),
793+
() -> assertThat(animals.get(1)).containsEntry("CALCULATED_WEIGHT", 11750.0),
794+
() -> assertThat(animals.get(2)).containsEntry("ANIMAL_NAME", "Brachiosaurus"),
795+
() -> assertThat(animals.get(2)).containsEntry("CALCULATED_WEIGHT", 87154.5)
796+
);
797+
}
798+
}
799+
770800
@Test
771801
void testAdd() {
772802
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
@@ -827,6 +857,36 @@ void testAddConstant() {
827857
}
828858
}
829859

860+
@Test
861+
void testAddConstantWithConstantFirst() {
862+
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
863+
AnimalDataMapper mapper = sqlSession.getMapper(AnimalDataMapper.class);
864+
865+
SelectStatementProvider selectStatement = select(id, animalName, add(constant("22"), bodyWeight, constant("33")).as("calculated_weight"))
866+
.from(animalData, "a")
867+
.where(add(bodyWeight, brainWeight), isGreaterThan(10000.0))
868+
.build()
869+
.render(RenderingStrategies.MYBATIS3);
870+
871+
String expected = "select a.id, a.animal_name, (22 + a.body_weight + 33) as calculated_weight "
872+
+ "from AnimalData a "
873+
+ "where (a.body_weight + a.brain_weight) > #{parameters.p1,jdbcType=DOUBLE}";
874+
875+
List<Map<String, Object>> animals = mapper.generalSelect(selectStatement);
876+
877+
assertAll(
878+
() -> assertThat(selectStatement.getSelectStatement()).isEqualTo(expected),
879+
() -> assertThat(animals).hasSize(3),
880+
() -> assertThat(animals.get(0)).containsEntry("ANIMAL_NAME", "African elephant"),
881+
() -> assertThat(animals.get(0)).containsEntry("CALCULATED_WEIGHT", 5767.0),
882+
() -> assertThat(animals.get(1)).containsEntry("ANIMAL_NAME", "Dipliodocus"),
883+
() -> assertThat(animals.get(1)).containsEntry("CALCULATED_WEIGHT", 105.0),
884+
() -> assertThat(animals.get(2)).containsEntry("ANIMAL_NAME", "Brachiosaurus"),
885+
() -> assertThat(animals.get(2)).containsEntry("CALCULATED_WEIGHT", 209.5)
886+
);
887+
}
888+
}
889+
830890
@Test
831891
void testConcatenate() {
832892
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
@@ -854,6 +914,33 @@ void testConcatenate() {
854914
}
855915
}
856916

917+
@Test
918+
void testConcatenateConstantFirst() {
919+
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
920+
AnimalDataMapper mapper = sqlSession.getMapper(AnimalDataMapper.class);
921+
922+
SelectStatementProvider selectStatement = select(id, concatenate(stringConstant("Name: "), animalName).as("display_name"))
923+
.from(animalData, "a")
924+
.where(add(bodyWeight, brainWeight), isGreaterThan(10000.0))
925+
.build()
926+
.render(RenderingStrategies.MYBATIS3);
927+
928+
String expected = "select a.id, ('Name: ' || a.animal_name) as display_name "
929+
+ "from AnimalData a "
930+
+ "where (a.body_weight + a.brain_weight) > #{parameters.p1,jdbcType=DOUBLE}";
931+
932+
List<Map<String, Object>> animals = mapper.generalSelect(selectStatement);
933+
934+
assertAll(
935+
() -> assertThat(selectStatement.getSelectStatement()).isEqualTo(expected),
936+
() -> assertThat(animals).hasSize(3),
937+
() -> assertThat(animals.get(0)).containsEntry("DISPLAY_NAME", "Name: African elephant"),
938+
() -> assertThat(animals.get(1)).containsEntry("DISPLAY_NAME", "Name: Dipliodocus"),
939+
() -> assertThat(animals.get(2)).containsEntry("DISPLAY_NAME", "Name: Brachiosaurus")
940+
);
941+
}
942+
}
943+
857944
@Test
858945
void testDivide() {
859946
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
@@ -1034,6 +1121,36 @@ void testSubtractConstant() {
10341121
}
10351122
}
10361123

1124+
@Test
1125+
void testGeneralOperator() {
1126+
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
1127+
AnimalDataMapper mapper = sqlSession.getMapper(AnimalDataMapper.class);
1128+
1129+
SelectStatementProvider selectStatement = select(id, animalName, applyOperator("-", bodyWeight, brainWeight).as("calculated_weight"))
1130+
.from(animalData, "a")
1131+
.where(add(bodyWeight, brainWeight), isGreaterThan(10000.0))
1132+
.build()
1133+
.render(RenderingStrategies.MYBATIS3);
1134+
1135+
String expected = "select a.id, a.animal_name, (a.body_weight - a.brain_weight) as calculated_weight "
1136+
+ "from AnimalData a "
1137+
+ "where (a.body_weight + a.brain_weight) > #{parameters.p1,jdbcType=DOUBLE}";
1138+
1139+
List<Map<String, Object>> animals = mapper.generalSelect(selectStatement);
1140+
1141+
assertAll(
1142+
() -> assertThat(selectStatement.getSelectStatement()).isEqualTo(expected),
1143+
() -> assertThat(animals).hasSize(3),
1144+
() -> assertThat(animals.get(0)).containsEntry("ANIMAL_NAME", "African elephant"),
1145+
() -> assertThat(animals.get(0)).containsEntry("CALCULATED_WEIGHT", -942.0),
1146+
() -> assertThat(animals.get(1)).containsEntry("ANIMAL_NAME", "Dipliodocus"),
1147+
() -> assertThat(animals.get(1)).containsEntry("CALCULATED_WEIGHT", -11650.0),
1148+
() -> assertThat(animals.get(2)).containsEntry("ANIMAL_NAME", "Brachiosaurus"),
1149+
() -> assertThat(animals.get(2)).containsEntry("CALCULATED_WEIGHT", -86845.5)
1150+
);
1151+
}
1152+
}
1153+
10371154
@Test
10381155
void testComplexExpression() {
10391156
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/**
2+
* Copyright 2016-2020 the original author or 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+
* http://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 examples.animal.data;
17+
18+
import java.util.Arrays;
19+
import java.util.List;
20+
21+
import org.mybatis.dynamic.sql.BasicColumn;
22+
import org.mybatis.dynamic.sql.BindableColumn;
23+
import org.mybatis.dynamic.sql.select.function.AbstractMultipleColumnArithmeticFunction;
24+
25+
public class DeprecatedAdd<T extends Number> extends AbstractMultipleColumnArithmeticFunction<T, DeprecatedAdd<T>> {
26+
27+
private DeprecatedAdd(BindableColumn<T> firstColumn, BasicColumn secondColumn,
28+
List<BasicColumn> subsequentColumns) {
29+
super(firstColumn, secondColumn, subsequentColumns);
30+
}
31+
32+
@Override
33+
protected DeprecatedAdd<T> copy() {
34+
return new DeprecatedAdd<>(column, secondColumn, subsequentColumns);
35+
}
36+
37+
@Override
38+
protected String operator() {
39+
return "+"; //$NON-NLS-1$
40+
}
41+
42+
public static <T extends Number> DeprecatedAdd<T> of(BindableColumn<T> firstColumn, BasicColumn secondColumn,
43+
BasicColumn... subsequentColumns) {
44+
return new DeprecatedAdd<>(firstColumn, secondColumn, Arrays.asList(subsequentColumns));
45+
}
46+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/**
2+
* Copyright 2016-2020 the original author or 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+
* http://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.mybatis.dynamic.sql;
17+
18+
import static org.assertj.core.api.Assertions.assertThat;
19+
20+
import org.junit.jupiter.api.Test;
21+
22+
class BindableColumnTest {
23+
24+
@Test
25+
void testDefaultFunctions() {
26+
StringConstant constant = StringConstant.of("Fred");
27+
28+
assertThat(constant.jdbcType()).isEmpty();
29+
assertThat(constant.typeHandler()).isEmpty();
30+
}
31+
}

0 commit comments

Comments
 (0)