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);
|
//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
|
mathConstantPI
|
||||||
//SELECT ABS(emp_no) m, PI(), first_name FROM "test_emp" WHERE emp_no < 10010 ORDER BY emp_no;
|
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) {
|
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) {
|
public static TypeResolution typeMustBe(Expression e, Predicate<Expression> predicate, String message) {
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
*/
|
*/
|
||||||
package org.elasticsearch.xpack.sql.expression;
|
package org.elasticsearch.xpack.sql.expression;
|
||||||
|
|
||||||
|
import org.elasticsearch.xpack.sql.SqlIllegalArgumentException;
|
||||||
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;
|
||||||
import org.elasticsearch.xpack.sql.type.DataTypeConversion;
|
import org.elasticsearch.xpack.sql.type.DataTypeConversion;
|
||||||
|
@ -40,6 +41,7 @@ public class Literal extends LeafExpression {
|
||||||
return value == null;
|
return value == null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public DataType dataType() {
|
public DataType dataType() {
|
||||||
return dataType;
|
return dataType;
|
||||||
}
|
}
|
||||||
|
@ -54,6 +56,7 @@ public class Literal extends LeafExpression {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Object fold() {
|
public Object fold() {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
@ -84,4 +87,16 @@ public class Literal extends LeafExpression {
|
||||||
}
|
}
|
||||||
return new Literal(loc, value, DataTypes.fromJava(value));
|
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);
|
super(location, field);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean foldable() {
|
public boolean foldable() {
|
||||||
return field().foldable();
|
return field().foldable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
protected String formatScript(String template) {
|
protected String formatScript(String template) {
|
||||||
return super.formatScript(format(Locale.ROOT, "Math.%s(%s)", mathFunction(), 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.SqlIllegalArgumentException;
|
||||||
import org.elasticsearch.xpack.sql.execution.search.SourceGenerator;
|
import org.elasticsearch.xpack.sql.execution.search.SourceGenerator;
|
||||||
import org.elasticsearch.xpack.sql.expression.Attribute;
|
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.NestedFieldAttribute;
|
||||||
import org.elasticsearch.xpack.sql.expression.RootFieldAttribute;
|
import org.elasticsearch.xpack.sql.expression.RootFieldAttribute;
|
||||||
import org.elasticsearch.xpack.sql.expression.function.scalar.ScalarFunctionAttribute;
|
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,
|
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,
|
Map<Attribute, ProcessorDefinition> scalarFunctions,
|
||||||
Set<Sort> sort, int limit) {
|
Set<Sort> sort, int limit) {
|
||||||
this.query = query;
|
this.query = query;
|
||||||
|
@ -99,7 +100,7 @@ public class QueryContainer {
|
||||||
// check field references
|
// check field references
|
||||||
if (((ComputedRef) ref).processor().anyMatch(p -> p instanceof ReferenceInput && ((ReferenceInput) p).context() instanceof FieldReference)) {
|
if (((ComputedRef) ref).processor().anyMatch(p -> p instanceof ReferenceInput && ((ReferenceInput) p).context() instanceof FieldReference)) {
|
||||||
onlyAggs = false;
|
onlyAggs = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ref instanceof FieldReference) {
|
if (ref instanceof FieldReference) {
|
||||||
onlyAggs = false;
|
onlyAggs = false;
|
||||||
|
@ -246,10 +247,10 @@ public class QueryContainer {
|
||||||
if (proc == null) {
|
if (proc == null) {
|
||||||
if (name instanceof ScalarFunctionAttribute) {
|
if (name instanceof ScalarFunctionAttribute) {
|
||||||
sfa = (ScalarFunctionAttribute) name;
|
sfa = (ScalarFunctionAttribute) name;
|
||||||
}
|
}
|
||||||
proc = sfa.processorDef();
|
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
|
// 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
|
// 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) {
|
private Tuple<QueryContainer, ColumnReference> toReference(Attribute attr) {
|
||||||
if (attr instanceof RootFieldAttribute) {
|
if (attr instanceof RootFieldAttribute) {
|
||||||
return new Tuple<>(this, fieldRef((RootFieldAttribute) attr));
|
return new Tuple<>(this, fieldRef((RootFieldAttribute) attr));
|
||||||
}
|
}
|
||||||
if (attr instanceof NestedFieldAttribute) {
|
if (attr instanceof NestedFieldAttribute) {
|
||||||
return nestedFieldRef((NestedFieldAttribute) attr);
|
return nestedFieldRef((NestedFieldAttribute) attr);
|
||||||
}
|
}
|
||||||
if (attr instanceof ScalarFunctionAttribute) {
|
if (attr instanceof ScalarFunctionAttribute) {
|
||||||
return computingRef((ScalarFunctionAttribute) attr);
|
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);
|
throw new SqlIllegalArgumentException("Unknown output attribute %s", attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue