Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A new option (shrinkWhitespacesInSql) to remove extra whitespaces from SQL #1901

Merged
merged 12 commits into from May 18, 2020
Merged
24 changes: 22 additions & 2 deletions src/main/java/org/apache/ibatis/builder/SqlSourceBuilder.java
@@ -1,5 +1,5 @@
/**
* Copyright 2009-2019 the original author or authors.
* Copyright 2009-2020 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.
Expand All @@ -18,6 +18,7 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.mapping.SqlSource;
Expand All @@ -42,10 +43,29 @@ public SqlSourceBuilder(Configuration configuration) {
public SqlSource parse(String originalSql, Class<?> parameterType, Map<String, Object> additionalParameters) {
ParameterMappingTokenHandler handler = new ParameterMappingTokenHandler(configuration, parameterType, additionalParameters);
GenericTokenParser parser = new GenericTokenParser("#{", "}", handler);
String sql = parser.parse(originalSql);
String sql;
if (configuration.isShrinkWhitespacesInSql()) {
sql = parser.parse(removeExtraWhitespaces(originalSql));
} else {
sql = parser.parse(originalSql);
}
return new StaticSqlSource(configuration, sql, handler.getParameterMappings());
}

public static String removeExtraWhitespaces(String original) {
StringTokenizer tokenizer = new StringTokenizer(original);
StringBuilder builder = new StringBuilder();
boolean hasMoreTokens = tokenizer.hasMoreTokens();
while (hasMoreTokens) {
builder.append(tokenizer.nextToken());
hasMoreTokens = tokenizer.hasMoreTokens();
if (hasMoreTokens) {
builder.append(' ');
}
}
return builder.toString();
}

private static class ParameterMappingTokenHandler extends BaseBuilder implements TokenHandler {

private List<ParameterMapping> parameterMappings = new ArrayList<>();
Expand Down
Expand Up @@ -268,6 +268,7 @@ private void settingsElement(Properties props) {
configuration.setReturnInstanceForEmptyRow(booleanValueOf(props.getProperty("returnInstanceForEmptyRow"), false));
configuration.setLogPrefix(props.getProperty("logPrefix"));
configuration.setConfigurationFactory(resolveClass(props.getProperty("configurationFactory")));
configuration.setShrinkWhitespacesInSql(booleanValueOf(props.getProperty("shrinkWhitespacesInSql"), false));
}

private void environmentsElement(XNode context) throws Exception {
Expand Down
14 changes: 4 additions & 10 deletions src/main/java/org/apache/ibatis/logging/jdbc/BaseJdbcLogger.java
@@ -1,5 +1,5 @@
/**
* Copyright 2009-2019 the original author or authors.
* Copyright 2009-2020 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.
Expand All @@ -26,9 +26,9 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.stream.Collectors;

import org.apache.ibatis.builder.SqlSourceBuilder;
import org.apache.ibatis.logging.Log;
import org.apache.ibatis.reflection.ArrayUtil;

Expand Down Expand Up @@ -120,14 +120,8 @@ protected void clearColumnInfo() {
columnValues.clear();
}

protected String removeBreakingWhitespace(String original) {
StringTokenizer whitespaceStripper = new StringTokenizer(original);
StringBuilder builder = new StringBuilder();
while (whitespaceStripper.hasMoreTokens()) {
builder.append(whitespaceStripper.nextToken());
builder.append(" ");
}
return builder.toString();
protected String removeExtraWhitespace(String original) {
return SqlSourceBuilder.removeExtraWhitespaces(original);
}

protected boolean isDebugEnabled() {
Expand Down
Expand Up @@ -50,7 +50,7 @@ public Object invoke(Object proxy, Method method, Object[] params)
}
if ("prepareStatement".equals(method.getName()) || "prepareCall".equals(method.getName())) {
if (isDebugEnabled()) {
debug(" Preparing: " + removeBreakingWhitespace((String) params[0]), true);
debug(" Preparing: " + removeExtraWhitespace((String) params[0]), true);
}
PreparedStatement stmt = (PreparedStatement) method.invoke(connection, params);
stmt = PreparedStatementLogger.newInstance(stmt, statementLog, queryStack);
Expand Down
Expand Up @@ -48,7 +48,7 @@ public Object invoke(Object proxy, Method method, Object[] params) throws Throwa
}
if (EXECUTE_METHODS.contains(method.getName())) {
if (isDebugEnabled()) {
debug(" Executing: " + removeBreakingWhitespace((String) params[0]), true);
debug(" Executing: " + removeExtraWhitespace((String) params[0]), true);
}
if ("executeQuery".equals(method.getName())) {
ResultSet rs = (ResultSet) method.invoke(statement, params);
Expand Down
9 changes: 9 additions & 0 deletions src/main/java/org/apache/ibatis/session/Configuration.java
Expand Up @@ -113,6 +113,7 @@ public class Configuration {
protected boolean callSettersOnNulls;
protected boolean useActualParamName = true;
protected boolean returnInstanceForEmptyRow;
protected boolean shrinkWhitespacesInSql;

protected String logPrefix;
protected Class<? extends Log> logImpl;
Expand Down Expand Up @@ -266,6 +267,14 @@ public void setReturnInstanceForEmptyRow(boolean returnEmptyInstance) {
this.returnInstanceForEmptyRow = returnEmptyInstance;
}

public boolean isShrinkWhitespacesInSql() {
return shrinkWhitespacesInSql;
}

public void setShrinkWhitespacesInSql(boolean shrinkWhitespacesInSql) {
this.shrinkWhitespacesInSql = shrinkWhitespacesInSql;
}

public String getDatabaseId() {
return databaseId;
}
Expand Down
16 changes: 15 additions & 1 deletion src/site/es/xdoc/configuration.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--

Copyright 2009-2019 the original author or authors.
Copyright 2009-2020 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.
Expand Down Expand Up @@ -547,6 +547,20 @@ SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environ
Not set
</td>
</tr>
<tr>
<td>
shrinkWhitespacesInSql
</td>
<td>
Removes extra whitespace characters from the SQL. Note that this also affects literal strings in SQL. (Since 3.5.5)
</td>
<td>
true | false
</td>
<td>
false
</td>
</tr>
</tbody>
</table>
<p>
Expand Down
16 changes: 15 additions & 1 deletion src/site/ja/xdoc/configuration.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--

Copyright 2009-2019 the original author or authors.
Copyright 2009-2020 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.
Expand Down Expand Up @@ -572,6 +572,20 @@ SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environ
未指定
</td>
</tr>
<tr>
<td>
shrinkWhitespacesInSql
</td>
<td>
SQL 内の余分な空白文字を削除します。リテラル文字列も対象となる点に注意してください。(導入されたバージョン: 3.5.5)
</td>
<td>
true | false
</td>
<td>
false
</td>
</tr>
</tbody>
</table>
<p>
Expand Down
16 changes: 15 additions & 1 deletion src/site/ko/xdoc/configuration.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--

Copyright 2009-2019 the original author or authors.
Copyright 2009-2020 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.
Expand Down Expand Up @@ -555,6 +555,20 @@ SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environ
설정하지 않음
</td>
</tr>
<tr>
<td>
shrinkWhitespacesInSql
</td>
<td>
SQL에서 여분의 whitespace 문자들을 삭제한다. 이는 SQL의 리터럴 문자열에도 영향을 미친다. (Since 3.5.5)
</td>
<td>
true | false
</td>
<td>
false
</td>
</tr>
</tbody>
</table>
<p>위 설정을 모두 사용한 setting 엘리먼트의 예제이다:</p>
Expand Down
18 changes: 16 additions & 2 deletions src/site/xdoc/configuration.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<?xml version="1.0" encoding="UTF-8"?>
<!--

Copyright 2009-2019 the original author or authors.
Copyright 2009-2020 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.
Expand Down Expand Up @@ -634,6 +634,20 @@ SqlSessionFactory factory =
Not set
</td>
</tr>
<tr>
<td>
shrinkWhitespacesInSql
</td>
<td>
Removes extra whitespace characters from the SQL. Note that this also affects literal strings in SQL. (Since 3.5.5)
</td>
<td>
true | false
</td>
<td>
false
</td>
</tr>
</tbody>
</table>
<p>
Expand Down
14 changes: 14 additions & 0 deletions src/site/zh/xdoc/configuration.xml
Expand Up @@ -565,6 +565,20 @@ SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(reader, environ
未设置
</td>
</tr>
<tr>
<td>
shrinkWhitespacesInSql
</td>
<td>
Removes extra whitespace characters from the SQL. Note that this also affects literal strings in SQL. (Since 3.5.5)
</td>
<td>
true | false
</td>
<td>
false
</td>
</tr>
</tbody>
</table>
<p>
Expand Down
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!--

Copyright 2009-2019 the original author or authors.
Copyright 2009-2020 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.
Expand Down Expand Up @@ -54,6 +54,7 @@
<setting name="vfsImpl" value="org.apache.ibatis.io.JBoss6VFS"/>
<setting name="configurationFactory" value="java.lang.String"/>
<setting name="defaultEnumTypeHandler" value="org.apache.ibatis.type.EnumOrdinalTypeHandler"/>
<setting name="shrinkWhitespacesInSql" value="true"/>
</settings>

<typeAliases>
Expand Down
56 changes: 56 additions & 0 deletions src/test/java/org/apache/ibatis/builder/SqlSourceBuilderTest.java
@@ -0,0 +1,56 @@
/**
* Copyright 2009-2020 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
*
* http://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.builder;

import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.SqlSource;
import org.apache.ibatis.session.Configuration;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

public class SqlSourceBuilderTest {

private static Configuration configuration;
private static SqlSourceBuilder sqlSourceBuilder;
private final String sqlFromXml = "\t\n\n SELECT * \n FROM user\n \t WHERE user_id = 1\n\t ";

@BeforeEach
void setUp() {
configuration = new Configuration();

sqlSourceBuilder = new SqlSourceBuilder(configuration);
}

@Test
void testShrinkWhitespacesInSqlIsFalse() {
SqlSource sqlSource = sqlSourceBuilder.parse(sqlFromXml, null, null);
BoundSql boundSql = sqlSource.getBoundSql(null);
String actual = boundSql.getSql();
Assertions.assertEquals(sqlFromXml, actual);
}

@Test
void testShrinkWhitespacesInSqlIsTrue() {
configuration.setShrinkWhitespacesInSql(true);
SqlSource sqlSource = sqlSourceBuilder.parse(sqlFromXml, null, null);
BoundSql boundSql = sqlSource.getBoundSql(null);
String actual = boundSql.getSql();

String shrankWhitespacesInSql = "SELECT * FROM user WHERE user_id = 1";
Assertions.assertEquals(shrankWhitespacesInSql, actual);
}
}
Expand Up @@ -100,6 +100,7 @@ void shouldSuccessfullyLoadMinimalXMLConfigFile() throws Exception {
assertNull(config.getLogImpl());
assertNull(config.getConfigurationFactory());
assertThat(config.getTypeHandlerRegistry().getTypeHandler(RoundingMode.class)).isInstanceOf(EnumTypeHandler.class);
assertThat(config.isShrinkWhitespacesInSql()).isFalse();
}
}

Expand Down Expand Up @@ -194,6 +195,7 @@ void shouldSuccessfullyLoadXMLConfigFile() throws Exception {
assertThat(config.getLogImpl().getName()).isEqualTo(Slf4jImpl.class.getName());
assertThat(config.getVfsImpl().getName()).isEqualTo(JBoss6VFS.class.getName());
assertThat(config.getConfigurationFactory().getName()).isEqualTo(String.class.getName());
assertThat(config.isShrinkWhitespacesInSql()).isTrue();

assertThat(config.getTypeAliasRegistry().getTypeAliases().get("blogauthor")).isEqualTo(Author.class);
assertThat(config.getTypeAliasRegistry().getTypeAliases().get("blog")).isEqualTo(Blog.class);
Expand Down
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!--

Copyright 2009-2019 the original author or authors.
Copyright 2009-2020 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.
Expand Down Expand Up @@ -50,6 +50,7 @@
<setting name="logImpl" value="SLF4J"/>
<setting name="vfsImpl" value="org.apache.ibatis.io.JBoss6VFS"/>
<setting name="configurationFactory" value="java.lang.String"/>
<setting name="shrinkWhitespacesInSql" value="true"/>
</settings>

<typeAliases>
Expand Down
Expand Up @@ -84,6 +84,7 @@ void shouldSuccessfullyLoadMinimalXMLConfigFile() throws Exception {
assertNull(config.getLogPrefix());
assertNull(config.getLogImpl());
assertNull(config.getConfigurationFactory());
assertFalse(config.isShrinkWhitespacesInSql());
} finally {
// System.clearProperty(XPathParser.KEY_USE_XSD);
}
Expand Down Expand Up @@ -121,6 +122,7 @@ void shouldSuccessfullyLoadXMLConfigFile() throws Exception {
assertEquals(Slf4jImpl.class.getName(), config.getLogImpl().getName());
assertEquals(JBoss6VFS.class.getName(), config.getVfsImpl().getName());
assertEquals(String.class.getName(), config.getConfigurationFactory().getName());
assertTrue(config.isShrinkWhitespacesInSql());

assertEquals(Author.class, config.getTypeAliasRegistry().getTypeAliases().get("blogauthor"));
assertEquals(Blog.class, config.getTypeAliasRegistry().getTypeAliases().get("blog"));
Expand Down