Skip to content

Commit 738f451

Browse files
committed
SQL: Provide null-safe scripts for Not and Neg (#34877)
Introduce null-safe Painless scripts for Not and Neg Simplify script generation for Unary functions Close #34848 (cherry picked from commit 5a7b8c0)
1 parent f44d9e8 commit 738f451

File tree

19 files changed

+250
-107
lines changed

19 files changed

+250
-107
lines changed

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

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,7 @@
66
package org.elasticsearch.xpack.sql.expression.function.scalar;
77

88
import org.elasticsearch.xpack.sql.expression.Expression;
9-
import org.elasticsearch.xpack.sql.expression.Expressions;
10-
import org.elasticsearch.xpack.sql.expression.gen.pipeline.Pipe;
11-
import org.elasticsearch.xpack.sql.expression.gen.pipeline.UnaryPipe;
9+
import org.elasticsearch.xpack.sql.expression.gen.processor.Processor;
1210
import org.elasticsearch.xpack.sql.tree.Location;
1311
import org.elasticsearch.xpack.sql.tree.NodeInfo;
1412
import org.elasticsearch.xpack.sql.type.DataType;
@@ -71,9 +69,8 @@ protected TypeResolution resolveType() {
7169
}
7270

7371
@Override
74-
protected Pipe makePipe() {
75-
return new UnaryPipe(location(), this, Expressions.pipe(field()),
76-
new CastProcessor(DataTypeConversion.conversionFor(from(), to())));
72+
protected Processor makeProcessor() {
73+
return new CastProcessor(DataTypeConversion.conversionFor(from(), to()));
7774
}
7875

7976
@Override

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66
package org.elasticsearch.xpack.sql.expression.function.scalar;
77

88
import org.elasticsearch.xpack.sql.expression.Expression;
9+
import org.elasticsearch.xpack.sql.expression.Expressions;
10+
import org.elasticsearch.xpack.sql.expression.gen.pipeline.Pipe;
11+
import org.elasticsearch.xpack.sql.expression.gen.pipeline.UnaryPipe;
12+
import org.elasticsearch.xpack.sql.expression.gen.processor.Processor;
913
import org.elasticsearch.xpack.sql.expression.gen.script.ScriptTemplate;
1014
import org.elasticsearch.xpack.sql.tree.Location;
1115

@@ -34,12 +38,20 @@ public final UnaryScalarFunction replaceChildren(List<Expression> newChildren) {
3438
}
3539
return replaceChild(newChildren.get(0));
3640
}
41+
3742
protected abstract UnaryScalarFunction replaceChild(Expression newChild);
3843

3944
public Expression field() {
4045
return field;
4146
}
4247

48+
@Override
49+
public final Pipe makePipe() {
50+
return new UnaryPipe(location(), this, Expressions.pipe(field()), makeProcessor());
51+
}
52+
53+
protected abstract Processor makeProcessor();
54+
4355
@Override
4456
public boolean foldable() {
4557
return field.foldable();

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

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,9 @@
66
package org.elasticsearch.xpack.sql.expression.function.scalar.datetime;
77

88
import org.elasticsearch.xpack.sql.expression.Expression;
9-
import org.elasticsearch.xpack.sql.expression.Expressions;
109
import org.elasticsearch.xpack.sql.expression.FieldAttribute;
1110
import org.elasticsearch.xpack.sql.expression.function.scalar.datetime.DateTimeProcessor.DateTimeExtractor;
12-
import org.elasticsearch.xpack.sql.expression.gen.pipeline.Pipe;
13-
import org.elasticsearch.xpack.sql.expression.gen.pipeline.UnaryPipe;
11+
import org.elasticsearch.xpack.sql.expression.gen.processor.Processor;
1412
import org.elasticsearch.xpack.sql.expression.gen.script.ParamsBuilder;
1513
import org.elasticsearch.xpack.sql.expression.gen.script.ScriptTemplate;
1614
import org.elasticsearch.xpack.sql.tree.Location;
@@ -63,13 +61,13 @@ public ScriptTemplate scriptWithField(FieldAttribute field) {
6361
*/
6462
protected abstract ChronoField chronoField();
6563

64+
protected abstract DateTimeExtractor extractor();
65+
6666
@Override
67-
protected Pipe makePipe() {
68-
return new UnaryPipe(location(), this, Expressions.pipe(field()), new DateTimeProcessor(extractor(), timeZone()));
67+
protected Processor makeProcessor() {
68+
return new DateTimeProcessor(extractor(), timeZone());
6969
}
7070

71-
protected abstract DateTimeExtractor extractor();
72-
7371
@Override
7472
public DataType dataType() {
7573
return DataType.INTEGER;

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

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,9 @@
66
package org.elasticsearch.xpack.sql.expression.function.scalar.datetime;
77

88
import org.elasticsearch.xpack.sql.expression.Expression;
9-
import org.elasticsearch.xpack.sql.expression.Expressions;
109
import org.elasticsearch.xpack.sql.expression.FieldAttribute;
1110
import org.elasticsearch.xpack.sql.expression.function.scalar.datetime.NamedDateTimeProcessor.NameExtractor;
12-
import org.elasticsearch.xpack.sql.expression.gen.pipeline.Pipe;
13-
import org.elasticsearch.xpack.sql.expression.gen.pipeline.UnaryPipe;
11+
import org.elasticsearch.xpack.sql.expression.gen.processor.Processor;
1412
import org.elasticsearch.xpack.sql.expression.gen.script.ScriptTemplate;
1513
import org.elasticsearch.xpack.sql.tree.Location;
1614
import org.elasticsearch.xpack.sql.type.DataType;
@@ -51,8 +49,8 @@ public ScriptTemplate scriptWithField(FieldAttribute field) {
5149
}
5250

5351
@Override
54-
protected final Pipe makePipe() {
55-
return new UnaryPipe(location(), this, Expressions.pipe(field()), new NamedDateTimeProcessor(nameExtractor, timeZone()));
52+
protected Processor makeProcessor() {
53+
return new NamedDateTimeProcessor(nameExtractor, timeZone());
5654
}
5755

5856
@Override

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

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,8 @@
77
package org.elasticsearch.xpack.sql.expression.function.scalar.datetime;
88

99
import org.elasticsearch.xpack.sql.expression.Expression;
10-
import org.elasticsearch.xpack.sql.expression.Expressions;
1110
import org.elasticsearch.xpack.sql.expression.FieldAttribute;
12-
import org.elasticsearch.xpack.sql.expression.gen.pipeline.Pipe;
13-
import org.elasticsearch.xpack.sql.expression.gen.pipeline.UnaryPipe;
11+
import org.elasticsearch.xpack.sql.expression.gen.processor.Processor;
1412
import org.elasticsearch.xpack.sql.expression.gen.script.ScriptTemplate;
1513
import org.elasticsearch.xpack.sql.tree.Location;
1614
import org.elasticsearch.xpack.sql.tree.NodeInfo.NodeCtor2;
@@ -53,8 +51,8 @@ protected Quarter replaceChild(Expression newChild) {
5351
}
5452

5553
@Override
56-
protected Pipe makePipe() {
57-
return new UnaryPipe(location(), this, Expressions.pipe(field()), new QuarterProcessor(timeZone()));
54+
protected Processor makeProcessor() {
55+
return new QuarterProcessor(timeZone());
5856
}
5957

6058
@Override

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

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,9 @@
66
package org.elasticsearch.xpack.sql.expression.function.scalar.math;
77

88
import org.elasticsearch.xpack.sql.expression.Expression;
9-
import org.elasticsearch.xpack.sql.expression.Expressions;
109
import org.elasticsearch.xpack.sql.expression.function.scalar.UnaryScalarFunction;
1110
import org.elasticsearch.xpack.sql.expression.function.scalar.math.MathProcessor.MathOperation;
12-
import org.elasticsearch.xpack.sql.expression.gen.pipeline.Pipe;
13-
import org.elasticsearch.xpack.sql.expression.gen.pipeline.UnaryPipe;
11+
import org.elasticsearch.xpack.sql.expression.gen.processor.Processor;
1412
import org.elasticsearch.xpack.sql.tree.Location;
1513
import org.elasticsearch.xpack.sql.type.DataType;
1614

@@ -64,8 +62,8 @@ protected TypeResolution resolveType() {
6462
}
6563

6664
@Override
67-
protected final Pipe makePipe() {
68-
return new UnaryPipe(location(), this, Expressions.pipe(field()), new MathProcessor(operation()));
65+
protected Processor makeProcessor() {
66+
return new MathProcessor(operation());
6967
}
7068

7169
protected abstract MathOperation operation();

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

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,10 @@
66
package org.elasticsearch.xpack.sql.expression.function.scalar.string;
77

88
import org.elasticsearch.xpack.sql.expression.Expression;
9-
import org.elasticsearch.xpack.sql.expression.Expressions;
109
import org.elasticsearch.xpack.sql.expression.FieldAttribute;
1110
import org.elasticsearch.xpack.sql.expression.function.scalar.UnaryScalarFunction;
1211
import org.elasticsearch.xpack.sql.expression.function.scalar.string.StringProcessor.StringOperation;
13-
import org.elasticsearch.xpack.sql.expression.gen.pipeline.Pipe;
14-
import org.elasticsearch.xpack.sql.expression.gen.pipeline.UnaryPipe;
12+
import org.elasticsearch.xpack.sql.expression.gen.processor.Processor;
1513
import org.elasticsearch.xpack.sql.expression.gen.script.ScriptTemplate;
1614
import org.elasticsearch.xpack.sql.tree.Location;
1715
import org.elasticsearch.xpack.sql.util.StringUtils;
@@ -49,8 +47,8 @@ protected TypeResolution resolveType() {
4947
}
5048

5149
@Override
52-
protected final Pipe makePipe() {
53-
return new UnaryPipe(location(), this, Expressions.pipe(field()), new StringProcessor(operation()));
50+
protected Processor makeProcessor() {
51+
return new StringProcessor(operation());
5452
}
5553

5654
protected abstract StringOperation operation();

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

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,10 @@
66
package org.elasticsearch.xpack.sql.expression.function.scalar.string;
77

88
import org.elasticsearch.xpack.sql.expression.Expression;
9-
import org.elasticsearch.xpack.sql.expression.Expressions;
109
import org.elasticsearch.xpack.sql.expression.FieldAttribute;
1110
import org.elasticsearch.xpack.sql.expression.function.scalar.UnaryScalarFunction;
1211
import org.elasticsearch.xpack.sql.expression.function.scalar.string.StringProcessor.StringOperation;
13-
import org.elasticsearch.xpack.sql.expression.gen.pipeline.Pipe;
14-
import org.elasticsearch.xpack.sql.expression.gen.pipeline.UnaryPipe;
12+
import org.elasticsearch.xpack.sql.expression.gen.processor.Processor;
1513
import org.elasticsearch.xpack.sql.expression.gen.script.ScriptTemplate;
1614
import org.elasticsearch.xpack.sql.tree.Location;
1715

@@ -51,8 +49,8 @@ protected TypeResolution resolveType() {
5149
}
5250

5351
@Override
54-
protected final Pipe makePipe() {
55-
return new UnaryPipe(location(), this, Expressions.pipe(field()), new StringProcessor(operation()));
52+
protected Processor makeProcessor() {
53+
return new StringProcessor(operation());
5654
}
5755

5856
protected abstract StringOperation operation();
@@ -72,6 +70,11 @@ public String processScript(String template) {
7270
template));
7371
}
7472

73+
@Override
74+
public int hashCode() {
75+
return Objects.hash(field());
76+
}
77+
7578
@Override
7679
public boolean equals(Object obj) {
7780
if (obj == null || obj.getClass() != getClass()) {
@@ -80,9 +83,4 @@ public boolean equals(Object obj) {
8083
UnaryStringIntFunction other = (UnaryStringIntFunction) obj;
8184
return Objects.equals(other.field(), field());
8285
}
83-
84-
@Override
85-
public int hashCode() {
86-
return Objects.hash(field());
87-
}
8886
}

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

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,11 @@
2121
import org.elasticsearch.xpack.sql.expression.function.scalar.string.ReplaceFunctionProcessor;
2222
import org.elasticsearch.xpack.sql.expression.function.scalar.string.StringProcessor.StringOperation;
2323
import org.elasticsearch.xpack.sql.expression.function.scalar.string.SubstringFunctionProcessor;
24+
import org.elasticsearch.xpack.sql.expression.predicate.IsNotNullProcessor;
2425
import org.elasticsearch.xpack.sql.expression.predicate.logical.BinaryLogicProcessor.BinaryLogicOperation;
26+
import org.elasticsearch.xpack.sql.expression.predicate.logical.NotProcessor;
2527
import org.elasticsearch.xpack.sql.expression.predicate.operator.arithmetic.BinaryArithmeticProcessor.BinaryArithmeticOperation;
28+
import org.elasticsearch.xpack.sql.expression.predicate.operator.arithmetic.UnaryArithmeticProcessor.UnaryArithmeticOperation;
2629
import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.BinaryComparisonProcessor.BinaryComparisonOperation;
2730
import org.elasticsearch.xpack.sql.expression.predicate.regex.RegexProcessor.RegexOperation;
2831
import org.elasticsearch.xpack.sql.util.StringUtils;
@@ -102,6 +105,14 @@ public static Boolean or(Boolean left, Boolean right) {
102105
return BinaryLogicOperation.OR.apply(left, right);
103106
}
104107

108+
public static Boolean not(Boolean expression) {
109+
return NotProcessor.apply(expression);
110+
}
111+
112+
public static Boolean notNull(Object expression) {
113+
return IsNotNullProcessor.apply(expression);
114+
}
115+
105116
//
106117
// Regex
107118
//
@@ -116,20 +127,24 @@ public static Number add(Number left, Number right) {
116127
return BinaryArithmeticOperation.ADD.apply(left, right);
117128
}
118129

119-
public static Number sub(Number left, Number right) {
120-
return BinaryArithmeticOperation.SUB.apply(left, right);
130+
public static Number div(Number left, Number right) {
131+
return BinaryArithmeticOperation.DIV.apply(left, right);
132+
}
133+
134+
public static Number mod(Number left, Number right) {
135+
return BinaryArithmeticOperation.MOD.apply(left, right);
121136
}
122137

123138
public static Number mul(Number left, Number right) {
124139
return BinaryArithmeticOperation.MUL.apply(left, right);
125140
}
126141

127-
public static Number div(Number left, Number right) {
128-
return BinaryArithmeticOperation.DIV.apply(left, right);
142+
public static Number neg(Number value) {
143+
return UnaryArithmeticOperation.NEGATE.apply(value);
129144
}
130145

131-
public static Number mod(Number left, Number right) {
132-
return BinaryArithmeticOperation.MOD.apply(left, right);
146+
public static Number sub(Number left, Number right) {
147+
return BinaryArithmeticOperation.SUB.apply(left, right);
133148
}
134149

135150
public static Number round(Number v, Number s) {

x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/gen/script/Scripts.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,16 @@
2424

2525
public final class Scripts {
2626

27+
public static final String DOC_VALUE = "doc[{}].value";
28+
public static final String SQL_SCRIPTS = "{sql}";
29+
public static final String PARAM = "{}";
30+
2731
private Scripts() {}
2832

2933
private static final Map<Pattern, String> FORMATTING_PATTERNS = Collections.unmodifiableMap(Stream.of(
30-
new SimpleEntry<>("doc[{}].value", "{sql}.docValue(doc,{})"),
31-
new SimpleEntry<>("{sql}", InternalSqlScriptUtils.class.getSimpleName()),
32-
new SimpleEntry<>("{}", "params.%s"))
34+
new SimpleEntry<>(DOC_VALUE, SQL_SCRIPTS + ".docValue(doc,{})"),
35+
new SimpleEntry<>(SQL_SCRIPTS, InternalSqlScriptUtils.class.getSimpleName()),
36+
new SimpleEntry<>(PARAM, "params.%s"))
3337
.collect(toMap(e -> Pattern.compile(e.getKey(), Pattern.LITERAL), Map.Entry::getValue, (a, b) -> a, LinkedHashMap::new)));
3438

3539
/**
@@ -83,4 +87,4 @@ public static ScriptTemplate binaryMethod(String methodName, ScriptTemplate left
8387
.build(),
8488
dataType);
8589
}
86-
}
90+
}

x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/IsNotNull.java

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,24 @@
55
*/
66
package org.elasticsearch.xpack.sql.expression.predicate;
77

8-
import org.elasticsearch.xpack.sql.SqlIllegalArgumentException;
98
import org.elasticsearch.xpack.sql.expression.Expression;
10-
import org.elasticsearch.xpack.sql.expression.UnaryExpression;
11-
import org.elasticsearch.xpack.sql.expression.gen.pipeline.Pipe;
12-
import org.elasticsearch.xpack.sql.expression.gen.script.ScriptTemplate;
9+
import org.elasticsearch.xpack.sql.expression.function.scalar.UnaryScalarFunction;
10+
import org.elasticsearch.xpack.sql.expression.gen.processor.Processor;
11+
import org.elasticsearch.xpack.sql.expression.gen.script.Scripts;
1312
import org.elasticsearch.xpack.sql.tree.Location;
1413
import org.elasticsearch.xpack.sql.tree.NodeInfo;
1514
import org.elasticsearch.xpack.sql.type.DataType;
1615
import org.elasticsearch.xpack.sql.type.DataTypes;
1716

18-
public class IsNotNull extends UnaryExpression {
17+
public class IsNotNull extends UnaryScalarFunction {
1918

20-
public IsNotNull(Location location, Expression child) {
21-
super(location, child);
19+
public IsNotNull(Location location, Expression field) {
20+
super(location, field);
2221
}
2322

2423
@Override
2524
protected NodeInfo<IsNotNull> info() {
26-
return NodeInfo.create(this, IsNotNull::new, child());
25+
return NodeInfo.create(this, IsNotNull::new, field());
2726
}
2827

2928
@Override
@@ -33,17 +32,17 @@ protected IsNotNull replaceChild(Expression newChild) {
3332

3433
@Override
3534
public Object fold() {
36-
return child().fold() != null && !DataTypes.isNull(child().dataType());
35+
return field().fold() != null && !DataTypes.isNull(field().dataType());
3736
}
3837

3938
@Override
40-
protected Pipe makePipe() {
41-
throw new SqlIllegalArgumentException("Not supported yet");
39+
protected Processor makeProcessor() {
40+
return IsNotNullProcessor.INSTANCE;
4241
}
4342

4443
@Override
45-
public ScriptTemplate asScript() {
46-
throw new SqlIllegalArgumentException("Not supported yet");
44+
public String processScript(String script) {
45+
return Scripts.formatTemplate(Scripts.SQL_SCRIPTS + ".notNull(" + script + ")");
4746
}
4847

4948
@Override
@@ -55,9 +54,4 @@ public boolean nullable() {
5554
public DataType dataType() {
5655
return DataType.BOOLEAN;
5756
}
58-
59-
@Override
60-
public String toString() {
61-
return child().toString() + " IS NOT NULL";
62-
}
63-
}
57+
}

0 commit comments

Comments
 (0)