Skip to content

Commit edf83c1

Browse files
authored
SQL: Add support for single parameter text manipulating functions (elastic#31874)
Added support for ASCII, BIT_LENGTH, CHAR, CHAR_LENGTH, LCASE, LENGTH, LTRIM, RTRIM, SPACE, UCASE functions. Wherever Painless scripting is necessary (WHERE conditions, ORDER BY etc), those scripts are being used.
1 parent 2cfe703 commit edf83c1

File tree

31 files changed

+1227
-3
lines changed

31 files changed

+1227
-3
lines changed

x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/FunctionRegistry.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,16 @@
5858
import org.elasticsearch.xpack.sql.expression.function.scalar.math.Sinh;
5959
import org.elasticsearch.xpack.sql.expression.function.scalar.math.Sqrt;
6060
import org.elasticsearch.xpack.sql.expression.function.scalar.math.Tan;
61+
import org.elasticsearch.xpack.sql.expression.function.scalar.string.Ascii;
62+
import org.elasticsearch.xpack.sql.expression.function.scalar.string.BitLength;
63+
import org.elasticsearch.xpack.sql.expression.function.scalar.string.Char;
64+
import org.elasticsearch.xpack.sql.expression.function.scalar.string.CharLength;
65+
import org.elasticsearch.xpack.sql.expression.function.scalar.string.LCase;
66+
import org.elasticsearch.xpack.sql.expression.function.scalar.string.LTrim;
67+
import org.elasticsearch.xpack.sql.expression.function.scalar.string.Length;
68+
import org.elasticsearch.xpack.sql.expression.function.scalar.string.RTrim;
69+
import org.elasticsearch.xpack.sql.expression.function.scalar.string.Space;
70+
import org.elasticsearch.xpack.sql.expression.function.scalar.string.UCase;
6171
import org.elasticsearch.xpack.sql.parser.ParsingException;
6272
import org.elasticsearch.xpack.sql.tree.Location;
6373
import org.elasticsearch.xpack.sql.util.StringUtils;
@@ -134,6 +144,17 @@ public class FunctionRegistry {
134144
def(Sinh.class, Sinh::new),
135145
def(Sqrt.class, Sqrt::new),
136146
def(Tan.class, Tan::new),
147+
// String
148+
def(Ascii.class, Ascii::new),
149+
def(Char.class, Char::new),
150+
def(BitLength.class, BitLength::new),
151+
def(CharLength.class, CharLength::new),
152+
def(LCase.class, LCase::new),
153+
def(Length.class, Length::new),
154+
def(LTrim.class, LTrim::new),
155+
def(RTrim.class, RTrim::new),
156+
def(Space.class, Space::new),
157+
def(UCase.class, UCase::new),
137158
// Special
138159
def(Score.class, Score::new)));
139160

@@ -299,6 +320,7 @@ interface BinaryFunctionBuilder<T> {
299320
T build(Location location, Expression lhs, Expression rhs);
300321
}
301322

323+
@SuppressWarnings("overloads")
302324
private static FunctionDefinition def(Class<? extends Function> function, FunctionBuilder builder,
303325
boolean datetime, String... aliases) {
304326
String primaryName = normalize(function.getSimpleName());

x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/Processors.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import org.elasticsearch.xpack.sql.expression.function.scalar.processor.runtime.ConstantProcessor;
1818
import org.elasticsearch.xpack.sql.expression.function.scalar.processor.runtime.HitExtractorProcessor;
1919
import org.elasticsearch.xpack.sql.expression.function.scalar.processor.runtime.Processor;
20+
import org.elasticsearch.xpack.sql.expression.function.scalar.string.StringProcessor;
2021

2122
import java.util.ArrayList;
2223
import java.util.List;
@@ -46,6 +47,8 @@ public static List<NamedWriteableRegistry.Entry> getNamedWriteables() {
4647
entries.add(new Entry(Processor.class, DateTimeProcessor.NAME, DateTimeProcessor::new));
4748
// math
4849
entries.add(new Entry(Processor.class, MathProcessor.NAME, MathProcessor::new));
50+
// string
51+
entries.add(new Entry(Processor.class, StringProcessor.NAME, StringProcessor::new));
4952
return entries;
5053
}
5154
}

x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/ATan2.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ protected BiFunction<Number, Number, Number> operation() {
3030
}
3131

3232
@Override
33-
protected NodeInfo<? extends Expression> info() {
33+
protected NodeInfo<ATan2> info() {
3434
return NodeInfo.create(this, ATan2::new, left(), right());
3535
}
3636

x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/Power.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ protected BiFunction<Number, Number, Number> operation() {
2626
}
2727

2828
@Override
29-
protected NodeInfo<? extends Expression> info() {
29+
protected NodeInfo<Power> info() {
3030
return NodeInfo.create(this, Power::new, left(), right());
3131
}
3232

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
package org.elasticsearch.xpack.sql.expression.function.scalar.string;
7+
8+
import org.elasticsearch.xpack.sql.expression.Expression;
9+
import org.elasticsearch.xpack.sql.expression.function.scalar.string.StringProcessor.StringOperation;
10+
import org.elasticsearch.xpack.sql.tree.Location;
11+
import org.elasticsearch.xpack.sql.tree.NodeInfo;
12+
import org.elasticsearch.xpack.sql.type.DataType;
13+
14+
/**
15+
* Returns the ASCII code of the leftmost character of the given (char) expression.
16+
*/
17+
public class Ascii extends UnaryStringFunction {
18+
19+
public Ascii(Location location, Expression field) {
20+
super(location, field);
21+
}
22+
23+
@Override
24+
protected NodeInfo<Ascii> info() {
25+
return NodeInfo.create(this, Ascii::new, field());
26+
}
27+
28+
@Override
29+
protected Ascii replaceChild(Expression newChild) {
30+
return new Ascii(location(), newChild);
31+
}
32+
33+
@Override
34+
protected StringOperation operation() {
35+
return StringOperation.ASCII;
36+
}
37+
38+
@Override
39+
public DataType dataType() {
40+
return DataType.INTEGER;
41+
}
42+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
package org.elasticsearch.xpack.sql.expression.function.scalar.string;
7+
8+
import org.elasticsearch.xpack.sql.expression.Expression;
9+
import org.elasticsearch.xpack.sql.expression.function.scalar.string.StringProcessor.StringOperation;
10+
import org.elasticsearch.xpack.sql.tree.Location;
11+
import org.elasticsearch.xpack.sql.tree.NodeInfo;
12+
import org.elasticsearch.xpack.sql.type.DataType;
13+
14+
/**
15+
* Returns returns the number of bits contained within the value expression.
16+
*/
17+
public class BitLength extends UnaryStringFunction {
18+
19+
public BitLength(Location location, Expression field) {
20+
super(location, field);
21+
}
22+
23+
@Override
24+
protected NodeInfo<BitLength> info() {
25+
return NodeInfo.create(this, BitLength::new, field());
26+
}
27+
28+
@Override
29+
protected BitLength replaceChild(Expression newChild) {
30+
return new BitLength(location(), newChild);
31+
}
32+
33+
@Override
34+
protected StringOperation operation() {
35+
return StringOperation.BIT_LENGTH;
36+
}
37+
38+
@Override
39+
public DataType dataType() {
40+
//TODO investigate if a data type Long (BIGINT) wouldn't be more appropriate here
41+
return DataType.INTEGER;
42+
}
43+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
package org.elasticsearch.xpack.sql.expression.function.scalar.string;
7+
8+
import org.elasticsearch.xpack.sql.expression.Expression;
9+
import org.elasticsearch.xpack.sql.expression.function.scalar.string.StringProcessor.StringOperation;
10+
import org.elasticsearch.xpack.sql.tree.Location;
11+
import org.elasticsearch.xpack.sql.tree.NodeInfo;
12+
import org.elasticsearch.xpack.sql.type.DataType;
13+
14+
/**
15+
* Converts an int ASCII code to a character value.
16+
*/
17+
public class Char extends UnaryStringIntFunction {
18+
19+
public Char(Location location, Expression field) {
20+
super(location, field);
21+
}
22+
23+
@Override
24+
protected NodeInfo<Char> info() {
25+
return NodeInfo.create(this, Char::new, field());
26+
}
27+
28+
@Override
29+
protected Char replaceChild(Expression newChild) {
30+
return new Char(location(), newChild);
31+
}
32+
33+
@Override
34+
protected StringOperation operation() {
35+
return StringOperation.CHAR;
36+
}
37+
38+
@Override
39+
public DataType dataType() {
40+
return DataType.KEYWORD;
41+
}
42+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
package org.elasticsearch.xpack.sql.expression.function.scalar.string;
7+
8+
import org.elasticsearch.xpack.sql.expression.Expression;
9+
import org.elasticsearch.xpack.sql.expression.function.scalar.string.StringProcessor.StringOperation;
10+
import org.elasticsearch.xpack.sql.tree.Location;
11+
import org.elasticsearch.xpack.sql.tree.NodeInfo;
12+
import org.elasticsearch.xpack.sql.type.DataType;
13+
14+
/**
15+
* Returns the length (in characters) of the string expression.
16+
*/
17+
public class CharLength extends UnaryStringFunction {
18+
19+
public CharLength(Location location, Expression field) {
20+
super(location, field);
21+
}
22+
23+
@Override
24+
protected NodeInfo<CharLength> info() {
25+
return NodeInfo.create(this, CharLength::new, field());
26+
}
27+
28+
@Override
29+
protected CharLength replaceChild(Expression newChild) {
30+
return new CharLength(location(), newChild);
31+
}
32+
33+
@Override
34+
protected StringOperation operation() {
35+
return StringOperation.CHAR_LENGTH;
36+
}
37+
38+
@Override
39+
public DataType dataType() {
40+
return DataType.INTEGER;
41+
}
42+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
package org.elasticsearch.xpack.sql.expression.function.scalar.string;
7+
8+
import org.elasticsearch.xpack.sql.expression.Expression;
9+
import org.elasticsearch.xpack.sql.expression.function.scalar.string.StringProcessor.StringOperation;
10+
import org.elasticsearch.xpack.sql.tree.Location;
11+
import org.elasticsearch.xpack.sql.tree.NodeInfo;
12+
import org.elasticsearch.xpack.sql.type.DataType;
13+
14+
/**
15+
* Lowercases all uppercase letters in a string.
16+
*/
17+
public class LCase extends UnaryStringFunction {
18+
19+
public LCase(Location location, Expression field) {
20+
super(location, field);
21+
}
22+
23+
@Override
24+
protected NodeInfo<LCase> info() {
25+
return NodeInfo.create(this, LCase::new, field());
26+
}
27+
28+
@Override
29+
protected LCase replaceChild(Expression newChild) {
30+
return new LCase(location(), newChild);
31+
}
32+
33+
@Override
34+
protected StringOperation operation() {
35+
return StringOperation.LCASE;
36+
}
37+
38+
@Override
39+
public DataType dataType() {
40+
return DataType.KEYWORD;
41+
}
42+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
package org.elasticsearch.xpack.sql.expression.function.scalar.string;
7+
8+
import org.elasticsearch.xpack.sql.expression.Expression;
9+
import org.elasticsearch.xpack.sql.expression.function.scalar.string.StringProcessor.StringOperation;
10+
import org.elasticsearch.xpack.sql.tree.Location;
11+
import org.elasticsearch.xpack.sql.tree.NodeInfo;
12+
import org.elasticsearch.xpack.sql.type.DataType;
13+
14+
/**
15+
* Trims the leading whitespaces.
16+
*/
17+
public class LTrim extends UnaryStringFunction {
18+
19+
public LTrim(Location location, Expression field) {
20+
super(location, field);
21+
}
22+
23+
@Override
24+
protected NodeInfo<LTrim> info() {
25+
return NodeInfo.create(this, LTrim::new, field());
26+
}
27+
28+
@Override
29+
protected LTrim replaceChild(Expression newChild) {
30+
return new LTrim(location(), newChild);
31+
}
32+
33+
@Override
34+
protected StringOperation operation() {
35+
return StringOperation.LTRIM;
36+
}
37+
38+
@Override
39+
public DataType dataType() {
40+
return DataType.KEYWORD;
41+
}
42+
43+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
package org.elasticsearch.xpack.sql.expression.function.scalar.string;
7+
8+
import org.elasticsearch.xpack.sql.expression.Expression;
9+
import org.elasticsearch.xpack.sql.expression.function.scalar.string.StringProcessor.StringOperation;
10+
import org.elasticsearch.xpack.sql.tree.Location;
11+
import org.elasticsearch.xpack.sql.tree.NodeInfo;
12+
import org.elasticsearch.xpack.sql.type.DataType;
13+
14+
/**
15+
* Returns the length (number of characters) in a string, excluding the trailing blanks.
16+
*/
17+
public class Length extends UnaryStringFunction {
18+
19+
public Length(Location location, Expression field) {
20+
super(location, field);
21+
}
22+
23+
@Override
24+
protected NodeInfo<Length> info() {
25+
return NodeInfo.create(this, Length::new, field());
26+
}
27+
28+
@Override
29+
protected Length replaceChild(Expression newChild) {
30+
return new Length(location(), newChild);
31+
}
32+
33+
@Override
34+
protected StringOperation operation() {
35+
return StringOperation.LENGTH;
36+
}
37+
38+
@Override
39+
public DataType dataType() {
40+
return DataType.INTEGER;
41+
}
42+
43+
}

0 commit comments

Comments
 (0)