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:
Costin Leau 2018-10-26 18:21:14 +03:00 committed by GitHub
parent 43f6ba1c63
commit 5a7b8c0e69
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 253 additions and 110 deletions

View File

@ -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

View File

@ -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();

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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();

View File

@ -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();

View File

@ -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());
}
} }

View File

@ -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);
} }

View File

@ -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)));
/** /**

View File

@ -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";
}
} }

View File

@ -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();
}
}

View File

@ -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;

View File

@ -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

View File

@ -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();
}
}

View File

@ -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);
} }
} }

View File

@ -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);
} }
} }

View File

@ -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)

View File

@ -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