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
This commit is contained in:
parent
43f6ba1c63
commit
5a7b8c0e69
|
@ -6,9 +6,7 @@
|
||||||
package org.elasticsearch.xpack.sql.expression.function.scalar;
|
package org.elasticsearch.xpack.sql.expression.function.scalar;
|
||||||
|
|
||||||
import org.elasticsearch.xpack.sql.expression.Expression;
|
import org.elasticsearch.xpack.sql.expression.Expression;
|
||||||
import org.elasticsearch.xpack.sql.expression.Expressions;
|
import org.elasticsearch.xpack.sql.expression.gen.processor.Processor;
|
||||||
import org.elasticsearch.xpack.sql.expression.gen.pipeline.Pipe;
|
|
||||||
import org.elasticsearch.xpack.sql.expression.gen.pipeline.UnaryPipe;
|
|
||||||
import org.elasticsearch.xpack.sql.tree.Location;
|
import org.elasticsearch.xpack.sql.tree.Location;
|
||||||
import org.elasticsearch.xpack.sql.tree.NodeInfo;
|
import org.elasticsearch.xpack.sql.tree.NodeInfo;
|
||||||
import org.elasticsearch.xpack.sql.type.DataType;
|
import org.elasticsearch.xpack.sql.type.DataType;
|
||||||
|
@ -71,9 +69,8 @@ public class Cast extends UnaryScalarFunction {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Pipe makePipe() {
|
protected Processor makeProcessor() {
|
||||||
return new UnaryPipe(location(), this, Expressions.pipe(field()),
|
return new CastProcessor(DataTypeConversion.conversionFor(from(), to()));
|
||||||
new CastProcessor(DataTypeConversion.conversionFor(from(), to())));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -6,6 +6,10 @@
|
||||||
package org.elasticsearch.xpack.sql.expression.function.scalar;
|
package org.elasticsearch.xpack.sql.expression.function.scalar;
|
||||||
|
|
||||||
import org.elasticsearch.xpack.sql.expression.Expression;
|
import org.elasticsearch.xpack.sql.expression.Expression;
|
||||||
|
import org.elasticsearch.xpack.sql.expression.Expressions;
|
||||||
|
import org.elasticsearch.xpack.sql.expression.gen.pipeline.Pipe;
|
||||||
|
import org.elasticsearch.xpack.sql.expression.gen.pipeline.UnaryPipe;
|
||||||
|
import org.elasticsearch.xpack.sql.expression.gen.processor.Processor;
|
||||||
import org.elasticsearch.xpack.sql.expression.gen.script.ScriptTemplate;
|
import org.elasticsearch.xpack.sql.expression.gen.script.ScriptTemplate;
|
||||||
import org.elasticsearch.xpack.sql.tree.Location;
|
import org.elasticsearch.xpack.sql.tree.Location;
|
||||||
|
|
||||||
|
@ -34,12 +38,20 @@ public abstract class UnaryScalarFunction extends ScalarFunction {
|
||||||
}
|
}
|
||||||
return replaceChild(newChildren.get(0));
|
return replaceChild(newChildren.get(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract UnaryScalarFunction replaceChild(Expression newChild);
|
protected abstract UnaryScalarFunction replaceChild(Expression newChild);
|
||||||
|
|
||||||
public Expression field() {
|
public Expression field() {
|
||||||
return field;
|
return field;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final Pipe makePipe() {
|
||||||
|
return new UnaryPipe(location(), this, Expressions.pipe(field()), makeProcessor());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract Processor makeProcessor();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean foldable() {
|
public boolean foldable() {
|
||||||
return field.foldable();
|
return field.foldable();
|
||||||
|
|
|
@ -6,11 +6,9 @@
|
||||||
package org.elasticsearch.xpack.sql.expression.function.scalar.datetime;
|
package org.elasticsearch.xpack.sql.expression.function.scalar.datetime;
|
||||||
|
|
||||||
import org.elasticsearch.xpack.sql.expression.Expression;
|
import org.elasticsearch.xpack.sql.expression.Expression;
|
||||||
import org.elasticsearch.xpack.sql.expression.Expressions;
|
|
||||||
import org.elasticsearch.xpack.sql.expression.FieldAttribute;
|
import org.elasticsearch.xpack.sql.expression.FieldAttribute;
|
||||||
import org.elasticsearch.xpack.sql.expression.function.scalar.datetime.DateTimeProcessor.DateTimeExtractor;
|
import org.elasticsearch.xpack.sql.expression.function.scalar.datetime.DateTimeProcessor.DateTimeExtractor;
|
||||||
import org.elasticsearch.xpack.sql.expression.gen.pipeline.Pipe;
|
import org.elasticsearch.xpack.sql.expression.gen.processor.Processor;
|
||||||
import org.elasticsearch.xpack.sql.expression.gen.pipeline.UnaryPipe;
|
|
||||||
import org.elasticsearch.xpack.sql.expression.gen.script.ParamsBuilder;
|
import org.elasticsearch.xpack.sql.expression.gen.script.ParamsBuilder;
|
||||||
import org.elasticsearch.xpack.sql.expression.gen.script.ScriptTemplate;
|
import org.elasticsearch.xpack.sql.expression.gen.script.ScriptTemplate;
|
||||||
import org.elasticsearch.xpack.sql.tree.Location;
|
import org.elasticsearch.xpack.sql.tree.Location;
|
||||||
|
@ -63,13 +61,13 @@ public abstract class DateTimeFunction extends BaseDateTimeFunction {
|
||||||
*/
|
*/
|
||||||
protected abstract ChronoField chronoField();
|
protected abstract ChronoField chronoField();
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Pipe makePipe() {
|
|
||||||
return new UnaryPipe(location(), this, Expressions.pipe(field()), new DateTimeProcessor(extractor(), timeZone()));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract DateTimeExtractor extractor();
|
protected abstract DateTimeExtractor extractor();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Processor makeProcessor() {
|
||||||
|
return new DateTimeProcessor(extractor(), timeZone());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DataType dataType() {
|
public DataType dataType() {
|
||||||
return DataType.INTEGER;
|
return DataType.INTEGER;
|
||||||
|
|
|
@ -6,11 +6,9 @@
|
||||||
package org.elasticsearch.xpack.sql.expression.function.scalar.datetime;
|
package org.elasticsearch.xpack.sql.expression.function.scalar.datetime;
|
||||||
|
|
||||||
import org.elasticsearch.xpack.sql.expression.Expression;
|
import org.elasticsearch.xpack.sql.expression.Expression;
|
||||||
import org.elasticsearch.xpack.sql.expression.Expressions;
|
|
||||||
import org.elasticsearch.xpack.sql.expression.FieldAttribute;
|
import org.elasticsearch.xpack.sql.expression.FieldAttribute;
|
||||||
import org.elasticsearch.xpack.sql.expression.function.scalar.datetime.NamedDateTimeProcessor.NameExtractor;
|
import org.elasticsearch.xpack.sql.expression.function.scalar.datetime.NamedDateTimeProcessor.NameExtractor;
|
||||||
import org.elasticsearch.xpack.sql.expression.gen.pipeline.Pipe;
|
import org.elasticsearch.xpack.sql.expression.gen.processor.Processor;
|
||||||
import org.elasticsearch.xpack.sql.expression.gen.pipeline.UnaryPipe;
|
|
||||||
import org.elasticsearch.xpack.sql.expression.gen.script.ScriptTemplate;
|
import org.elasticsearch.xpack.sql.expression.gen.script.ScriptTemplate;
|
||||||
import org.elasticsearch.xpack.sql.tree.Location;
|
import org.elasticsearch.xpack.sql.tree.Location;
|
||||||
import org.elasticsearch.xpack.sql.type.DataType;
|
import org.elasticsearch.xpack.sql.type.DataType;
|
||||||
|
@ -51,8 +49,8 @@ abstract class NamedDateTimeFunction extends BaseDateTimeFunction {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected final Pipe makePipe() {
|
protected Processor makeProcessor() {
|
||||||
return new UnaryPipe(location(), this, Expressions.pipe(field()), new NamedDateTimeProcessor(nameExtractor, timeZone()));
|
return new NamedDateTimeProcessor(nameExtractor, timeZone());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -7,10 +7,8 @@
|
||||||
package org.elasticsearch.xpack.sql.expression.function.scalar.datetime;
|
package org.elasticsearch.xpack.sql.expression.function.scalar.datetime;
|
||||||
|
|
||||||
import org.elasticsearch.xpack.sql.expression.Expression;
|
import org.elasticsearch.xpack.sql.expression.Expression;
|
||||||
import org.elasticsearch.xpack.sql.expression.Expressions;
|
|
||||||
import org.elasticsearch.xpack.sql.expression.FieldAttribute;
|
import org.elasticsearch.xpack.sql.expression.FieldAttribute;
|
||||||
import org.elasticsearch.xpack.sql.expression.gen.pipeline.Pipe;
|
import org.elasticsearch.xpack.sql.expression.gen.processor.Processor;
|
||||||
import org.elasticsearch.xpack.sql.expression.gen.pipeline.UnaryPipe;
|
|
||||||
import org.elasticsearch.xpack.sql.expression.gen.script.ScriptTemplate;
|
import org.elasticsearch.xpack.sql.expression.gen.script.ScriptTemplate;
|
||||||
import org.elasticsearch.xpack.sql.tree.Location;
|
import org.elasticsearch.xpack.sql.tree.Location;
|
||||||
import org.elasticsearch.xpack.sql.tree.NodeInfo.NodeCtor2;
|
import org.elasticsearch.xpack.sql.tree.NodeInfo.NodeCtor2;
|
||||||
|
@ -53,8 +51,8 @@ public class Quarter extends BaseDateTimeFunction {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Pipe makePipe() {
|
protected Processor makeProcessor() {
|
||||||
return new UnaryPipe(location(), this, Expressions.pipe(field()), new QuarterProcessor(timeZone()));
|
return new QuarterProcessor(timeZone());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -6,11 +6,9 @@
|
||||||
package org.elasticsearch.xpack.sql.expression.function.scalar.math;
|
package org.elasticsearch.xpack.sql.expression.function.scalar.math;
|
||||||
|
|
||||||
import org.elasticsearch.xpack.sql.expression.Expression;
|
import org.elasticsearch.xpack.sql.expression.Expression;
|
||||||
import org.elasticsearch.xpack.sql.expression.Expressions;
|
|
||||||
import org.elasticsearch.xpack.sql.expression.function.scalar.UnaryScalarFunction;
|
import org.elasticsearch.xpack.sql.expression.function.scalar.UnaryScalarFunction;
|
||||||
import org.elasticsearch.xpack.sql.expression.function.scalar.math.MathProcessor.MathOperation;
|
import org.elasticsearch.xpack.sql.expression.function.scalar.math.MathProcessor.MathOperation;
|
||||||
import org.elasticsearch.xpack.sql.expression.gen.pipeline.Pipe;
|
import org.elasticsearch.xpack.sql.expression.gen.processor.Processor;
|
||||||
import org.elasticsearch.xpack.sql.expression.gen.pipeline.UnaryPipe;
|
|
||||||
import org.elasticsearch.xpack.sql.tree.Location;
|
import org.elasticsearch.xpack.sql.tree.Location;
|
||||||
import org.elasticsearch.xpack.sql.type.DataType;
|
import org.elasticsearch.xpack.sql.type.DataType;
|
||||||
|
|
||||||
|
@ -64,8 +62,8 @@ public abstract class MathFunction extends UnaryScalarFunction {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected final Pipe makePipe() {
|
protected Processor makeProcessor() {
|
||||||
return new UnaryPipe(location(), this, Expressions.pipe(field()), new MathProcessor(operation()));
|
return new MathProcessor(operation());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract MathOperation operation();
|
protected abstract MathOperation operation();
|
||||||
|
|
|
@ -6,12 +6,10 @@
|
||||||
package org.elasticsearch.xpack.sql.expression.function.scalar.string;
|
package org.elasticsearch.xpack.sql.expression.function.scalar.string;
|
||||||
|
|
||||||
import org.elasticsearch.xpack.sql.expression.Expression;
|
import org.elasticsearch.xpack.sql.expression.Expression;
|
||||||
import org.elasticsearch.xpack.sql.expression.Expressions;
|
|
||||||
import org.elasticsearch.xpack.sql.expression.FieldAttribute;
|
import org.elasticsearch.xpack.sql.expression.FieldAttribute;
|
||||||
import org.elasticsearch.xpack.sql.expression.function.scalar.UnaryScalarFunction;
|
import org.elasticsearch.xpack.sql.expression.function.scalar.UnaryScalarFunction;
|
||||||
import org.elasticsearch.xpack.sql.expression.function.scalar.string.StringProcessor.StringOperation;
|
import org.elasticsearch.xpack.sql.expression.function.scalar.string.StringProcessor.StringOperation;
|
||||||
import org.elasticsearch.xpack.sql.expression.gen.pipeline.Pipe;
|
import org.elasticsearch.xpack.sql.expression.gen.processor.Processor;
|
||||||
import org.elasticsearch.xpack.sql.expression.gen.pipeline.UnaryPipe;
|
|
||||||
import org.elasticsearch.xpack.sql.expression.gen.script.ScriptTemplate;
|
import org.elasticsearch.xpack.sql.expression.gen.script.ScriptTemplate;
|
||||||
import org.elasticsearch.xpack.sql.tree.Location;
|
import org.elasticsearch.xpack.sql.tree.Location;
|
||||||
import org.elasticsearch.xpack.sql.util.StringUtils;
|
import org.elasticsearch.xpack.sql.util.StringUtils;
|
||||||
|
@ -49,8 +47,8 @@ public abstract class UnaryStringFunction extends UnaryScalarFunction {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected final Pipe makePipe() {
|
protected Processor makeProcessor() {
|
||||||
return new UnaryPipe(location(), this, Expressions.pipe(field()), new StringProcessor(operation()));
|
return new StringProcessor(operation());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract StringOperation operation();
|
protected abstract StringOperation operation();
|
||||||
|
|
|
@ -6,12 +6,10 @@
|
||||||
package org.elasticsearch.xpack.sql.expression.function.scalar.string;
|
package org.elasticsearch.xpack.sql.expression.function.scalar.string;
|
||||||
|
|
||||||
import org.elasticsearch.xpack.sql.expression.Expression;
|
import org.elasticsearch.xpack.sql.expression.Expression;
|
||||||
import org.elasticsearch.xpack.sql.expression.Expressions;
|
|
||||||
import org.elasticsearch.xpack.sql.expression.FieldAttribute;
|
import org.elasticsearch.xpack.sql.expression.FieldAttribute;
|
||||||
import org.elasticsearch.xpack.sql.expression.function.scalar.UnaryScalarFunction;
|
import org.elasticsearch.xpack.sql.expression.function.scalar.UnaryScalarFunction;
|
||||||
import org.elasticsearch.xpack.sql.expression.function.scalar.string.StringProcessor.StringOperation;
|
import org.elasticsearch.xpack.sql.expression.function.scalar.string.StringProcessor.StringOperation;
|
||||||
import org.elasticsearch.xpack.sql.expression.gen.pipeline.Pipe;
|
import org.elasticsearch.xpack.sql.expression.gen.processor.Processor;
|
||||||
import org.elasticsearch.xpack.sql.expression.gen.pipeline.UnaryPipe;
|
|
||||||
import org.elasticsearch.xpack.sql.expression.gen.script.ScriptTemplate;
|
import org.elasticsearch.xpack.sql.expression.gen.script.ScriptTemplate;
|
||||||
import org.elasticsearch.xpack.sql.tree.Location;
|
import org.elasticsearch.xpack.sql.tree.Location;
|
||||||
|
|
||||||
|
@ -51,8 +49,8 @@ public abstract class UnaryStringIntFunction extends UnaryScalarFunction {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected final Pipe makePipe() {
|
protected Processor makeProcessor() {
|
||||||
return new UnaryPipe(location(), this, Expressions.pipe(field()), new StringProcessor(operation()));
|
return new StringProcessor(operation());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract StringOperation operation();
|
protected abstract StringOperation operation();
|
||||||
|
@ -72,6 +70,11 @@ public abstract class UnaryStringIntFunction extends UnaryScalarFunction {
|
||||||
template));
|
template));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(field());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
if (obj == null || obj.getClass() != getClass()) {
|
if (obj == null || obj.getClass() != getClass()) {
|
||||||
|
@ -80,9 +83,4 @@ public abstract class UnaryStringIntFunction extends UnaryScalarFunction {
|
||||||
UnaryStringIntFunction other = (UnaryStringIntFunction) obj;
|
UnaryStringIntFunction other = (UnaryStringIntFunction) obj;
|
||||||
return Objects.equals(other.field(), field());
|
return Objects.equals(other.field(), field());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hash(field());
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -21,8 +21,11 @@ import org.elasticsearch.xpack.sql.expression.function.scalar.string.LocateFunct
|
||||||
import org.elasticsearch.xpack.sql.expression.function.scalar.string.ReplaceFunctionProcessor;
|
import org.elasticsearch.xpack.sql.expression.function.scalar.string.ReplaceFunctionProcessor;
|
||||||
import org.elasticsearch.xpack.sql.expression.function.scalar.string.StringProcessor.StringOperation;
|
import org.elasticsearch.xpack.sql.expression.function.scalar.string.StringProcessor.StringOperation;
|
||||||
import org.elasticsearch.xpack.sql.expression.function.scalar.string.SubstringFunctionProcessor;
|
import org.elasticsearch.xpack.sql.expression.function.scalar.string.SubstringFunctionProcessor;
|
||||||
|
import org.elasticsearch.xpack.sql.expression.predicate.IsNotNullProcessor;
|
||||||
import org.elasticsearch.xpack.sql.expression.predicate.logical.BinaryLogicProcessor.BinaryLogicOperation;
|
import org.elasticsearch.xpack.sql.expression.predicate.logical.BinaryLogicProcessor.BinaryLogicOperation;
|
||||||
|
import org.elasticsearch.xpack.sql.expression.predicate.logical.NotProcessor;
|
||||||
import org.elasticsearch.xpack.sql.expression.predicate.operator.arithmetic.BinaryArithmeticProcessor.BinaryArithmeticOperation;
|
import org.elasticsearch.xpack.sql.expression.predicate.operator.arithmetic.BinaryArithmeticProcessor.BinaryArithmeticOperation;
|
||||||
|
import org.elasticsearch.xpack.sql.expression.predicate.operator.arithmetic.UnaryArithmeticProcessor.UnaryArithmeticOperation;
|
||||||
import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.BinaryComparisonProcessor.BinaryComparisonOperation;
|
import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.BinaryComparisonProcessor.BinaryComparisonOperation;
|
||||||
import org.elasticsearch.xpack.sql.expression.predicate.regex.RegexProcessor.RegexOperation;
|
import org.elasticsearch.xpack.sql.expression.predicate.regex.RegexProcessor.RegexOperation;
|
||||||
import org.elasticsearch.xpack.sql.util.StringUtils;
|
import org.elasticsearch.xpack.sql.util.StringUtils;
|
||||||
|
@ -102,6 +105,14 @@ public final class InternalSqlScriptUtils {
|
||||||
return BinaryLogicOperation.OR.apply(left, right);
|
return BinaryLogicOperation.OR.apply(left, right);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Boolean not(Boolean expression) {
|
||||||
|
return NotProcessor.apply(expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Boolean notNull(Object expression) {
|
||||||
|
return IsNotNullProcessor.apply(expression);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Regex
|
// Regex
|
||||||
//
|
//
|
||||||
|
@ -116,14 +127,6 @@ public final class InternalSqlScriptUtils {
|
||||||
return BinaryArithmeticOperation.ADD.apply(left, right);
|
return BinaryArithmeticOperation.ADD.apply(left, right);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Number sub(Number left, Number right) {
|
|
||||||
return BinaryArithmeticOperation.SUB.apply(left, right);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Number mul(Number left, Number right) {
|
|
||||||
return BinaryArithmeticOperation.MUL.apply(left, right);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Number div(Number left, Number right) {
|
public static Number div(Number left, Number right) {
|
||||||
return BinaryArithmeticOperation.DIV.apply(left, right);
|
return BinaryArithmeticOperation.DIV.apply(left, right);
|
||||||
}
|
}
|
||||||
|
@ -132,6 +135,18 @@ public final class InternalSqlScriptUtils {
|
||||||
return BinaryArithmeticOperation.MOD.apply(left, right);
|
return BinaryArithmeticOperation.MOD.apply(left, right);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Number mul(Number left, Number right) {
|
||||||
|
return BinaryArithmeticOperation.MUL.apply(left, right);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Number neg(Number value) {
|
||||||
|
return UnaryArithmeticOperation.NEGATE.apply(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Number sub(Number left, Number right) {
|
||||||
|
return BinaryArithmeticOperation.SUB.apply(left, right);
|
||||||
|
}
|
||||||
|
|
||||||
public static Number round(Number v, Number s) {
|
public static Number round(Number v, Number s) {
|
||||||
return BinaryMathOperation.ROUND.apply(v, s);
|
return BinaryMathOperation.ROUND.apply(v, s);
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,12 +24,16 @@ import static org.elasticsearch.xpack.sql.expression.gen.script.ParamsBuilder.pa
|
||||||
|
|
||||||
public final class Scripts {
|
public final class Scripts {
|
||||||
|
|
||||||
|
public static final String DOC_VALUE = "doc[{}].value";
|
||||||
|
public static final String SQL_SCRIPTS = "{sql}";
|
||||||
|
public static final String PARAM = "{}";
|
||||||
|
|
||||||
private Scripts() {}
|
private Scripts() {}
|
||||||
|
|
||||||
private static final Map<Pattern, String> FORMATTING_PATTERNS = Collections.unmodifiableMap(Stream.of(
|
private static final Map<Pattern, String> FORMATTING_PATTERNS = Collections.unmodifiableMap(Stream.of(
|
||||||
new SimpleEntry<>("doc[{}].value", "{sql}.docValue(doc,{})"),
|
new SimpleEntry<>(DOC_VALUE, SQL_SCRIPTS + ".docValue(doc,{})"),
|
||||||
new SimpleEntry<>("{sql}", InternalSqlScriptUtils.class.getSimpleName()),
|
new SimpleEntry<>(SQL_SCRIPTS, InternalSqlScriptUtils.class.getSimpleName()),
|
||||||
new SimpleEntry<>("{}", "params.%s"))
|
new SimpleEntry<>(PARAM, "params.%s"))
|
||||||
.collect(toMap(e -> Pattern.compile(e.getKey(), Pattern.LITERAL), Map.Entry::getValue, (a, b) -> a, LinkedHashMap::new)));
|
.collect(toMap(e -> Pattern.compile(e.getKey(), Pattern.LITERAL), Map.Entry::getValue, (a, b) -> a, LinkedHashMap::new)));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -5,25 +5,24 @@
|
||||||
*/
|
*/
|
||||||
package org.elasticsearch.xpack.sql.expression.predicate;
|
package org.elasticsearch.xpack.sql.expression.predicate;
|
||||||
|
|
||||||
import org.elasticsearch.xpack.sql.SqlIllegalArgumentException;
|
|
||||||
import org.elasticsearch.xpack.sql.expression.Expression;
|
import org.elasticsearch.xpack.sql.expression.Expression;
|
||||||
import org.elasticsearch.xpack.sql.expression.UnaryExpression;
|
import org.elasticsearch.xpack.sql.expression.function.scalar.UnaryScalarFunction;
|
||||||
import org.elasticsearch.xpack.sql.expression.gen.pipeline.Pipe;
|
import org.elasticsearch.xpack.sql.expression.gen.processor.Processor;
|
||||||
import org.elasticsearch.xpack.sql.expression.gen.script.ScriptTemplate;
|
import org.elasticsearch.xpack.sql.expression.gen.script.Scripts;
|
||||||
import org.elasticsearch.xpack.sql.tree.Location;
|
import org.elasticsearch.xpack.sql.tree.Location;
|
||||||
import org.elasticsearch.xpack.sql.tree.NodeInfo;
|
import org.elasticsearch.xpack.sql.tree.NodeInfo;
|
||||||
import org.elasticsearch.xpack.sql.type.DataType;
|
import org.elasticsearch.xpack.sql.type.DataType;
|
||||||
import org.elasticsearch.xpack.sql.type.DataTypes;
|
import org.elasticsearch.xpack.sql.type.DataTypes;
|
||||||
|
|
||||||
public class IsNotNull extends UnaryExpression {
|
public class IsNotNull extends UnaryScalarFunction {
|
||||||
|
|
||||||
public IsNotNull(Location location, Expression child) {
|
public IsNotNull(Location location, Expression field) {
|
||||||
super(location, child);
|
super(location, field);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected NodeInfo<IsNotNull> info() {
|
protected NodeInfo<IsNotNull> info() {
|
||||||
return NodeInfo.create(this, IsNotNull::new, child());
|
return NodeInfo.create(this, IsNotNull::new, field());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -33,17 +32,17 @@ public class IsNotNull extends UnaryExpression {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object fold() {
|
public Object fold() {
|
||||||
return child().fold() != null && !DataTypes.isNull(child().dataType());
|
return field().fold() != null && !DataTypes.isNull(field().dataType());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Pipe makePipe() {
|
protected Processor makeProcessor() {
|
||||||
throw new SqlIllegalArgumentException("Not supported yet");
|
return IsNotNullProcessor.INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ScriptTemplate asScript() {
|
public String processScript(String script) {
|
||||||
throw new SqlIllegalArgumentException("Not supported yet");
|
return Scripts.formatTemplate(Scripts.SQL_SCRIPTS + ".notNull(" + script + ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -55,9 +54,4 @@ public class IsNotNull extends UnaryExpression {
|
||||||
public DataType dataType() {
|
public DataType dataType() {
|
||||||
return DataType.BOOLEAN;
|
return DataType.BOOLEAN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return child().toString() + " IS NOT NULL";
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||||
|
* or more contributor license agreements. Licensed under the Elastic License;
|
||||||
|
* you may not use this file except in compliance with the Elastic License.
|
||||||
|
*/
|
||||||
|
package org.elasticsearch.xpack.sql.expression.predicate;
|
||||||
|
|
||||||
|
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||||
|
import org.elasticsearch.xpack.sql.expression.gen.processor.Processor;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class IsNotNullProcessor implements Processor {
|
||||||
|
|
||||||
|
static final IsNotNullProcessor INSTANCE = new IsNotNullProcessor();
|
||||||
|
|
||||||
|
public static final String NAME = "inn";
|
||||||
|
|
||||||
|
private IsNotNullProcessor() {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getWriteableName() {
|
||||||
|
return NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeTo(StreamOutput out) throws IOException {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object process(Object input) {
|
||||||
|
return apply(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Boolean apply(Object input) {
|
||||||
|
return input != null ? Boolean.TRUE : Boolean.FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return IsNotNullProcessor.class.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return obj == null || getClass() != obj.getClass();
|
||||||
|
}
|
||||||
|
}
|
|
@ -26,7 +26,7 @@ public class BinaryLogicProcessor extends FunctionalBinaryProcessor<Boolean, Boo
|
||||||
if (l == null || r == null) {
|
if (l == null || r == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return l.booleanValue() && r.booleanValue();
|
return Boolean.logicalAnd(l.booleanValue(), r.booleanValue());
|
||||||
}, "&&"),
|
}, "&&"),
|
||||||
OR((l, r) -> {
|
OR((l, r) -> {
|
||||||
if (Boolean.TRUE.equals(l) || Boolean.TRUE.equals(r)) {
|
if (Boolean.TRUE.equals(l) || Boolean.TRUE.equals(r)) {
|
||||||
|
@ -35,7 +35,7 @@ public class BinaryLogicProcessor extends FunctionalBinaryProcessor<Boolean, Boo
|
||||||
if (l == null || r == null) {
|
if (l == null || r == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return l.booleanValue() || r.booleanValue();
|
return Boolean.logicalOr(l.booleanValue(), r.booleanValue());
|
||||||
}, "||");
|
}, "||");
|
||||||
|
|
||||||
private final BiFunction<Boolean, Boolean, Boolean> process;
|
private final BiFunction<Boolean, Boolean, Boolean> process;
|
||||||
|
|
|
@ -5,19 +5,16 @@
|
||||||
*/
|
*/
|
||||||
package org.elasticsearch.xpack.sql.expression.predicate.logical;
|
package org.elasticsearch.xpack.sql.expression.predicate.logical;
|
||||||
|
|
||||||
import org.elasticsearch.xpack.sql.SqlIllegalArgumentException;
|
|
||||||
import org.elasticsearch.xpack.sql.expression.Expression;
|
import org.elasticsearch.xpack.sql.expression.Expression;
|
||||||
import org.elasticsearch.xpack.sql.expression.Expressions;
|
import org.elasticsearch.xpack.sql.expression.Expressions;
|
||||||
import org.elasticsearch.xpack.sql.expression.function.scalar.UnaryScalarFunction;
|
import org.elasticsearch.xpack.sql.expression.function.scalar.UnaryScalarFunction;
|
||||||
import org.elasticsearch.xpack.sql.expression.gen.pipeline.Pipe;
|
import org.elasticsearch.xpack.sql.expression.gen.processor.Processor;
|
||||||
import org.elasticsearch.xpack.sql.expression.gen.script.ScriptTemplate;
|
import org.elasticsearch.xpack.sql.expression.gen.script.Scripts;
|
||||||
import org.elasticsearch.xpack.sql.expression.predicate.BinaryOperator.Negateable;
|
import org.elasticsearch.xpack.sql.expression.predicate.BinaryOperator.Negateable;
|
||||||
import org.elasticsearch.xpack.sql.tree.Location;
|
import org.elasticsearch.xpack.sql.tree.Location;
|
||||||
import org.elasticsearch.xpack.sql.tree.NodeInfo;
|
import org.elasticsearch.xpack.sql.tree.NodeInfo;
|
||||||
import org.elasticsearch.xpack.sql.type.DataType;
|
import org.elasticsearch.xpack.sql.type.DataType;
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
public class Not extends UnaryScalarFunction {
|
public class Not extends UnaryScalarFunction {
|
||||||
|
|
||||||
public Not(Location location, Expression child) {
|
public Not(Location location, Expression child) {
|
||||||
|
@ -45,17 +42,17 @@ public class Not extends UnaryScalarFunction {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object fold() {
|
public Object fold() {
|
||||||
return Objects.equals(field().fold(), Boolean.TRUE) ? Boolean.FALSE : Boolean.TRUE;
|
return NotProcessor.INSTANCE.process(field().fold());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Pipe makePipe() {
|
protected Processor makeProcessor() {
|
||||||
throw new SqlIllegalArgumentException("Not supported yet");
|
return NotProcessor.INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ScriptTemplate asScript() {
|
public String processScript(String script) {
|
||||||
throw new SqlIllegalArgumentException("Not supported yet");
|
return Scripts.formatTemplate(Scripts.SQL_SCRIPTS + ".not(" + script + ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
/*
|
||||||
|
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||||
|
* or more contributor license agreements. Licensed under the Elastic License;
|
||||||
|
* you may not use this file except in compliance with the Elastic License.
|
||||||
|
*/
|
||||||
|
package org.elasticsearch.xpack.sql.expression.predicate.logical;
|
||||||
|
|
||||||
|
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||||
|
import org.elasticsearch.xpack.sql.SqlIllegalArgumentException;
|
||||||
|
import org.elasticsearch.xpack.sql.expression.gen.processor.Processor;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class NotProcessor implements Processor {
|
||||||
|
|
||||||
|
static final NotProcessor INSTANCE = new NotProcessor();
|
||||||
|
|
||||||
|
public static final String NAME = "ln";
|
||||||
|
|
||||||
|
private NotProcessor() {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getWriteableName() {
|
||||||
|
return NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeTo(StreamOutput out) throws IOException {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object process(Object input) {
|
||||||
|
return apply(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Boolean apply(Object input) {
|
||||||
|
if (input == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(input instanceof Boolean)) {
|
||||||
|
throw new SqlIllegalArgumentException("A boolean is required; received {}", input);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ((Boolean) input).booleanValue() ? Boolean.FALSE : Boolean.TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return NotProcessor.class.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return obj == null || getClass() != obj.getClass();
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,9 +9,9 @@ import org.elasticsearch.xpack.sql.expression.Expression;
|
||||||
import org.elasticsearch.xpack.sql.expression.Expressions;
|
import org.elasticsearch.xpack.sql.expression.Expressions;
|
||||||
import org.elasticsearch.xpack.sql.expression.NamedExpression;
|
import org.elasticsearch.xpack.sql.expression.NamedExpression;
|
||||||
import org.elasticsearch.xpack.sql.expression.function.scalar.UnaryScalarFunction;
|
import org.elasticsearch.xpack.sql.expression.function.scalar.UnaryScalarFunction;
|
||||||
import org.elasticsearch.xpack.sql.expression.gen.pipeline.Pipe;
|
import org.elasticsearch.xpack.sql.expression.gen.processor.Processor;
|
||||||
import org.elasticsearch.xpack.sql.expression.gen.pipeline.UnaryPipe;
|
|
||||||
import org.elasticsearch.xpack.sql.expression.gen.script.ScriptWeaver;
|
import org.elasticsearch.xpack.sql.expression.gen.script.ScriptWeaver;
|
||||||
|
import org.elasticsearch.xpack.sql.expression.gen.script.Scripts;
|
||||||
import org.elasticsearch.xpack.sql.expression.predicate.operator.arithmetic.UnaryArithmeticProcessor.UnaryArithmeticOperation;
|
import org.elasticsearch.xpack.sql.expression.predicate.operator.arithmetic.UnaryArithmeticProcessor.UnaryArithmeticOperation;
|
||||||
import org.elasticsearch.xpack.sql.tree.Location;
|
import org.elasticsearch.xpack.sql.tree.Location;
|
||||||
import org.elasticsearch.xpack.sql.tree.NodeInfo;
|
import org.elasticsearch.xpack.sql.tree.NodeInfo;
|
||||||
|
@ -57,12 +57,12 @@ public class Neg extends UnaryScalarFunction implements ScriptWeaver {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String processScript(String template) {
|
public String processScript(String script) {
|
||||||
return super.processScript("-" + template);
|
return Scripts.formatTemplate(Scripts.SQL_SCRIPTS + ".neg(" + script + ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Pipe makePipe() {
|
protected Processor makeProcessor() {
|
||||||
return new UnaryPipe(location(), this, Expressions.pipe(field()), new UnaryArithmeticProcessor(UnaryArithmeticOperation.NEGATE));
|
return new UnaryArithmeticProcessor(UnaryArithmeticOperation.NEGATE);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -13,7 +13,6 @@ import org.elasticsearch.xpack.sql.expression.Expressions;
|
||||||
import org.elasticsearch.xpack.sql.expression.FieldAttribute;
|
import org.elasticsearch.xpack.sql.expression.FieldAttribute;
|
||||||
import org.elasticsearch.xpack.sql.expression.Literal;
|
import org.elasticsearch.xpack.sql.expression.Literal;
|
||||||
import org.elasticsearch.xpack.sql.expression.NamedExpression;
|
import org.elasticsearch.xpack.sql.expression.NamedExpression;
|
||||||
import org.elasticsearch.xpack.sql.expression.UnaryExpression;
|
|
||||||
import org.elasticsearch.xpack.sql.expression.function.Function;
|
import org.elasticsearch.xpack.sql.expression.function.Function;
|
||||||
import org.elasticsearch.xpack.sql.expression.function.Functions;
|
import org.elasticsearch.xpack.sql.expression.function.Functions;
|
||||||
import org.elasticsearch.xpack.sql.expression.function.aggregate.AggregateFunction;
|
import org.elasticsearch.xpack.sql.expression.function.aggregate.AggregateFunction;
|
||||||
|
@ -354,11 +353,6 @@ final class QueryTranslator {
|
||||||
return new BoolQuery(loc, false, left, right);
|
return new BoolQuery(loc, false, left, right);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Query not(Query query) {
|
|
||||||
Check.isTrue(query != null, "Expressions is null");
|
|
||||||
return new NotQuery(query.location(), query);
|
|
||||||
}
|
|
||||||
|
|
||||||
static String nameOf(Expression e) {
|
static String nameOf(Expression e) {
|
||||||
if (e instanceof DateTimeFunction) {
|
if (e instanceof DateTimeFunction) {
|
||||||
return nameOf(((DateTimeFunction) e).field());
|
return nameOf(((DateTimeFunction) e).field());
|
||||||
|
@ -484,20 +478,41 @@ final class QueryTranslator {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected QueryTranslation asQuery(Not not, boolean onAggs) {
|
protected QueryTranslation asQuery(Not not, boolean onAggs) {
|
||||||
QueryTranslation translation = toQuery(not.field(), onAggs);
|
Query query = null;
|
||||||
return new QueryTranslation(not(translation.query), translation.aggFilter);
|
AggFilter aggFilter = null;
|
||||||
|
|
||||||
|
if (onAggs) {
|
||||||
|
aggFilter = new AggFilter(not.id().toString(), not.asScript());
|
||||||
|
} else {
|
||||||
|
query = new NotQuery(not.location(), toQuery(not.field(), false).query);
|
||||||
|
// query directly on the field
|
||||||
|
if (not.field() instanceof FieldAttribute) {
|
||||||
|
query = wrapIfNested(query, not.field());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static class Nulls extends ExpressionTranslator<UnaryExpression> {
|
return new QueryTranslation(query, aggFilter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class Nulls extends ExpressionTranslator<IsNotNull> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected QueryTranslation asQuery(UnaryExpression ue, boolean onAggs) {
|
protected QueryTranslation asQuery(IsNotNull inn, boolean onAggs) {
|
||||||
// TODO: handle onAggs - missing bucket aggregation
|
Query query = null;
|
||||||
if (ue instanceof IsNotNull) {
|
AggFilter aggFilter = null;
|
||||||
return new QueryTranslation(new ExistsQuery(ue.location(), nameOf(ue.child())));
|
|
||||||
|
if (onAggs) {
|
||||||
|
aggFilter = new AggFilter(inn.id().toString(), inn.asScript());
|
||||||
|
} else {
|
||||||
|
query = new ExistsQuery(inn.location(), nameOf(inn.field()));
|
||||||
|
// query directly on the field
|
||||||
|
if (inn.field() instanceof NamedExpression) {
|
||||||
|
query = wrapIfNested(query, inn.field());
|
||||||
}
|
}
|
||||||
return null;
|
}
|
||||||
|
|
||||||
|
return new QueryTranslation(query, aggFilter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,8 @@ class org.elasticsearch.xpack.sql.expression.function.scalar.whitelist.InternalS
|
||||||
#
|
#
|
||||||
Boolean and(Boolean, Boolean)
|
Boolean and(Boolean, Boolean)
|
||||||
Boolean or(Boolean, Boolean)
|
Boolean or(Boolean, Boolean)
|
||||||
|
Boolean not(Boolean)
|
||||||
|
Boolean notNull(Object)
|
||||||
|
|
||||||
#
|
#
|
||||||
# Regex
|
# Regex
|
||||||
|
@ -43,6 +45,7 @@ class org.elasticsearch.xpack.sql.expression.function.scalar.whitelist.InternalS
|
||||||
Number div(Number, Number)
|
Number div(Number, Number)
|
||||||
Number mod(Number, Number)
|
Number mod(Number, Number)
|
||||||
Number mul(Number, Number)
|
Number mul(Number, Number)
|
||||||
|
Number neg(Number)
|
||||||
Number sub(Number, Number)
|
Number sub(Number, Number)
|
||||||
Number round(Number, Number)
|
Number round(Number, Number)
|
||||||
Number truncate(Number, Number)
|
Number truncate(Number, Number)
|
||||||
|
|
|
@ -456,6 +456,13 @@ selectHireDateGroupByHireDate
|
||||||
SELECT hire_date HD, COUNT(*) c FROM test_emp GROUP BY hire_date ORDER BY hire_date DESC;
|
SELECT hire_date HD, COUNT(*) c FROM test_emp GROUP BY hire_date ORDER BY hire_date DESC;
|
||||||
selectSalaryGroupBySalary
|
selectSalaryGroupBySalary
|
||||||
SELECT salary, COUNT(*) c FROM test_emp GROUP BY salary ORDER BY salary DESC;
|
SELECT salary, COUNT(*) c FROM test_emp GROUP BY salary ORDER BY salary DESC;
|
||||||
|
selectLangGroupByLangHavingCountIsNotNull
|
||||||
|
SELECT languages, COUNT(*) c FROM test_emp GROUP BY languages HAVING COUNT(*) IS NOT NULL ORDER BY languages DESC;
|
||||||
|
selectLangGroupByLangHavingNotEquality
|
||||||
|
SELECT languages, COUNT(*) c FROM test_emp GROUP BY languages HAVING NOT COUNT(*) = 1 ORDER BY languages DESC;
|
||||||
|
selectLangGroupByLangHavingDifferent
|
||||||
|
SELECT languages, COUNT(*) c FROM test_emp GROUP BY languages HAVING COUNT(*) <> 1 ORDER BY languages DESC;
|
||||||
|
|
||||||
|
|
||||||
// filter with IN
|
// filter with IN
|
||||||
aggMultiWithHavingUsingInAndNullHandling
|
aggMultiWithHavingUsingInAndNullHandling
|
||||||
|
|
Loading…
Reference in New Issue