SQL: Improve performances of LTRIM/RTRIM (#57603)
Change custom stripping leading and trailing whitespaces implementation to substantially improves performance: ``` Benchmark Mode Cnt Score Error Units StringTrim.testWithStringBuilder avgt 25 82547.575 ± 66.244 ns/op (existing impl) StringTrim.testWithSubstring avgt 25 1398.762 ± 101.152 ns/op (new impl) StringTrim.testWithJavaStrip avgt 25 1186.120 ± 10.374 ns/op (for reference) ``` Java's string stripLeading()/stripTrailing() not available to all supported JDKs. Enhanced LENGTH unit tests and compine a couple of LTRIM/RTRIM integ tests. Relates to: #57594 (partially cherry picked from commit ee7868d68733f195dc46926a7eab3d9dd7033ef4) Co-authored-by: Bogdan Pintea <bogdan.pintea@elastic.co>
This commit is contained in:
parent
2c2d903277
commit
5f8442d1f4
|
@ -70,11 +70,8 @@ SELECT LEFT('Elasticsearch', LENGTH('abcdefghijklmnop')) leftchars;
|
||||||
ltrimFilter
|
ltrimFilter
|
||||||
SELECT LTRIM(first_name) lt FROM "test_emp" WHERE LTRIM(first_name) = 'Bob';
|
SELECT LTRIM(first_name) lt FROM "test_emp" WHERE LTRIM(first_name) = 'Bob';
|
||||||
|
|
||||||
ltrimInline1
|
ltrimInline
|
||||||
SELECT LTRIM(' Elastic ') trimmed;
|
SELECT LTRIM(' Elastic ') lt1, LTRIM(' ') lt2;
|
||||||
|
|
||||||
ltrimInline2
|
|
||||||
SELECT LTRIM(' ') trimmed;
|
|
||||||
|
|
||||||
locateInline1
|
locateInline1
|
||||||
SELECT LOCATE('a', 'Elasticsearch', 8) location;
|
SELECT LOCATE('a', 'Elasticsearch', 8) location;
|
||||||
|
@ -127,11 +124,8 @@ SELECT LTRIM("first_name") lt FROM "test_emp" WHERE LTRIM("first_name") LIKE '%a
|
||||||
rtrimFilter
|
rtrimFilter
|
||||||
SELECT RTRIM(first_name) rt FROM "test_emp" WHERE RTRIM(first_name) = 'Johnny';
|
SELECT RTRIM(first_name) rt FROM "test_emp" WHERE RTRIM(first_name) = 'Johnny';
|
||||||
|
|
||||||
rtrimInline1
|
rtrimInline
|
||||||
SELECT RTRIM(' Elastic ') trimmed;
|
SELECT RTRIM(' Elastic ') rt1, RTRIM(' ') rt2;
|
||||||
|
|
||||||
rtrimInline2
|
|
||||||
SELECT RTRIM(' ') trimmed;
|
|
||||||
|
|
||||||
spaceFilter
|
spaceFilter
|
||||||
SELECT SPACE(languages) spaces, languages FROM "test_emp" WHERE SPACE(languages) = ' ';
|
SELECT SPACE(languages) spaces, languages FROM "test_emp" WHERE SPACE(languages) = ' ';
|
||||||
|
|
|
@ -23,15 +23,15 @@ final class StringFunctionUtils {
|
||||||
if (!hasLength(s)) {
|
if (!hasLength(s)) {
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (start < 0) {
|
if (start < 0) {
|
||||||
start = 0;
|
start = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (start + 1 > s.length() || length < 0) {
|
if (start + 1 > s.length() || length < 0) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
return (start + length > s.length()) ? s.substring(start) : s.substring(start, start + length);
|
return (start + length > s.length()) ? s.substring(start) : s.substring(start, start + length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,11 +47,11 @@ final class StringFunctionUtils {
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder(s);
|
int i = s.length() - 1;
|
||||||
while (sb.length() > 0 && Character.isWhitespace(sb.charAt(sb.length() - 1))) {
|
while (i >= 0 && Character.isWhitespace(s.charAt(i))) {
|
||||||
sb.deleteCharAt(sb.length() - 1);
|
i--;
|
||||||
}
|
}
|
||||||
return sb.toString();
|
return s.substring(0, i + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -66,10 +66,10 @@ final class StringFunctionUtils {
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder(s);
|
int i = 0;
|
||||||
while (sb.length() > 0 && Character.isWhitespace(sb.charAt(0))) {
|
while (i < s.length() && Character.isWhitespace(s.charAt(i))) {
|
||||||
sb.deleteCharAt(0);
|
i++;
|
||||||
}
|
}
|
||||||
return sb.toString();
|
return s.substring(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,8 +51,8 @@ public class StringProcessor implements Processor {
|
||||||
LCASE((String s) -> s.toLowerCase(Locale.ROOT)),
|
LCASE((String s) -> s.toLowerCase(Locale.ROOT)),
|
||||||
UCASE((String s) -> s.toUpperCase(Locale.ROOT)),
|
UCASE((String s) -> s.toUpperCase(Locale.ROOT)),
|
||||||
LENGTH((String s) -> StringFunctionUtils.trimTrailingWhitespaces(s).length()),
|
LENGTH((String s) -> StringFunctionUtils.trimTrailingWhitespaces(s).length()),
|
||||||
RTRIM((String s) -> StringFunctionUtils.trimTrailingWhitespaces(s)),
|
RTRIM(StringFunctionUtils::trimTrailingWhitespaces),
|
||||||
LTRIM((String s) -> StringFunctionUtils.trimLeadingWhitespaces(s)),
|
LTRIM(StringFunctionUtils::trimLeadingWhitespaces),
|
||||||
TRIM(String::trim),
|
TRIM(String::trim),
|
||||||
SPACE((Number n) -> {
|
SPACE((Number n) -> {
|
||||||
int i = n.intValue();
|
int i = n.intValue();
|
||||||
|
|
|
@ -134,10 +134,10 @@ public class StringFunctionProcessorTests extends AbstractWireSerializingTestCas
|
||||||
StringProcessor proc = new StringProcessor(StringOperation.LENGTH);
|
StringProcessor proc = new StringProcessor(StringOperation.LENGTH);
|
||||||
assertNull(proc.process(null));
|
assertNull(proc.process(null));
|
||||||
assertEquals(7, proc.process("foo bar"));
|
assertEquals(7, proc.process("foo bar"));
|
||||||
assertEquals(0, proc.process(""));
|
assertEquals(0, proc.process(withRandomWhitespaces(" \t \r\n \n ", true, true)));
|
||||||
assertEquals(0, proc.process(" "));
|
assertEquals(0, proc.process(withRandomWhitespaces(" ", true, true)));
|
||||||
assertEquals(7, proc.process("foo bar "));
|
assertEquals(7, proc.process(withRandomWhitespaces("foo bar", false, true)));
|
||||||
assertEquals(10, proc.process(" foo bar "));
|
assertEquals(10, proc.process(withRandomWhitespaces(" foo bar ", false, true)));
|
||||||
assertEquals(1, proc.process('f'));
|
assertEquals(1, proc.process('f'));
|
||||||
|
|
||||||
stringCharInputValidation(proc);
|
stringCharInputValidation(proc);
|
||||||
|
|
Loading…
Reference in New Issue