View Javadoc
1   /*
2    *    Copyright 2016-2025 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    *       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.mybatis.dynamic.sql.update;
17  
18  import static org.assertj.core.api.Assertions.assertThat;
19  import static org.junit.jupiter.api.Assertions.assertAll;
20  import static org.mybatis.dynamic.sql.SqlBuilder.*;
21  
22  import java.sql.JDBCType;
23  
24  import org.junit.jupiter.api.Test;
25  import org.mybatis.dynamic.sql.SqlColumn;
26  import org.mybatis.dynamic.sql.SqlTable;
27  import org.mybatis.dynamic.sql.render.RenderingStrategies;
28  import org.mybatis.dynamic.sql.update.render.UpdateStatementProvider;
29  
30  class UpdateStatementTest {
31      private static final SqlTable foo = SqlTable.of("foo");
32      private static final SqlColumn<Integer> id = foo.column("id", JDBCType.INTEGER);
33      private static final SqlColumn<String> firstName = foo.column("firstName", JDBCType.VARCHAR);
34      private static final SqlColumn<String> lastName = foo.column("lastName", JDBCType.VARCHAR);
35      private static final SqlColumn<String> occupation = foo.column("occupation", JDBCType.VARCHAR);
36  
37      @Test
38      void testUpdateParameterWithMultipleCriteria() {
39          UpdateStatementProvider updateStatement = update(foo)
40                  .set(firstName).equalTo("fred")
41                  .set(lastName).equalTo("jones")
42                  .set(occupation).equalToNull()
43                  .where(id, isEqualTo(3), or(id, isEqualTo(4)), or(id, isEqualTo(5)))
44                  .build()
45                  .render(RenderingStrategies.MYBATIS3);
46  
47          String expected = "update foo set firstName = #{parameters.p1,jdbcType=VARCHAR}, lastName = #{parameters.p2,jdbcType=VARCHAR}, occupation = null "
48                  + "where id = #{parameters.p3,jdbcType=INTEGER} or id = #{parameters.p4,jdbcType=INTEGER} or id = #{parameters.p5,jdbcType=INTEGER}";
49  
50          assertAll(
51                  () -> assertThat(updateStatement.getUpdateStatement()).isEqualTo(expected),
52                  () -> assertThat(updateStatement.getParameters()).hasSize(5),
53                  () -> assertThat(updateStatement.getParameters()).containsEntry("p1", "fred"),
54                  () -> assertThat(updateStatement.getParameters()).containsEntry("p2", "jones"),
55                  () -> assertThat(updateStatement.getParameters()).containsEntry("p3", 3),
56                  () -> assertThat(updateStatement.getParameters()).containsEntry("p4", 4),
57                  () -> assertThat(updateStatement.getParameters()).containsEntry("p5", 5)
58          );
59      }
60  
61      @Test
62      void testUpdateParameterWithMultipleNestedCriteria() {
63          UpdateStatementProvider updateStatement = update(foo)
64                  .set(firstName).equalTo("fred")
65                  .set(lastName).equalTo("jones")
66                  .set(occupation).equalToNull()
67                  .where(id, isEqualTo(3), or(id, isEqualTo(4), or(id, isEqualTo(5))))
68                  .build()
69                  .render(RenderingStrategies.MYBATIS3);
70  
71          String expected = "update foo set firstName = #{parameters.p1,jdbcType=VARCHAR}, lastName = #{parameters.p2,jdbcType=VARCHAR}, occupation = null "
72                  + "where id = #{parameters.p3,jdbcType=INTEGER} or (id = #{parameters.p4,jdbcType=INTEGER} or id = #{parameters.p5,jdbcType=INTEGER})";
73  
74          assertAll(
75                  () -> assertThat(updateStatement.getUpdateStatement()).isEqualTo(expected),
76                  () -> assertThat(updateStatement.getParameters()).hasSize(5),
77                  () -> assertThat(updateStatement.getParameters()).containsEntry("p1", "fred"),
78                  () -> assertThat(updateStatement.getParameters()).containsEntry("p2", "jones"),
79                  () -> assertThat(updateStatement.getParameters()).containsEntry("p3", 3),
80                  () -> assertThat(updateStatement.getParameters()).containsEntry("p4", 4),
81                  () -> assertThat(updateStatement.getParameters()).containsEntry("p5", 5)
82          );
83      }
84  
85      @Test
86      void testUpdateParameterStartWithNull() {
87          UpdateStatementProvider updateStatement = update(foo)
88                  .set(occupation).equalToNull()
89                  .set(firstName).equalTo("fred")
90                  .set(lastName).equalTo("jones")
91                  .where(id, isEqualTo(3))
92                  .and(firstName, isEqualTo("barney"))
93                  .build()
94                  .render(RenderingStrategies.MYBATIS3);
95  
96          String expected = "update foo set occupation = null, firstName = #{parameters.p1,jdbcType=VARCHAR}, lastName = #{parameters.p2,jdbcType=VARCHAR} "
97                  + "where id = #{parameters.p3,jdbcType=INTEGER} and firstName = #{parameters.p4,jdbcType=VARCHAR}";
98  
99          assertAll(
100                 () -> assertThat(updateStatement.getUpdateStatement()).isEqualTo(expected),
101                 () -> assertThat(updateStatement.getParameters()).hasSize(4),
102                 () -> assertThat(updateStatement.getParameters()).containsEntry("p1", "fred"),
103                 () -> assertThat(updateStatement.getParameters()).containsEntry("p2", "jones"),
104                 () -> assertThat(updateStatement.getParameters()).containsEntry("p3", 3),
105                 () -> assertThat(updateStatement.getParameters()).containsEntry("p4", "barney")
106         );
107     }
108 
109     @Test
110     void testUpdateParameterStartWithConstant() {
111         UpdateStatementProvider updateStatement = update(foo)
112                 .set(occupation).equalToStringConstant("Y")
113                 .set(firstName).equalTo("fred")
114                 .set(lastName).equalTo("jones")
115                 .set(id).equalToConstant("4")
116                 .where(id, isEqualTo(3))
117                 .and(firstName, isEqualTo("barney"))
118                 .build()
119                 .render(RenderingStrategies.MYBATIS3);
120 
121         String expected = "update foo set occupation = 'Y', firstName = #{parameters.p1,jdbcType=VARCHAR}, lastName = #{parameters.p2,jdbcType=VARCHAR}, id = 4 "
122                 + "where id = #{parameters.p3,jdbcType=INTEGER} and firstName = #{parameters.p4,jdbcType=VARCHAR}";
123 
124         assertAll(
125                 () -> assertThat(updateStatement.getUpdateStatement()).isEqualTo(expected),
126                 () -> assertThat(updateStatement.getParameters()).hasSize(4),
127                 () -> assertThat(updateStatement.getParameters()).containsEntry("p1", "fred"),
128                 () -> assertThat(updateStatement.getParameters()).containsEntry("p2", "jones"),
129                 () -> assertThat(updateStatement.getParameters()).containsEntry("p3", 3),
130                 () -> assertThat(updateStatement.getParameters()).containsEntry("p4", "barney")
131         );
132     }
133 
134     @Test
135     void testFullUpdateStatement() {
136         UpdateStatementProvider updateStatement = update(foo)
137                 .set(firstName).equalTo("fred")
138                 .set(lastName).equalTo("jones")
139                 .set(occupation).equalToNull()
140                 .where(id, isEqualTo(3))
141                 .build()
142                 .render(RenderingStrategies.MYBATIS3);
143 
144         String expectedStatement = "update foo "
145                 + "set firstName = #{parameters.p1,jdbcType=VARCHAR}, lastName = #{parameters.p2,jdbcType=VARCHAR}, occupation = null "
146                 + "where id = #{parameters.p3,jdbcType=INTEGER}";
147 
148         assertAll(
149                 () -> assertThat(updateStatement.getUpdateStatement()).isEqualTo(expectedStatement),
150                 () -> assertThat(updateStatement.getParameters()).hasSize(3),
151                 () -> assertThat(updateStatement.getParameters()).containsEntry("p1", "fred"),
152                 () -> assertThat(updateStatement.getParameters()).containsEntry("p2", "jones"),
153                 () -> assertThat(updateStatement.getParameters()).containsEntry("p3", 3)
154         );
155     }
156 
157     @Test
158     void testFullUpdateStatementNoWhere() {
159         UpdateStatementProvider updateStatement = update(foo)
160                 .set(firstName).equalTo("fred")
161                 .set(lastName).equalTo("jones")
162                 .set(occupation).equalToNull()
163                 .build()
164                 .render(RenderingStrategies.MYBATIS3);
165 
166         String expectedStatement = "update foo "
167                 + "set firstName = #{parameters.p1,jdbcType=VARCHAR}, lastName = #{parameters.p2,jdbcType=VARCHAR}, occupation = null";
168 
169         assertAll(
170                 () -> assertThat(updateStatement.getUpdateStatement()).isEqualTo(expectedStatement),
171                 () -> assertThat(updateStatement.getParameters()).hasSize(2),
172                 () -> assertThat(updateStatement.getParameters()).containsEntry("p1", "fred"),
173                 () -> assertThat(updateStatement.getParameters()).containsEntry("p2", "jones")
174         );
175     }
176 
177     @Test
178     void testUpdateStatementArithmeticOperation() {
179         UpdateStatementProvider updateStatement = update(foo)
180                 .set(id).equalTo(add(id, constant("1")))
181                 .set(id).equalTo(subtract(id, constant("2")))
182                 .set(id).equalTo(multiply(id, constant("3")))
183                 .set(id).equalTo(divide(id, constant("4")))
184                 .build()
185                 .render(RenderingStrategies.MYBATIS3);
186 
187         String expectedStatement = "update foo "
188                 + "set id = (id + 1), "
189                 + "id = (id - 2), "
190                 + "id = (id * 3), "
191                 + "id = (id / 4)";
192 
193         assertAll(
194                 () -> assertThat(updateStatement.getUpdateStatement()).isEqualTo(expectedStatement),
195                 () -> assertThat(updateStatement.getParameters()).isEmpty()
196         );
197     }
198 
199     @Test
200     void testUpdateSelectStatement() {
201         UpdateStatementProvider updateStatement = update(foo)
202                 .set(lastName).equalTo("Jones")
203                 .set(firstName).equalTo(select(firstName).from(foo).where(id, isEqualTo(4)))
204                 .where(id, isEqualTo(3))
205                 .build()
206                 .render(RenderingStrategies.MYBATIS3);
207 
208         String expectedStatement = "update foo "
209                 + "set lastName = #{parameters.p1,jdbcType=VARCHAR}, firstName = (select firstName from foo where id = #{parameters.p2,jdbcType=INTEGER}) "
210                 + "where id = #{parameters.p3,jdbcType=INTEGER}";
211 
212         assertAll(
213                 () -> assertThat(updateStatement.getUpdateStatement()).isEqualTo(expectedStatement),
214                 () -> assertThat(updateStatement.getParameters()).hasSize(3),
215                 () -> assertThat(updateStatement.getParameters()).containsEntry("p1", "Jones"),
216                 () -> assertThat(updateStatement.getParameters()).containsEntry("p2", 4),
217                 () -> assertThat(updateStatement.getParameters()).containsEntry("p3", 3)
218         );
219     }
220 }