allValValues = bindValueCaptor.getAllValues();
+ assertEquals(Arrays.asList("index", "__frch_index_0", "item", "__frch_item_0",
+ "index", "__frch_index_0", "item", "__frch_item_0",
+ "index", "__frch_index_0", "item", "__frch_item_0"), allKeyValues);
+ assertEquals(Arrays.asList(0, 0, "a", "a",
+ 1, 1, "b", "b",
+ 2, 2, "c", "c"), allValValues);
+ }
+}
diff --git a/src/test/java/org/apache/ibatis/scripting/xmltags/IfSqlNodeTest.java b/src/test/java/org/apache/ibatis/scripting/xmltags/IfSqlNodeTest.java
new file mode 100644
index 00000000000..4e7760f667c
--- /dev/null
+++ b/src/test/java/org/apache/ibatis/scripting/xmltags/IfSqlNodeTest.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2009-2024 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ibatis.scripting.xmltags;
+
+import java.util.HashMap;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+/**
+ * {@code
+ * mawen12
+ * @see if
+ */
+class IfSqlNodeTest extends SqlNodeTest {
+
+ private static final String CONDITION = "title != null";
+ private static final String TEXT = "AND title like #{title}";
+
+ private SqlNode sqlNode;
+
+ @BeforeEach
+ void setup() {
+ SqlNode contents = new StaticTextSqlNode(TEXT);
+ this.sqlNode = new IfSqlNode(contents, CONDITION);
+ }
+
+ @Test
+ @Override
+ public void shouldApply() throws Exception {
+ when(context.getBindings()).thenReturn(new HashMap<>() {{
+ put("title", "ENGLISH");
+ }});
+
+ boolean result = sqlNode.apply(context);
+
+ assertTrue(result);
+ verify(context).appendSql(TEXT);
+ }
+
+ @Test
+ public void shouldAppendNone() {
+ when(context.getBindings()).thenReturn(new HashMap<>() {{
+ put("title", null);
+ }});
+
+ boolean result = sqlNode.apply(context);
+
+ assertFalse(result);
+ verify(context, never()).appendSql(TEXT);
+ }
+}
diff --git a/src/test/java/org/apache/ibatis/scripting/xmltags/MixedSqlNodeTest.java b/src/test/java/org/apache/ibatis/scripting/xmltags/MixedSqlNodeTest.java
new file mode 100644
index 00000000000..0c5579d823f
--- /dev/null
+++ b/src/test/java/org/apache/ibatis/scripting/xmltags/MixedSqlNodeTest.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2009-2024 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ibatis.scripting.xmltags;
+
+import java.util.Arrays;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.mockito.Mockito.*;
+
+/**
+ * @author mawen12
+ */
+class MixedSqlNodeTest extends SqlNodeTest{
+
+ private static final String FIRST_TEXT = "abc";
+ private static final String SECOND_TEXT = "bcd";
+ private SqlNode sqlNode;
+
+ @BeforeEach
+ void setup() {
+ SqlNode first = new StaticTextSqlNode(FIRST_TEXT);
+ SqlNode second = new StaticTextSqlNode(SECOND_TEXT);
+ this.sqlNode = new MixedSqlNode(Arrays.asList(first, second));
+ }
+
+ @Test
+ @Override
+ public void shouldApply() throws Exception {
+ sqlNode.apply(context);
+
+ verify(context).appendSql("abc");
+ verify(context).appendSql("bcd");
+ }
+}
diff --git a/src/test/java/org/apache/ibatis/scripting/xmltags/SetSqlNodeTest.java b/src/test/java/org/apache/ibatis/scripting/xmltags/SetSqlNodeTest.java
new file mode 100644
index 00000000000..0249804d242
--- /dev/null
+++ b/src/test/java/org/apache/ibatis/scripting/xmltags/SetSqlNodeTest.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2009-2024 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ibatis.scripting.xmltags;
+
+import java.util.Arrays;
+import java.util.HashMap;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+/**
+ * {@code
+ * UPDATE author
+ *
+ *
+ * password = #{password}
+ *
+ *
+ * WHERE id = #{id}
+ * }
+ *
+ * @author mawen12
+ * @see trim-where-set
+ */
+class SetSqlNodeTest extends SqlNodeTest {
+
+ private static final String FIRST_TEXT = " username = #{username},";
+ private static final String SECOND_TEXT = " password = #{password}";
+
+ private SqlNode sqlNode;
+
+ @BeforeEach
+ void setup() {
+ SqlNode first = new IfSqlNode(new StaticTextSqlNode(FIRST_TEXT), "username != null");
+ SqlNode second = new IfSqlNode(new StaticTextSqlNode(SECOND_TEXT), "password != null");
+ SqlNode contents = new MixedSqlNode(Arrays.asList(first, second));
+
+ this.sqlNode = new SetSqlNode(configuration, contents);
+ }
+
+ @Test
+ @Override
+ public void shouldApply() throws Exception {
+ when(context.getBindings()).thenReturn(new HashMap<>(){{
+ put("username", "Jack");
+ put("password", "***");
+ }});
+
+ boolean result = sqlNode.apply(context);
+
+ assertTrue(result);
+ verify(context).appendSql("SET username = #{username}, password = #{password}");
+ }
+
+ @Test
+ public void shouldAppendOnlyUsername() throws Exception {
+ when(context.getBindings()).thenReturn(new HashMap<>(){{
+ put("username", "Jack");
+ }});
+
+ boolean result = sqlNode.apply(context);
+
+ assertTrue(result);
+ verify(context).appendSql("SET username = #{username}");
+ }
+
+ @Test
+ public void shouldAppendOnlyPassword() throws Exception {
+ when(context.getBindings()).thenReturn(new HashMap<>(){{
+ put("password", "***");
+ }});
+
+ boolean result = sqlNode.apply(context);
+
+ assertTrue(result);
+ verify(context).appendSql("SET password = #{password}");
+ }
+
+ @Test
+ public void shouldAppendNone() throws Exception {
+ when(context.getBindings()).thenReturn(new HashMap<>());
+
+ boolean result = sqlNode.apply(context);
+
+ assertTrue(result);
+ verify(context).appendSql("");
+ }
+}
diff --git a/src/test/java/org/apache/ibatis/scripting/xmltags/SqlNodeTest.java b/src/test/java/org/apache/ibatis/scripting/xmltags/SqlNodeTest.java
new file mode 100644
index 00000000000..8d3355209fc
--- /dev/null
+++ b/src/test/java/org/apache/ibatis/scripting/xmltags/SqlNodeTest.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2009-2024 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ibatis.scripting.xmltags;
+
+import org.apache.ibatis.session.Configuration;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+/**
+ * @author mawen12
+ */
+@ExtendWith(MockitoExtension.class)
+abstract class SqlNodeTest {
+
+ @Mock
+ protected Configuration configuration;
+
+ @Mock
+ protected DynamicContext context;
+
+ public abstract void shouldApply() throws Exception;
+}
diff --git a/src/test/java/org/apache/ibatis/scripting/xmltags/StaticTextSqlNodeTest.java b/src/test/java/org/apache/ibatis/scripting/xmltags/StaticTextSqlNodeTest.java
new file mode 100644
index 00000000000..e94ae5ec0b9
--- /dev/null
+++ b/src/test/java/org/apache/ibatis/scripting/xmltags/StaticTextSqlNodeTest.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2009-2024 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ibatis.scripting.xmltags;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+/**
+ * @author mawen12
+ */
+class StaticTextSqlNodeTest extends SqlNodeTest {
+
+ private static final String TEXT = "select 1 from dual";
+
+ @Test
+ @Override
+ public void shouldApply() throws Exception {
+ // given
+ SqlNode sqlNode = new StaticTextSqlNode(TEXT);
+
+ //when
+ boolean result = sqlNode.apply(context);
+
+ // then
+ assertTrue(result);
+ verify(context).appendSql(TEXT);
+ }
+}
diff --git a/src/test/java/org/apache/ibatis/scripting/xmltags/TextSqlNodeTest.java b/src/test/java/org/apache/ibatis/scripting/xmltags/TextSqlNodeTest.java
new file mode 100644
index 00000000000..e88e0dd68b2
--- /dev/null
+++ b/src/test/java/org/apache/ibatis/scripting/xmltags/TextSqlNodeTest.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2009-2024 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ibatis.scripting.xmltags;
+
+import java.util.HashMap;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+/**
+ * @author mawen12
+ */
+class TextSqlNodeTest extends SqlNodeTest {
+
+ private static final String TEXT = "select 1 from dual";
+ private static final String DYNAMIC_TEXT = "select * from user where id = ${id}";
+
+ @Test
+ @Override
+ public void shouldApply() throws Exception {
+ // given
+ TextSqlNode sqlNode = new TextSqlNode(TEXT);
+
+ // when
+ boolean result = sqlNode.apply(context);
+
+ // then
+ assertTrue(result);
+ assertFalse(sqlNode.isDynamic());
+ verify(context).appendSql(TEXT);
+ }
+
+ @Test
+ public void shouldApplyDynamic() {
+ // given
+ TextSqlNode sqlNode = new TextSqlNode(DYNAMIC_TEXT);
+ when(context.getBindings()).thenReturn(new HashMap<>() {{
+ put("id", 1);
+ }});
+
+ // when
+ boolean result = sqlNode.apply(context);
+
+ // then
+ assertTrue(result);
+ assertTrue(sqlNode.isDynamic());
+ verify(context).appendSql("select * from user where id = 1");
+ }
+}
diff --git a/src/test/java/org/apache/ibatis/scripting/xmltags/TrimSqlNodeTest.java b/src/test/java/org/apache/ibatis/scripting/xmltags/TrimSqlNodeTest.java
new file mode 100644
index 00000000000..e3e2d72b438
--- /dev/null
+++ b/src/test/java/org/apache/ibatis/scripting/xmltags/TrimSqlNodeTest.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2009-2024 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ibatis.scripting.xmltags;
+
+import java.util.Arrays;
+import java.util.HashMap;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+/**
+ * {@code
+ * SELECT *
+ * FROM users
+ *
+ *
+ * AND id = #{id}
+ *
+ *
+ * AND name = #{name}
+ *
+ *
+ * }
+ *
+ * @author mawen12
+ * @see trim-where-set
+ */
+class TrimSqlNodeTest extends SqlNodeTest {
+
+ private static final String FIRST_TEXT = " AND id = #{id}";
+ private static final String SECOND_TEXT = " AND name = #{name}";
+ private static final String PREFIX = "WHERE";
+ private static final String PREFIX_OVERRIDES = "AND |OR ";
+
+ private SqlNode sqlNode;
+
+ @BeforeEach
+ void setup() {
+ SqlNode first = new IfSqlNode(new StaticTextSqlNode(FIRST_TEXT), "id != null");
+ SqlNode second = new IfSqlNode(new StaticTextSqlNode(SECOND_TEXT), "name != null");
+ SqlNode contents = new MixedSqlNode(Arrays.asList(first, second));
+
+ this.sqlNode = new TrimSqlNode(configuration, contents, PREFIX, PREFIX_OVERRIDES, null, null);
+ }
+
+ @Test
+ @Override
+ public void shouldApply() throws Exception {
+ when(context.getBindings()).thenReturn(new HashMap<>() {{
+ put("id", 1);
+ put("name", "mybatis");
+ }});
+
+ boolean result = sqlNode.apply(context);
+
+ assertTrue(result);
+ verify(context).appendSql("WHERE id = #{id} AND name = #{name}");
+ }
+
+ @Test
+ public void shouldAppendOnlyId() throws Exception {
+ when(context.getBindings()).thenReturn(new HashMap<>() {{
+ put("id", 1);
+ }});
+
+ boolean result = sqlNode.apply(context);
+
+ assertTrue(result);
+ verify(context).appendSql("WHERE id = #{id}");
+ }
+
+ @Test
+ public void shouldAppendOnlyName() throws Exception {
+ when(context.getBindings()).thenReturn(new HashMap<>() {{
+ put("name", "mybatis");
+ }});
+
+ boolean result = sqlNode.apply(context);
+
+ assertTrue(result);
+ verify(context).appendSql("WHERE name = #{name}");
+ }
+
+ @Test
+ public void shouldAppendNone() throws Exception {
+ when(context.getBindings()).thenReturn(new HashMap<>());
+
+ boolean result = sqlNode.apply(context);
+
+ assertTrue(result);
+ verify(context).appendSql("");
+ }
+}
diff --git a/src/test/java/org/apache/ibatis/scripting/xmltags/VarDeclSqlNodeTest.java b/src/test/java/org/apache/ibatis/scripting/xmltags/VarDeclSqlNodeTest.java
new file mode 100644
index 00000000000..457fb41c0ee
--- /dev/null
+++ b/src/test/java/org/apache/ibatis/scripting/xmltags/VarDeclSqlNodeTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2009-2024 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ibatis.scripting.xmltags;
+
+import java.util.HashMap;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+/**
+ * {@code
+ *
+ * SELECT * FROM BLOG
+ * WHERE title like #{pattern}
+ * }
+ *
+ * @author mawen12
+ * @see bind
+ */
+class VarDeclSqlNodeTest extends SqlNodeTest {
+
+ private SqlNode sqlNode;
+
+ @BeforeEach
+ void setup() {
+ this.sqlNode = new VarDeclSqlNode("pattern", "'%' + _parameter.getTitle() + '%'");
+ }
+
+ @Test
+ @Override
+ public void shouldApply() throws Exception {
+ when(context.getBindings()).thenReturn(new HashMap<>() {{
+ put("_parameter", new Bean("abc"));
+ }});
+
+ boolean result = sqlNode.apply(context);
+
+ assertTrue(result);
+ verify(context).bind("pattern", "%abc%");
+ }
+
+ private static class Bean {
+
+ private String title;
+
+ public Bean(String title) {
+ this.title = title;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+ }
+}
diff --git a/src/test/java/org/apache/ibatis/scripting/xmltags/WhereSqlNodeTest.java b/src/test/java/org/apache/ibatis/scripting/xmltags/WhereSqlNodeTest.java
new file mode 100644
index 00000000000..80f81af4ade
--- /dev/null
+++ b/src/test/java/org/apache/ibatis/scripting/xmltags/WhereSqlNodeTest.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2009-2024 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ibatis.scripting.xmltags;
+
+import java.util.Arrays;
+import java.util.HashMap;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+/**
+ * {@code
+ * SELECT *
+ * FROM users
+ *
+ *
+ * AND id = #{id}
+ *
+ *
+ * AND name = #{name}
+ *
+ *
+ * }
+ *
+ * @author mawen12
+ * @see trim-where-set
+ */
+class WhereSqlNodeTest extends SqlNodeTest {
+
+ private static final String FIRST_TEXT = " AND id = #{id}";
+ private static final String SECOND_TEXT = " AND name = #{name}";
+
+ private SqlNode sqlNode;
+
+ @BeforeEach
+ void setup() {
+ SqlNode first = new IfSqlNode(new StaticTextSqlNode(FIRST_TEXT), "id != null");
+ SqlNode second = new IfSqlNode(new StaticTextSqlNode(SECOND_TEXT), "name != null");
+ SqlNode contents = new MixedSqlNode(Arrays.asList(first, second));
+
+ this.sqlNode = new WhereSqlNode(configuration, contents);
+ }
+
+ @Test
+ @Override
+ public void shouldApply() throws Exception {
+ when(context.getBindings()).thenReturn(new HashMap<>() {{
+ put("id", 1);
+ put("name", "mybatis");
+ }});
+
+ boolean result = sqlNode.apply(context);
+
+ assertTrue(result);
+ verify(context).appendSql("WHERE id = #{id} AND name = #{name}");
+ }
+
+ @Test
+ public void shouldAppendOnlyId() throws Exception {
+ when(context.getBindings()).thenReturn(new HashMap<>() {{
+ put("id", 1);
+ }});
+
+ boolean result = sqlNode.apply(context);
+
+ assertTrue(result);
+ verify(context).appendSql("WHERE id = #{id}");
+ }
+
+ @Test
+ public void shouldAppendOnlyName() throws Exception {
+ when(context.getBindings()).thenReturn(new HashMap<>() {{
+ put("name", "mybatis");
+ }});
+
+ boolean result = sqlNode.apply(context);
+
+ assertTrue(result);
+ verify(context).appendSql("WHERE name = #{name}");
+ }
+
+ @Test
+ public void shouldAppendNone() throws Exception {
+ when(context.getBindings()).thenReturn(new HashMap<>());
+
+ boolean result = sqlNode.apply(context);
+
+ assertTrue(result);
+ verify(context).appendSql("");
+ }
+}