Get rid of query level normalization

This commit is contained in:
Timo Westkämper 2015-10-16 21:41:25 +03:00
parent 3c58eec1c2
commit af2da8c0d4
3 changed files with 6 additions and 228 deletions

View File

@ -1,98 +0,0 @@
/*
* Copyright 2015, The Querydsl Team (http://www.querydsl.com/team)
*
* 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 com.querydsl.core.support;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
final class Normalization {
private static final String WS = "\\s*";
private static final String NUMBER = "([\\+\\-]?\\d+\\.?\\d*)(?!\\p{Alpha})";
// TODO simplify
private static final Pattern FULL_OPERATION = Pattern.compile(
"(?<![\\d*/\"?' ])" + "(\\b|\\(|\\s+)" +
"(" + NUMBER + WS + "[+\\-/*]" + WS + ")+" + NUMBER + WS +
"(?![\\d*/\"' ])");
private static final Pattern[] OPERATIONS = {
Pattern.compile(NUMBER + WS + "([*/])" + WS + NUMBER),
Pattern.compile(NUMBER + WS + "([+-])" + WS + NUMBER),
};
private static String normalizeOperation(String queryString) {
for (Pattern operation : OPERATIONS) {
Matcher matcher;
while ((matcher = operation.matcher(queryString)).find()) {
char operator = matcher.group(2).charAt(0);
BigDecimal first = new BigDecimal(matcher.group(1));
BigDecimal second = new BigDecimal(matcher.group(3));
BigDecimal result;
switch (operator) {
case '*':
result = first.multiply(second);
break;
case '/':
result = first.divide(second, 10, RoundingMode.HALF_UP);
break;
case '+':
result = first.add(second);
break;
case '-':
result = first.subtract(second);
break;
default:
throw new IllegalStateException();
}
StringBuffer buffer = new StringBuffer();
matcher.appendReplacement(buffer, result.stripTrailingZeros().toPlainString())
.appendTail(buffer);
queryString = buffer.toString();
}
}
return queryString;
}
public static String normalize(String queryString) {
if (!hasOperators(queryString)) {
return queryString;
}
StringBuffer buffer = new StringBuffer();
Matcher m = FULL_OPERATION.matcher(queryString);
while (m.find()) {
String result = normalizeOperation(queryString.substring(m.start(), m.end()));
m.appendReplacement(buffer, result);
}
m.appendTail(buffer);
return buffer.toString();
}
private static boolean hasOperators(String queryString) {
for (int i = 0; i < queryString.length(); i++) {
char ch = queryString.charAt(i);
if (ch == '+' || ch == '-' || ch == '*' || ch == '/') {
return true;
}
}
return false;
}
private Normalization() { }
}

View File

@ -48,8 +48,6 @@ public abstract class SerializerBase<S extends SerializerBase<S>> implements Vis
private final Templates templates;
private boolean normalize = true;
private boolean strict = true;
public SerializerBase(Templates templates) {
@ -170,8 +168,12 @@ public abstract class SerializerBase<S extends SerializerBase<S>> implements Vis
this.anonParamPrefix = prefix;
}
/**
* Not used anymore
*/
@Deprecated
public void setNormalize(boolean normalize) {
this.normalize = normalize;
// not used anymore
}
public void setStrict(boolean strict) {
@ -180,11 +182,7 @@ public abstract class SerializerBase<S extends SerializerBase<S>> implements Vis
@Override
public String toString() {
if (normalize) {
return Normalization.normalize(builder.toString());
} else {
return builder.toString();
}
return builder.toString();
}
@Override

View File

@ -1,122 +0,0 @@
package com.querydsl.core.support;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import com.querydsl.core.testutil.Benchmark;
import com.querydsl.core.testutil.Performance;
import com.querydsl.core.testutil.Runner;
public class NormalizationTest {
@Test
@Category(Performance.class)
public void Performance() throws Exception {
Runner.run("NormalizationTest Performance", new Benchmark() {
@Override
public void run(int times) throws Exception {
for (int i = 0; i < times; i++) {
Normalization.normalize("select name from companies where id = ?");
}
}
});
}
@Test
public void Variables() {
assertEquals("var1 + 3", Normalization.normalize("var1 + 3"));
}
@Test
public void Arithmetic() {
assertEquals("3", Normalization.normalize("1 - 2 + 4"));
}
@Test
public void Normalize_Addition() {
assertEquals("3", Normalization.normalize("1+2"));
assertEquals("where 3 = 3", Normalization.normalize("where 1+2 = 3"));
assertEquals("where 3.3 = 3.3", Normalization.normalize("where 1.1+2.2 = 3.3"));
assertEquals("where 3.3 = 3.3", Normalization.normalize("where 1.1 + 2.2 = 3.3"));
}
@Test
public void Normalize_Subtraction() {
assertEquals("3", Normalization.normalize("5-2"));
assertEquals("where 3 = 3", Normalization.normalize("where 5-2 = 3"));
assertEquals("where 3.3 = 3.3", Normalization.normalize("where 5.5-2.2 = 3.3"));
assertEquals("where 3.3 = 3.3", Normalization.normalize("where 5.5 - 2.2 = 3.3"));
}
@Test
public void Normalize_Multiplication() {
assertEquals("10", Normalization.normalize("5*2"));
assertEquals("where 10 = 10", Normalization.normalize("where 5*2 = 10"));
assertEquals("where 11 = 11", Normalization.normalize("where 5.5*2 = 11"));
assertEquals("where 10.8 = 10.8", Normalization.normalize("where 5.4 * 2 = 10.8"));
assertEquals("where 9 = 9 and 13 = 13", Normalization.normalize("where 2 * 3 + 3 = 9 and 5 + 4 * 2 = 13"));
}
@Test
public void Normalize_Division() {
assertEquals("2.5", Normalization.normalize("5/2"));
assertEquals("where 2.5 = 2.5", Normalization.normalize("where 5/2 = 2.5"));
assertEquals("where 2.6 = 2.6", Normalization.normalize("where 5.2/2 = 2.6"));
assertEquals("where 2.6 = 2.6", Normalization.normalize("where 5.2 / 2 = 2.6"));
}
@Test
public void Mixed() {
assertEquals("13", Normalization.normalize("2 * 5 + 3"));
assertEquals("17", Normalization.normalize("2 + 5 * 3"));
assertEquals("-2.5", Normalization.normalize("2.5 * -1"));
assertEquals("hours * 2 + 3", Normalization.normalize("hours * 2 + 3"));
assertEquals("2 + 3 * hours", Normalization.normalize("2 + 3 * hours"));
assertEquals("2 + 3 * 0hours", Normalization.normalize("2 + 3 * 0hours"));
assertEquals("a like '1 + 2 ' and b like '2 * 3'", Normalization.normalize("a like '1 + 2 ' and b like '2 * 3'"));
}
@Test
public void PI() {
assertEquals("0.1591549431", Normalization.normalize("0.5 / " + Math.PI));
}
@Test
public void DateTimeLiterals() {
assertEquals("'1980-10-10'", Normalization.normalize("'1980-10-10'"));
}
@Test
public void DateTimeLiterals2() {
assertEquals("\"1980-10-10\"", Normalization.normalize("\"1980-10-10\""));
}
@Test
public void Math1() {
assertEquals("fn(1)", Normalization.normalize("fn(-1+2)"));
assertEquals("fn(3)", Normalization.normalize("fn(1--2)"));
}
@Test
public void Substring() {
assertEquals("substring(cat.name,1,locate(?1,cat.name)-1)",
Normalization.normalize("substring(cat.name,0+1,locate(?1,cat.name)-1-0)"));
}
@Test
public void Parameters() {
assertEquals("?1 + 1", Normalization.normalize("?1 + 1"));
}
@Test
public void Literals() {
assertEquals("'INPS-ISET-0000-12345678A'", Normalization.normalize("'INPS-ISET-0000-12345678A'"));
assertEquals("'INPS-ISET-0000X00000000A'", Normalization.normalize("'INPS-ISET-0000X00000000A'"));
assertEquals("'INPS-ISET-0000-00000000A'", Normalization.normalize("'INPS-ISET-0000-00000000A'"));
assertEquals("column = 'INPS-ISET-0000-00000000A' limit 1", Normalization.normalize("column = 'INPS-ISET-0000-00000000A' limit 1"));
}
}