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:
Costin Leau 2017-12-06 19:35:34 +02:00 committed by GitHub
parent aa9199f5d1
commit 432f10e736
6 changed files with 83 additions and 9 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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