From 36bd849cd357b9185388a35c7416891831d15d3b Mon Sep 17 00:00:00 2001 From: Igor Motov Date: Wed, 24 Jan 2018 14:43:23 -0500 Subject: [PATCH] SQL: Refactor the type handling (elastic/x-pack-elasticsearch#3694) Separates ES types and field metadata. Relates to elastic/x-pack-elasticsearch#3556 Original commit: elastic/x-pack-elasticsearch@c9601f33904c8b04f763bce33f4db5a0d09b9d04 --- .../xpack/sql/jdbc/jdbc/JdbcUtils.java | 32 --- .../xpack/sql/analysis/analyzer/Analyzer.java | 15 +- .../xpack/sql/analysis/analyzer/Verifier.java | 4 +- .../xpack/sql/analysis/index/EsIndex.java | 8 +- .../sql/analysis/index/IndexResolver.java | 4 +- .../xpack/sql/expression/Alias.java | 9 +- .../xpack/sql/expression/Attribute.java | 23 +- .../xpack/sql/expression/BinaryLogic.java | 7 +- .../xpack/sql/expression/Exists.java | 2 +- .../xpack/sql/expression/Expressions.java | 2 +- .../xpack/sql/expression/FieldAttribute.java | 63 ++---- .../xpack/sql/expression/Foldables.java | 10 +- .../sql/expression/LiteralAttribute.java | 6 +- .../sql/expression/UnresolvedAttribute.java | 3 +- .../xpack/sql/expression/function/Score.java | 2 +- .../expression/function/ScoreAttribute.java | 9 +- .../aggregate/AggregateFunctionAttribute.java | 5 +- .../expression/function/aggregate/Count.java | 2 +- .../expression/function/aggregate/Mean.java | 2 +- .../function/aggregate/NumericAggregate.java | 2 +- .../function/aggregate/Percentile.java | 2 +- .../function/aggregate/PercentileRank.java | 2 +- .../scalar/ScalarFunctionAttribute.java | 5 +- .../scalar/datetime/DateTimeFunction.java | 7 +- .../expression/function/scalar/math/E.java | 5 +- .../function/scalar/math/MathFunction.java | 2 +- .../expression/function/scalar/math/Pi.java | 5 +- .../scalar/script/ScriptTemplate.java | 2 +- .../predicate/BinaryComparison.java | 2 +- .../xpack/sql/expression/predicate/In.java | 2 +- .../sql/expression/predicate/IsNotNull.java | 4 +- .../xpack/sql/expression/predicate/Not.java | 7 +- .../xpack/sql/expression/predicate/Range.java | 2 +- .../predicate/fulltext/FullTextPredicate.java | 2 +- .../xpack/sql/expression/regex/Like.java | 2 +- .../sql/expression/regex/LikePattern.java | 2 +- .../xpack/sql/expression/regex/RLike.java | 2 +- .../xpack/sql/optimizer/Optimizer.java | 4 +- .../xpack/sql/parser/ExpressionBuilder.java | 30 +-- .../xpack/sql/parser/LogicalPlanBuilder.java | 3 +- .../xpack/sql/plan/logical/EsRelation.java | 15 +- .../xpack/sql/plan/logical/Join.java | 3 +- .../xpack/sql/plan/logical/command/Debug.java | 4 +- .../sql/plan/logical/command/Explain.java | 4 +- .../sql/plan/logical/command/ShowColumns.java | 20 +- .../plan/logical/command/ShowFunctions.java | 6 +- .../sql/plan/logical/command/ShowSchemas.java | 4 +- .../sql/plan/logical/command/ShowTables.java | 6 +- .../xpack/sql/planner/QueryTranslator.java | 9 +- .../plugin/TransportSqlListColumnsAction.java | 11 +- .../sql/plugin/TransportSqlQueryAction.java | 5 +- .../xpack/sql/querydsl/agg/AndAggFilter.java | 3 +- .../xpack/sql/querydsl/agg/OrAggFilter.java | 3 +- .../querydsl/container/QueryContainer.java | 6 +- .../xpack/sql/type/AbstractDataType.java | 59 ----- .../xpack/sql/type/ArrayType.java | 82 ------- .../xpack/sql/type/BinaryType.java | 20 -- .../xpack/sql/type/BooleanType.java | 20 -- .../xpack/sql/type/ByteType.java | 20 -- .../xpack/sql/type/CompoundDataType.java | 54 ----- .../xpack/sql/type/DataType.java | 148 +++++++++---- .../xpack/sql/type/DataTypeConversion.java | 150 ++++++------- .../xpack/sql/type/DataTypes.java | 96 +------- .../xpack/sql/type/DateEsField.java | 52 +++++ .../xpack/sql/type/DateType.java | 53 ----- .../xpack/sql/type/DoubleType.java | 20 -- .../elasticsearch/xpack/sql/type/EsField.java | 103 +++++++++ .../xpack/sql/type/FloatType.java | 20 -- .../xpack/sql/type/GeoPointType.java | 25 --- .../xpack/sql/type/HalfFloatType.java | 20 -- .../xpack/sql/type/IntegerType.java | 20 -- .../elasticsearch/xpack/sql/type/IpType.java | 26 --- .../xpack/sql/type/JdbcUtils.java | 122 ---------- .../xpack/sql/type/KeywordEsField.java | 55 +++++ .../xpack/sql/type/KeywordType.java | 62 ------ .../xpack/sql/type/LongType.java | 20 -- .../xpack/sql/type/NestedType.java | 26 --- .../xpack/sql/type/NullType.java | 20 -- .../xpack/sql/type/ObjectType.java | 30 --- .../xpack/sql/type/ScaledFloatType.java | 26 --- .../elasticsearch/xpack/sql/type/Schema.java | 2 +- .../xpack/sql/type/ShortType.java | 20 -- .../xpack/sql/type/StringType.java | 86 -------- .../xpack/sql/type/TextEsField.java | 44 ++++ .../xpack/sql/type/TextType.java | 56 ----- .../xpack/sql/type/TokenCountType.java | 30 --- .../elasticsearch/xpack/sql/type/Types.java | 172 +++++---------- .../xpack/sql/type/UnsupportedDataType.java | 61 ----- .../xpack/sql/type/UnsupportedEsField.java | 41 ++++ .../analyzer/FieldAttributeTests.java | 19 +- .../analyzer/VerifierErrorMessagesTests.java | 4 +- .../search/SourceGeneratorTests.java | 6 +- .../xpack/sql/expression/LiteralTests.java | 26 +-- .../scalar/datetime/DayOfYearTests.java | 4 +- .../xpack/sql/optimizer/OptimizerTests.java | 6 +- .../sql/planner/QueryTranslatorTests.java | 4 +- .../planner/VerifierErrorMessagesTests.java | 15 +- .../sql/type/DataTypeConversionTests.java | 38 ++-- .../xpack/sql/type/TypesTests.java | 208 +++++++++--------- 99 files changed, 887 insertions(+), 1705 deletions(-) delete mode 100644 plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/AbstractDataType.java delete mode 100644 plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/ArrayType.java delete mode 100644 plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/BinaryType.java delete mode 100644 plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/BooleanType.java delete mode 100644 plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/ByteType.java delete mode 100644 plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/CompoundDataType.java create mode 100644 plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/DateEsField.java delete mode 100644 plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/DateType.java delete mode 100644 plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/DoubleType.java create mode 100644 plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/EsField.java delete mode 100644 plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/FloatType.java delete mode 100644 plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/GeoPointType.java delete mode 100644 plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/HalfFloatType.java delete mode 100644 plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/IntegerType.java delete mode 100644 plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/IpType.java delete mode 100644 plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/JdbcUtils.java create mode 100644 plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/KeywordEsField.java delete mode 100644 plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/KeywordType.java delete mode 100644 plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/LongType.java delete mode 100644 plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/NestedType.java delete mode 100644 plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/NullType.java delete mode 100644 plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/ObjectType.java delete mode 100644 plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/ScaledFloatType.java delete mode 100644 plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/ShortType.java delete mode 100644 plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/StringType.java create mode 100644 plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/TextEsField.java delete mode 100644 plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/TextType.java delete mode 100644 plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/TokenCountType.java delete mode 100644 plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/UnsupportedDataType.java create mode 100644 plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/UnsupportedEsField.java diff --git a/plugin/sql/jdbc/src/main/java/org/elasticsearch/xpack/sql/jdbc/jdbc/JdbcUtils.java b/plugin/sql/jdbc/src/main/java/org/elasticsearch/xpack/sql/jdbc/jdbc/JdbcUtils.java index b27e0451d11..522438be5a7 100644 --- a/plugin/sql/jdbc/src/main/java/org/elasticsearch/xpack/sql/jdbc/jdbc/JdbcUtils.java +++ b/plugin/sql/jdbc/src/main/java/org/elasticsearch/xpack/sql/jdbc/jdbc/JdbcUtils.java @@ -42,38 +42,6 @@ import static java.sql.Types.VARCHAR; public abstract class JdbcUtils { - public static Class asPrimitive(Class wrapperClass) { - if (Boolean.class == wrapperClass) { - return boolean.class; - } - if (Byte.class == wrapperClass) { - return byte.class; - } - if (Short.class == wrapperClass) { - return short.class; - } - if (Character.class == wrapperClass) { - return char.class; - } - if (Integer.class == wrapperClass) { - return int.class; - } - if (Long.class == wrapperClass) { - return long.class; - } - if (Double.class == wrapperClass) { - return double.class; - } - if (Float.class == wrapperClass) { - return float.class; - } - if (Void.class == wrapperClass) { - return void.class; - } - - return wrapperClass; - } - public static int fromClass(Class clazz) throws JdbcSQLException { if (clazz == null) { return NULL; diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/analysis/analyzer/Analyzer.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/analysis/analyzer/Analyzer.java index 5f0bea23a59..091d796a58d 100644 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/analysis/analyzer/Analyzer.java +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/analysis/analyzer/Analyzer.java @@ -48,6 +48,7 @@ import org.elasticsearch.xpack.sql.tree.Node; import org.elasticsearch.xpack.sql.type.DataType; import org.elasticsearch.xpack.sql.type.DataTypeConversion; import org.elasticsearch.xpack.sql.type.DataTypes; +import org.elasticsearch.xpack.sql.type.UnsupportedEsField; import org.elasticsearch.xpack.sql.util.StringUtils; import org.joda.time.DateTimeZone; @@ -353,12 +354,14 @@ public class Analyzer extends RuleExecutor { if (named instanceof FieldAttribute) { FieldAttribute fa = (FieldAttribute) named; if (DataTypes.isUnsupported(fa.dataType())) { + UnsupportedEsField unsupportedField = (UnsupportedEsField) fa.field(); named = u.withUnresolvedMessage( - "Cannot use field [" + fa.name() + "] type [" + fa.dataType().esName() + "] as is unsupported"); + "Cannot use field [" + fa.name() + "] type [" + unsupportedField.getOriginalType() + + "] as is unsupported"); } else if (!fa.dataType().isPrimitive()) { named = u.withUnresolvedMessage( - "Cannot use field [" + fa.name() + "] type [" + fa.dataType().esName() + "] only its subfields"); + "Cannot use field [" + fa.name() + "] type [" + fa.dataType().esType + "] only its subfields"); } } @@ -543,7 +546,7 @@ public class Analyzer extends RuleExecutor { private Integer findOrdinal(Expression expression) { if (expression instanceof Literal) { Literal l = (Literal) expression; - if (l.dataType().isInteger()) { + if (l.dataType().isInteger) { Object v = l.value(); if (v instanceof Number) { return Integer.valueOf(((Number) v).intValue()); @@ -1030,13 +1033,13 @@ public class Analyzer extends RuleExecutor { if (left != null) { DataType l = left.dataType(); DataType r = right.dataType(); - if (!l.same(r)) { + if (l != r) { DataType common = DataTypeConversion.commonType(l, r); if (common == null) { return e; } - left = l.same(common) ? left : new Cast(left.location(), left, common); - right = r.same(common) ? right : new Cast(right.location(), right, common); + left = l == common ? left : new Cast(left.location(), left, common); + right = r == common ? right : new Cast(right.location(), right, common); return e.replaceChildren(Arrays.asList(left, right)); } } diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/analysis/analyzer/Verifier.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/analysis/analyzer/Verifier.java index aa5e2016c43..36ee5ca9b6b 100644 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/analysis/analyzer/Verifier.java +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/analysis/analyzer/Verifier.java @@ -24,7 +24,7 @@ import org.elasticsearch.xpack.sql.plan.logical.Filter; import org.elasticsearch.xpack.sql.plan.logical.LogicalPlan; import org.elasticsearch.xpack.sql.plan.logical.OrderBy; import org.elasticsearch.xpack.sql.tree.Node; -import org.elasticsearch.xpack.sql.type.UnsupportedDataType; +import org.elasticsearch.xpack.sql.type.DataType; import org.elasticsearch.xpack.sql.util.StringUtils; import java.util.ArrayList; @@ -138,7 +138,7 @@ abstract class Verifier { for (Attribute a : p.intputSet()) { String nameCandidate = useQualifier ? a.qualifiedName() : a.name(); // add only primitives (object types would only result in another error) - if (!(a.dataType() instanceof UnsupportedDataType) && a.dataType().isPrimitive()) { + if (!(a.dataType() == DataType.UNSUPPORTED) && a.dataType().isPrimitive()) { potentialMatches.add(nameCandidate); } } diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/analysis/index/EsIndex.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/analysis/index/EsIndex.java index 5c28dc1c92a..790bb67c22c 100644 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/analysis/index/EsIndex.java +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/analysis/index/EsIndex.java @@ -5,16 +5,16 @@ */ package org.elasticsearch.xpack.sql.analysis.index; -import org.elasticsearch.xpack.sql.type.DataType; +import org.elasticsearch.xpack.sql.type.EsField; import java.util.Map; public class EsIndex { private final String name; - private final Map mapping; + private final Map mapping; - public EsIndex(String name, Map mapping) { + public EsIndex(String name, Map mapping) { assert name != null; assert mapping != null; this.name = name; @@ -25,7 +25,7 @@ public class EsIndex { return name; } - public Map mapping() { + public Map mapping() { return mapping; } diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/analysis/index/IndexResolver.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/analysis/index/IndexResolver.java index ba281c01cd2..55c4054264b 100644 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/analysis/index/IndexResolver.java +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/analysis/index/IndexResolver.java @@ -20,7 +20,7 @@ import org.elasticsearch.cluster.metadata.AliasMetaData; import org.elasticsearch.cluster.metadata.MappingMetaData; import org.elasticsearch.common.collect.ImmutableOpenMap; import org.elasticsearch.index.IndexNotFoundException; -import org.elasticsearch.xpack.sql.type.DataType; +import org.elasticsearch.xpack.sql.type.EsField; import org.elasticsearch.xpack.sql.type.Types; import java.util.ArrayList; @@ -279,7 +279,7 @@ public class IndexResolver { "[" + indexOrAlias + "] contains more than one type " + typeNames + " so it is incompatible with sql"); } else { try { - Map mapping = Types.fromEs(singleType.sourceAsMap()); + Map mapping = Types.fromEs(singleType.sourceAsMap()); return IndexResolution.valid(new EsIndex(indexOrAlias, mapping)); } catch (MappingException ex) { return IndexResolution.invalid(ex.getMessage()); diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/Alias.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/Alias.java index f439ce03c6a..9a44994239e 100644 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/Alias.java +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/Alias.java @@ -8,9 +8,11 @@ package org.elasticsearch.xpack.sql.expression; import org.elasticsearch.xpack.sql.tree.Location; import org.elasticsearch.xpack.sql.tree.NodeInfo; import org.elasticsearch.xpack.sql.type.DataType; +import org.elasticsearch.xpack.sql.type.EsField; import static java.util.Collections.singletonList; +import java.util.Collections; import java.util.List; public class Alias extends NamedExpression { @@ -87,10 +89,13 @@ public class Alias extends NamedExpression { Attribute attr = Expressions.attribute(c); if (attr != null) { - return attr.clone(location(), name(), child.dataType(), qualifier, child.nullable(), id(), synthetic()); + return attr.clone(location(), name(), qualifier, child.nullable(), id(), synthetic()); } else { - return new FieldAttribute(location(), null, name(), child.dataType(), qualifier, child.nullable(), id(), synthetic()); + // TODO: WE need to fix this fake Field + return new FieldAttribute(location(), null, name(), + new EsField(name(), child.dataType(), Collections.emptyMap(), true), + qualifier, child.nullable(), id(), synthetic()); } } diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/Attribute.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/Attribute.java index 1401cf54584..d1c58546d29 100644 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/Attribute.java +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/Attribute.java @@ -66,32 +66,19 @@ public abstract class Attribute extends NamedExpression { } public Attribute withLocation(Location location) { - return Objects.equals(location(), location) ? this : clone(location, name(), dataType(), qualifier(), - nullable(), id(), synthetic()); + return Objects.equals(location(), location) ? this : clone(location, name(), qualifier(), nullable(), id(), synthetic()); } public Attribute withQualifier(String qualifier) { - return Objects.equals(qualifier(), qualifier) ? this : clone(location(), name(), dataType(), qualifier, - nullable(), id(), synthetic()); - } - - public Attribute withName(String name) { - return Objects.equals(name(), name) ? this : clone(location(), name, dataType(), qualifier(), nullable(), - id(), synthetic()); + return Objects.equals(qualifier(), qualifier) ? this : clone(location(), name(), qualifier, nullable(), id(), synthetic()); } public Attribute withNullability(boolean nullable) { - return Objects.equals(nullable(), nullable) ? this : clone(location(), name(), dataType(), qualifier(), - nullable, id(), synthetic()); + return Objects.equals(nullable(), nullable) ? this : clone(location(), name(), qualifier(), nullable, id(), synthetic()); } - public Attribute withId(ExpressionId id) { - return Objects.equals(id(), id) ? this : clone(location(), name(), dataType(), qualifier(), nullable(), - id, synthetic()); - } - - protected abstract Attribute clone(Location location, String name, DataType dataType, String qualifier, - boolean nullable, ExpressionId id, boolean synthetic); + protected abstract Attribute clone(Location location, String name, String qualifier, boolean nullable, ExpressionId id, + boolean synthetic); @Override public Attribute toAttribute() { diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/BinaryLogic.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/BinaryLogic.java index edef746e41c..8cb51a6ea0c 100644 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/BinaryLogic.java +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/BinaryLogic.java @@ -7,7 +7,6 @@ package org.elasticsearch.xpack.sql.expression; import org.elasticsearch.xpack.sql.tree.Location; import org.elasticsearch.xpack.sql.type.DataType; -import org.elasticsearch.xpack.sql.type.DataTypes; public abstract class BinaryLogic extends BinaryOperator { @@ -17,12 +16,12 @@ public abstract class BinaryLogic extends BinaryOperator { @Override public DataType dataType() { - return DataTypes.BOOLEAN; + return DataType.BOOLEAN; } @Override protected TypeResolution resolveInputType(DataType inputType) { - return DataTypes.BOOLEAN.equals(inputType) ? TypeResolution.TYPE_RESOLVED : new TypeResolution( - "'%s' requires type %s not %s", symbol(), DataTypes.BOOLEAN.sqlName(), inputType.sqlName()); + return DataType.BOOLEAN == inputType ? TypeResolution.TYPE_RESOLVED : new TypeResolution( + "'%s' requires type %s not %s", symbol(), DataType.BOOLEAN.sqlName(), inputType.sqlName()); } } diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/Exists.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/Exists.java index 1a111af96e3..32c2ee253f1 100644 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/Exists.java +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/Exists.java @@ -33,7 +33,7 @@ public class Exists extends SubQueryExpression { @Override public DataType dataType() { - return DataTypes.BOOLEAN; + return DataType.BOOLEAN; } @Override diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/Expressions.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/Expressions.java index cfd4a49bb40..722c015ce90 100644 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/Expressions.java +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/Expressions.java @@ -97,6 +97,6 @@ public abstract class Expressions { public static TypeResolution typeMustBeNumeric(Expression e) { return e.dataType().isNumeric()? TypeResolution.TYPE_RESOLVED : new TypeResolution( - "Argument required to be numeric ('%s' of type '%s')", Expressions.name(e), e.dataType().esName()); + "Argument required to be numeric ('" + Expressions.name(e) + "' of type '" + e.dataType().esType + "')"); } } \ No newline at end of file diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/FieldAttribute.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/FieldAttribute.java index 6f5e23ff708..d5b472c2fab 100644 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/FieldAttribute.java +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/FieldAttribute.java @@ -6,17 +6,12 @@ package org.elasticsearch.xpack.sql.expression; import org.elasticsearch.common.Strings; -import org.elasticsearch.xpack.sql.analysis.index.MappingException; import org.elasticsearch.xpack.sql.tree.Location; import org.elasticsearch.xpack.sql.tree.NodeInfo; import org.elasticsearch.xpack.sql.type.DataType; -import org.elasticsearch.xpack.sql.type.KeywordType; -import org.elasticsearch.xpack.sql.type.NestedType; -import org.elasticsearch.xpack.sql.type.StringType; +import org.elasticsearch.xpack.sql.type.EsField; import org.elasticsearch.xpack.sql.util.StringUtils; -import java.util.Map; -import java.util.Map.Entry; import java.util.Objects; /** @@ -32,26 +27,28 @@ public class FieldAttribute extends TypedAttribute { private final FieldAttribute parent; private final FieldAttribute nestedParent; private final String path; + private final EsField field; - public FieldAttribute(Location location, String name, DataType dataType) { - this(location, null, name, dataType); + public FieldAttribute(Location location, String name, EsField field) { + this(location, null, name, field); } - public FieldAttribute(Location location, FieldAttribute parent, String name, DataType dataType) { - this(location, parent, name, dataType, null, true, null, false); + public FieldAttribute(Location location, FieldAttribute parent, String name, EsField field) { + this(location, parent, name, field, null, true, null, false); } - public FieldAttribute(Location location, FieldAttribute parent, String name, DataType dataType, String qualifier, - boolean nullable, ExpressionId id, boolean synthetic) { - super(location, name, dataType, qualifier, nullable, id, synthetic); + public FieldAttribute(Location location, FieldAttribute parent, String name, EsField field, String qualifier, + boolean nullable, ExpressionId id, boolean synthetic) { + super(location, name, field.getDataType(), qualifier, nullable, id, synthetic); this.path = parent != null ? parent.name() : StringUtils.EMPTY; this.parent = parent; + this.field = field; // figure out the last nested parent FieldAttribute nestedPar = null; if (parent != null) { nestedPar = parent.nestedParent; - if (parent.dataType() instanceof NestedType) { + if (parent.dataType() == DataType.NESTED) { nestedPar = parent; } } @@ -60,8 +57,7 @@ public class FieldAttribute extends TypedAttribute { @Override protected NodeInfo info() { - return NodeInfo.create(this, FieldAttribute::new, - parent, name(), dataType(), qualifier(), nullable(), id(), synthetic()); + return NodeInfo.create(this, FieldAttribute::new, parent, name(), field, qualifier(), nullable(), id(), synthetic()); } public FieldAttribute parent() { @@ -86,44 +82,29 @@ public class FieldAttribute extends TypedAttribute { } public boolean isInexact() { - return (dataType() instanceof StringType && ((StringType) dataType()).isInexact()); + return field.isExact() == false; } public FieldAttribute exactAttribute() { - if (isInexact()) { - Map exactFields = ((StringType) dataType()).exactKeywords(); - if (exactFields.size() == 1) { - Entry entry = exactFields.entrySet().iterator().next(); - return innerField(entry.getKey(), entry.getValue()); - } - if (exactFields.isEmpty()) { - throw new MappingException( - "No keyword/multi-field defined exact matches for [%s]; define one or use MATCH/QUERY instead", - name()); - } - // pick the default - keyword - if (exactFields.size() > 1) { - throw new MappingException("Multiple exact keyword candidates %s available for [%s]; specify which one to use", - exactFields.keySet(), name()); - } + if (field.isExact() == false) { + return innerField(field.getExactField()); } return this; } - private FieldAttribute innerField(String subFieldName, DataType type) { - return new FieldAttribute(location(), this, name() + "." + subFieldName, type, qualifier(), nullable(), id(), synthetic()); + private FieldAttribute innerField(EsField type) { + return new FieldAttribute(location(), this, name() + "." + type.getName(), type, qualifier(), nullable(), id(), synthetic()); } @Override protected Expression canonicalize() { - return new FieldAttribute(location(), null, "", dataType(), null, true, id(), false); + return new FieldAttribute(location(), null, "", field, null, true, id(), false); } @Override - protected Attribute clone(Location location, String name, DataType dataType, String qualifier, boolean nullable, - ExpressionId id, boolean synthetic) { + protected Attribute clone(Location location, String name, String qualifier, boolean nullable, ExpressionId id, boolean synthetic) { FieldAttribute qualifiedParent = parent != null ? (FieldAttribute) parent.withQualifier(qualifier) : null; - return new FieldAttribute(location, qualifiedParent, name, dataType, qualifier, nullable, id, synthetic); + return new FieldAttribute(location, qualifiedParent, name, field, qualifier, nullable, id, synthetic); } @Override @@ -140,4 +121,8 @@ public class FieldAttribute extends TypedAttribute { protected String label() { return "f"; } + + public EsField field() { + return field; + } } diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/Foldables.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/Foldables.java index 6f8cdaa9dae..41b795c0488 100644 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/Foldables.java +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/Foldables.java @@ -31,19 +31,19 @@ public abstract class Foldables { } public static String stringValueOf(Expression e) { - return valueOf(e, DataTypes.KEYWORD); + return valueOf(e, DataType.KEYWORD); } public static Integer intValueOf(Expression e) { - return valueOf(e, DataTypes.INTEGER); + return valueOf(e, DataType.INTEGER); } public static Long longValueOf(Expression e) { - return valueOf(e, DataTypes.LONG); + return valueOf(e, DataType.LONG); } public static double doubleValueOf(Expression e) { - return valueOf(e, DataTypes.DOUBLE); + return valueOf(e, DataType.DOUBLE); } public static List valuesOf(List list, DataType to) { @@ -55,6 +55,6 @@ public abstract class Foldables { } public static List doubleValuesOf(List list) { - return valuesOf(list, DataTypes.DOUBLE); + return valuesOf(list, DataType.DOUBLE); } } diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/LiteralAttribute.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/LiteralAttribute.java index d045daa8627..ff07731b82e 100644 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/LiteralAttribute.java +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/LiteralAttribute.java @@ -36,9 +36,9 @@ public class LiteralAttribute extends TypedAttribute { } @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); + protected LiteralAttribute clone(Location location, String name, String qualifier, boolean nullable, + ExpressionId id, boolean synthetic) { + return new LiteralAttribute(location, name, qualifier, nullable, id, synthetic, dataType(), literal); } public ProcessorDefinition asProcessorDefinition() { diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/UnresolvedAttribute.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/UnresolvedAttribute.java index bf7f4c7a237..0a31b74d636 100644 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/UnresolvedAttribute.java +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/UnresolvedAttribute.java @@ -65,8 +65,7 @@ public class UnresolvedAttribute extends Attribute implements Unresolvable { } @Override - protected Attribute clone(Location location, String name, DataType dataType, String qualifier, boolean nullable, - ExpressionId id, boolean synthetic) { + protected Attribute clone(Location location, String name, String qualifier, boolean nullable, ExpressionId id, boolean synthetic) { return this; } diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/Score.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/Score.java index 16e86e5ed4e..f913cf0ea56 100644 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/Score.java +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/Score.java @@ -39,7 +39,7 @@ public class Score extends Function { @Override public DataType dataType() { - return DataTypes.FLOAT; + return DataType.FLOAT; } @Override diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/ScoreAttribute.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/ScoreAttribute.java index fd2ea288f47..654369d0b96 100644 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/ScoreAttribute.java +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/ScoreAttribute.java @@ -21,14 +21,14 @@ public class ScoreAttribute extends FunctionAttribute { * Constructor for normal use. */ public ScoreAttribute(Location location) { - this(location, "SCORE()", DataTypes.FLOAT, null, false, null, false); + this(location, "SCORE()", DataType.FLOAT, null, false, null, false); } /** * Constructor for {@link #clone()} */ private ScoreAttribute(Location location, String name, DataType dataType, String qualifier, boolean nullable, ExpressionId id, - boolean synthetic) { + boolean synthetic) { super(location, name, dataType, qualifier, nullable, id, synthetic, "SCORE"); } @@ -38,9 +38,8 @@ public class ScoreAttribute extends FunctionAttribute { } @Override - protected Attribute clone(Location location, String name, DataType dataType, String qualifier, boolean nullable, - ExpressionId id, boolean synthetic) { - return new ScoreAttribute(location, name, dataType, qualifier, nullable, id, synthetic); + protected Attribute clone(Location location, String name, String qualifier, boolean nullable, ExpressionId id, boolean synthetic) { + return new ScoreAttribute(location, name, dataType(), qualifier, nullable, id, synthetic); } @Override diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/aggregate/AggregateFunctionAttribute.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/aggregate/AggregateFunctionAttribute.java index 55400a888e3..ab0ae9bfe8b 100644 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/aggregate/AggregateFunctionAttribute.java +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/aggregate/AggregateFunctionAttribute.java @@ -46,11 +46,10 @@ public class AggregateFunctionAttribute extends FunctionAttribute { } @Override - protected Attribute clone(Location location, String name, DataType dataType, String qualifier, - boolean nullable, ExpressionId id, boolean synthetic) { + protected Attribute clone(Location location, String name, String qualifier, boolean nullable, ExpressionId id, boolean synthetic) { // this is highly correlated with QueryFolder$FoldAggregate#addFunction (regarding the function name within the querydsl) // that is the functionId is actually derived from the expression id to easily track it across contexts - return new AggregateFunctionAttribute(location, name, dataType, qualifier, nullable, id, synthetic, functionId(), propertyPath); + return new AggregateFunctionAttribute(location, name, dataType(), qualifier, nullable, id, synthetic, functionId(), propertyPath); } public AggregateFunctionAttribute withFunctionId(String functionId, String propertyPath) { diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/aggregate/Count.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/aggregate/Count.java index b646b41e6d2..397ff1e7c9e 100644 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/aggregate/Count.java +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/aggregate/Count.java @@ -47,7 +47,7 @@ public class Count extends AggregateFunction { @Override public DataType dataType() { - return DataTypes.LONG; + return DataType.LONG; } @Override diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/aggregate/Mean.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/aggregate/Mean.java index 4181c85e90c..6f16ca11b7a 100644 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/aggregate/Mean.java +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/aggregate/Mean.java @@ -33,7 +33,7 @@ public class Mean extends NumericAggregate implements MatrixStatsEnclosed { @Override public DataType dataType() { - return DataTypes.DOUBLE; + return DataType.DOUBLE; } @Override diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/aggregate/NumericAggregate.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/aggregate/NumericAggregate.java index 5e5c081a75f..57fdc01e935 100644 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/aggregate/NumericAggregate.java +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/aggregate/NumericAggregate.java @@ -30,6 +30,6 @@ abstract class NumericAggregate extends AggregateFunction { @Override public DataType dataType() { - return DataTypes.DOUBLE; + return DataType.DOUBLE; } } diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/aggregate/Percentile.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/aggregate/Percentile.java index 1ef911e60ab..dcff951bc42 100644 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/aggregate/Percentile.java +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/aggregate/Percentile.java @@ -56,7 +56,7 @@ public class Percentile extends NumericAggregate implements EnclosedAgg { @Override public DataType dataType() { - return DataTypes.DOUBLE; + return DataType.DOUBLE; } @Override diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/aggregate/PercentileRank.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/aggregate/PercentileRank.java index 319afa5f880..8ddcf1a2b07 100644 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/aggregate/PercentileRank.java +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/aggregate/PercentileRank.java @@ -56,7 +56,7 @@ public class PercentileRank extends AggregateFunction implements EnclosedAgg { @Override public DataType dataType() { - return DataTypes.DOUBLE; + return DataType.DOUBLE; } @Override diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/ScalarFunctionAttribute.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/ScalarFunctionAttribute.java index ebcddd209cb..84ad136e95b 100644 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/ScalarFunctionAttribute.java +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/ScalarFunctionAttribute.java @@ -65,9 +65,8 @@ public class ScalarFunctionAttribute extends FunctionAttribute { } @Override - protected Attribute clone(Location location, String name, DataType dataType, String qualifier, - boolean nullable, ExpressionId id, boolean synthetic) { - return new ScalarFunctionAttribute(location, name, dataType, qualifier, nullable, id, synthetic, + protected Attribute clone(Location location, String name, String qualifier, boolean nullable, ExpressionId id, boolean synthetic) { + return new ScalarFunctionAttribute(location, name, dataType(), qualifier, nullable, id, synthetic, functionId(), script, orderBy, processorDef); } diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/DateTimeFunction.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/DateTimeFunction.java index 1472e811b65..a5bd66079e3 100644 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/DateTimeFunction.java +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/DateTimeFunction.java @@ -19,7 +19,6 @@ import org.elasticsearch.xpack.sql.expression.function.scalar.script.ScriptTempl import org.elasticsearch.xpack.sql.tree.Location; import org.elasticsearch.xpack.sql.tree.NodeInfo; import org.elasticsearch.xpack.sql.type.DataType; -import org.elasticsearch.xpack.sql.type.DataTypes; import org.joda.time.DateTimeZone; import java.time.Instant; @@ -75,11 +74,11 @@ public abstract class DateTimeFunction extends UnaryScalarFunction { @Override protected TypeResolution resolveType() { - if (field().dataType().same(DataTypes.DATE)) { + if (field().dataType() == DataType.DATE) { return TypeResolution.TYPE_RESOLVED; } return new TypeResolution("Function [" + functionName() + "] cannot be applied on a non-date expression ([" - + Expressions.name(field()) + "] of type [" + field().dataType().esName() + "])"); + + Expressions.name(field()) + "] of type [" + field().dataType().esType + "])"); } @Override @@ -137,7 +136,7 @@ public abstract class DateTimeFunction extends UnaryScalarFunction { @Override public DataType dataType() { - return DataTypes.INTEGER; + return DataType.INTEGER; } // used for applying ranges diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/E.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/E.java index 4206ebb7b99..3e320f82bc2 100644 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/E.java +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/E.java @@ -13,15 +13,16 @@ import org.elasticsearch.xpack.sql.expression.function.scalar.script.Params; import org.elasticsearch.xpack.sql.expression.function.scalar.script.ScriptTemplate; import org.elasticsearch.xpack.sql.tree.Location; import org.elasticsearch.xpack.sql.tree.NodeInfo; +import org.elasticsearch.xpack.sql.type.DataType; import org.elasticsearch.xpack.sql.type.DataTypes; import org.elasticsearch.xpack.sql.util.StringUtils; public class E extends MathFunction { - private static final ScriptTemplate TEMPLATE = new ScriptTemplate("Math.E", Params.EMPTY, DataTypes.DOUBLE); + private static final ScriptTemplate TEMPLATE = new ScriptTemplate("Math.E", Params.EMPTY, DataType.DOUBLE); public E(Location location) { - super(location, new Literal(location, Math.E, DataTypes.DOUBLE)); + super(location, new Literal(location, Math.E, DataType.DOUBLE)); } @Override diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/MathFunction.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/MathFunction.java index 182a812f34a..329efe33e0e 100644 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/MathFunction.java +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/MathFunction.java @@ -46,7 +46,7 @@ public abstract class MathFunction extends UnaryScalarFunction { @Override public DataType dataType() { - return DataTypes.DOUBLE; + return DataType.DOUBLE; } @Override diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/Pi.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/Pi.java index 9e4d1dee887..16955cd545b 100644 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/Pi.java +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/Pi.java @@ -13,15 +13,16 @@ import org.elasticsearch.xpack.sql.expression.function.scalar.script.Params; import org.elasticsearch.xpack.sql.expression.function.scalar.script.ScriptTemplate; import org.elasticsearch.xpack.sql.tree.Location; import org.elasticsearch.xpack.sql.tree.NodeInfo; +import org.elasticsearch.xpack.sql.type.DataType; import org.elasticsearch.xpack.sql.type.DataTypes; import org.elasticsearch.xpack.sql.util.StringUtils; public class Pi extends MathFunction { - private static final ScriptTemplate TEMPLATE = new ScriptTemplate("Math.PI", Params.EMPTY, DataTypes.DOUBLE); + private static final ScriptTemplate TEMPLATE = new ScriptTemplate("Math.PI", Params.EMPTY, DataType.DOUBLE); public Pi(Location location) { - super(location, new Literal(location, Math.PI, DataTypes.DOUBLE)); + super(location, new Literal(location, Math.PI, DataType.DOUBLE)); } @Override diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/script/ScriptTemplate.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/script/ScriptTemplate.java index ef8b4abfabc..b5f9e7f3f9c 100644 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/script/ScriptTemplate.java +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/script/ScriptTemplate.java @@ -28,7 +28,7 @@ public class ScriptTemplate { private final DataType outputType; public ScriptTemplate(String template) { - this(template, Params.EMPTY, DataTypes.KEYWORD); + this(template, Params.EMPTY, DataType.KEYWORD); } public ScriptTemplate(String template, Params params, DataType outputType) { diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/BinaryComparison.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/BinaryComparison.java index a4158926fc8..0fe94feba16 100644 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/BinaryComparison.java +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/BinaryComparison.java @@ -30,7 +30,7 @@ public abstract class BinaryComparison extends BinaryOperator { @Override public DataType dataType() { - return DataTypes.BOOLEAN; + return DataType.BOOLEAN; } @SuppressWarnings({ "rawtypes", "unchecked" }) diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/In.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/In.java index 6eb9d3aeca3..ca3a08f9513 100644 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/In.java +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/In.java @@ -53,7 +53,7 @@ public class In extends Expression { @Override public DataType dataType() { - return DataTypes.BOOLEAN; + return DataType.BOOLEAN; } @Override diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/IsNotNull.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/IsNotNull.java index b9f866bf1e1..42140510245 100644 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/IsNotNull.java +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/IsNotNull.java @@ -29,7 +29,7 @@ public class IsNotNull extends UnaryExpression { } public Object fold() { - return child().fold() != null && !DataTypes.NULL.same(child().dataType()); + return child().fold() != null && !DataTypes.isNull(child().dataType()); } @Override @@ -39,7 +39,7 @@ public class IsNotNull extends UnaryExpression { @Override public DataType dataType() { - return DataTypes.BOOLEAN; + return DataType.BOOLEAN; } @Override diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/Not.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/Not.java index efc53c3e3eb..71ce42ba8aa 100644 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/Not.java +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/Not.java @@ -12,7 +12,6 @@ import org.elasticsearch.xpack.sql.expression.UnaryExpression; import org.elasticsearch.xpack.sql.tree.Location; import org.elasticsearch.xpack.sql.tree.NodeInfo; import org.elasticsearch.xpack.sql.type.DataType; -import org.elasticsearch.xpack.sql.type.DataTypes; import java.util.Objects; @@ -33,11 +32,11 @@ public class Not extends UnaryExpression { } protected TypeResolution resolveType() { - if (DataTypes.BOOLEAN.same(child().dataType())) { + if (DataType.BOOLEAN == child().dataType()) { return TypeResolution.TYPE_RESOLVED; } return new TypeResolution("Cannot negate expression ([" + Expressions.name(child()) + "] of type [" - + child().dataType().esName() + "])"); + + child().dataType().esType + "])"); } @Override @@ -56,6 +55,6 @@ public class Not extends UnaryExpression { @Override public DataType dataType() { - return DataTypes.BOOLEAN; + return DataType.BOOLEAN; } } diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/Range.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/Range.java index c1f9754edd0..96e427e90f1 100644 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/Range.java +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/Range.java @@ -86,7 +86,7 @@ public class Range extends Expression { @Override public DataType dataType() { - return DataTypes.BOOLEAN; + return DataType.BOOLEAN; } @Override diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/fulltext/FullTextPredicate.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/fulltext/FullTextPredicate.java index 5e1b5ccb272..c0f5edb8095 100644 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/fulltext/FullTextPredicate.java +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/fulltext/FullTextPredicate.java @@ -63,7 +63,7 @@ public abstract class FullTextPredicate extends Expression { @Override public DataType dataType() { - return DataTypes.BOOLEAN; + return DataType.BOOLEAN; } @Override diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/regex/Like.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/regex/Like.java index 8b148c6def8..ef2635cec37 100644 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/regex/Like.java +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/regex/Like.java @@ -53,7 +53,7 @@ public class Like extends BinaryExpression { @Override public DataType dataType() { - return DataTypes.BOOLEAN; + return DataType.BOOLEAN; } @Override diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/regex/LikePattern.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/regex/LikePattern.java index b3b21ecebbb..b9c10435660 100644 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/regex/LikePattern.java +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/regex/LikePattern.java @@ -82,7 +82,7 @@ public class LikePattern extends LeafExpression { @Override public DataType dataType() { - return DataTypes.KEYWORD; + return DataType.KEYWORD; } @Override diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/regex/RLike.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/regex/RLike.java index fb387f252fb..7d3879ef84f 100644 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/regex/RLike.java +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/regex/RLike.java @@ -48,7 +48,7 @@ public class RLike extends BinaryExpression { @Override public DataType dataType() { - return DataTypes.BOOLEAN; + return DataType.BOOLEAN; } @Override diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/optimizer/Optimizer.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/optimizer/Optimizer.java index b56baecb6fe..a56be01c955 100644 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/optimizer/Optimizer.java +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/optimizer/Optimizer.java @@ -855,7 +855,7 @@ public class Optimizer extends RuleExecutor { if (as.child() instanceof Cast) { Cast c = (Cast) as.child(); - if (c.from().same(c.to())) { + if (c.from() == c.to()) { Alias newAs = new Alias(as.location(), as.name(), as.qualifier(), c.field(), as.id(), as.synthetic()); replacedCast.put(as.toAttribute(), newAs.toAttribute()); return newAs; @@ -871,7 +871,7 @@ public class Optimizer extends RuleExecutor { if (e instanceof Cast) { Cast c = (Cast) e; - if (c.from().same(c.to())) { + if (c.from() == c.to()) { Expression argument = c.field(); if (argument instanceof NamedExpression) { replacedCast.put(c.toAttribute(), ((NamedExpression) argument).toAttribute()); diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/ExpressionBuilder.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/ExpressionBuilder.java index 21a0c36ae22..d2d70d57325 100644 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/ExpressionBuilder.java +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/ExpressionBuilder.java @@ -192,7 +192,7 @@ abstract class ExpressionBuilder extends IdentifierBuilder { e = new Like(loc, exp, visitPattern(pCtx.pattern())); break; case SqlBaseParser.RLIKE: - e = new RLike(loc, exp, new Literal(source(pCtx.regex), string(pCtx.regex), DataTypes.KEYWORD)); + e = new RLike(loc, exp, new Literal(source(pCtx.regex), string(pCtx.regex), DataType.KEYWORD)); break; case SqlBaseParser.NULL: // shortcut to avoid double negation later on (since there's no IsNull (missing in ES is a negated exists)) @@ -335,31 +335,31 @@ abstract class ExpressionBuilder extends IdentifierBuilder { case "bit": case "bool": case "boolean": - return DataTypes.BOOLEAN; + return DataType.BOOLEAN; case "tinyint": case "byte": - return DataTypes.BYTE; + return DataType.BYTE; case "smallint": case "short": - return DataTypes.SHORT; + return DataType.SHORT; case "int": case "integer": - return DataTypes.INTEGER; + return DataType.INTEGER; case "long": case "bigint": - return DataTypes.LONG; + return DataType.LONG; case "real": - return DataTypes.FLOAT; + return DataType.FLOAT; case "float": case "double": - return DataTypes.DOUBLE; + return DataType.DOUBLE; case "date": case "timestamp": - return DataTypes.DATE; + return DataType.DATE; case "char": case "varchar": case "string": - return DataTypes.KEYWORD; + return DataType.KEYWORD; default: throw new ParsingException(source(ctx), "Does not recognize type %s", type); } @@ -433,12 +433,12 @@ abstract class ExpressionBuilder extends IdentifierBuilder { @Override public Expression visitNullLiteral(NullLiteralContext ctx) { - return new Literal(source(ctx), null, DataTypes.NULL); + return new Literal(source(ctx), null, DataType.NULL); } @Override public Expression visitBooleanLiteral(BooleanLiteralContext ctx) { - return new Literal(source(ctx), Booleans.parseBoolean(ctx.getText().toLowerCase(Locale.ROOT), false), DataTypes.BOOLEAN); + return new Literal(source(ctx), Booleans.parseBoolean(ctx.getText().toLowerCase(Locale.ROOT), false), DataType.BOOLEAN); } @Override @@ -447,18 +447,18 @@ abstract class ExpressionBuilder extends IdentifierBuilder { for (TerminalNode node : ctx.STRING()) { sb.append(unquoteString(text(node))); } - return new Literal(source(ctx), sb.toString(), DataTypes.KEYWORD); + return new Literal(source(ctx), sb.toString(), DataType.KEYWORD); } @Override public Object visitDecimalLiteral(DecimalLiteralContext ctx) { - return new Literal(source(ctx), new BigDecimal(ctx.getText()).doubleValue(), DataTypes.DOUBLE); + return new Literal(source(ctx), new BigDecimal(ctx.getText()).doubleValue(), DataType.DOUBLE); } @Override public Object visitIntegerLiteral(IntegerLiteralContext ctx) { BigDecimal bigD = new BigDecimal(ctx.getText()); // TODO: this can be improved to use the smallest type available - return new Literal(source(ctx), bigD.longValueExact(), DataTypes.INTEGER); + return new Literal(source(ctx), bigD.longValueExact(), DataType.INTEGER); } } \ No newline at end of file diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/LogicalPlanBuilder.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/LogicalPlanBuilder.java index fe97b2cd06d..38c1cef8356 100644 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/LogicalPlanBuilder.java +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/LogicalPlanBuilder.java @@ -41,6 +41,7 @@ import org.elasticsearch.xpack.sql.plan.logical.SubQueryAlias; import org.elasticsearch.xpack.sql.plan.logical.UnresolvedRelation; import org.elasticsearch.xpack.sql.plan.logical.With; import org.elasticsearch.xpack.sql.session.EmptyExecutable; +import org.elasticsearch.xpack.sql.type.DataType; import org.elasticsearch.xpack.sql.type.DataTypes; import org.joda.time.DateTimeZone; @@ -88,7 +89,7 @@ abstract class LogicalPlanBuilder extends ExpressionBuilder { if (ctx.limit != null && ctx.INTEGER_VALUE() != null) { plan = new Limit(source(ctx.limit), new Literal(source(ctx), - Integer.parseInt(ctx.limit.getText()), DataTypes.INTEGER), plan); + Integer.parseInt(ctx.limit.getText()), DataType.INTEGER), plan); } return plan; diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/EsRelation.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/EsRelation.java index 1ace2df6241..552e25eef48 100644 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/EsRelation.java +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/EsRelation.java @@ -10,8 +10,7 @@ import org.elasticsearch.xpack.sql.expression.Attribute; import org.elasticsearch.xpack.sql.expression.FieldAttribute; import org.elasticsearch.xpack.sql.tree.Location; import org.elasticsearch.xpack.sql.tree.NodeInfo; -import org.elasticsearch.xpack.sql.type.CompoundDataType; -import org.elasticsearch.xpack.sql.type.DataType; +import org.elasticsearch.xpack.sql.type.EsField; import org.elasticsearch.xpack.sql.util.StringUtils; import java.util.ArrayList; @@ -36,23 +35,23 @@ public class EsRelation extends LeafPlan { return NodeInfo.create(this, EsRelation::new, index); } - private static List flatten(Location location, Map mapping) { + private static List flatten(Location location, Map mapping) { return flatten(location, mapping, null); } - private static List flatten(Location location, Map mapping, FieldAttribute parent) { + private static List flatten(Location location, Map mapping, FieldAttribute parent) { List list = new ArrayList<>(); - for (Entry entry : mapping.entrySet()) { + for (Entry entry : mapping.entrySet()) { String name = entry.getKey(); - DataType t = entry.getValue(); + EsField t = entry.getValue(); if (t != null) { FieldAttribute f = new FieldAttribute(location, parent, parent != null ? parent.name() + "." + name : name, t); list.add(f); // object or nested - if (t instanceof CompoundDataType) { - list.addAll(flatten(location, ((CompoundDataType) t).properties(), f)); + if (t.getProperties().isEmpty() == false) { + list.addAll(flatten(location, t.getProperties(), f)); } } } diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/Join.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/Join.java index c9c4512ebfb..6a513eed107 100644 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/Join.java +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/Join.java @@ -12,6 +12,7 @@ import org.elasticsearch.xpack.sql.expression.Attribute; import org.elasticsearch.xpack.sql.expression.Expression; import org.elasticsearch.xpack.sql.tree.Location; import org.elasticsearch.xpack.sql.tree.NodeInfo; +import org.elasticsearch.xpack.sql.type.DataType; import org.elasticsearch.xpack.sql.type.DataTypes; import static java.util.stream.Collectors.toList; @@ -100,7 +101,7 @@ public class Join extends BinaryPlan { return childrenResolved() && duplicatesResolved() && expressionsResolved() && - (condition == null || DataTypes.BOOLEAN.equals(condition.dataType())); + (condition == null || DataType.BOOLEAN == condition.dataType()); } @Override diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/command/Debug.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/command/Debug.java index eef2baba387..403165d5087 100644 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/command/Debug.java +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/command/Debug.java @@ -19,7 +19,7 @@ import org.elasticsearch.xpack.sql.tree.Location; import org.elasticsearch.xpack.sql.tree.Node; import org.elasticsearch.xpack.sql.tree.NodeInfo; import org.elasticsearch.xpack.sql.tree.NodeUtils; -import org.elasticsearch.xpack.sql.type.DataTypes; +import org.elasticsearch.xpack.sql.type.KeywordEsField; import org.elasticsearch.xpack.sql.util.Graphviz; import java.util.LinkedHashMap; @@ -71,7 +71,7 @@ public class Debug extends Command { @Override public List output() { - return singletonList(new FieldAttribute(location(), "plan", DataTypes.KEYWORD)); + return singletonList(new FieldAttribute(location(), "plan", new KeywordEsField("plan"))); } @Override diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/command/Explain.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/command/Explain.java index 87b5a5a8cac..5ff9df391a7 100644 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/command/Explain.java +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/command/Explain.java @@ -19,7 +19,7 @@ import org.elasticsearch.xpack.sql.session.SchemaRowSet; import org.elasticsearch.xpack.sql.session.SqlSession; import org.elasticsearch.xpack.sql.tree.Location; import org.elasticsearch.xpack.sql.tree.NodeInfo; -import org.elasticsearch.xpack.sql.type.DataTypes; +import org.elasticsearch.xpack.sql.type.KeywordEsField; import org.elasticsearch.xpack.sql.util.Graphviz; import java.util.HashMap; @@ -82,7 +82,7 @@ public class Explain extends Command { @Override public List output() { - return singletonList(new FieldAttribute(location(), "plan", DataTypes.KEYWORD)); + return singletonList(new FieldAttribute(location(), "plan", new KeywordEsField("plan"))); } @Override diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/command/ShowColumns.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/command/ShowColumns.java index 7d04c6018cf..afd35f8d730 100644 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/command/ShowColumns.java +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/command/ShowColumns.java @@ -8,15 +8,14 @@ package org.elasticsearch.xpack.sql.plan.logical.command; import org.elasticsearch.action.ActionListener; import org.elasticsearch.xpack.sql.expression.Attribute; import org.elasticsearch.xpack.sql.expression.FieldAttribute; -import org.elasticsearch.xpack.sql.plan.logical.LogicalPlan; import org.elasticsearch.xpack.sql.session.Rows; import org.elasticsearch.xpack.sql.session.SchemaRowSet; import org.elasticsearch.xpack.sql.session.SqlSession; import org.elasticsearch.xpack.sql.tree.Location; import org.elasticsearch.xpack.sql.tree.NodeInfo; -import org.elasticsearch.xpack.sql.type.CompoundDataType; import org.elasticsearch.xpack.sql.type.DataType; -import org.elasticsearch.xpack.sql.type.DataTypes; +import org.elasticsearch.xpack.sql.type.KeywordEsField; +import org.elasticsearch.xpack.sql.type.EsField; import java.util.ArrayList; import java.util.List; @@ -47,8 +46,8 @@ public class ShowColumns extends Command { @Override public List output() { - return asList(new FieldAttribute(location(), "column", DataTypes.KEYWORD), - new FieldAttribute(location(), "type", DataTypes.KEYWORD)); + return asList(new FieldAttribute(location(), "column", new KeywordEsField("column")), + new FieldAttribute(location(), "type", new KeywordEsField("type"))); } @Override @@ -66,15 +65,16 @@ public class ShowColumns extends Command { )); } - private void fillInRows(Map mapping, String prefix, List> rows) { - for (Entry e : mapping.entrySet()) { - DataType dt = e.getValue(); + private void fillInRows(Map mapping, String prefix, List> rows) { + for (Entry e : mapping.entrySet()) { + EsField field = e.getValue(); + DataType dt = field.getDataType(); String name = e.getKey(); if (dt != null) { rows.add(asList(prefix != null ? prefix + "." + name : name, dt.sqlName())); - if (dt instanceof CompoundDataType) { + if (field.getProperties().isEmpty() == false) { String newPrefix = prefix != null ? prefix + "." + name : name; - fillInRows(((CompoundDataType) dt).properties(), newPrefix, rows); + fillInRows(field.getProperties(), newPrefix, rows); } } } diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/command/ShowFunctions.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/command/ShowFunctions.java index 9f06989e1a8..9fdbab46eb8 100644 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/command/ShowFunctions.java +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/command/ShowFunctions.java @@ -16,7 +16,7 @@ import org.elasticsearch.xpack.sql.session.SchemaRowSet; import org.elasticsearch.xpack.sql.session.SqlSession; import org.elasticsearch.xpack.sql.tree.Location; import org.elasticsearch.xpack.sql.tree.NodeInfo; -import org.elasticsearch.xpack.sql.type.DataTypes; +import org.elasticsearch.xpack.sql.type.KeywordEsField; import java.util.Collection; import java.util.List; @@ -45,8 +45,8 @@ public class ShowFunctions extends Command { @Override public List output() { - return asList(new FieldAttribute(location(), "name", DataTypes.KEYWORD), - new FieldAttribute(location(), "type", DataTypes.KEYWORD)); + return asList(new FieldAttribute(location(), "name", new KeywordEsField("name")), + new FieldAttribute(location(), "type", new KeywordEsField("type"))); } @Override diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/command/ShowSchemas.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/command/ShowSchemas.java index ce0a5f6fd73..8a1c8ad0807 100644 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/command/ShowSchemas.java +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/command/ShowSchemas.java @@ -13,7 +13,7 @@ import org.elasticsearch.xpack.sql.session.SchemaRowSet; import org.elasticsearch.xpack.sql.session.SqlSession; import org.elasticsearch.xpack.sql.tree.Location; import org.elasticsearch.xpack.sql.tree.NodeInfo; -import org.elasticsearch.xpack.sql.type.DataTypes; +import org.elasticsearch.xpack.sql.type.KeywordEsField; import java.util.List; @@ -32,7 +32,7 @@ public class ShowSchemas extends Command { @Override public List output() { - return singletonList(new FieldAttribute(location(), "schema", DataTypes.KEYWORD)); + return singletonList(new FieldAttribute(location(), "schema", new KeywordEsField("schema"))); } @Override diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/command/ShowTables.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/command/ShowTables.java index 3e43b6bdf1c..c929394d33b 100644 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/command/ShowTables.java +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/command/ShowTables.java @@ -14,7 +14,7 @@ import org.elasticsearch.xpack.sql.session.SchemaRowSet; import org.elasticsearch.xpack.sql.session.SqlSession; import org.elasticsearch.xpack.sql.tree.Location; import org.elasticsearch.xpack.sql.tree.NodeInfo; -import org.elasticsearch.xpack.sql.type.DataTypes; +import org.elasticsearch.xpack.sql.type.KeywordEsField; import java.util.List; import java.util.Objects; @@ -42,8 +42,8 @@ public class ShowTables extends Command { @Override public List output() { - return asList(new FieldAttribute(location(), "name", DataTypes.KEYWORD), - new FieldAttribute(location(), "type", DataTypes.KEYWORD)); + return asList(new FieldAttribute(location(), "name", new KeywordEsField("name")), + new FieldAttribute(location(), "type", new KeywordEsField("type"))); } @Override diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/planner/QueryTranslator.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/planner/QueryTranslator.java index fb9d7bee09e..6076bd8dc6a 100644 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/planner/QueryTranslator.java +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/planner/QueryTranslator.java @@ -85,6 +85,7 @@ import org.elasticsearch.xpack.sql.querydsl.query.ScriptQuery; import org.elasticsearch.xpack.sql.querydsl.query.TermQuery; import org.elasticsearch.xpack.sql.querydsl.query.WildcardQuery; import org.elasticsearch.xpack.sql.tree.Location; +import org.elasticsearch.xpack.sql.type.DataType; import org.elasticsearch.xpack.sql.type.DataTypes; import org.elasticsearch.xpack.sql.util.Check; import org.elasticsearch.xpack.sql.util.ReflectionUtils; @@ -553,7 +554,7 @@ abstract class QueryTranslator { // no need to bind the wrapped/target agg - it is already available through the nested script // (needed to create the script itself) Params params = paramsBuilder().script(scriptTemplate.params()).variable(valueOf(bc.right())).build(); - ScriptTemplate script = new ScriptTemplate(template, params, DataTypes.BOOLEAN); + ScriptTemplate script = new ScriptTemplate(template, params, DataType.BOOLEAN); if (onAggs) { aggFilter = new AggFilter(at.id().toString(), script); } @@ -580,7 +581,7 @@ abstract class QueryTranslator { params = paramsBuilder().agg(fa).variable(valueOf(bc.right())).build(); } - aggFilter = new AggFilter(at.id().toString(), new ScriptTemplate(template, params, DataTypes.BOOLEAN)); + aggFilter = new AggFilter(at.id().toString(), new ScriptTemplate(template, params, DataType.BOOLEAN)); } // @@ -675,7 +676,7 @@ abstract class QueryTranslator { .variable(upper) .build(); - ScriptTemplate script = new ScriptTemplate(template, params, DataTypes.BOOLEAN); + ScriptTemplate script = new ScriptTemplate(template, params, DataType.BOOLEAN); if (onAggs) { aggFilter = new AggFilter(at.id().toString(), script); @@ -708,7 +709,7 @@ abstract class QueryTranslator { } aggFilter = new AggFilter(((NamedExpression) r.value()).id().toString(), - new ScriptTemplate(template, params, DataTypes.BOOLEAN)); + new ScriptTemplate(template, params, DataType.BOOLEAN)); } // // WHERE diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/TransportSqlListColumnsAction.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/TransportSqlListColumnsAction.java index d1bbf6d21a0..70784471c49 100644 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/TransportSqlListColumnsAction.java +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/TransportSqlListColumnsAction.java @@ -15,7 +15,7 @@ import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.transport.TransportService; import org.elasticsearch.xpack.sql.analysis.index.EsIndex; import org.elasticsearch.xpack.sql.analysis.index.IndexResolver; -import org.elasticsearch.xpack.sql.type.DataType; +import org.elasticsearch.xpack.sql.type.EsField; import org.elasticsearch.xpack.sql.util.StringUtils; import java.util.ArrayList; @@ -57,16 +57,17 @@ public class TransportSqlListColumnsAction extends HandledTransportAction columns = new ArrayList<>(); for (EsIndex esIndex : esIndices) { int pos = 0; - for (Map.Entry entry : esIndex.mapping().entrySet()) { + for (Map.Entry entry : esIndex.mapping().entrySet()) { String name = entry.getKey(); pos++; // JDBC is 1-based so we start with 1 here if (columnMatcher == null || columnMatcher.matcher(name).matches()) { - DataType type = entry.getValue(); + EsField field = entry.getValue(); if (request.mode() == JDBC) { // the column size it's actually its precision (based on the Javadocs) - columns.add(new MetaColumnInfo(esIndex.name(), name, type.esName(), type.sqlType(), type.precision(), pos)); + columns.add(new MetaColumnInfo(esIndex.name(), name, field.getDataType().esType, + field.getDataType().jdbcType, field.getPrecision(), pos)); } else { - columns.add(new MetaColumnInfo(esIndex.name(), name, type.esName(), pos)); + columns.add(new MetaColumnInfo(esIndex.name(), name, field.getDataType().esType, pos)); } } } diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/TransportSqlQueryAction.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/TransportSqlQueryAction.java index 48f99b6d60f..c1f679d76b2 100644 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/TransportSqlQueryAction.java +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/TransportSqlQueryAction.java @@ -73,9 +73,10 @@ public class TransportSqlQueryAction extends HandledTransportAction columns = new ArrayList<>(rowSet.columnCount()); for (Schema.Entry entry : rowSet.schema()) { if (request.mode() == JDBC) { - columns.add(new ColumnInfo("", entry.name(), entry.type().esName(), entry.type().sqlType(), entry.type().displaySize())); + columns.add(new ColumnInfo("", entry.name(), entry.type().esType, entry.type().jdbcType, + entry.type().displaySize)); } else { - columns.add(new ColumnInfo("", entry.name(), entry.type().esName())); + columns.add(new ColumnInfo("", entry.name(), entry.type().esType)); } } columns = unmodifiableList(columns); diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/agg/AndAggFilter.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/agg/AndAggFilter.java index ea1e3c95785..920be9e8198 100644 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/agg/AndAggFilter.java +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/agg/AndAggFilter.java @@ -8,6 +8,7 @@ package org.elasticsearch.xpack.sql.querydsl.agg; import org.elasticsearch.xpack.sql.expression.function.scalar.script.Params; import org.elasticsearch.xpack.sql.expression.function.scalar.script.ParamsBuilder; import org.elasticsearch.xpack.sql.expression.function.scalar.script.ScriptTemplate; +import org.elasticsearch.xpack.sql.type.DataType; import org.elasticsearch.xpack.sql.type.DataTypes; import java.util.Locale; @@ -27,6 +28,6 @@ public class AndAggFilter extends AggFilter { private static ScriptTemplate and(ScriptTemplate left, ScriptTemplate right) { String template = format(Locale.ROOT, "( %s ) && ( %s )", left.template(), right.template()); Params params = new ParamsBuilder().script(left.params()).script(right.params()).build(); - return new ScriptTemplate(template, params, DataTypes.BOOLEAN); + return new ScriptTemplate(template, params, DataType.BOOLEAN); } } diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/agg/OrAggFilter.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/agg/OrAggFilter.java index 5bf2d78a222..e06253cc75b 100644 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/agg/OrAggFilter.java +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/agg/OrAggFilter.java @@ -8,6 +8,7 @@ package org.elasticsearch.xpack.sql.querydsl.agg; import org.elasticsearch.xpack.sql.expression.function.scalar.script.Params; import org.elasticsearch.xpack.sql.expression.function.scalar.script.ParamsBuilder; import org.elasticsearch.xpack.sql.expression.function.scalar.script.ScriptTemplate; +import org.elasticsearch.xpack.sql.type.DataType; import org.elasticsearch.xpack.sql.type.DataTypes; import java.util.Locale; @@ -27,6 +28,6 @@ public class OrAggFilter extends AggFilter { private static ScriptTemplate and(ScriptTemplate left, ScriptTemplate right) { String template = format(Locale.ROOT, "( %s ) || ( %s )", left.template(), right.template()); Params params = new ParamsBuilder().script(left.params()).script(right.params()).build(); - return new ScriptTemplate(template, params, DataTypes.BOOLEAN); + return new ScriptTemplate(template, params, DataType.BOOLEAN); } } diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/container/QueryContainer.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/container/QueryContainer.java index 02481a96f82..4a463e9eaf0 100644 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/container/QueryContainer.java +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/container/QueryContainer.java @@ -178,7 +178,7 @@ public class QueryContainer { // reference methods // private FieldExtraction topHitFieldRef(FieldAttribute fieldAttr) { - return new SearchHitFieldRef(aliasName(fieldAttr), fieldAttr.dataType().hasDocValues()); + return new SearchHitFieldRef(aliasName(fieldAttr), fieldAttr.field().hasDocValues()); } private Tuple nestedHitFieldRef(FieldAttribute attr) { @@ -187,9 +187,9 @@ public class QueryContainer { String name = aliasName(attr); Query q = rewriteToContainNestedField(query, attr.location(), - attr.nestedParent().name(), name, attr.dataType().hasDocValues()); + attr.nestedParent().name(), name, attr.field().hasDocValues()); - SearchHitFieldRef nestedFieldRef = new SearchHitFieldRef(name, attr.dataType().hasDocValues(), attr.parent().name()); + SearchHitFieldRef nestedFieldRef = new SearchHitFieldRef(name, attr.field().hasDocValues(), attr.parent().name()); nestedRefs.add(nestedFieldRef); return new Tuple<>(new QueryContainer(q, aggs, columns, aliases, pseudoFunctions, scalarFunctions, sort, limit), nestedFieldRef); diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/AbstractDataType.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/AbstractDataType.java deleted file mode 100644 index 1951dff7fa6..00000000000 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/AbstractDataType.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * 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.type; - -import java.sql.JDBCType; -import java.util.Objects; - -abstract class AbstractDataType implements DataType { - - private final JDBCType sqlType; - private final boolean hasDocValues; - - AbstractDataType(JDBCType sqlType, boolean hasDocValues) { - this.sqlType = sqlType; - this.hasDocValues = hasDocValues; - } - - @Override - public boolean hasDocValues() { - return hasDocValues; - } - - @Override - public boolean isPrimitive() { - return true; - } - - @Override - public JDBCType sqlType() { - return sqlType; - } - - @Override - public String toString() { - return esName(); - } - - @Override - public int hashCode() { - return esName().hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - - if (obj == null || getClass() != obj.getClass()) { - return false; - } - - AbstractDataType other = (AbstractDataType) obj; - return Objects.equals(esName(), other.esName()); - } -} diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/ArrayType.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/ArrayType.java deleted file mode 100644 index 2abd118e755..00000000000 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/ArrayType.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * 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.type; - -import java.sql.JDBCType; -import java.util.Objects; - -public class ArrayType implements DataType { - - private final DateType type; - private final int dimension; - - public ArrayType(DateType type, int dimension) { - this.type = type; - this.dimension = dimension; - } - - public DateType type() { - return type; - } - - public int dimension() { - return dimension; - } - - @Override - public String esName() { - return "array"; - } - - @Override - public JDBCType sqlType() { - return JDBCType.ARRAY; - } - - @Override - public int precision() { - return type.precision(); - } - - @Override - public boolean isInteger() { - return false; - } - - @Override - public boolean isRational() { - return false; - } - - @Override - public boolean isPrimitive() { - return false; - } - - @Override - public boolean hasDocValues() { - return type.hasDocValues(); - } - - @Override - public int hashCode() { - return Objects.hash(type, dimension); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - - if (obj == null || getClass() != obj.getClass()) { - return false; - } - - ArrayType other = (ArrayType) obj; - return Objects.equals(dimension, other.dimension) && Objects.equals(type, other.type); - } -} \ No newline at end of file diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/BinaryType.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/BinaryType.java deleted file mode 100644 index cf9bcb4b19e..00000000000 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/BinaryType.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * 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.type; - -import java.sql.JDBCType; - -public class BinaryType extends AbstractDataType { - - BinaryType(boolean docValues) { - super(JDBCType.VARBINARY, docValues); - } - - @Override - public String esName() { - return "binary"; - } -} diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/BooleanType.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/BooleanType.java deleted file mode 100644 index eed7e0636a5..00000000000 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/BooleanType.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * 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.type; - -import java.sql.JDBCType; - -public class BooleanType extends AbstractDataType { - - BooleanType(boolean docValues) { - super(JDBCType.BOOLEAN, docValues); - } - - @Override - public String esName() { - return "boolean"; - } -} diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/ByteType.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/ByteType.java deleted file mode 100644 index f531e8745d1..00000000000 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/ByteType.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * 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.type; - -import java.sql.JDBCType; - -public class ByteType extends AbstractDataType { - - ByteType(boolean docValues) { - super(JDBCType.TINYINT, docValues); - } - - @Override - public String esName() { - return "byte"; - } -} diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/CompoundDataType.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/CompoundDataType.java deleted file mode 100644 index 259fd22c97d..00000000000 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/CompoundDataType.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * 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.type; - -import java.sql.JDBCType; -import java.util.Map; -import java.util.Objects; - -public abstract class CompoundDataType extends AbstractDataType { - - private final Map properties; - - CompoundDataType(JDBCType sqlType, boolean hasDocValues, Map properties) { - super(sqlType, hasDocValues); - this.properties = properties; - } - - public Map properties() { - return properties; - } - - @Override - public int precision() { - return 0; - } - - @Override - public boolean isInteger() { - return false; - } - - @Override - public boolean isRational() { - return false; - } - - @Override - public boolean isPrimitive() { - return false; - } - - @Override - public int hashCode() { - return Objects.hash(super.hashCode(), Objects.hash(properties)); - } - - @Override - public boolean equals(Object obj) { - return super.equals(obj) && Objects.equals(properties, ((CompoundDataType) obj).properties); - } -} diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/DataType.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/DataType.java index 22abeaac4af..a3add41f7d5 100644 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/DataType.java +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/DataType.java @@ -6,58 +6,126 @@ package org.elasticsearch.xpack.sql.type; import java.sql.JDBCType; +import java.util.Locale; -public interface DataType { +/** + * Elasticsearch data types that supported by SQL interface + */ +public enum DataType { + // @formatter:off + // jdbc type, size, defPrecision, dispSize, sig, int, rat, docvals + NULL( JDBCType.NULL, 0, 0, 0), + UNSUPPORTED( JDBCType.OTHER, 0, 0, 0), + BOOLEAN( JDBCType.BOOLEAN, 1, 1, 1), + BYTE( JDBCType.TINYINT, Byte.BYTES, 3, 5, true, true, false, true), + SHORT( JDBCType.SMALLINT, Short.BYTES, 5, 6, true, true, false, true), + INTEGER( JDBCType.INTEGER, Integer.BYTES, 10, 11, true, true, false, true), + LONG( JDBCType.BIGINT, Long.BYTES, 19, 20, true, true, false, true), + // 53 bits defaultPrecision ~ 16(15.95) decimal digits (53log10(2)), + DOUBLE( JDBCType.DOUBLE, Double.BYTES, 16, 25, true, false, true, true), + // 24 bits defaultPrecision - 24*log10(2) =~ 7 (7.22) + FLOAT( JDBCType.REAL, Float.BYTES, 7, 15, true, false, true, true), + HALF_FLOAT( JDBCType.FLOAT, Double.BYTES, 16, 25, true, false, true, true), + // precision is based on long + SCALED_FLOAT(JDBCType.FLOAT, Double.BYTES, 19, 25, true, false, true, true), + // 39 is maximum address in IPv6 + IP( JDBCType.VARCHAR, -1, 39, 0), + KEYWORD( JDBCType.VARCHAR, Integer.MAX_VALUE, 256, 0), + TEXT( JDBCType.VARCHAR, Integer.MAX_VALUE, Integer.MAX_VALUE, 0, false, false, false, false), + OBJECT( JDBCType.STRUCT, -1, 0, 0), + NESTED( JDBCType.STRUCT, -1, 0, 0), + TOKEN_COUNT( JDBCType.INTEGER, Integer.BYTES, 10, 11), + BINARY( JDBCType.VARBINARY, -1, Integer.MAX_VALUE, 0), + GEO_POINT( null, -1, Integer.MAX_VALUE, 0), + DATE( JDBCType.TIMESTAMP, Long.BYTES, 19, 20); + // @formatter:on - String esName(); + /** + * Elasticsearch type name + */ + public final String esType; - default String sqlName() { - return sqlType().name(); + /** + * Compatible JDBC type + */ + public final JDBCType jdbcType; + + + /** + * Size of the type in bytes + *

+ * -1 if the size can vary + */ + public final int size; + + /** + * Precision + *

+ * Specified column size. For numeric data, this is the maximum precision. For character + * data, this is the length in characters. For datetime datatypes, this is the length in characters of the + * String representation (assuming the maximum allowed defaultPrecision of the fractional seconds component). + */ + public final int defaultPrecision; + + + /** + * Display Size + *

+ * Normal maximum width in characters. + */ + public final int displaySize; + + /** + * True if the type represents a signed number + */ + public final boolean isSigned; + + /** + * True if the type represents an integer number + */ + public final boolean isInteger; + + /** + * True if the type represents a rational number + */ + public final boolean isRational; + + /** + * True if the type supports doc values by default + */ + public final boolean defaultDocValues; + + DataType(JDBCType jdbcType, int size, int defaultPrecision, int displaySize, boolean isSigned, boolean isInteger, boolean isRational, + boolean defaultDocValues) { + this.esType = name().toLowerCase(Locale.ROOT); + this.jdbcType = jdbcType; + this.size = size; + this.defaultPrecision = defaultPrecision; + this.displaySize = displaySize; + this.isSigned = isSigned; + this.isInteger = isInteger; + this.isRational = isRational; + this.defaultDocValues = defaultDocValues; } - JDBCType sqlType(); - - boolean hasDocValues(); - - default Object defaultValue() { - return null; + DataType(JDBCType jdbcType, int size, int defaultPrecision, int displaySize) { + this(jdbcType, size, defaultPrecision, displaySize, false, false, false, true); } - default int size() { - return JdbcUtils.size(sqlType()); + public String sqlName() { + return jdbcType.getName(); } - default int precision() { - return JdbcUtils.precision(sqlType()); + public boolean isNumeric() { + return isInteger || isRational; } - default int scale() { - return JdbcUtils.scale(sqlType()); + public boolean isString() { + return this == KEYWORD || this == TEXT; } - default int displaySize() { - return JdbcUtils.displaySize(sqlType()); + public boolean isPrimitive() { + return this != OBJECT && this != NESTED; } - default boolean isSigned() { - return JdbcUtils.isSigned(sqlType()); - } - - default boolean isInteger() { - return JdbcUtils.isInteger(sqlType()); - } - - default boolean isRational() { - return JdbcUtils.isRational(sqlType()); - } - - default boolean isNumeric() { - return isInteger() || isRational(); - } - - boolean isPrimitive(); - - default boolean same(DataType other) { - return getClass() == other.getClass(); - } -} \ No newline at end of file +} diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/DataTypeConversion.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/DataTypeConversion.java index 37223cc2d66..c5536e0d14c 100644 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/DataTypeConversion.java +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/DataTypeConversion.java @@ -25,7 +25,7 @@ public abstract class DataTypeConversion { private static final DateTimeFormatter UTC_DATE_FORMATTER = ISODateTimeFormat.dateTimeNoMillis().withZoneUTC(); public static DataType commonType(DataType left, DataType right) { - if (left.same(right)) { + if (left == right) { return left; } if (DataTypes.isNull(left)) { @@ -36,27 +36,27 @@ public abstract class DataTypeConversion { } if (left.isNumeric() && right.isNumeric()) { // if one is int - if (left.isInteger()) { + if (left.isInteger) { // promote the highest int - if (right.isInteger()) { - return left.size() > right.size() ? left : right; + if (right.isInteger) { + return left.size > right.size ? left : right; } // promote the rational return right; } // try the other side - if (right.isInteger()) { + if (right.isInteger) { return left; } // promote the highest rational - return left.size() > right.size() ? left : right; + return left.size > right.size ? left : right; } - if (left instanceof StringType) { + if (left.isString()) { if (right.isNumeric()) { return right; } } - if (right instanceof StringType) { + if (right.isString()) { if (left.isNumeric()) { return left; } @@ -74,25 +74,27 @@ public abstract class DataTypeConversion { if (from.getClass() == to.getClass()) { return true; } - if (from instanceof NullType) { + if (from == DataType.NULL) { return true; } // anything can be converted to String - if (to instanceof StringType) { + if (to.isString()) { return true; } + // also anything can be converted into a bool - if (to instanceof BooleanType) { + if (to == DataType.BOOLEAN) { return true; } // numeric conversion - if ((from instanceof StringType || from instanceof BooleanType || from instanceof DateType || from.isNumeric()) && to.isNumeric()) { + if ((from.isString() || from == DataType.BOOLEAN || from == DataType.DATE || from.isNumeric()) && to.isNumeric()) { return true; } + // date conversion - if ((from instanceof DateType || from instanceof StringType || from.isNumeric()) && to instanceof DateType) { + if ((from == DataType.DATE || from.isString() || from.isNumeric()) && to == DataType.DATE) { return true; } @@ -103,150 +105,145 @@ public abstract class DataTypeConversion { * Get the conversion from one type to another. */ public static Conversion conversionFor(DataType from, DataType to) { - if (to instanceof StringType) { - return conversionToString(from); + switch (to) { + case KEYWORD: + case TEXT: + return conversionToString(from); + case LONG: + return conversionToLong(from); + case INTEGER: + return conversionToInt(from); + case SHORT: + return conversionToShort(from); + case BYTE: + return conversionToByte(from); + case FLOAT: + return conversionToFloat(from); + case DOUBLE: + return conversionToDouble(from); + case DATE: + return conversionToDate(from); + case BOOLEAN: + return conversionToBoolean(from); + default: + throw new SqlIllegalArgumentException("cannot convert from [" + from + "] to [" + to + "]"); } - if (to instanceof LongType) { - return conversionToLong(from); - } - if (to instanceof IntegerType) { - return conversionToInt(from); - } - if (to instanceof ShortType) { - return conversionToShort(from); - } - if (to instanceof ByteType) { - return conversionToByte(from); - } - if (to instanceof FloatType) { - return conversionToFloat(from); - } - if (to instanceof DoubleType) { - return conversionToDouble(from); - } - if (to instanceof DateType) { - return conversionToDate(from); - } - if (to instanceof BooleanType) { - return conversionToBoolean(from); - } - throw new SqlIllegalArgumentException("cannot convert from [" + from + "] to [" + to + "]"); } private static Conversion conversionToString(DataType from) { - if (from instanceof DateType) { + if (from == DataType.DATE) { return Conversion.DATE_TO_STRING; } return Conversion.OTHER_TO_STRING; } private static Conversion conversionToLong(DataType from) { - if (from.isRational()) { + if (from.isRational) { return Conversion.RATIONAL_TO_LONG; } - if (from.isInteger()) { + if (from.isInteger) { return Conversion.INTEGER_TO_LONG; } - if (from instanceof BooleanType) { + if (from == DataType.BOOLEAN) { return Conversion.BOOL_TO_INT; // We emit an int here which is ok because of Java's casting rules } - if (from instanceof StringType) { + if (from.isString()) { return Conversion.STRING_TO_LONG; } throw new SqlIllegalArgumentException("cannot convert from [" + from + "] to [Long]"); } private static Conversion conversionToInt(DataType from) { - if (from.isRational()) { + if (from.isRational) { return Conversion.RATIONAL_TO_INT; } - if (from.isInteger()) { + if (from.isInteger) { return Conversion.INTEGER_TO_INT; } - if (from instanceof BooleanType) { + if (from == DataType.BOOLEAN) { return Conversion.BOOL_TO_INT; } - if (from instanceof StringType) { + if (from.isString()) { return Conversion.STRING_TO_INT; } throw new SqlIllegalArgumentException("cannot convert from [" + from + "] to [Integer]"); } private static Conversion conversionToShort(DataType from) { - if (from.isRational()) { + if (from.isRational) { return Conversion.RATIONAL_TO_SHORT; } - if (from.isInteger()) { + if (from.isInteger) { return Conversion.INTEGER_TO_SHORT; } - if (from instanceof BooleanType) { + if (from == DataType.BOOLEAN) { return Conversion.BOOL_TO_SHORT; } - if (from instanceof StringType) { + if (from.isString()) { return Conversion.STRING_TO_SHORT; } throw new SqlIllegalArgumentException("cannot convert [" + from + "] to [Short]"); } private static Conversion conversionToByte(DataType from) { - if (from.isRational()) { + if (from.isRational) { return Conversion.RATIONAL_TO_BYTE; } - if (from.isInteger()) { + if (from.isInteger) { return Conversion.INTEGER_TO_BYTE; } - if (from instanceof BooleanType) { + if (from == DataType.BOOLEAN) { return Conversion.BOOL_TO_BYTE; } - if (from instanceof StringType) { + if (from.isString()) { return Conversion.STRING_TO_BYTE; } throw new SqlIllegalArgumentException("cannot convert [" + from + "] to [Byte]"); } private static Conversion conversionToFloat(DataType from) { - if (from.isRational()) { + if (from.isRational) { return Conversion.RATIONAL_TO_FLOAT; } - if (from.isInteger()) { + if (from.isInteger) { return Conversion.INTEGER_TO_FLOAT; } - if (from instanceof BooleanType) { + if (from == DataType.BOOLEAN) { return Conversion.BOOL_TO_FLOAT; } - if (from instanceof StringType) { + if (from.isString()) { return Conversion.STRING_TO_FLOAT; } throw new SqlIllegalArgumentException("cannot convert [" + from + "] to [Float]"); } private static Conversion conversionToDouble(DataType from) { - if (from.isRational()) { + if (from.isRational) { return Conversion.RATIONAL_TO_DOUBLE; } - if (from.isInteger()) { + if (from.isInteger) { return Conversion.INTEGER_TO_DOUBLE; } - if (from instanceof BooleanType) { + if (from == DataType.BOOLEAN) { return Conversion.BOOL_TO_DOUBLE; } - if (from instanceof StringType) { + if (from.isString()) { return Conversion.STRING_TO_DOUBLE; } throw new SqlIllegalArgumentException("cannot convert [" + from + "] to [Double]"); } private static Conversion conversionToDate(DataType from) { - if (from.isRational()) { + if (from.isRational) { return Conversion.RATIONAL_TO_LONG; } - if (from.isInteger()) { + if (from.isInteger) { return Conversion.INTEGER_TO_LONG; } - if (from instanceof BooleanType) { + if (from == DataType.BOOLEAN) { return Conversion.BOOL_TO_INT; // We emit an int here which is ok because of Java's casting rules } - if (from instanceof StringType) { + if (from.isString()) { return Conversion.STRING_TO_DATE; } throw new SqlIllegalArgumentException("cannot convert [" + from + "] to [Date]"); @@ -256,7 +253,7 @@ public abstract class DataTypeConversion { if (from.isNumeric()) { return Conversion.NUMERIC_TO_BOOLEAN; } - if (from instanceof StringType) { + if (from.isString()) { return Conversion.STRING_TO_BOOLEAN; } throw new SqlIllegalArgumentException("cannot convert [" + from + "] to [Boolean]"); @@ -297,12 +294,10 @@ public abstract class DataTypeConversion { } return Booleans.parseBoolean(lowVal); } + public static Object convert(Object value, DataType dataType) { DataType detectedType = DataTypes.fromJava(value); - if (detectedType.equals(dataType)) { - return value; - } - if (value == null) { + if (detectedType.equals(dataType) || value == null) { return value; } return conversionFor(detectedType, dataType).convert(value); @@ -337,12 +332,11 @@ public abstract class DataTypeConversion { STRING_TO_FLOAT(fromString(Float::valueOf, "Float")), RATIONAL_TO_DOUBLE(fromDouble(value -> value)), INTEGER_TO_DOUBLE(fromLong(Double::valueOf)), - BOOL_TO_DOUBLE(fromBool(value -> value ? 1d: 0d)), + BOOL_TO_DOUBLE(fromBool(value -> value ? 1d : 0d)), STRING_TO_DOUBLE(fromString(Double::valueOf, "Double")), STRING_TO_DATE(fromString(UTC_DATE_FORMATTER::parseMillis, "Date")), NUMERIC_TO_BOOLEAN(fromLong(value -> value != 0)), - STRING_TO_BOOLEAN(fromString(DataTypeConversion::convertToBoolean, "Boolean")), - ; + STRING_TO_BOOLEAN(fromString(DataTypeConversion::convertToBoolean, "Boolean")),; private final Function converter; @@ -387,6 +381,6 @@ public abstract class DataTypeConversion { return dataType; } - return dataType.isInteger() ? dataType : DataTypes.LONG; + return dataType.isInteger ? dataType : DataType.LONG; } } diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/DataTypes.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/DataTypes.java index 511602db522..8975288ff04 100644 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/DataTypes.java +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/DataTypes.java @@ -8,119 +8,47 @@ package org.elasticsearch.xpack.sql.type; import org.elasticsearch.xpack.sql.SqlIllegalArgumentException; import org.joda.time.DateTime; -import java.sql.JDBCType; -import java.util.LinkedHashMap; -import java.util.Map; - public abstract class DataTypes { - public static final DataType NULL = new NullType(); - public static final DataType BOOLEAN = new BooleanType(true); - public static final DataType BYTE = new ByteType(true); - public static final DataType SHORT = new ShortType(true); - public static final DataType INTEGER = new IntegerType(true); - public static final DataType LONG = new LongType(true); - public static final DataType DOUBLE = new DoubleType(true); - public static final DataType FLOAT = new FloatType(true); - public static final DataType HALF_FLOAT = new HalfFloatType(true); - public static final DataType IP_TYPE = new IpType(true); - public static final DataType KEYWORD = KeywordType.DEFAULT; - public static final DataType TEXT = new TextType(); - - public static final DataType GEO_POINT = new GeoPointType(); - public static final DataType DATE = DateType.DEFAULT; - - public static final DataType BINARY = new BinaryType(true); - - private static final Map ES_PRIMITIVES_DEFAULT = new LinkedHashMap<>(); - private static final Map ES_PRIMITIVES_NO_DOC_VALUES = new LinkedHashMap<>(); - private static final Map JDBC_TO_TYPES = new LinkedHashMap<>(); - - static { - initDefault(NULL); - initDefault(BOOLEAN); - initDefault(BYTE); - initDefault(SHORT); - initDefault(INTEGER); - initDefault(LONG); - initDefault(DOUBLE); - initDefault(FLOAT); - initDefault(HALF_FLOAT); - initDefault(IP_TYPE); - // text and keyword are handled separately - initDefault(BINARY); - - //init(GEO_POINT); - - for (DataType type : ES_PRIMITIVES_DEFAULT.values()) { - JDBC_TO_TYPES.put(type.sqlType(), type); - } - - initNoDocValues(NULL); - initNoDocValues(new BooleanType(false)); - initNoDocValues(new ByteType(false)); - initNoDocValues(new ShortType(false)); - initNoDocValues(new IntegerType(false)); - initNoDocValues(new LongType(false)); - initNoDocValues(new DoubleType(false)); - initNoDocValues(new FloatType(false)); - initNoDocValues(new HalfFloatType(false)); - initNoDocValues(new IpType(false)); - initNoDocValues(new BinaryType(false)); - } - - private static void initDefault(DataType type) { - ES_PRIMITIVES_DEFAULT.put(type.esName(), type); - } - - private static void initNoDocValues(DataType type) { - ES_PRIMITIVES_NO_DOC_VALUES.put(type.esName(), type); - } - public static boolean isNull(DataType from) { - return from instanceof NullType; + return from == DataType.NULL; } public static boolean isUnsupported(DataType from) { - return from instanceof UnsupportedDataType; + return from == DataType.UNSUPPORTED; } public static DataType fromJava(Object value) { if (value == null) { - return NULL; + return DataType.NULL; } if (value instanceof Integer) { - return INTEGER; + return DataType.INTEGER; } if (value instanceof Long) { - return LONG; + return DataType.LONG; } if (value instanceof Boolean) { - return BOOLEAN; + return DataType.BOOLEAN; } if (value instanceof Double) { - return DOUBLE; + return DataType.DOUBLE; } if (value instanceof Float) { - return FLOAT; + return DataType.FLOAT; } if (value instanceof Byte) { - return BYTE; + return DataType.BYTE; } if (value instanceof Short) { - return SHORT; + return DataType.SHORT; } if (value instanceof DateTime) { - return DATE; + return DataType.DATE; } if (value instanceof String) { - return KEYWORD; + return DataType.KEYWORD; } throw new SqlIllegalArgumentException("No idea what's the DataType for %s", value.getClass()); } - - public static DataType fromEsName(String typeString, boolean docValuesEnabled) { - DataType t = docValuesEnabled ? ES_PRIMITIVES_DEFAULT.get(typeString) : ES_PRIMITIVES_NO_DOC_VALUES.get(typeString); - return t != null ? t : new UnsupportedDataType(typeString); - } } \ No newline at end of file diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/DateEsField.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/DateEsField.java new file mode 100644 index 00000000000..b9737fbba60 --- /dev/null +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/DateEsField.java @@ -0,0 +1,52 @@ +/* + * 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.type; + +import org.elasticsearch.common.util.CollectionUtils; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * SQL-related information about an index field with date type + */ +public class DateEsField extends EsField { + + public static final List DEFAULT_FORMAT = Arrays.asList("strict_date_optional_time", "epoch_millis"); + private final List formats; + + public DateEsField(String name, Map properties, boolean hasDocValues, String... formats) { + super(name, DataType.DATE, properties, hasDocValues); + this.formats = CollectionUtils.isEmpty(formats) ? DEFAULT_FORMAT : Arrays.asList(formats); + } + + @Override + public int getPrecision() { + // same as Long + // TODO: based this on format string + return 19; + } + + public List getFormats() { + return formats; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + if (!super.equals(o)) return false; + DateEsField dateField = (DateEsField) o; + return Objects.equals(formats, dateField.formats); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), formats); + } +} diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/DateType.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/DateType.java deleted file mode 100644 index 4d5a313422c..00000000000 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/DateType.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 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.type; - -import org.elasticsearch.common.util.CollectionUtils; - -import java.sql.JDBCType; -import java.util.Arrays; -import java.util.List; - -public class DateType extends AbstractDataType { - - public static final List DEFAULT_FORMAT = Arrays.asList("strict_date_optional_time", "epoch_millis"); - public static final DateType DEFAULT = new DateType(true); - - private final List formats; - - DateType(boolean docValues, String... formats) { - /* Since we normalize timestamps to UTC for storage and do not keep - * the origination zone information information we are technically - * `TIMESTAMP WITHOUT TIME ZONE` or just `TIMESTAMP`, or, in Oracle - * parlance, `TIMESTAMP WITH LOCAL TIME ZONE`. - * `TIMESTAMP WITH TIME ZONE` implies that we store the original - * time zone of the even. Confusingly, PostgreSQL's - * `TIMESTAMP WITH TIME ZONE` type does not store original time zone, - * unlike H2 and Oracle, *but* it is aware of the session's time zone - * so it is preferred. But it is *weird*. As bad as it feels not to - * be like PostgreSQL, we are going to not be like PostgreSQL here - * and return TIMESTAMP so we more closely conform with H2 and - * (shudder) Oracle. */ - super(JDBCType.TIMESTAMP, docValues); - this.formats = CollectionUtils.isEmpty(formats) ? DEFAULT_FORMAT : Arrays.asList(formats); - } - - @Override - public String esName() { - return "date"; - } - - @Override - public int precision() { - // same as Long - // TODO: based this on format string - return 19; - } - - public List formats() { - return formats; - } -} diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/DoubleType.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/DoubleType.java deleted file mode 100644 index 0126a5c8ba1..00000000000 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/DoubleType.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * 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.type; - -import java.sql.JDBCType; - -public class DoubleType extends AbstractDataType { - - DoubleType(boolean docValues) { - super(JDBCType.DOUBLE, docValues); - } - - @Override - public String esName() { - return "double"; - } -} diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/EsField.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/EsField.java new file mode 100644 index 00000000000..cc7e085416c --- /dev/null +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/EsField.java @@ -0,0 +1,103 @@ +/* + * 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.type; + +import org.elasticsearch.common.Nullable; + +import java.util.Map; +import java.util.Objects; + +/** + * SQL-related information about an index field + */ +public class EsField { + private final DataType esDataType; + private final boolean hasDocValues; + private final Map properties; + private final String name; + + public EsField(String name, DataType esDataType, Map properties, boolean hasDocValues) { + this.name = name; + this.esDataType = esDataType; + this.hasDocValues = hasDocValues; + this.properties = properties; + } + + /** + * Returns the field path + */ + public String getName() { + return name; + } + + /** + * The field type + */ + public DataType getDataType() { + return esDataType; + } + + /** + * The field supports doc values + */ + public boolean hasDocValues() { + return hasDocValues; + } + + /** + * Returns list of properties for the nested and object fields, list of subfield if the field + * was indexed in a few different ways or null otherwise + */ + @Nullable + public Map getProperties() { + return properties; + } + + /** + * Returns the path to the keyword version of this field if this field is text and it has a subfield that is + * indexed as keyword, null if such field is not found or the field name itself in all other cases + */ + public EsField getExactField() { + return this; + } + + /** + * Returns the precision of the field + *

+ * Precision is the specified column size. For numeric data, this is the maximum precision. For character + * data, this is the length in characters. For datetime datatypes, this is the length in characters of the + * String representation (assuming the maximum allowed defaultPrecision of the fractional seconds component). + */ + public int getPrecision() { + return esDataType.defaultPrecision; + } + + /** + * True if this field name can be used in sorting, aggregations and term queries as is + *

+ * This will be true for most fields except analyzed text fields that cannot be used directly and should be + * replaced with the field returned by {@link EsField#getExactField()} instead. + */ + public boolean isExact() { + return true; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + EsField field = (EsField) o; + return hasDocValues == field.hasDocValues && + esDataType == field.esDataType && + Objects.equals(properties, field.properties) && + Objects.equals(name, field.name); + } + + @Override + public int hashCode() { + return Objects.hash(esDataType, hasDocValues, properties, name); + } +} diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/FloatType.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/FloatType.java deleted file mode 100644 index f14045b1651..00000000000 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/FloatType.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * 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.type; - -import java.sql.JDBCType; - -public class FloatType extends AbstractDataType { - - FloatType(boolean docValues) { - super(JDBCType.REAL, docValues); - } - - @Override - public String esName() { - return "float"; - } -} diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/GeoPointType.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/GeoPointType.java deleted file mode 100644 index e93b232e700..00000000000 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/GeoPointType.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * 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.type; - -import java.sql.JDBCType; - -public class GeoPointType extends AbstractDataType { - - GeoPointType() { - super(JDBCType.NULL, false); - } - - @Override - public String esName() { - return "geo-point"; - } - - @Override - public JDBCType sqlType() { - throw new UnsupportedOperationException("need to determine actual format"); - } -} diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/HalfFloatType.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/HalfFloatType.java deleted file mode 100644 index c4227864f93..00000000000 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/HalfFloatType.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * 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.type; - -import java.sql.JDBCType; - -public class HalfFloatType extends AbstractDataType { - - HalfFloatType(boolean docValues) { - super(JDBCType.FLOAT, docValues); - } - - @Override - public String esName() { - return "half_float"; - } -} diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/IntegerType.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/IntegerType.java deleted file mode 100644 index 82710f1e652..00000000000 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/IntegerType.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * 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.type; - -import java.sql.JDBCType; - -public class IntegerType extends AbstractDataType { - - IntegerType(boolean docValues) { - super(JDBCType.INTEGER, docValues); - } - - @Override - public String esName() { - return "integer"; - } -} diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/IpType.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/IpType.java deleted file mode 100644 index 7bbfbf5b27e..00000000000 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/IpType.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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.type; - -import java.sql.JDBCType; - -public class IpType extends AbstractDataType { - - IpType(boolean docValues) { - super(JDBCType.VARCHAR, docValues); - } - - @Override - public String esName() { - return "ip"; - } - - @Override - public int precision() { - // maximum address in IPv6 - return 39; - } -} diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/JdbcUtils.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/JdbcUtils.java deleted file mode 100644 index 486939125a6..00000000000 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/JdbcUtils.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * 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.type; - -import java.sql.JDBCType; - -abstract class JdbcUtils { - - static boolean isSigned(JDBCType type) { - switch (type) { - case BIGINT: - case DECIMAL: - case DOUBLE: - case INTEGER: - case SMALLINT: - case FLOAT: - case REAL: - case NUMERIC: - case TINYINT: - return true; - default: - return false; - } - } - - static int scale(JDBCType type) { - switch (type) { - case REAL: return 7; - case FLOAT: - case DOUBLE: return 16; - default: return 0; - } - } - - static int precision(JDBCType type) { - switch (type) { - case NULL: return 0; - case BOOLEAN: return 1; - case TINYINT: return 3; - case SMALLINT: return 5; - case INTEGER: return 10; - case BIGINT: return 19; - // 24 bits precision - 24*log10(2) =~ 7 (7.22) - case REAL: return 7; - // 53 bits precision ~ 16(15.95) decimal digits (53log10(2)) - case FLOAT: - case DOUBLE: return 16; - case VARBINARY: - case VARCHAR: - return Integer.MAX_VALUE; - case TIME_WITH_TIMEZONE: return displaySize(type); - default: - return -1; - } - } - - static int displaySize(JDBCType type) { - switch (type) { - case NULL: return 0; - case BOOLEAN: return 1; - case TINYINT: return 3; - case SMALLINT: return 6; - case INTEGER: return 11; - case BIGINT: return 20; - case REAL: return 15; - case FLOAT: - case DOUBLE: return 25; - case VARCHAR: - case VARBINARY: return 0; - case TIMESTAMP: return 20; - default: - return 0; - } - } - - static boolean isRational(JDBCType type) { - switch (type) { - case REAL: - case DOUBLE: - case FLOAT: - case DECIMAL: - case NUMERIC: - return true; - default: - return false; - } - } - - static boolean isInteger(JDBCType type) { - switch (type) { - case TINYINT: - case SMALLINT: - case INTEGER: - case BIGINT: - return true; - default: - return false; - } - } - - static int size(JDBCType type) { - switch (type) { - case NULL: return 0; - case BOOLEAN: return 1; - case TINYINT: return Byte.BYTES; - case SMALLINT: return Short.BYTES; - case INTEGER: return Integer.BYTES; - case TIMESTAMP: - case BIGINT: return Long.BYTES; - case REAL: return Float.BYTES; - case FLOAT: - case DOUBLE: return Double.BYTES; - case VARCHAR: - case VARBINARY: return Integer.MAX_VALUE; - default: - return -1; - } - } -} \ No newline at end of file diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/KeywordEsField.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/KeywordEsField.java new file mode 100644 index 00000000000..d40fa7b19af --- /dev/null +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/KeywordEsField.java @@ -0,0 +1,55 @@ +/* + * 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.type; + +import java.util.Collections; +import java.util.Map; +import java.util.Objects; + +/** + * SQL-related information about an index field with keyword type + */ +public class KeywordEsField extends EsField { + + private final int precision; + private final boolean normalized; + + public KeywordEsField(String name) { + this(name, Collections.emptyMap(), true, DataType.KEYWORD.defaultPrecision, false); + } + + public KeywordEsField(String name, Map properties, boolean hasDocValues, int precision, boolean normalized) { + super(name, DataType.KEYWORD, properties, hasDocValues); + this.precision = precision; + this.normalized = normalized; + } + + @Override + public int getPrecision() { + return precision; + } + + @Override + public boolean isExact() { + return normalized == false; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + if (!super.equals(o)) return false; + KeywordEsField that = (KeywordEsField) o; + return precision == that.precision && + normalized == that.normalized; + } + + @Override + public int hashCode() { + + return Objects.hash(super.hashCode(), precision, normalized); + } +} \ No newline at end of file diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/KeywordType.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/KeywordType.java deleted file mode 100644 index bc135d61b02..00000000000 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/KeywordType.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * 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.type; - -import java.util.Map; -import java.util.Objects; - -import static java.util.Collections.emptyMap; - -public class KeywordType extends StringType { - - static final int DEFAULT_LENGTH = 256; - static final boolean DEFAULT_NORMALIZED = false; - static final KeywordType DEFAULT = new KeywordType(true, DEFAULT_LENGTH, DEFAULT_NORMALIZED, emptyMap()); - - private final int length; - private final boolean normalized; - - KeywordType(boolean docValues, int length, boolean normalized, Map fields) { - super(docValues, fields); - this.length = length; - this.normalized = normalized; - } - - @Override - public boolean isInexact() { - return normalized; - } - - public boolean isNormalized() { - return normalized; - } - - @Override - public String esName() { - return "keyword"; - } - - @Override - public int precision() { - return length; - } - - @Override - public int hashCode() { - return Objects.hash(length, hasDocValues(), fields()); - } - - @Override - public boolean equals(Object obj) { - return super.equals(obj) && length == ((KeywordType) obj).length; - } - - static DataType from(boolean docValues, int length, boolean normalized, Map fields) { - return docValues && length == DEFAULT_LENGTH && fields.isEmpty() && normalized == DEFAULT_NORMALIZED - ? DEFAULT - : new KeywordType(docValues, length, normalized, fields); - } -} diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/LongType.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/LongType.java deleted file mode 100644 index e2ab14cf3ca..00000000000 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/LongType.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * 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.type; - -import java.sql.JDBCType; - -public class LongType extends AbstractDataType { - - LongType(boolean docValues) { - super(JDBCType.BIGINT, docValues); - } - - @Override - public String esName() { - return "long"; - } -} diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/NestedType.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/NestedType.java deleted file mode 100644 index 7382e62a2fe..00000000000 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/NestedType.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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.type; - -import java.sql.JDBCType; -import java.util.Map; - -public class NestedType extends CompoundDataType { - - public NestedType(Map properties) { - super(JDBCType.STRUCT, false, properties); - } - - @Override - public String esName() { - return "nested"; - } - - @Override - public String toString() { - return "N" + properties(); - } -} \ No newline at end of file diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/NullType.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/NullType.java deleted file mode 100644 index f96f8411b1e..00000000000 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/NullType.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * 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.type; - -import java.sql.JDBCType; - -public class NullType extends AbstractDataType { - - NullType() { - super(JDBCType.NULL, false); - } - - @Override - public String esName() { - return "null"; - } -} diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/ObjectType.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/ObjectType.java deleted file mode 100644 index 0c63ab6d334..00000000000 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/ObjectType.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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.type; - -import java.sql.JDBCType; -import java.util.Map; - -import static java.util.Collections.emptyMap; - -public class ObjectType extends CompoundDataType { - - public static final ObjectType EMPTY = new ObjectType(emptyMap()); - - ObjectType(Map properties) { - super(JDBCType.STRUCT, false, properties); - } - - @Override - public String esName() { - return "object"; - } - - @Override - public String toString() { - return "O" + properties(); - } -} diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/ScaledFloatType.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/ScaledFloatType.java deleted file mode 100644 index 9be5a2fac02..00000000000 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/ScaledFloatType.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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.type; - -import java.sql.JDBCType; - -public class ScaledFloatType extends AbstractDataType { - - public ScaledFloatType(boolean docValues) { - super(JDBCType.FLOAT, docValues); - } - - @Override - public String esName() { - return "scaled_float"; - } - - @Override - public int precision() { - // just like long - return 19; - } -} diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/Schema.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/Schema.java index 4370b232f68..2252920a53c 100644 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/Schema.java +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/Schema.java @@ -120,7 +120,7 @@ public class Schema implements Iterable { } sb.append(names.get(i)); sb.append(":"); - sb.append(types.get(i).esName()); + sb.append(types.get(i).esType); } sb.append("]"); return sb.toString(); diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/ShortType.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/ShortType.java deleted file mode 100644 index 767a31d6d9b..00000000000 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/ShortType.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * 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.type; - -import java.sql.JDBCType; - -public class ShortType extends AbstractDataType { - - ShortType(boolean docValues) { - super(JDBCType.SMALLINT, docValues); - } - - @Override - public String esName() { - return "short"; - } -} diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/StringType.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/StringType.java deleted file mode 100644 index abe9128434e..00000000000 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/StringType.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * 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.type; - -import java.sql.JDBCType; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Objects; - -import static java.util.Collections.emptyMap; - -// String type is a special type of CompoundDataType -public abstract class StringType extends CompoundDataType { - - private final boolean docValue; - private final Map fields; - private final Map exactKeywords; - - - StringType(boolean docValue, Map fields) { - super(JDBCType.VARCHAR, docValue, fields); - - this.docValue = docValue; - this.fields = fields; - - if (docValue || fields.isEmpty()) { - exactKeywords = emptyMap(); - } else { - exactKeywords = new LinkedHashMap<>(); - for (Entry entry : fields.entrySet()) { - DataType t = entry.getValue(); - // consider only non-normalized keywords - if (t instanceof KeywordType) { - KeywordType kt = (KeywordType) t; - if (!kt.isNormalized()) { - exactKeywords.put(entry.getKey(), kt); - } - } - } - } - } - - public abstract boolean isInexact(); - - public Map fields() { - return properties(); - } - - public Map exactKeywords() { - return exactKeywords; - } - - @Override - public boolean isPrimitive() { - return true; - } - - @Override - public int precision() { - return Integer.MAX_VALUE; - } - - @Override - public int hashCode() { - return Objects.hash(docValue, fields); - } - - @Override - public boolean equals(Object obj) { - if (super.equals(obj)) { - StringType other = (StringType) obj; - return Objects.equals(docValue, other.docValue) - && Objects.equals(fields(), other.fields()); - } - return false; - } - - @Override - public String toString() { - return esName(); - } -} \ No newline at end of file diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/TextEsField.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/TextEsField.java new file mode 100644 index 00000000000..f1c596a301c --- /dev/null +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/TextEsField.java @@ -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.type; + +import org.elasticsearch.xpack.sql.analysis.index.MappingException; + +import java.util.Map; + +/** + * SQL-related information about an index field with text type + */ +public class TextEsField extends EsField { + + public TextEsField(String name, Map properties, boolean hasDocValues) { + super(name, DataType.TEXT, properties, hasDocValues); + } + + @Override + public EsField getExactField() { + EsField field = null; + for (EsField property : getProperties().values()) { + if (property.getDataType() == DataType.KEYWORD && property.isExact()) { + if (field != null) { + throw new MappingException("Multiple exact keyword candidates available for [" + getName() + + "]; specify which one to use"); + } + field = property; + } + } + if (field == null) { + throw new MappingException("No keyword/multi-field defined exact matches for [" + getName() + + "]; define one or use MATCH/QUERY instead"); + } + return field; + } + + @Override + public boolean isExact() { + return false; + } +} diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/TextType.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/TextType.java deleted file mode 100644 index 47b74053f86..00000000000 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/TextType.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * 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.type; - -import java.util.Map; -import java.util.Objects; - -import static java.util.Collections.emptyMap; -import static java.util.Collections.singletonMap; - -public class TextType extends StringType { - - private static final TextType DEFAULT = new TextType(false, singletonMap("keyword", KeywordType.DEFAULT)); - - private final boolean fieldData; - - TextType() { - this(false, emptyMap()); - } - - TextType(boolean fieldData, Map fields) { - super(false, fields); - this.fieldData = fieldData; - } - - public boolean hasFieldData() { - return fieldData; - } - - @Override - public boolean isInexact() { - return true; - } - - @Override - public String esName() { - return "text"; - } - - @Override - public int hashCode() { - return Objects.hash(super.hashCode(), fieldData); - } - - @Override - public boolean equals(Object obj) { - return super.equals(obj) && fieldData == ((TextType) obj).fieldData; - } - - static DataType from(boolean fieldData, Map fields) { - return DEFAULT.fieldData == fieldData && DEFAULT.fields().equals(fields) ? DEFAULT : new TextType(fieldData, fields); - } -} diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/TokenCountType.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/TokenCountType.java deleted file mode 100644 index 27a4c18d5aa..00000000000 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/TokenCountType.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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.type; - -import java.sql.JDBCType; - -public class TokenCountType extends AbstractDataType { - - TokenCountType(boolean docValues) { - super(JDBCType.INTEGER, docValues); - } - - @Override - public String esName() { - return "token_count"; - } - - @Override - public boolean isInteger() { - return false; - } - - @Override - public boolean isRational() { - return false; - } -} diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/Types.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/Types.java index 1939f673507..fd537d9f667 100644 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/Types.java +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/Types.java @@ -7,47 +7,19 @@ package org.elasticsearch.xpack.sql.type; import org.elasticsearch.common.Booleans; import org.elasticsearch.common.Strings; -import org.elasticsearch.xpack.sql.analysis.index.MappingException; -import java.util.HashSet; +import java.util.Collections; import java.util.LinkedHashMap; +import java.util.Locale; import java.util.Map; import java.util.Map.Entry; -import java.util.Set; -import static java.lang.Math.floor; -import static java.lang.Math.log10; -import static java.lang.Math.round; import static java.util.Collections.emptyMap; -import static java.util.Collections.unmodifiableSet; public abstract class Types { - private static final Set KNOWN_TYPES; - - static { - Set types = new HashSet<>(); - types.add("text"); - types.add("keyword"); - types.add("long"); - types.add("integer"); - types.add("short"); - types.add("byte"); - types.add("double"); - types.add("float"); - types.add("half_float"); - types.add("scaled_float"); - types.add("date"); - types.add("boolean"); - types.add("binary"); - types.add("object"); - types.add("nested"); - - KNOWN_TYPES = unmodifiableSet(types); - } - @SuppressWarnings("unchecked") - public static Map fromEs(Map asMap) { + public static Map fromEs(Map asMap) { Map props = null; if (asMap != null && !asMap.isEmpty()) { props = (Map) asMap.get("properties"); @@ -55,8 +27,8 @@ public abstract class Types { return props == null || props.isEmpty() ? emptyMap() : startWalking(props); } - private static Map startWalking(Map mapping) { - Map types = new LinkedHashMap<>(); + private static Map startWalking(Map mapping) { + Map types = new LinkedHashMap<>(); if (mapping == null) { return emptyMap(); @@ -68,87 +40,74 @@ public abstract class Types { return types; } + private static DataType getType(Map content) { + if (content.containsKey("type")) { + try { + return DataType.valueOf(content.get("type").toString().toUpperCase(Locale.ROOT)); + } catch (IllegalArgumentException ex) { + return DataType.UNSUPPORTED; + } + } else if (content.containsKey("properties")) { + return DataType.OBJECT; + } else { + return DataType.UNSUPPORTED; + } + } + @SuppressWarnings("unchecked") - private static void walkMapping(String name, Object value, Map mapping) { + private static void walkMapping(String name, Object value, Map mapping) { // object type - only root or nested docs supported if (value instanceof Map) { Map content = (Map) value; // extract field type - Object type = content.get("type"); - if (type instanceof String) { - String st = type.toString(); - - if (knownType(st)) { - if (isNested(st)) { - mapping.put(name, new NestedType(fromEs(content))); - } else { - // check dates first to account for the format - DataType primitiveType = createPrimitiveType(st, content); - if (primitiveType != null) { - mapping.put(name, primitiveType); - } - } + DataType esDataType = getType(content); + final Map properties; + if (esDataType == DataType.OBJECT || esDataType == DataType.NESTED) { + properties = fromEs(content); + } else if (content.containsKey("fields")) { + // Check for multifields + Object fields = content.get("fields"); + if (fields instanceof Map) { + properties = startWalking((Map) fields); } else { - mapping.put(name, new UnsupportedDataType(st)); + properties = Collections.emptyMap(); } + } else { + properties = Collections.emptyMap(); } - // object type ? - else if (type == null && content.containsKey("properties")) { - mapping.put(name, new ObjectType(fromEs(content))); - } - // bail out - else { - throw new MappingException("Unsupported mapping %s", type); + boolean docValues = boolSetting(content.get("doc_values"), esDataType.defaultDocValues); + final EsField field; + switch (esDataType) { + case TEXT: + field = new TextEsField(name, properties, docValues); + break; + case KEYWORD: + int length = intSetting(content.get("ignore_above"), esDataType.defaultPrecision); + boolean normalized = Strings.hasText(textSetting(content.get("normalizer"), null)); + field = new KeywordEsField(name, properties, docValues, length, normalized); + break; + case DATE: + Object fmt = content.get("format"); + if (fmt != null) { + field = new DateEsField(name, properties, docValues, Strings.delimitedListToStringArray(fmt.toString(), "||")); + } else { + field = new DateEsField(name, properties, docValues); + } + break; + case UNSUPPORTED: + String type = content.get("type").toString(); + field = new UnsupportedEsField(name, type); + break; + default: + field = new EsField(name, esDataType, properties, docValues); } + mapping.put(name, field); } else { - throw new MappingException("Unrecognized mapping %s", value); + throw new IllegalArgumentException("Unrecognized mapping " + value); } } - @SuppressWarnings("unchecked") - private static DataType createPrimitiveType(String typeString, Map content) { - // since this setting is available in most types, search for it regardless - - DataType type = null; - - boolean docValues = boolSetting(content.get("doc_values"), true); - switch (typeString) { - case "date": - Object fmt = content.get("format"); - if (fmt != null) { - type = new DateType(docValues, Strings.delimitedListToStringArray(fmt.toString(), "||")); - } - else { - type = docValues ? DateType.DEFAULT : new DateType(false); - } - break; - case "text": - boolean fieldData = boolSetting(content.get("fielddata"), false); - Object value = content.get("fields"); - Map fields = emptyMap(); - if (value instanceof Map) { - fields = startWalking((Map) value); - } - type = TextType.from(fieldData, fields); - break; - case "keyword": - int length = intSetting(content.get("ignore_above"), KeywordType.DEFAULT_LENGTH); - boolean normalized = Strings.hasText(textSetting(content.get("normalizer"), null)); - fields = emptyMap(); - value = content.get("fields"); - if (value instanceof Map) { - fields = startWalking((Map) value); - } - type = KeywordType.from(docValues, length, normalized, fields); - break; - default: - type = DataTypes.fromEsName(typeString, docValues); - } - - return type; - } - private static String textSetting(Object value, String defaultValue) { return value == null ? defaultValue : value.toString(); } @@ -160,17 +119,4 @@ public abstract class Types { private static int intSetting(Object value, int defaultValue) { return value == null ? defaultValue : Integer.parseInt(value.toString()); } - - private static boolean knownType(String st) { - return KNOWN_TYPES.contains(st); - } - - private static boolean isNested(String type) { - return "nested".equals(type); - } - - static int precision(long number) { - long abs = number == Long.MIN_VALUE ? Long.MAX_VALUE : number < 0 ? -number : number; - return (int) round(floor(log10(abs))) + 1; - } } \ No newline at end of file diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/UnsupportedDataType.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/UnsupportedDataType.java deleted file mode 100644 index f8ef7ed6573..00000000000 --- a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/UnsupportedDataType.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * 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.type; - -import org.elasticsearch.xpack.sql.analysis.index.MappingException; - -import java.sql.JDBCType; -import java.util.Objects; - -public class UnsupportedDataType extends AbstractDataType { - - private final String esType; - - UnsupportedDataType(String esType) { - super(JDBCType.OTHER, false); - this.esType = esType; - } - - @Override - public String sqlName() { - return "UNSUPPORTED"; - } - - @Override - public Object defaultValue() { - throw new MappingException("Unsupported Elasticsearch type " + esType); - } - - @Override - public boolean isInteger() { - throw new MappingException("Unsupported Elasticsearch type " + esType); - } - - @Override - public boolean isRational() { - throw new MappingException("Unsupported Elasticsearch type " + esType); - } - - @Override - public boolean same(DataType other) { - return (other instanceof UnsupportedDataType) && Objects.equals(esType, ((UnsupportedDataType) other).esType); - } - - @Override - public String esName() { - return esType; - } - - @Override - public boolean hasDocValues() { - throw new MappingException("Unsupported Elasticsearch type " + esType); - } - - @Override - public boolean isPrimitive() { - throw new MappingException("Unsupported Elasticsearch type " + esType); - } -} \ No newline at end of file diff --git a/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/UnsupportedEsField.java b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/UnsupportedEsField.java new file mode 100644 index 00000000000..c88d676c223 --- /dev/null +++ b/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/UnsupportedEsField.java @@ -0,0 +1,41 @@ +/* + * 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.type; + +import java.util.Collections; +import java.util.Objects; + +/** + * SQL-related information about an index field that cannot be supported by SQL + */ +public class UnsupportedEsField extends EsField { + + private String originalType; + + public UnsupportedEsField(String name, String originalType) { + super(name, DataType.UNSUPPORTED, Collections.emptyMap(), false); + this.originalType = originalType; + } + + public String getOriginalType() { + return originalType; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + if (!super.equals(o)) return false; + UnsupportedEsField that = (UnsupportedEsField) o; + return Objects.equals(originalType, that.originalType); + } + + @Override + public int hashCode() { + + return Objects.hash(super.hashCode(), originalType); + } +} diff --git a/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/analysis/analyzer/FieldAttributeTests.java b/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/analysis/analyzer/FieldAttributeTests.java index 1a96130c12a..f562a8d5063 100644 --- a/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/analysis/analyzer/FieldAttributeTests.java +++ b/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/analysis/analyzer/FieldAttributeTests.java @@ -18,16 +18,15 @@ import org.elasticsearch.xpack.sql.parser.SqlParser; import org.elasticsearch.xpack.sql.plan.logical.LogicalPlan; import org.elasticsearch.xpack.sql.plan.logical.Project; import org.elasticsearch.xpack.sql.type.DataType; -import org.elasticsearch.xpack.sql.type.KeywordType; -import org.elasticsearch.xpack.sql.type.TextType; +import org.elasticsearch.xpack.sql.type.EsField; import org.elasticsearch.xpack.sql.type.TypesTests; import org.joda.time.DateTimeZone; import java.util.List; import java.util.Map; -import static org.elasticsearch.xpack.sql.type.DataTypes.BOOLEAN; -import static org.elasticsearch.xpack.sql.type.DataTypes.KEYWORD; +import static org.elasticsearch.xpack.sql.type.DataType.BOOLEAN; +import static org.elasticsearch.xpack.sql.type.DataType.KEYWORD; import static org.hamcrest.CoreMatchers.instanceOf; import static org.hamcrest.Matchers.hasItem; import static org.hamcrest.Matchers.hasItems; @@ -46,7 +45,7 @@ public class FieldAttributeTests extends ESTestCase { parser = new SqlParser(DateTimeZone.UTC); functionRegistry = new FunctionRegistry(); - Map mapping = TypesTests.loadMapping("mapping-multi-field-variation.json"); + Map mapping = TypesTests.loadMapping("mapping-multi-field-variation.json"); EsIndex test = new EsIndex("test", mapping); getIndexResult = IndexResolution.valid(test); @@ -90,30 +89,30 @@ public class FieldAttributeTests extends ESTestCase { FieldAttribute attr = attribute("some.string"); assertThat(attr.path(), is("some")); assertThat(attr.name(), is("some.string")); - assertThat(attr.dataType(), instanceOf(TextType.class)); + assertThat(attr.dataType(), is(DataType.TEXT)); assertThat(attr.isInexact(), is(true)); FieldAttribute exact = attr.exactAttribute(); assertThat(exact.isInexact(), is(false)); assertThat(exact.name(), is("some.string.typical")); - assertThat(exact.dataType(), instanceOf(KeywordType.class)); + assertThat(exact.dataType(), is(KEYWORD)); } public void testAmbiguousExactKeyword() { FieldAttribute attr = attribute("some.ambiguous"); assertThat(attr.path(), is("some")); assertThat(attr.name(), is("some.ambiguous")); - assertThat(attr.dataType(), instanceOf(TextType.class)); + assertThat(attr.dataType(), is(DataType.TEXT)); assertThat(attr.isInexact(), is(true)); MappingException me = expectThrows(MappingException.class, () -> attr.exactAttribute()); assertThat(me.getMessage(), - is("Multiple exact keyword candidates [one, two] available for [some.ambiguous]; specify which one to use")); + is("Multiple exact keyword candidates available for [ambiguous]; specify which one to use")); } public void testNormalizedKeyword() { FieldAttribute attr = attribute("some.string.normalized"); assertThat(attr.path(), is("some.string")); assertThat(attr.name(), is("some.string.normalized")); - assertThat(attr.dataType(), instanceOf(KeywordType.class)); + assertThat(attr.dataType(), is(KEYWORD)); assertThat(attr.isInexact(), is(true)); } diff --git a/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/analysis/analyzer/VerifierErrorMessagesTests.java b/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/analysis/analyzer/VerifierErrorMessagesTests.java index 684901bfece..25d4178640d 100644 --- a/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/analysis/analyzer/VerifierErrorMessagesTests.java +++ b/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/analysis/analyzer/VerifierErrorMessagesTests.java @@ -11,7 +11,7 @@ import org.elasticsearch.xpack.sql.analysis.index.EsIndex; import org.elasticsearch.xpack.sql.analysis.index.IndexResolution; import org.elasticsearch.xpack.sql.expression.function.FunctionRegistry; import org.elasticsearch.xpack.sql.parser.SqlParser; -import org.elasticsearch.xpack.sql.type.DataType; +import org.elasticsearch.xpack.sql.type.EsField; import org.elasticsearch.xpack.sql.type.TypesTests; import org.joda.time.DateTimeZone; @@ -21,7 +21,7 @@ public class VerifierErrorMessagesTests extends ESTestCase { private SqlParser parser = new SqlParser(DateTimeZone.UTC); private String verify(String sql) { - Map mapping = TypesTests.loadMapping("mapping-multi-field-with-nested.json"); + Map mapping = TypesTests.loadMapping("mapping-multi-field-with-nested.json"); EsIndex test = new EsIndex("test", mapping); return verify(IndexResolution.valid(test), sql); } diff --git a/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/execution/search/SourceGeneratorTests.java b/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/execution/search/SourceGeneratorTests.java index 328afbd2712..e406f488265 100644 --- a/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/execution/search/SourceGeneratorTests.java +++ b/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/execution/search/SourceGeneratorTests.java @@ -26,7 +26,7 @@ import org.elasticsearch.xpack.sql.querydsl.container.ScoreSort; import org.elasticsearch.xpack.sql.querydsl.container.Sort.Direction; import org.elasticsearch.xpack.sql.querydsl.query.MatchQuery; import org.elasticsearch.xpack.sql.tree.Location; -import org.elasticsearch.xpack.sql.type.DataTypes; +import org.elasticsearch.xpack.sql.type.KeywordEsField; import static java.util.Collections.emptyList; import static java.util.Collections.singletonList; @@ -94,12 +94,12 @@ public class SourceGeneratorTests extends ESTestCase { public void testSortFieldSpecified() { QueryContainer container = new QueryContainer() - .sort(new AttributeSort(new FieldAttribute(new Location(1, 1), "test", DataTypes.KEYWORD), Direction.ASC)); + .sort(new AttributeSort(new FieldAttribute(new Location(1, 1), "test", new KeywordEsField("test")), Direction.ASC)); SearchSourceBuilder sourceBuilder = SourceGenerator.sourceBuilder(container, null, randomIntBetween(1, 10)); assertEquals(singletonList(fieldSort("test").order(SortOrder.ASC)), sourceBuilder.sorts()); container = new QueryContainer() - .sort(new AttributeSort(new FieldAttribute(new Location(1, 1), "test", DataTypes.KEYWORD), Direction.DESC)); + .sort(new AttributeSort(new FieldAttribute(new Location(1, 1), "test", new KeywordEsField("test")), Direction.DESC)); sourceBuilder = SourceGenerator.sourceBuilder(container, null, randomIntBetween(1, 10)); assertEquals(singletonList(fieldSort("test").order(SortOrder.DESC)), sourceBuilder.sorts()); } diff --git a/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/LiteralTests.java b/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/LiteralTests.java index 3db46e90233..90f5901784e 100644 --- a/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/LiteralTests.java +++ b/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/LiteralTests.java @@ -70,17 +70,17 @@ public class LiteralTests extends AbstractNodeTestCase { * after a generators is its "native" type. */ private static final List GENERATORS = Arrays.asList( - new ValueAndCompatibleTypes(() -> randomBoolean() ? randomBoolean() : randomFrom("true", "false"), DataTypes.BOOLEAN), - new ValueAndCompatibleTypes(ESTestCase::randomByte, DataTypes.BYTE, DataTypes.SHORT, DataTypes.INTEGER, DataTypes.LONG, - DataTypes.FLOAT, DataTypes.DOUBLE, DataTypes.BOOLEAN), - new ValueAndCompatibleTypes(ESTestCase::randomShort, DataTypes.SHORT, DataTypes.INTEGER, DataTypes.LONG, - DataTypes.FLOAT, DataTypes.DOUBLE, DataTypes.BOOLEAN), - new ValueAndCompatibleTypes(ESTestCase::randomInt, DataTypes.INTEGER, DataTypes.LONG, - DataTypes.FLOAT, DataTypes.DOUBLE, DataTypes.BOOLEAN), - new ValueAndCompatibleTypes(ESTestCase::randomLong, DataTypes.LONG, DataTypes.FLOAT, DataTypes.DOUBLE, DataTypes.BOOLEAN), - new ValueAndCompatibleTypes(ESTestCase::randomFloat, DataTypes.FLOAT, DataTypes.LONG, DataTypes.DOUBLE, DataTypes.BOOLEAN), - new ValueAndCompatibleTypes(ESTestCase::randomDouble, DataTypes.DOUBLE, DataTypes.LONG, DataTypes.FLOAT, DataTypes.BOOLEAN), - new ValueAndCompatibleTypes(() -> randomAlphaOfLength(5), DataTypes.KEYWORD)); + new ValueAndCompatibleTypes(() -> randomBoolean() ? randomBoolean() : randomFrom("true", "false"), DataType.BOOLEAN), + new ValueAndCompatibleTypes(ESTestCase::randomByte, DataType.BYTE, DataType.SHORT, DataType.INTEGER, DataType.LONG, + DataType.FLOAT, DataType.DOUBLE, DataType.BOOLEAN), + new ValueAndCompatibleTypes(ESTestCase::randomShort, DataType.SHORT, DataType.INTEGER, DataType.LONG, + DataType.FLOAT, DataType.DOUBLE, DataType.BOOLEAN), + new ValueAndCompatibleTypes(ESTestCase::randomInt, DataType.INTEGER, DataType.LONG, + DataType.FLOAT, DataType.DOUBLE, DataType.BOOLEAN), + new ValueAndCompatibleTypes(ESTestCase::randomLong, DataType.LONG, DataType.FLOAT, DataType.DOUBLE, DataType.BOOLEAN), + new ValueAndCompatibleTypes(ESTestCase::randomFloat, DataType.FLOAT, DataType.LONG, DataType.DOUBLE, DataType.BOOLEAN), + new ValueAndCompatibleTypes(ESTestCase::randomDouble, DataType.DOUBLE, DataType.LONG, DataType.FLOAT, DataType.BOOLEAN), + new ValueAndCompatibleTypes(() -> randomAlphaOfLength(5), DataType.KEYWORD)); public static Literal randomLiteral() { ValueAndCompatibleTypes gen = randomFrom(GENERATORS); @@ -146,8 +146,8 @@ public class LiteralTests extends AbstractNodeTestCase { private List validReplacementDataTypes(Object value, DataType type) { List validDataTypes = new ArrayList<>(); - List options = Arrays.asList(DataTypes.BYTE, DataTypes.SHORT, DataTypes.INTEGER, DataTypes.LONG, - DataTypes.FLOAT, DataTypes.DOUBLE, DataTypes.BOOLEAN); + List options = Arrays.asList(DataType.BYTE, DataType.SHORT, DataType.INTEGER, DataType.LONG, + DataType.FLOAT, DataType.DOUBLE, DataType.BOOLEAN); for (DataType candidate : options) { try { DataTypeConversion.Conversion c = DataTypeConversion.conversionFor(type, candidate); diff --git a/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/DayOfYearTests.java b/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/DayOfYearTests.java index bf246ee7662..14320620c8a 100644 --- a/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/DayOfYearTests.java +++ b/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/DayOfYearTests.java @@ -7,7 +7,7 @@ package org.elasticsearch.xpack.sql.expression.function.scalar.datetime; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.xpack.sql.expression.Literal; -import org.elasticsearch.xpack.sql.type.DateType; +import org.elasticsearch.xpack.sql.type.DataType; import org.joda.time.DateTime; import org.joda.time.DateTimeZone; @@ -29,6 +29,6 @@ public class DayOfYearTests extends ESTestCase { } private DayOfYear build(Object value, DateTimeZone timeZone) { - return new DayOfYear(null, new Literal(null, value, DateType.DEFAULT), timeZone); + return new DayOfYear(null, new Literal(null, value, DataType.DATE), timeZone); } } diff --git a/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/optimizer/OptimizerTests.java b/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/optimizer/OptimizerTests.java index d7d6840d8d6..0eda60fa3b5 100644 --- a/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/optimizer/OptimizerTests.java +++ b/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/optimizer/OptimizerTests.java @@ -95,7 +95,7 @@ public class OptimizerTests extends ESTestCase { @Override public DataType dataType() { - return DataTypes.BOOLEAN; + return DataType.BOOLEAN; } @Override @@ -264,14 +264,14 @@ public class OptimizerTests extends ESTestCase { } public void testConstantFoldingDatetime() { - Expression cast = new Cast(EMPTY, Literal.of(EMPTY, "2018-01-19T10:23:27Z"), DataTypes.DATE); + Expression cast = new Cast(EMPTY, Literal.of(EMPTY, "2018-01-19T10:23:27Z"), DataType.DATE); assertEquals(2018, unwrapAlias(new ConstantFolding().rule(new Year(EMPTY, cast, DateTimeZone.UTC)))); assertEquals(1, unwrapAlias(new ConstantFolding().rule(new MonthOfYear(EMPTY, cast, DateTimeZone.UTC)))); assertEquals(19, unwrapAlias(new ConstantFolding().rule(new DayOfMonth(EMPTY, cast, DateTimeZone.UTC)))); assertEquals(19, unwrapAlias(new ConstantFolding().rule(new DayOfYear(EMPTY, cast, DateTimeZone.UTC)))); assertEquals(3, unwrapAlias(new ConstantFolding().rule(new WeekOfYear(EMPTY, cast, DateTimeZone.UTC)))); assertNull(unwrapAlias(new ConstantFolding().rule( - new WeekOfYear(EMPTY, new Literal(EMPTY, null, DataTypes.NULL), DateTimeZone.UTC)))); + new WeekOfYear(EMPTY, new Literal(EMPTY, null, DataType.NULL), DateTimeZone.UTC)))); } private Object unwrapAlias(Expression e) { diff --git a/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/planner/QueryTranslatorTests.java b/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/planner/QueryTranslatorTests.java index de3e82945c4..953790defb8 100644 --- a/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/planner/QueryTranslatorTests.java +++ b/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/planner/QueryTranslatorTests.java @@ -19,7 +19,7 @@ import org.elasticsearch.xpack.sql.plan.logical.Project; import org.elasticsearch.xpack.sql.planner.QueryTranslator.QueryTranslation; import org.elasticsearch.xpack.sql.querydsl.query.Query; import org.elasticsearch.xpack.sql.querydsl.query.TermQuery; -import org.elasticsearch.xpack.sql.type.DataType; +import org.elasticsearch.xpack.sql.type.EsField; import org.elasticsearch.xpack.sql.type.TypesTests; import org.joda.time.DateTimeZone; @@ -36,7 +36,7 @@ public class QueryTranslatorTests extends ESTestCase { parser = new SqlParser(DateTimeZone.UTC); functionRegistry = new FunctionRegistry(); - Map mapping = TypesTests.loadMapping("mapping-multi-field-variation.json"); + Map mapping = TypesTests.loadMapping("mapping-multi-field-variation.json"); EsIndex test = new EsIndex("test", mapping); getIndexResult = IndexResolution.valid(test); diff --git a/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/planner/VerifierErrorMessagesTests.java b/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/planner/VerifierErrorMessagesTests.java index ecc2d201a43..27c715c258d 100644 --- a/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/planner/VerifierErrorMessagesTests.java +++ b/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/planner/VerifierErrorMessagesTests.java @@ -14,9 +14,12 @@ import org.elasticsearch.xpack.sql.optimizer.Optimizer; import org.elasticsearch.xpack.sql.parser.SqlParser; import org.elasticsearch.xpack.sql.plan.logical.LogicalPlan; import org.elasticsearch.xpack.sql.type.DataType; -import org.elasticsearch.xpack.sql.type.DataTypes; +import org.elasticsearch.xpack.sql.type.EsField; +import org.elasticsearch.xpack.sql.type.KeywordEsField; +import org.elasticsearch.xpack.sql.type.TextEsField; import org.joda.time.DateTimeZone; +import java.util.Collections; import java.util.LinkedHashMap; import java.util.Map; @@ -27,11 +30,11 @@ public class VerifierErrorMessagesTests extends ESTestCase { private Planner planner = new Planner(); private String verify(String sql) { - Map mapping = new LinkedHashMap<>(); - mapping.put("bool", DataTypes.BOOLEAN); - mapping.put("int", DataTypes.INTEGER); - mapping.put("text", DataTypes.TEXT); - mapping.put("keyword", DataTypes.KEYWORD); + Map mapping = new LinkedHashMap<>(); + mapping.put("bool", new EsField("bool", DataType.BOOLEAN, Collections.emptyMap(), true)); + mapping.put("int", new EsField("int", DataType.INTEGER, Collections.emptyMap(), true)); + mapping.put("text", new TextEsField("text", Collections.emptyMap(), true)); + mapping.put("keyword", new KeywordEsField("keyword", Collections.emptyMap(), true, DataType.KEYWORD.defaultPrecision, true)); EsIndex test = new EsIndex("test", mapping); IndexResolution getIndexResult = IndexResolution.valid(test); Analyzer analyzer = new Analyzer(new FunctionRegistry(), getIndexResult, DateTimeZone.UTC); diff --git a/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/type/DataTypeConversionTests.java b/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/type/DataTypeConversionTests.java index 193132c1056..c9f8815f283 100644 --- a/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/type/DataTypeConversionTests.java +++ b/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/type/DataTypeConversionTests.java @@ -13,11 +13,11 @@ import org.joda.time.DateTimeZone; public class DataTypeConversionTests extends ESTestCase { public void testConversionToString() { - Conversion conversion = DataTypeConversion.conversionFor(new DoubleType(true), KeywordType.DEFAULT); + Conversion conversion = DataTypeConversion.conversionFor(DataType.DOUBLE, DataType.KEYWORD); assertNull(conversion.convert(null)); assertEquals("10.0", conversion.convert(10.0)); - conversion = DataTypeConversion.conversionFor(new DateType(true), KeywordType.DEFAULT); + conversion = DataTypeConversion.conversionFor(DataType.DATE, DataType.KEYWORD); assertNull(conversion.convert(null)); assertEquals("1970-01-01T00:00:00.000Z", conversion.convert(new DateTime(0, DateTimeZone.UTC))); } @@ -26,9 +26,9 @@ public class DataTypeConversionTests extends ESTestCase { * Test conversion to a date or long. These are almost the same. */ public void testConversionToLongOrDate() { - DataType to = randomBoolean() ? new LongType(true) : new DateType(true); + DataType to = randomBoolean() ? DataType.LONG : DataType.DATE; { - Conversion conversion = DataTypeConversion.conversionFor(new DoubleType(true), to); + Conversion conversion = DataTypeConversion.conversionFor(DataType.DOUBLE, to); assertNull(conversion.convert(null)); assertEquals(10L, conversion.convert(10.0)); assertEquals(10L, conversion.convert(10.1)); @@ -37,20 +37,20 @@ public class DataTypeConversionTests extends ESTestCase { assertEquals("[" + Double.MAX_VALUE + "] out of [Long] range", e.getMessage()); } { - Conversion conversion = DataTypeConversion.conversionFor(new IntegerType(true), to); + Conversion conversion = DataTypeConversion.conversionFor(DataType.INTEGER, to); assertNull(conversion.convert(null)); assertEquals(10L, conversion.convert(10)); assertEquals(-134L, conversion.convert(-134)); } { - Conversion conversion = DataTypeConversion.conversionFor(new BooleanType(true), to); + Conversion conversion = DataTypeConversion.conversionFor(DataType.BOOLEAN, to); assertNull(conversion.convert(null)); assertEquals(1, conversion.convert(true)); assertEquals(0, conversion.convert(false)); } - Conversion conversion = DataTypeConversion.conversionFor(KeywordType.DEFAULT, to); + Conversion conversion = DataTypeConversion.conversionFor(DataType.KEYWORD, to); assertNull(conversion.convert(null)); - if (to instanceof LongType) { + if (to == DataType.LONG) { assertEquals(1L, conversion.convert("1")); assertEquals(0L, conversion.convert("-0")); Exception e = expectThrows(SqlIllegalArgumentException.class, () -> conversion.convert("0xff")); @@ -67,26 +67,26 @@ public class DataTypeConversionTests extends ESTestCase { public void testConversionToDouble() { { - Conversion conversion = DataTypeConversion.conversionFor(new FloatType(true), new DoubleType(true)); + Conversion conversion = DataTypeConversion.conversionFor(DataType.FLOAT, DataType.DOUBLE); assertNull(conversion.convert(null)); assertEquals(10.0, (double) conversion.convert(10.0f), 0.00001); assertEquals(10.1, (double) conversion.convert(10.1f), 0.00001); assertEquals(10.6, (double) conversion.convert(10.6f), 0.00001); } { - Conversion conversion = DataTypeConversion.conversionFor(new IntegerType(true), new DoubleType(true)); + Conversion conversion = DataTypeConversion.conversionFor(DataType.INTEGER, DataType.DOUBLE); assertNull(conversion.convert(null)); assertEquals(10.0, (double) conversion.convert(10), 0.00001); assertEquals(-134.0, (double) conversion.convert(-134), 0.00001); } { - Conversion conversion = DataTypeConversion.conversionFor(new BooleanType(true), new DoubleType(true)); + Conversion conversion = DataTypeConversion.conversionFor(DataType.BOOLEAN, DataType.DOUBLE); assertNull(conversion.convert(null)); assertEquals(1.0, (double) conversion.convert(true), 0); assertEquals(0.0, (double) conversion.convert(false), 0); } { - Conversion conversion = DataTypeConversion.conversionFor(KeywordType.DEFAULT, new DoubleType(true)); + Conversion conversion = DataTypeConversion.conversionFor(DataType.KEYWORD, DataType.DOUBLE); assertNull(conversion.convert(null)); assertEquals(1.0, (double) conversion.convert("1"), 0); assertEquals(0.0, (double) conversion.convert("-0"), 0); @@ -98,28 +98,28 @@ public class DataTypeConversionTests extends ESTestCase { public void testConversionToBoolean() { { - Conversion conversion = DataTypeConversion.conversionFor(new FloatType(true), new BooleanType(true)); + Conversion conversion = DataTypeConversion.conversionFor(DataType.FLOAT, DataType.BOOLEAN); assertNull(conversion.convert(null)); assertEquals(true, conversion.convert(10.0f)); assertEquals(true, conversion.convert(-10.0f)); assertEquals(false, conversion.convert(0.0f)); } { - Conversion conversion = DataTypeConversion.conversionFor(new IntegerType(true), new BooleanType(true)); + Conversion conversion = DataTypeConversion.conversionFor(DataType.INTEGER, DataType.BOOLEAN); assertNull(conversion.convert(null)); assertEquals(true, conversion.convert(10)); assertEquals(true, conversion.convert(-10)); assertEquals(false, conversion.convert(0)); } { - Conversion conversion = DataTypeConversion.conversionFor(new DoubleType(true), new BooleanType(true)); + Conversion conversion = DataTypeConversion.conversionFor(DataType.DOUBLE, DataType.BOOLEAN); assertNull(conversion.convert(null)); assertEquals(true, conversion.convert(10.0)); assertEquals(true, conversion.convert(-10.0)); assertEquals(false, conversion.convert(0.0)); } { - Conversion conversion = DataTypeConversion.conversionFor(KeywordType.DEFAULT, new BooleanType(true)); + Conversion conversion = DataTypeConversion.conversionFor(DataType.KEYWORD, DataType.BOOLEAN); assertNull(conversion.convert(null)); // We only handled upper and lower case true and false assertEquals(true, conversion.convert("true")); @@ -144,7 +144,7 @@ public class DataTypeConversionTests extends ESTestCase { public void testConversionToInt() { { - Conversion conversion = DataTypeConversion.conversionFor(new DoubleType(true), new IntegerType(true)); + Conversion conversion = DataTypeConversion.conversionFor(DataType.DOUBLE, DataType.INTEGER); assertNull(conversion.convert(null)); assertEquals(10, conversion.convert(10.0)); assertEquals(10, conversion.convert(10.1)); @@ -156,7 +156,7 @@ public class DataTypeConversionTests extends ESTestCase { public void testConversionToShort() { { - Conversion conversion = DataTypeConversion.conversionFor(new DoubleType(true), new ShortType(true)); + Conversion conversion = DataTypeConversion.conversionFor(DataType.DOUBLE, DataType.SHORT); assertNull(conversion.convert(null)); assertEquals((short) 10, conversion.convert(10.0)); assertEquals((short) 10, conversion.convert(10.1)); @@ -168,7 +168,7 @@ public class DataTypeConversionTests extends ESTestCase { public void testConversionToByte() { { - Conversion conversion = DataTypeConversion.conversionFor(new DoubleType(true), new ByteType(true)); + Conversion conversion = DataTypeConversion.conversionFor(DataType.DOUBLE, DataType.BYTE); assertNull(conversion.convert(null)); assertEquals((byte) 10, conversion.convert(10.0)); assertEquals((byte) 10, conversion.convert(10.1)); diff --git a/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/type/TypesTests.java b/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/type/TypesTests.java index f82e860ad93..1c69d198bee 100644 --- a/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/type/TypesTests.java +++ b/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/type/TypesTests.java @@ -14,184 +14,182 @@ import java.util.List; import java.util.Map; import static java.util.Collections.emptyMap; -import static org.elasticsearch.xpack.sql.type.DataTypes.DATE; -import static org.elasticsearch.xpack.sql.type.DataTypes.INTEGER; -import static org.elasticsearch.xpack.sql.type.DataTypes.KEYWORD; -import static org.elasticsearch.xpack.sql.type.DataTypes.TEXT; +import static org.elasticsearch.xpack.sql.type.DataType.DATE; +import static org.elasticsearch.xpack.sql.type.DataType.INTEGER; +import static org.elasticsearch.xpack.sql.type.DataType.KEYWORD; +import static org.elasticsearch.xpack.sql.type.DataType.NESTED; +import static org.elasticsearch.xpack.sql.type.DataType.OBJECT; +import static org.elasticsearch.xpack.sql.type.DataType.TEXT; import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; public class TypesTests extends ESTestCase { - public void testNullMap() throws Exception { - Map fromEs = Types.fromEs(null); + public void testNullMap() { + Map fromEs = Types.fromEs(null); assertThat(fromEs.isEmpty(), is(true)); } - public void testEmptyMap() throws Exception { - Map fromEs = Types.fromEs(emptyMap()); + public void testEmptyMap() { + Map fromEs = Types.fromEs(emptyMap()); assertThat(fromEs.isEmpty(), is(true)); } - public void testBasicMapping() throws Exception { - Map mapping = loadMapping("mapping-basic.json"); + public void testBasicMapping() { + Map mapping = loadMapping("mapping-basic.json"); assertThat(mapping.size(), is(6)); - assertThat(mapping.get("emp_no"), is(INTEGER)); - assertThat(mapping.get("first_name"), instanceOf(TextType.class)); - assertThat(mapping.get("last_name"), is(TEXT)); - assertThat(mapping.get("gender"), is(KEYWORD)); - assertThat(mapping.get("salary"), is(INTEGER)); + assertThat(mapping.get("emp_no").getDataType(), is(INTEGER)); + assertThat(mapping.get("first_name"), instanceOf(TextEsField.class)); + assertThat(mapping.get("last_name").getDataType(), is(TEXT)); + assertThat(mapping.get("gender").getDataType(), is(KEYWORD)); + assertThat(mapping.get("salary").getDataType(), is(INTEGER)); } - public void testDefaultStringMapping() throws Exception { - Map mapping = loadMapping("mapping-default-string.json"); + public void testDefaultStringMapping() { + Map mapping = loadMapping("mapping-default-string.json"); assertThat(mapping.size(), is(1)); - assertThat(mapping.get("dep_no").same(TEXT), is(true)); + assertThat(mapping.get("dep_no").getDataType(), is(TEXT)); } - public void testTextField() throws Exception { - Map mapping = loadMapping("mapping-text.json"); + public void testTextField() { + Map mapping = loadMapping("mapping-text.json"); assertThat(mapping.size(), is(1)); - DataType type = mapping.get("full_name"); - assertThat(type, instanceOf(TextType.class)); + EsField type = mapping.get("full_name"); + assertThat(type, instanceOf(TextEsField.class)); assertThat(type.hasDocValues(), is(false)); - TextType ttype = (TextType) type; - assertThat(type.precision(), is(Integer.MAX_VALUE)); - assertThat(ttype.hasFieldData(), is(false)); + TextEsField ttype = (TextEsField) type; + assertThat(type.getPrecision(), is(Integer.MAX_VALUE)); + assertThat(ttype.hasDocValues(), is(false)); } - public void testKeywordField() throws Exception { - Map mapping = loadMapping("mapping-keyword.json"); + public void testKeywordField() { + Map mapping = loadMapping("mapping-keyword.json"); assertThat(mapping.size(), is(1)); - DataType type = mapping.get("full_name"); - assertThat(type, instanceOf(KeywordType.class)); - assertThat(type.hasDocValues(), is(true)); - assertThat(type.precision(), is(256)); + EsField field = mapping.get("full_name"); + assertThat(field, instanceOf(KeywordEsField.class)); + assertThat(field.hasDocValues(), is(true)); + assertThat(field.getPrecision(), is(256)); } - public void testDateField() throws Exception { - Map mapping = loadMapping("mapping-date.json"); + public void testDateField() { + Map mapping = loadMapping("mapping-date.json"); assertThat(mapping.size(), is(1)); - DataType type = mapping.get("date"); - assertThat(type, is(DATE)); - assertThat(type.hasDocValues(), is(true)); - assertThat(type.precision(), is(19)); + EsField field = mapping.get("date"); + assertThat(field.getDataType(), is(DATE)); + assertThat(field.hasDocValues(), is(true)); + assertThat(field.getPrecision(), is(19)); - DateType dtype = (DateType) type; - List formats = dtype.formats(); + DateEsField dfield = (DateEsField) field; + List formats = dfield.getFormats(); assertThat(formats, hasSize(3)); } - public void testDateNoFormat() throws Exception { - Map mapping = loadMapping("mapping-date-no-format.json"); + public void testDateNoFormat() { + Map mapping = loadMapping("mapping-date-no-format.json"); assertThat(mapping.size(), is(1)); - DataType type = mapping.get("date"); - assertThat(type, is(DATE)); - assertThat(type.hasDocValues(), is(true)); - DateType dtype = (DateType) type; + EsField field = mapping.get("date"); + assertThat(field.getDataType(), is(DATE)); + assertThat(field.hasDocValues(), is(true)); + DateEsField dfield = (DateEsField) field; // default types - assertThat(dtype.formats(), hasSize(2)); + assertThat(dfield.getFormats(), hasSize(2)); } - public void testDateMulti() throws Exception { - Map mapping = loadMapping("mapping-date-multi.json"); + public void testDateMulti() { + Map mapping = loadMapping("mapping-date-multi.json"); assertThat(mapping.size(), is(1)); - DataType type = mapping.get("date"); - assertThat(type, is(DATE)); - assertThat(type.hasDocValues(), is(true)); - DateType dtype = (DateType) type; + EsField field = mapping.get("date"); + assertThat(field.getDataType(), is(DATE)); + assertThat(field.hasDocValues(), is(true)); + DateEsField dfield = (DateEsField) field; // default types - assertThat(dtype.formats(), hasSize(1)); + assertThat(dfield.getFormats(), hasSize(1)); } - public void testDocValueField() throws Exception { - Map mapping = loadMapping("mapping-docvalues.json"); + public void testDocValueField() { + Map mapping = loadMapping("mapping-docvalues.json"); assertThat(mapping.size(), is(1)); - DataType type = mapping.get("session_id"); - assertThat(type, instanceOf(KeywordType.class)); - assertThat(type.precision(), is(15)); - assertThat(type.hasDocValues(), is(false)); + EsField field = mapping.get("session_id"); + assertThat(field, instanceOf(KeywordEsField.class)); + assertThat(field.getPrecision(), is(15)); + assertThat(field.hasDocValues(), is(false)); } - public void testDottedField() throws Exception { - Map mapping = loadMapping("mapping-object.json"); + public void testDottedField() { + Map mapping = loadMapping("mapping-object.json"); assertThat(mapping.size(), is(2)); - DataType type = mapping.get("manager"); - assertThat(type.isPrimitive(), is(false)); - assertThat(type, instanceOf(ObjectType.class)); - ObjectType ot = (ObjectType) type; - Map children = ot.properties(); + EsField field = mapping.get("manager"); + assertThat(field.getDataType().isPrimitive(), is(false)); + assertThat(field.getDataType(), is(OBJECT)); + Map children = field.getProperties(); assertThat(children.size(), is(2)); - DataType names = children.get("name"); - children = ((ObjectType) names).properties(); + EsField names = children.get("name"); + children = names.getProperties(); assertThat(children.size(), is(2)); - assertThat(children.get("first"), is(TEXT)); + assertThat(children.get("first").getDataType(), is(TEXT)); } - public void testMultiField() throws Exception { - Map mapping = loadMapping("mapping-multi-field.json"); + public void testMultiField() { + Map mapping = loadMapping("mapping-multi-field.json"); assertThat(mapping.size(), is(1)); - DataType type = mapping.get("text"); - assertThat(type.isPrimitive(), is(true)); - assertThat(type, instanceOf(TextType.class)); - TextType tt = (TextType) type; - Map fields = tt.fields(); + EsField field = mapping.get("text"); + assertThat(field.getDataType().isPrimitive(), is(true)); + assertThat(field.getDataType(), is(TEXT)); + Map fields = field.getProperties(); assertThat(fields.size(), is(2)); - assertThat(fields.get("raw"), is(KEYWORD)); - assertThat(fields.get("english"), is(TEXT)); + assertThat(fields.get("raw").getDataType(), is(KEYWORD)); + assertThat(fields.get("english").getDataType(), is(TEXT)); } - public void testMultiFieldTooManyOptions() throws Exception { - Map mapping = loadMapping("mapping-multi-field.json"); + public void testMultiFieldTooManyOptions() { + Map mapping = loadMapping("mapping-multi-field.json"); assertThat(mapping.size(), is(1)); - DataType type = mapping.get("text"); - assertThat(type.isPrimitive(), is(true)); - assertThat(type, instanceOf(TextType.class)); - TextType tt = (TextType) type; - Map fields = tt.fields(); + EsField field = mapping.get("text"); + assertThat(field.getDataType().isPrimitive(), is(true)); + assertThat(field, instanceOf(TextEsField.class)); + Map fields = field.getProperties(); assertThat(fields.size(), is(2)); - assertThat(fields.get("raw"), is(KEYWORD)); - assertThat(fields.get("english"), is(TEXT)); + assertThat(fields.get("raw").getDataType(), is(KEYWORD)); + assertThat(fields.get("english").getDataType(), is(TEXT)); } - public void testNestedDoc() throws Exception { - Map mapping = loadMapping("mapping-nested.json"); + public void testNestedDoc() { + Map mapping = loadMapping("mapping-nested.json"); assertThat(mapping.size(), is(1)); - DataType type = mapping.get("dep"); - assertThat(type.isPrimitive(), is(false)); - assertThat(type, instanceOf(NestedType.class)); - NestedType ot = (NestedType) type; - Map children = ot.properties(); + EsField field = mapping.get("dep"); + assertThat(field.getDataType().isPrimitive(), is(false)); + assertThat(field.getDataType(), is(NESTED)); + Map children = field.getProperties(); assertThat(children.size(), is(4)); - assertThat(children.get("dep_name"), is(TEXT)); - assertThat(children.get("start_date"), is(DATE)); + assertThat(children.get("dep_name").getDataType(), is(TEXT)); + assertThat(children.get("start_date").getDataType(), is(DATE)); } - public void testGeoField() throws Exception { - Map mapping = loadMapping("mapping-geo.json"); - DataType dt = mapping.get("location"); - assertThat(dt.esName(), is("geo_point")); + public void testGeoField() { + Map mapping = loadMapping("mapping-geo.json"); + EsField dt = mapping.get("location"); + assertThat(dt.getDataType().esType, is("geo_point")); } - public void testUnsupportedTypes() throws Exception { - Map mapping = loadMapping("mapping-unsupported.json"); - DataType dt = mapping.get("range"); - assertThat(dt.esName(), is("integer_range")); + public void testUnsupportedTypes() { + Map mapping = loadMapping("mapping-unsupported.json"); + EsField dt = mapping.get("range"); + assertThat(dt.getDataType().esType, is("unsupported")); } - public static Map loadMapping(String name) { + public static Map loadMapping(String name) { InputStream stream = TypesTests.class.getResourceAsStream("/" + name); assertNotNull("Could not find mapping resource:" + name, stream); return Types.fromEs(XContentHelper.convertToMap(JsonXContent.jsonXContent, stream, randomBoolean()));