SQL: Introduce LiteralAttribute for values that are not extracted from ES (elastic/x-pack-elasticsearch#3209)
This is mainly a promotion of Literal to Attribute to better handle folding expressions from extracted queries Original commit: elastic/x-pack-elasticsearch@c3bb48bb61
This commit is contained in:
parent
aa9199f5d1
commit
432f10e736
|
@ -70,7 +70,9 @@ SELECT emp_no, CAST(CEIL(emp_no) AS INT) m, first_name FROM "test_emp" WHERE CEI
|
|||
//SELECT emp_no, COSH(emp_no) m, first_name FROM "test_emp" WHERE COSH(emp_no) < 10010 ORDER BY COSH(emp_no);
|
||||
|
||||
//
|
||||
// constants - added when folding will be supported
|
||||
// constants
|
||||
//
|
||||
//mathConstantPI
|
||||
//SELECT ABS(emp_no) m, PI(), first_name FROM "test_emp" WHERE emp_no < 10010 ORDER BY emp_no;
|
||||
mathConstantPI
|
||||
SELECT ABS(emp_no) m, PI() as pi, first_name FROM "test_emp" WHERE emp_no < 10010 ORDER BY emp_no;
|
||||
mathConstant
|
||||
SELECT 5 + 2 * 3 / 2 % 2 AS c, PI() as e, first_name FROM "test_emp" WHERE emp_no < 10010 ORDER BY emp_no;
|
|
@ -82,7 +82,13 @@ public abstract class Expressions {
|
|||
}
|
||||
|
||||
public static Attribute attribute(Expression e) {
|
||||
return e instanceof NamedExpression ? ((NamedExpression) e).toAttribute() : null;
|
||||
if (e instanceof NamedExpression) {
|
||||
return ((NamedExpression) e).toAttribute();
|
||||
}
|
||||
if (e != null && e.foldable()) {
|
||||
return new LiteralAttribute(Literal.of(e));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static TypeResolution typeMustBe(Expression e, Predicate<Expression> predicate, String message) {
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
package org.elasticsearch.xpack.sql.expression;
|
||||
|
||||
import org.elasticsearch.xpack.sql.SqlIllegalArgumentException;
|
||||
import org.elasticsearch.xpack.sql.tree.Location;
|
||||
import org.elasticsearch.xpack.sql.type.DataType;
|
||||
import org.elasticsearch.xpack.sql.type.DataTypeConversion;
|
||||
|
@ -40,6 +41,7 @@ public class Literal extends LeafExpression {
|
|||
return value == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType dataType() {
|
||||
return dataType;
|
||||
}
|
||||
|
@ -54,6 +56,7 @@ public class Literal extends LeafExpression {
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object fold() {
|
||||
return value;
|
||||
}
|
||||
|
@ -84,4 +87,16 @@ public class Literal extends LeafExpression {
|
|||
}
|
||||
return new Literal(loc, value, DataTypes.fromJava(value));
|
||||
}
|
||||
|
||||
public static Literal of(Expression foldable) {
|
||||
if (foldable instanceof Literal) {
|
||||
return (Literal) foldable;
|
||||
}
|
||||
|
||||
if (!foldable.foldable()) {
|
||||
throw new SqlIllegalArgumentException("Foldable expression required for Literal creation; received unfoldable " + foldable);
|
||||
}
|
||||
|
||||
return new Literal(foldable.location(), foldable.fold(), foldable.dataType());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
import org.elasticsearch.xpack.sql.expression.function.scalar.processor.definition.ConstantInput;
|
||||
import org.elasticsearch.xpack.sql.expression.function.scalar.processor.definition.ProcessorDefinition;
|
||||
import org.elasticsearch.xpack.sql.tree.Location;
|
||||
import org.elasticsearch.xpack.sql.type.DataType;
|
||||
|
||||
public class LiteralAttribute extends TypedAttribute {
|
||||
|
||||
private final Literal literal;
|
||||
|
||||
public LiteralAttribute(Literal literal) {
|
||||
this(literal.location(), String.valueOf(literal.fold()), null, false, null, false, literal.dataType(), literal);
|
||||
}
|
||||
|
||||
public LiteralAttribute(Location location, String name, String qualifier, boolean nullable, ExpressionId id, boolean synthetic,
|
||||
DataType dataType, Literal literal) {
|
||||
super(location, name, dataType, qualifier, nullable, id, synthetic);
|
||||
this.literal = literal;
|
||||
}
|
||||
|
||||
public Literal literal() {
|
||||
return literal;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LiteralAttribute clone(Location location, String name, DataType dataType, String qualifier, boolean nullable, ExpressionId id, boolean synthetic) {
|
||||
return new LiteralAttribute(location, name, qualifier, nullable, id, synthetic, dataType, literal);
|
||||
}
|
||||
|
||||
public ProcessorDefinition asProcessorDefinition() {
|
||||
return new ConstantInput(literal, literal.value());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String label() {
|
||||
return "c";
|
||||
}
|
||||
}
|
|
@ -29,10 +29,12 @@ public abstract class MathFunction extends UnaryScalarFunction {
|
|||
super(location, field);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean foldable() {
|
||||
return field().foldable();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String formatScript(String template) {
|
||||
return super.formatScript(format(Locale.ROOT, "Math.%s(%s)", mathFunction(), template));
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import org.elasticsearch.common.xcontent.json.JsonXContent;
|
|||
import org.elasticsearch.xpack.sql.SqlIllegalArgumentException;
|
||||
import org.elasticsearch.xpack.sql.execution.search.SourceGenerator;
|
||||
import org.elasticsearch.xpack.sql.expression.Attribute;
|
||||
import org.elasticsearch.xpack.sql.expression.LiteralAttribute;
|
||||
import org.elasticsearch.xpack.sql.expression.NestedFieldAttribute;
|
||||
import org.elasticsearch.xpack.sql.expression.RootFieldAttribute;
|
||||
import org.elasticsearch.xpack.sql.expression.function.scalar.ScalarFunctionAttribute;
|
||||
|
@ -76,7 +77,7 @@ public class QueryContainer {
|
|||
}
|
||||
|
||||
public QueryContainer(Query query, Aggs aggs, List<ColumnReference> refs, Map<Attribute, Attribute> aliases,
|
||||
Map<String, GroupingAgg> pseudoFunctions,
|
||||
Map<String, GroupingAgg> pseudoFunctions,
|
||||
Map<Attribute, ProcessorDefinition> scalarFunctions,
|
||||
Set<Sort> sort, int limit) {
|
||||
this.query = query;
|
||||
|
@ -99,7 +100,7 @@ public class QueryContainer {
|
|||
// check field references
|
||||
if (((ComputedRef) ref).processor().anyMatch(p -> p instanceof ReferenceInput && ((ReferenceInput) p).context() instanceof FieldReference)) {
|
||||
onlyAggs = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ref instanceof FieldReference) {
|
||||
onlyAggs = false;
|
||||
|
@ -246,10 +247,10 @@ public class QueryContainer {
|
|||
if (proc == null) {
|
||||
if (name instanceof ScalarFunctionAttribute) {
|
||||
sfa = (ScalarFunctionAttribute) name;
|
||||
}
|
||||
}
|
||||
proc = sfa.processorDef();
|
||||
}
|
||||
AtomicReference<QueryContainer> containerRef = new AtomicReference<QueryContainer>(this);
|
||||
AtomicReference<QueryContainer> containerRef = new AtomicReference<>(this);
|
||||
|
||||
// find the processor inputs (Attributes) and convert them into references
|
||||
// no need to promote them to the top since the container doesn't have to be aware
|
||||
|
@ -276,13 +277,17 @@ public class QueryContainer {
|
|||
private Tuple<QueryContainer, ColumnReference> toReference(Attribute attr) {
|
||||
if (attr instanceof RootFieldAttribute) {
|
||||
return new Tuple<>(this, fieldRef((RootFieldAttribute) attr));
|
||||
}
|
||||
}
|
||||
if (attr instanceof NestedFieldAttribute) {
|
||||
return nestedFieldRef((NestedFieldAttribute) attr);
|
||||
}
|
||||
if (attr instanceof ScalarFunctionAttribute) {
|
||||
return computingRef((ScalarFunctionAttribute) attr);
|
||||
}
|
||||
if (attr instanceof LiteralAttribute) {
|
||||
return new Tuple<>(this, new ComputedRef(((LiteralAttribute) attr).asProcessorDefinition()));
|
||||
}
|
||||
|
||||
throw new SqlIllegalArgumentException("Unknown output attribute %s", attr);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue