From aebda81b30e1563b877a8896309fd50633e0b663 Mon Sep 17 00:00:00 2001 From: Costin Leau Date: Mon, 27 Jan 2020 17:32:51 +0200 Subject: [PATCH] QL: Refactor DataType for pluggability (#51328) Change DataType from enum to class Break DataType enums into QL (default) and SQL types Make data type conversion pluggable so that new types can be introduced As part of the process: - static type conversion in QL package (such as Literal) has been removed - several utility classes have been broken into base (QL) and extended (SQL) parts based on type awareness - operators (+,-,/,*) are - due to extensibility, serialization of arithmetic operation has been slightly changed and pushed down to the operator executor itself --- .../extractor/AbstractFieldHitExtractor.java | 40 +- .../xpack/ql/expression/Expression.java | 7 +- .../xpack/ql/expression/Expressions.java | 5 +- .../xpack/ql/expression/FieldAttribute.java | 5 +- .../xpack/ql/expression/Literal.java | 16 +- .../xpack/ql/expression/TypeResolutions.java | 30 +- .../function/DefaultFunctionTypeRegistry.java | 2 - .../function/UnresolvedFunction.java | 3 +- .../expression/function/aggregate/Count.java | 3 +- .../function/scalar/IntervalScripting.java | 18 + .../function/scalar/ScalarFunction.java | 113 ++- .../whitelist/InternalQlScriptUtils.java | 17 +- .../gen/processor/ConstantNamedWriteable.java | 16 + .../gen/processor/ConstantProcessor.java | 14 +- .../processor/FunctionalBinaryProcessor.java | 10 +- .../FunctionalEnumBinaryProcessor.java | 33 + .../expression/gen/script/ScriptTemplate.java | 3 +- .../expression/gen/script/ScriptWeaver.java | 149 ---- .../ql/expression/gen/script/Scripts.java | 7 +- .../xpack/ql/expression/predicate/Range.java | 5 +- .../predicate/fulltext/FullTextPredicate.java | 3 +- .../predicate/logical/BinaryLogic.java | 3 +- .../logical/BinaryLogicProcessor.java | 4 +- .../ql/expression/predicate/logical/Not.java | 5 +- .../predicate/operator/arithmetic/Add.java | 3 +- .../arithmetic/ArithmeticOperation.java | 5 +- .../operator/arithmetic/Arithmetics.java | 82 +- .../arithmetic/BinaryArithmeticOperation.java | 16 + .../arithmetic/BinaryArithmeticPipe.java | 4 +- .../arithmetic/BinaryArithmeticProcessor.java | 159 +--- .../DateTimeArithmeticOperation.java | 28 +- .../DefaultBinaryArithmeticOperation.java | 66 ++ .../predicate/operator/arithmetic/Div.java | 7 +- .../predicate/operator/arithmetic/Mod.java | 3 +- .../predicate/operator/arithmetic/Mul.java | 24 +- .../predicate/operator/arithmetic/Sub.java | 18 +- .../operator/comparison/BinaryComparison.java | 3 +- .../comparison/BinaryComparisonProcessor.java | 4 +- .../predicate/regex/RegexMatch.java | 3 +- .../ql/expression/processor/Processors.java | 21 +- .../xpack/ql/index/IndexResolver.java | 77 +- .../xpack/ql/type/Converter.java | 14 + .../elasticsearch/xpack/ql/type/DataType.java | 330 ++------ .../xpack/ql/type/DataTypeConversion.java | 705 ----------------- .../xpack/ql/type/DataTypeConverter.java | 519 +++++++++++++ .../xpack/ql/type/DataTypeRegistry.java | 35 + .../xpack/ql/type/DataTypes.java | 244 +++--- .../xpack/ql/type/DateEsField.java | 2 +- .../xpack/ql/type/DateUtils.java | 51 +- .../ql/type/DefaultDataTypeRegistry.java | 51 ++ .../elasticsearch/xpack/ql/type/EsField.java | 13 +- .../xpack/ql/type/InvalidMappedField.java | 2 +- .../xpack/ql/type/KeywordEsField.java | 22 +- .../xpack/ql/type/TextEsField.java | 7 +- .../elasticsearch/xpack/ql/type/Types.java | 71 +- .../xpack/ql/type/UnsupportedEsField.java | 2 +- .../xpack/ql/util/CollectionUtils.java | 7 + .../org/elasticsearch/xpack/ql/TestUtils.java | 13 + .../xpack/ql/expression/LiteralTests.java | 42 +- .../ql/expression/TyperResolutionTests.java | 26 +- .../function/NamedExpressionTests.java | 7 +- .../function/scalar/FunctionTestUtils.java | 17 +- .../gen/pipeline/BinaryPipesTests.java | 3 +- .../gen/processor/ConstantProcessorTests.java | 9 +- .../BinaryArithmeticProcessorTests.java | 5 +- .../BinaryComparisonProcessorTests.java | 3 +- .../xpack/ql/tree/NodeSubclassTests.java | 11 +- .../xpack/ql/tree/TestCompoundAggregate.java | 3 +- .../xpack/ql/tree/TestEnclosedAgg.java | 3 +- .../ql/type/DataTypeConversionTests.java | 444 ++--------- .../xpack/ql/type/TypesTests.java | 55 +- .../xpack/sql/analysis/analyzer/Analyzer.java | 8 +- .../xpack/sql/analysis/analyzer/Verifier.java | 13 +- .../search/extractor/FieldHitExtractor.java | 32 +- .../search/extractor/TopHitsAggExtractor.java | 9 +- .../xpack/sql/expression/Exists.java | 4 +- .../xpack/sql}/expression/Foldables.java | 18 +- .../sql/expression/SqlTypeResolutions.java | 41 + .../xpack/sql/expression/function/Score.java | 3 +- .../function/SqlFunctionRegistry.java | 14 +- .../function/SqlFunctionTypeRegistry.java | 2 + .../expression/function/aggregate/Avg.java | 3 +- .../expression/function/aggregate/Max.java | 5 +- .../aggregate/MedianAbsoluteDeviation.java | 3 +- .../expression/function/aggregate/Min.java | 5 +- .../function/aggregate/NumericAggregate.java | 3 +- .../function/aggregate/Percentile.java | 5 +- .../function/aggregate/PercentileRank.java | 5 +- .../function/grouping/Histogram.java | 7 +- .../sql/expression/function/scalar/Cast.java | 8 +- .../function/scalar/CastProcessor.java | 14 +- .../expression/function/scalar/Database.java | 4 +- .../function/scalar/Processors.java | 23 + .../sql/expression/function/scalar/User.java | 4 +- .../scalar/datetime/BaseDateTimeFunction.java | 2 +- .../datetime/BinaryDateTimeFunction.java | 2 +- .../function/scalar/datetime/CurrentDate.java | 4 +- .../scalar/datetime/CurrentDateTime.java | 4 +- .../function/scalar/datetime/CurrentTime.java | 4 +- .../function/scalar/datetime/DateAdd.java | 5 +- .../function/scalar/datetime/DateDiff.java | 5 +- .../function/scalar/datetime/DatePart.java | 3 +- .../scalar/datetime/DateTimeFunction.java | 3 +- .../function/scalar/datetime/DateTrunc.java | 3 +- .../datetime/NamedDateTimeFunction.java | 3 +- .../datetime/NonIsoDateTimeFunction.java | 3 +- .../function/scalar/datetime/Quarter.java | 3 +- .../scalar/datetime/TimeFunction.java | 2 +- .../function/scalar/geo/GeoProcessor.java | 2 +- .../function/scalar/geo/StAswkt.java | 3 +- .../function/scalar/geo/StDistance.java | 5 +- .../scalar/geo/StDistanceProcessor.java | 2 +- .../function/scalar/geo/StGeometryType.java | 3 +- .../function/scalar/geo/StWkttosql.java | 6 +- .../scalar/geo/StWkttosqlProcessor.java | 2 +- .../expression/function/scalar/geo/StX.java | 3 +- .../expression/function/scalar/geo/StY.java | 3 +- .../expression/function/scalar/geo/StZ.java | 3 +- .../function/scalar/geo/UnaryGeoFunction.java | 2 +- .../scalar/math/BinaryMathProcessor.java | 4 +- .../scalar/math/BinaryNumericFunction.java | 3 +- .../math/BinaryOptionalNumericFunction.java | 3 +- .../expression/function/scalar/math/Ceil.java | 6 +- .../expression/function/scalar/math/E.java | 6 +- .../function/scalar/math/Floor.java | 6 +- .../function/scalar/math/MathFunction.java | 3 +- .../function/scalar/math/MathProcessor.java | 14 +- .../expression/function/scalar/math/Pi.java | 6 +- .../expression/function/scalar/math/Sign.java | 3 +- .../function/scalar/string/Ascii.java | 3 +- .../string/BinaryStringNumericFunction.java | 3 +- .../string/BinaryStringNumericProcessor.java | 4 +- .../string/BinaryStringStringFunction.java | 3 +- .../string/BinaryStringStringProcessor.java | 4 +- .../function/scalar/string/BitLength.java | 3 +- .../function/scalar/string/Char.java | 3 +- .../function/scalar/string/CharLength.java | 3 +- .../function/scalar/string/Concat.java | 3 +- .../function/scalar/string/Insert.java | 3 +- .../function/scalar/string/LCase.java | 3 +- .../function/scalar/string/LTrim.java | 3 +- .../function/scalar/string/Length.java | 3 +- .../function/scalar/string/Locate.java | 3 +- .../function/scalar/string/OctetLength.java | 3 +- .../function/scalar/string/RTrim.java | 3 +- .../function/scalar/string/Replace.java | 3 +- .../function/scalar/string/Space.java | 3 +- .../function/scalar/string/Substring.java | 3 +- .../function/scalar/string/UCase.java | 3 +- .../whitelist/InternalSqlScriptUtils.java | 53 +- .../sql}/expression/literal/Literals.java | 11 +- .../sql/expression/literal/SqlLiterals.java | 31 - .../sql/expression/literal}/geo/GeoShape.java | 6 +- .../literal/interval}/Interval.java | 17 +- .../literal/interval/IntervalArithmetics.java | 72 ++ .../literal/interval}/IntervalDayTime.java | 19 +- .../literal/interval}/IntervalYearMonth.java | 23 +- .../literal/interval}/Intervals.java | 126 ++- .../ArbitraryConditionalFunction.java | 4 +- .../predicate/conditional/Case.java | 19 +- .../predicate/conditional/CasePipe.java | 2 +- .../predicate/conditional/CaseProcessor.java | 2 +- .../predicate/conditional/Coalesce.java | 4 +- .../conditional/ConditionalFunction.java | 17 +- .../conditional/ConditionalPipe.java | 4 +- .../conditional/ConditionalProcessor.java | 2 +- .../predicate/conditional/Conditionals.java | 2 +- .../predicate/conditional/Greatest.java | 8 +- .../predicate/conditional/IfConditional.java | 2 +- .../predicate/conditional/IfNull.java | 2 +- .../expression/predicate/conditional/Iif.java | 6 +- .../predicate/conditional/Least.java | 8 +- .../predicate/conditional/NullIf.java | 2 +- .../predicate/conditional/NullIfPipe.java | 2 +- .../conditional/NullIfProcessor.java | 2 +- .../predicate/nulls/CheckNullProcessor.java | 2 +- .../expression/predicate/nulls/IsNotNull.java | 9 +- .../expression/predicate/nulls/IsNull.java | 9 +- .../predicate/operator/arithmetic/Add.java | 29 + .../DateTimeArithmeticOperation.java | 67 ++ .../predicate/operator/arithmetic/Div.java | 37 + .../predicate/operator/arithmetic/Mod.java | 33 + .../predicate/operator/arithmetic/Mul.java | 70 ++ .../arithmetic/SqlArithmeticOperation.java | 31 + .../SqlBinaryArithmeticOperation.java | 154 ++++ .../predicate/operator/arithmetic/Sub.java | 46 ++ .../predicate/operator/comparison/In.java | 11 +- .../predicate/operator/comparison/InPipe.java | 2 +- .../operator/comparison/InProcessor.java | 3 +- .../xpack/sql/optimizer/Optimizer.java | 60 +- .../xpack/sql/parser/ExpressionBuilder.java | 59 +- .../xpack/sql/parser/LogicalPlanBuilder.java | 4 +- .../xpack/sql/plan/logical/Join.java | 4 +- .../sql/plan/logical/command/ShowColumns.java | 3 +- .../plan/logical/command/sys/SysColumns.java | 30 +- .../plan/logical/command/sys/SysTypes.java | 39 +- .../xpack/sql/planner/QueryFolder.java | 23 +- .../xpack/sql/planner/QueryTranslator.java | 12 +- .../xpack/sql/plugin/SqlPlugin.java | 3 +- .../sql/plugin/TransportSqlQueryAction.java | 3 +- .../xpack/sql/querydsl/agg/GroupByKey.java | 20 +- .../xpack/sql/querydsl/agg/TopHitsAgg.java | 3 +- .../querydsl/container/QueryContainer.java | 13 +- .../querydsl/container/SearchHitFieldRef.java | 6 +- .../xpack/sql/querydsl/query/TermsQuery.java | 5 +- .../xpack/sql/session/Cursors.java | 4 +- .../xpack/sql}/type/ExtTypes.java | 2 +- .../xpack/sql/type/SqlDataTypeConverter.java | 453 +++++++++++ .../xpack/sql/type/SqlDataTypeRegistry.java | 56 ++ .../xpack/sql/type/SqlDataTypes.java | 726 ++++++++++++++++++ .../xpack/sql/util/DateUtils.java | 2 +- .../xpack/sql/plugin/sql_whitelist.txt | 6 +- .../sql/{TestUtils.java => SqlTestUtils.java} | 18 +- .../analyzer/FieldAttributeTests.java | 19 +- .../analyzer/VerifierErrorMessagesTests.java | 33 +- .../analysis/index/IndexResolverTests.java | 122 +-- .../extractor/ComputingExtractorTests.java | 9 +- .../extractor/FieldHitExtractorTests.java | 30 +- .../extractor/MetricAggExtractorTests.java | 3 +- .../extractor/TopHitsAggExtractorTests.java | 11 +- .../xpack/sql/expression/ProcessorTests.java | 1 + .../sql/expression/TypeResolutionTests.java | 45 ++ .../function/scalar/CastProcessorTests.java | 11 +- .../scalar/DatabaseFunctionTests.java | 4 +- .../function/scalar/UserFunctionTests.java | 4 +- .../scalar/datetime/CurrentDateTests.java | 6 +- .../scalar/datetime/CurrentDateTimeTests.java | 36 +- .../scalar/datetime/CurrentTimeTests.java | 36 +- .../scalar/datetime/DayOfYearTests.java | 4 +- .../scalar/geo/GeoProcessorTests.java | 2 +- .../scalar/geo/StDistanceProcessorTests.java | 2 +- .../scalar/geo/StWkttosqlProcessorTests.java | 2 +- .../scalar/math/BinaryMathProcessorTests.java | 3 +- .../literal/interval}/IntervalsTests.java | 36 +- .../sql/expression/parser/ParameterTests.java | 27 +- .../predicate/conditional/CaseTests.java | 29 +- .../predicate/conditional/IifTests.java | 10 +- .../nulls/CheckNullProcessorTests.java | 3 +- .../arithmetic/SqlBinaryArithmeticTests.java} | 27 +- .../operator/comparison/InProcessorTests.java | 7 +- .../operator/comparison/InTests.java | 6 +- .../sql/optimizer/OptimizerRunTests.java | 8 +- .../xpack/sql/optimizer/OptimizerTests.java | 130 ++-- .../sql/parser/EscapedFunctionsTests.java | 23 +- .../xpack/sql/parser/ExpressionTests.java | 115 +-- .../sql/parser/LikeEscapingParsingTests.java | 4 +- .../logical/command/ShowFunctionsTests.java | 4 +- .../logical/command/sys/SysColumnsTests.java | 16 +- .../logical/command/sys/SysTablesTests.java | 10 +- .../logical/command/sys/SysTypesTests.java | 29 +- .../planner/PostOptimizerVerifierTests.java | 8 +- .../xpack/sql/planner/QueryFolderTests.java | 8 +- .../sql/planner/QueryTranslatorTests.java | 105 +-- .../xpack/sql/plugin/CursorTests.java | 6 +- .../container/QueryContainerTests.java | 4 +- .../sql/querydsl/query/MatchQueryTests.java | 6 +- .../xpack/sql/stats/VerifierMetricsTests.java | 10 +- .../xpack/sql/tree/SqlNodeSubclassTests.java | 16 +- .../sql/type/SqlDataTypeConverterTests.java | 695 +++++++++++++++++ .../xpack/sql/type/SqlDataTypesTests.java} | 96 ++- .../xpack/sql/types/SqlTypesTests.java | 84 ++ 261 files changed, 5318 insertions(+), 3269 deletions(-) create mode 100644 x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/function/scalar/IntervalScripting.java create mode 100644 x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/gen/processor/ConstantNamedWriteable.java create mode 100644 x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/gen/processor/FunctionalEnumBinaryProcessor.java delete mode 100644 x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/gen/script/ScriptWeaver.java create mode 100644 x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/arithmetic/BinaryArithmeticOperation.java create mode 100644 x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/arithmetic/DefaultBinaryArithmeticOperation.java create mode 100644 x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/Converter.java delete mode 100644 x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/DataTypeConversion.java create mode 100644 x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/DataTypeConverter.java create mode 100644 x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/DataTypeRegistry.java create mode 100644 x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/DefaultDataTypeRegistry.java rename x-pack/plugin/{ql/src/main/java/org/elasticsearch/xpack/ql => sql/src/main/java/org/elasticsearch/xpack/sql}/expression/Foldables.java (73%) create mode 100644 x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/SqlTypeResolutions.java rename x-pack/plugin/{ql/src/main/java/org/elasticsearch/xpack/ql => sql/src/main/java/org/elasticsearch/xpack/sql}/expression/literal/Literals.java (56%) delete mode 100644 x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/literal/SqlLiterals.java rename x-pack/plugin/{ql/src/main/java/org/elasticsearch/xpack/ql/expression/function/scalar => sql/src/main/java/org/elasticsearch/xpack/sql/expression/literal}/geo/GeoShape.java (97%) rename x-pack/plugin/{ql/src/main/java/org/elasticsearch/xpack/ql/expression/literal => sql/src/main/java/org/elasticsearch/xpack/sql/expression/literal/interval}/Interval.java (83%) create mode 100644 x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/literal/interval/IntervalArithmetics.java rename x-pack/plugin/{ql/src/main/java/org/elasticsearch/xpack/ql/expression/literal => sql/src/main/java/org/elasticsearch/xpack/sql/expression/literal/interval}/IntervalDayTime.java (75%) rename x-pack/plugin/{ql/src/main/java/org/elasticsearch/xpack/ql/expression/literal => sql/src/main/java/org/elasticsearch/xpack/sql/expression/literal/interval}/IntervalYearMonth.java (72%) rename x-pack/plugin/{ql/src/main/java/org/elasticsearch/xpack/ql/expression/literal => sql/src/main/java/org/elasticsearch/xpack/sql/expression/literal/interval}/Intervals.java (72%) rename x-pack/plugin/{ql/src/main/java/org/elasticsearch/xpack/ql => sql/src/main/java/org/elasticsearch/xpack/sql}/expression/predicate/conditional/ArbitraryConditionalFunction.java (91%) rename x-pack/plugin/{ql/src/main/java/org/elasticsearch/xpack/ql => sql/src/main/java/org/elasticsearch/xpack/sql}/expression/predicate/conditional/Case.java (88%) rename x-pack/plugin/{ql/src/main/java/org/elasticsearch/xpack/ql => sql/src/main/java/org/elasticsearch/xpack/sql}/expression/predicate/conditional/CasePipe.java (94%) rename x-pack/plugin/{ql/src/main/java/org/elasticsearch/xpack/ql => sql/src/main/java/org/elasticsearch/xpack/sql}/expression/predicate/conditional/CaseProcessor.java (97%) rename x-pack/plugin/{ql/src/main/java/org/elasticsearch/xpack/ql => sql/src/main/java/org/elasticsearch/xpack/sql}/expression/predicate/conditional/Coalesce.java (88%) rename x-pack/plugin/{ql/src/main/java/org/elasticsearch/xpack/ql => sql/src/main/java/org/elasticsearch/xpack/sql}/expression/predicate/conditional/ConditionalFunction.java (83%) rename x-pack/plugin/{ql/src/main/java/org/elasticsearch/xpack/ql => sql/src/main/java/org/elasticsearch/xpack/sql}/expression/predicate/conditional/ConditionalPipe.java (90%) rename x-pack/plugin/{ql/src/main/java/org/elasticsearch/xpack/ql => sql/src/main/java/org/elasticsearch/xpack/sql}/expression/predicate/conditional/ConditionalProcessor.java (97%) rename x-pack/plugin/{ql/src/main/java/org/elasticsearch/xpack/ql => sql/src/main/java/org/elasticsearch/xpack/sql}/expression/predicate/conditional/Conditionals.java (97%) rename x-pack/plugin/{ql/src/main/java/org/elasticsearch/xpack/ql => sql/src/main/java/org/elasticsearch/xpack/sql}/expression/predicate/conditional/Greatest.java (75%) rename x-pack/plugin/{ql/src/main/java/org/elasticsearch/xpack/ql => sql/src/main/java/org/elasticsearch/xpack/sql}/expression/predicate/conditional/IfConditional.java (97%) rename x-pack/plugin/{ql/src/main/java/org/elasticsearch/xpack/ql => sql/src/main/java/org/elasticsearch/xpack/sql}/expression/predicate/conditional/IfNull.java (93%) rename x-pack/plugin/{ql/src/main/java/org/elasticsearch/xpack/ql => sql/src/main/java/org/elasticsearch/xpack/sql}/expression/predicate/conditional/Iif.java (91%) rename x-pack/plugin/{ql/src/main/java/org/elasticsearch/xpack/ql => sql/src/main/java/org/elasticsearch/xpack/sql}/expression/predicate/conditional/Least.java (75%) rename x-pack/plugin/{ql/src/main/java/org/elasticsearch/xpack/ql => sql/src/main/java/org/elasticsearch/xpack/sql}/expression/predicate/conditional/NullIf.java (96%) rename x-pack/plugin/{ql/src/main/java/org/elasticsearch/xpack/ql => sql/src/main/java/org/elasticsearch/xpack/sql}/expression/predicate/conditional/NullIfPipe.java (94%) rename x-pack/plugin/{ql/src/main/java/org/elasticsearch/xpack/ql => sql/src/main/java/org/elasticsearch/xpack/sql}/expression/predicate/conditional/NullIfProcessor.java (97%) rename x-pack/plugin/{ql/src/main/java/org/elasticsearch/xpack/ql => sql/src/main/java/org/elasticsearch/xpack/sql}/expression/predicate/nulls/CheckNullProcessor.java (97%) rename x-pack/plugin/{ql/src/main/java/org/elasticsearch/xpack/ql => sql/src/main/java/org/elasticsearch/xpack/sql}/expression/predicate/nulls/IsNotNull.java (84%) rename x-pack/plugin/{ql/src/main/java/org/elasticsearch/xpack/ql => sql/src/main/java/org/elasticsearch/xpack/sql}/expression/predicate/nulls/IsNull.java (84%) create mode 100644 x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/arithmetic/Add.java create mode 100644 x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/arithmetic/DateTimeArithmeticOperation.java create mode 100644 x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/arithmetic/Div.java create mode 100644 x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/arithmetic/Mod.java create mode 100644 x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/arithmetic/Mul.java create mode 100644 x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/arithmetic/SqlArithmeticOperation.java create mode 100644 x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/arithmetic/SqlBinaryArithmeticOperation.java create mode 100644 x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/arithmetic/Sub.java rename x-pack/plugin/{ql/src/main/java/org/elasticsearch/xpack/ql => sql/src/main/java/org/elasticsearch/xpack/sql}/expression/predicate/operator/comparison/In.java (93%) rename x-pack/plugin/{ql/src/main/java/org/elasticsearch/xpack/ql => sql/src/main/java/org/elasticsearch/xpack/sql}/expression/predicate/operator/comparison/InPipe.java (95%) rename x-pack/plugin/{ql/src/main/java/org/elasticsearch/xpack/ql => sql/src/main/java/org/elasticsearch/xpack/sql}/expression/predicate/operator/comparison/InProcessor.java (93%) rename x-pack/plugin/{ql/src/main/java/org/elasticsearch/xpack/ql => sql/src/main/java/org/elasticsearch/xpack/sql}/type/ExtTypes.java (96%) create mode 100644 x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/SqlDataTypeConverter.java create mode 100644 x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/SqlDataTypeRegistry.java create mode 100644 x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/SqlDataTypes.java rename x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/{TestUtils.java => SqlTestUtils.java} (82%) create mode 100644 x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/TypeResolutionTests.java rename x-pack/plugin/{ql/src/test/java/org/elasticsearch/xpack/ql/expression/literal => sql/src/test/java/org/elasticsearch/xpack/sql/expression/literal/interval}/IntervalsTests.java (88%) rename x-pack/plugin/{ql/src/test/java/org/elasticsearch/xpack/ql => sql/src/test/java/org/elasticsearch/xpack/sql}/expression/predicate/conditional/CaseTests.java (81%) rename x-pack/plugin/{ql/src/test/java/org/elasticsearch/xpack/ql => sql/src/test/java/org/elasticsearch/xpack/sql}/expression/predicate/conditional/IifTests.java (92%) rename x-pack/plugin/{ql/src/test/java/org/elasticsearch/xpack/ql => sql/src/test/java/org/elasticsearch/xpack/sql}/expression/predicate/nulls/CheckNullProcessorTests.java (94%) rename x-pack/plugin/{ql/src/test/java/org/elasticsearch/xpack/ql/expression/predicate/operator/arithmetic/BinaryArithmeticTests.java => sql/src/test/java/org/elasticsearch/xpack/sql/expression/predicate/operator/arithmetic/SqlBinaryArithmeticTests.java} (91%) rename x-pack/plugin/{ql/src/test/java/org/elasticsearch/xpack/ql => sql/src/test/java/org/elasticsearch/xpack/sql}/expression/predicate/operator/comparison/InProcessorTests.java (87%) rename x-pack/plugin/{ql/src/test/java/org/elasticsearch/xpack/ql => sql/src/test/java/org/elasticsearch/xpack/sql}/expression/predicate/operator/comparison/InTests.java (86%) create mode 100644 x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/type/SqlDataTypeConverterTests.java rename x-pack/plugin/{ql/src/test/java/org/elasticsearch/xpack/ql/type/DataTypesTests.java => sql/src/test/java/org/elasticsearch/xpack/sql/type/SqlDataTypesTests.java} (59%) create mode 100644 x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/types/SqlTypesTests.java diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/execution/search/extractor/AbstractFieldHitExtractor.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/execution/search/extractor/AbstractFieldHitExtractor.java index 9be92337c2545..cbb50605f72e2 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/execution/search/extractor/AbstractFieldHitExtractor.java +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/execution/search/extractor/AbstractFieldHitExtractor.java @@ -12,19 +12,25 @@ import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.index.mapper.IgnoredFieldMapper; +import org.elasticsearch.index.mapper.NumberFieldMapper.NumberType; import org.elasticsearch.search.SearchHit; import org.elasticsearch.xpack.ql.QlIllegalArgumentException; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import java.io.IOException; import java.time.ZoneId; import java.util.ArrayDeque; import java.util.Deque; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Objects; import java.util.StringJoiner; +import static org.elasticsearch.xpack.ql.type.DataTypes.DATETIME; +import static org.elasticsearch.xpack.ql.type.DataTypes.KEYWORD; +import static org.elasticsearch.xpack.ql.type.DataTypes.SCALED_FLOAT; /** * Extractor for ES fields. Works for both 'normal' fields but also nested ones (which require hitName to be set). * The latter is used as metadata in assembling the results in the tabular response. @@ -83,8 +89,8 @@ protected AbstractFieldHitExtractor(StreamInput in) throws IOException { } else { fullFieldName = null; } - String esType = in.readOptionalString(); - dataType = esType != null ? DataType.fromTypeName(esType) : null; + String typeName = in.readOptionalString(); + dataType = typeName != null ? loadTypeFromName(typeName) : null; useDocValue = in.readBoolean(); hitName = in.readOptionalString(); arrayLeniency = in.readBoolean(); @@ -92,6 +98,10 @@ protected AbstractFieldHitExtractor(StreamInput in) throws IOException { zoneId = readZoneId(in); } + protected DataType loadTypeFromName(String typeName) { + return DataTypes.fromTypeName(typeName); + } + protected abstract ZoneId readZoneId(StreamInput in) throws IOException; @Override @@ -118,7 +128,7 @@ public Object extract(SearchHit hit) { // if the field was ignored because it was malformed and ignore_malformed was turned on if (fullFieldName != null && hit.getFields().containsKey(IgnoredFieldMapper.NAME) - && dataType.isFromDocValuesOnly() == false + && isFromDocValuesOnly(dataType) == false && dataType.isNumeric()) { /* * ignore_malformed makes sense for extraction from _source for numeric fields only. @@ -171,11 +181,11 @@ protected Object unwrapMultiValue(Object values) { if (dataType == null) { return values; } - if (dataType.isNumeric() && dataType.isFromDocValuesOnly() == false) { - if (dataType == DataType.DOUBLE || dataType == DataType.FLOAT || dataType == DataType.HALF_FLOAT) { + if (dataType.isNumeric() && isFromDocValuesOnly(dataType) == false) { + if (dataType == DataTypes.DOUBLE || dataType == DataTypes.FLOAT || dataType == DataTypes.HALF_FLOAT) { Number result = null; try { - result = dataType.numberType().parse(values, true); + result = numberType(dataType).parse(values, true); } catch(IllegalArgumentException iae) { return null; } @@ -185,13 +195,13 @@ protected Object unwrapMultiValue(Object values) { } else { Number result = null; try { - result = dataType.numberType().parse(values, true); + result = numberType(dataType).parse(values, true); } catch(IllegalArgumentException iae) { return null; } return result; } - } else if (dataType.isString()) { + } else if (DataTypes.isString(dataType)) { return values.toString(); } else { return values; @@ -200,12 +210,22 @@ protected Object unwrapMultiValue(Object values) { throw new QlIllegalArgumentException("Type {} (returned by [{}]) is not supported", values.getClass().getSimpleName(), fieldName); } + protected boolean isFromDocValuesOnly(DataType dataType) { + return dataType == KEYWORD // because of ignore_above. + || dataType == DATETIME + || dataType == SCALED_FLOAT; // because of scaling_factor + } + + private static NumberType numberType(DataType dataType) { + return NumberType.valueOf(dataType.esType().toUpperCase(Locale.ROOT)); + } + protected abstract Object unwrapCustomValue(Object values); protected abstract boolean isPrimitive(List list); @SuppressWarnings({ "unchecked", "rawtypes" }) - protected Object extractFromSource(Map map) { + public Object extractFromSource(Map map) { Object value = null; // Used to avoid recursive method calls @@ -286,7 +306,7 @@ public ZoneId zoneId() { return zoneId; } - protected DataType dataType() { + public DataType dataType() { return dataType; } diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/Expression.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/Expression.java index 7e12acec9fbab..c26661258410c 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/Expression.java +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/Expression.java @@ -46,12 +46,17 @@ public boolean unresolved() { } public boolean resolved() { - return !failed; + return failed == false; } public String message() { return message; } + + @Override + public String toString() { + return resolved() ? "" : message; + } } private TypeResolution lazyTypeResolution = null; diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/Expressions.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/Expressions.java index 7bdf244e4cf6e..dfb235ba7746e 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/Expressions.java +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/Expressions.java @@ -10,7 +10,6 @@ import org.elasticsearch.xpack.ql.expression.gen.pipeline.AttributeInput; import org.elasticsearch.xpack.ql.expression.gen.pipeline.ConstantInput; import org.elasticsearch.xpack.ql.expression.gen.pipeline.Pipe; -import org.elasticsearch.xpack.ql.type.DataType; import org.elasticsearch.xpack.ql.type.DataTypes; import java.util.ArrayList; @@ -112,7 +111,7 @@ public static String name(Expression e) { } public static boolean isNull(Expression e) { - return e.dataType() == DataType.NULL || (e.foldable() && e.fold() == null); + return e.dataType() == DataTypes.NULL || (e.foldable() && e.fold() == null); } public static List names(Collection e) { @@ -165,7 +164,7 @@ public static List onlyPrimitiveFieldAttributes(Collection Set seenMultiFields = new LinkedHashSet<>(); for (Attribute a : attributes) { - if (!DataTypes.isUnsupported(a.dataType()) && a.dataType().isPrimitive()) { + if (DataTypes.isUnsupported(a.dataType()) == false && DataTypes.isPrimitive(a.dataType())) { if (a instanceof FieldAttribute) { FieldAttribute fa = (FieldAttribute) a; // skip nested fields and seen multi-fields diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/FieldAttribute.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/FieldAttribute.java index 5ab482fbfd4c3..6511e244f8881 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/FieldAttribute.java +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/FieldAttribute.java @@ -9,6 +9,7 @@ import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import org.elasticsearch.xpack.ql.type.EsField; import org.elasticsearch.xpack.ql.util.StringUtils; @@ -53,7 +54,7 @@ public FieldAttribute(Source source, FieldAttribute parent, String name, DataTyp FieldAttribute nestedPar = null; if (parent != null) { nestedPar = parent.nestedParent; - if (parent.dataType() == DataType.NESTED) { + if (parent.dataType() == DataTypes.NESTED) { nestedPar = parent; } } @@ -103,7 +104,7 @@ private FieldAttribute innerField(EsField type) { } @Override - protected Attribute clone(Source source, String name, DataType type, String qualifier, Nullability nullability, NameId id, + protected Attribute clone(Source source, String name, DataType type, String qualifier, Nullability nullability, NameId id, boolean synthetic) { FieldAttribute qualifiedParent = parent != null ? (FieldAttribute) parent.withQualifier(qualifier) : null; return new FieldAttribute(source, qualifiedParent, name, field, qualifier, nullability, id, synthetic); diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/Literal.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/Literal.java index 0064edc26740e..82788601e2e61 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/Literal.java +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/Literal.java @@ -18,9 +18,9 @@ */ public class Literal extends LeafExpression { - public static final Literal TRUE = new Literal(Source.EMPTY, Boolean.TRUE, DataType.BOOLEAN); - public static final Literal FALSE = new Literal(Source.EMPTY, Boolean.FALSE, DataType.BOOLEAN); - public static final Literal NULL = new Literal(Source.EMPTY, null, DataType.NULL); + public static final Literal TRUE = new Literal(Source.EMPTY, Boolean.TRUE, DataTypes.BOOLEAN); + public static final Literal FALSE = new Literal(Source.EMPTY, Boolean.FALSE, DataTypes.BOOLEAN); + public static final Literal NULL = new Literal(Source.EMPTY, null, DataTypes.NULL); private final Object value; private final DataType dataType; @@ -93,16 +93,6 @@ public String nodeString() { return toString() + "[" + dataType + "]"; } - /** - * Utility method for creating 'in-line' Literals (out of values instead of expressions). - */ - public static Literal of(Source source, Object value) { - if (value instanceof Literal) { - return (Literal) value; - } - return new Literal(source, value, DataTypes.fromJava(value)); - } - /** * Utility method for creating a literal out of a foldable expression. * Throws an exception if the expression is not foldable. diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/TypeResolutions.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/TypeResolutions.java index f59415e990341..01307d7ef84fc 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/TypeResolutions.java +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/TypeResolutions.java @@ -8,6 +8,7 @@ import org.elasticsearch.xpack.ql.expression.Expression.TypeResolution; import org.elasticsearch.xpack.ql.expression.Expressions.ParamOrdinal; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import org.elasticsearch.xpack.ql.type.EsField; import java.util.Locale; @@ -16,7 +17,8 @@ import static org.elasticsearch.common.logging.LoggerMessageFormat.format; import static org.elasticsearch.xpack.ql.expression.Expressions.name; -import static org.elasticsearch.xpack.ql.type.DataType.BOOLEAN; +import static org.elasticsearch.xpack.ql.type.DataTypes.BOOLEAN; +import static org.elasticsearch.xpack.ql.type.DataTypes.NULL; public final class TypeResolutions { @@ -35,29 +37,7 @@ public static TypeResolution isNumeric(Expression e, String operationName, Param } public static TypeResolution isString(Expression e, String operationName, ParamOrdinal paramOrd) { - return isType(e, DataType::isString, operationName, paramOrd, "string"); - } - - public static TypeResolution isDate(Expression e, String operationName, ParamOrdinal paramOrd) { - return isType(e, DataType::isDateBased, operationName, paramOrd, "date", "datetime"); - } - - public static TypeResolution isDateOrTime(Expression e, String operationName, ParamOrdinal paramOrd) { - return isType(e, DataType::isDateOrTimeBased, operationName, paramOrd, "date", "time", "datetime"); - } - - public static TypeResolution isNumericOrDate(Expression e, String operationName, ParamOrdinal paramOrd) { - return isType(e, dt -> dt.isNumeric() || dt.isDateBased(), operationName, paramOrd, - "date", "datetime", "numeric"); - } - - public static TypeResolution isNumericOrDateOrTime(Expression e, String operationName, ParamOrdinal paramOrd) { - return isType(e, dt -> dt.isNumeric() || dt.isDateOrTimeBased(), operationName, paramOrd, - "date", "time", "datetime", "numeric"); - } - - public static TypeResolution isGeo(Expression e, String operationName, ParamOrdinal paramOrd) { - return isType(e, DataType::isGeo, operationName, paramOrd, "geo_point", "geo_shape"); + return isType(e, DataTypes::isString, operationName, paramOrd, "string"); } public static TypeResolution isExact(Expression e, String message) { @@ -118,7 +98,7 @@ public static TypeResolution isType(Expression e, String operationName, ParamOrdinal paramOrd, String... acceptedTypes) { - return predicate.test(e.dataType()) || e.dataType().isNull() ? + return predicate.test(e.dataType()) || e.dataType() == NULL ? TypeResolution.TYPE_RESOLVED : new TypeResolution(format(null, "{}argument of [{}] must be [{}], found value [{}] type [{}]", paramOrd == null || paramOrd == ParamOrdinal.DEFAULT ? "" : paramOrd.name().toLowerCase(Locale.ROOT) + " ", diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/function/DefaultFunctionTypeRegistry.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/function/DefaultFunctionTypeRegistry.java index c9feab80c3d18..7f1e4789f096c 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/function/DefaultFunctionTypeRegistry.java +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/function/DefaultFunctionTypeRegistry.java @@ -7,7 +7,6 @@ import org.elasticsearch.xpack.ql.expression.function.aggregate.AggregateFunction; import org.elasticsearch.xpack.ql.expression.function.scalar.ScalarFunction; -import org.elasticsearch.xpack.ql.expression.predicate.conditional.ConditionalFunction; public class DefaultFunctionTypeRegistry implements FunctionTypeRegistry { @@ -16,7 +15,6 @@ public class DefaultFunctionTypeRegistry implements FunctionTypeRegistry { private enum Types { AGGREGATE(AggregateFunction.class), - CONDITIONAL(ConditionalFunction.class), SCALAR(ScalarFunction.class); private Class baseClass; diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/function/UnresolvedFunction.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/function/UnresolvedFunction.java index f2a3deb60da02..de3beb39e6d55 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/function/UnresolvedFunction.java +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/function/UnresolvedFunction.java @@ -16,6 +16,7 @@ import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import org.elasticsearch.xpack.ql.util.StringUtils; import java.util.LinkedHashSet; @@ -195,7 +196,7 @@ public UnresolvedFunction preprocessStar(UnresolvedFunction uf) { // dedicated count optimization if (uf.name.toUpperCase(Locale.ROOT).equals("COUNT")) { return new UnresolvedFunction(uf.source(), uf.name(), uf.resolutionType, - singletonList(new Literal(uf.arguments().get(0).source(), Integer.valueOf(1), DataType.INTEGER))); + singletonList(new Literal(uf.arguments().get(0).source(), Integer.valueOf(1), DataTypes.INTEGER))); } return uf; } diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/function/aggregate/Count.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/function/aggregate/Count.java index 60ffd1aed9975..aa03d9e32e2a9 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/function/aggregate/Count.java +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/function/aggregate/Count.java @@ -9,6 +9,7 @@ import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import java.util.List; import java.util.Objects; @@ -46,7 +47,7 @@ public boolean distinct() { @Override public DataType dataType() { - return DataType.LONG; + return DataTypes.LONG; } @Override diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/function/scalar/IntervalScripting.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/function/scalar/IntervalScripting.java new file mode 100644 index 0000000000000..9216235471576 --- /dev/null +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/function/scalar/IntervalScripting.java @@ -0,0 +1,18 @@ +/* + * 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.ql.expression.function.scalar; + +// FIXME: accessor interface until making script generation pluggable +public interface IntervalScripting { + + String script(); + + String value(); + + String typeName(); + +} diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/function/scalar/ScalarFunction.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/function/scalar/ScalarFunction.java index 49e620fa5aa03..bcb3cbcabcaf9 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/function/scalar/ScalarFunction.java +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/function/scalar/ScalarFunction.java @@ -5,14 +5,23 @@ */ package org.elasticsearch.xpack.ql.expression.function.scalar; +import org.elasticsearch.xpack.ql.QlIllegalArgumentException; import org.elasticsearch.xpack.ql.expression.Expression; +import org.elasticsearch.xpack.ql.expression.FieldAttribute; import org.elasticsearch.xpack.ql.expression.function.Function; -import org.elasticsearch.xpack.ql.expression.gen.script.ScriptWeaver; +import org.elasticsearch.xpack.ql.expression.function.aggregate.AggregateFunction; +import org.elasticsearch.xpack.ql.expression.function.grouping.GroupingFunction; +import org.elasticsearch.xpack.ql.expression.gen.script.ScriptTemplate; +import org.elasticsearch.xpack.ql.expression.gen.script.Scripts; import org.elasticsearch.xpack.ql.tree.Source; +import org.elasticsearch.xpack.ql.util.DateUtils; +import java.time.OffsetTime; +import java.time.ZonedDateTime; import java.util.List; import static java.util.Collections.emptyList; +import static org.elasticsearch.xpack.ql.expression.gen.script.ParamsBuilder.paramsBuilder; /** * A {@code ScalarFunction} is a {@code Function} that takes values from some @@ -20,7 +29,7 @@ * {@code ABS()}, which takes one value at a time, applies a function to the * value (abs) and returns a new value. */ -public abstract class ScalarFunction extends Function implements ScriptWeaver { +public abstract class ScalarFunction extends Function { protected ScalarFunction(Source source) { super(source, emptyList()); @@ -35,4 +44,104 @@ protected ScalarFunction(Source source, List fields) { public Expression orderBy() { return null; } + + + // + // Script generation + // + + public ScriptTemplate asScript(Expression exp) { + if (exp.foldable()) { + return scriptWithFoldable(exp); + } + + if (exp instanceof FieldAttribute) { + return scriptWithField((FieldAttribute) exp); + } + + if (exp instanceof ScalarFunction) { + return scriptWithScalar((ScalarFunction) exp); + } + + if (exp instanceof AggregateFunction) { + return scriptWithAggregate((AggregateFunction) exp); + } + + if (exp instanceof GroupingFunction) { + return scriptWithGrouping((GroupingFunction) exp); + } + throw new QlIllegalArgumentException("Cannot evaluate script for expression {}", exp); + } + + + protected ScriptTemplate scriptWithFoldable(Expression foldable) { + Object fold = foldable.fold(); + + // FIXME: this needs to be refactored + // + // Custom type handling + // + + // wrap intervals with dedicated methods for serialization + if (fold instanceof ZonedDateTime) { + ZonedDateTime zdt = (ZonedDateTime) fold; + return new ScriptTemplate(processScript("{sql}.asDateTime({})"), paramsBuilder().variable(DateUtils.toString(zdt)).build(), + dataType()); + } + + if (fold instanceof IntervalScripting) { + IntervalScripting is = (IntervalScripting) fold; + return new ScriptTemplate(processScript(is.script()), paramsBuilder().variable(is.value()).variable(is.typeName()).build(), + dataType()); + } + + if (fold instanceof OffsetTime) { + OffsetTime ot = (OffsetTime) fold; + return new ScriptTemplate(processScript("{sql}.asTime({})"), paramsBuilder().variable(ot.toString()).build(), dataType()); + } + + if (fold != null && fold.getClass().getSimpleName().equals("GeoShape")) { + return new ScriptTemplate(processScript("{sql}.stWktToSql({})"), paramsBuilder().variable(fold.toString()).build(), dataType()); + } + + + return new ScriptTemplate(processScript("{}"), + paramsBuilder().variable(fold).build(), + dataType()); + } + + protected ScriptTemplate scriptWithScalar(ScalarFunction scalar) { + ScriptTemplate nested = scalar.asScript(); + return new ScriptTemplate(processScript(nested.template()), + paramsBuilder().script(nested.params()).build(), + dataType()); + } + + protected ScriptTemplate scriptWithAggregate(AggregateFunction aggregate) { + String template = "{}"; + return new ScriptTemplate(processScript(template), + paramsBuilder().agg(aggregate).build(), + dataType()); + } + + protected ScriptTemplate scriptWithGrouping(GroupingFunction grouping) { + String template = "{}"; + return new ScriptTemplate(processScript(template), + paramsBuilder().grouping(grouping).build(), + dataType()); + } + + protected ScriptTemplate scriptWithField(FieldAttribute field) { + return new ScriptTemplate(processScript("doc[{}].value"), + paramsBuilder().variable(field.name()).build(), + dataType()); + } + + protected String processScript(String script) { + return formatTemplate(script); + } + + protected String formatTemplate(String template) { + return Scripts.formatTemplate(template); + } } \ No newline at end of file diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/function/scalar/whitelist/InternalQlScriptUtils.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/function/scalar/whitelist/InternalQlScriptUtils.java index f5b0992d9ebf5..26c4bea1cf592 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/function/scalar/whitelist/InternalQlScriptUtils.java +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/function/scalar/whitelist/InternalQlScriptUtils.java @@ -9,12 +9,9 @@ import org.elasticsearch.index.fielddata.ScriptDocValues; import org.elasticsearch.xpack.ql.expression.predicate.logical.BinaryLogicProcessor.BinaryLogicOperation; import org.elasticsearch.xpack.ql.expression.predicate.logical.NotProcessor; -import org.elasticsearch.xpack.ql.expression.predicate.nulls.CheckNullProcessor.CheckNullOperation; import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.BinaryComparisonProcessor.BinaryComparisonOperation; -import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.InProcessor; import org.elasticsearch.xpack.ql.util.StringUtils; -import java.util.List; import java.util.Map; public abstract class InternalQlScriptUtils { @@ -93,16 +90,4 @@ public static Boolean or(Boolean left, Boolean right) { public static Boolean not(Boolean expression) { return NotProcessor.apply(expression); } - - public static Boolean isNull(Object expression) { - return CheckNullOperation.IS_NULL.apply(expression); - } - - public static Boolean isNotNull(Object expression) { - return CheckNullOperation.IS_NOT_NULL.apply(expression); - } - - public static Boolean in(Object value, List values) { - return InProcessor.apply(value, values); - } -} +} \ No newline at end of file diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/gen/processor/ConstantNamedWriteable.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/gen/processor/ConstantNamedWriteable.java new file mode 100644 index 0000000000000..e59078ac65eb6 --- /dev/null +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/gen/processor/ConstantNamedWriteable.java @@ -0,0 +1,16 @@ +/* + * 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.ql.expression.gen.processor; + +import org.elasticsearch.common.io.stream.NamedWriteable; + +/** + * Marker interface used by QL for pluggable constant serialization. + */ +public interface ConstantNamedWriteable extends NamedWriteable { + +} diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/gen/processor/ConstantProcessor.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/gen/processor/ConstantProcessor.java index 7230d21919297..cb7d60c831994 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/gen/processor/ConstantProcessor.java +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/gen/processor/ConstantProcessor.java @@ -18,26 +18,17 @@ public class ConstantProcessor implements Processor { private final Object constant; private final boolean namedWriteable; - private final Class clazz; public ConstantProcessor(Object value) { this.constant = value; this.namedWriteable = value instanceof NamedWriteable; - this.clazz = namedWriteable ? value.getClass() : null; } - @SuppressWarnings("unchecked") public ConstantProcessor(StreamInput in) throws IOException { namedWriteable = in.readBoolean(); if (namedWriteable) { - try { - clazz = ConstantProcessor.class.getClassLoader().loadClass(in.readString()); - } catch (ClassNotFoundException e) { - throw new IOException(e); - } - constant = in.readNamedWriteable((Class) clazz); + constant = in.readNamedWriteable(ConstantNamedWriteable.class); } else { - clazz = null; constant = in.readGenericValue(); } } @@ -46,7 +37,6 @@ public ConstantProcessor(StreamInput in) throws IOException { public void writeTo(StreamOutput out) throws IOException { out.writeBoolean(namedWriteable); if (namedWriteable) { - out.writeString(constant.getClass().getName()); out.writeNamedWriteable((NamedWriteable) constant); } else { out.writeGenericValue(constant); @@ -86,4 +76,4 @@ public boolean equals(Object obj) { public String toString() { return "^" + constant; } -} +} \ No newline at end of file diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/gen/processor/FunctionalBinaryProcessor.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/gen/processor/FunctionalBinaryProcessor.java index e0c28f4f44f4a..b42753f7c1fbc 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/gen/processor/FunctionalBinaryProcessor.java +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/gen/processor/FunctionalBinaryProcessor.java @@ -7,16 +7,15 @@ package org.elasticsearch.xpack.ql.expression.gen.processor; import org.elasticsearch.common.io.stream.StreamInput; -import org.elasticsearch.common.io.stream.StreamOutput; import java.io.IOException; import java.util.Objects; import java.util.function.BiFunction; /** - * Base class for definition binary processors based on functions (for applying) defined as enums (for serialization purposes). + * Base class for definition binary processors based on functions (for applying). */ -public abstract class FunctionalBinaryProcessor & BiFunction> extends BinaryProcessor { +public abstract class FunctionalBinaryProcessor> extends BinaryProcessor { private final F function; @@ -34,11 +33,6 @@ public F function() { return function; } - @Override - protected void doWrite(StreamOutput out) throws IOException { - out.writeEnum(function()); - } - @SuppressWarnings("unchecked") @Override protected Object doProcess(Object left, Object right) { diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/gen/processor/FunctionalEnumBinaryProcessor.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/gen/processor/FunctionalEnumBinaryProcessor.java new file mode 100644 index 0000000000000..50828ff1ec01a --- /dev/null +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/gen/processor/FunctionalEnumBinaryProcessor.java @@ -0,0 +1,33 @@ +/* + * 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.ql.expression.gen.processor; + +import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.common.io.stream.StreamOutput; + +import java.io.IOException; +import java.util.function.BiFunction; + +/** + * Base class for definition binary processors based on functions (for applying) defined as enums (for serialization purposes). + */ +public abstract class FunctionalEnumBinaryProcessor & BiFunction> + extends FunctionalBinaryProcessor { + + protected FunctionalEnumBinaryProcessor(Processor left, Processor right, F function) { + super(left, right, function); + } + + protected FunctionalEnumBinaryProcessor(StreamInput in, Reader reader) throws IOException { + super(in, reader); + } + + @Override + protected void doWrite(StreamOutput out) throws IOException { + out.writeEnum(function()); + } +} diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/gen/script/ScriptTemplate.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/gen/script/ScriptTemplate.java index 6e6d2104ef324..e2a3a2bbbeafd 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/gen/script/ScriptTemplate.java +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/gen/script/ScriptTemplate.java @@ -8,6 +8,7 @@ import org.elasticsearch.script.Script; import org.elasticsearch.script.ScriptType; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import org.elasticsearch.xpack.ql.util.StringUtils; import java.util.List; @@ -27,7 +28,7 @@ public class ScriptTemplate { private final DataType outputType; public ScriptTemplate(String template) { - this(template, Params.EMPTY, DataType.KEYWORD); + this(template, Params.EMPTY, DataTypes.KEYWORD); } public ScriptTemplate(String template, Params params, DataType outputType) { diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/gen/script/ScriptWeaver.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/gen/script/ScriptWeaver.java deleted file mode 100644 index 3a2007328307c..0000000000000 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/gen/script/ScriptWeaver.java +++ /dev/null @@ -1,149 +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.ql.expression.gen.script; - -import org.elasticsearch.xpack.ql.QlIllegalArgumentException; -import org.elasticsearch.xpack.ql.expression.Expression; -import org.elasticsearch.xpack.ql.expression.FieldAttribute; -import org.elasticsearch.xpack.ql.expression.Literal; -import org.elasticsearch.xpack.ql.expression.function.aggregate.AggregateFunction; -import org.elasticsearch.xpack.ql.expression.function.grouping.GroupingFunction; -import org.elasticsearch.xpack.ql.expression.function.scalar.ScalarFunction; -import org.elasticsearch.xpack.ql.expression.function.scalar.geo.GeoShape; -import org.elasticsearch.xpack.ql.expression.literal.IntervalDayTime; -import org.elasticsearch.xpack.ql.expression.literal.IntervalYearMonth; -import org.elasticsearch.xpack.ql.type.DataType; -import org.elasticsearch.xpack.ql.util.DateUtils; - -import java.time.OffsetTime; -import java.time.ZonedDateTime; - -import static org.elasticsearch.xpack.ql.expression.gen.script.ParamsBuilder.paramsBuilder; - -/** - * Mixin-like interface for customizing the default script generation. - */ -public interface ScriptWeaver { - - default ScriptTemplate asScript(Expression exp) { - if (exp.foldable()) { - return scriptWithFoldable(exp); - } - - if (exp instanceof ScalarFunction) { - return scriptWithScalar((ScalarFunction) exp); - } - - if (exp instanceof AggregateFunction) { - return scriptWithAggregate((AggregateFunction) exp); - } - - if (exp instanceof GroupingFunction) { - return scriptWithGrouping((GroupingFunction) exp); - } - - if (exp instanceof FieldAttribute) { - return scriptWithField((FieldAttribute) exp); - } - throw new QlIllegalArgumentException("Cannot evaluate script for expression {}", exp); - } - - /* - * To be used when the function has an optional parameter. - */ - default ScriptTemplate asOptionalScript(Expression exp) { - return exp == null ? asScript(Literal.NULL) : asScript(exp); - } - - DataType dataType(); - - default ScriptTemplate scriptWithFoldable(Expression foldable) { - Object fold = foldable.fold(); - - // - // Custom type handling - // - - // wrap intervals with dedicated methods for serialization - if (fold instanceof ZonedDateTime) { - ZonedDateTime zdt = (ZonedDateTime) fold; - return new ScriptTemplate(processScript("{sql}.asDateTime({})"), - paramsBuilder().variable(DateUtils.toString(zdt)).build(), dataType()); - } - - if (fold instanceof IntervalYearMonth) { - IntervalYearMonth iym = (IntervalYearMonth) fold; - return new ScriptTemplate(processScript("{sql}.intervalYearMonth({},{})"), - paramsBuilder().variable(iym.interval().toString()).variable(iym.dataType().name()).build(), - dataType()); - } - if (fold instanceof IntervalDayTime) { - IntervalDayTime idt = (IntervalDayTime) fold; - return new ScriptTemplate(processScript("{sql}.intervalDayTime({},{})"), - paramsBuilder().variable(idt.interval().toString()).variable(idt.dataType().name()).build(), - dataType()); - } - if (fold instanceof OffsetTime) { - OffsetTime ot = (OffsetTime) fold; - return new ScriptTemplate(processScript("{sql}.asTime({})"), - paramsBuilder().variable(ot.toString()).build(), - dataType()); - } - - if (fold instanceof GeoShape) { - GeoShape geoShape = (GeoShape) fold; - return new ScriptTemplate(processScript("{sql}.stWktToSql({})"), - paramsBuilder().variable(geoShape.toString()).build(), - dataType()); - } - - return new ScriptTemplate(processScript("{}"), - paramsBuilder().variable(fold).build(), - dataType()); - } - - default ScriptTemplate scriptWithScalar(ScalarFunction scalar) { - ScriptTemplate nested = scalar.asScript(); - return new ScriptTemplate(processScript(nested.template()), - paramsBuilder().script(nested.params()).build(), - dataType()); - } - - default ScriptTemplate scriptWithAggregate(AggregateFunction aggregate) { - String template = "{}"; - if (aggregate.dataType().isDateBased()) { - template = "{sql}.asDateTime({})"; - } - return new ScriptTemplate(processScript(template), - paramsBuilder().agg(aggregate).build(), - dataType()); - } - - default ScriptTemplate scriptWithGrouping(GroupingFunction grouping) { - String template = "{}"; - if (grouping.dataType().isDateBased()) { - template = "{sql}.asDateTime({})"; - } - return new ScriptTemplate(processScript(template), - paramsBuilder().grouping(grouping).build(), - dataType()); - } - - default ScriptTemplate scriptWithField(FieldAttribute field) { - return new ScriptTemplate(processScript("doc[{}].value"), - paramsBuilder().variable(field.name()).build(), - dataType()); - } - - default String processScript(String script) { - return formatTemplate(script); - } - - default String formatTemplate(String template) { - return Scripts.formatTemplate(template); - } -} diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/gen/script/Scripts.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/gen/script/Scripts.java index 6a57e33d87837..a743500337f45 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/gen/script/Scripts.java +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/gen/script/Scripts.java @@ -7,6 +7,7 @@ package org.elasticsearch.xpack.ql.expression.gen.script; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import java.util.AbstractMap.SimpleEntry; import java.util.LinkedHashMap; @@ -57,7 +58,7 @@ public static ScriptTemplate nullSafeFilter(ScriptTemplate script) { return new ScriptTemplate(formatTemplate( format(Locale.ROOT, "{sql}.nullSafeFilter(%s)", script.template())), script.params(), - DataType.BOOLEAN); + DataTypes.BOOLEAN); } public static ScriptTemplate nullSafeSort(ScriptTemplate script) { @@ -69,11 +70,11 @@ public static ScriptTemplate nullSafeSort(ScriptTemplate script) { } public static ScriptTemplate and(ScriptTemplate left, ScriptTemplate right) { - return binaryMethod("and", left, right, DataType.BOOLEAN); + return binaryMethod("and", left, right, DataTypes.BOOLEAN); } public static ScriptTemplate or(ScriptTemplate left, ScriptTemplate right) { - return binaryMethod("or", left, right, DataType.BOOLEAN); + return binaryMethod("or", left, right, DataTypes.BOOLEAN); } public static ScriptTemplate binaryMethod(String methodName, ScriptTemplate leftScript, ScriptTemplate rightScript, diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/Range.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/Range.java index c5bdb7c8a5754..35ccd1d06b334 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/Range.java +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/Range.java @@ -20,6 +20,7 @@ import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import java.util.List; import java.util.Locale; @@ -118,7 +119,7 @@ public Nullability nullable() { @Override public DataType dataType() { - return DataType.BOOLEAN; + return DataTypes.BOOLEAN; } @Override @@ -144,7 +145,7 @@ public ScriptTemplate asScript() { .script(upperScript.params()) .build(); - return new ScriptTemplate(template, params, DataType.BOOLEAN); + return new ScriptTemplate(template, params, DataTypes.BOOLEAN); } @Override diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/fulltext/FullTextPredicate.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/fulltext/FullTextPredicate.java index 8bd00c1bf3ac8..088c67443d92a 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/fulltext/FullTextPredicate.java +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/fulltext/FullTextPredicate.java @@ -9,6 +9,7 @@ import org.elasticsearch.xpack.ql.expression.Nullability; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import java.util.List; import java.util.Map; @@ -63,7 +64,7 @@ public Nullability nullable() { @Override public DataType dataType() { - return DataType.BOOLEAN; + return DataTypes.BOOLEAN; } @Override diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/logical/BinaryLogic.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/logical/BinaryLogic.java index 1e370d9d7b292..e40994a4cb84e 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/logical/BinaryLogic.java +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/logical/BinaryLogic.java @@ -13,6 +13,7 @@ import org.elasticsearch.xpack.ql.expression.predicate.logical.BinaryLogicProcessor.BinaryLogicOperation; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import static org.elasticsearch.xpack.ql.expression.TypeResolutions.isBoolean; @@ -24,7 +25,7 @@ protected BinaryLogic(Source source, Expression left, Expression right, BinaryLo @Override public DataType dataType() { - return DataType.BOOLEAN; + return DataTypes.BOOLEAN; } @Override diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/logical/BinaryLogicProcessor.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/logical/BinaryLogicProcessor.java index 1301b43a3ae8d..3b46a0a00075b 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/logical/BinaryLogicProcessor.java +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/logical/BinaryLogicProcessor.java @@ -7,7 +7,7 @@ import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.xpack.ql.QlIllegalArgumentException; -import org.elasticsearch.xpack.ql.expression.gen.processor.FunctionalBinaryProcessor; +import org.elasticsearch.xpack.ql.expression.gen.processor.FunctionalEnumBinaryProcessor; import org.elasticsearch.xpack.ql.expression.gen.processor.Processor; import org.elasticsearch.xpack.ql.expression.predicate.PredicateBiFunction; import org.elasticsearch.xpack.ql.expression.predicate.logical.BinaryLogicProcessor.BinaryLogicOperation; @@ -15,7 +15,7 @@ import java.io.IOException; import java.util.function.BiFunction; -public class BinaryLogicProcessor extends FunctionalBinaryProcessor { +public class BinaryLogicProcessor extends FunctionalEnumBinaryProcessor { public enum BinaryLogicOperation implements PredicateBiFunction { diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/logical/Not.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/logical/Not.java index e32b2594010ac..9beec2870a2b8 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/logical/Not.java +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/logical/Not.java @@ -14,6 +14,7 @@ import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import static org.elasticsearch.xpack.ql.expression.TypeResolutions.isBoolean; @@ -35,7 +36,7 @@ protected Not replaceChild(Expression newChild) { @Override protected TypeResolution resolveType() { - if (DataType.BOOLEAN == field().dataType()) { + if (DataTypes.BOOLEAN == field().dataType()) { return TypeResolution.TYPE_RESOLVED; } return isBoolean(field(), sourceText(), ParamOrdinal.DEFAULT); @@ -67,6 +68,6 @@ protected Expression canonicalize() { @Override public DataType dataType() { - return DataType.BOOLEAN; + return DataTypes.BOOLEAN; } } diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/arithmetic/Add.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/arithmetic/Add.java index 2ce2730afd5de..df18990f5401e 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/arithmetic/Add.java +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/arithmetic/Add.java @@ -6,7 +6,6 @@ package org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic; import org.elasticsearch.xpack.ql.expression.Expression; -import org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.BinaryArithmeticProcessor.BinaryArithmeticOperation; import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; @@ -15,7 +14,7 @@ */ public class Add extends DateTimeArithmeticOperation { public Add(Source source, Expression left, Expression right) { - super(source, left, right, BinaryArithmeticOperation.ADD); + super(source, left, right, DefaultBinaryArithmeticOperation.ADD); } @Override diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/arithmetic/ArithmeticOperation.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/arithmetic/ArithmeticOperation.java index 584718b5f8085..c2105333daf3a 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/arithmetic/ArithmeticOperation.java +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/arithmetic/ArithmeticOperation.java @@ -9,10 +9,9 @@ import org.elasticsearch.xpack.ql.expression.Expressions; import org.elasticsearch.xpack.ql.expression.gen.pipeline.Pipe; import org.elasticsearch.xpack.ql.expression.predicate.BinaryOperator; -import org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.BinaryArithmeticProcessor.BinaryArithmeticOperation; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; -import org.elasticsearch.xpack.ql.type.DataTypeConversion; +import org.elasticsearch.xpack.ql.type.DataTypeConverter; import static org.elasticsearch.xpack.ql.expression.TypeResolutions.isNumeric; @@ -37,7 +36,7 @@ public ArithmeticOperation swapLeftAndRight() { @Override public DataType dataType() { if (dataType == null) { - dataType = DataTypeConversion.commonType(left().dataType(), right().dataType()); + dataType = DataTypeConverter.commonType(left().dataType(), right().dataType()); } return dataType; } diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/arithmetic/Arithmetics.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/arithmetic/Arithmetics.java index 03e514d636f34..b029ce96cf218 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/arithmetic/Arithmetics.java +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/arithmetic/Arithmetics.java @@ -5,10 +5,9 @@ */ package org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic; -import java.time.Duration; -import java.time.OffsetTime; -import java.time.Period; -import java.time.temporal.Temporal; +import org.elasticsearch.xpack.ql.QlIllegalArgumentException; + +import java.util.function.BiFunction; /** * Arithmetic operation using the type widening rules of the JLS 5.6.2 namely @@ -16,16 +15,23 @@ */ public final class Arithmetics { - public static final long DAY_IN_MILLIS = 60 * 60 * 24 * 1000L; - private Arithmetics() {} - private enum IntervalOperation { - ADD, - SUB + public interface NumericArithmetic extends BiFunction { + default Object wrap(Object l, Object r) { + if (!(l instanceof Number)) { + throw new QlIllegalArgumentException("A number is required; received {}", l); + } + + if (!(r instanceof Number)) { + throw new QlIllegalArgumentException("A number is required; received {}", r); + } + + return apply((Number) l, (Number) r); + } } - static Number add(Number l, Number r) { + public static Number add(Number l, Number r) { if (l == null || r == null) { return null; } @@ -43,15 +49,7 @@ static Number add(Number l, Number r) { return Integer.valueOf(Math.addExact(l.intValue(), r.intValue())); } - static Temporal add(Temporal l, Period r) { - return periodArithmetics(l, r, IntervalOperation.ADD); - } - - static Temporal add(Temporal l, Duration r) { - return durationArithmetics(l, r, IntervalOperation.ADD); - } - - static Number sub(Number l, Number r) { + public static Number sub(Number l, Number r) { if (l == null || r == null) { return null; } @@ -69,15 +67,7 @@ static Number sub(Number l, Number r) { return Integer.valueOf(Math.subtractExact(l.intValue(), r.intValue())); } - static Temporal sub(Temporal l, Period r) { - return periodArithmetics(l, r, IntervalOperation.SUB); - } - - static Temporal sub(Temporal l, Duration r) { - return durationArithmetics(l, r, IntervalOperation.SUB); - } - - static Number mul(Number l, Number r) { + public static Number mul(Number l, Number r) { if (l == null || r == null) { return null; } @@ -95,7 +85,7 @@ static Number mul(Number l, Number r) { return Integer.valueOf(Math.multiplyExact(l.intValue(), r.intValue())); } - static Number div(Number l, Number r) { + public static Number div(Number l, Number r) { if (l == null || r == null) { return null; } @@ -156,36 +146,4 @@ static Number negate(Number n) { return Integer.valueOf(Math.negateExact(n.intValue())); } - - private static Temporal periodArithmetics(Temporal l, Period r, IntervalOperation operation) { - if (l == null || r == null) { - return null; - } - - if (l instanceof OffsetTime) { - return l; - } - - if (operation == IntervalOperation.ADD) { - return l.plus(r); - } else { - return l.minus(r); - } - } - - private static Temporal durationArithmetics(Temporal l, Duration r, IntervalOperation operation) { - if (l == null || r == null) { - return null; - } - - if (l instanceof OffsetTime) { - r = Duration.ofMillis(r.toMillis() % DAY_IN_MILLIS); - } - - if (operation == IntervalOperation.ADD) { - return l.plus(r); - } else { - return l.minus(r); - } - } -} +} \ No newline at end of file diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/arithmetic/BinaryArithmeticOperation.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/arithmetic/BinaryArithmeticOperation.java new file mode 100644 index 0000000000000..83d832f6d65c1 --- /dev/null +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/arithmetic/BinaryArithmeticOperation.java @@ -0,0 +1,16 @@ +/* + * 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.ql.expression.predicate.operator.arithmetic; + +import org.elasticsearch.common.io.stream.NamedWriteable; +import org.elasticsearch.xpack.ql.expression.predicate.PredicateBiFunction; + +public interface BinaryArithmeticOperation extends PredicateBiFunction, NamedWriteable { + + @Override + String symbol(); +} diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/arithmetic/BinaryArithmeticPipe.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/arithmetic/BinaryArithmeticPipe.java index 1492d7d37fe52..9402d1717e805 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/arithmetic/BinaryArithmeticPipe.java +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/arithmetic/BinaryArithmeticPipe.java @@ -8,7 +8,7 @@ import org.elasticsearch.xpack.ql.expression.Expression; import org.elasticsearch.xpack.ql.expression.gen.pipeline.BinaryPipe; import org.elasticsearch.xpack.ql.expression.gen.pipeline.Pipe; -import org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.BinaryArithmeticProcessor.BinaryArithmeticOperation; +import org.elasticsearch.xpack.ql.expression.gen.processor.Processor; import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; @@ -34,7 +34,7 @@ protected BinaryPipe replaceChildren(Pipe left, Pipe right) { } @Override - public BinaryArithmeticProcessor asProcessor() { + public Processor asProcessor() { return new BinaryArithmeticProcessor(left().asProcessor(), right().asProcessor(), operation); } diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/arithmetic/BinaryArithmeticProcessor.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/arithmetic/BinaryArithmeticProcessor.java index 382f2e3eeeeff..efdf4823a6e6c 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/arithmetic/BinaryArithmeticProcessor.java +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/arithmetic/BinaryArithmeticProcessor.java @@ -6,140 +6,13 @@ package org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic; import org.elasticsearch.common.io.stream.StreamInput; -import org.elasticsearch.script.JodaCompatibleZonedDateTime; -import org.elasticsearch.xpack.ql.QlIllegalArgumentException; +import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.xpack.ql.expression.gen.processor.FunctionalBinaryProcessor; import org.elasticsearch.xpack.ql.expression.gen.processor.Processor; -import org.elasticsearch.xpack.ql.expression.literal.Interval; -import org.elasticsearch.xpack.ql.expression.literal.IntervalDayTime; -import org.elasticsearch.xpack.ql.expression.literal.IntervalYearMonth; -import org.elasticsearch.xpack.ql.expression.predicate.PredicateBiFunction; -import org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.BinaryArithmeticProcessor.BinaryArithmeticOperation; import java.io.IOException; -import java.time.OffsetTime; -import java.time.ZonedDateTime; -import java.time.temporal.Temporal; -import java.util.function.BiFunction; -public class BinaryArithmeticProcessor extends FunctionalBinaryProcessor { - - private interface NumericArithmetic extends BiFunction { - default Object wrap(Object l, Object r) { - return apply((Number) l, (Number) r); - } - } - - public enum BinaryArithmeticOperation implements PredicateBiFunction { - ADD((Object l, Object r) -> { - if (l instanceof Number) { - return Arithmetics.add((Number) l, (Number) r); - } - if (l instanceof IntervalYearMonth && r instanceof IntervalYearMonth) { - return ((IntervalYearMonth) l).add((IntervalYearMonth) r); - } - if (l instanceof IntervalDayTime && r instanceof IntervalDayTime) { - return ((IntervalDayTime) l).add((IntervalDayTime) r); - } - l = unwrapJodaTime(l); - r = unwrapJodaTime(r); - if ((l instanceof ZonedDateTime || l instanceof OffsetTime) && r instanceof IntervalYearMonth) { - return Arithmetics.add((Temporal) l, ((IntervalYearMonth) r).interval()); - } - if ((l instanceof ZonedDateTime || l instanceof OffsetTime) && r instanceof IntervalDayTime) { - return Arithmetics.add((Temporal) l, ((IntervalDayTime) r).interval()); - } - if ((r instanceof ZonedDateTime || r instanceof OffsetTime) && l instanceof IntervalYearMonth) { - return Arithmetics.add((Temporal) r, ((IntervalYearMonth) l).interval()); - } - if ((r instanceof ZonedDateTime || r instanceof OffsetTime) && l instanceof IntervalDayTime) { - return Arithmetics.add((Temporal) r, ((IntervalDayTime) l).interval()); - } - - throw new QlIllegalArgumentException("Cannot compute [+] between [{}] [{}]", l.getClass().getSimpleName(), - r.getClass().getSimpleName()); - }, "+"), - SUB((Object l, Object r) -> { - if (l instanceof Number) { - return Arithmetics.sub((Number) l, (Number) r); - } - if (l instanceof IntervalYearMonth && r instanceof IntervalYearMonth) { - return ((IntervalYearMonth) l).sub((IntervalYearMonth) r); - } - if (l instanceof IntervalDayTime && r instanceof IntervalDayTime) { - return ((IntervalDayTime) l).sub((IntervalDayTime) r); - } - l = unwrapJodaTime(l); - r = unwrapJodaTime(r); - if ((l instanceof ZonedDateTime || l instanceof OffsetTime) && r instanceof IntervalYearMonth) { - return Arithmetics.sub((Temporal) l, ((IntervalYearMonth) r).interval()); - } - if ((l instanceof ZonedDateTime || l instanceof OffsetTime) && r instanceof IntervalDayTime) { - return Arithmetics.sub((Temporal) l, ((IntervalDayTime) r).interval()); - } - if ((r instanceof ZonedDateTime || r instanceof OffsetTime) && l instanceof Interval) { - throw new QlIllegalArgumentException("Cannot subtract a date from an interval; do you mean the reverse?"); - } - - throw new QlIllegalArgumentException("Cannot compute [-] between [{}] [{}]", l.getClass().getSimpleName(), - r.getClass().getSimpleName()); - }, "-"), - MUL((Object l, Object r) -> { - if (l instanceof Number && r instanceof Number) { - return Arithmetics.mul((Number) l, (Number) r); - } - l = unwrapJodaTime(l); - r = unwrapJodaTime(r); - if (l instanceof Number && r instanceof IntervalYearMonth) { - return ((IntervalYearMonth) r).mul(((Number) l).intValue()); - } - if (r instanceof Number && l instanceof IntervalYearMonth) { - return ((IntervalYearMonth) l).mul(((Number) r).intValue()); - } - if (l instanceof Number && r instanceof IntervalDayTime) { - return ((IntervalDayTime) r).mul(((Number) l).longValue()); - } - if (r instanceof Number && l instanceof IntervalDayTime) { - return ((IntervalDayTime) l).mul(((Number) r).longValue()); - } - - throw new QlIllegalArgumentException("Cannot compute [*] between [{}] [{}]", l.getClass().getSimpleName(), - r.getClass().getSimpleName()); - }, "*"), - DIV(Arithmetics::div, "/"), - MOD(Arithmetics::mod, "%"); - - private final BiFunction process; - private final String symbol; - - BinaryArithmeticOperation(BiFunction process, String symbol) { - this.process = process; - this.symbol = symbol; - } - - BinaryArithmeticOperation(NumericArithmetic process, String symbol) { - this(process::wrap, symbol); - } - - @Override - public String symbol() { - return symbol; - } - - @Override - public final Object doApply(Object left, Object right) { - return process.apply(left, right); - } - - @Override - public String toString() { - return symbol; - } - - private static Object unwrapJodaTime(Object o) { - return o instanceof JodaCompatibleZonedDateTime ? ((JodaCompatibleZonedDateTime) o).getZonedDateTime() : o; - } - } +public final class BinaryArithmeticProcessor extends FunctionalBinaryProcessor { public static final String NAME = "abn"; @@ -148,7 +21,12 @@ public BinaryArithmeticProcessor(Processor left, Processor right, BinaryArithmet } public BinaryArithmeticProcessor(StreamInput in) throws IOException { - super(in, i -> i.readEnum(BinaryArithmeticOperation.class)); + super(in, i -> i.readNamedWriteable(BinaryArithmeticOperation.class)); + } + + @Override + protected void doWrite(StreamOutput out) throws IOException { + out.writeNamedWriteable(function()); } @Override @@ -164,23 +42,6 @@ protected Object doProcess(Object left, Object right) { return null; } - if (f == BinaryArithmeticOperation.DIV || f == BinaryArithmeticOperation.MOD) { - if (!(left instanceof Number)) { - throw new QlIllegalArgumentException("A number is required; received {}", left); - } - - if (!(right instanceof Number)) { - throw new QlIllegalArgumentException("A number is required; received {}", right); - } - - return f.apply(left, right); - } - - if (f == BinaryArithmeticOperation.ADD || f == BinaryArithmeticOperation.SUB || f == BinaryArithmeticOperation.MUL) { - return f.apply(left, right); - } - - // this should not occur - throw new QlIllegalArgumentException("Cannot perform arithmetic operation due to arguments"); + return f.apply(left, right); } -} +} \ No newline at end of file diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/arithmetic/DateTimeArithmeticOperation.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/arithmetic/DateTimeArithmeticOperation.java index 2e1f03666b3e9..c430b433171a2 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/arithmetic/DateTimeArithmeticOperation.java +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/arithmetic/DateTimeArithmeticOperation.java @@ -7,12 +7,8 @@ package org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic; import org.elasticsearch.xpack.ql.expression.Expression; -import org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.BinaryArithmeticProcessor.BinaryArithmeticOperation; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; -import org.elasticsearch.xpack.ql.type.DataTypeConversion; - -import static org.elasticsearch.common.logging.LoggerMessageFormat.format; abstract class DateTimeArithmeticOperation extends ArithmeticOperation { @@ -26,11 +22,7 @@ protected TypeResolution resolveType() { return new TypeResolution("Unresolved children"); } - // arithmetic operation can work on: - // 1. numbers - // 2. intervals (of compatible types) - // 3. dates and intervals - // 4. single unit intervals and numbers + // arithmetic operation can work on numbers in QL DataType l = left().dataType(); DataType r = right().dataType(); @@ -39,26 +31,8 @@ protected TypeResolution resolveType() { if (l.isNumeric() && r.isNumeric()) { return TypeResolution.TYPE_RESOLVED; } - // 2. 3. 4. intervals - if (l.isInterval() || r.isInterval()) { - if (DataTypeConversion.commonType(l, r) == null) { - return new TypeResolution(format(null, "[{}] has arguments with incompatible types [{}] and [{}]", symbol(), l, r)); - } else { - return resolveWithIntervals(); - } - } // fall-back to default checks return super.resolveType(); } - - protected TypeResolution resolveWithIntervals() { - DataType l = left().dataType(); - DataType r = right().dataType(); - - if (!(r.isDateOrTimeBased() || r.isInterval() || r.isNull())|| !(l.isDateOrTimeBased() || l.isInterval() || l.isNull())) { - return new TypeResolution(format(null, "[{}] has arguments with incompatible types [{}] and [{}]", symbol(), l, r)); - } - return TypeResolution.TYPE_RESOLVED; - } } diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/arithmetic/DefaultBinaryArithmeticOperation.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/arithmetic/DefaultBinaryArithmeticOperation.java new file mode 100644 index 0000000000000..11a9522954087 --- /dev/null +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/arithmetic/DefaultBinaryArithmeticOperation.java @@ -0,0 +1,66 @@ +/* + * 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.ql.expression.predicate.operator.arithmetic; + +import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.common.io.stream.StreamOutput; +import org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.Arithmetics.NumericArithmetic; + +import java.io.IOException; +import java.util.function.BiFunction; + +public enum DefaultBinaryArithmeticOperation implements BinaryArithmeticOperation { + + ADD(Arithmetics::add, "+"), + SUB(Arithmetics::sub, "-"), + MUL(Arithmetics::mul, "*"), + DIV(Arithmetics::div, "/"), + MOD(Arithmetics::mod, "%"); + + public static final String NAME = "abn-def"; + + private final BiFunction process; + private final String symbol; + + DefaultBinaryArithmeticOperation(BiFunction process, String symbol) { + this.process = process; + this.symbol = symbol; + } + + DefaultBinaryArithmeticOperation(NumericArithmetic process, String symbol) { + this(process::wrap, symbol); + } + + @Override + public String symbol() { + return symbol; + } + + @Override + public final Object doApply(Object left, Object right) { + return process.apply(left, right); + } + + @Override + public String toString() { + return symbol; + } + + @Override + public String getWriteableName() { + return NAME; + } + + @Override + public void writeTo(StreamOutput out) throws IOException { + out.writeEnum(this); + } + + public static DefaultBinaryArithmeticOperation read(StreamInput in) throws IOException { + return in.readEnum(DefaultBinaryArithmeticOperation.class); + } +} diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/arithmetic/Div.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/arithmetic/Div.java index 2045c094d436a..bf2538eee6441 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/arithmetic/Div.java +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/arithmetic/Div.java @@ -6,11 +6,10 @@ package org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic; import org.elasticsearch.xpack.ql.expression.Expression; -import org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.BinaryArithmeticProcessor.BinaryArithmeticOperation; import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; -import org.elasticsearch.xpack.ql.type.DataTypeConversion; +import org.elasticsearch.xpack.ql.type.DataTypeConverter; /** * Division function ({@code a / b}). @@ -18,7 +17,7 @@ public class Div extends ArithmeticOperation { public Div(Source source, Expression left, Expression right) { - super(source, left, right, BinaryArithmeticOperation.DIV); + super(source, left, right, DefaultBinaryArithmeticOperation.DIV); } @Override @@ -33,6 +32,6 @@ protected Div replaceChildren(Expression newLeft, Expression newRight) { @Override public DataType dataType() { - return DataTypeConversion.commonType(left().dataType(), right().dataType()); + return DataTypeConverter.commonType(left().dataType(), right().dataType()); } } diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/arithmetic/Mod.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/arithmetic/Mod.java index 68688fc6b83a6..1fec0758fedb3 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/arithmetic/Mod.java +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/arithmetic/Mod.java @@ -6,7 +6,6 @@ package org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic; import org.elasticsearch.xpack.ql.expression.Expression; -import org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.BinaryArithmeticProcessor.BinaryArithmeticOperation; import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; @@ -19,7 +18,7 @@ public class Mod extends ArithmeticOperation { public Mod(Source source, Expression left, Expression right) { - super(source, left, right, BinaryArithmeticOperation.MOD); + super(source, left, right, DefaultBinaryArithmeticOperation.MOD); } @Override diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/arithmetic/Mul.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/arithmetic/Mul.java index 5868355a0a828..79dd648278dc4 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/arithmetic/Mul.java +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/arithmetic/Mul.java @@ -6,10 +6,10 @@ package org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic; import org.elasticsearch.xpack.ql.expression.Expression; -import org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.BinaryArithmeticProcessor.BinaryArithmeticOperation; import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import static org.elasticsearch.common.logging.LoggerMessageFormat.format; @@ -18,10 +18,8 @@ */ public class Mul extends ArithmeticOperation { - private DataType dataType; - public Mul(Source source, Expression left, Expression right) { - super(source, left, right, BinaryArithmeticOperation.MUL); + super(source, left, right, DefaultBinaryArithmeticOperation.MUL); } @Override @@ -34,29 +32,13 @@ protected TypeResolution resolveType() { DataType r = right().dataType(); // 1. both are numbers - if (l.isNullOrNumeric() && r.isNullOrNumeric()) { - return TypeResolution.TYPE_RESOLVED; - } - - if (l.isNullOrInterval() && (r.isInteger() || r.isNull())) { - dataType = l; - return TypeResolution.TYPE_RESOLVED; - } else if (r.isNullOrInterval() && (l.isInteger() || l.isNull())) { - dataType = r; + if (DataTypes.isNullOrNumeric(l) && DataTypes.isNullOrNumeric(r)) { return TypeResolution.TYPE_RESOLVED; } return new TypeResolution(format(null, "[{}] has arguments with incompatible types [{}] and [{}]", symbol(), l, r)); } - @Override - public DataType dataType() { - if (dataType == null) { - dataType = super.dataType(); - } - return dataType; - } - @Override protected NodeInfo info() { return NodeInfo.create(this, Mul::new, left(), right()); diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/arithmetic/Sub.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/arithmetic/Sub.java index 61e7e24787884..c5d7fc920e843 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/arithmetic/Sub.java +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/arithmetic/Sub.java @@ -6,19 +6,16 @@ package org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic; import org.elasticsearch.xpack.ql.expression.Expression; -import org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.BinaryArithmeticProcessor.BinaryArithmeticOperation; import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; -import static org.elasticsearch.common.logging.LoggerMessageFormat.format; - /** * Subtraction function ({@code a - b}). */ public class Sub extends DateTimeArithmeticOperation { public Sub(Source source, Expression left, Expression right) { - super(source, left, right, BinaryArithmeticOperation.SUB); + super(source, left, right, DefaultBinaryArithmeticOperation.SUB); } @Override @@ -30,17 +27,4 @@ protected NodeInfo info() { protected Sub replaceChildren(Expression newLeft, Expression newRight) { return new Sub(source(), newLeft, newRight); } - - @Override - protected TypeResolution resolveWithIntervals() { - TypeResolution resolution = super.resolveWithIntervals(); - if (resolution.unresolved()) { - return resolution; - } - if ((right().dataType().isDateOrTimeBased()) && left().dataType().isInterval()) { - return new TypeResolution(format(null, "Cannot subtract a {}[{}] from an interval[{}]; do you mean the reverse?", - right().dataType().typeName(), right().source().text(), left().source().text())); - } - return TypeResolution.TYPE_RESOLVED; - } } diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/comparison/BinaryComparison.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/comparison/BinaryComparison.java index 322c3f86e6553..49288c294b238 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/comparison/BinaryComparison.java +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/comparison/BinaryComparison.java @@ -13,6 +13,7 @@ import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.BinaryComparisonProcessor.BinaryComparisonOperation; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; // marker class to indicate operations that rely on values public abstract class BinaryComparison extends BinaryOperator { @@ -33,7 +34,7 @@ protected Expression canonicalize() { @Override public DataType dataType() { - return DataType.BOOLEAN; + return DataTypes.BOOLEAN; } @Override diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/comparison/BinaryComparisonProcessor.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/comparison/BinaryComparisonProcessor.java index c7867e0ffdd5a..ed9d430617d44 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/comparison/BinaryComparisonProcessor.java +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/comparison/BinaryComparisonProcessor.java @@ -6,7 +6,7 @@ package org.elasticsearch.xpack.ql.expression.predicate.operator.comparison; import org.elasticsearch.common.io.stream.StreamInput; -import org.elasticsearch.xpack.ql.expression.gen.processor.FunctionalBinaryProcessor; +import org.elasticsearch.xpack.ql.expression.gen.processor.FunctionalEnumBinaryProcessor; import org.elasticsearch.xpack.ql.expression.gen.processor.Processor; import org.elasticsearch.xpack.ql.expression.predicate.PredicateBiFunction; import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.BinaryComparisonProcessor.BinaryComparisonOperation; @@ -14,7 +14,7 @@ import java.io.IOException; import java.util.function.BiFunction; -public class BinaryComparisonProcessor extends FunctionalBinaryProcessor { +public class BinaryComparisonProcessor extends FunctionalEnumBinaryProcessor { public enum BinaryComparisonOperation implements PredicateBiFunction { diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/regex/RegexMatch.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/regex/RegexMatch.java index c1b9cd4db937c..517c243992c24 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/regex/RegexMatch.java +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/regex/RegexMatch.java @@ -12,6 +12,7 @@ import org.elasticsearch.xpack.ql.expression.function.scalar.UnaryScalarFunction; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import java.util.Objects; @@ -32,7 +33,7 @@ public T pattern() { @Override public DataType dataType() { - return DataType.BOOLEAN; + return DataTypes.BOOLEAN; } @Override diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/processor/Processors.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/processor/Processors.java index ac954a67e5aad..4cf9b004a86ae 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/processor/Processors.java +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/processor/Processors.java @@ -12,17 +12,16 @@ import org.elasticsearch.xpack.ql.expression.gen.processor.ConstantProcessor; import org.elasticsearch.xpack.ql.expression.gen.processor.HitExtractorProcessor; import org.elasticsearch.xpack.ql.expression.gen.processor.Processor; -import org.elasticsearch.xpack.ql.expression.predicate.conditional.CaseProcessor; -import org.elasticsearch.xpack.ql.expression.predicate.conditional.ConditionalProcessor; -import org.elasticsearch.xpack.ql.expression.predicate.conditional.NullIfProcessor; import org.elasticsearch.xpack.ql.expression.predicate.logical.BinaryLogicProcessor; import org.elasticsearch.xpack.ql.expression.predicate.logical.NotProcessor; -import org.elasticsearch.xpack.ql.expression.predicate.nulls.CheckNullProcessor; +import org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.BinaryArithmeticOperation; import org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.BinaryArithmeticProcessor; +import org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.DefaultBinaryArithmeticOperation; import org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.UnaryArithmeticProcessor; import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.BinaryComparisonProcessor; -import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.InProcessor; import org.elasticsearch.xpack.ql.expression.predicate.regex.RegexProcessor; +import org.elasticsearch.xpack.ql.type.Converter; +import org.elasticsearch.xpack.ql.type.DataTypeConverter.DefaultConverter; import java.util.ArrayList; import java.util.List; @@ -37,7 +36,10 @@ private Processors() {} */ public static List getNamedWriteables() { List entries = new ArrayList<>(); + // base + entries.add(new Entry(Converter.class, DefaultConverter.NAME, DefaultConverter::read)); + entries.add(new Entry(Processor.class, ConstantProcessor.NAME, ConstantProcessor::new)); entries.add(new Entry(Processor.class, HitExtractorProcessor.NAME, HitExtractorProcessor::new)); entries.add(new Entry(Processor.class, BucketExtractorProcessor.NAME, BucketExtractorProcessor::new)); @@ -46,18 +48,15 @@ public static List getNamedWriteables() { // logical entries.add(new Entry(Processor.class, BinaryLogicProcessor.NAME, BinaryLogicProcessor::new)); entries.add(new Entry(Processor.class, NotProcessor.NAME, NotProcessor::new)); - // conditionals - entries.add(new Entry(Processor.class, CaseProcessor.NAME, CaseProcessor::new)); - entries.add(new Entry(Processor.class, CheckNullProcessor.NAME, CheckNullProcessor::new)); - entries.add(new Entry(Processor.class, ConditionalProcessor.NAME, ConditionalProcessor::new)); - entries.add(new Entry(Processor.class, NullIfProcessor.NAME, NullIfProcessor::new)); // arithmetic + // binary arithmetics are pluggable + entries.add( + new Entry(BinaryArithmeticOperation.class, DefaultBinaryArithmeticOperation.NAME, DefaultBinaryArithmeticOperation::read)); entries.add(new Entry(Processor.class, BinaryArithmeticProcessor.NAME, BinaryArithmeticProcessor::new)); entries.add(new Entry(Processor.class, UnaryArithmeticProcessor.NAME, UnaryArithmeticProcessor::new)); // comparators entries.add(new Entry(Processor.class, BinaryComparisonProcessor.NAME, BinaryComparisonProcessor::new)); - entries.add(new Entry(Processor.class, InProcessor.NAME, InProcessor::new)); // regex entries.add(new Entry(Processor.class, RegexProcessor.NAME, RegexProcessor::new)); diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/index/IndexResolver.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/index/IndexResolver.java index 21b466e6919b2..770fef089bba5 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/index/IndexResolver.java +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/index/IndexResolver.java @@ -26,6 +26,7 @@ import org.elasticsearch.index.IndexSettings; import org.elasticsearch.xpack.ql.QlIllegalArgumentException; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypeRegistry; import org.elasticsearch.xpack.ql.type.DateEsField; import org.elasticsearch.xpack.ql.type.EsField; import org.elasticsearch.xpack.ql.type.InvalidMappedField; @@ -59,6 +60,11 @@ import static java.util.Collections.emptyMap; import static java.util.Collections.emptySet; import static org.elasticsearch.action.ActionListener.wrap; +import static org.elasticsearch.xpack.ql.type.DataTypes.DATETIME; +import static org.elasticsearch.xpack.ql.type.DataTypes.KEYWORD; +import static org.elasticsearch.xpack.ql.type.DataTypes.OBJECT; +import static org.elasticsearch.xpack.ql.type.DataTypes.TEXT; +import static org.elasticsearch.xpack.ql.type.DataTypes.UNSUPPORTED; public class IndexResolver { @@ -154,11 +160,13 @@ public boolean equals(Object obj) { private final Client client; private final String clusterName; + private final DataTypeRegistry typeRegistry; - public IndexResolver(Client client, String clusterName) { + public IndexResolver(Client client, String clusterName, DataTypeRegistry typeRegistry) { this.client = client; this.clusterName = clusterName; + this.typeRegistry = typeRegistry; } public String clusterName() { @@ -274,11 +282,11 @@ public void resolveAsMergedMapping(String indexWildcard, String javaRegex, boole FieldCapabilitiesRequest fieldRequest = createFieldCapsRequest(indexWildcard, includeFrozen); client.fieldCaps(fieldRequest, ActionListener.wrap( - response -> listener.onResponse(mergedMappings(indexWildcard, response.getIndices(), response.get())), + response -> listener.onResponse(mergedMappings(typeRegistry, indexWildcard, response.getIndices(), response.get())), listener::onFailure)); } - public static IndexResolution mergedMappings(String indexPattern, String[] indexNames, + public static IndexResolution mergedMappings(DataTypeRegistry typeRegistry, String indexPattern, String[] indexNames, Map> fieldCaps) { if (fieldCaps == null || fieldCaps.isEmpty()) { @@ -286,7 +294,7 @@ public static IndexResolution mergedMappings(String indexPattern, String[] index } // merge all indices onto the same one - List indices = buildIndices(indexNames, null, fieldCaps, i -> indexPattern, (n, types) -> { + List indices = buildIndices(typeRegistry, indexNames, null, fieldCaps, i -> indexPattern, (n, types) -> { StringBuilder errorMessage = new StringBuilder(); boolean hasUnmapped = types.containsKey(UNMAPPED); @@ -349,7 +357,8 @@ public static IndexResolution mergedMappings(String indexPattern, String[] index return IndexResolution.valid(indices.isEmpty() ? new EsIndex(indexNames[0], emptyMap()) : indices.get(0)); } - private static EsField createField(String fieldName, Map> globalCaps, + private static EsField createField(DataTypeRegistry typeRegistry, String fieldName, + Map> globalCaps, Map hierarchicalMapping, Map flattedMapping, Function field) { @@ -371,7 +380,7 @@ private static EsField createField(String fieldName, Map createField(s, DataType.OBJECT.name(), new TreeMap<>(), false, true); + fieldFunction = s -> createField(typeRegistry, s, OBJECT.esType(), new TreeMap<>(), false, true); } else { Iterator iterator = map.values().iterator(); FieldCapabilities parentCap = iterator.next(); @@ -379,10 +388,10 @@ private static EsField createField(String fieldName, Map createField(s, parentC.getType(), new TreeMap<>(), parentC.isAggregatable(), false); + fieldFunction = s -> createField(typeRegistry, s, parentC.getType(), new TreeMap<>(), parentC.isAggregatable(), false); } - parent = createField(parentName, globalCaps, hierarchicalMapping, flattedMapping, fieldFunction); + parent = createField(typeRegistry, parentName, globalCaps, hierarchicalMapping, flattedMapping, fieldFunction); } parentProps = parent.getProperties(); } @@ -410,24 +419,27 @@ private static EsField createField(String fieldName, Map props, + private static EsField createField(DataTypeRegistry typeRegistry, String fieldName, String typeName, Map props, boolean isAggregateable, boolean isAlias) { - DataType esType = DataType.fromTypeName(typeName); - switch (esType) { - case TEXT: - return new TextEsField(fieldName, props, false, isAlias); - case KEYWORD: - int length = DataType.KEYWORD.defaultPrecision; - // TODO: to check whether isSearchable/isAggregateable takes into account the presence of the normalizer - boolean normalized = false; - return new KeywordEsField(fieldName, props, isAggregateable, length, normalized, isAlias); - case DATETIME: - return new DateEsField(fieldName, props, isAggregateable); - case UNSUPPORTED: - return new UnsupportedEsField(fieldName, typeName, null, props); - default: - return new EsField(fieldName, esType, props, isAggregateable, isAlias); + DataType esType = typeRegistry.fromEs(typeName); + + if (esType == TEXT) { + return new TextEsField(fieldName, props, false, isAlias); + } + if (esType == KEYWORD) { + int length = Short.MAX_VALUE; + // TODO: to check whether isSearchable/isAggregateable takes into account the presence of the normalizer + boolean normalized = false; + return new KeywordEsField(fieldName, props, isAggregateable, length, normalized, isAlias); + } + if (esType == DATETIME) { + return new DateEsField(fieldName, props, isAggregateable); } + if (esType == UNSUPPORTED) { + return new UnsupportedEsField(fieldName, typeName, null, props); + } + + return new EsField(fieldName, esType, props, isAggregateable, isAlias); } private static FieldCapabilitiesRequest createFieldCapsRequest(String index, boolean includeFrozen) { @@ -448,14 +460,15 @@ public void resolveAsSeparateMappings(String indexWildcard, String javaRegex, bo FieldCapabilitiesRequest fieldRequest = createFieldCapsRequest(indexWildcard, includeFrozen); client.fieldCaps(fieldRequest, ActionListener.wrap( - response -> listener.onResponse(separateMappings(indexWildcard, javaRegex, response.getIndices(), response.get())), + response -> listener.onResponse( + separateMappings(typeRegistry, indexWildcard, javaRegex, response.getIndices(), response.get())), listener::onFailure)); } - public static List separateMappings(String indexPattern, String javaRegex, String[] indexNames, + public static List separateMappings(DataTypeRegistry typeRegistry, String indexPattern, String javaRegex, String[] indexNames, Map> fieldCaps) { - return buildIndices(indexNames, javaRegex, fieldCaps, Function.identity(), (s, cap) -> null); + return buildIndices(typeRegistry, indexNames, javaRegex, fieldCaps, Function.identity(), (s, cap) -> null); } private static class Fields { @@ -467,7 +480,8 @@ private static class Fields { * Assemble an index-based mapping from the field caps (which is field based) by looking at the indices associated with * each field. */ - private static List buildIndices(String[] indexNames, String javaRegex, Map> fieldCaps, + private static List buildIndices(DataTypeRegistry typeRegistry, String[] indexNames, String javaRegex, + Map> fieldCaps, Function indexNameProcessor, BiFunction, InvalidMappedField> validityVerifier) { @@ -558,9 +572,10 @@ private static List buildIndices(String[] indexNames, String javaRegex, } } - createField(fieldName, fieldCaps, indexFields.hierarchicalMapping, indexFields.flattedMapping, - s -> invalidField != null ? invalidField : createField(s, typeCap.getType(), emptyMap(), - typeCap.isAggregatable(), isAlias.get())); + createField(typeRegistry, fieldName, fieldCaps, indexFields.hierarchicalMapping, indexFields.flattedMapping, + s -> invalidField != null ? invalidField : + createField(typeRegistry, s, typeCap.getType(), emptyMap(), typeCap.isAggregatable(), + isAlias.get())); } } } diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/Converter.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/Converter.java new file mode 100644 index 0000000000000..d588605410d40 --- /dev/null +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/Converter.java @@ -0,0 +1,14 @@ +/* + * 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.ql.type; + +import org.elasticsearch.common.io.stream.NamedWriteable; + +public interface Converter extends NamedWriteable { + + Object convert(Object value); +} diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/DataType.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/DataType.java index 80dae7dd13366..aa02d4b44a2eb 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/DataType.java +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/DataType.java @@ -3,182 +3,22 @@ * 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.ql.type; -import org.elasticsearch.index.mapper.NumberFieldMapper.NumberType; +package org.elasticsearch.xpack.ql.type; -import java.sql.JDBCType; -import java.sql.SQLType; -import java.sql.Types; -import java.util.HashMap; import java.util.Locale; -import java.util.Map; -import java.util.Map.Entry; - -/** - * Elasticsearch SQL data types. - * This class also implements JDBC {@link SQLType} for properly receiving and setting values. - * Where possible, please use the built-in, JDBC {@link Types} and {@link JDBCType} to avoid coupling - * to the API. - */ -public enum DataType { - - // @formatter:off - // esType jdbc type, size, defPrecision,dispSize, int, rat, docvals - NULL( "null", JDBCType.NULL, 0, 0, 0, false, false, false), - UNSUPPORTED( JDBCType.OTHER, 0, 0, 0, false, false, false), - BOOLEAN( "boolean", JDBCType.BOOLEAN, 1, 1, 1, false, false, false), - BYTE( "byte", JDBCType.TINYINT, Byte.BYTES, 3, 5, true, false, true), - SHORT( "short", JDBCType.SMALLINT, Short.BYTES, 5, 6, true, false, true), - INTEGER( "integer", JDBCType.INTEGER, Integer.BYTES, 10, 11, true, false, true), - LONG( "long", JDBCType.BIGINT, Long.BYTES, 19, 20, true, false, true), - // 53 bits defaultPrecision ~ 15(15.95) decimal digits (53log10(2)), - DOUBLE( "double", JDBCType.DOUBLE, Double.BYTES, 15, 25, false, true, true), - // 24 bits defaultPrecision - 24*log10(2) =~ 7 (7.22) - FLOAT( "float", JDBCType.REAL, Float.BYTES, 7, 15, false, true, true), - HALF_FLOAT( "half_float", JDBCType.FLOAT, Float.BYTES, 3, 25, false, true, true), - // precision is based on long - SCALED_FLOAT( "scaled_float", JDBCType.DOUBLE, Long.BYTES, 15, 25, false, true, true), - KEYWORD( "keyword", JDBCType.VARCHAR, Integer.MAX_VALUE, 32766, 32766, false, false, true), - TEXT( "text", JDBCType.VARCHAR, Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, false, false, false), - OBJECT( "object", JDBCType.STRUCT, -1, 0, 0, false, false, false), - NESTED( "nested", JDBCType.STRUCT, -1, 0, 0, false, false, false), - BINARY( "binary", JDBCType.VARBINARY, -1, Integer.MAX_VALUE, Integer.MAX_VALUE, false, false, false), - // since ODBC and JDBC interpret precision for Date as display size - // the precision is 23 (number of chars in ISO8601 with millis) + 6 chars for the timezone (e.g.: +05:00) - // see https://github.com/elastic/elasticsearch/issues/30386#issuecomment-386807288 - DATE( JDBCType.DATE, Long.BYTES, 3, 29, false, false, true), - TIME( JDBCType.TIME, Long.BYTES, 3, 18, false, false, true), - DATETIME( "date", JDBCType.TIMESTAMP, Long.BYTES, 3, 29, false, false, true), - // - // specialized types - // - GEO_SHAPE( ExtTypes.GEOMETRY, Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, false, false, false), - // display size = 2 doubles + len("POINT( )") - GEO_POINT( ExtTypes.GEOMETRY, Double.BYTES*2, Integer.MAX_VALUE, 25 * 2 + 8, false, false, false), - // IP can be v4 or v6. The latter has 2^128 addresses or 340,282,366,920,938,463,463,374,607,431,768,211,456 - // aka 39 chars - SHAPE( ExtTypes.GEOMETRY, Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, false, false, false), - // display size = 2 doubles + len("POINT( )") - IP( "ip", JDBCType.VARCHAR, 39, 39, 0, false, false, true), - // - // INTERVALS - // the list is long as there are a lot of variations and that's what clients (ODBC) expect - // esType:null jdbc type, size, prec,disp, int, rat, docvals - INTERVAL_YEAR( ExtTypes.INTERVAL_YEAR, Integer.BYTES, 7, 7, false, false, false), - INTERVAL_MONTH( ExtTypes.INTERVAL_MONTH, Integer.BYTES, 7, 7, false, false, false), - INTERVAL_DAY( ExtTypes.INTERVAL_DAY, Long.BYTES, 23, 23, false, false, false), - INTERVAL_HOUR( ExtTypes.INTERVAL_HOUR, Long.BYTES, 23, 23, false, false, false), - INTERVAL_MINUTE( ExtTypes.INTERVAL_MINUTE, Long.BYTES, 23, 23, false, false, false), - INTERVAL_SECOND( ExtTypes.INTERVAL_SECOND, Long.BYTES, 23, 23, false, false, false), - INTERVAL_YEAR_TO_MONTH( ExtTypes.INTERVAL_YEAR_TO_MONTH, Integer.BYTES, 7, 7, false, false, false), - INTERVAL_DAY_TO_HOUR( ExtTypes.INTERVAL_DAY_TO_HOUR, Long.BYTES, 23, 23, false, false, false), - INTERVAL_DAY_TO_MINUTE( ExtTypes.INTERVAL_DAY_TO_MINUTE, Long.BYTES, 23, 23, false, false, false), - INTERVAL_DAY_TO_SECOND( ExtTypes.INTERVAL_DAY_TO_SECOND, Long.BYTES, 23, 23, false, false, false), - INTERVAL_HOUR_TO_MINUTE( ExtTypes.INTERVAL_HOUR_TO_MINUTE, Long.BYTES, 23, 23, false, false, false), - INTERVAL_HOUR_TO_SECOND( ExtTypes.INTERVAL_HOUR_TO_SECOND, Long.BYTES, 23, 23, false, false, false), - INTERVAL_MINUTE_TO_SECOND(ExtTypes.INTERVAL_MINUTE_TO_SECOND,Long.BYTES, 23, 23, false, false, false); - // @formatter:on - - private static final Map ODBC_TO_ES = new HashMap<>(36); - static { - // Numeric - ODBC_TO_ES.put("SQL_BIT", BOOLEAN); - ODBC_TO_ES.put("SQL_TINYINT", BYTE); - ODBC_TO_ES.put("SQL_SMALLINT", SHORT); - ODBC_TO_ES.put("SQL_INTEGER", INTEGER); - ODBC_TO_ES.put("SQL_BIGINT", LONG); - ODBC_TO_ES.put("SQL_REAL", FLOAT); - ODBC_TO_ES.put("SQL_FLOAT", DOUBLE); - ODBC_TO_ES.put("SQL_DOUBLE", DOUBLE); - ODBC_TO_ES.put("SQL_DECIMAL", DOUBLE); - ODBC_TO_ES.put("SQL_NUMERIC", DOUBLE); - - // String - ODBC_TO_ES.put("SQL_GUID", KEYWORD); - ODBC_TO_ES.put("SQL_CHAR", KEYWORD); - ODBC_TO_ES.put("SQL_WCHAR", KEYWORD); - ODBC_TO_ES.put("SQL_VARCHAR", TEXT); - ODBC_TO_ES.put("SQL_WVARCHAR", TEXT); - ODBC_TO_ES.put("SQL_LONGVARCHAR", TEXT); - ODBC_TO_ES.put("SQL_WLONGVARCHAR", TEXT); - - // Binary - ODBC_TO_ES.put("SQL_BINARY", BINARY); - ODBC_TO_ES.put("SQL_VARBINARY", BINARY); - ODBC_TO_ES.put("SQL_LONGVARBINARY", BINARY); - - // Date - ODBC_TO_ES.put("SQL_DATE", DATE); - ODBC_TO_ES.put("SQL_TIME", TIME); - ODBC_TO_ES.put("SQL_TIMESTAMP", DATETIME); - - // Intervals - ODBC_TO_ES.put("SQL_INTERVAL_HOUR_TO_MINUTE", INTERVAL_HOUR_TO_MINUTE); - ODBC_TO_ES.put("SQL_INTERVAL_HOUR_TO_SECOND", INTERVAL_HOUR_TO_SECOND); - ODBC_TO_ES.put("SQL_INTERVAL_MINUTE_TO_SECOND", INTERVAL_MINUTE_TO_SECOND); - ODBC_TO_ES.put("SQL_INTERVAL_MONTH", INTERVAL_MONTH); - ODBC_TO_ES.put("SQL_INTERVAL_YEAR", INTERVAL_YEAR); - ODBC_TO_ES.put("SQL_INTERVAL_YEAR_TO_MONTH", INTERVAL_YEAR_TO_MONTH); - ODBC_TO_ES.put("SQL_INTERVAL_DAY", INTERVAL_DAY); - ODBC_TO_ES.put("SQL_INTERVAL_HOUR", INTERVAL_HOUR); - ODBC_TO_ES.put("SQL_INTERVAL_MINUTE", INTERVAL_MINUTE); - ODBC_TO_ES.put("SQL_INTERVAL_SECOND", INTERVAL_SECOND); - ODBC_TO_ES.put("SQL_INTERVAL_DAY_TO_HOUR", INTERVAL_DAY_TO_HOUR); - ODBC_TO_ES.put("SQL_INTERVAL_DAY_TO_MINUTE", INTERVAL_DAY_TO_MINUTE); - ODBC_TO_ES.put("SQL_INTERVAL_DAY_TO_SECOND", INTERVAL_DAY_TO_SECOND); - } - - - private static final Map SQL_TO_ES = new HashMap<>(45); - static { - // first add ES types - for (DataType type : DataType.values()) { - if (type.isPrimitive()) { - SQL_TO_ES.put(type.name(), type); - } - } - - // reuse the ODBC definition (without SQL_) - // note that this will override existing types in particular FLOAT - for (Entry entry : ODBC_TO_ES.entrySet()) { - SQL_TO_ES.put(entry.getKey().substring(4), entry.getValue()); - } - - // special ones - SQL_TO_ES.put("BOOL", DataType.BOOLEAN); - SQL_TO_ES.put("INT", DataType.INTEGER); - SQL_TO_ES.put("STRING", DataType.KEYWORD); - } +import java.util.Objects; +public class DataType { private final String typeName; - private final String esType; + private final String name; - /** - * Compatible JDBC type - */ - private final SQLType sqlType; + private final String esType; private 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 milliseconds component). - */ - public final int defaultPrecision; - - /** - * Display Size - *

- * Normal maximum width in characters. - */ - public final int displaySize; - /** * True if the type represents an integer number */ @@ -192,24 +32,25 @@ public enum DataType { /** * True if the type supports doc values by default */ - public final boolean defaultDocValues; + private final boolean docValues; - DataType(SQLType sqlType, int size, int defaultPrecision, int displaySize, boolean isInteger, - boolean isRational, boolean defaultDocValues) { - this(null, sqlType, size, defaultPrecision, displaySize, isInteger, isRational, defaultDocValues); + public DataType(String esName, int size, boolean isInteger, boolean isRational, boolean hasDocValues) { + this(null, esName, size, isInteger, isRational, hasDocValues); } - DataType(String esType, SQLType sqlType, int size, int defaultPrecision, int displaySize, boolean isInteger, - boolean isRational, boolean defaultDocValues) { - this.typeName = name().toLowerCase(Locale.ROOT); + public DataType(String typeName, String esType, int size, boolean isInteger, boolean isRational, boolean hasDocValues) { + String typeString = typeName != null ? typeName : esType; + this.typeName = typeString.toLowerCase(Locale.ROOT); + this.name = typeString.toUpperCase(Locale.ROOT); this.esType = esType; - this.sqlType = sqlType; this.size = size; - this.defaultPrecision = defaultPrecision; - this.displaySize = displaySize; this.isInteger = isInteger; this.isRational = isRational; - this.defaultDocValues = defaultDocValues; + this.docValues = hasDocValues; + } + + public String name() { + return name; } public String typeName() { @@ -220,23 +61,6 @@ public String esType() { return esType; } - public SQLType sqlType() { - return sqlType; - } - - /** - * Size of the type in bytes - *

- * -1 if the size can vary - */ - public int size() { - return size; - } - - public String sqlName() { - return sqlType.getName(); - } - public boolean isInteger() { return isInteger; } @@ -249,108 +73,40 @@ public boolean isNumeric() { return isInteger || isRational; } - /** - * Returns true if value is signed, false otherwise (including if the type is not numeric) - */ - public boolean isSigned() { - // For now all numeric values that es supports are signed - return isNumeric(); - } - - public boolean isNull() { - return this == NULL; - } - - public boolean isNullOrNumeric() { - return isNull() || isNumeric(); - } - - public boolean isNullOrInterval() { - return isNull() || isInterval(); - } - - public boolean isString() { - return this == KEYWORD || this == TEXT; - } - - public boolean isPrimitive() { - return this != OBJECT && this != NESTED && this != UNSUPPORTED; - } - - public boolean isGeo() { - return this == GEO_POINT || this == GEO_SHAPE || this == SHAPE; - } - - public boolean isDateBased() { - return this == DATE || this == DATETIME; - } - - public boolean isTimeBased() { - return this == TIME; - } - - public boolean isDateOrTimeBased() { - return isDateBased() || isTimeBased(); - } - - public boolean isInterval() { - int ordinal = this.ordinal(); - return ordinal >= INTERVAL_YEAR.ordinal() && ordinal <= INTERVAL_MINUTE_TO_SECOND.ordinal(); - } - - public boolean isYearMonthInterval() { - return this == INTERVAL_YEAR || this == INTERVAL_MONTH || this == INTERVAL_YEAR_TO_MONTH; - } - - public boolean isDayTimeInterval() { - int ordinal = this.ordinal(); - return (ordinal >= INTERVAL_DAY.ordinal() && ordinal <= INTERVAL_SECOND.ordinal()) - || (ordinal >= INTERVAL_DAY_TO_HOUR.ordinal() && ordinal <= INTERVAL_MINUTE_TO_SECOND.ordinal()); - } - - // data type extract-able from _source or from docvalue_fields - public boolean isFromDocValuesOnly() { - return this == KEYWORD // because of ignore_above. Extracting this from _source wouldn't make sense if it wasn't indexed at all. - || this == DATE // because of date formats - || this == DATETIME - || this == SCALED_FLOAT // because of scaling_factor - || this == GEO_POINT - || this == GEO_SHAPE - || this == SHAPE; + public int size() { + return size; } - public static DataType fromOdbcType(String odbcType) { - return ODBC_TO_ES.get(odbcType); + public boolean hasDocValues() { + return docValues; } - public static DataType fromSqlOrEsType(String typeName) { - return SQL_TO_ES.get(typeName.toUpperCase(Locale.ROOT)); + @Override + public int hashCode() { + return Objects.hash(typeName, esType, size, isInteger, isRational, docValues); } - /** - * Creates returns DataType enum corresponding to the specified es type - */ - public static DataType fromTypeName(String esType) { - String uppercase = esType.toUpperCase(Locale.ROOT); - if (uppercase.equals("DATE")) { - return DataType.DATETIME; + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; } - try { - return DataType.valueOf(uppercase); - } catch (IllegalArgumentException ex) { - return DataType.UNSUPPORTED; + + if (obj == null || getClass() != obj.getClass()) { + return false; } + + DataType other = (DataType) obj; + return Objects.equals(typeName, other.typeName) + && Objects.equals(esType, other.esType) + && size == other.size + && isInteger == other.isInteger + && isRational == other.isRational + && docValues == other.docValues; } - public String format() { - - return isDateOrTimeBased() ? DateUtils.DATE_PARSE_FORMAT : null; - } - - /** - * Returns the appropriate NumberType enum corresponding to this es type - */ - public NumberType numberType() { - return NumberType.valueOf(esType.toUpperCase(Locale.ROOT)); + @Override + public String toString() { + return name; } -} +} \ No newline at end of file diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/DataTypeConversion.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/DataTypeConversion.java deleted file mode 100644 index e3f97fa7240e3..0000000000000 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/DataTypeConversion.java +++ /dev/null @@ -1,705 +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.ql.type; - -import org.elasticsearch.common.Booleans; -import org.elasticsearch.common.network.InetAddresses; -import org.elasticsearch.xpack.ql.QlIllegalArgumentException; - -import java.time.OffsetTime; -import java.time.ZonedDateTime; -import java.time.format.DateTimeParseException; -import java.util.Locale; -import java.util.function.DoubleFunction; -import java.util.function.Function; -import java.util.function.LongFunction; - -import static org.elasticsearch.xpack.ql.type.DataType.BOOLEAN; -import static org.elasticsearch.xpack.ql.type.DataType.DATE; -import static org.elasticsearch.xpack.ql.type.DataType.DATETIME; -import static org.elasticsearch.xpack.ql.type.DataType.LONG; -import static org.elasticsearch.xpack.ql.type.DataType.NULL; -import static org.elasticsearch.xpack.ql.type.DataType.TEXT; -import static org.elasticsearch.xpack.ql.type.DataType.TIME; - -/** - * Conversions from one Elasticsearch data type to another Elasticsearch data types. - *

- * This class throws {@link QlIllegalArgumentException} to differentiate between validation - * errors inside SQL as oppose to the rest of ES. - */ -public abstract class DataTypeConversion { - - /** - * Returns the type compatible with both left and right types - *

- * If one of the types is null - returns another type - * If both types are numeric - returns type with the highest precision int < long < float < double - * If one of the types is string and another numeric - returns numeric - */ - public static DataType commonType(DataType left, DataType right) { - if (left == right) { - return left; - } - if (left.isNull()) { - return right; - } - if (right.isNull()) { - return left; - } - if (left.isString() && right.isString()) { - if (left == TEXT) { - return TEXT; - } - return right; - } - if (left.isNumeric() && right.isNumeric()) { - // if one is int - if (left.isInteger()) { - // promote the highest int - if (right.isInteger()) { - return left.size() > right.size() ? left : right; - } - // promote the rational - return right; - } - // try the other side - if (right.isInteger()) { - return left; - } - // promote the highest rational - return left.size() > right.size() ? left : right; - } - if (left.isString()) { - if (right.isNumeric()) { - return right; - } - } - if (right.isString()) { - if (left.isNumeric()) { - return left; - } - } - - // interval and dates - if (left == DATE) { - if (right.isYearMonthInterval()) { - return left; - } - // promote - return DATETIME; - } - if (right == DATE) { - if (left.isYearMonthInterval()) { - return right; - } - // promote - return DATETIME; - } - if (left == TIME) { - if (right == DATE) { - return DATETIME; - } - if (right.isInterval()) { - return left; - } - } - if (right == TIME) { - if (left == DATE) { - return DATETIME; - } - if (left.isInterval()) { - return right; - } - } - if (left == DATETIME) { - if (right == DATE || right == TIME) { - return left; - } - if (right.isInterval()) { - return left; - } - } - if (right == DATETIME) { - if (left == DATE || left == TIME) { - return right; - } - if (left.isInterval()) { - return right; - } - } - // Interval * integer is a valid operation - if (left.isInterval()) { - if (right.isInteger()) { - return left; - } - } - if (right.isInterval()) { - if (left.isInteger()) { - return right; - } - } - if (left.isInterval()) { - // intervals widening - if (right.isInterval()) { - // null returned for incompatible intervals - return DataTypes.compatibleInterval(left, right); - } - } - - // none found - return null; - } - - /** - * Returns true if the from type can be converted to the to type, false - otherwise - */ - public static boolean canConvert(DataType from, DataType to) { - // Special handling for nulls and if conversion is not requires - if (from == to || from == NULL) { - return true; - } - // only primitives are supported so far - return from.isPrimitive() && to.isPrimitive() && conversion(from, to) != null; - } - - /** - * Get the conversion from one type to another. - */ - public static Conversion conversionFor(DataType from, DataType to) { - // Special handling for nulls and if conversion is not requires - if (from == to) { - return Conversion.IDENTITY; - } - if (to == NULL || from == NULL) { - return Conversion.NULL; - } - if (from == NULL) { - return Conversion.NULL; - } - - Conversion conversion = conversion(from, to); - if (conversion == null) { - throw new QlIllegalArgumentException("cannot convert from [" + from.typeName() + "] to [" + to.typeName() + "]"); - } - return conversion; - } - - private static Conversion conversion(DataType from, DataType to) { - switch (to) { - case KEYWORD: - case TEXT: - return conversionToString(from); - case IP: - return conversionToIp(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 TIME: - return conversionToTime(from); - case DATETIME: - return conversionToDateTime(from); - case BOOLEAN: - return conversionToBoolean(from); - default: - return null; - } - - } - - private static Conversion conversionToString(DataType from) { - if (from == DATE) { - return Conversion.DATE_TO_STRING; - } - if (from == TIME) { - return Conversion.TIME_TO_STRING; - } - if (from == DATETIME) { - return Conversion.DATETIME_TO_STRING; - } - return Conversion.OTHER_TO_STRING; - } - - private static Conversion conversionToIp(DataType from) { - if (from.isString()) { - return Conversion.STRING_TO_IP; - } - return null; - } - - private static Conversion conversionToLong(DataType from) { - if (from.isRational()) { - return Conversion.RATIONAL_TO_LONG; - } - if (from.isInteger()) { - return Conversion.INTEGER_TO_LONG; - } - if (from == BOOLEAN) { - return Conversion.BOOL_TO_LONG; - } - if (from.isString()) { - return Conversion.STRING_TO_LONG; - } - if (from == DATE) { - return Conversion.DATE_TO_LONG; - } - if (from == TIME) { - return Conversion.TIME_TO_LONG; - } - if (from == DATETIME) { - return Conversion.DATETIME_TO_LONG; - } - return null; - } - - private static Conversion conversionToInt(DataType from) { - if (from.isRational()) { - return Conversion.RATIONAL_TO_INT; - } - if (from.isInteger()) { - return Conversion.INTEGER_TO_INT; - } - if (from == BOOLEAN) { - return Conversion.BOOL_TO_INT; - } - if (from.isString()) { - return Conversion.STRING_TO_INT; - } - if (from == DATE) { - return Conversion.DATE_TO_INT; - } - if (from == TIME) { - return Conversion.TIME_TO_INT; - } - if (from == DATETIME) { - return Conversion.DATETIME_TO_INT; - } - return null; - } - - private static Conversion conversionToShort(DataType from) { - if (from.isRational()) { - return Conversion.RATIONAL_TO_SHORT; - } - if (from.isInteger()) { - return Conversion.INTEGER_TO_SHORT; - } - if (from == BOOLEAN) { - return Conversion.BOOL_TO_SHORT; - } - if (from.isString()) { - return Conversion.STRING_TO_SHORT; - } - if (from == DATE) { - return Conversion.DATE_TO_SHORT; - } - if (from == TIME) { - return Conversion.TIME_TO_SHORT; - } - if (from == DATETIME) { - return Conversion.DATETIME_TO_SHORT; - } - return null; - } - - private static Conversion conversionToByte(DataType from) { - if (from.isRational()) { - return Conversion.RATIONAL_TO_BYTE; - } - if (from.isInteger()) { - return Conversion.INTEGER_TO_BYTE; - } - if (from == BOOLEAN) { - return Conversion.BOOL_TO_BYTE; - } - if (from.isString()) { - return Conversion.STRING_TO_BYTE; - } - if (from == DATE) { - return Conversion.DATE_TO_BYTE; - } - if (from == TIME) { - return Conversion.TIME_TO_BYTE; - } - if (from == DATETIME) { - return Conversion.DATETIME_TO_BYTE; - } - return null; - } - - private static Conversion conversionToFloat(DataType from) { - if (from.isRational()) { - return Conversion.RATIONAL_TO_FLOAT; - } - if (from.isInteger()) { - return Conversion.INTEGER_TO_FLOAT; - } - if (from == BOOLEAN) { - return Conversion.BOOL_TO_FLOAT; - } - if (from.isString()) { - return Conversion.STRING_TO_FLOAT; - } - if (from == DATE) { - return Conversion.DATE_TO_FLOAT; - } - if (from == TIME) { - return Conversion.TIME_TO_FLOAT; - } - if (from == DATETIME) { - return Conversion.DATETIME_TO_FLOAT; - } - return null; - } - - private static Conversion conversionToDouble(DataType from) { - if (from.isRational()) { - return Conversion.RATIONAL_TO_DOUBLE; - } - if (from.isInteger()) { - return Conversion.INTEGER_TO_DOUBLE; - } - if (from == BOOLEAN) { - return Conversion.BOOL_TO_DOUBLE; - } - if (from.isString()) { - return Conversion.STRING_TO_DOUBLE; - } - if (from == DATE) { - return Conversion.DATE_TO_DOUBLE; - } - if (from == TIME) { - return Conversion.TIME_TO_DOUBLE; - } - if (from == DATETIME) { - return Conversion.DATETIME_TO_DOUBLE; - } - return null; - } - - private static Conversion conversionToDate(DataType from) { - if (from.isRational()) { - return Conversion.RATIONAL_TO_DATE; - } - if (from.isInteger()) { - return Conversion.INTEGER_TO_DATE; - } - if (from == BOOLEAN) { - return Conversion.BOOL_TO_DATE; // We emit an int here which is ok because of Java's casting rules - } - if (from.isString()) { - return Conversion.STRING_TO_DATE; - } - if (from == DATETIME) { - return Conversion.DATETIME_TO_DATE; - } - return null; - } - - private static Conversion conversionToTime(DataType from) { - if (from.isRational()) { - return Conversion.RATIONAL_TO_TIME; - } - if (from.isInteger()) { - return Conversion.INTEGER_TO_TIME; - } - if (from == BOOLEAN) { - return Conversion.BOOL_TO_TIME; // We emit an int here which is ok because of Java's casting rules - } - if (from.isString()) { - return Conversion.STRING_TO_TIME; - } - if (from == DATE) { - return Conversion.DATE_TO_TIME; - } - if (from == DATETIME) { - return Conversion.DATETIME_TO_TIME; - } - return null; - } - - private static Conversion conversionToDateTime(DataType from) { - if (from.isRational()) { - return Conversion.RATIONAL_TO_DATETIME; - } - if (from.isInteger()) { - return Conversion.INTEGER_TO_DATETIME; - } - if (from == BOOLEAN) { - return Conversion.BOOL_TO_DATETIME; // We emit an int here which is ok because of Java's casting rules - } - if (from.isString()) { - return Conversion.STRING_TO_DATETIME; - } - if (from == DATE) { - return Conversion.DATE_TO_DATETIME; - } - return null; - } - - private static Conversion conversionToBoolean(DataType from) { - if (from.isNumeric()) { - return Conversion.NUMERIC_TO_BOOLEAN; - } - if (from.isString()) { - return Conversion.STRING_TO_BOOLEAN; - } - if (from == DATE) { - return Conversion.DATE_TO_BOOLEAN; - } - if (from == TIME) { - return Conversion.TIME_TO_BOOLEAN; - } - if (from == DATETIME) { - return Conversion.DATETIME_TO_BOOLEAN; - } - return null; - } - - public static byte safeToByte(long x) { - if (x > Byte.MAX_VALUE || x < Byte.MIN_VALUE) { - throw new QlIllegalArgumentException("[" + x + "] out of [byte] range"); - } - return (byte) x; - } - - public static short safeToShort(long x) { - if (x > Short.MAX_VALUE || x < Short.MIN_VALUE) { - throw new QlIllegalArgumentException("[" + x + "] out of [short] range"); - } - return (short) x; - } - - public static int safeToInt(long x) { - if (x > Integer.MAX_VALUE || x < Integer.MIN_VALUE) { - throw new QlIllegalArgumentException("[" + x + "] out of [integer] range"); - } - return (int) x; - } - - public static long safeToLong(double x) { - if (x > Long.MAX_VALUE || x < Long.MIN_VALUE) { - throw new QlIllegalArgumentException("[" + x + "] out of [long] range"); - } - return Math.round(x); - } - - public static Number toInteger(double x, DataType dataType) { - long l = safeToLong(x); - - switch (dataType) { - case BYTE: - return safeToByte(l); - case SHORT: - return safeToShort(l); - case INTEGER: - return safeToInt(l); - default: - return l; - } - } - - public static boolean convertToBoolean(String val) { - String lowVal = val.toLowerCase(Locale.ROOT); - if (Booleans.isBoolean(lowVal) == false) { - throw new QlIllegalArgumentException("cannot cast [" + val + "] to [boolean]"); - } - return Booleans.parseBoolean(lowVal); - } - - /** - * Converts arbitrary object to the desired data type. - *

- * Throws QlIllegalArgumentException if such conversion is not possible - */ - public static Object convert(Object value, DataType dataType) { - DataType detectedType = DataTypes.fromJava(value); - if (detectedType == dataType || value == null) { - return value; - } - return conversionFor(detectedType, dataType).convert(value); - } - - /** - * Reference to a data type conversion that can be serialized. Note that the position in the enum - * is important because it is used for serialization. - */ - public enum Conversion { - IDENTITY(Function.identity()), - NULL(value -> null), - - DATE_TO_STRING(o -> DateUtils.toDateString((ZonedDateTime) o)), - TIME_TO_STRING(o -> DateUtils.toTimeString((OffsetTime) o)), - DATETIME_TO_STRING(o -> DateUtils.toString((ZonedDateTime) o)), - OTHER_TO_STRING(String::valueOf), - - RATIONAL_TO_LONG(fromDouble(DataTypeConversion::safeToLong)), - INTEGER_TO_LONG(fromLong(value -> value)), - STRING_TO_LONG(fromString(Long::valueOf, "long")), - DATE_TO_LONG(fromDateTime(value -> value)), - TIME_TO_LONG(fromTime(value -> value)), - DATETIME_TO_LONG(fromDateTime(value -> value)), - - RATIONAL_TO_INT(fromDouble(value -> safeToInt(safeToLong(value)))), - INTEGER_TO_INT(fromLong(DataTypeConversion::safeToInt)), - BOOL_TO_INT(fromBool(value -> value ? 1 : 0)), - STRING_TO_INT(fromString(Integer::valueOf, "integer")), - DATE_TO_INT(fromDateTime(DataTypeConversion::safeToInt)), - TIME_TO_INT(fromTime(DataTypeConversion::safeToInt)), - DATETIME_TO_INT(fromDateTime(DataTypeConversion::safeToInt)), - - RATIONAL_TO_SHORT(fromDouble(value -> safeToShort(safeToLong(value)))), - INTEGER_TO_SHORT(fromLong(DataTypeConversion::safeToShort)), - BOOL_TO_SHORT(fromBool(value -> value ? (short) 1 : (short) 0)), - STRING_TO_SHORT(fromString(Short::valueOf, "short")), - DATE_TO_SHORT(fromDateTime(DataTypeConversion::safeToShort)), - TIME_TO_SHORT(fromTime(DataTypeConversion::safeToShort)), - DATETIME_TO_SHORT(fromDateTime(DataTypeConversion::safeToShort)), - - RATIONAL_TO_BYTE(fromDouble(value -> safeToByte(safeToLong(value)))), - INTEGER_TO_BYTE(fromLong(DataTypeConversion::safeToByte)), - BOOL_TO_BYTE(fromBool(value -> value ? (byte) 1 : (byte) 0)), - STRING_TO_BYTE(fromString(Byte::valueOf, "byte")), - DATE_TO_BYTE(fromDateTime(DataTypeConversion::safeToByte)), - TIME_TO_BYTE(fromTime(DataTypeConversion::safeToByte)), - DATETIME_TO_BYTE(fromDateTime(DataTypeConversion::safeToByte)), - - // TODO floating point conversions are lossy but conversions to integer conversions are not. Are we ok with that? - RATIONAL_TO_FLOAT(fromDouble(value -> (float) value)), - INTEGER_TO_FLOAT(fromLong(value -> (float) value)), - BOOL_TO_FLOAT(fromBool(value -> value ? 1f : 0f)), - STRING_TO_FLOAT(fromString(Float::valueOf, "float")), - DATE_TO_FLOAT(fromDateTime(value -> (float) value)), - TIME_TO_FLOAT(fromTime(value -> (float) value)), - DATETIME_TO_FLOAT(fromDateTime(value -> (float) value)), - - RATIONAL_TO_DOUBLE(fromDouble(Double::valueOf)), - INTEGER_TO_DOUBLE(fromLong(Double::valueOf)), - BOOL_TO_DOUBLE(fromBool(value -> value ? 1d : 0d)), - STRING_TO_DOUBLE(fromString(Double::valueOf, "double")), - DATE_TO_DOUBLE(fromDateTime(Double::valueOf)), - TIME_TO_DOUBLE(fromTime(Double::valueOf)), - DATETIME_TO_DOUBLE(fromDateTime(Double::valueOf)), - - RATIONAL_TO_DATE(toDate(RATIONAL_TO_LONG)), - INTEGER_TO_DATE(toDate(INTEGER_TO_LONG)), - BOOL_TO_DATE(toDate(BOOL_TO_INT)), - STRING_TO_DATE(fromString(DateUtils::asDateOnly, "date")), - DATETIME_TO_DATE(fromDatetimeToDate()), - - RATIONAL_TO_TIME(toTime(RATIONAL_TO_LONG)), - INTEGER_TO_TIME(toTime(INTEGER_TO_LONG)), - BOOL_TO_TIME(toTime(BOOL_TO_INT)), - STRING_TO_TIME(fromString(DateUtils::asTimeOnly, "time")), - DATE_TO_TIME(fromDatetimeToTime()), - DATETIME_TO_TIME(fromDatetimeToTime()), - - RATIONAL_TO_DATETIME(toDateTime(RATIONAL_TO_LONG)), - INTEGER_TO_DATETIME(toDateTime(INTEGER_TO_LONG)), - BOOL_TO_DATETIME(toDateTime(BOOL_TO_INT)), - STRING_TO_DATETIME(fromString(DateUtils::asDateTime, "datetime")), - DATE_TO_DATETIME(value -> value), - - NUMERIC_TO_BOOLEAN(fromLong(value -> value != 0)), - STRING_TO_BOOLEAN(fromString(DataTypeConversion::convertToBoolean, "boolean")), - DATE_TO_BOOLEAN(fromDateTime(value -> value != 0)), - TIME_TO_BOOLEAN(fromTime(value -> value != 0)), - DATETIME_TO_BOOLEAN(fromDateTime(value -> value != 0)), - - BOOL_TO_LONG(fromBool(value -> value ? 1L : 0L)), - - STRING_TO_IP(o -> { - if (!InetAddresses.isInetAddress(o.toString())) { - throw new QlIllegalArgumentException("[" + o + "] is not a valid IPv4 or IPv6 address"); - } - return o; - }); - - private final Function converter; - - Conversion(Function converter) { - this.converter = converter; - } - - private static Function fromDouble(DoubleFunction converter) { - return (Object l) -> converter.apply(((Number) l).doubleValue()); - } - - private static Function fromLong(LongFunction converter) { - return (Object l) -> converter.apply(((Number) l).longValue()); - } - - private static Function fromString(Function converter, String to) { - return (Object value) -> { - try { - return converter.apply(value.toString()); - } catch (NumberFormatException e) { - throw new QlIllegalArgumentException(e, "cannot cast [{}] to [{}]", value, to); - } catch (DateTimeParseException | IllegalArgumentException e) { - throw new QlIllegalArgumentException(e, "cannot cast [{}] to [{}]: {}", value, to, e.getMessage()); - } - }; - } - - private static Function fromBool(Function converter) { - return (Object l) -> converter.apply(((Boolean) l)); - } - - private static Function fromTime(Function converter) { - return l -> converter.apply(((OffsetTime) l).atDate(DateUtils.EPOCH).toInstant().toEpochMilli()); - } - - private static Function fromDateTime(Function converter) { - return l -> converter.apply(((ZonedDateTime) l).toInstant().toEpochMilli()); - } - - private static Function toDate(Conversion conversion) { - return l -> DateUtils.asDateOnly(((Number) conversion.convert(l)).longValue()); - } - - private static Function toTime(Conversion conversion) { - return l -> DateUtils.asTimeOnly(((Number) conversion.convert(l)).longValue()); - } - - private static Function toDateTime(Conversion conversion) { - return l -> DateUtils.asDateTime(((Number) conversion.convert(l)).longValue()); - } - - private static Function fromDatetimeToDate() { - return l -> DateUtils.asDateOnly((ZonedDateTime) l); - } - - private static Function fromDatetimeToTime() { - return l -> ((ZonedDateTime) l).toOffsetDateTime().toOffsetTime(); - } - - public Object convert(Object l) { - if (l == null) { - return null; - } - return converter.apply(l); - } - } - - public static DataType asInteger(DataType dataType) { - if (!dataType.isNumeric()) { - return dataType; - } - - return dataType.isInteger() ? dataType : LONG; - } -} diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/DataTypeConverter.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/DataTypeConverter.java new file mode 100644 index 0000000000000..5400659c75ab4 --- /dev/null +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/DataTypeConverter.java @@ -0,0 +1,519 @@ +/* + * 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.ql.type; + +import org.elasticsearch.common.Booleans; +import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.common.io.stream.StreamOutput; +import org.elasticsearch.common.network.InetAddresses; +import org.elasticsearch.xpack.ql.QlIllegalArgumentException; + +import java.io.IOException; +import java.time.ZonedDateTime; +import java.time.format.DateTimeParseException; +import java.util.Locale; +import java.util.function.DoubleFunction; +import java.util.function.Function; +import java.util.function.LongFunction; + +import static org.elasticsearch.xpack.ql.type.DataTypes.BOOLEAN; +import static org.elasticsearch.xpack.ql.type.DataTypes.BYTE; +import static org.elasticsearch.xpack.ql.type.DataTypes.DATETIME; +import static org.elasticsearch.xpack.ql.type.DataTypes.DOUBLE; +import static org.elasticsearch.xpack.ql.type.DataTypes.FLOAT; +import static org.elasticsearch.xpack.ql.type.DataTypes.INTEGER; +import static org.elasticsearch.xpack.ql.type.DataTypes.IP; +import static org.elasticsearch.xpack.ql.type.DataTypes.KEYWORD; +import static org.elasticsearch.xpack.ql.type.DataTypes.LONG; +import static org.elasticsearch.xpack.ql.type.DataTypes.NULL; +import static org.elasticsearch.xpack.ql.type.DataTypes.SHORT; +import static org.elasticsearch.xpack.ql.type.DataTypes.TEXT; +import static org.elasticsearch.xpack.ql.type.DataTypes.isPrimitive; +import static org.elasticsearch.xpack.ql.type.DataTypes.isString; + +/** + * Conversion utility from one Elasticsearch data type to another Elasticsearch data types. + */ +public final class DataTypeConverter { + + private DataTypeConverter() {} + + /** + * Returns the type compatible with both left and right types + *

+ * If one of the types is null - returns another type + * If both types are numeric - returns type with the highest precision int < long < float < double + * If one of the types is string and another numeric - returns numeric + */ + public static DataType commonType(DataType left, DataType right) { + if (left == right) { + return left; + } + if (left == NULL) { + return right; + } + if (right == NULL) { + return left; + } + if (isString(left) && isString(right)) { + if (left == TEXT) { + return TEXT; + } + return right; + } + if (left.isNumeric() && right.isNumeric()) { + // if one is int + if (left.isInteger()) { + // promote the highest int + if (right.isInteger()) { + return left.size() > right.size() ? left : right; + } + // promote the rational + return right; + } + // try the other side + if (right.isInteger()) { + return left; + } + // promote the highest rational + return left.size() > right.size() ? left : right; + } + if (isString(left)) { + if (right.isNumeric()) { + return right; + } + } + if (isString(right)) { + if (left.isNumeric()) { + return left; + } + } + + // none found + return null; + } + + /** + * Returns true if the from type can be converted to the to type, false - otherwise + */ + public static boolean canConvert(DataType from, DataType to) { + // Special handling for nulls and if conversion is not requires + if (from == to || from == NULL) { + return true; + } + // only primitives are supported so far + return isPrimitive(from) && isPrimitive(to) && converterFor(from, to) != null; + } + + /** + * Get the conversion from one type to another. + */ + public static Converter converterFor(DataType from, DataType to) { + // Special handling for nulls and if conversion is not requires + if (from == to) { + return DefaultConverter.IDENTITY; + } + if (to == NULL || from == NULL) { + return DefaultConverter.TO_NULL; + } + // proper converters + if (to == KEYWORD || to == TEXT) { + return conversionToString(from); + } + if (to == LONG) { + return conversionToLong(from); + } + if (to == INTEGER) { + return conversionToInt(from); + } + if (to == SHORT) { + return conversionToShort(from); + } + if (to == BYTE) { + return conversionToByte(from); + } + if (to == FLOAT) { + return conversionToFloat(from); + } + if (to == DOUBLE) { + return conversionToDouble(from); + } + if (to == DATETIME) { + return conversionToDateTime(from); + } + if (to == BOOLEAN) { + return conversionToBoolean(from); + } + if (to == IP) { + return conversionToIp(from); + } + return null; + } + + private static Converter conversionToString(DataType from) { + if (from == DATETIME) { + return DefaultConverter.DATETIME_TO_STRING; + } + return DefaultConverter.OTHER_TO_STRING; + } + + private static Converter conversionToIp(DataType from) { + if (isString(from)) { + return DefaultConverter.STRING_TO_IP; + } + return null; + } + + private static Converter conversionToLong(DataType from) { + if (from.isRational()) { + return DefaultConverter.RATIONAL_TO_LONG; + } + if (from.isInteger()) { + return DefaultConverter.INTEGER_TO_LONG; + } + if (from == BOOLEAN) { + return DefaultConverter.BOOL_TO_LONG; + } + if (isString(from)) { + return DefaultConverter.STRING_TO_LONG; + } + if (from == DATETIME) { + return DefaultConverter.DATETIME_TO_LONG; + } + return null; + } + + private static Converter conversionToInt(DataType from) { + if (from.isRational()) { + return DefaultConverter.RATIONAL_TO_INT; + } + if (from.isInteger()) { + return DefaultConverter.INTEGER_TO_INT; + } + if (from == BOOLEAN) { + return DefaultConverter.BOOL_TO_INT; + } + if (isString(from)) { + return DefaultConverter.STRING_TO_INT; + } + if (from == DATETIME) { + return DefaultConverter.DATETIME_TO_INT; + } + return null; + } + + private static Converter conversionToShort(DataType from) { + if (from.isRational()) { + return DefaultConverter.RATIONAL_TO_SHORT; + } + if (from.isInteger()) { + return DefaultConverter.INTEGER_TO_SHORT; + } + if (from == BOOLEAN) { + return DefaultConverter.BOOL_TO_SHORT; + } + if (isString(from)) { + return DefaultConverter.STRING_TO_SHORT; + } + if (from == DATETIME) { + return DefaultConverter.DATETIME_TO_SHORT; + } + return null; + } + + private static Converter conversionToByte(DataType from) { + if (from.isRational()) { + return DefaultConverter.RATIONAL_TO_BYTE; + } + if (from.isInteger()) { + return DefaultConverter.INTEGER_TO_BYTE; + } + if (from == BOOLEAN) { + return DefaultConverter.BOOL_TO_BYTE; + } + if (isString(from)) { + return DefaultConverter.STRING_TO_BYTE; + } + if (from == DATETIME) { + return DefaultConverter.DATETIME_TO_BYTE; + } + return null; + } + + private static DefaultConverter conversionToFloat(DataType from) { + if (from.isRational()) { + return DefaultConverter.RATIONAL_TO_FLOAT; + } + if (from.isInteger()) { + return DefaultConverter.INTEGER_TO_FLOAT; + } + if (from == BOOLEAN) { + return DefaultConverter.BOOL_TO_FLOAT; + } + if (isString(from)) { + return DefaultConverter.STRING_TO_FLOAT; + } + if (from == DATETIME) { + return DefaultConverter.DATETIME_TO_FLOAT; + } + return null; + } + + private static DefaultConverter conversionToDouble(DataType from) { + if (from.isRational()) { + return DefaultConverter.RATIONAL_TO_DOUBLE; + } + if (from.isInteger()) { + return DefaultConverter.INTEGER_TO_DOUBLE; + } + if (from == BOOLEAN) { + return DefaultConverter.BOOL_TO_DOUBLE; + } + if (isString(from)) { + return DefaultConverter.STRING_TO_DOUBLE; + } + if (from == DATETIME) { + return DefaultConverter.DATETIME_TO_DOUBLE; + } + return null; + } + + private static DefaultConverter conversionToDateTime(DataType from) { + if (from.isRational()) { + return DefaultConverter.RATIONAL_TO_DATETIME; + } + if (from.isInteger()) { + return DefaultConverter.INTEGER_TO_DATETIME; + } + if (from == BOOLEAN) { + return DefaultConverter.BOOL_TO_DATETIME; // We emit an int here which is ok because of Java's casting rules + } + if (isString(from)) { + return DefaultConverter.STRING_TO_DATETIME; + } + return null; + } + + private static DefaultConverter conversionToBoolean(DataType from) { + if (from.isNumeric()) { + return DefaultConverter.NUMERIC_TO_BOOLEAN; + } + if (isString(from)) { + return DefaultConverter.STRING_TO_BOOLEAN; + } + if (from == DATETIME) { + return DefaultConverter.DATETIME_TO_BOOLEAN; + } + return null; + } + + public static byte safeToByte(long x) { + if (x > Byte.MAX_VALUE || x < Byte.MIN_VALUE) { + throw new QlIllegalArgumentException("[" + x + "] out of [byte] range"); + } + return (byte) x; + } + + public static short safeToShort(long x) { + if (x > Short.MAX_VALUE || x < Short.MIN_VALUE) { + throw new QlIllegalArgumentException("[" + x + "] out of [short] range"); + } + return (short) x; + } + + public static int safeToInt(long x) { + if (x > Integer.MAX_VALUE || x < Integer.MIN_VALUE) { + throw new QlIllegalArgumentException("[" + x + "] out of [integer] range"); + } + return (int) x; + } + + public static long safeToLong(double x) { + if (x > Long.MAX_VALUE || x < Long.MIN_VALUE) { + throw new QlIllegalArgumentException("[" + x + "] out of [long] range"); + } + return Math.round(x); + } + + public static Number toInteger(double x, DataType dataType) { + long l = safeToLong(x); + + if (dataType == BYTE) { + return safeToByte(l); + } + if (dataType == SHORT) { + return safeToShort(l); + } + if (dataType == INTEGER) { + return safeToInt(l); + } + return l; + } + + public static boolean convertToBoolean(String val) { + String lowVal = val.toLowerCase(Locale.ROOT); + if (Booleans.isBoolean(lowVal) == false) { + throw new QlIllegalArgumentException("cannot cast [" + val + "] to [boolean]"); + } + return Booleans.parseBoolean(lowVal); + } + + /** + * Converts arbitrary object to the desired data type. + *

+ * Throws QlIllegalArgumentException if such conversion is not possible + */ + public static Object convert(Object value, DataType dataType) { + DataType detectedType = DataTypes.fromJava(value); + if (detectedType == dataType || value == null) { + return value; + } + Converter converter = converterFor(detectedType, dataType); + + if (converter == null) { + throw new QlIllegalArgumentException("cannot convert from [{}], type [{}] to [{}]", value, detectedType.typeName(), + dataType.typeName()); + } + + return converter.convert(value); + } + + /** + * Reference to a data type conversion that can be serialized. Note that the position in the enum + * is important because it is used for serialization. + */ + public enum DefaultConverter implements Converter { + IDENTITY(Function.identity()), + TO_NULL(value -> null), + + DATETIME_TO_STRING(o -> DateUtils.toString((ZonedDateTime) o)), + OTHER_TO_STRING(String::valueOf), + + RATIONAL_TO_LONG(fromDouble(DataTypeConverter::safeToLong)), + INTEGER_TO_LONG(fromLong(value -> value)), + STRING_TO_LONG(fromString(Long::valueOf, "long")), + DATETIME_TO_LONG(fromDateTime(value -> value)), + + RATIONAL_TO_INT(fromDouble(value -> safeToInt(safeToLong(value)))), + INTEGER_TO_INT(fromLong(DataTypeConverter::safeToInt)), + BOOL_TO_INT(fromBool(value -> value ? 1 : 0)), + STRING_TO_INT(fromString(Integer::valueOf, "integer")), + DATETIME_TO_INT(fromDateTime(DataTypeConverter::safeToInt)), + + RATIONAL_TO_SHORT(fromDouble(value -> safeToShort(safeToLong(value)))), + INTEGER_TO_SHORT(fromLong(DataTypeConverter::safeToShort)), + BOOL_TO_SHORT(fromBool(value -> value ? (short) 1 : (short) 0)), + STRING_TO_SHORT(fromString(Short::valueOf, "short")), + DATETIME_TO_SHORT(fromDateTime(DataTypeConverter::safeToShort)), + + RATIONAL_TO_BYTE(fromDouble(value -> safeToByte(safeToLong(value)))), + INTEGER_TO_BYTE(fromLong(DataTypeConverter::safeToByte)), + BOOL_TO_BYTE(fromBool(value -> value ? (byte) 1 : (byte) 0)), + STRING_TO_BYTE(fromString(Byte::valueOf, "byte")), + DATETIME_TO_BYTE(fromDateTime(DataTypeConverter::safeToByte)), + + // TODO floating point conversions are lossy but conversions to integer conversions are not. Are we ok with that? + RATIONAL_TO_FLOAT(fromDouble(value -> (float) value)), + INTEGER_TO_FLOAT(fromLong(value -> (float) value)), + BOOL_TO_FLOAT(fromBool(value -> value ? 1f : 0f)), + STRING_TO_FLOAT(fromString(Float::valueOf, "float")), + DATETIME_TO_FLOAT(fromDateTime(value -> (float) value)), + + RATIONAL_TO_DOUBLE(fromDouble(Double::valueOf)), + INTEGER_TO_DOUBLE(fromLong(Double::valueOf)), + BOOL_TO_DOUBLE(fromBool(value -> value ? 1d : 0d)), + STRING_TO_DOUBLE(fromString(Double::valueOf, "double")), + DATETIME_TO_DOUBLE(fromDateTime(Double::valueOf)), + + RATIONAL_TO_DATETIME(toDateTime(RATIONAL_TO_LONG)), + INTEGER_TO_DATETIME(toDateTime(INTEGER_TO_LONG)), + BOOL_TO_DATETIME(toDateTime(BOOL_TO_INT)), + STRING_TO_DATETIME(fromString(DateUtils::asDateTime, "datetime")), + + NUMERIC_TO_BOOLEAN(fromLong(value -> value != 0)), + STRING_TO_BOOLEAN(fromString(DataTypeConverter::convertToBoolean, "boolean")), + DATETIME_TO_BOOLEAN(fromDateTime(value -> value != 0)), + + BOOL_TO_LONG(fromBool(value -> value ? 1L : 0L)), + + STRING_TO_IP(o -> { + if (!InetAddresses.isInetAddress(o.toString())) { + throw new QlIllegalArgumentException("[" + o + "] is not a valid IPv4 or IPv6 address"); + } + return o; + }); + + public static final String NAME = "dtc-def"; + + private final Function converter; + + DefaultConverter(Function converter) { + this.converter = converter; + } + + private static Function fromDouble(DoubleFunction converter) { + return (Object l) -> converter.apply(((Number) l).doubleValue()); + } + + private static Function fromLong(LongFunction converter) { + return (Object l) -> converter.apply(((Number) l).longValue()); + } + + private static Function fromString(Function converter, String to) { + return (Object value) -> { + try { + return converter.apply(value.toString()); + } catch (NumberFormatException e) { + throw new QlIllegalArgumentException(e, "cannot cast [{}] to [{}]", value, to); + } catch (DateTimeParseException | IllegalArgumentException e) { + throw new QlIllegalArgumentException(e, "cannot cast [{}] to [{}]: {}", value, to, e.getMessage()); + } + }; + } + + private static Function fromBool(Function converter) { + return (Object l) -> converter.apply(((Boolean) l)); + } + + private static Function fromDateTime(Function converter) { + return l -> converter.apply(((ZonedDateTime) l).toInstant().toEpochMilli()); + } + + private static Function toDateTime(Converter conversion) { + return l -> DateUtils.asDateTime(((Number) conversion.convert(l)).longValue()); + } + + @Override + public Object convert(Object l) { + if (l == null) { + return null; + } + return converter.apply(l); + } + + @Override + public String getWriteableName() { + return NAME; + } + + @Override + public void writeTo(StreamOutput out) throws IOException { + out.writeEnum(this); + } + + public static Converter read(StreamInput in) throws IOException { + return in.readEnum(DefaultConverter.class); + } + } + + public static DataType asInteger(DataType dataType) { + if (!dataType.isNumeric()) { + return dataType; + } + + return dataType.isInteger() ? dataType : LONG; + } +} \ No newline at end of file diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/DataTypeRegistry.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/DataTypeRegistry.java new file mode 100644 index 0000000000000..714eef3586362 --- /dev/null +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/DataTypeRegistry.java @@ -0,0 +1,35 @@ +/* + * 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.ql.type; + +import java.util.Collection; + +/** + * Central class for {@link DataType} creation and conversion. + */ +public interface DataTypeRegistry { + + // + // Discovery + // + Collection dataTypes(); + + DataType fromEs(String typeName); + + DataType fromJava(Object value); + + boolean isUnsupported(DataType type); + + // + // Conversion methods + // + boolean canConvert(DataType from, DataType to); + + Object convert(Object value, DataType type); + + DataType commonType(DataType left, DataType right); +} diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/DataTypes.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/DataTypes.java index 24bb42ef54b77..0d7f338e89959 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/DataTypes.java +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/DataTypes.java @@ -5,34 +5,91 @@ */ package org.elasticsearch.xpack.ql.type; -import org.elasticsearch.xpack.ql.QlIllegalArgumentException; -import org.elasticsearch.xpack.ql.expression.function.scalar.geo.GeoShape; -import org.elasticsearch.xpack.ql.expression.literal.Interval; - -import java.time.OffsetTime; import java.time.ZonedDateTime; +import java.util.Arrays; +import java.util.Collection; +import java.util.Comparator; +import java.util.Locale; +import java.util.Map; -import static org.elasticsearch.xpack.ql.type.DataType.BOOLEAN; -import static org.elasticsearch.xpack.ql.type.DataType.BYTE; -import static org.elasticsearch.xpack.ql.type.DataType.DATETIME; -import static org.elasticsearch.xpack.ql.type.DataType.DOUBLE; -import static org.elasticsearch.xpack.ql.type.DataType.FLOAT; -import static org.elasticsearch.xpack.ql.type.DataType.INTEGER; -import static org.elasticsearch.xpack.ql.type.DataType.INTERVAL_YEAR_TO_MONTH; -import static org.elasticsearch.xpack.ql.type.DataType.KEYWORD; -import static org.elasticsearch.xpack.ql.type.DataType.LONG; -import static org.elasticsearch.xpack.ql.type.DataType.NULL; -import static org.elasticsearch.xpack.ql.type.DataType.SHORT; -import static org.elasticsearch.xpack.ql.type.DataType.TIME; -import static org.elasticsearch.xpack.ql.type.DataType.UNSUPPORTED; -import static org.elasticsearch.xpack.ql.type.DataType.fromTypeName; +import static java.util.stream.Collectors.toUnmodifiableList; +import static java.util.stream.Collectors.toUnmodifiableMap; public final class DataTypes { + // @formatter:off + public static final DataType UNSUPPORTED = new DataType("UNSUPPORTED", null, 0, false, false, false); + + public static final DataType NULL = new DataType("null", 0, false, false, false); + + public static final DataType BOOLEAN = new DataType("boolean", 1, false, false, false); + // integer numeric + public static final DataType BYTE = new DataType("byte", Byte.BYTES, true, false, true); + public static final DataType SHORT = new DataType("short", Short.BYTES, true, false, true); + public static final DataType INTEGER = new DataType("integer", Integer.BYTES, true, false, true); + public static final DataType LONG = new DataType("long", Long.BYTES, true, false, true); + // decimal numeric + public static final DataType DOUBLE = new DataType("double", Double.BYTES, false, true, true); + public static final DataType FLOAT = new DataType("float", Float.BYTES, false, true, true); + public static final DataType HALF_FLOAT = new DataType("half_float", Float.BYTES, false, true, true); + public static final DataType SCALED_FLOAT = new DataType("scaled_float", Long.BYTES, false, true, true); + // string + public static final DataType KEYWORD = new DataType("keyword", Integer.MAX_VALUE, false, false, true); + public static final DataType TEXT = new DataType("text", Integer.MAX_VALUE, false, false, false); + // date + public static final DataType DATETIME = new DataType("DATETIME", "date", Long.BYTES, false, false, true); + // ip + public static final DataType IP = new DataType("ip", 39, false, false, true); + // binary + public static final DataType BINARY = new DataType("binary", Integer.MAX_VALUE, false, false, true); + // complex types + public static final DataType OBJECT = new DataType("object", 0, false, false, false); + public static final DataType NESTED = new DataType("nested", 0, false, false, false); + //@formatter:on + + private static final Collection TYPES = Arrays.asList( + UNSUPPORTED, + NULL, + BOOLEAN, + BYTE, + SHORT, + INTEGER, + LONG, + DOUBLE, + FLOAT, + HALF_FLOAT, + SCALED_FLOAT, + KEYWORD, + TEXT, + DATETIME, + IP, + BINARY, + OBJECT, + NESTED) + .stream() + .sorted(Comparator.comparing(DataType::typeName)) + .collect(toUnmodifiableList()); + + private static final Map NAME_TO_TYPE = TYPES.stream() + .collect(toUnmodifiableMap(DataType::typeName, t -> t)); + + private static final Map ES_TO_TYPE = TYPES.stream() + .filter(e -> e.esType() != null) + .collect(toUnmodifiableMap(DataType::esType, t -> t)); + private DataTypes() {} - public static boolean isUnsupported(DataType from) { - return from == UNSUPPORTED; + public static Collection types() { + return TYPES; + } + + public static DataType fromTypeName(String name) { + return NAME_TO_TYPE.get(name.toLowerCase(Locale.ROOT)); + } + + public static DataType fromEs(String name) { + DataType type = ES_TO_TYPE.get(name); + return type != null ? type : UNSUPPORTED; } public static DataType fromJava(Object value) { @@ -60,160 +117,49 @@ public static DataType fromJava(Object value) { if (value instanceof Short) { return SHORT; } - if (value instanceof OffsetTime) { - return TIME; - } if (value instanceof ZonedDateTime) { return DATETIME; } if (value instanceof String || value instanceof Character) { return KEYWORD; } - if (value instanceof Interval) { - return ((Interval) value).dataType(); - } - if (value instanceof GeoShape) { - return DataType.GEO_SHAPE; - } - - throw new QlIllegalArgumentException("No idea what's the DataType for {}", value.getClass()); - } - // return the compatible interval between the two - it is assumed the types are intervals - // YEAR and MONTH -> YEAR_TO_MONTH - // DAY... SECOND -> DAY_TIME - // YEAR_MONTH and DAY_SECOND are NOT compatible - public static DataType compatibleInterval(DataType left, DataType right) { - if (left == right) { - return left; - } - if (left.isYearMonthInterval() && right.isYearMonthInterval()) { - // no need to look at YEAR/YEAR or MONTH/MONTH as these are equal and already handled - return INTERVAL_YEAR_TO_MONTH; - } - if (left.isDayTimeInterval() && right.isDayTimeInterval()) { - // to avoid specifying the combinations, extract the leading and trailing unit from the name - // D > H > S > M which is also the alphabetical order - String lName = left.name().substring(9); - String rName = right.name().substring(9); - - char leading = lName.charAt(0); - if (rName.charAt(0) < leading) { - leading = rName.charAt(0); - } - // look at the trailing unit - if (lName.length() > 6) { - int indexOf = lName.indexOf("_TO_"); - lName = lName.substring(indexOf + 4); - } - if (rName.length() > 6) { - int indexOf = rName.indexOf("_TO_"); - rName = rName.substring(indexOf + 4); - } - char trailing = lName.charAt(0); - if (rName.charAt(0) > trailing) { - trailing = rName.charAt(0); - } - - return fromTypeName("INTERVAL_" + intervalUnit(leading) + "_TO_" + intervalUnit(trailing)); - } return null; } - private static String intervalUnit(char unitChar) { - switch (unitChar) { - case 'D': - return "DAY"; - case 'H': - return "HOUR"; - case 'M': - return "MINUTE"; - case 'S': - return "SECOND"; - default: - throw new QlIllegalArgumentException("Unknown unit {}", unitChar); - } - } - - // - // Metadata methods, mainly for ODBC. - // As these are fairly obscure and limited in use, there is no point to promote them as a full type methods - // hence why they appear here as utility methods. - // - - // https://docs.microsoft.com/en-us/sql/relational-databases/native-client-odbc-date-time/metadata-catalog - // https://github.com/elastic/elasticsearch/issues/30386 - public static Integer metaSqlDataType(DataType t) { - if (t == DATETIME) { - // ODBC SQL_DATETME - return Integer.valueOf(9); - } - // this is safe since the vendor SQL types are short despite the return value - return t.sqlType().getVendorTypeNumber(); - } - - // https://github.com/elastic/elasticsearch/issues/30386 - // https://docs.microsoft.com/en-us/sql/odbc/reference/syntax/sqlgettypeinfo-function - public static Integer metaSqlDateTimeSub(DataType t) { - if (t == DATETIME) { - // ODBC SQL_CODE_TIMESTAMP - return Integer.valueOf(3); - } - // ODBC null - return 0; + public static boolean isUnsupported(DataType from) { + return from == UNSUPPORTED; } - public static Short metaSqlMinimumScale(DataType t) { - return metaSqlSameScale(t); + public static boolean isString(DataType t) { + return t == KEYWORD || t == TEXT; } - public static Short metaSqlMaximumScale(DataType t) { - return metaSqlSameScale(t); + public static boolean isPrimitive(DataType t) { + return t != OBJECT && t != NESTED && t != UNSUPPORTED; } - // https://docs.microsoft.com/en-us/sql/odbc/reference/appendixes/decimal-digits - // https://github.com/elastic/elasticsearch/issues/40357 - // since the scale is fixed, minimum and maximum should return the same value - // hence why this method exists - private static Short metaSqlSameScale(DataType t) { - // TODO: return info for SCALED_FLOATS (should be based on field not type) - if (t.isInteger()) { - return Short.valueOf((short) 0); - } - if (t.isDateBased() || t.isRational()) { - return Short.valueOf((short) t.defaultPrecision); - } - return null; + public static boolean isNull(DataType t) { + return t == NULL; } - // https://docs.microsoft.com/en-us/sql/odbc/reference/syntax/sqlgettypeinfo-function - public static Integer metaSqlRadix(DataType t) { - // RADIX - Determines how numbers returned by COLUMN_SIZE and DECIMAL_DIGITS should be interpreted. - // 10 means they represent the number of decimal digits allowed for the column. - // 2 means they represent the number of bits allowed for the column. - // null means radix is not applicable for the given type. - return t.isInteger() ? Integer.valueOf(10) : (t.isRational() ? Integer.valueOf(2) : null); + public static boolean isNullOrNumeric(DataType t) { + return t.isNumeric() || isNull(t); } - //https://docs.microsoft.com/en-us/sql/odbc/reference/syntax/sqlgettypeinfo-function#comments - //https://docs.microsoft.com/en-us/sql/odbc/reference/appendixes/column-size - public static Integer precision(DataType t) { - if (t.isNumeric()) { - return t.defaultPrecision; - } - return t.displaySize; + public static boolean isSigned(DataType t) { + return t.isNumeric(); } - public static boolean areTypesCompatible(DataType left, DataType right) { + public static boolean areCompatible(DataType left, DataType right) { if (left == right) { return true; } else { return - (left == DataType.NULL || right == DataType.NULL) - || (left.isString() && right.isString()) + (left == NULL || right == NULL) + || (isString(left) && isString(right)) || (left.isNumeric() && right.isNumeric()) - || (left.isDateBased() && right.isDateBased()) - || (left.isInterval() && right.isInterval() && compatibleInterval(left, right) != null); + || (left == DATETIME && right == DATETIME); } } -} +} \ No newline at end of file diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/DateEsField.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/DateEsField.java index 5186a2c2b5494..69d03c0b7bc6b 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/DateEsField.java +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/DateEsField.java @@ -13,6 +13,6 @@ public class DateEsField extends EsField { public DateEsField(String name, Map properties, boolean hasDocValues) { - super(name, DataType.DATETIME, properties, hasDocValues); + super(name, DataTypes.DATETIME, properties, hasDocValues); } } diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/DateUtils.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/DateUtils.java index 7e10560aa0330..f0204a9dbfb1f 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/DateUtils.java +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/DateUtils.java @@ -10,44 +10,18 @@ import org.elasticsearch.common.time.DateFormatters; import java.time.Instant; -import java.time.LocalDate; -import java.time.OffsetTime; import java.time.ZoneId; import java.time.ZonedDateTime; -import static java.time.format.DateTimeFormatter.ISO_LOCAL_DATE; -import static java.time.format.DateTimeFormatter.ISO_TIME; - -//FIXME: Taken from sql-proto. -//Ideally it should be shared but the dependencies across projects and and SQL-client make it tricky. -//Maybe a gradle task would fix that... +//NB: Taken from sql-proto. public final class DateUtils { public static final ZoneId UTC = ZoneId.of("Z"); - // In Java 8 LocalDate.EPOCH is not available, introduced with later Java versions - public static final LocalDate EPOCH = LocalDate.of(1970, 1, 1); - public static final long DAY_IN_MILLIS = 60 * 60 * 24 * 1000L; private static final DateFormatter UTC_DATE_TIME_FORMATTER = DateFormatter.forPattern("date_optional_time").withZone(UTC); - static final String DATE_PARSE_FORMAT = "epoch_millis"; - private DateUtils() {} - /** - * Creates an date for SQL DATE type from the millis since epoch. - */ - public static ZonedDateTime asDateOnly(long millis) { - return ZonedDateTime.ofInstant(Instant.ofEpochMilli(millis), UTC).toLocalDate().atStartOfDay(UTC); - } - - /** - * Creates an date for SQL TIME type from the millis since epoch. - */ - public static OffsetTime asTimeOnly(long millis) { - return OffsetTime.ofInstant(Instant.ofEpochMilli(millis % DAY_IN_MILLIS), UTC); - } - /** * Creates a datetime from the millis since epoch (thus the time-zone is UTC). */ @@ -55,21 +29,6 @@ public static ZonedDateTime asDateTime(long millis) { return ZonedDateTime.ofInstant(Instant.ofEpochMilli(millis), UTC); } - /** - * Parses the given string into a Date (SQL DATE type) using UTC as a default timezone. - */ - public static ZonedDateTime asDateOnly(String dateFormat) { - return LocalDate.parse(dateFormat, ISO_LOCAL_DATE).atStartOfDay(UTC); - } - - public static ZonedDateTime asDateOnly(ZonedDateTime zdt) { - return zdt.toLocalDate().atStartOfDay(zdt.getZone()); - } - - public static OffsetTime asTimeOnly(String timeFormat) { - return DateFormatters.from(ISO_TIME.parse(timeFormat)).toOffsetDateTime().toOffsetTime(); - } - /** * Parses the given string into a DateTime using UTC as a default timezone. */ @@ -80,12 +39,4 @@ public static ZonedDateTime asDateTime(String dateFormat) { public static String toString(ZonedDateTime dateTime) { return StringUtils.toString(dateTime); } - - public static String toDateString(ZonedDateTime date) { - return date.format(ISO_LOCAL_DATE); - } - - public static String toTimeString(OffsetTime time) { - return StringUtils.toString(time); - } } \ No newline at end of file diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/DefaultDataTypeRegistry.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/DefaultDataTypeRegistry.java new file mode 100644 index 0000000000000..4748e7f093ba5 --- /dev/null +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/DefaultDataTypeRegistry.java @@ -0,0 +1,51 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +package org.elasticsearch.xpack.ql.type; + +import java.util.Collection; + +public class DefaultDataTypeRegistry implements DataTypeRegistry { + + public static final DataTypeRegistry INSTANCE = new DefaultDataTypeRegistry(); + + private DefaultDataTypeRegistry() {} + + @Override + public Collection dataTypes() { + return DataTypes.types(); + } + + @Override + public DataType fromEs(String typeName) { + return DataTypes.fromEs(typeName); + } + + @Override + public DataType fromJava(Object value) { + return DataTypes.fromJava(value); + } + + @Override + public boolean isUnsupported(DataType type) { + return DataTypes.isUnsupported(type); + } + + @Override + public boolean canConvert(DataType from, DataType to) { + return DataTypeConverter.canConvert(from, to); + } + + @Override + public Object convert(Object value, DataType type) { + return DataTypeConverter.convert(value, type); + } + + @Override + public DataType commonType(DataType left, DataType right) { + return DataTypeConverter.commonType(left, right); + } +} \ No newline at end of file diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/EsField.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/EsField.java index 694c7c1c1b1cf..8c8cd4a153a22 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/EsField.java +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/EsField.java @@ -80,17 +80,6 @@ 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; - } - /** * Returns and {@link Exact} object with all the necessary info about the field: *

    @@ -104,7 +93,7 @@ public Exact getExactInfo() { @Override public String toString() { - return name + "@" + esDataType.name() + "=" + properties; + return name + "@" + esDataType.typeName() + "=" + properties; } @Override diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/InvalidMappedField.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/InvalidMappedField.java index 796fe4a37ef71..c69407a25598b 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/InvalidMappedField.java +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/InvalidMappedField.java @@ -21,7 +21,7 @@ public class InvalidMappedField extends EsField { private final String errorMessage; public InvalidMappedField(String name, String errorMessage) { - super(name, DataType.UNSUPPORTED, emptyMap(), false); + super(name, DataTypes.UNSUPPORTED, emptyMap(), false); this.errorMessage = errorMessage; } diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/KeywordEsField.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/KeywordEsField.java index 1ac4f26077770..78d84946da4c9 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/KeywordEsField.java +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/KeywordEsField.java @@ -9,6 +9,8 @@ import java.util.Map; import java.util.Objects; +import static org.elasticsearch.xpack.ql.type.DataTypes.KEYWORD; + /** * SQL-related information about an index field with keyword type */ @@ -18,7 +20,7 @@ public class KeywordEsField extends EsField { private final boolean normalized; public KeywordEsField(String name) { - this(name, Collections.emptyMap(), true, DataType.KEYWORD.defaultPrecision, false); + this(name, Collections.emptyMap(), true, Short.MAX_VALUE, false); } public KeywordEsField(String name, Map properties, boolean hasDocValues, int precision, boolean normalized) { @@ -27,12 +29,11 @@ public KeywordEsField(String name, Map properties, boolean hasD public KeywordEsField(String name, Map properties, boolean hasDocValues, int precision, boolean normalized, boolean isAlias) { - super(name, DataType.KEYWORD, properties, hasDocValues, isAlias); + super(name, KEYWORD, properties, hasDocValues, isAlias); this.precision = precision; this.normalized = normalized; } - @Override public int getPrecision() { return precision; } @@ -44,9 +45,15 @@ public Exact getExactInfo() { @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; + 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; @@ -54,7 +61,6 @@ public boolean equals(Object o) { @Override public int hashCode() { - return Objects.hash(super.hashCode(), precision, normalized); } -} +} \ No newline at end of file diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/TextEsField.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/TextEsField.java index d203430f09be0..e3e325be23f33 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/TextEsField.java +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/TextEsField.java @@ -11,6 +11,9 @@ import java.util.Map; import java.util.function.Function; +import static org.elasticsearch.xpack.ql.type.DataTypes.KEYWORD; +import static org.elasticsearch.xpack.ql.type.DataTypes.TEXT; + /** * SQL-related information about an index field with text type */ @@ -21,7 +24,7 @@ public TextEsField(String name, Map properties, boolean hasDocV } public TextEsField(String name, Map properties, boolean hasDocValues, boolean isAlias) { - super(name, DataType.TEXT, properties, hasDocValues, isAlias); + super(name, TEXT, properties, hasDocValues, isAlias); } @Override @@ -41,7 +44,7 @@ public Exact getExactInfo() { private Tuple findExact() { EsField field = null; for (EsField property : getProperties().values()) { - if (property.getDataType() == DataType.KEYWORD && property.getExactInfo().hasExact()) { + if (property.getDataType() == KEYWORD && property.getExactInfo().hasExact()) { if (field != null) { return new Tuple<>(null, "Multiple exact keyword candidates available for [" + getName() + "]; specify which one to use"); diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/Types.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/Types.java index 08defc2fada3b..44202b006fcf6 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/Types.java +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/Types.java @@ -14,88 +14,89 @@ import java.util.Map.Entry; import static java.util.Collections.emptyMap; +import static org.elasticsearch.xpack.ql.type.DataTypes.DATETIME; +import static org.elasticsearch.xpack.ql.type.DataTypes.KEYWORD; +import static org.elasticsearch.xpack.ql.type.DataTypes.NESTED; +import static org.elasticsearch.xpack.ql.type.DataTypes.OBJECT; +import static org.elasticsearch.xpack.ql.type.DataTypes.TEXT; +import static org.elasticsearch.xpack.ql.type.DataTypes.UNSUPPORTED; public abstract class Types { @SuppressWarnings("unchecked") - public static Map fromEs(Map asMap) { + public static Map fromEs(DataTypeRegistry typeRegistry, Map asMap) { Map props = null; if (asMap != null && !asMap.isEmpty()) { props = (Map) asMap.get("properties"); } - return props == null || props.isEmpty() ? emptyMap() : startWalking(props); + return props == null || props.isEmpty() ? emptyMap() : startWalking(typeRegistry, props); } - private static Map startWalking(Map mapping) { + private static Map startWalking(DataTypeRegistry typeRegistry, Map mapping) { Map types = new LinkedHashMap<>(); if (mapping == null) { return emptyMap(); } for (Entry entry : mapping.entrySet()) { - walkMapping(entry.getKey(), entry.getValue(), types); + walkMapping(typeRegistry, entry.getKey(), entry.getValue(), types); } return types; } - private static DataType getType(Map content) { + private static DataType getType(DataTypeRegistry typeRegistry, Map content) { if (content.containsKey("type")) { try { - return DataType.fromTypeName(content.get("type").toString()); + return typeRegistry.fromEs(content.get("type").toString()); } catch (IllegalArgumentException ex) { - return DataType.UNSUPPORTED; + return UNSUPPORTED; } } else if (content.containsKey("properties")) { - return DataType.OBJECT; + return OBJECT; } else { - return DataType.UNSUPPORTED; + return UNSUPPORTED; } } @SuppressWarnings("unchecked") - private static void walkMapping(String name, Object value, Map mapping) { + private static void walkMapping(DataTypeRegistry typeRegistry, 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 - DataType esDataType = getType(content); + DataType esDataType = getType(typeRegistry, content); final Map properties; - if (esDataType == DataType.OBJECT || esDataType == DataType.NESTED) { - properties = fromEs(content); + if (esDataType == OBJECT || esDataType == NESTED) { + properties = fromEs(typeRegistry, content); } else if (content.containsKey("fields")) { // Check for multifields Object fields = content.get("fields"); if (fields instanceof Map) { - properties = startWalking((Map) fields); + properties = startWalking(typeRegistry, (Map) fields); } else { properties = Collections.emptyMap(); } } else { - properties = fromEs(content); + properties = fromEs(typeRegistry, content); } - boolean docValues = boolSetting(content.get("doc_values"), esDataType.defaultDocValues); + boolean docValues = boolSetting(content.get("doc_values"), esDataType.hasDocValues()); 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 DATETIME: - field = new DateEsField(name, properties, docValues); - break; - case UNSUPPORTED: - String type = content.get("type").toString(); - field = new UnsupportedEsField(name, type, null, properties); - propagateUnsupportedType(name, type, properties); - break; - default: - field = new EsField(name, esDataType, properties, docValues); + if (esDataType == TEXT) { + field = new TextEsField(name, properties, docValues); + } else if (esDataType == KEYWORD) { + int length = intSetting(content.get("ignore_above"), Short.MAX_VALUE); + boolean normalized = Strings.hasText(textSetting(content.get("normalizer"), null)); + field = new KeywordEsField(name, properties, docValues, length, normalized); + } else if (esDataType == DATETIME) { + field = new DateEsField(name, properties, docValues); + } else if (esDataType == UNSUPPORTED) { + String type = content.get("type").toString(); + field = new UnsupportedEsField(name, type, null, properties); + propagateUnsupportedType(name, type, properties); + } else { + field = new EsField(name, esDataType, properties, docValues); } mapping.put(name, field); } else { diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/UnsupportedEsField.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/UnsupportedEsField.java index 4987ba97f2ba1..5a6ba946f6647 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/UnsupportedEsField.java +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/UnsupportedEsField.java @@ -23,7 +23,7 @@ public UnsupportedEsField(String name, String originalType) { } public UnsupportedEsField(String name, String originalType, String inherited, Map properties) { - super(name, DataType.UNSUPPORTED, properties, false); + super(name, DataTypes.UNSUPPORTED, properties, false); this.originalType = originalType; this.inherited = inherited; } diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/util/CollectionUtils.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/util/CollectionUtils.java index 9d140eb550dae..19443c55a4d9e 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/util/CollectionUtils.java +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/util/CollectionUtils.java @@ -72,4 +72,11 @@ public static List combine(Collection left, T... entries) { } return list; } + + public static int mapSize(int size) { + if (size < 2) { + return size + 1; + } + return (int) (size / 0.75f + 1f); + } } \ No newline at end of file diff --git a/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/TestUtils.java b/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/TestUtils.java index 3cf1d920514fb..d59cda2e3ea3e 100644 --- a/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/TestUtils.java +++ b/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/TestUtils.java @@ -6,7 +6,10 @@ package org.elasticsearch.xpack.ql; +import org.elasticsearch.xpack.ql.expression.Literal; import org.elasticsearch.xpack.ql.session.Configuration; +import org.elasticsearch.xpack.ql.tree.Source; +import org.elasticsearch.xpack.ql.type.DataTypes; import java.time.ZoneId; @@ -32,4 +35,14 @@ public static Configuration randomConfiguration(ZoneId zoneId) { randomAlphaOfLength(10), randomAlphaOfLength(10)); } + + /** + * Utility method for creating 'in-line' Literals (out of values instead of expressions). + */ + public static Literal of(Source source, Object value) { + if (value instanceof Literal) { + return (Literal) value; + } + return new Literal(source, value, DataTypes.fromJava(value)); + } } diff --git a/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/expression/LiteralTests.java b/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/expression/LiteralTests.java index fca1ca0726a08..abc9fee4d97db 100644 --- a/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/expression/LiteralTests.java +++ b/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/expression/LiteralTests.java @@ -9,8 +9,9 @@ import org.elasticsearch.xpack.ql.QlIllegalArgumentException; import org.elasticsearch.xpack.ql.tree.AbstractNodeTestCase; import org.elasticsearch.xpack.ql.tree.SourceTests; +import org.elasticsearch.xpack.ql.type.Converter; import org.elasticsearch.xpack.ql.type.DataType; -import org.elasticsearch.xpack.ql.type.DataTypeConversion; +import org.elasticsearch.xpack.ql.type.DataTypeConverter; import java.util.ArrayList; import java.util.Arrays; @@ -19,6 +20,14 @@ import java.util.function.Supplier; import static java.util.Collections.emptyList; +import static org.elasticsearch.xpack.ql.type.DataTypes.BOOLEAN; +import static org.elasticsearch.xpack.ql.type.DataTypes.BYTE; +import static org.elasticsearch.xpack.ql.type.DataTypes.DOUBLE; +import static org.elasticsearch.xpack.ql.type.DataTypes.FLOAT; +import static org.elasticsearch.xpack.ql.type.DataTypes.INTEGER; +import static org.elasticsearch.xpack.ql.type.DataTypes.KEYWORD; +import static org.elasticsearch.xpack.ql.type.DataTypes.LONG; +import static org.elasticsearch.xpack.ql.type.DataTypes.SHORT; public class LiteralTests extends AbstractNodeTestCase { static class ValueAndCompatibleTypes { @@ -37,22 +46,19 @@ static class ValueAndCompatibleTypes { * after a generators is its "native" type. */ private static final List GENERATORS = Arrays.asList( - 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)); + new ValueAndCompatibleTypes(() -> randomBoolean() ? randomBoolean() : randomFrom("true", "false"), BOOLEAN), + new ValueAndCompatibleTypes(ESTestCase::randomByte, BYTE, SHORT, INTEGER, LONG, FLOAT, DOUBLE, BOOLEAN), + new ValueAndCompatibleTypes(ESTestCase::randomShort, SHORT, INTEGER, LONG, FLOAT, DOUBLE, BOOLEAN), + new ValueAndCompatibleTypes(ESTestCase::randomInt, INTEGER, LONG, FLOAT, DOUBLE, BOOLEAN), + new ValueAndCompatibleTypes(ESTestCase::randomLong, LONG, FLOAT, DOUBLE, BOOLEAN), + new ValueAndCompatibleTypes(ESTestCase::randomFloat, FLOAT, LONG, DOUBLE, BOOLEAN), + new ValueAndCompatibleTypes(ESTestCase::randomDouble, DOUBLE, LONG, FLOAT, BOOLEAN), + new ValueAndCompatibleTypes(() -> randomAlphaOfLength(5), KEYWORD)); public static Literal randomLiteral() { ValueAndCompatibleTypes gen = randomFrom(GENERATORS); DataType dataType = randomFrom(gen.validDataTypes); - return new Literal(SourceTests.randomSource(), DataTypeConversion.convert(gen.valueSupplier.get(), dataType), dataType); + return new Literal(SourceTests.randomSource(), DataTypeConverter.convert(gen.valueSupplier.get(), dataType), dataType); } @Override @@ -93,7 +99,7 @@ public void testTransform() { if (validDataTypes.size() > 1) { DataType newDataType = randomValueOtherThan(literal.dataType(), () -> randomFrom(validDataTypes)); assertEquals(new Literal(literal.source(), literal.value(), newDataType), - literal.transformPropertiesOnly(p -> newDataType, DataType.class)); + literal.transformPropertiesOnly(p -> newDataType, DataType.class)); } } @@ -106,7 +112,7 @@ public void testReplaceChildren() { private Object randomValueOfTypeOtherThan(Object original, DataType type) { for (ValueAndCompatibleTypes gen : GENERATORS) { if (gen.validDataTypes.get(0) == type) { - return randomValueOtherThan(original, () -> DataTypeConversion.convert(gen.valueSupplier.get(), type)); + return randomValueOtherThan(original, () -> DataTypeConverter.convert(gen.valueSupplier.get(), type)); } } throw new IllegalArgumentException("No native generator for [" + type + "]"); @@ -114,11 +120,11 @@ private Object randomValueOfTypeOtherThan(Object original, DataType type) { private List validReplacementDataTypes(Object value, DataType type) { List validDataTypes = new ArrayList<>(); - List options = Arrays.asList(DataType.BYTE, DataType.SHORT, DataType.INTEGER, DataType.LONG, - DataType.FLOAT, DataType.DOUBLE, DataType.BOOLEAN); + List options = Arrays.asList(BYTE, SHORT, INTEGER, LONG, + FLOAT, DOUBLE, BOOLEAN); for (DataType candidate : options) { try { - DataTypeConversion.Conversion c = DataTypeConversion.conversionFor(type, candidate); + Converter c = DataTypeConverter.converterFor(type, candidate); c.convert(value); validDataTypes.add(candidate); } catch (QlIllegalArgumentException e) { diff --git a/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/expression/TyperResolutionTests.java b/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/expression/TyperResolutionTests.java index c8efccbae2b6b..b438270be30f2 100644 --- a/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/expression/TyperResolutionTests.java +++ b/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/expression/TyperResolutionTests.java @@ -7,12 +7,9 @@ package org.elasticsearch.xpack.ql.expression; import org.elasticsearch.test.ESTestCase; +import org.elasticsearch.xpack.ql.TestUtils; import org.elasticsearch.xpack.ql.expression.Expression.TypeResolution; -import org.elasticsearch.xpack.ql.expression.literal.IntervalYearMonth; import org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.Mul; -import org.elasticsearch.xpack.ql.type.DataType; - -import java.time.Period; import static org.elasticsearch.xpack.ql.tree.Source.EMPTY; @@ -23,26 +20,7 @@ public void testMulNumeric() { assertEquals(TypeResolution.TYPE_RESOLVED, m.typeResolved()); } - public void testMulIntervalAndNumber() { - Mul m = new Mul(EMPTY, L(1), randomYearInterval()); - assertEquals(TypeResolution.TYPE_RESOLVED, m.typeResolved()); - } - - public void testMulNumberAndInterval() { - Mul m = new Mul(EMPTY, randomYearInterval(), L(1)); - assertEquals(TypeResolution.TYPE_RESOLVED, m.typeResolved()); - } - - public void testMulTypeResolution() throws Exception { - Mul mul = new Mul(EMPTY, randomYearInterval(), randomYearInterval()); - assertTrue(mul.typeResolved().unresolved()); - } - - private static Literal randomYearInterval() { - return Literal.of(EMPTY, new IntervalYearMonth(Period.ofMonths(randomInt(123)), DataType.INTERVAL_YEAR_TO_MONTH)); - } - private static Literal L(Object value) { - return Literal.of(EMPTY, value); + return TestUtils.of(EMPTY, value); } } diff --git a/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/expression/function/NamedExpressionTests.java b/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/expression/function/NamedExpressionTests.java index d9250bc53a0ef..3e1d8185e2866 100644 --- a/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/expression/function/NamedExpressionTests.java +++ b/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/expression/function/NamedExpressionTests.java @@ -6,6 +6,7 @@ package org.elasticsearch.xpack.ql.expression.function; import org.elasticsearch.test.ESTestCase; +import org.elasticsearch.xpack.ql.TestUtils; import org.elasticsearch.xpack.ql.expression.FieldAttribute; import org.elasticsearch.xpack.ql.expression.Literal; import org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.Add; @@ -16,7 +17,7 @@ import org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.Sub; import org.elasticsearch.xpack.ql.tree.Location; import org.elasticsearch.xpack.ql.tree.Source; -import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import org.elasticsearch.xpack.ql.type.EsField; import static java.util.Collections.emptyMap; @@ -51,7 +52,7 @@ public void testArithmeticFunctionName() { } public void testNameForArithmeticFunctionAppliedOnTableColumn() { - FieldAttribute fa = new FieldAttribute(EMPTY, "myField", new EsField("myESField", DataType.INTEGER, emptyMap(), true)); + FieldAttribute fa = new FieldAttribute(EMPTY, "myField", new EsField("myESField", DataTypes.INTEGER, emptyMap(), true)); String e = "myField + 10"; Add add = new Add(s(e), fa, l(10)); assertEquals(e, add.sourceText()); @@ -62,6 +63,6 @@ private static Source s(String text) { } private static Literal l(Object value) { - return Literal.of(EMPTY, value); + return TestUtils.of(EMPTY, value); } } diff --git a/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/expression/function/scalar/FunctionTestUtils.java b/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/expression/function/scalar/FunctionTestUtils.java index 7713bb1a70b48..d718b8349939e 100644 --- a/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/expression/function/scalar/FunctionTestUtils.java +++ b/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/expression/function/scalar/FunctionTestUtils.java @@ -8,6 +8,8 @@ import org.elasticsearch.test.ESTestCase; import org.elasticsearch.xpack.ql.expression.Literal; +import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import java.time.Instant; import java.time.ZonedDateTime; @@ -15,23 +17,30 @@ import java.util.Iterator; import static org.elasticsearch.xpack.ql.tree.Source.EMPTY; +import static org.elasticsearch.xpack.ql.type.DataTypes.DATETIME; +import static org.elasticsearch.xpack.ql.type.DataTypes.INTEGER; +import static org.elasticsearch.xpack.ql.type.DataTypes.KEYWORD; public final class FunctionTestUtils { public static Literal l(Object value) { - return Literal.of(EMPTY, value); + return new Literal(EMPTY, value, DataTypes.fromJava(value)); + } + + public static Literal l(Object value, DataType type) { + return new Literal(EMPTY, value, type); } public static Literal randomStringLiteral() { - return l(ESTestCase.randomRealisticUnicodeOfLength(1024)); + return l(ESTestCase.randomRealisticUnicodeOfLength(1024), KEYWORD); } public static Literal randomIntLiteral() { - return l(ESTestCase.randomInt()); + return l(ESTestCase.randomInt(), INTEGER); } public static Literal randomDatetimeLiteral() { - return l(ZonedDateTime.ofInstant(Instant.ofEpochMilli(ESTestCase.randomLong()), ESTestCase.randomZone())); + return l(ZonedDateTime.ofInstant(Instant.ofEpochMilli(ESTestCase.randomLong()), ESTestCase.randomZone()), DATETIME); } public static class Combinations implements Iterable { diff --git a/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/expression/gen/pipeline/BinaryPipesTests.java b/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/expression/gen/pipeline/BinaryPipesTests.java index 61e96cc99509e..22b73c97e6b27 100644 --- a/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/expression/gen/pipeline/BinaryPipesTests.java +++ b/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/expression/gen/pipeline/BinaryPipesTests.java @@ -17,6 +17,7 @@ import java.util.List; import static java.util.Collections.emptyList; +import static org.elasticsearch.xpack.ql.type.DataTypes.KEYWORD; public class BinaryPipesTests extends ESTestCase { public void testSupportedByAggsOnlyQuery() { @@ -86,7 +87,7 @@ public static BinaryPipe randomBinaryPipe() { } public static Pipe randomUnaryPipe() { - return new ConstantInput(Source.EMPTY, Literal.of(Source.EMPTY, randomAlphaOfLength(16)), randomAlphaOfLength(16)); + return new ConstantInput(Source.EMPTY, new Literal(Source.EMPTY, randomAlphaOfLength(16), KEYWORD), randomAlphaOfLength(16)); } public static final class DummyBinaryPipe extends BinaryPipe { diff --git a/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/expression/gen/processor/ConstantProcessorTests.java b/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/expression/gen/processor/ConstantProcessorTests.java index e2f249d082652..d9b5331d93e24 100644 --- a/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/expression/gen/processor/ConstantProcessorTests.java +++ b/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/expression/gen/processor/ConstantProcessorTests.java @@ -7,12 +7,8 @@ import org.elasticsearch.common.io.stream.Writeable.Reader; import org.elasticsearch.test.AbstractWireSerializingTestCase; -import org.elasticsearch.xpack.ql.expression.literal.IntervalDayTime; -import org.elasticsearch.xpack.ql.type.DataType; import java.io.IOException; -import java.time.Duration; -import java.util.concurrent.TimeUnit; public class ConstantProcessorTests extends AbstractWireSerializingTestCase { public static ConstantProcessor randomConstantProcessor() { @@ -31,10 +27,7 @@ protected Reader instanceReader() { @Override protected ConstantProcessor mutateInstance(ConstantProcessor instance) throws IOException { - return new ConstantProcessor(randomValueOtherThan(instance.process(null), - () -> new IntervalDayTime(Duration.ofSeconds( - randomLongBetween(TimeUnit.SECONDS.convert(3, TimeUnit.HOURS), TimeUnit.SECONDS.convert(23, TimeUnit.HOURS))), - DataType.INTERVAL_DAY_TO_SECOND))); + return new ConstantProcessor(randomValueOtherThan(instance.process(null), () -> randomLong())); } public void testApply() { diff --git a/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/expression/predicate/operator/arithmetic/BinaryArithmeticProcessorTests.java b/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/expression/predicate/operator/arithmetic/BinaryArithmeticProcessorTests.java index 099985fc5aebe..dc5dbdbca9d77 100644 --- a/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/expression/predicate/operator/arithmetic/BinaryArithmeticProcessorTests.java +++ b/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/expression/predicate/operator/arithmetic/BinaryArithmeticProcessorTests.java @@ -8,6 +8,7 @@ import org.elasticsearch.common.io.stream.NamedWriteableRegistry; import org.elasticsearch.common.io.stream.Writeable.Reader; import org.elasticsearch.test.AbstractWireSerializingTestCase; +import org.elasticsearch.xpack.ql.TestUtils; import org.elasticsearch.xpack.ql.expression.Expression; import org.elasticsearch.xpack.ql.expression.Literal; import org.elasticsearch.xpack.ql.expression.gen.processor.ConstantProcessor; @@ -21,7 +22,7 @@ public static BinaryArithmeticProcessor randomProcessor() { return new BinaryArithmeticProcessor( new ConstantProcessor(randomLong()), new ConstantProcessor(randomLong()), - randomFrom(BinaryArithmeticProcessor.BinaryArithmeticOperation.values())); + randomFrom(DefaultBinaryArithmeticOperation.values())); } @Override @@ -93,6 +94,6 @@ public void testHandleNull() { } private static Literal l(Object value) { - return Literal.of(EMPTY, value); + return TestUtils.of(EMPTY, value); } } \ No newline at end of file diff --git a/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/expression/predicate/operator/comparison/BinaryComparisonProcessorTests.java b/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/expression/predicate/operator/comparison/BinaryComparisonProcessorTests.java index 97088971ac9be..9e2bdbb9afc1c 100644 --- a/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/expression/predicate/operator/comparison/BinaryComparisonProcessorTests.java +++ b/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/expression/predicate/operator/comparison/BinaryComparisonProcessorTests.java @@ -8,6 +8,7 @@ import org.elasticsearch.common.io.stream.NamedWriteableRegistry; import org.elasticsearch.common.io.stream.Writeable.Reader; import org.elasticsearch.test.AbstractWireSerializingTestCase; +import org.elasticsearch.xpack.ql.TestUtils; import org.elasticsearch.xpack.ql.expression.Literal; import org.elasticsearch.xpack.ql.expression.gen.processor.ConstantProcessor; import org.elasticsearch.xpack.ql.expression.processor.Processors; @@ -90,6 +91,6 @@ public void testHandleNull() { } private static Literal l(Object value) { - return Literal.of(EMPTY, value); + return TestUtils.of(EMPTY, value); } } diff --git a/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/tree/NodeSubclassTests.java b/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/tree/NodeSubclassTests.java index 48fe6cdf22318..3101199425821 100644 --- a/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/tree/NodeSubclassTests.java +++ b/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/tree/NodeSubclassTests.java @@ -23,12 +23,7 @@ import org.elasticsearch.xpack.ql.expression.gen.pipeline.Pipe; import org.elasticsearch.xpack.ql.expression.gen.processor.ConstantProcessor; import org.elasticsearch.xpack.ql.expression.gen.processor.Processor; -import org.elasticsearch.xpack.ql.expression.predicate.conditional.IfConditional; -import org.elasticsearch.xpack.ql.expression.predicate.conditional.IfNull; -import org.elasticsearch.xpack.ql.expression.predicate.conditional.Iif; import org.elasticsearch.xpack.ql.expression.predicate.fulltext.FullTextPredicate; -import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.In; -import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.InPipe; import org.elasticsearch.xpack.ql.expression.predicate.regex.Like; import org.elasticsearch.xpack.ql.expression.predicate.regex.LikePattern; import org.elasticsearch.xpack.ql.tree.NodeTests.ChildrenAreAProperty; @@ -49,7 +44,6 @@ import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.EnumSet; import java.util.HashMap; @@ -92,9 +86,6 @@ */ public class NodeSubclassTests> extends ESTestCase { - protected static final List> CLASSES_WITH_MIN_TWO_CHILDREN = Arrays.asList(Iif.class, IfConditional.class, IfNull.class, - In.class, InPipe.class); - private final Class subclass; public NodeSubclassTests(Class subclass) { @@ -572,7 +563,7 @@ private int randomSizeForCollection(Class> toBuildClass) { } protected boolean hasAtLeastTwoChildren(Class> toBuildClass) { - return CLASSES_WITH_MIN_TWO_CHILDREN.stream().anyMatch(toBuildClass::equals); + return false; } private List makeListOfSameSizeOtherThan(Type listType, List original) throws Exception { diff --git a/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/tree/TestCompoundAggregate.java b/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/tree/TestCompoundAggregate.java index 737d1d0950074..d807e662662ee 100644 --- a/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/tree/TestCompoundAggregate.java +++ b/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/tree/TestCompoundAggregate.java @@ -10,6 +10,7 @@ import org.elasticsearch.xpack.ql.expression.function.aggregate.AggregateFunction; import org.elasticsearch.xpack.ql.expression.function.aggregate.CompoundAggregate; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import java.util.List; @@ -34,6 +35,6 @@ public TestCompoundAggregate replaceChildren(List newChildren) { @Override public DataType dataType() { - return DataType.DOUBLE; + return DataTypes.DOUBLE; } } diff --git a/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/tree/TestEnclosedAgg.java b/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/tree/TestEnclosedAgg.java index a19b43fa2e9cb..8bd041df82c70 100644 --- a/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/tree/TestEnclosedAgg.java +++ b/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/tree/TestEnclosedAgg.java @@ -10,6 +10,7 @@ import org.elasticsearch.xpack.ql.expression.function.aggregate.AggregateFunction; import org.elasticsearch.xpack.ql.expression.function.aggregate.EnclosedAgg; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import java.util.List; @@ -39,6 +40,6 @@ public String innerName() { @Override public DataType dataType() { - return DataType.DOUBLE; + return DataTypes.DOUBLE; } } diff --git a/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/type/DataTypeConversionTests.java b/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/type/DataTypeConversionTests.java index 1258e05432b1f..f1188ed546e5a 100644 --- a/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/type/DataTypeConversionTests.java +++ b/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/type/DataTypeConversionTests.java @@ -10,68 +10,37 @@ import org.elasticsearch.xpack.ql.expression.Literal; import org.elasticsearch.xpack.ql.tree.Location; import org.elasticsearch.xpack.ql.tree.Source; -import org.elasticsearch.xpack.ql.type.DataTypeConversion.Conversion; -import java.time.OffsetTime; -import java.time.ZoneOffset; import java.time.ZonedDateTime; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import static org.elasticsearch.xpack.ql.type.DataType.BOOLEAN; -import static org.elasticsearch.xpack.ql.type.DataType.BYTE; -import static org.elasticsearch.xpack.ql.type.DataType.DATE; -import static org.elasticsearch.xpack.ql.type.DataType.DATETIME; -import static org.elasticsearch.xpack.ql.type.DataType.DOUBLE; -import static org.elasticsearch.xpack.ql.type.DataType.FLOAT; -import static org.elasticsearch.xpack.ql.type.DataType.INTEGER; -import static org.elasticsearch.xpack.ql.type.DataType.INTERVAL_HOUR_TO_MINUTE; -import static org.elasticsearch.xpack.ql.type.DataType.INTERVAL_HOUR_TO_SECOND; -import static org.elasticsearch.xpack.ql.type.DataType.INTERVAL_MONTH; -import static org.elasticsearch.xpack.ql.type.DataType.INTERVAL_SECOND; -import static org.elasticsearch.xpack.ql.type.DataType.INTERVAL_YEAR; -import static org.elasticsearch.xpack.ql.type.DataType.INTERVAL_YEAR_TO_MONTH; -import static org.elasticsearch.xpack.ql.type.DataType.IP; -import static org.elasticsearch.xpack.ql.type.DataType.KEYWORD; -import static org.elasticsearch.xpack.ql.type.DataType.LONG; -import static org.elasticsearch.xpack.ql.type.DataType.NULL; -import static org.elasticsearch.xpack.ql.type.DataType.SHORT; -import static org.elasticsearch.xpack.ql.type.DataType.TEXT; -import static org.elasticsearch.xpack.ql.type.DataType.TIME; -import static org.elasticsearch.xpack.ql.type.DataType.UNSUPPORTED; -import static org.elasticsearch.xpack.ql.type.DataType.fromTypeName; -import static org.elasticsearch.xpack.ql.type.DataType.values; -import static org.elasticsearch.xpack.ql.type.DataTypeConversion.commonType; -import static org.elasticsearch.xpack.ql.type.DataTypeConversion.conversionFor; -import static org.elasticsearch.xpack.ql.type.DateUtils.asDateOnly; +import static org.elasticsearch.xpack.ql.type.DataTypeConverter.commonType; +import static org.elasticsearch.xpack.ql.type.DataTypeConverter.converterFor; +import static org.elasticsearch.xpack.ql.type.DataTypes.BOOLEAN; +import static org.elasticsearch.xpack.ql.type.DataTypes.BYTE; +import static org.elasticsearch.xpack.ql.type.DataTypes.DATETIME; +import static org.elasticsearch.xpack.ql.type.DataTypes.DOUBLE; +import static org.elasticsearch.xpack.ql.type.DataTypes.FLOAT; +import static org.elasticsearch.xpack.ql.type.DataTypes.INTEGER; +import static org.elasticsearch.xpack.ql.type.DataTypes.IP; +import static org.elasticsearch.xpack.ql.type.DataTypes.KEYWORD; +import static org.elasticsearch.xpack.ql.type.DataTypes.LONG; +import static org.elasticsearch.xpack.ql.type.DataTypes.NULL; +import static org.elasticsearch.xpack.ql.type.DataTypes.SHORT; +import static org.elasticsearch.xpack.ql.type.DataTypes.TEXT; +import static org.elasticsearch.xpack.ql.type.DataTypes.UNSUPPORTED; import static org.elasticsearch.xpack.ql.type.DateUtils.asDateTime; -import static org.elasticsearch.xpack.ql.type.DateUtils.asTimeOnly; public class DataTypeConversionTests extends ESTestCase { public void testConversionToString() { DataType to = KEYWORD; { - Conversion conversion = conversionFor(DOUBLE, to); + Converter conversion = converterFor(DOUBLE, to); assertNull(conversion.convert(null)); assertEquals("10.0", conversion.convert(10.0)); } { - Conversion conversion = conversionFor(DATE, to); - assertNull(conversion.convert(null)); - assertEquals("1973-11-29", conversion.convert(asDateOnly(123456789101L))); - assertEquals("1966-02-02", conversion.convert(asDateOnly(-123456789101L))); - } - { - Conversion conversion = conversionFor(TIME, to); - assertNull(conversion.convert(null)); - assertEquals("00:02:03.456Z", conversion.convert(asTimeOnly(123456L))); - assertEquals("21:33:09.101Z", conversion.convert(asTimeOnly(123456789101L))); - assertEquals("23:57:56.544Z", conversion.convert(asTimeOnly(-123456L))); - assertEquals("02:26:50.899Z", conversion.convert(asTimeOnly(-123456789101L))); - } - { - Conversion conversion = conversionFor(DATETIME, to); + Converter conversion = converterFor(DATETIME, to); assertNull(conversion.convert(null)); assertEquals("1973-11-29T21:33:09.101Z", conversion.convert(asDateTime(123456789101L))); assertEquals("1966-02-02T02:26:50.899Z", conversion.convert(asDateTime(-123456789101L))); @@ -84,7 +53,7 @@ public void testConversionToString() { public void testConversionToLong() { DataType to = LONG; { - Conversion conversion = conversionFor(DOUBLE, to); + Converter conversion = converterFor(DOUBLE, to); assertNull(conversion.convert(null)); assertEquals(10L, conversion.convert(10.0)); assertEquals(10L, conversion.convert(10.1)); @@ -93,39 +62,25 @@ public void testConversionToLong() { assertEquals("[" + Double.MAX_VALUE + "] out of [long] range", e.getMessage()); } { - Conversion conversion = conversionFor(INTEGER, to); + Converter conversion = converterFor(INTEGER, to); assertNull(conversion.convert(null)); assertEquals(10L, conversion.convert(10)); assertEquals(-134L, conversion.convert(-134)); } { - Conversion conversion = conversionFor(BOOLEAN, to); + Converter conversion = converterFor(BOOLEAN, to); assertNull(conversion.convert(null)); assertEquals(1L, conversion.convert(true)); assertEquals(0L, conversion.convert(false)); } { - Conversion conversion = conversionFor(DATE, to); - assertNull(conversion.convert(null)); - assertEquals(123379200000L, conversion.convert(asDateOnly(123456789101L))); - assertEquals(-123465600000L, conversion.convert(asDateOnly(-123456789101L))); - } - { - Conversion conversion = conversionFor(TIME, to); - assertNull(conversion.convert(null)); - assertEquals(123456L, conversion.convert(asTimeOnly(123456L))); - assertEquals(77589101L, conversion.convert(asTimeOnly(123456789101L))); - assertEquals(86276544L, conversion.convert(asTimeOnly(-123456L))); - assertEquals(8810899L, conversion.convert(asTimeOnly(-123456789101L))); - } - { - Conversion conversion = conversionFor(DATETIME, to); + Converter conversion = converterFor(DATETIME, to); assertNull(conversion.convert(null)); assertEquals(123456789101L, conversion.convert(asDateTime(123456789101L))); assertEquals(-123456789101L, conversion.convert(asDateTime(-123456789101L))); } { - Conversion conversion = conversionFor(KEYWORD, to); + Converter conversion = converterFor(KEYWORD, to); assertNull(conversion.convert(null)); assertEquals(1L, conversion.convert("1")); assertEquals(0L, conversion.convert("-0")); @@ -134,162 +89,44 @@ public void testConversionToLong() { } } - public void testConversionToDate() { - DataType to = DATE; - { - Conversion conversion = conversionFor(DOUBLE, to); - assertNull(conversion.convert(null)); - assertEquals(date(10L), conversion.convert(10.0)); - assertEquals(date(10L), conversion.convert(10.1)); - assertEquals(date(11L), conversion.convert(10.6)); - Exception e = expectThrows(QlIllegalArgumentException.class, () -> conversion.convert(Double.MAX_VALUE)); - assertEquals("[" + Double.MAX_VALUE + "] out of [long] range", e.getMessage()); - } - { - Conversion conversion = conversionFor(INTEGER, to); - assertNull(conversion.convert(null)); - assertEquals(date(10L), conversion.convert(10)); - assertEquals(date(-134L), conversion.convert(-134)); - } - { - Conversion conversion = conversionFor(BOOLEAN, to); - assertNull(conversion.convert(null)); - assertEquals(date(1), conversion.convert(true)); - assertEquals(date(0), conversion.convert(false)); - } - { - Exception e = expectThrows(QlIllegalArgumentException.class, () -> conversionFor(TIME, to)); - assertEquals("cannot convert from [time] to [date]", e.getMessage()); - } - { - Conversion conversion = conversionFor(DATETIME, to); - assertNull(conversion.convert(null)); - assertEquals(date(123456780000L), conversion.convert(asDateTime(123456789101L))); - assertEquals(date(-123456789101L), conversion.convert(asDateTime(-123456789101L))); - } - { - Conversion conversion = conversionFor(KEYWORD, to); - assertNull(conversion.convert(null)); - - assertEquals(date(0L), conversion.convert("1970-01-01")); - assertEquals(date(1483228800000L), conversion.convert("2017-01-01")); - assertEquals(date(-1672531200000L), conversion.convert("1917-01-01")); - assertEquals(date(18000000L), conversion.convert("1970-01-01")); - - // double check back and forth conversion - - ZonedDateTime zdt = org.elasticsearch.common.time.DateUtils.nowWithMillisResolution(); - Conversion forward = conversionFor(DATE, KEYWORD); - Conversion back = conversionFor(KEYWORD, DATE); - assertEquals(asDateOnly(zdt), back.convert(forward.convert(zdt))); - Exception e = expectThrows(QlIllegalArgumentException.class, () -> conversion.convert("0xff")); - assertEquals("cannot cast [0xff] to [date]: Text '0xff' could not be parsed at index 0", e.getMessage()); - } - } - - public void testConversionToTime() { - DataType to = TIME; - { - Conversion conversion = conversionFor(DOUBLE, to); - assertNull(conversion.convert(null)); - assertEquals(time(10L), conversion.convert(10.0)); - assertEquals(time(10L), conversion.convert(10.1)); - assertEquals(time(11L), conversion.convert(10.6)); - Exception e = expectThrows(QlIllegalArgumentException.class, () -> conversion.convert(Double.MAX_VALUE)); - assertEquals("[" + Double.MAX_VALUE + "] out of [long] range", e.getMessage()); - } - { - Conversion conversion = conversionFor(INTEGER, to); - assertNull(conversion.convert(null)); - assertEquals(time(10L), conversion.convert(10)); - assertEquals(time(-134L), conversion.convert(-134)); - } - { - Conversion conversion = conversionFor(BOOLEAN, to); - assertNull(conversion.convert(null)); - assertEquals(time(1), conversion.convert(true)); - assertEquals(time(0), conversion.convert(false)); - } - { - Conversion conversion = conversionFor(DATE, to); - assertNull(conversion.convert(null)); - assertEquals(time(123379200000L), conversion.convert(asDateOnly(123456789101L))); - assertEquals(time(-123465600000L), conversion.convert(asDateOnly(-123456789101L))); - } - { - Conversion conversion = conversionFor(DATETIME, to); - assertNull(conversion.convert(null)); - assertEquals(time(77589101L), conversion.convert(asDateTime(123456789101L))); - assertEquals(time(8810899L), conversion.convert(asDateTime(-123456789101L))); - } - { - Conversion conversion = conversionFor(KEYWORD, to); - assertNull(conversion.convert(null)); - - assertEquals(time(0L), conversion.convert("00:00:00Z")); - assertEquals(time(1000L), conversion.convert("00:00:01Z")); - assertEquals(time(1234L), conversion.convert("00:00:01.234Z")); - assertEquals(time(63296789L).withOffsetSameInstant(ZoneOffset.ofHours(-5)), conversion.convert("12:34:56.789-05:00")); - - // double check back and forth conversion - OffsetTime ot = org.elasticsearch.common.time.DateUtils.nowWithMillisResolution().toOffsetDateTime().toOffsetTime(); - Conversion forward = conversionFor(TIME, KEYWORD); - Conversion back = conversionFor(KEYWORD, TIME); - assertEquals(ot, back.convert(forward.convert(ot))); - Exception e = expectThrows(QlIllegalArgumentException.class, () -> conversion.convert("0xff")); - assertEquals("cannot cast [0xff] to [time]: Text '0xff' could not be parsed at index 0", - e.getMessage()); - } - } - public void testConversionToDateTime() { DataType to = DATETIME; { - Conversion conversion = conversionFor(DOUBLE, to); + Converter conversion = converterFor(DOUBLE, to); assertNull(conversion.convert(null)); - assertEquals(dateTime(10L), conversion.convert(10.0)); - assertEquals(dateTime(10L), conversion.convert(10.1)); - assertEquals(dateTime(11L), conversion.convert(10.6)); + assertEquals(asDateTime(10L), conversion.convert(10.0)); + assertEquals(asDateTime(10L), conversion.convert(10.1)); + assertEquals(asDateTime(11L), conversion.convert(10.6)); Exception e = expectThrows(QlIllegalArgumentException.class, () -> conversion.convert(Double.MAX_VALUE)); assertEquals("[" + Double.MAX_VALUE + "] out of [long] range", e.getMessage()); } { - Conversion conversion = conversionFor(INTEGER, to); + Converter conversion = converterFor(INTEGER, to); assertNull(conversion.convert(null)); - assertEquals(dateTime(10L), conversion.convert(10)); - assertEquals(dateTime(-134L), conversion.convert(-134)); + assertEquals(asDateTime(10L), conversion.convert(10)); + assertEquals(asDateTime(-134L), conversion.convert(-134)); } { - Conversion conversion = conversionFor(BOOLEAN, to); + Converter conversion = converterFor(BOOLEAN, to); assertNull(conversion.convert(null)); - assertEquals(dateTime(1), conversion.convert(true)); - assertEquals(dateTime(0), conversion.convert(false)); + assertEquals(asDateTime(1), conversion.convert(true)); + assertEquals(asDateTime(0), conversion.convert(false)); } { - Conversion conversion = conversionFor(DATE, to); - assertNull(conversion.convert(null)); - assertEquals(dateTime(123379200000L), conversion.convert(asDateOnly(123456789101L))); - assertEquals(dateTime(-123465600000L), conversion.convert(asDateOnly(-123456789101L))); - } - { - Exception e = expectThrows(QlIllegalArgumentException.class, () -> conversionFor(TIME, to)); - assertEquals("cannot convert from [time] to [datetime]", e.getMessage()); - } - { - Conversion conversion = conversionFor(KEYWORD, to); + Converter conversion = converterFor(KEYWORD, to); assertNull(conversion.convert(null)); - assertEquals(dateTime(0L), conversion.convert("1970-01-01")); - assertEquals(dateTime(1000L), conversion.convert("1970-01-01T00:00:01Z")); - assertEquals(dateTime(1483228800000L), conversion.convert("2017-01-01T00:00:00Z")); - assertEquals(dateTime(1483228800000L), conversion.convert("2017-01-01T00:00:00Z")); - assertEquals(dateTime(18000000L), conversion.convert("1970-01-01T00:00:00-05:00")); + assertEquals(asDateTime(0L), conversion.convert("1970-01-01")); + assertEquals(asDateTime(1000L), conversion.convert("1970-01-01T00:00:01Z")); + assertEquals(asDateTime(1483228800000L), conversion.convert("2017-01-01T00:00:00Z")); + assertEquals(asDateTime(1483228800000L), conversion.convert("2017-01-01T00:00:00Z")); + assertEquals(asDateTime(18000000L), conversion.convert("1970-01-01T00:00:00-05:00")); // double check back and forth conversion ZonedDateTime dt = org.elasticsearch.common.time.DateUtils.nowWithMillisResolution(); - Conversion forward = conversionFor(DATETIME, KEYWORD); - Conversion back = conversionFor(KEYWORD, DATETIME); + Converter forward = converterFor(DATETIME, KEYWORD); + Converter back = converterFor(KEYWORD, DATETIME); assertEquals(dt, back.convert(forward.convert(dt))); Exception e = expectThrows(QlIllegalArgumentException.class, () -> conversion.convert("0xff")); assertEquals("cannot cast [0xff] to [datetime]: failed to parse date field [0xff] with format [date_optional_time]", @@ -300,46 +137,32 @@ public void testConversionToDateTime() { public void testConversionToFloat() { DataType to = FLOAT; { - Conversion conversion = conversionFor(DOUBLE, to); + Converter conversion = converterFor(DOUBLE, to); assertNull(conversion.convert(null)); assertEquals(10.0f, (float) conversion.convert(10.0d), 0.00001); assertEquals(10.1f, (float) conversion.convert(10.1d), 0.00001); assertEquals(10.6f, (float) conversion.convert(10.6d), 0.00001); } { - Conversion conversion = conversionFor(INTEGER, to); + Converter conversion = converterFor(INTEGER, to); assertNull(conversion.convert(null)); assertEquals(10.0f, (float) conversion.convert(10), 0.00001); assertEquals(-134.0f, (float) conversion.convert(-134), 0.00001); } { - Conversion conversion = conversionFor(BOOLEAN, to); + Converter conversion = converterFor(BOOLEAN, to); assertNull(conversion.convert(null)); assertEquals(1.0f, (float) conversion.convert(true), 0); assertEquals(0.0f, (float) conversion.convert(false), 0); } { - Conversion conversion = conversionFor(DATE, to); - assertNull(conversion.convert(null)); - assertEquals(1.233792E11f, (float) conversion.convert(asDateOnly(123456789101L)), 0); - assertEquals(-1.234656E11f, (float) conversion.convert(asDateOnly(-123456789101L)), 0); - } - { - Conversion conversion = conversionFor(TIME, to); - assertNull(conversion.convert(null)); - assertEquals(123456.0f, (float) conversion.convert(asTimeOnly(123456L)), 0); - assertEquals(7.7589104E7f, (float) conversion.convert(asTimeOnly(123456789101L)), 0); - assertEquals(8.6276544E7f, (float) conversion.convert(asTimeOnly(-123456L)), 0); - assertEquals(8810899.0f, (float) conversion.convert(asTimeOnly(-123456789101L)), 0); - } - { - Conversion conversion = conversionFor(DATETIME, to); + Converter conversion = converterFor(DATETIME, to); assertNull(conversion.convert(null)); assertEquals(1.23456789101E11f, (float) conversion.convert(asDateTime(123456789101L)), 0); assertEquals(-1.23456789101E11f, (float) conversion.convert(asDateTime(-123456789101L)), 0); } { - Conversion conversion = conversionFor(KEYWORD, to); + Converter conversion = converterFor(KEYWORD, to); assertNull(conversion.convert(null)); assertEquals(1.0f, (float) conversion.convert("1"), 0); assertEquals(0.0f, (float) conversion.convert("-0"), 0); @@ -352,46 +175,32 @@ public void testConversionToFloat() { public void testConversionToDouble() { DataType to = DOUBLE; { - Conversion conversion = conversionFor(FLOAT, to); + Converter conversion = converterFor(FLOAT, to); 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 = conversionFor(INTEGER, to); + Converter conversion = converterFor(INTEGER, to); assertNull(conversion.convert(null)); assertEquals(10.0, (double) conversion.convert(10), 0.00001); assertEquals(-134.0, (double) conversion.convert(-134), 0.00001); } { - Conversion conversion = conversionFor(BOOLEAN, to); + Converter conversion = converterFor(BOOLEAN, to); assertNull(conversion.convert(null)); assertEquals(1.0, (double) conversion.convert(true), 0); assertEquals(0.0, (double) conversion.convert(false), 0); } { - Conversion conversion = conversionFor(DATE, to); - assertNull(conversion.convert(null)); - assertEquals(1.233792E11, (double) conversion.convert(asDateOnly(123456789101L)), 0); - assertEquals(-1.234656E11, (double) conversion.convert(asDateOnly(-123456789101L)), 0); - } - { - Conversion conversion = conversionFor(TIME, to); - assertNull(conversion.convert(null)); - assertEquals(123456.0, (double) conversion.convert(asTimeOnly(123456L)), 0); - assertEquals(7.7589101E7, (double) conversion.convert(asTimeOnly(123456789101L)), 0); - assertEquals(8.6276544E7, (double) conversion.convert(asTimeOnly(-123456L)), 0); - assertEquals(8810899.0, (double) conversion.convert(asTimeOnly(-123456789101L)), 0); - } - { - Conversion conversion = conversionFor(DATETIME, to); + Converter conversion = converterFor(DATETIME, to); assertNull(conversion.convert(null)); assertEquals(1.23456789101E11, (double) conversion.convert(asDateTime(123456789101L)), 0); assertEquals(-1.23456789101E11, (double) conversion.convert(asDateTime(-123456789101L)), 0); } { - Conversion conversion = conversionFor(KEYWORD, to); + Converter conversion = converterFor(KEYWORD, to); assertNull(conversion.convert(null)); assertEquals(1.0, (double) conversion.convert("1"), 0); assertEquals(0.0, (double) conversion.convert("-0"), 0); @@ -404,56 +213,42 @@ public void testConversionToDouble() { public void testConversionToBoolean() { DataType to = BOOLEAN; { - Conversion conversion = conversionFor(FLOAT, to); + Converter conversion = converterFor(FLOAT, to); assertNull(conversion.convert(null)); assertEquals(true, conversion.convert(10.0f)); assertEquals(true, conversion.convert(-10.0f)); assertEquals(false, conversion.convert(0.0f)); } { - Conversion conversion = conversionFor(INTEGER, to); + Converter conversion = converterFor(INTEGER, to); assertNull(conversion.convert(null)); assertEquals(true, conversion.convert(10)); assertEquals(true, conversion.convert(-10)); assertEquals(false, conversion.convert(0)); } { - Conversion conversion = conversionFor(LONG, to); + Converter conversion = converterFor(LONG, to); assertNull(conversion.convert(null)); assertEquals(true, conversion.convert(10L)); assertEquals(true, conversion.convert(-10L)); assertEquals(false, conversion.convert(0L)); } { - Conversion conversion = conversionFor(DOUBLE, to); + Converter conversion = converterFor(DOUBLE, to); assertNull(conversion.convert(null)); assertEquals(true, conversion.convert(10.0d)); assertEquals(true, conversion.convert(-10.0d)); assertEquals(false, conversion.convert(0.0d)); } { - Conversion conversion = conversionFor(DATE, to); - assertNull(conversion.convert(null)); - assertEquals(true, conversion.convert(asDateOnly(123456789101L))); - assertEquals(true, conversion.convert(asDateOnly(-123456789101L))); - assertEquals(false, conversion.convert(asDateOnly(0L))); - } - { - Conversion conversion = conversionFor(TIME, to); - assertNull(conversion.convert(null)); - assertEquals(true, conversion.convert(asTimeOnly(123456789101L))); - assertEquals(true, conversion.convert(asTimeOnly(-123456789101L))); - assertEquals(false, conversion.convert(asTimeOnly(0L))); - } - { - Conversion conversion = conversionFor(DATETIME, to); + Converter conversion = converterFor(DATETIME, to); assertNull(conversion.convert(null)); assertEquals(true, conversion.convert(asDateTime(123456789101L))); assertEquals(true, conversion.convert(asDateTime(-123456789101L))); assertEquals(false, conversion.convert(asDateTime(0L))); } { - Conversion conversion = conversionFor(KEYWORD, to); + Converter conversion = converterFor(KEYWORD, to); assertNull(conversion.convert(null)); // We only handled upper and lower case true and false assertEquals(true, conversion.convert("true")); @@ -479,7 +274,7 @@ public void testConversionToBoolean() { public void testConversionToInt() { DataType to = INTEGER; { - Conversion conversion = conversionFor(DOUBLE, to); + Converter conversion = converterFor(DOUBLE, to); assertNull(conversion.convert(null)); assertEquals(10, conversion.convert(10.0)); assertEquals(10, conversion.convert(10.1)); @@ -488,26 +283,7 @@ public void testConversionToInt() { assertEquals("[" + Long.MAX_VALUE + "] out of [integer] range", e.getMessage()); } { - Conversion conversion = conversionFor(DATE, to); - assertNull(conversion.convert(null)); - assertEquals(0, conversion.convert(asDateOnly(12345678L))); - assertEquals(86400000, conversion.convert(asDateOnly(123456789L))); - assertEquals(172800000, conversion.convert(asDateOnly(223456789L))); - assertEquals(-172800000, conversion.convert(asDateOnly(-123456789L))); - Exception e = expectThrows(QlIllegalArgumentException.class, () -> conversion.convert(asDateOnly(Long.MAX_VALUE))); - assertEquals("[9223372036828800000] out of [integer] range", e.getMessage()); - } - { - Conversion conversion = conversionFor(TIME, to); - assertNull(conversion.convert(null)); - assertEquals(123456, conversion.convert(asTimeOnly(123456L))); - assertEquals(77589101, conversion.convert(asTimeOnly(123456789101L))); - assertEquals(86276544, conversion.convert(asTimeOnly(-123456L))); - assertEquals(8810899, conversion.convert(asTimeOnly(-123456789101L))); - assertEquals(25975807, conversion.convert(asTimeOnly(Long.MAX_VALUE))); - } - { - Conversion conversion = conversionFor(DATETIME, to); + Converter conversion = converterFor(DATETIME, to); assertNull(conversion.convert(null)); assertEquals(12345678, conversion.convert(asDateTime(12345678L))); assertEquals(223456789, conversion.convert(asDateTime(223456789L))); @@ -520,7 +296,7 @@ public void testConversionToInt() { public void testConversionToShort() { DataType to = SHORT; { - Conversion conversion = conversionFor(DOUBLE, to); + Converter conversion = converterFor(DOUBLE, to); assertNull(conversion.convert(null)); assertEquals((short) 10, conversion.convert(10.0)); assertEquals((short) 10, conversion.convert(10.1)); @@ -529,23 +305,7 @@ public void testConversionToShort() { assertEquals("[" + Integer.MAX_VALUE + "] out of [short] range", e.getMessage()); } { - Conversion conversion = conversionFor(DATE, to); - assertNull(conversion.convert(null)); - assertEquals((short) 0, conversion.convert(asDateOnly(12345678L))); - Exception e = expectThrows(QlIllegalArgumentException.class, () -> conversion.convert(asDateOnly(123456789L))); - assertEquals("[86400000] out of [short] range", e.getMessage()); - } - { - Conversion conversion = conversionFor(TIME, to); - assertNull(conversion.convert(null)); - assertEquals((short) 12345, conversion.convert(asTimeOnly(12345L))); - Exception e1 = expectThrows(QlIllegalArgumentException.class, () -> conversion.convert(asTimeOnly(-123456789L))); - assertEquals("[49343211] out of [short] range", e1.getMessage()); - Exception e2 = expectThrows(QlIllegalArgumentException.class, () -> conversion.convert(asTimeOnly(123456789L))); - assertEquals("[37056789] out of [short] range", e2.getMessage()); - } - { - Conversion conversion = conversionFor(DATETIME, to); + Converter conversion = converterFor(DATETIME, to); assertNull(conversion.convert(null)); assertEquals((short) 12345, conversion.convert(asDateTime(12345L))); assertEquals((short) -12345, conversion.convert(asDateTime(-12345L))); @@ -558,7 +318,7 @@ public void testConversionToShort() { public void testConversionToByte() { DataType to = BYTE; { - Conversion conversion = conversionFor(DOUBLE, to); + Converter conversion = converterFor(DOUBLE, to); assertNull(conversion.convert(null)); assertEquals((byte) 10, conversion.convert(10.0)); assertEquals((byte) 10, conversion.convert(10.1)); @@ -567,23 +327,7 @@ public void testConversionToByte() { assertEquals("[" + Short.MAX_VALUE + "] out of [byte] range", e.getMessage()); } { - Conversion conversion = conversionFor(DATE, to); - assertNull(conversion.convert(null)); - assertEquals((byte) 0, conversion.convert(asDateOnly(12345678L))); - Exception e = expectThrows(QlIllegalArgumentException.class, () -> conversion.convert(asDateOnly(123456789L))); - assertEquals("[86400000] out of [byte] range", e.getMessage()); - } - { - Conversion conversion = conversionFor(TIME, to); - assertNull(conversion.convert(null)); - assertEquals((byte) 123, conversion.convert(asTimeOnly(123L))); - Exception e1 = expectThrows(QlIllegalArgumentException.class, () -> conversion.convert(asTimeOnly(-123L))); - assertEquals("[86399877] out of [byte] range", e1.getMessage()); - Exception e2 = expectThrows(QlIllegalArgumentException.class, () -> conversion.convert(asTimeOnly(123456789L))); - assertEquals("[37056789] out of [byte] range", e2.getMessage()); - } - { - Conversion conversion = conversionFor(DATETIME, to); + Converter conversion = converterFor(DATETIME, to); assertNull(conversion.convert(null)); assertEquals((byte) 123, conversion.convert(asDateTime(123L))); assertEquals((byte) -123, conversion.convert(asDateTime(-123L))); @@ -594,19 +338,19 @@ public void testConversionToByte() { } public void testConversionToNull() { - Conversion conversion = conversionFor(DOUBLE, NULL); + Converter conversion = converterFor(DOUBLE, NULL); assertNull(conversion.convert(null)); assertNull(conversion.convert(10.0)); } public void testConversionFromNull() { - Conversion conversion = conversionFor(NULL, INTEGER); + Converter conversion = converterFor(NULL, INTEGER); assertNull(conversion.convert(null)); assertNull(conversion.convert(10)); } public void testConversionToIdentity() { - Conversion conversion = conversionFor(INTEGER, INTEGER); + Converter conversion = converterFor(INTEGER, INTEGER); assertNull(conversion.convert(null)); assertEquals(10, conversion.convert(10)); } @@ -626,46 +370,22 @@ public void testCommonType() { // strings assertEquals(TEXT, commonType(TEXT, KEYWORD)); assertEquals(TEXT, commonType(KEYWORD, TEXT)); - - // numeric and intervals - assertEquals(INTERVAL_YEAR_TO_MONTH, commonType(INTERVAL_YEAR_TO_MONTH, LONG)); - assertEquals(INTERVAL_HOUR_TO_MINUTE, commonType(INTEGER, INTERVAL_HOUR_TO_MINUTE)); - - // dates/datetimes and intervals - assertEquals(DATETIME, commonType(DATE, DATETIME)); - assertEquals(DATETIME, commonType(DATETIME, DATE)); - assertEquals(DATETIME, commonType(TIME, DATETIME)); - assertEquals(DATETIME, commonType(DATETIME, TIME)); - assertEquals(DATETIME, commonType(DATETIME, randomInterval())); - assertEquals(DATETIME, commonType(randomInterval(), DATETIME)); - assertEquals(DATETIME, commonType(DATE, TIME)); - assertEquals(DATETIME, commonType(TIME, DATE)); - assertEquals(DATE, commonType(DATE, INTERVAL_YEAR)); - assertEquals(DATETIME, commonType(DATE, INTERVAL_HOUR_TO_MINUTE)); - assertEquals(TIME, commonType(TIME, randomInterval())); - assertEquals(TIME, commonType(randomInterval(), TIME)); - - assertEquals(INTERVAL_YEAR_TO_MONTH, commonType(INTERVAL_YEAR_TO_MONTH, INTERVAL_MONTH)); - assertEquals(INTERVAL_HOUR_TO_SECOND, commonType(INTERVAL_HOUR_TO_MINUTE, INTERVAL_HOUR_TO_SECOND)); - assertNull(commonType(INTERVAL_SECOND, INTERVAL_YEAR)); } public void testEsDataTypes() { - for (DataType type : values()) { - if (type != DATE) { // Doesn't have a corresponding type in ES - assertEquals(type, fromTypeName(type.typeName())); - } + for (DataType type : DataTypes.types()) { + assertEquals(type, DataTypes.fromTypeName(type.typeName())); } } public void testConversionToUnsupported() { Exception e = expectThrows(QlIllegalArgumentException.class, - () -> conversionFor(INTEGER, UNSUPPORTED)); - assertEquals("cannot convert from [integer] to [unsupported]", e.getMessage()); + () -> DataTypeConverter.convert(Integer.valueOf(1), UNSUPPORTED)); + assertEquals("cannot convert from [1], type [integer] to [unsupported]", e.getMessage()); } public void testStringToIp() { - Conversion conversion = conversionFor(KEYWORD, IP); + Converter conversion = converterFor(KEYWORD, IP); assertNull(conversion.convert(null)); assertEquals("192.168.1.1", conversion.convert("192.168.1.1")); Exception e = expectThrows(QlIllegalArgumentException.class, () -> conversion.convert("10.1.1.300")); @@ -674,25 +394,9 @@ public void testStringToIp() { public void testIpToString() { Source s = new Source(Location.EMPTY, "10.0.0.1"); - Conversion ipToString = conversionFor(IP, KEYWORD); + Converter ipToString = converterFor(IP, KEYWORD); assertEquals("10.0.0.1", ipToString.convert(new Literal(s, "10.0.0.1", IP))); - Conversion stringToIp = conversionFor(KEYWORD, IP); - assertEquals("10.0.0.1", ipToString.convert(stringToIp.convert(Literal.of(s, "10.0.0.1")))); - } - - private DataType randomInterval() { - return randomFrom(Stream.of(DataType.values()).filter(DataType::isInterval).collect(Collectors.toList())); - } - - static ZonedDateTime date(long millisSinceEpoch) { - return DateUtils.asDateOnly(millisSinceEpoch); - } - - static ZonedDateTime dateTime(long millisSinceEpoch) { - return DateUtils.asDateTime(millisSinceEpoch); - } - - static OffsetTime time(long millisSinceEpoch) { - return DateUtils.asTimeOnly(millisSinceEpoch); + Converter stringToIp = converterFor(KEYWORD, IP); + assertEquals("10.0.0.1", ipToString.convert(stringToIp.convert(new Literal(s, "10.0.0.1", KEYWORD)))); } -} +} \ No newline at end of file diff --git a/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/type/TypesTests.java b/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/type/TypesTests.java index 8be30f389973d..8057c1cd48348 100644 --- a/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/type/TypesTests.java +++ b/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/type/TypesTests.java @@ -13,24 +13,24 @@ import java.util.Map; import static java.util.Collections.emptyMap; -import static org.elasticsearch.xpack.ql.type.DataType.DATETIME; -import static org.elasticsearch.xpack.ql.type.DataType.INTEGER; -import static org.elasticsearch.xpack.ql.type.DataType.KEYWORD; -import static org.elasticsearch.xpack.ql.type.DataType.NESTED; -import static org.elasticsearch.xpack.ql.type.DataType.OBJECT; -import static org.elasticsearch.xpack.ql.type.DataType.TEXT; +import static org.elasticsearch.xpack.ql.type.DataTypes.DATETIME; +import static org.elasticsearch.xpack.ql.type.DataTypes.INTEGER; +import static org.elasticsearch.xpack.ql.type.DataTypes.KEYWORD; +import static org.elasticsearch.xpack.ql.type.DataTypes.NESTED; +import static org.elasticsearch.xpack.ql.type.DataTypes.OBJECT; +import static org.elasticsearch.xpack.ql.type.DataTypes.TEXT; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; public class TypesTests extends ESTestCase { public void testNullMap() { - Map fromEs = Types.fromEs(null); + Map fromEs = Types.fromEs(DefaultDataTypeRegistry.INSTANCE, null); assertThat(fromEs.isEmpty(), is(true)); } public void testEmptyMap() { - Map fromEs = Types.fromEs(emptyMap()); + Map fromEs = Types.fromEs(DefaultDataTypeRegistry.INSTANCE, emptyMap()); assertThat(fromEs.isEmpty(), is(true)); } @@ -60,7 +60,6 @@ public void testTextField() { assertThat(type, instanceOf(TextEsField.class)); assertThat(type.isAggregatable(), is(false)); TextEsField ttype = (TextEsField) type; - assertThat(type.getPrecision(), is(Integer.MAX_VALUE)); assertThat(ttype.isAggregatable(), is(false)); } @@ -71,7 +70,6 @@ public void testKeywordField() { EsField field = mapping.get("full_name"); assertThat(field, instanceOf(KeywordEsField.class)); assertThat(field.isAggregatable(), is(true)); - assertThat(field.getPrecision(), is(256)); } public void testDateField() { @@ -81,7 +79,6 @@ public void testDateField() { EsField field = mapping.get("date"); assertThat(field.getDataType(), is(DATETIME)); assertThat(field.isAggregatable(), is(true)); - assertThat(field.getPrecision(), is(3)); } public void testDateNoFormat() { @@ -110,7 +107,7 @@ public void testDocValueField() { assertThat(mapping.size(), is(1)); EsField field = mapping.get("session_id"); assertThat(field, instanceOf(KeywordEsField.class)); - assertThat(field.getPrecision(), is(15)); + //assertThat(field.getPrecision(), is(15)); assertThat(field.isAggregatable(), is(false)); } @@ -119,7 +116,7 @@ public void testDottedField() { assertThat(mapping.size(), is(2)); EsField field = mapping.get("manager"); - assertThat(field.getDataType().isPrimitive(), is(false)); + assertThat(DataTypes.isPrimitive(field.getDataType()), is(false)); assertThat(field.getDataType(), is(OBJECT)); Map children = field.getProperties(); assertThat(children.size(), is(2)); @@ -134,7 +131,7 @@ public void testMultiField() { assertThat(mapping.size(), is(1)); EsField field = mapping.get("text"); - assertThat(field.getDataType().isPrimitive(), is(true)); + assertThat(DataTypes.isPrimitive(field.getDataType()), is(true)); assertThat(field.getDataType(), is(TEXT)); Map fields = field.getProperties(); assertThat(fields.size(), is(2)); @@ -147,7 +144,7 @@ public void testMultiFieldTooManyOptions() { assertThat(mapping.size(), is(1)); EsField field = mapping.get("text"); - assertThat(field.getDataType().isPrimitive(), is(true)); + assertThat(DataTypes.isPrimitive(field.getDataType()), is(true)); assertThat(field, instanceOf(TextEsField.class)); Map fields = field.getProperties(); assertThat(fields.size(), is(2)); @@ -160,7 +157,7 @@ public void testNestedDoc() { assertThat(mapping.size(), is(1)); EsField field = mapping.get("dep"); - assertThat(field.getDataType().isPrimitive(), is(false)); + assertThat(DataTypes.isPrimitive(field.getDataType()), is(false)); assertThat(field.getDataType(), is(NESTED)); Map children = field.getProperties(); assertThat(children.size(), is(4)); @@ -168,15 +165,6 @@ public void testNestedDoc() { assertThat(children.get("start_date").getDataType(), is(DATETIME)); } - public void testGeoField() { - Map mapping = loadMapping("mapping-geo.json"); - assertThat(mapping.size(), is(2)); - EsField gp = mapping.get("location"); - assertThat(gp.getDataType().typeName(), is("geo_point")); - EsField gs = mapping.get("site"); - assertThat(gs.getDataType().typeName(), is("geo_shape")); - } - public void testIpField() { Map mapping = loadMapping("mapping-ip.json"); assertThat(mapping.size(), is(1)); @@ -195,14 +183,21 @@ public void testUnsupportedTypes() { } 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())); + return loadMapping(DefaultDataTypeRegistry.INSTANCE, name, null); } public static Map loadMapping(String name, boolean ordered) { + return loadMapping(DefaultDataTypeRegistry.INSTANCE, name, ordered); + } + + public static Map loadMapping(DataTypeRegistry registry, String name) { + return loadMapping(registry, name, null); + } + + public static Map loadMapping(DataTypeRegistry registry, String name, Boolean ordered) { + boolean order = ordered != null ? ordered.booleanValue() : randomBoolean(); InputStream stream = TypesTests.class.getResourceAsStream("/" + name); assertNotNull("Could not find mapping resource:" + name, stream); - return Types.fromEs(XContentHelper.convertToMap(JsonXContent.jsonXContent, stream, ordered)); + return Types.fromEs(registry, XContentHelper.convertToMap(JsonXContent.jsonXContent, stream, order)); } -} +} \ No newline at end of file diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/analysis/analyzer/Analyzer.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/analysis/analyzer/Analyzer.java index c47f31bcb901f..3be204c3a89a4 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/analysis/analyzer/Analyzer.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/analysis/analyzer/Analyzer.java @@ -14,7 +14,6 @@ import org.elasticsearch.xpack.ql.expression.Expression; import org.elasticsearch.xpack.ql.expression.Expressions; import org.elasticsearch.xpack.ql.expression.FieldAttribute; -import org.elasticsearch.xpack.ql.expression.Foldables; import org.elasticsearch.xpack.ql.expression.NamedExpression; import org.elasticsearch.xpack.ql.expression.Order; import org.elasticsearch.xpack.ql.expression.ReferenceAttribute; @@ -41,13 +40,13 @@ import org.elasticsearch.xpack.ql.rule.RuleExecutor; import org.elasticsearch.xpack.ql.session.Configuration; import org.elasticsearch.xpack.ql.type.DataType; -import org.elasticsearch.xpack.ql.type.DataTypeConversion; import org.elasticsearch.xpack.ql.type.DataTypes; import org.elasticsearch.xpack.ql.type.InvalidMappedField; import org.elasticsearch.xpack.ql.type.UnsupportedEsField; import org.elasticsearch.xpack.ql.util.CollectionUtils; import org.elasticsearch.xpack.ql.util.Holder; import org.elasticsearch.xpack.sql.analysis.analyzer.Verifier.Failure; +import org.elasticsearch.xpack.sql.expression.Foldables; import org.elasticsearch.xpack.sql.expression.SubQueryExpression; import org.elasticsearch.xpack.sql.expression.function.scalar.Cast; import org.elasticsearch.xpack.sql.plan.logical.Join; @@ -55,6 +54,7 @@ import org.elasticsearch.xpack.sql.plan.logical.Pivot; import org.elasticsearch.xpack.sql.plan.logical.SubQueryAlias; import org.elasticsearch.xpack.sql.plan.logical.With; +import org.elasticsearch.xpack.sql.type.SqlDataTypeConverter; import java.util.ArrayList; import java.util.Arrays; @@ -227,7 +227,7 @@ else if (DataTypes.isUnsupported(fa.dataType())) { } } // compound fields - else if (allowCompound == false && fa.dataType().isPrimitive() == false) { + else if (allowCompound == false && DataTypes.isPrimitive(fa.dataType()) == false) { named = u.withUnresolvedMessage( "Cannot use field [" + fa.name() + "] type [" + fa.dataType().typeName() + "] only its subfields"); } @@ -1188,7 +1188,7 @@ private Expression implicitCast(Expression e) { DataType l = left.dataType(); DataType r = right.dataType(); if (l != r) { - DataType common = DataTypeConversion.commonType(l, r); + DataType common = SqlDataTypeConverter.commonType(l, r); if (common == null) { return e; } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/analysis/analyzer/Verifier.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/analysis/analyzer/Verifier.java index d71ff27eaa0f9..9026567025521 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/analysis/analyzer/Verifier.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/analysis/analyzer/Verifier.java @@ -45,6 +45,7 @@ import org.elasticsearch.xpack.sql.plan.logical.command.Command; import org.elasticsearch.xpack.sql.stats.FeatureMetric; import org.elasticsearch.xpack.sql.stats.Metrics; +import org.elasticsearch.xpack.sql.type.SqlDataTypes; import java.util.ArrayList; import java.util.BitSet; @@ -60,8 +61,6 @@ import static java.util.stream.Collectors.toMap; import static org.elasticsearch.common.logging.LoggerMessageFormat.format; -import static org.elasticsearch.xpack.ql.type.DataType.GEO_SHAPE; -import static org.elasticsearch.xpack.ql.type.DataType.SHAPE; import static org.elasticsearch.xpack.ql.util.CollectionUtils.combine; import static org.elasticsearch.xpack.sql.stats.FeatureMetric.COMMAND; import static org.elasticsearch.xpack.sql.stats.FeatureMetric.GROUPBY; @@ -70,6 +69,8 @@ import static org.elasticsearch.xpack.sql.stats.FeatureMetric.LOCAL; import static org.elasticsearch.xpack.sql.stats.FeatureMetric.ORDERBY; import static org.elasticsearch.xpack.sql.stats.FeatureMetric.WHERE; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.GEO_SHAPE; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.SHAPE; /** * The verifier has the role of checking the analyzed tree for failures and build a list of failures following this check. @@ -182,7 +183,7 @@ Collection verify(LogicalPlan plan) { for (Attribute a : p.inputSet()) { String nameCandidate = useQualifier ? a.qualifiedName() : a.name(); // add only primitives (object types would only result in another error) - if ((a.dataType() != DataType.UNSUPPORTED) && a.dataType().isPrimitive()) { + if (DataTypes.isUnsupported(a.dataType()) == false && DataTypes.isPrimitive(a.dataType())) { potentialMatches.add(nameCandidate); } } @@ -450,7 +451,7 @@ private static boolean checkGroupByHavingHasOnlyAggs(Expression e, Set localFailure // TIME data type is not allowed for grouping key // https://github.com/elastic/elasticsearch/issues/40639 a.groupings().forEach(f -> { - if (f.dataType().isTimeBased()) { + if (f.dataType() == SqlDataTypes.TIME) { localFailures.add(fail(f, "Function [" + f.sourceText() + "] with data type [" + f.dataType().typeName() + "] " + "cannot be used for grouping")); } @@ -810,7 +811,7 @@ else if (ex.foldable() && ex.fold() == null) { localFailures.add(fail(v, "Null not allowed as a PIVOT value", v.name())); } // and that their type is compatible with that of the column - else if (DataTypes.areTypesCompatible(colType, v.dataType()) == false) { + else if (SqlDataTypes.areCompatible(colType, v.dataType()) == false) { localFailures.add(fail(v, "Literal [{}] of type [{}] does not match type [{}] of PIVOT column [{}]", v.name(), v.dataType().typeName(), colType.typeName(), pv.column().sourceText())); } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/execution/search/extractor/FieldHitExtractor.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/execution/search/extractor/FieldHitExtractor.java index 046cf8401e5b6..0a621eec44cd3 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/execution/search/extractor/FieldHitExtractor.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/execution/search/extractor/FieldHitExtractor.java @@ -11,10 +11,11 @@ import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.xpack.ql.execution.search.extractor.AbstractFieldHitExtractor; import org.elasticsearch.xpack.ql.execution.search.extractor.HitExtractor; -import org.elasticsearch.xpack.ql.expression.function.scalar.geo.GeoShape; import org.elasticsearch.xpack.ql.type.DataType; import org.elasticsearch.xpack.sql.SqlIllegalArgumentException; import org.elasticsearch.xpack.sql.common.io.SqlStreamInput; +import org.elasticsearch.xpack.sql.expression.literal.geo.GeoShape; +import org.elasticsearch.xpack.sql.type.SqlDataTypes; import org.elasticsearch.xpack.sql.util.DateUtils; import java.io.IOException; @@ -22,6 +23,11 @@ import java.util.List; import java.util.Map; +import static org.elasticsearch.xpack.ql.type.DataTypes.DATETIME; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.GEO_POINT; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.GEO_SHAPE; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.SHAPE; + /** * Extractor for ES fields. Works for both 'normal' fields but also nested ones (which require hitName to be set). * The latter is used as metadata in assembling the results in the tabular response. @@ -51,6 +57,10 @@ public FieldHitExtractor(StreamInput in) throws IOException { super(in); } + @Override + protected DataType loadTypeFromName(String typeName) { + return SqlDataTypes.fromTypeName(typeName); + } @Override protected ZoneId readZoneId(StreamInput in) throws IOException { @@ -69,7 +79,7 @@ protected boolean isPrimitive(List list) { } private boolean isGeoPointArray(List list) { - if (dataType() != DataType.GEO_POINT) { + if (dataType() != GEO_POINT) { return false; } // we expect the point in [lon lat] or [lon lat alt] formats @@ -79,16 +89,17 @@ private boolean isGeoPointArray(List list) { return list.get(0) instanceof Number; } + @Override - protected Object extractFromSource(Map map) { - return super.extractFromSource(map); + protected boolean isFromDocValuesOnly(DataType dataType) { + return SqlDataTypes.isFromDocValuesOnly(dataType); } @Override protected Object unwrapCustomValue(Object values) { DataType dataType = dataType(); - if (dataType == DataType.GEO_POINT) { + if (dataType == GEO_POINT) { try { GeoPoint geoPoint = GeoUtils.parseGeoPoint(values, true); return new GeoShape(geoPoint.lon(), geoPoint.lat()); @@ -96,14 +107,14 @@ protected Object unwrapCustomValue(Object values) { throw new SqlIllegalArgumentException("Cannot parse geo_point value [{}] (returned by [{}])", values, fieldName()); } } - if (dataType == DataType.GEO_SHAPE) { + if (dataType == GEO_SHAPE) { try { return new GeoShape(values); } catch (IOException ex) { throw new SqlIllegalArgumentException("Cannot read geo_shape value [{}] (returned by [{}])", values, fieldName()); } } - if (dataType == DataType.SHAPE) { + if (dataType == SHAPE) { try { return new GeoShape(values); } catch (IOException ex) { @@ -113,7 +124,7 @@ protected Object unwrapCustomValue(Object values) { if (values instanceof Map) { throw new SqlIllegalArgumentException("Objects (returned by [{}]) are not supported", fieldName()); } - if (dataType == DataType.DATETIME) { + if (dataType == DATETIME) { if (values instanceof String) { return DateUtils.asDateTime(Long.parseLong(values.toString()), zoneId()); } @@ -121,9 +132,4 @@ protected Object unwrapCustomValue(Object values) { return null; } - - @Override - protected DataType dataType() { - return super.dataType(); - } } \ No newline at end of file diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/execution/search/extractor/TopHitsAggExtractor.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/execution/search/extractor/TopHitsAggExtractor.java index 3b705ee6b5cdc..0c746991d91e9 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/execution/search/extractor/TopHitsAggExtractor.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/execution/search/extractor/TopHitsAggExtractor.java @@ -13,6 +13,7 @@ import org.elasticsearch.xpack.ql.type.DataType; import org.elasticsearch.xpack.sql.SqlIllegalArgumentException; import org.elasticsearch.xpack.sql.common.io.SqlStreamInput; +import org.elasticsearch.xpack.sql.type.SqlDataTypes; import org.elasticsearch.xpack.sql.util.DateUtils; import java.io.IOException; @@ -35,14 +36,14 @@ public TopHitsAggExtractor(String name, DataType fieldDataType, ZoneId zoneId) { TopHitsAggExtractor(StreamInput in) throws IOException { name = in.readString(); - fieldDataType = in.readEnum(DataType.class); + fieldDataType = SqlDataTypes.fromTypeName(in.readString()); zoneId = SqlStreamInput.asSqlStream(in).zoneId(); } @Override public void writeTo(StreamOutput out) throws IOException { out.writeString(name); - out.writeEnum(fieldDataType); + out.writeString(fieldDataType.typeName()); } String name() { @@ -74,9 +75,9 @@ public Object extract(Bucket bucket) { } Object value = agg.getHits().getAt(0).getFields().values().iterator().next().getValue(); - if (fieldDataType.isDateBased()) { + if (SqlDataTypes.isDateBased(fieldDataType)) { return DateUtils.asDateTime(Long.parseLong(value.toString()), zoneId); - } else if (fieldDataType.isTimeBased()) { + } else if (SqlDataTypes.isTimeBased(fieldDataType)) { return DateUtils.asTimeOnly(Long.parseLong(value.toString()), zoneId); } else { return value; diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/Exists.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/Exists.java index cebe50b9f6d56..a115b9f2b8eec 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/Exists.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/Exists.java @@ -12,6 +12,8 @@ import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; +import static org.elasticsearch.xpack.ql.type.DataTypes.BOOLEAN; + public class Exists extends SubQueryExpression { public Exists(Source source, LogicalPlan query) { @@ -34,7 +36,7 @@ protected SubQueryExpression clone(LogicalPlan newQuery) { @Override public DataType dataType() { - return DataType.BOOLEAN; + return BOOLEAN; } @Override diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/Foldables.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/Foldables.java similarity index 73% rename from x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/Foldables.java rename to x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/Foldables.java index f70f6423497f7..067b85ae30d7c 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/Foldables.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/Foldables.java @@ -3,11 +3,13 @@ * 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.ql.expression; +package org.elasticsearch.xpack.sql.expression; import org.elasticsearch.xpack.ql.QlIllegalArgumentException; +import org.elasticsearch.xpack.ql.expression.Expression; import org.elasticsearch.xpack.ql.type.DataType; -import org.elasticsearch.xpack.ql.type.DataTypeConversion; +import org.elasticsearch.xpack.ql.type.DataTypes; +import org.elasticsearch.xpack.sql.type.SqlDataTypeConverter; import java.util.ArrayList; import java.util.Collection; @@ -18,9 +20,9 @@ public abstract class Foldables { @SuppressWarnings("unchecked") - public static T valueOf(Expression e, DataType to) { + private static T valueOf(Expression e, DataType to) { if (e.foldable()) { - return (T) DataTypeConversion.conversionFor(e.dataType(), to).convert(e.fold()); + return (T) SqlDataTypeConverter.convert(e.fold(), to); } throw new QlIllegalArgumentException("Cannot determine value for {}", e); } @@ -33,18 +35,18 @@ public static Object valueOf(Expression e) { } public static Integer intValueOf(Expression e) { - return valueOf(e, DataType.INTEGER); + return valueOf(e, DataTypes.INTEGER); } public static double doubleValueOf(Expression e) { - return valueOf(e, DataType.DOUBLE); + return valueOf(e, DataTypes.DOUBLE); } public static List valuesOf(List list, DataType to) { return foldTo(list, to, new ArrayList<>(list.size())); } - public static Set valuesOfNoDuplicates(List list, DataType to) { + public static Set valuesUnique(List list, DataType to) { return foldTo(list, to, new LinkedHashSet<>(list.size())); } @@ -56,6 +58,6 @@ private static > C foldTo(Collection expr } public static List doubleValuesOf(List list) { - return valuesOf(list, DataType.DOUBLE); + return valuesOf(list, DataTypes.DOUBLE); } } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/SqlTypeResolutions.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/SqlTypeResolutions.java new file mode 100644 index 0000000000000..1d5af2446fb05 --- /dev/null +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/SqlTypeResolutions.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.expression; + +import org.elasticsearch.xpack.ql.expression.Expression; +import org.elasticsearch.xpack.ql.expression.Expression.TypeResolution; +import org.elasticsearch.xpack.ql.expression.Expressions.ParamOrdinal; +import org.elasticsearch.xpack.sql.type.SqlDataTypes; + +import static org.elasticsearch.xpack.ql.expression.TypeResolutions.isType; + +public final class SqlTypeResolutions { + + private SqlTypeResolutions() {} + + public static TypeResolution isDate(Expression e, String operationName, ParamOrdinal paramOrd) { + return isType(e, SqlDataTypes::isDateBased, operationName, paramOrd, "date", "datetime"); + } + + public static TypeResolution isDateOrTime(Expression e, String operationName, ParamOrdinal paramOrd) { + return isType(e, SqlDataTypes::isDateOrTimeBased, operationName, paramOrd, "date", "time", "datetime"); + } + + public static TypeResolution isNumericOrDate(Expression e, String operationName, ParamOrdinal paramOrd) { + return isType(e, dt -> dt.isNumeric() || SqlDataTypes.isDateBased(dt), operationName, paramOrd, + "date", "datetime", "numeric"); + } + + public static TypeResolution isNumericOrDateOrTime(Expression e, String operationName, ParamOrdinal paramOrd) { + return isType(e, dt -> dt.isNumeric() || SqlDataTypes.isDateOrTimeBased(dt), operationName, paramOrd, + "date", "time", "datetime", "numeric"); + } + + public static TypeResolution isGeo(Expression e, String operationName, ParamOrdinal paramOrd) { + return isType(e, SqlDataTypes::isGeo, operationName, paramOrd, "geo_point", "geo_shape"); + } +} diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/Score.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/Score.java index af575b18f8fa1..cbe02fb675497 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/Score.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/Score.java @@ -12,6 +12,7 @@ import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import org.elasticsearch.xpack.sql.SqlIllegalArgumentException; import java.util.List; @@ -40,7 +41,7 @@ public Expression replaceChildren(List newChildren) { @Override public DataType dataType() { - return DataType.FLOAT; + return DataTypes.FLOAT; } @Override diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/SqlFunctionRegistry.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/SqlFunctionRegistry.java index 17ded961b605a..ec1656f0dad54 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/SqlFunctionRegistry.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/SqlFunctionRegistry.java @@ -8,13 +8,6 @@ import org.elasticsearch.xpack.ql.expression.function.FunctionDefinition; import org.elasticsearch.xpack.ql.expression.function.FunctionRegistry; import org.elasticsearch.xpack.ql.expression.function.aggregate.Count; -import org.elasticsearch.xpack.ql.expression.predicate.conditional.Case; -import org.elasticsearch.xpack.ql.expression.predicate.conditional.Coalesce; -import org.elasticsearch.xpack.ql.expression.predicate.conditional.Greatest; -import org.elasticsearch.xpack.ql.expression.predicate.conditional.IfNull; -import org.elasticsearch.xpack.ql.expression.predicate.conditional.Iif; -import org.elasticsearch.xpack.ql.expression.predicate.conditional.Least; -import org.elasticsearch.xpack.ql.expression.predicate.conditional.NullIf; import org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.Mod; import org.elasticsearch.xpack.sql.expression.function.aggregate.Avg; import org.elasticsearch.xpack.sql.expression.function.aggregate.First; @@ -111,6 +104,13 @@ import org.elasticsearch.xpack.sql.expression.function.scalar.string.Space; import org.elasticsearch.xpack.sql.expression.function.scalar.string.Substring; import org.elasticsearch.xpack.sql.expression.function.scalar.string.UCase; +import org.elasticsearch.xpack.sql.expression.predicate.conditional.Case; +import org.elasticsearch.xpack.sql.expression.predicate.conditional.Coalesce; +import org.elasticsearch.xpack.sql.expression.predicate.conditional.Greatest; +import org.elasticsearch.xpack.sql.expression.predicate.conditional.IfNull; +import org.elasticsearch.xpack.sql.expression.predicate.conditional.Iif; +import org.elasticsearch.xpack.sql.expression.predicate.conditional.Least; +import org.elasticsearch.xpack.sql.expression.predicate.conditional.NullIf; public class SqlFunctionRegistry extends FunctionRegistry { diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/SqlFunctionTypeRegistry.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/SqlFunctionTypeRegistry.java index e98addfa14cc7..98e51a0d302a7 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/SqlFunctionTypeRegistry.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/SqlFunctionTypeRegistry.java @@ -9,12 +9,14 @@ import org.elasticsearch.xpack.ql.expression.function.DefaultFunctionTypeRegistry; import org.elasticsearch.xpack.ql.expression.function.Function; import org.elasticsearch.xpack.ql.expression.function.grouping.GroupingFunction; +import org.elasticsearch.xpack.sql.expression.predicate.conditional.ConditionalFunction; public class SqlFunctionTypeRegistry extends DefaultFunctionTypeRegistry { public static final SqlFunctionTypeRegistry INSTANCE = new SqlFunctionTypeRegistry(); private enum Types { + CONDITIONAL(ConditionalFunction.class), GROUPING(GroupingFunction.class), SCORE(Score.class); diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/aggregate/Avg.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/aggregate/Avg.java index e6940009dba79..b4fe32e663a3f 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/aggregate/Avg.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/aggregate/Avg.java @@ -10,6 +10,7 @@ import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import java.util.List; @@ -42,6 +43,6 @@ public String innerName() { @Override public DataType dataType() { - return DataType.DOUBLE; + return DataTypes.DOUBLE; } } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/aggregate/Max.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/aggregate/Max.java index 90117255dba46..3a370c45be5f9 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/aggregate/Max.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/aggregate/Max.java @@ -11,11 +11,12 @@ import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import java.util.List; import static org.elasticsearch.xpack.ql.expression.TypeResolutions.isExact; -import static org.elasticsearch.xpack.ql.expression.TypeResolutions.isNumericOrDateOrTime; +import static org.elasticsearch.xpack.sql.expression.SqlTypeResolutions.isNumericOrDateOrTime; /** * Find the maximum value in matching documents. @@ -48,7 +49,7 @@ public String innerName() { @Override protected TypeResolution resolveType() { - if (field().dataType().isString()) { + if (DataTypes.isString(field().dataType())) { return isExact(field(), sourceText(), ParamOrdinal.DEFAULT); } else { return isNumericOrDateOrTime(field(), sourceText(), ParamOrdinal.DEFAULT); diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/aggregate/MedianAbsoluteDeviation.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/aggregate/MedianAbsoluteDeviation.java index 858f128e8dd68..6fe9af2b7c8a1 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/aggregate/MedianAbsoluteDeviation.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/aggregate/MedianAbsoluteDeviation.java @@ -10,6 +10,7 @@ import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import java.util.List; @@ -21,7 +22,7 @@ public MedianAbsoluteDeviation(Source source, Expression field) { @Override public DataType dataType() { - return DataType.DOUBLE; + return DataTypes.DOUBLE; } @Override diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/aggregate/Min.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/aggregate/Min.java index 7eb6cc49df7ae..30f38f21e42cc 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/aggregate/Min.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/aggregate/Min.java @@ -11,11 +11,12 @@ import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import java.util.List; import static org.elasticsearch.xpack.ql.expression.TypeResolutions.isExact; -import static org.elasticsearch.xpack.ql.expression.TypeResolutions.isNumericOrDateOrTime; +import static org.elasticsearch.xpack.sql.expression.SqlTypeResolutions.isNumericOrDateOrTime; /** * Find the minimum value in matched documents. @@ -51,7 +52,7 @@ public String innerName() { @Override protected TypeResolution resolveType() { - if (field().dataType().isString()) { + if (DataTypes.isString(field().dataType())) { return isExact(field(), sourceText(), ParamOrdinal.DEFAULT); } else { return isNumericOrDateOrTime(field(), sourceText(), ParamOrdinal.DEFAULT); diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/aggregate/NumericAggregate.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/aggregate/NumericAggregate.java index 1bda9abf0edf7..d6e23fb619e97 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/aggregate/NumericAggregate.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/aggregate/NumericAggregate.java @@ -10,6 +10,7 @@ import org.elasticsearch.xpack.ql.expression.function.aggregate.AggregateFunction; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import java.util.List; @@ -32,6 +33,6 @@ protected TypeResolution resolveType() { @Override public DataType dataType() { - return DataType.DOUBLE; + return DataTypes.DOUBLE; } } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/aggregate/Percentile.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/aggregate/Percentile.java index 082a15da6a355..785cbb1a7a6be 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/aggregate/Percentile.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/aggregate/Percentile.java @@ -7,11 +7,12 @@ import org.elasticsearch.xpack.ql.expression.Expression; import org.elasticsearch.xpack.ql.expression.Expressions.ParamOrdinal; -import org.elasticsearch.xpack.ql.expression.Foldables; import org.elasticsearch.xpack.ql.expression.function.aggregate.EnclosedAgg; import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; +import org.elasticsearch.xpack.sql.expression.Foldables; import java.util.List; @@ -62,7 +63,7 @@ public Expression percent() { @Override public DataType dataType() { - return DataType.DOUBLE; + return DataTypes.DOUBLE; } @Override diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/aggregate/PercentileRank.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/aggregate/PercentileRank.java index 146bcc9324689..be253aa461917 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/aggregate/PercentileRank.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/aggregate/PercentileRank.java @@ -7,12 +7,13 @@ import org.elasticsearch.xpack.ql.expression.Expression; import org.elasticsearch.xpack.ql.expression.Expressions.ParamOrdinal; -import org.elasticsearch.xpack.ql.expression.Foldables; import org.elasticsearch.xpack.ql.expression.function.aggregate.AggregateFunction; import org.elasticsearch.xpack.ql.expression.function.aggregate.EnclosedAgg; import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; +import org.elasticsearch.xpack.sql.expression.Foldables; import java.util.List; @@ -63,7 +64,7 @@ public Expression value() { @Override public DataType dataType() { - return DataType.DOUBLE; + return DataTypes.DOUBLE; } @Override diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/grouping/Histogram.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/grouping/Histogram.java index 3937641b5b9e5..b7ec8c1d5e561 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/grouping/Histogram.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/grouping/Histogram.java @@ -13,6 +13,7 @@ import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.sql.type.SqlDataTypes; import java.time.ZoneId; import java.util.Collections; @@ -20,8 +21,8 @@ import java.util.Objects; import static org.elasticsearch.xpack.ql.expression.TypeResolutions.isNumeric; -import static org.elasticsearch.xpack.ql.expression.TypeResolutions.isNumericOrDate; import static org.elasticsearch.xpack.ql.expression.TypeResolutions.isType; +import static org.elasticsearch.xpack.sql.expression.SqlTypeResolutions.isNumericOrDate; public class Histogram extends GroupingFunction { @@ -47,8 +48,8 @@ protected TypeResolution resolveType() { TypeResolution resolution = isNumericOrDate(field(), "HISTOGRAM", ParamOrdinal.FIRST); if (resolution == TypeResolution.TYPE_RESOLVED) { // interval must be Literal interval - if (field().dataType().isDateBased()) { - resolution = isType(interval, DataType::isInterval, "(Date) HISTOGRAM", ParamOrdinal.SECOND, "interval"); + if (SqlDataTypes.isDateBased(field().dataType())) { + resolution = isType(interval, SqlDataTypes::isInterval, "(Date) HISTOGRAM", ParamOrdinal.SECOND, "interval"); } else { resolution = isNumeric(interval, "(Numeric) HISTOGRAM", ParamOrdinal.SECOND); } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/Cast.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/Cast.java index 31377efc2823d..461f0ea93e4ec 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/Cast.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/Cast.java @@ -14,7 +14,7 @@ import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; -import org.elasticsearch.xpack.ql.type.DataTypeConversion; +import org.elasticsearch.xpack.sql.type.SqlDataTypeConverter; import java.util.Objects; @@ -60,7 +60,7 @@ public boolean foldable() { @Override public Object fold() { - return DataTypeConversion.convert(field().fold(), dataType); + return SqlDataTypeConverter.convert(field().fold(), dataType); } @Override @@ -70,14 +70,14 @@ public Nullability nullable() { @Override protected TypeResolution resolveType() { - return DataTypeConversion.canConvert(from(), to()) ? + return SqlDataTypeConverter.canConvert(from(), to()) ? TypeResolution.TYPE_RESOLVED : new TypeResolution("Cannot cast [" + from() + "] to [" + to()+ "]"); } @Override protected Processor makeProcessor() { - return new CastProcessor(DataTypeConversion.conversionFor(from(), to())); + return new CastProcessor(SqlDataTypeConverter.converterFor(from(), to())); } @Override diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/CastProcessor.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/CastProcessor.java index f381485aa5410..d8f85fbb7fd99 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/CastProcessor.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/CastProcessor.java @@ -8,7 +8,7 @@ import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.xpack.ql.expression.gen.processor.Processor; -import org.elasticsearch.xpack.ql.type.DataTypeConversion.Conversion; +import org.elasticsearch.xpack.ql.type.Converter; import java.io.IOException; import java.util.Objects; @@ -17,14 +17,14 @@ public class CastProcessor implements Processor { public static final String NAME = "ca"; - private final Conversion conversion; + private final Converter conversion; - public CastProcessor(Conversion conversion) { + public CastProcessor(Converter conversion) { this.conversion = conversion; } public CastProcessor(StreamInput in) throws IOException { - conversion = in.readEnum(Conversion.class); + conversion = in.readNamedWriteable(Converter.class); } @Override @@ -34,7 +34,7 @@ public String getWriteableName() { @Override public void writeTo(StreamOutput out) throws IOException { - out.writeEnum(conversion); + out.writeNamedWriteable(conversion); } @Override @@ -42,7 +42,7 @@ public Object process(Object input) { return conversion.convert(input); } - Conversion converter() { + Converter converter() { return conversion; } @@ -67,6 +67,6 @@ public int hashCode() { @Override public String toString() { - return conversion.name(); + return conversion.getClass().getSimpleName(); } } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/Database.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/Database.java index eb4d25bdbb520..3acd89bc0d7de 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/Database.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/Database.java @@ -9,12 +9,12 @@ import org.elasticsearch.xpack.ql.session.Configuration; import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; -import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; public class Database extends ConfigurationFunction { public Database(Source source, Configuration configuration) { - super(source, configuration, DataType.KEYWORD); + super(source, configuration, DataTypes.KEYWORD); } @Override diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/Processors.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/Processors.java index d324413577883..e842a3f25eca8 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/Processors.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/Processors.java @@ -8,6 +8,8 @@ import org.elasticsearch.common.io.stream.NamedWriteableRegistry; import org.elasticsearch.common.io.stream.NamedWriteableRegistry.Entry; import org.elasticsearch.xpack.ql.expression.gen.processor.Processor; +import org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.BinaryArithmeticOperation; +import org.elasticsearch.xpack.ql.type.Converter; import org.elasticsearch.xpack.sql.expression.function.scalar.datetime.DateAddProcessor; import org.elasticsearch.xpack.sql.expression.function.scalar.datetime.DateDiffProcessor; import org.elasticsearch.xpack.sql.expression.function.scalar.datetime.DatePartProcessor; @@ -31,6 +33,13 @@ import org.elasticsearch.xpack.sql.expression.function.scalar.string.ReplaceFunctionProcessor; import org.elasticsearch.xpack.sql.expression.function.scalar.string.StringProcessor; import org.elasticsearch.xpack.sql.expression.function.scalar.string.SubstringFunctionProcessor; +import org.elasticsearch.xpack.sql.expression.predicate.conditional.CaseProcessor; +import org.elasticsearch.xpack.sql.expression.predicate.conditional.ConditionalProcessor; +import org.elasticsearch.xpack.sql.expression.predicate.conditional.NullIfProcessor; +import org.elasticsearch.xpack.sql.expression.predicate.nulls.CheckNullProcessor; +import org.elasticsearch.xpack.sql.expression.predicate.operator.arithmetic.SqlBinaryArithmeticOperation; +import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.InProcessor; +import org.elasticsearch.xpack.sql.type.SqlDataTypeConverter.SqlConverter; import java.util.ArrayList; import java.util.List; @@ -50,6 +59,20 @@ public static List getNamedWriteables() { // base entries.add(new Entry(Processor.class, CastProcessor.NAME, CastProcessor::new)); + entries.add(new Entry(Converter.class, SqlConverter.NAME, SqlConverter::read)); + + // arithmetic + // binary arithmetics are pluggable + entries.add(new Entry(BinaryArithmeticOperation.class, SqlBinaryArithmeticOperation.NAME, SqlBinaryArithmeticOperation::read)); + + // comparators + entries.add(new Entry(Processor.class, InProcessor.NAME, InProcessor::new)); + + // conditionals + entries.add(new Entry(Processor.class, CaseProcessor.NAME, CaseProcessor::new)); + entries.add(new Entry(Processor.class, CheckNullProcessor.NAME, CheckNullProcessor::new)); + entries.add(new Entry(Processor.class, ConditionalProcessor.NAME, ConditionalProcessor::new)); + entries.add(new Entry(Processor.class, NullIfProcessor.NAME, NullIfProcessor::new)); // datetime entries.add(new Entry(Processor.class, DateTimeProcessor.NAME, DateTimeProcessor::new)); diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/User.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/User.java index 737d10430fb7e..dd2c24950298c 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/User.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/User.java @@ -9,12 +9,12 @@ import org.elasticsearch.xpack.ql.session.Configuration; import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; -import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; public class User extends ConfigurationFunction { public User(Source source, Configuration configuration) { - super(source, configuration, DataType.KEYWORD); + super(source, configuration, DataTypes.KEYWORD); } @Override diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/BaseDateTimeFunction.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/BaseDateTimeFunction.java index 66cd1b1a3add2..eaa0a43d05153 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/BaseDateTimeFunction.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/BaseDateTimeFunction.java @@ -15,7 +15,7 @@ import java.time.ZoneId; import java.util.Objects; -import static org.elasticsearch.xpack.ql.expression.TypeResolutions.isDate; +import static org.elasticsearch.xpack.sql.expression.SqlTypeResolutions.isDate; abstract class BaseDateTimeFunction extends UnaryScalarFunction { diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/BinaryDateTimeFunction.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/BinaryDateTimeFunction.java index dc68e04fcd758..c6855eccee8cd 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/BinaryDateTimeFunction.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/BinaryDateTimeFunction.java @@ -17,9 +17,9 @@ import java.util.Objects; import static org.elasticsearch.common.logging.LoggerMessageFormat.format; -import static org.elasticsearch.xpack.ql.expression.TypeResolutions.isDate; import static org.elasticsearch.xpack.ql.expression.TypeResolutions.isString; import static org.elasticsearch.xpack.ql.expression.gen.script.ParamsBuilder.paramsBuilder; +import static org.elasticsearch.xpack.sql.expression.SqlTypeResolutions.isDate; public abstract class BinaryDateTimeFunction extends BinaryScalarFunction { diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/CurrentDate.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/CurrentDate.java index 284e0601658e2..5265932b16155 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/CurrentDate.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/CurrentDate.java @@ -9,7 +9,7 @@ import org.elasticsearch.xpack.ql.session.Configuration; import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; -import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.sql.type.SqlDataTypes; import org.elasticsearch.xpack.sql.util.DateUtils; import java.time.ZonedDateTime; @@ -17,7 +17,7 @@ public class CurrentDate extends CurrentFunction { public CurrentDate(Source source, Configuration configuration) { - super(source, configuration, DateUtils.asDateOnly(configuration.now()), DataType.DATE); + super(source, configuration, DateUtils.asDateOnly(configuration.now()), SqlDataTypes.DATE); } @Override diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/CurrentDateTime.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/CurrentDateTime.java index 0ecf891c4797e..1ff640d7915c4 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/CurrentDateTime.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/CurrentDateTime.java @@ -10,7 +10,7 @@ import org.elasticsearch.xpack.ql.session.Configuration; import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; -import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import java.time.ZonedDateTime; @@ -21,7 +21,7 @@ public class CurrentDateTime extends CurrentFunction { private final Expression precision; public CurrentDateTime(Source source, Expression precision, Configuration configuration) { - super(source, configuration, nanoPrecision(configuration.now(), precision), DataType.DATETIME); + super(source, configuration, nanoPrecision(configuration.now(), precision), DataTypes.DATETIME); this.precision = precision; } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/CurrentTime.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/CurrentTime.java index 4603941db52f4..a09d7149f4f56 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/CurrentTime.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/CurrentTime.java @@ -10,7 +10,7 @@ import org.elasticsearch.xpack.ql.session.Configuration; import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; -import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.sql.type.SqlDataTypes; import java.time.OffsetTime; @@ -22,7 +22,7 @@ public class CurrentTime extends CurrentFunction { public CurrentTime(Source source, Expression precision, Configuration configuration) { super(source, configuration, nanoPrecision(configuration.now().toOffsetDateTime().toOffsetTime(), precision), - DataType.TIME); + SqlDataTypes.TIME); this.precision = precision; } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/DateAdd.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/DateAdd.java index fc4694c5a70b5..e20bf7679886d 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/DateAdd.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/DateAdd.java @@ -11,6 +11,7 @@ import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import java.time.ZoneId; import java.time.ZonedDateTime; @@ -21,9 +22,9 @@ import java.util.function.BiFunction; import static org.elasticsearch.common.logging.LoggerMessageFormat.format; -import static org.elasticsearch.xpack.ql.expression.TypeResolutions.isDate; import static org.elasticsearch.xpack.ql.expression.TypeResolutions.isInteger; import static org.elasticsearch.xpack.ql.expression.TypeResolutions.isString; +import static org.elasticsearch.xpack.sql.expression.SqlTypeResolutions.isDate; public class DateAdd extends ThreeArgsDateTimeFunction { @@ -120,7 +121,7 @@ protected TypeResolution resolveType() { @Override public DataType dataType() { - return DataType.DATETIME; + return DataTypes.DATETIME; } @Override diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/DateDiff.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/DateDiff.java index 76a461d294dec..a2a1a788c2130 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/DateDiff.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/DateDiff.java @@ -12,6 +12,7 @@ import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import org.elasticsearch.xpack.sql.SqlIllegalArgumentException; import java.time.ZoneId; @@ -23,8 +24,8 @@ import java.util.function.BiFunction; import static org.elasticsearch.common.logging.LoggerMessageFormat.format; -import static org.elasticsearch.xpack.ql.expression.TypeResolutions.isDate; import static org.elasticsearch.xpack.ql.expression.TypeResolutions.isString; +import static org.elasticsearch.xpack.sql.expression.SqlTypeResolutions.isDate; import static org.elasticsearch.xpack.sql.util.DateUtils.DAY_IN_MILLIS; import static org.elasticsearch.xpack.sql.util.DateUtils.UTC; @@ -168,7 +169,7 @@ protected TypeResolution resolveType() { @Override public DataType dataType() { - return DataType.INTEGER; + return DataTypes.INTEGER; } @Override diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/DatePart.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/DatePart.java index b84115444529b..2349dc9dd9c9b 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/DatePart.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/DatePart.java @@ -11,6 +11,7 @@ import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import org.elasticsearch.xpack.sql.expression.function.scalar.datetime.DateTimeProcessor.DateTimeExtractor; import org.elasticsearch.xpack.sql.expression.function.scalar.datetime.NonIsoDateTimeProcessor.NonIsoDateTimeExtractor; @@ -80,7 +81,7 @@ public DatePart(Source source, Expression dateTimePart, Expression timestamp, Zo @Override public DataType dataType() { - return DataType.INTEGER; + return DataTypes.INTEGER; } @Override diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/DateTimeFunction.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/DateTimeFunction.java index d4fbb998a3fc4..7ec72d7061e6d 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/DateTimeFunction.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/DateTimeFunction.java @@ -11,6 +11,7 @@ import org.elasticsearch.xpack.ql.expression.gen.script.ScriptTemplate; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import org.elasticsearch.xpack.sql.expression.function.scalar.datetime.DateTimeProcessor.DateTimeExtractor; import java.time.ZoneId; @@ -58,7 +59,7 @@ protected Processor makeProcessor() { @Override public DataType dataType() { - return DataType.INTEGER; + return DataTypes.INTEGER; } // used for applying ranges diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/DateTrunc.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/DateTrunc.java index ed600286856fe..9b336ddaed0e7 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/DateTrunc.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/DateTrunc.java @@ -11,6 +11,7 @@ import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import java.time.ZoneId; import java.time.ZonedDateTime; @@ -136,7 +137,7 @@ public DateTrunc(Source source, Expression truncateTo, Expression timestamp, Zon @Override public DataType dataType() { - return DataType.DATETIME; + return DataTypes.DATETIME; } @Override diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/NamedDateTimeFunction.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/NamedDateTimeFunction.java index c9752052bc6d2..920d5a85afc49 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/NamedDateTimeFunction.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/NamedDateTimeFunction.java @@ -11,6 +11,7 @@ import org.elasticsearch.xpack.ql.expression.gen.script.ScriptTemplate; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import org.elasticsearch.xpack.ql.util.StringUtils; import org.elasticsearch.xpack.sql.expression.function.scalar.datetime.NamedDateTimeProcessor.NameExtractor; @@ -48,6 +49,6 @@ protected Processor makeProcessor() { @Override public DataType dataType() { - return DataType.KEYWORD; + return DataTypes.KEYWORD; } } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/NonIsoDateTimeFunction.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/NonIsoDateTimeFunction.java index b9e8618ee2dab..a558dfed724d7 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/NonIsoDateTimeFunction.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/NonIsoDateTimeFunction.java @@ -11,6 +11,7 @@ import org.elasticsearch.xpack.ql.expression.gen.script.ScriptTemplate; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import org.elasticsearch.xpack.ql.util.StringUtils; import org.elasticsearch.xpack.sql.expression.function.scalar.datetime.NonIsoDateTimeProcessor.NonIsoDateTimeExtractor; @@ -48,6 +49,6 @@ protected Processor makeProcessor() { @Override public DataType dataType() { - return DataType.INTEGER; + return DataTypes.INTEGER; } } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/Quarter.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/Quarter.java index 0f272e9c82425..3b981a689a0f2 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/Quarter.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/Quarter.java @@ -13,6 +13,7 @@ import org.elasticsearch.xpack.ql.tree.NodeInfo.NodeCtor2; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import java.time.ZoneId; @@ -51,6 +52,6 @@ protected Processor makeProcessor() { @Override public DataType dataType() { - return DataType.INTEGER; + return DataTypes.INTEGER; } } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/TimeFunction.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/TimeFunction.java index dd865f33ac240..887959b5966ad 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/TimeFunction.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/TimeFunction.java @@ -15,7 +15,7 @@ import java.time.ZoneId; import java.time.temporal.ChronoField; -import static org.elasticsearch.xpack.ql.expression.TypeResolutions.isDateOrTime; +import static org.elasticsearch.xpack.sql.expression.SqlTypeResolutions.isDateOrTime; import static org.elasticsearch.xpack.sql.util.DateUtils.asTimeAtZone; public abstract class TimeFunction extends DateTimeFunction { diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/geo/GeoProcessor.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/geo/GeoProcessor.java index f12521934d103..d9b188a6a96d6 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/geo/GeoProcessor.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/geo/GeoProcessor.java @@ -7,9 +7,9 @@ import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; -import org.elasticsearch.xpack.ql.expression.function.scalar.geo.GeoShape; import org.elasticsearch.xpack.ql.expression.gen.processor.Processor; import org.elasticsearch.xpack.sql.SqlIllegalArgumentException; +import org.elasticsearch.xpack.sql.expression.literal.geo.GeoShape; import java.io.IOException; import java.util.function.Function; diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/geo/StAswkt.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/geo/StAswkt.java index c7cf15b7ac830..ee45b3b646518 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/geo/StAswkt.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/geo/StAswkt.java @@ -11,6 +11,7 @@ import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import org.elasticsearch.xpack.sql.expression.function.scalar.geo.GeoProcessor.GeoOperation; /** @@ -39,7 +40,7 @@ protected GeoOperation operation() { @Override public DataType dataType() { - return DataType.KEYWORD; + return DataTypes.KEYWORD; } } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/geo/StDistance.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/geo/StDistance.java index 4c7c2dead19a9..1dc7f2efbfbf5 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/geo/StDistance.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/geo/StDistance.java @@ -15,9 +15,10 @@ import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; -import static org.elasticsearch.xpack.ql.expression.TypeResolutions.isGeo; import static org.elasticsearch.xpack.ql.expression.gen.script.ParamsBuilder.paramsBuilder; +import static org.elasticsearch.xpack.sql.expression.SqlTypeResolutions.isGeo; /** * Calculates the distance between two points @@ -37,7 +38,7 @@ protected StDistance replaceChildren(Expression newLeft, Expression newRight) { @Override public DataType dataType() { - return DataType.DOUBLE; + return DataTypes.DOUBLE; } @Override diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/geo/StDistanceProcessor.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/geo/StDistanceProcessor.java index 4ca6b89916eaa..86e9068643bd4 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/geo/StDistanceProcessor.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/geo/StDistanceProcessor.java @@ -8,10 +8,10 @@ import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; -import org.elasticsearch.xpack.ql.expression.function.scalar.geo.GeoShape; import org.elasticsearch.xpack.ql.expression.gen.processor.BinaryProcessor; import org.elasticsearch.xpack.ql.expression.gen.processor.Processor; import org.elasticsearch.xpack.sql.SqlIllegalArgumentException; +import org.elasticsearch.xpack.sql.expression.literal.geo.GeoShape; import java.io.IOException; import java.util.Objects; diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/geo/StGeometryType.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/geo/StGeometryType.java index 6a81f4c7ce109..d3c49931906cb 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/geo/StGeometryType.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/geo/StGeometryType.java @@ -11,6 +11,7 @@ import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import org.elasticsearch.xpack.sql.expression.function.scalar.geo.GeoProcessor.GeoOperation; /** @@ -39,7 +40,7 @@ protected GeoOperation operation() { @Override public DataType dataType() { - return DataType.KEYWORD; + return DataTypes.KEYWORD; } } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/geo/StWkttosql.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/geo/StWkttosql.java index b35eef4c3150b..fc3c026c5fa46 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/geo/StWkttosql.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/geo/StWkttosql.java @@ -14,6 +14,8 @@ import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; +import org.elasticsearch.xpack.sql.type.SqlDataTypes; import static org.elasticsearch.xpack.ql.expression.TypeResolutions.isString; @@ -33,7 +35,7 @@ protected StWkttosql replaceChild(Expression newChild) { @Override protected TypeResolution resolveType() { - if (field().dataType().isString()) { + if (DataTypes.isString(field().dataType())) { return TypeResolution.TYPE_RESOLVED; } return isString(field(), sourceText(), Expressions.ParamOrdinal.DEFAULT); @@ -46,7 +48,7 @@ protected Processor makeProcessor() { @Override public DataType dataType() { - return DataType.GEO_SHAPE; + return SqlDataTypes.GEO_SHAPE; } @Override diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/geo/StWkttosqlProcessor.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/geo/StWkttosqlProcessor.java index d2965bd6a0168..2057e8eb2ace2 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/geo/StWkttosqlProcessor.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/geo/StWkttosqlProcessor.java @@ -9,9 +9,9 @@ import org.elasticsearch.ElasticsearchParseException; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; -import org.elasticsearch.xpack.ql.expression.function.scalar.geo.GeoShape; import org.elasticsearch.xpack.ql.expression.gen.processor.Processor; import org.elasticsearch.xpack.sql.SqlIllegalArgumentException; +import org.elasticsearch.xpack.sql.expression.literal.geo.GeoShape; import java.io.IOException; diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/geo/StX.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/geo/StX.java index f6e348e0f0c85..7f2d78c132490 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/geo/StX.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/geo/StX.java @@ -11,6 +11,7 @@ import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import org.elasticsearch.xpack.sql.expression.function.scalar.geo.GeoProcessor.GeoOperation; /** @@ -39,7 +40,7 @@ protected GeoOperation operation() { @Override public DataType dataType() { - return DataType.DOUBLE; + return DataTypes.DOUBLE; } } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/geo/StY.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/geo/StY.java index 483292f682b26..a727427010f04 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/geo/StY.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/geo/StY.java @@ -11,6 +11,7 @@ import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import org.elasticsearch.xpack.sql.expression.function.scalar.geo.GeoProcessor.GeoOperation; /** @@ -39,7 +40,7 @@ protected GeoOperation operation() { @Override public DataType dataType() { - return DataType.DOUBLE; + return DataTypes.DOUBLE; } } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/geo/StZ.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/geo/StZ.java index 567e801b48482..85d5b9271acb3 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/geo/StZ.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/geo/StZ.java @@ -11,6 +11,7 @@ import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import org.elasticsearch.xpack.sql.expression.function.scalar.geo.GeoProcessor.GeoOperation; /** @@ -39,7 +40,7 @@ protected GeoOperation operation() { @Override public DataType dataType() { - return DataType.DOUBLE; + return DataTypes.DOUBLE; } } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/geo/UnaryGeoFunction.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/geo/UnaryGeoFunction.java index 1ff4fcc6040b2..fa15209773ba6 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/geo/UnaryGeoFunction.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/geo/UnaryGeoFunction.java @@ -19,8 +19,8 @@ import java.util.Objects; import static java.lang.String.format; -import static org.elasticsearch.xpack.ql.expression.TypeResolutions.isGeo; import static org.elasticsearch.xpack.ql.expression.gen.script.ParamsBuilder.paramsBuilder; +import static org.elasticsearch.xpack.sql.expression.SqlTypeResolutions.isGeo; /** * Base class for functions that get a single geo shape or geo point as an argument diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/BinaryMathProcessor.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/BinaryMathProcessor.java index c5adab6bb7f3e..413f77ff28aea 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/BinaryMathProcessor.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/BinaryMathProcessor.java @@ -6,7 +6,7 @@ package org.elasticsearch.xpack.sql.expression.function.scalar.math; import org.elasticsearch.common.io.stream.StreamInput; -import org.elasticsearch.xpack.ql.expression.gen.processor.FunctionalBinaryProcessor; +import org.elasticsearch.xpack.ql.expression.gen.processor.FunctionalEnumBinaryProcessor; import org.elasticsearch.xpack.ql.expression.gen.processor.Processor; import org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.Arithmetics; import org.elasticsearch.xpack.sql.SqlIllegalArgumentException; @@ -19,7 +19,7 @@ /** * Binary math operations. Sister class to {@link MathOperation}. */ -public class BinaryMathProcessor extends FunctionalBinaryProcessor { +public class BinaryMathProcessor extends FunctionalEnumBinaryProcessor { public enum BinaryMathOperation implements BiFunction { diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/BinaryNumericFunction.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/BinaryNumericFunction.java index 862282387b528..a799e240d5442 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/BinaryNumericFunction.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/BinaryNumericFunction.java @@ -12,6 +12,7 @@ import org.elasticsearch.xpack.ql.expression.gen.pipeline.Pipe; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import org.elasticsearch.xpack.sql.expression.function.scalar.math.BinaryMathProcessor.BinaryMathOperation; import java.util.Objects; @@ -29,7 +30,7 @@ public abstract class BinaryNumericFunction extends BinaryScalarFunction { @Override public DataType dataType() { - return DataType.DOUBLE; + return DataTypes.DOUBLE; } @Override diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/BinaryOptionalNumericFunction.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/BinaryOptionalNumericFunction.java index bd0afb2d2ac1c..b0f2d0f5c3a5f 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/BinaryOptionalNumericFunction.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/BinaryOptionalNumericFunction.java @@ -9,6 +9,7 @@ import org.elasticsearch.xpack.ql.expression.Expression; import org.elasticsearch.xpack.ql.expression.Expressions; import org.elasticsearch.xpack.ql.expression.Expressions.ParamOrdinal; +import org.elasticsearch.xpack.ql.expression.Literal; import org.elasticsearch.xpack.ql.expression.function.scalar.ScalarFunction; import org.elasticsearch.xpack.ql.expression.gen.pipeline.Pipe; import org.elasticsearch.xpack.ql.expression.gen.script.ScriptTemplate; @@ -88,7 +89,7 @@ public Expression replaceChildren(List newChildren) { @Override public ScriptTemplate asScript() { ScriptTemplate leftScript = asScript(left); - ScriptTemplate rightScript = asOptionalScript(right); + ScriptTemplate rightScript = asScript(right == null ? Literal.NULL : right); return asScriptFrom(leftScript, rightScript); } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/Ceil.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/Ceil.java index 7d709c49123e0..0727197f1e51e 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/Ceil.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/Ceil.java @@ -9,7 +9,7 @@ import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; -import org.elasticsearch.xpack.ql.type.DataTypeConversion; +import org.elasticsearch.xpack.ql.type.DataTypeConverter; import org.elasticsearch.xpack.sql.expression.function.scalar.math.MathProcessor.MathOperation; /** @@ -37,7 +37,7 @@ public Number fold() { if (result == null) { return null; } - return DataTypeConversion.toInteger((double) result, dataType()); + return DataTypeConverter.toInteger((double) result, dataType()); } @Override @@ -47,6 +47,6 @@ protected MathOperation operation() { @Override public DataType dataType() { - return DataTypeConversion.asInteger(field().dataType()); + return DataTypeConverter.asInteger(field().dataType()); } } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/E.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/E.java index b07cb57c33d67..28a58f3a8717f 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/E.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/E.java @@ -12,15 +12,15 @@ import org.elasticsearch.xpack.ql.expression.gen.script.ScriptTemplate; import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; -import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import org.elasticsearch.xpack.sql.expression.function.scalar.math.MathProcessor.MathOperation; public class E extends MathFunction { - private static final ScriptTemplate TEMPLATE = new ScriptTemplate("Math.E", Params.EMPTY, DataType.DOUBLE); + private static final ScriptTemplate TEMPLATE = new ScriptTemplate("Math.E", Params.EMPTY, DataTypes.DOUBLE); public E(Source source) { - super(source, new Literal(source, Math.E, DataType.DOUBLE)); + super(source, new Literal(source, Math.E, DataTypes.DOUBLE)); } @Override diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/Floor.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/Floor.java index e1ba4bdd3c7b4..9e66623a0b1d4 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/Floor.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/Floor.java @@ -9,7 +9,7 @@ import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; -import org.elasticsearch.xpack.ql.type.DataTypeConversion; +import org.elasticsearch.xpack.ql.type.DataTypeConverter; import org.elasticsearch.xpack.sql.expression.function.scalar.math.MathProcessor.MathOperation; /** @@ -37,7 +37,7 @@ public Object fold() { if (result == null) { return null; } - return DataTypeConversion.toInteger((double) result, dataType()); + return DataTypeConverter.toInteger((double) result, dataType()); } @Override @@ -47,6 +47,6 @@ protected MathOperation operation() { @Override public DataType dataType() { - return DataTypeConversion.asInteger(field().dataType()); + return DataTypeConverter.asInteger(field().dataType()); } } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/MathFunction.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/MathFunction.java index ec084f70def67..0bbcf75dbb89f 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/MathFunction.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/MathFunction.java @@ -11,6 +11,7 @@ import org.elasticsearch.xpack.ql.expression.gen.processor.Processor; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import org.elasticsearch.xpack.sql.expression.function.scalar.math.MathProcessor.MathOperation; import java.util.Locale; @@ -47,7 +48,7 @@ public String processScript(String template) { @Override public DataType dataType() { - return DataType.DOUBLE; + return DataTypes.DOUBLE; } @Override diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/MathProcessor.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/MathProcessor.java index bc13b8ef36f21..07acf3a43149c 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/MathProcessor.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/MathProcessor.java @@ -10,7 +10,7 @@ import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.xpack.ql.QlIllegalArgumentException; import org.elasticsearch.xpack.ql.expression.gen.processor.Processor; -import org.elasticsearch.xpack.ql.type.DataTypeConversion; +import org.elasticsearch.xpack.ql.type.DataTypeConverter; import org.elasticsearch.xpack.sql.SqlIllegalArgumentException; import java.io.IOException; @@ -43,14 +43,14 @@ public enum MathOperation { if ((int) lo == Integer.MIN_VALUE) { throw new QlIllegalArgumentException("[" + lo + "] cannot be negated since the result is outside the range"); } - return DataTypeConversion.safeToInt(lo); + return DataTypeConverter.safeToInt(lo); } if (l instanceof Short) { - return DataTypeConversion.safeToShort(lo); + return DataTypeConverter.safeToShort(lo); } if (l instanceof Byte) { - return DataTypeConversion.safeToByte(lo); + return DataTypeConverter.safeToByte(lo); } return lo; @@ -86,13 +86,13 @@ public enum MathOperation { long lo = Long.signum(((Number) l).longValue()); if (l instanceof Integer) { - return DataTypeConversion.safeToInt(lo); + return DataTypeConverter.safeToInt(lo); } if (l instanceof Short) { - return DataTypeConversion.safeToShort(lo); + return DataTypeConverter.safeToShort(lo); } if (l instanceof Byte) { - return DataTypeConversion.safeToByte(lo); + return DataTypeConverter.safeToByte(lo); } //fallback to generic double diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/Pi.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/Pi.java index d0855016969bb..145f380d5bba2 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/Pi.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/Pi.java @@ -12,15 +12,15 @@ import org.elasticsearch.xpack.ql.expression.gen.script.ScriptTemplate; import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; -import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import org.elasticsearch.xpack.sql.expression.function.scalar.math.MathProcessor.MathOperation; public class Pi extends MathFunction { - private static final ScriptTemplate TEMPLATE = new ScriptTemplate("Math.PI", Params.EMPTY, DataType.DOUBLE); + private static final ScriptTemplate TEMPLATE = new ScriptTemplate("Math.PI", Params.EMPTY, DataTypes.DOUBLE); public Pi(Source source) { - super(source, new Literal(source, Math.PI, DataType.DOUBLE)); + super(source, new Literal(source, Math.PI, DataTypes.DOUBLE)); } @Override diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/Sign.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/Sign.java index 5c70470b0e73b..5167311c18844 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/Sign.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/Sign.java @@ -9,6 +9,7 @@ import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import org.elasticsearch.xpack.sql.expression.function.scalar.math.MathProcessor.MathOperation; /** @@ -41,6 +42,6 @@ protected MathOperation operation() { @Override public DataType dataType() { - return DataType.INTEGER; + return DataTypes.INTEGER; } } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/Ascii.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/Ascii.java index 6edad9dc48930..08b1d1b611e6b 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/Ascii.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/Ascii.java @@ -9,6 +9,7 @@ import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import org.elasticsearch.xpack.sql.expression.function.scalar.string.StringProcessor.StringOperation; /** @@ -37,6 +38,6 @@ protected StringOperation operation() { @Override public DataType dataType() { - return DataType.INTEGER; + return DataTypes.INTEGER; } } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/BinaryStringNumericFunction.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/BinaryStringNumericFunction.java index 687b49561d33f..9508c6095d09a 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/BinaryStringNumericFunction.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/BinaryStringNumericFunction.java @@ -10,6 +10,7 @@ import org.elasticsearch.xpack.ql.expression.gen.pipeline.Pipe; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import org.elasticsearch.xpack.sql.expression.function.scalar.string.BinaryStringNumericProcessor.BinaryStringNumericOperation; import static org.elasticsearch.xpack.ql.expression.TypeResolutions.isNumeric; @@ -38,6 +39,6 @@ protected Pipe makePipe() { @Override public DataType dataType() { - return DataType.KEYWORD; + return DataTypes.KEYWORD; } } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/BinaryStringNumericProcessor.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/BinaryStringNumericProcessor.java index 2c7e77d69c222..64e84351f9d85 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/BinaryStringNumericProcessor.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/BinaryStringNumericProcessor.java @@ -6,7 +6,7 @@ package org.elasticsearch.xpack.sql.expression.function.scalar.string; import org.elasticsearch.common.io.stream.StreamInput; -import org.elasticsearch.xpack.ql.expression.gen.processor.FunctionalBinaryProcessor; +import org.elasticsearch.xpack.ql.expression.gen.processor.FunctionalEnumBinaryProcessor; import org.elasticsearch.xpack.ql.expression.gen.processor.Processor; import org.elasticsearch.xpack.sql.SqlIllegalArgumentException; import org.elasticsearch.xpack.sql.expression.function.scalar.string.BinaryStringNumericProcessor.BinaryStringNumericOperation; @@ -18,7 +18,7 @@ * Processor class covering string manipulating functions that have the first parameter as string, * second parameter as numeric and a string result. */ -public class BinaryStringNumericProcessor extends FunctionalBinaryProcessor { +public class BinaryStringNumericProcessor extends FunctionalEnumBinaryProcessor { public enum BinaryStringNumericOperation implements BiFunction { LEFT((s,c) -> { diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/BinaryStringStringFunction.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/BinaryStringStringFunction.java index 3f3db4fdaf2b9..d93553ce316bb 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/BinaryStringStringFunction.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/BinaryStringStringFunction.java @@ -9,6 +9,7 @@ import org.elasticsearch.xpack.ql.expression.Expressions; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import static org.elasticsearch.xpack.ql.expression.TypeResolutions.isStringAndExact; @@ -28,6 +29,6 @@ protected TypeResolution resolveSecondParameterInputType(Expression e) { @Override public DataType dataType() { - return DataType.INTEGER; + return DataTypes.INTEGER; } } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/BinaryStringStringProcessor.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/BinaryStringStringProcessor.java index f3ca9344c8cc2..ad2e1232cda05 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/BinaryStringStringProcessor.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/BinaryStringStringProcessor.java @@ -6,7 +6,7 @@ package org.elasticsearch.xpack.sql.expression.function.scalar.string; import org.elasticsearch.common.io.stream.StreamInput; -import org.elasticsearch.xpack.ql.expression.gen.processor.FunctionalBinaryProcessor; +import org.elasticsearch.xpack.ql.expression.gen.processor.FunctionalEnumBinaryProcessor; import org.elasticsearch.xpack.ql.expression.gen.processor.Processor; import org.elasticsearch.xpack.sql.SqlIllegalArgumentException; import org.elasticsearch.xpack.sql.expression.function.scalar.string.BinaryStringStringProcessor.BinaryStringStringOperation; @@ -17,7 +17,7 @@ /** * Processor class covering string manipulating functions that have two string parameters and a numeric result. */ -public class BinaryStringStringProcessor extends FunctionalBinaryProcessor { +public class BinaryStringStringProcessor extends FunctionalEnumBinaryProcessor { public enum BinaryStringStringOperation implements BiFunction { POSITION((sub,str) -> { diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/BitLength.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/BitLength.java index ce308b361a119..e9512d47fe576 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/BitLength.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/BitLength.java @@ -9,6 +9,7 @@ import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import org.elasticsearch.xpack.sql.expression.function.scalar.string.StringProcessor.StringOperation; /** @@ -38,6 +39,6 @@ protected StringOperation operation() { @Override public DataType dataType() { //TODO investigate if a data type Long (BIGINT) wouldn't be more appropriate here - return DataType.INTEGER; + return DataTypes.INTEGER; } } \ No newline at end of file diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/Char.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/Char.java index 4a0a44b501e38..b37d02dbbef26 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/Char.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/Char.java @@ -9,6 +9,7 @@ import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import org.elasticsearch.xpack.sql.expression.function.scalar.string.StringProcessor.StringOperation; /** @@ -37,6 +38,6 @@ protected StringOperation operation() { @Override public DataType dataType() { - return DataType.KEYWORD; + return DataTypes.KEYWORD; } } \ No newline at end of file diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/CharLength.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/CharLength.java index 8b6df6a5cbafb..a19039f79b3c9 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/CharLength.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/CharLength.java @@ -9,6 +9,7 @@ import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import org.elasticsearch.xpack.sql.expression.function.scalar.string.StringProcessor.StringOperation; /** @@ -37,6 +38,6 @@ protected StringOperation operation() { @Override public DataType dataType() { - return DataType.INTEGER; + return DataTypes.INTEGER; } } \ No newline at end of file diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/Concat.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/Concat.java index ec9656eeb8e48..f811de23e0f7c 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/Concat.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/Concat.java @@ -16,6 +16,7 @@ import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import static org.elasticsearch.xpack.ql.expression.TypeResolutions.isStringAndExact; import static org.elasticsearch.xpack.ql.expression.gen.script.ParamsBuilder.paramsBuilder; @@ -85,6 +86,6 @@ public ScriptTemplate scriptWithField(FieldAttribute field) { @Override public DataType dataType() { - return DataType.KEYWORD; + return DataTypes.KEYWORD; } } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/Insert.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/Insert.java index 8be5b2b24535a..7b0ef796c0f4b 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/Insert.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/Insert.java @@ -15,6 +15,7 @@ import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import java.util.Arrays; import java.util.List; @@ -127,7 +128,7 @@ public ScriptTemplate scriptWithField(FieldAttribute field) { @Override public DataType dataType() { - return DataType.KEYWORD; + return DataTypes.KEYWORD; } @Override diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/LCase.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/LCase.java index 74e8a51757f48..e04a93d62186a 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/LCase.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/LCase.java @@ -9,6 +9,7 @@ import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import org.elasticsearch.xpack.sql.expression.function.scalar.string.StringProcessor.StringOperation; /** @@ -37,6 +38,6 @@ protected StringOperation operation() { @Override public DataType dataType() { - return DataType.KEYWORD; + return DataTypes.KEYWORD; } } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/LTrim.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/LTrim.java index d3339f7a8bec9..c3c61443d9f44 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/LTrim.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/LTrim.java @@ -9,6 +9,7 @@ import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import org.elasticsearch.xpack.sql.expression.function.scalar.string.StringProcessor.StringOperation; /** @@ -37,7 +38,7 @@ protected StringOperation operation() { @Override public DataType dataType() { - return DataType.KEYWORD; + return DataTypes.KEYWORD; } } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/Length.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/Length.java index 4c713c8e6b8ed..adced21088c5a 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/Length.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/Length.java @@ -9,6 +9,7 @@ import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import org.elasticsearch.xpack.sql.expression.function.scalar.string.StringProcessor.StringOperation; /** @@ -37,7 +38,7 @@ protected StringOperation operation() { @Override public DataType dataType() { - return DataType.INTEGER; + return DataTypes.INTEGER; } } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/Locate.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/Locate.java index 5ac8afc7fb51a..f45bd075a9499 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/Locate.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/Locate.java @@ -16,6 +16,7 @@ import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import java.util.Arrays; import java.util.List; @@ -129,7 +130,7 @@ public ScriptTemplate scriptWithField(FieldAttribute field) { @Override public DataType dataType() { - return DataType.INTEGER; + return DataTypes.INTEGER; } @Override diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/OctetLength.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/OctetLength.java index 0f7ab3fc5f027..d594d60f85da5 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/OctetLength.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/OctetLength.java @@ -9,6 +9,7 @@ import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import org.elasticsearch.xpack.sql.expression.function.scalar.string.StringProcessor.StringOperation; /** @@ -37,6 +38,6 @@ protected StringOperation operation() { @Override public DataType dataType() { - return DataType.INTEGER; + return DataTypes.INTEGER; } } \ No newline at end of file diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/RTrim.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/RTrim.java index 53f65067cfd54..1a6c90073aac2 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/RTrim.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/RTrim.java @@ -9,6 +9,7 @@ import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import org.elasticsearch.xpack.sql.expression.function.scalar.string.StringProcessor.StringOperation; /** @@ -37,7 +38,7 @@ protected StringOperation operation() { @Override public DataType dataType() { - return DataType.KEYWORD; + return DataTypes.KEYWORD; } } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/Replace.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/Replace.java index b7cd60c29f9e2..05203aa2816d7 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/Replace.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/Replace.java @@ -15,6 +15,7 @@ import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import java.util.Arrays; import java.util.List; @@ -114,7 +115,7 @@ public ScriptTemplate scriptWithField(FieldAttribute field) { @Override public DataType dataType() { - return DataType.KEYWORD; + return DataTypes.KEYWORD; } @Override diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/Space.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/Space.java index 450a8f8f4caf7..e48d828e93ecb 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/Space.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/Space.java @@ -9,6 +9,7 @@ import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import org.elasticsearch.xpack.sql.expression.function.scalar.string.StringProcessor.StringOperation; /** @@ -37,6 +38,6 @@ protected StringOperation operation() { @Override public DataType dataType() { - return DataType.KEYWORD; + return DataTypes.KEYWORD; } } \ No newline at end of file diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/Substring.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/Substring.java index ec663bbe313e9..421281740948d 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/Substring.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/Substring.java @@ -15,6 +15,7 @@ import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import java.util.Arrays; import java.util.List; @@ -115,7 +116,7 @@ public ScriptTemplate scriptWithField(FieldAttribute field) { @Override public DataType dataType() { - return DataType.KEYWORD; + return DataTypes.KEYWORD; } @Override diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/UCase.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/UCase.java index 8011b51d62a9f..da34e041b9b0a 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/UCase.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/string/UCase.java @@ -9,6 +9,7 @@ import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import org.elasticsearch.xpack.sql.expression.function.scalar.string.StringProcessor.StringOperation; /** @@ -37,7 +38,7 @@ protected StringOperation operation() { @Override public DataType dataType() { - return DataType.KEYWORD; + return DataTypes.KEYWORD; } } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/whitelist/InternalSqlScriptUtils.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/whitelist/InternalSqlScriptUtils.java index 2eea2da544037..126c0323bea8f 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/whitelist/InternalSqlScriptUtils.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/function/scalar/whitelist/InternalSqlScriptUtils.java @@ -8,18 +8,9 @@ import org.elasticsearch.common.geo.GeoPoint; import org.elasticsearch.index.fielddata.ScriptDocValues; import org.elasticsearch.script.JodaCompatibleZonedDateTime; -import org.elasticsearch.xpack.ql.expression.function.scalar.geo.GeoShape; import org.elasticsearch.xpack.ql.expression.function.scalar.whitelist.InternalQlScriptUtils; -import org.elasticsearch.xpack.ql.expression.literal.IntervalDayTime; -import org.elasticsearch.xpack.ql.expression.literal.IntervalYearMonth; -import org.elasticsearch.xpack.ql.expression.predicate.conditional.CaseProcessor; -import org.elasticsearch.xpack.ql.expression.predicate.conditional.ConditionalProcessor.ConditionalOperation; -import org.elasticsearch.xpack.ql.expression.predicate.conditional.NullIfProcessor; -import org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.BinaryArithmeticProcessor.BinaryArithmeticOperation; import org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.UnaryArithmeticProcessor.UnaryArithmeticOperation; import org.elasticsearch.xpack.ql.expression.predicate.regex.RegexProcessor.RegexOperation; -import org.elasticsearch.xpack.ql.type.DataType; -import org.elasticsearch.xpack.ql.type.DataTypeConversion; import org.elasticsearch.xpack.sql.SqlIllegalArgumentException; import org.elasticsearch.xpack.sql.expression.function.scalar.datetime.DateAddProcessor; import org.elasticsearch.xpack.sql.expression.function.scalar.datetime.DateDiffProcessor; @@ -44,6 +35,17 @@ import org.elasticsearch.xpack.sql.expression.function.scalar.string.ReplaceFunctionProcessor; import org.elasticsearch.xpack.sql.expression.function.scalar.string.StringProcessor.StringOperation; import org.elasticsearch.xpack.sql.expression.function.scalar.string.SubstringFunctionProcessor; +import org.elasticsearch.xpack.sql.expression.literal.geo.GeoShape; +import org.elasticsearch.xpack.sql.expression.literal.interval.IntervalDayTime; +import org.elasticsearch.xpack.sql.expression.literal.interval.IntervalYearMonth; +import org.elasticsearch.xpack.sql.expression.predicate.conditional.CaseProcessor; +import org.elasticsearch.xpack.sql.expression.predicate.conditional.ConditionalProcessor.ConditionalOperation; +import org.elasticsearch.xpack.sql.expression.predicate.conditional.NullIfProcessor; +import org.elasticsearch.xpack.sql.expression.predicate.nulls.CheckNullProcessor.CheckNullOperation; +import org.elasticsearch.xpack.sql.expression.predicate.operator.arithmetic.SqlBinaryArithmeticOperation; +import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.InProcessor; +import org.elasticsearch.xpack.sql.type.SqlDataTypeConverter; +import org.elasticsearch.xpack.sql.type.SqlDataTypes; import org.elasticsearch.xpack.sql.util.DateUtils; import java.time.Duration; @@ -64,6 +66,23 @@ public class InternalSqlScriptUtils extends InternalQlScriptUtils { InternalSqlScriptUtils() {} + + // + // Logical + // + + public static Boolean isNull(Object expression) { + return CheckNullOperation.IS_NULL.apply(expression); + } + + public static Boolean isNotNull(Object expression) { + return CheckNullOperation.IS_NOT_NULL.apply(expression); + } + + public static Boolean in(Object value, List values) { + return InProcessor.apply(value, values); + } + // // Conditional // @@ -99,19 +118,19 @@ public static Boolean regex(String value, String pattern) { // Math // public static Object add(Object left, Object right) { - return BinaryArithmeticOperation.ADD.apply(left, right); + return SqlBinaryArithmeticOperation.ADD.apply(left, right); } public static Object div(Object left, Object right) { - return BinaryArithmeticOperation.DIV.apply(left, right); + return SqlBinaryArithmeticOperation.DIV.apply(left, right); } public static Object mod(Object left, Object right) { - return BinaryArithmeticOperation.MOD.apply(left, right); + return SqlBinaryArithmeticOperation.MOD.apply(left, right); } public static Object mul(Object left, Object right) { - return BinaryArithmeticOperation.MUL.apply(left, right); + return SqlBinaryArithmeticOperation.MUL.apply(left, right); } public static Number neg(Number value) { @@ -119,7 +138,7 @@ public static Number neg(Number value) { } public static Object sub(Object left, Object right) { - return BinaryArithmeticOperation.SUB.apply(left, right); + return SqlBinaryArithmeticOperation.SUB.apply(left, right); } public static Number round(Number v, Number s) { @@ -329,7 +348,7 @@ public static IntervalDayTime intervalDayTime(String text, String typeName) { if (text == null || typeName == null) { return null; } - return new IntervalDayTime(Duration.parse(text), DataType.fromSqlOrEsType(typeName)); + return new IntervalDayTime(Duration.parse(text), SqlDataTypes.fromSqlOrEsType(typeName)); } public static IntervalYearMonth intervalYearMonth(String text, String typeName) { @@ -337,7 +356,7 @@ public static IntervalYearMonth intervalYearMonth(String text, String typeName) return null; } - return new IntervalYearMonth(Period.parse(text), DataType.fromSqlOrEsType(typeName)); + return new IntervalYearMonth(Period.parse(text), SqlDataTypes.fromSqlOrEsType(typeName)); } public static OffsetTime asTime(String time) { @@ -477,6 +496,6 @@ public static GeoShape geoDocValue(Map> doc, Stri public static Object cast(Object value, String typeName) { // we call asDateTime here to make sure we handle JodaCompatibleZonedDateTime properly, // since casting works for ZonedDateTime objects only - return DataTypeConversion.convert(asDateTime(value, true), DataType.fromSqlOrEsType(typeName)); + return SqlDataTypeConverter.convert(asDateTime(value, true), SqlDataTypes.fromSqlOrEsType(typeName)); } } diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/literal/Literals.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/literal/Literals.java similarity index 56% rename from x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/literal/Literals.java rename to x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/literal/Literals.java index 0a2cc37db1e0d..75c5b4eb3c25f 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/literal/Literals.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/literal/Literals.java @@ -4,9 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ -package org.elasticsearch.xpack.ql.expression.literal; +package org.elasticsearch.xpack.sql.expression.literal; import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.xpack.ql.expression.gen.processor.ConstantNamedWriteable; +import org.elasticsearch.xpack.sql.expression.literal.geo.GeoShape; +import org.elasticsearch.xpack.sql.expression.literal.interval.IntervalDayTime; +import org.elasticsearch.xpack.sql.expression.literal.interval.IntervalYearMonth; import java.util.ArrayList; import java.util.Collection; @@ -28,8 +32,9 @@ private Literals() { public static Collection getNamedWriteables() { List entries = new ArrayList<>(); - entries.add(new NamedWriteableRegistry.Entry(IntervalDayTime.class, IntervalDayTime.NAME, IntervalDayTime::new)); - entries.add(new NamedWriteableRegistry.Entry(IntervalYearMonth.class, IntervalYearMonth.NAME, IntervalYearMonth::new)); + entries.add(new NamedWriteableRegistry.Entry(ConstantNamedWriteable.class, IntervalDayTime.NAME, IntervalDayTime::new)); + entries.add(new NamedWriteableRegistry.Entry(ConstantNamedWriteable.class, IntervalYearMonth.NAME, IntervalYearMonth::new)); + entries.add(new NamedWriteableRegistry.Entry(ConstantNamedWriteable.class, GeoShape.NAME, GeoShape::new)); return entries; } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/literal/SqlLiterals.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/literal/SqlLiterals.java deleted file mode 100644 index affc0c86e9d88..0000000000000 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/literal/SqlLiterals.java +++ /dev/null @@ -1,31 +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.expression.literal; - -import org.elasticsearch.common.io.stream.NamedWriteableRegistry; -import org.elasticsearch.xpack.ql.expression.function.scalar.geo.GeoShape; -import org.elasticsearch.xpack.ql.expression.literal.Literals; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -public final class SqlLiterals { - - private SqlLiterals() {} - - /** - * All custom types that are not serializable by default can be be serialized as a part of Cursor (i.e as constant in ConstantProcessor) - * should implement NamedWriteables interface and register their de-serialization methods here. - */ - public static Collection getNamedWriteables() { - List entries = new ArrayList<>(Literals.getNamedWriteables()); - entries.add(new NamedWriteableRegistry.Entry(GeoShape.class, GeoShape.NAME, GeoShape::new)); - - return entries; - } -} diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/function/scalar/geo/GeoShape.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/literal/geo/GeoShape.java similarity index 97% rename from x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/function/scalar/geo/GeoShape.java rename to x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/literal/geo/GeoShape.java index 7762d65c16464..9335903254e0c 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/function/scalar/geo/GeoShape.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/literal/geo/GeoShape.java @@ -3,12 +3,11 @@ * 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.ql.expression.function.scalar.geo; +package org.elasticsearch.xpack.sql.expression.literal.geo; import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.geo.GeoUtils; import org.elasticsearch.common.geo.GeometryParser; -import org.elasticsearch.common.io.stream.NamedWriteable; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.xcontent.LoggingDeprecationHandler; @@ -33,6 +32,7 @@ import org.elasticsearch.geometry.utils.StandardValidator; import org.elasticsearch.geometry.utils.WellKnownText; import org.elasticsearch.xpack.ql.QlIllegalArgumentException; +import org.elasticsearch.xpack.ql.expression.gen.processor.ConstantNamedWriteable; import java.io.IOException; import java.io.InputStream; @@ -45,7 +45,7 @@ * It is required to override the XContent serialization. The ShapeBuilder serializes using GeoJSON by default, * but in SQL we need the serialization to be WKT-based. */ -public class GeoShape implements ToXContentFragment, NamedWriteable { +public class GeoShape implements ToXContentFragment, ConstantNamedWriteable { public static final String NAME = "geo"; diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/literal/Interval.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/literal/interval/Interval.java similarity index 83% rename from x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/literal/Interval.java rename to x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/literal/interval/Interval.java index dc29f075e7f83..6c53d5ccecc10 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/literal/Interval.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/literal/interval/Interval.java @@ -4,11 +4,12 @@ * you may not use this file except in compliance with the Elastic License. */ -package org.elasticsearch.xpack.ql.expression.literal; +package org.elasticsearch.xpack.sql.expression.literal.interval; -import org.elasticsearch.common.io.stream.NamedWriteable; import org.elasticsearch.common.xcontent.ToXContentObject; import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.xpack.ql.expression.function.scalar.IntervalScripting; +import org.elasticsearch.xpack.ql.expression.gen.processor.ConstantNamedWriteable; import org.elasticsearch.xpack.ql.type.DataType; import org.elasticsearch.xpack.ql.util.DateUtils; @@ -25,7 +26,7 @@ * Unfortunately because the SQL interval type is not preserved accurately by the JDK TemporalAmount class * in both cases, the data type needs to be carried around as it cannot be inferred. */ -public abstract class Interval implements NamedWriteable, ToXContentObject { +public abstract class Interval implements ConstantNamedWriteable, ToXContentObject, IntervalScripting { private final I interval; private final DataType intervalType; @@ -78,4 +79,14 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws public String toString() { return DateUtils.toString(interval); } + + @Override + public String value() { + return interval().toString(); + } + + @Override + public String typeName() { + return dataType().toString(); + } } \ No newline at end of file diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/literal/interval/IntervalArithmetics.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/literal/interval/IntervalArithmetics.java new file mode 100644 index 0000000000000..32056ed586403 --- /dev/null +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/literal/interval/IntervalArithmetics.java @@ -0,0 +1,72 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +package org.elasticsearch.xpack.sql.expression.literal.interval; + +import java.time.Duration; +import java.time.OffsetTime; +import java.time.Period; +import java.time.temporal.Temporal; + +public final class IntervalArithmetics { + + private IntervalArithmetics() {} + + public static final long DAY_IN_MILLIS = 60 * 60 * 24 * 1000L; + + private enum IntervalOperation { + ADD, + SUB + } + + public static Temporal add(Temporal l, Period r) { + return periodArithmetics(l, r, IntervalOperation.ADD); + } + + public static Temporal add(Temporal l, Duration r) { + return durationArithmetics(l, r, IntervalOperation.ADD); + } + + public static Temporal sub(Temporal l, Period r) { + return periodArithmetics(l, r, IntervalOperation.SUB); + } + + public static Temporal sub(Temporal l, Duration r) { + return durationArithmetics(l, r, IntervalOperation.SUB); + } + + private static Temporal periodArithmetics(Temporal l, Period r, IntervalOperation operation) { + if (l == null || r == null) { + return null; + } + + if (l instanceof OffsetTime) { + return l; + } + + if (operation == IntervalOperation.ADD) { + return l.plus(r); + } else { + return l.minus(r); + } + } + + private static Temporal durationArithmetics(Temporal l, Duration r, IntervalOperation operation) { + if (l == null || r == null) { + return null; + } + + if (l instanceof OffsetTime) { + r = Duration.ofMillis(r.toMillis() % DAY_IN_MILLIS); + } + + if (operation == IntervalOperation.ADD) { + return l.plus(r); + } else { + return l.minus(r); + } + } +} diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/literal/IntervalDayTime.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/literal/interval/IntervalDayTime.java similarity index 75% rename from x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/literal/IntervalDayTime.java rename to x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/literal/interval/IntervalDayTime.java index 66f3ce7238f6a..842619701a5b0 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/literal/IntervalDayTime.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/literal/interval/IntervalDayTime.java @@ -4,12 +4,12 @@ * you may not use this file except in compliance with the Elastic License. */ -package org.elasticsearch.xpack.ql.expression.literal; +package org.elasticsearch.xpack.sql.expression.literal.interval; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.xpack.ql.type.DataType; -import org.elasticsearch.xpack.ql.type.DataTypes; +import org.elasticsearch.xpack.sql.type.SqlDataTypes; import java.io.IOException; import java.time.Duration; @@ -29,15 +29,15 @@ public IntervalDayTime(Duration interval, DataType intervalType) { super(interval, intervalType); } - IntervalDayTime(StreamInput in) throws IOException { - super(duration(in), in.readEnum(DataType.class)); + public IntervalDayTime(StreamInput in) throws IOException { + super(duration(in), SqlDataTypes.fromTypeName(in.readString())); } @Override public void writeTo(StreamOutput out) throws IOException { out.writeVLong(interval().getSeconds()); out.writeVInt(interval().getNano()); - out.writeEnum(dataType()); + out.writeString(dataType().typeName()); } @Override @@ -47,16 +47,21 @@ public String getWriteableName() { @Override public IntervalDayTime add(Interval interval) { - return new IntervalDayTime(interval().plus(interval.interval()), DataTypes.compatibleInterval(dataType(), interval.dataType())); + return new IntervalDayTime(interval().plus(interval.interval()), Intervals.compatibleInterval(dataType(), interval.dataType())); } @Override public IntervalDayTime sub(Interval interval) { - return new IntervalDayTime(interval().minus(interval.interval()), DataTypes.compatibleInterval(dataType(), interval.dataType())); + return new IntervalDayTime(interval().minus(interval.interval()), Intervals.compatibleInterval(dataType(), interval.dataType())); } @Override public Interval mul(long mul) { return new IntervalDayTime(interval().multipliedBy(mul), dataType()); } + + @Override + public String script() { + return "{sql}.intervalDayTime({},{})"; + } } diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/literal/IntervalYearMonth.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/literal/interval/IntervalYearMonth.java similarity index 72% rename from x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/literal/IntervalYearMonth.java rename to x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/literal/interval/IntervalYearMonth.java index ec93819bb93fb..2d64022e57cc3 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/literal/IntervalYearMonth.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/literal/interval/IntervalYearMonth.java @@ -4,13 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ -package org.elasticsearch.xpack.ql.expression.literal; +package org.elasticsearch.xpack.sql.expression.literal.interval; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.xpack.ql.type.DataType; -import org.elasticsearch.xpack.ql.type.DataTypeConversion; -import org.elasticsearch.xpack.ql.type.DataTypes; +import org.elasticsearch.xpack.ql.type.DataTypeConverter; +import org.elasticsearch.xpack.sql.type.SqlDataTypes; import java.io.IOException; import java.time.Period; @@ -30,8 +30,8 @@ public IntervalYearMonth(Period interval, DataType intervalType) { super(interval, intervalType); } - IntervalYearMonth(StreamInput in) throws IOException { - super(period(in), in.readEnum(DataType.class)); + public IntervalYearMonth(StreamInput in) throws IOException { + super(period(in), SqlDataTypes.fromTypeName(in.readString())); } @Override @@ -40,7 +40,7 @@ public void writeTo(StreamOutput out) throws IOException { out.writeVInt(p.getYears()); out.writeVInt(p.getMonths()); out.writeVInt(p.getDays()); - out.writeEnum(dataType()); + out.writeString(dataType().typeName()); } @Override @@ -51,18 +51,23 @@ public String getWriteableName() { @Override public IntervalYearMonth add(Interval interval) { return new IntervalYearMonth(interval().plus(interval.interval()).normalized(), - DataTypes.compatibleInterval(dataType(), interval.dataType())); + Intervals.compatibleInterval(dataType(), interval.dataType())); } @Override public IntervalYearMonth sub(Interval interval) { return new IntervalYearMonth(interval().minus(interval.interval()).normalized(), - DataTypes.compatibleInterval(dataType(), interval.dataType())); + Intervals.compatibleInterval(dataType(), interval.dataType())); } @Override public Interval mul(long mul) { - int i = DataTypeConversion.safeToInt(mul); + int i = DataTypeConverter.safeToInt(mul); return new IntervalYearMonth(interval().multipliedBy(i), dataType()); } + + @Override + public String script() { + return "{sql}.intervalYearMonth({},{})"; + } } diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/literal/Intervals.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/literal/interval/Intervals.java similarity index 72% rename from x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/literal/Intervals.java rename to x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/literal/interval/Intervals.java index 0cd3e6371bcdf..5b9d5a48ec849 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/literal/Intervals.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/literal/interval/Intervals.java @@ -4,17 +4,17 @@ * you may not use this file except in compliance with the Elastic License. */ -package org.elasticsearch.xpack.ql.expression.literal; +package org.elasticsearch.xpack.sql.expression.literal.interval; import org.elasticsearch.common.Strings; import org.elasticsearch.xpack.ql.ParsingException; import org.elasticsearch.xpack.ql.QlIllegalArgumentException; -import org.elasticsearch.xpack.ql.expression.Foldables; import org.elasticsearch.xpack.ql.expression.Literal; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; import org.elasticsearch.xpack.ql.util.Check; import org.elasticsearch.xpack.ql.util.StringUtils; +import org.elasticsearch.xpack.sql.expression.Foldables; import java.time.Duration; import java.time.Period; @@ -22,15 +22,25 @@ import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; +import java.util.Locale; import java.util.Map; -import static org.elasticsearch.xpack.ql.type.DataType.INTERVAL_DAY_TO_HOUR; -import static org.elasticsearch.xpack.ql.type.DataType.INTERVAL_DAY_TO_MINUTE; -import static org.elasticsearch.xpack.ql.type.DataType.INTERVAL_DAY_TO_SECOND; -import static org.elasticsearch.xpack.ql.type.DataType.INTERVAL_HOUR_TO_MINUTE; -import static org.elasticsearch.xpack.ql.type.DataType.INTERVAL_HOUR_TO_SECOND; -import static org.elasticsearch.xpack.ql.type.DataType.INTERVAL_MINUTE_TO_SECOND; -import static org.elasticsearch.xpack.ql.type.DataType.INTERVAL_YEAR_TO_MONTH; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.INTERVAL_DAY; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.INTERVAL_DAY_TO_HOUR; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.INTERVAL_DAY_TO_MINUTE; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.INTERVAL_DAY_TO_SECOND; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.INTERVAL_HOUR; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.INTERVAL_HOUR_TO_MINUTE; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.INTERVAL_HOUR_TO_SECOND; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.INTERVAL_MINUTE; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.INTERVAL_MINUTE_TO_SECOND; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.INTERVAL_MONTH; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.INTERVAL_SECOND; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.INTERVAL_YEAR; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.INTERVAL_YEAR_TO_MONTH; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.fromTypeName; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.isDayTimeInterval; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.isYearMonthInterval; public final class Intervals { @@ -91,17 +101,17 @@ public static DataType intervalType(Source source, TimeUnit leading, TimeUnit tr if (trailing == null) { switch (leading) { case YEAR: - return DataType.INTERVAL_YEAR; + return INTERVAL_YEAR; case MONTH: - return DataType.INTERVAL_MONTH; + return INTERVAL_MONTH; case DAY: - return DataType.INTERVAL_DAY; + return INTERVAL_DAY; case HOUR: - return DataType.INTERVAL_HOUR; + return INTERVAL_HOUR; case MINUTE: - return DataType.INTERVAL_MINUTE; + return INTERVAL_MINUTE; case SECOND: - return DataType.INTERVAL_SECOND; + return INTERVAL_SECOND; default: throw new ParsingException(source, "Cannot determine datatype for [{}]", leading); } @@ -131,6 +141,64 @@ public static DataType intervalType(Source source, TimeUnit leading, TimeUnit tr } } + // return the compatible interval between the two - it is assumed the types are intervals + // YEAR and MONTH -> YEAR_TO_MONTH + // DAY... SECOND -> DAY_TIME + // YEAR_MONTH and DAY_SECOND are NOT compatible + public static DataType compatibleInterval(DataType left, DataType right) { + if (left == right) { + return left; + } + if (isYearMonthInterval(left) && isYearMonthInterval(right)) { + // no need to look at YEAR/YEAR or MONTH/MONTH as these are equal and already handled + return INTERVAL_YEAR_TO_MONTH; + } + if (isDayTimeInterval(left) && isDayTimeInterval(right)) { + int PREFIX = "INTERVAL_".length(); + // to avoid specifying the combinations, extract the leading and trailing unit from the name + // D > H > S > M which is also the alphabetical order + String lName = left.typeName().toUpperCase(Locale.ROOT).substring(PREFIX); + String rName = right.typeName().toUpperCase(Locale.ROOT).substring(PREFIX); + + char leading = lName.charAt(0); + if (rName.charAt(0) < leading) { + leading = rName.charAt(0); + } + // look at the trailing unit + if (lName.length() > 6) { + int indexOf = lName.indexOf("_TO_"); + lName = lName.substring(indexOf + 4); + } + if (rName.length() > 6) { + int indexOf = rName.indexOf("_TO_"); + rName = rName.substring(indexOf + 4); + } + char trailing = lName.charAt(0); + if (rName.charAt(0) > trailing) { + trailing = rName.charAt(0); + } + + return fromTypeName("INTERVAL_" + intervalUnit(leading) + "_TO_" + intervalUnit(trailing)); + } + return null; + } + + private static String intervalUnit(char unitChar) { + switch (unitChar) { + case 'D': + return "DAY"; + case 'H': + return "HOUR"; + case 'M': + return "MINUTE"; + case 'S': + return "SECOND"; + default: + throw new QlIllegalArgumentException("Unknown unit {}", unitChar); + } + } + + // // String parsers // @@ -146,7 +214,7 @@ private static class ParserBuilder { ParserBuilder(DataType dataType) { units = new ArrayList<>(10); tokens = new ArrayList<>(6); - name = dataType.name().replace('_', ' '); + name = dataType.typeName().replace('_', ' ').toUpperCase(Locale.ROOT); } ParserBuilder unit(TimeUnit unit) { @@ -336,31 +404,31 @@ public static TemporalAmount negate(TemporalAmount interval) { char MINUS = '-'; char COLON = ':'; - PARSERS.put(DataType.INTERVAL_YEAR, new ParserBuilder(DataType.INTERVAL_YEAR).unit(TimeUnit.YEAR).build()); - PARSERS.put(DataType.INTERVAL_MONTH, new ParserBuilder(DataType.INTERVAL_MONTH).unit(TimeUnit.MONTH).build()); - PARSERS.put(DataType.INTERVAL_DAY, new ParserBuilder(DataType.INTERVAL_DAY).unit(TimeUnit.DAY).build()); - PARSERS.put(DataType.INTERVAL_HOUR, new ParserBuilder(DataType.INTERVAL_HOUR).unit(TimeUnit.HOUR).build()); - PARSERS.put(DataType.INTERVAL_MINUTE, new ParserBuilder(DataType.INTERVAL_MINUTE).unit(TimeUnit.MINUTE).build()); - PARSERS.put(DataType.INTERVAL_SECOND, new ParserBuilder(DataType.INTERVAL_SECOND) + PARSERS.put(INTERVAL_YEAR, new ParserBuilder(INTERVAL_YEAR).unit(TimeUnit.YEAR).build()); + PARSERS.put(INTERVAL_MONTH, new ParserBuilder(INTERVAL_MONTH).unit(TimeUnit.MONTH).build()); + PARSERS.put(INTERVAL_DAY, new ParserBuilder(INTERVAL_DAY).unit(TimeUnit.DAY).build()); + PARSERS.put(INTERVAL_HOUR, new ParserBuilder(INTERVAL_HOUR).unit(TimeUnit.HOUR).build()); + PARSERS.put(INTERVAL_MINUTE, new ParserBuilder(INTERVAL_MINUTE).unit(TimeUnit.MINUTE).build()); + PARSERS.put(INTERVAL_SECOND, new ParserBuilder(INTERVAL_SECOND) .unit(TimeUnit.SECOND) .optional() .separator(DOT).unit(TimeUnit.MILLISECOND, MAX_MILLI) .build()); // patterns - PARSERS.put(DataType.INTERVAL_YEAR_TO_MONTH, new ParserBuilder(DataType.INTERVAL_YEAR_TO_MONTH) + PARSERS.put(INTERVAL_YEAR_TO_MONTH, new ParserBuilder(INTERVAL_YEAR_TO_MONTH) .unit(TimeUnit.YEAR) .separator(MINUS) .unit(TimeUnit.MONTH, MAX_MONTH) .build()); - PARSERS.put(DataType.INTERVAL_DAY_TO_HOUR, new ParserBuilder(DataType.INTERVAL_DAY_TO_HOUR) + PARSERS.put(INTERVAL_DAY_TO_HOUR, new ParserBuilder(INTERVAL_DAY_TO_HOUR) .unit(TimeUnit.DAY) .separator(SPACE) .unit(TimeUnit.HOUR, MAX_HOUR) .build()); - PARSERS.put(DataType.INTERVAL_DAY_TO_MINUTE, new ParserBuilder(DataType.INTERVAL_DAY_TO_MINUTE) + PARSERS.put(INTERVAL_DAY_TO_MINUTE, new ParserBuilder(INTERVAL_DAY_TO_MINUTE) .unit(TimeUnit.DAY) .separator(SPACE) .unit(TimeUnit.HOUR, MAX_HOUR) @@ -368,7 +436,7 @@ public static TemporalAmount negate(TemporalAmount interval) { .unit(TimeUnit.MINUTE, MAX_MINUTE) .build()); - PARSERS.put(DataType.INTERVAL_DAY_TO_SECOND, new ParserBuilder(DataType.INTERVAL_DAY_TO_SECOND) + PARSERS.put(INTERVAL_DAY_TO_SECOND, new ParserBuilder(INTERVAL_DAY_TO_SECOND) .unit(TimeUnit.DAY) .separator(SPACE) .unit(TimeUnit.HOUR, MAX_HOUR) @@ -380,13 +448,13 @@ public static TemporalAmount negate(TemporalAmount interval) { .separator(DOT).unit(TimeUnit.MILLISECOND, MAX_MILLI) .build()); - PARSERS.put(DataType.INTERVAL_HOUR_TO_MINUTE, new ParserBuilder(DataType.INTERVAL_HOUR_TO_MINUTE) + PARSERS.put(INTERVAL_HOUR_TO_MINUTE, new ParserBuilder(INTERVAL_HOUR_TO_MINUTE) .unit(TimeUnit.HOUR) .separator(COLON) .unit(TimeUnit.MINUTE, MAX_MINUTE) .build()); - PARSERS.put(DataType.INTERVAL_HOUR_TO_SECOND, new ParserBuilder(DataType.INTERVAL_HOUR_TO_SECOND) + PARSERS.put(INTERVAL_HOUR_TO_SECOND, new ParserBuilder(INTERVAL_HOUR_TO_SECOND) .unit(TimeUnit.HOUR) .separator(COLON) .unit(TimeUnit.MINUTE, MAX_MINUTE) @@ -396,7 +464,7 @@ public static TemporalAmount negate(TemporalAmount interval) { .separator(DOT).unit(TimeUnit.MILLISECOND, MAX_MILLI) .build()); - PARSERS.put(DataType.INTERVAL_MINUTE_TO_SECOND, new ParserBuilder(DataType.INTERVAL_MINUTE_TO_SECOND) + PARSERS.put(INTERVAL_MINUTE_TO_SECOND, new ParserBuilder(INTERVAL_MINUTE_TO_SECOND) .unit(TimeUnit.MINUTE) .separator(COLON) .unit(TimeUnit.SECOND, MAX_SECOND) diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/conditional/ArbitraryConditionalFunction.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/ArbitraryConditionalFunction.java similarity index 91% rename from x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/conditional/ArbitraryConditionalFunction.java rename to x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/ArbitraryConditionalFunction.java index 85c0dc484cbdb..72a14a22934c4 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/conditional/ArbitraryConditionalFunction.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/ArbitraryConditionalFunction.java @@ -4,15 +4,15 @@ * you may not use this file except in compliance with the Elastic License. */ -package org.elasticsearch.xpack.ql.expression.predicate.conditional; +package org.elasticsearch.xpack.sql.expression.predicate.conditional; import org.elasticsearch.xpack.ql.expression.Expression; import org.elasticsearch.xpack.ql.expression.Expressions; import org.elasticsearch.xpack.ql.expression.gen.pipeline.Pipe; import org.elasticsearch.xpack.ql.expression.gen.script.ParamsBuilder; import org.elasticsearch.xpack.ql.expression.gen.script.ScriptTemplate; -import org.elasticsearch.xpack.ql.expression.predicate.conditional.ConditionalProcessor.ConditionalOperation; import org.elasticsearch.xpack.ql.tree.Source; +import org.elasticsearch.xpack.sql.expression.predicate.conditional.ConditionalProcessor.ConditionalOperation; import java.util.ArrayList; import java.util.List; diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/conditional/Case.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/Case.java similarity index 88% rename from x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/conditional/Case.java rename to x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/Case.java index 80bd5620c04a7..362d14b2df0f2 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/conditional/Case.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/Case.java @@ -3,7 +3,7 @@ * 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.ql.expression.predicate.conditional; +package org.elasticsearch.xpack.sql.expression.predicate.conditional; import org.elasticsearch.xpack.ql.expression.Expression; import org.elasticsearch.xpack.ql.expression.Expressions; @@ -13,8 +13,9 @@ import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; -import org.elasticsearch.xpack.ql.type.DataTypeConversion; import org.elasticsearch.xpack.ql.type.DataTypes; +import org.elasticsearch.xpack.sql.type.SqlDataTypeConverter; +import org.elasticsearch.xpack.sql.type.SqlDataTypes; import java.util.ArrayList; import java.util.List; @@ -52,12 +53,12 @@ public DataType dataType() { if (conditions.isEmpty()) { dataType = elseResult().dataType(); } else { - dataType = DataType.NULL; + dataType = DataTypes.NULL; for (IfConditional conditional : conditions) { - dataType = DataTypeConversion.commonType(dataType, conditional.dataType()); + dataType = SqlDataTypeConverter.commonType(dataType, conditional.dataType()); } - dataType = DataTypeConversion.commonType(dataType, elseResult.dataType()); + dataType = SqlDataTypeConverter.commonType(dataType, elseResult.dataType()); } } return dataType; @@ -77,7 +78,7 @@ protected NodeInfo info() { protected TypeResolution resolveType() { DataType expectedResultDataType = null; for (IfConditional ifConditional : conditions) { - if (ifConditional.result().dataType().isNull() == false) { + if (DataTypes.isNull(ifConditional.result().dataType()) == false) { expectedResultDataType = ifConditional.result().dataType(); break; } @@ -87,13 +88,13 @@ protected TypeResolution resolveType() { } for (IfConditional conditional : conditions) { - if (conditional.condition().dataType() != DataType.BOOLEAN) { + if (conditional.condition().dataType() != DataTypes.BOOLEAN) { return new TypeResolution(format(null, "condition of [{}] must be [boolean], found value [{}] type [{}]", conditional.sourceText(), Expressions.name(conditional.condition()), conditional.condition().dataType().typeName())); } - if (DataTypes.areTypesCompatible(expectedResultDataType, conditional.dataType()) == false) { + if (SqlDataTypes.areCompatible(expectedResultDataType, conditional.dataType()) == false) { return new TypeResolution(format(null, "result of [{}] must be [{}], found value [{}] type [{}]", conditional.sourceText(), expectedResultDataType.typeName(), @@ -102,7 +103,7 @@ protected TypeResolution resolveType() { } } - if (DataTypes.areTypesCompatible(expectedResultDataType, elseResult.dataType()) == false) { + if (SqlDataTypes.areCompatible(expectedResultDataType, elseResult.dataType()) == false) { return new TypeResolution(format(null, "ELSE clause of [{}] must be [{}], found value [{}] type [{}]", elseResult.sourceText(), expectedResultDataType.typeName(), diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/conditional/CasePipe.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/CasePipe.java similarity index 94% rename from x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/conditional/CasePipe.java rename to x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/CasePipe.java index 96f18487585e7..7f316a480b384 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/conditional/CasePipe.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/CasePipe.java @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -package org.elasticsearch.xpack.ql.expression.predicate.conditional; +package org.elasticsearch.xpack.sql.expression.predicate.conditional; import org.elasticsearch.xpack.ql.expression.Expression; import org.elasticsearch.xpack.ql.expression.gen.pipeline.MultiPipe; diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/conditional/CaseProcessor.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/CaseProcessor.java similarity index 97% rename from x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/conditional/CaseProcessor.java rename to x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/CaseProcessor.java index fc3d0417fb506..dc4d083d53c17 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/conditional/CaseProcessor.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/CaseProcessor.java @@ -3,7 +3,7 @@ * 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.ql.expression.predicate.conditional; +package org.elasticsearch.xpack.sql.expression.predicate.conditional; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/conditional/Coalesce.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/Coalesce.java similarity index 88% rename from x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/conditional/Coalesce.java rename to x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/Coalesce.java index 898ce160a2baf..04f04ce3da535 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/conditional/Coalesce.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/Coalesce.java @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -package org.elasticsearch.xpack.ql.expression.predicate.conditional; +package org.elasticsearch.xpack.sql.expression.predicate.conditional; import org.elasticsearch.xpack.ql.expression.Expression; import org.elasticsearch.xpack.ql.tree.NodeInfo; @@ -12,7 +12,7 @@ import java.util.List; -import static org.elasticsearch.xpack.ql.expression.predicate.conditional.ConditionalProcessor.ConditionalOperation.COALESCE; +import static org.elasticsearch.xpack.sql.expression.predicate.conditional.ConditionalProcessor.ConditionalOperation.COALESCE; public class Coalesce extends ArbitraryConditionalFunction { diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/conditional/ConditionalFunction.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/ConditionalFunction.java similarity index 83% rename from x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/conditional/ConditionalFunction.java rename to x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/ConditionalFunction.java index 27b5c779c6b01..284433cdb122a 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/conditional/ConditionalFunction.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/ConditionalFunction.java @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -package org.elasticsearch.xpack.ql.expression.predicate.conditional; +package org.elasticsearch.xpack.sql.expression.predicate.conditional; import org.elasticsearch.xpack.ql.expression.Expression; import org.elasticsearch.xpack.ql.expression.Expressions; @@ -12,13 +12,14 @@ import org.elasticsearch.xpack.ql.expression.function.scalar.ScalarFunction; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; -import org.elasticsearch.xpack.ql.type.DataTypeConversion; +import org.elasticsearch.xpack.ql.type.DataTypes; +import org.elasticsearch.xpack.sql.type.SqlDataTypeConverter; +import org.elasticsearch.xpack.sql.type.SqlDataTypes; import java.util.List; import java.util.Objects; import static org.elasticsearch.common.logging.LoggerMessageFormat.format; -import static org.elasticsearch.xpack.ql.type.DataTypes.areTypesCompatible; import static org.elasticsearch.xpack.ql.util.StringUtils.ordinal; /** @@ -35,9 +36,9 @@ public abstract class ConditionalFunction extends ScalarFunction { @Override public DataType dataType() { if (dataType == null) { - dataType = DataType.NULL; + dataType = DataTypes.NULL; for (Expression exp : children()) { - dataType = DataTypeConversion.commonType(dataType, exp.dataType()); + dataType = SqlDataTypeConverter.commonType(dataType, exp.dataType()); } } return dataType; @@ -50,16 +51,16 @@ public boolean foldable() { @Override protected TypeResolution resolveType() { - DataType dt = DataType.NULL; + DataType dt = DataTypes.NULL; for (int i = 0; i < children().size(); i++) { Expression child = children().get(i); - if (dt == DataType.NULL) { + if (dt == DataTypes.NULL) { if (Expressions.isNull(child) == false) { dt = child.dataType(); } } else { - if (areTypesCompatible(dt, child.dataType()) == false) { + if (SqlDataTypes.areCompatible(dt, child.dataType()) == false) { return new TypeResolution(format(null, "{} argument of [{}] must be [{}], found value [{}] type [{}]", ordinal(i + 1), sourceText(), diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/conditional/ConditionalPipe.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/ConditionalPipe.java similarity index 90% rename from x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/conditional/ConditionalPipe.java rename to x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/ConditionalPipe.java index 1d0e595f294a2..776f151f9286a 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/conditional/ConditionalPipe.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/ConditionalPipe.java @@ -4,15 +4,15 @@ * you may not use this file except in compliance with the Elastic License. */ -package org.elasticsearch.xpack.ql.expression.predicate.conditional; +package org.elasticsearch.xpack.sql.expression.predicate.conditional; import org.elasticsearch.xpack.ql.expression.Expression; import org.elasticsearch.xpack.ql.expression.gen.pipeline.MultiPipe; import org.elasticsearch.xpack.ql.expression.gen.pipeline.Pipe; import org.elasticsearch.xpack.ql.expression.gen.processor.Processor; -import org.elasticsearch.xpack.ql.expression.predicate.conditional.ConditionalProcessor.ConditionalOperation; import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; +import org.elasticsearch.xpack.sql.expression.predicate.conditional.ConditionalProcessor.ConditionalOperation; import java.util.List; import java.util.Objects; diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/conditional/ConditionalProcessor.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/ConditionalProcessor.java similarity index 97% rename from x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/conditional/ConditionalProcessor.java rename to x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/ConditionalProcessor.java index cd329efef5fbe..83f27eade4db2 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/conditional/ConditionalProcessor.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/ConditionalProcessor.java @@ -3,7 +3,7 @@ * 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.ql.expression.predicate.conditional; +package org.elasticsearch.xpack.sql.expression.predicate.conditional; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/conditional/Conditionals.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/Conditionals.java similarity index 97% rename from x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/conditional/Conditionals.java rename to x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/Conditionals.java index 18121147d4e32..34648d63cee15 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/conditional/Conditionals.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/Conditionals.java @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -package org.elasticsearch.xpack.ql.expression.predicate.conditional; +package org.elasticsearch.xpack.sql.expression.predicate.conditional; import org.elasticsearch.xpack.ql.expression.gen.processor.Processor; import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.Comparisons; diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/conditional/Greatest.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/Greatest.java similarity index 75% rename from x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/conditional/Greatest.java rename to x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/Greatest.java index 6191cde4c1337..13b740261ca51 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/conditional/Greatest.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/Greatest.java @@ -4,18 +4,18 @@ * you may not use this file except in compliance with the Elastic License. */ -package org.elasticsearch.xpack.ql.expression.predicate.conditional; +package org.elasticsearch.xpack.sql.expression.predicate.conditional; import org.elasticsearch.xpack.ql.expression.Expression; -import org.elasticsearch.xpack.ql.expression.Foldables; import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; +import org.elasticsearch.xpack.sql.expression.Foldables; import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List; -import static org.elasticsearch.xpack.ql.expression.predicate.conditional.ConditionalProcessor.ConditionalOperation.GREATEST; +import static org.elasticsearch.xpack.sql.expression.predicate.conditional.ConditionalProcessor.ConditionalOperation.GREATEST; public class Greatest extends ArbitraryConditionalFunction { @@ -35,6 +35,6 @@ public Expression replaceChildren(List newChildren) { @Override public Object fold() { - return GREATEST.apply(Foldables.valuesOfNoDuplicates(children(), dataType)); + return GREATEST.apply(Foldables.valuesUnique(children(), dataType)); } } diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/conditional/IfConditional.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/IfConditional.java similarity index 97% rename from x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/conditional/IfConditional.java rename to x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/IfConditional.java index 3316bb35d5ff4..1e5c4edfcc8b6 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/conditional/IfConditional.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/IfConditional.java @@ -3,7 +3,7 @@ * 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.ql.expression.predicate.conditional; +package org.elasticsearch.xpack.sql.expression.predicate.conditional; import org.elasticsearch.xpack.ql.expression.Expression; import org.elasticsearch.xpack.ql.expression.Nullability; diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/conditional/IfNull.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/IfNull.java similarity index 93% rename from x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/conditional/IfNull.java rename to x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/IfNull.java index 1fc50f7d3613a..9014c6c8c1bb5 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/conditional/IfNull.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/IfNull.java @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -package org.elasticsearch.xpack.ql.expression.predicate.conditional; +package org.elasticsearch.xpack.sql.expression.predicate.conditional; import org.elasticsearch.xpack.ql.expression.Expression; import org.elasticsearch.xpack.ql.tree.NodeInfo; diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/conditional/Iif.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/Iif.java similarity index 91% rename from x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/conditional/Iif.java rename to x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/Iif.java index af55e86e1c17e..b270d29c63712 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/conditional/Iif.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/Iif.java @@ -3,7 +3,7 @@ * 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.ql.expression.predicate.conditional; +package org.elasticsearch.xpack.sql.expression.predicate.conditional; import org.elasticsearch.xpack.ql.expression.Expression; import org.elasticsearch.xpack.ql.expression.Expressions; @@ -12,7 +12,7 @@ import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; -import org.elasticsearch.xpack.ql.type.DataTypes; +import org.elasticsearch.xpack.sql.type.SqlDataTypes; import java.util.Arrays; import java.util.List; @@ -53,7 +53,7 @@ protected TypeResolution resolveType() { } DataType resultDataType = conditions().get(0).dataType(); - if (DataTypes.areTypesCompatible(resultDataType, elseResult().dataType()) == false) { + if (SqlDataTypes.areCompatible(resultDataType, elseResult().dataType()) == false) { return new TypeResolution(format(null, "third argument of [{}] must be [{}], found value [{}] type [{}]", sourceText(), resultDataType.typeName(), diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/conditional/Least.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/Least.java similarity index 75% rename from x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/conditional/Least.java rename to x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/Least.java index 017d87beadb91..b9d2470d5a17c 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/conditional/Least.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/Least.java @@ -4,18 +4,18 @@ * you may not use this file except in compliance with the Elastic License. */ -package org.elasticsearch.xpack.ql.expression.predicate.conditional; +package org.elasticsearch.xpack.sql.expression.predicate.conditional; import org.elasticsearch.xpack.ql.expression.Expression; -import org.elasticsearch.xpack.ql.expression.Foldables; import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; +import org.elasticsearch.xpack.sql.expression.Foldables; import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List; -import static org.elasticsearch.xpack.ql.expression.predicate.conditional.ConditionalProcessor.ConditionalOperation.LEAST; +import static org.elasticsearch.xpack.sql.expression.predicate.conditional.ConditionalProcessor.ConditionalOperation.LEAST; public class Least extends ArbitraryConditionalFunction { @@ -35,6 +35,6 @@ public Expression replaceChildren(List newChildren) { @Override public Object fold() { - return LEAST.apply(Foldables.valuesOfNoDuplicates(children(), dataType)); + return LEAST.apply(Foldables.valuesUnique(children(), dataType)); } } diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/conditional/NullIf.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/NullIf.java similarity index 96% rename from x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/conditional/NullIf.java rename to x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/NullIf.java index e1b85cde3feec..1b8b02b89e540 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/conditional/NullIf.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/NullIf.java @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -package org.elasticsearch.xpack.ql.expression.predicate.conditional; +package org.elasticsearch.xpack.sql.expression.predicate.conditional; import org.elasticsearch.xpack.ql.expression.Expression; import org.elasticsearch.xpack.ql.expression.Expressions; diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/conditional/NullIfPipe.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/NullIfPipe.java similarity index 94% rename from x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/conditional/NullIfPipe.java rename to x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/NullIfPipe.java index d151960230293..ffd7516a2b629 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/conditional/NullIfPipe.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/NullIfPipe.java @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -package org.elasticsearch.xpack.ql.expression.predicate.conditional; +package org.elasticsearch.xpack.sql.expression.predicate.conditional; import org.elasticsearch.xpack.ql.expression.Expression; import org.elasticsearch.xpack.ql.expression.gen.pipeline.BinaryPipe; diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/conditional/NullIfProcessor.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/NullIfProcessor.java similarity index 97% rename from x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/conditional/NullIfProcessor.java rename to x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/NullIfProcessor.java index 11b5adadd41d4..f1b334a678b8f 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/conditional/NullIfProcessor.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/NullIfProcessor.java @@ -3,7 +3,7 @@ * 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.ql.expression.predicate.conditional; +package org.elasticsearch.xpack.sql.expression.predicate.conditional; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/nulls/CheckNullProcessor.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/nulls/CheckNullProcessor.java similarity index 97% rename from x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/nulls/CheckNullProcessor.java rename to x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/nulls/CheckNullProcessor.java index eb12134858212..c37f6cf274676 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/nulls/CheckNullProcessor.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/nulls/CheckNullProcessor.java @@ -3,7 +3,7 @@ * 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.ql.expression.predicate.nulls; +package org.elasticsearch.xpack.sql.expression.predicate.nulls; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/nulls/IsNotNull.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/nulls/IsNotNull.java similarity index 84% rename from x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/nulls/IsNotNull.java rename to x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/nulls/IsNotNull.java index 5cae27d85f237..f17a533e159c3 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/nulls/IsNotNull.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/nulls/IsNotNull.java @@ -3,7 +3,7 @@ * 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.ql.expression.predicate.nulls; +package org.elasticsearch.xpack.sql.expression.predicate.nulls; import org.elasticsearch.xpack.ql.expression.Expression; import org.elasticsearch.xpack.ql.expression.Nullability; @@ -11,10 +11,11 @@ import org.elasticsearch.xpack.ql.expression.gen.processor.Processor; import org.elasticsearch.xpack.ql.expression.gen.script.Scripts; import org.elasticsearch.xpack.ql.expression.predicate.Negatable; -import org.elasticsearch.xpack.ql.expression.predicate.nulls.CheckNullProcessor.CheckNullOperation; import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; +import org.elasticsearch.xpack.sql.expression.predicate.nulls.CheckNullProcessor.CheckNullOperation; public class IsNotNull extends UnaryScalarFunction implements Negatable { @@ -34,7 +35,7 @@ protected IsNotNull replaceChild(Expression newChild) { @Override public Object fold() { - return field().fold() != null && !field().dataType().isNull(); + return field().fold() != null && DataTypes.isNull(field().dataType()) == false; } @Override @@ -54,7 +55,7 @@ public Nullability nullable() { @Override public DataType dataType() { - return DataType.BOOLEAN; + return DataTypes.BOOLEAN; } @Override diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/nulls/IsNull.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/nulls/IsNull.java similarity index 84% rename from x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/nulls/IsNull.java rename to x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/nulls/IsNull.java index 208160b66df39..5bc8bfc6718bc 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/nulls/IsNull.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/nulls/IsNull.java @@ -3,7 +3,7 @@ * 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.ql.expression.predicate.nulls; +package org.elasticsearch.xpack.sql.expression.predicate.nulls; import org.elasticsearch.xpack.ql.expression.Expression; import org.elasticsearch.xpack.ql.expression.Nullability; @@ -11,10 +11,11 @@ import org.elasticsearch.xpack.ql.expression.gen.processor.Processor; import org.elasticsearch.xpack.ql.expression.gen.script.Scripts; import org.elasticsearch.xpack.ql.expression.predicate.Negatable; -import org.elasticsearch.xpack.ql.expression.predicate.nulls.CheckNullProcessor.CheckNullOperation; import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; +import org.elasticsearch.xpack.sql.expression.predicate.nulls.CheckNullProcessor.CheckNullOperation; public class IsNull extends UnaryScalarFunction implements Negatable { @@ -34,7 +35,7 @@ protected IsNull replaceChild(Expression newChild) { @Override public Object fold() { - return field().fold() == null || field().dataType().isNull(); + return field().fold() == null || DataTypes.isNull(field().dataType()); } @Override @@ -54,7 +55,7 @@ public Nullability nullable() { @Override public DataType dataType() { - return DataType.BOOLEAN; + return DataTypes.BOOLEAN; } @Override diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/arithmetic/Add.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/arithmetic/Add.java new file mode 100644 index 0000000000000..2b3b535c9b960 --- /dev/null +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/arithmetic/Add.java @@ -0,0 +1,29 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +package org.elasticsearch.xpack.sql.expression.predicate.operator.arithmetic; + +import org.elasticsearch.xpack.ql.expression.Expression; +import org.elasticsearch.xpack.ql.tree.NodeInfo; +import org.elasticsearch.xpack.ql.tree.Source; + +/** + * Addition function ({@code a + b}). + */ +public class Add extends DateTimeArithmeticOperation { + public Add(Source source, Expression left, Expression right) { + super(source, left, right, SqlBinaryArithmeticOperation.ADD); + } + + @Override + protected NodeInfo info() { + return NodeInfo.create(this, Add::new, left(), right()); + } + + @Override + protected Add replaceChildren(Expression left, Expression right) { + return new Add(source(), left, right); + } +} diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/arithmetic/DateTimeArithmeticOperation.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/arithmetic/DateTimeArithmeticOperation.java new file mode 100644 index 0000000000000..f0eb11f6f6d20 --- /dev/null +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/arithmetic/DateTimeArithmeticOperation.java @@ -0,0 +1,67 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +package org.elasticsearch.xpack.sql.expression.predicate.operator.arithmetic; + +import org.elasticsearch.xpack.ql.expression.Expression; +import org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.BinaryArithmeticOperation; +import org.elasticsearch.xpack.ql.tree.Source; +import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; +import org.elasticsearch.xpack.sql.type.SqlDataTypeConverter; +import org.elasticsearch.xpack.sql.type.SqlDataTypes; + +import static org.elasticsearch.common.logging.LoggerMessageFormat.format; + +abstract class DateTimeArithmeticOperation extends SqlArithmeticOperation { + + DateTimeArithmeticOperation(Source source, Expression left, Expression right, BinaryArithmeticOperation operation) { + super(source, left, right, operation); + } + + @Override + protected TypeResolution resolveType() { + if (!childrenResolved()) { + return new TypeResolution("Unresolved children"); + } + + // arithmetic operation can work on: + // 1. numbers + // 2. intervals (of compatible types) + // 3. dates and intervals + // 4. single unit intervals and numbers + + DataType l = left().dataType(); + DataType r = right().dataType(); + + // 1. both are numbers + if (l.isNumeric() && r.isNumeric()) { + return TypeResolution.TYPE_RESOLVED; + } + // 2. 3. 4. intervals + if (SqlDataTypes.isInterval(l) || SqlDataTypes.isInterval(r)) { + if (SqlDataTypeConverter.commonType(l, r) == null) { + return new TypeResolution(format(null, "[{}] has arguments with incompatible types [{}] and [{}]", symbol(), l, r)); + } else { + return resolveWithIntervals(); + } + } + + // fall-back to default checks + return super.resolveType(); + } + + protected TypeResolution resolveWithIntervals() { + DataType l = left().dataType(); + DataType r = right().dataType(); + + if ((SqlDataTypes.isDateOrTimeBased(r) || SqlDataTypes.isInterval(r) || DataTypes.isNull(r)) == false + || (SqlDataTypes.isDateOrTimeBased(l) || SqlDataTypes.isInterval(l) || DataTypes.isNull(l)) == false) { + return new TypeResolution(format(null, "[{}] has arguments with incompatible types [{}] and [{}]", symbol(), l, r)); + } + return TypeResolution.TYPE_RESOLVED; + } +} diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/arithmetic/Div.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/arithmetic/Div.java new file mode 100644 index 0000000000000..67da39f46eaf3 --- /dev/null +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/arithmetic/Div.java @@ -0,0 +1,37 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +package org.elasticsearch.xpack.sql.expression.predicate.operator.arithmetic; + +import org.elasticsearch.xpack.ql.expression.Expression; +import org.elasticsearch.xpack.ql.tree.NodeInfo; +import org.elasticsearch.xpack.ql.tree.Source; +import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.sql.type.SqlDataTypeConverter; + +/** + * Division function ({@code a / b}). + */ +public class Div extends SqlArithmeticOperation { + + public Div(Source source, Expression left, Expression right) { + super(source, left, right, SqlBinaryArithmeticOperation.DIV); + } + + @Override + protected NodeInfo
    info() { + return NodeInfo.create(this, Div::new, left(), right()); + } + + @Override + protected Div replaceChildren(Expression newLeft, Expression newRight) { + return new Div(source(), newLeft, newRight); + } + + @Override + public DataType dataType() { + return SqlDataTypeConverter.commonType(left().dataType(), right().dataType()); + } +} diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/arithmetic/Mod.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/arithmetic/Mod.java new file mode 100644 index 0000000000000..1d828d51cb7c4 --- /dev/null +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/arithmetic/Mod.java @@ -0,0 +1,33 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +package org.elasticsearch.xpack.sql.expression.predicate.operator.arithmetic; + +import org.elasticsearch.xpack.ql.expression.Expression; +import org.elasticsearch.xpack.ql.tree.NodeInfo; +import org.elasticsearch.xpack.ql.tree.Source; + +/** + * Modulo + * function ({@code a % b}). + * + * Note this operator is also registered as a function (needed for ODBC/SQL) purposes. + */ +public class Mod extends SqlArithmeticOperation { + + public Mod(Source source, Expression left, Expression right) { + super(source, left, right, SqlBinaryArithmeticOperation.MOD); + } + + @Override + protected NodeInfo info() { + return NodeInfo.create(this, Mod::new, left(), right()); + } + + @Override + protected Mod replaceChildren(Expression newLeft, Expression newRight) { + return new Mod(source(), newLeft, newRight); + } +} diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/arithmetic/Mul.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/arithmetic/Mul.java new file mode 100644 index 0000000000000..1b5a3f49ddedb --- /dev/null +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/arithmetic/Mul.java @@ -0,0 +1,70 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +package org.elasticsearch.xpack.sql.expression.predicate.operator.arithmetic; + +import org.elasticsearch.xpack.ql.expression.Expression; +import org.elasticsearch.xpack.ql.tree.NodeInfo; +import org.elasticsearch.xpack.ql.tree.Source; +import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; +import org.elasticsearch.xpack.sql.type.SqlDataTypes; + +import static org.elasticsearch.common.logging.LoggerMessageFormat.format; + +/** + * Multiplication function ({@code a * b}). + */ +public class Mul extends SqlArithmeticOperation { + + private DataType dataType; + + public Mul(Source source, Expression left, Expression right) { + super(source, left, right, SqlBinaryArithmeticOperation.MUL); + } + + @Override + protected TypeResolution resolveType() { + if (!childrenResolved()) { + return new TypeResolution("Unresolved children"); + } + + DataType l = left().dataType(); + DataType r = right().dataType(); + + // 1. both are numbers + if (DataTypes.isNullOrNumeric(l) && DataTypes.isNullOrNumeric(r)) { + return TypeResolution.TYPE_RESOLVED; + } + + if (SqlDataTypes.isNullOrInterval(l) && (r.isInteger() || DataTypes.isNull(r))) { + dataType = l; + return TypeResolution.TYPE_RESOLVED; + } else if (SqlDataTypes.isNullOrInterval(r) && (l.isInteger() || DataTypes.isNull(l))) { + dataType = r; + return TypeResolution.TYPE_RESOLVED; + } + + return new TypeResolution(format(null, "[{}] has arguments with incompatible types [{}] and [{}]", symbol(), l, r)); + } + + @Override + public DataType dataType() { + if (dataType == null) { + dataType = super.dataType(); + } + return dataType; + } + + @Override + protected NodeInfo info() { + return NodeInfo.create(this, Mul::new, left(), right()); + } + + @Override + protected Mul replaceChildren(Expression newLeft, Expression newRight) { + return new Mul(source(), newLeft, newRight); + } +} diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/arithmetic/SqlArithmeticOperation.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/arithmetic/SqlArithmeticOperation.java new file mode 100644 index 0000000000000..8635f7e35b96a --- /dev/null +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/arithmetic/SqlArithmeticOperation.java @@ -0,0 +1,31 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +package org.elasticsearch.xpack.sql.expression.predicate.operator.arithmetic; + +import org.elasticsearch.xpack.ql.expression.Expression; +import org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.ArithmeticOperation; +import org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.BinaryArithmeticOperation; +import org.elasticsearch.xpack.ql.tree.Source; +import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.sql.type.SqlDataTypeConverter; + +public abstract class SqlArithmeticOperation extends ArithmeticOperation { + + private DataType dataType; + + public SqlArithmeticOperation(Source source, Expression left, Expression right, BinaryArithmeticOperation operation) { + super(source, left, right, operation); + } + + @Override + public DataType dataType() { + if (dataType == null) { + dataType = SqlDataTypeConverter.commonType(left().dataType(), right().dataType()); + } + return dataType; + } +} diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/arithmetic/SqlBinaryArithmeticOperation.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/arithmetic/SqlBinaryArithmeticOperation.java new file mode 100644 index 0000000000000..04be1399a1115 --- /dev/null +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/arithmetic/SqlBinaryArithmeticOperation.java @@ -0,0 +1,154 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +package org.elasticsearch.xpack.sql.expression.predicate.operator.arithmetic; + +import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.common.io.stream.StreamOutput; +import org.elasticsearch.script.JodaCompatibleZonedDateTime; +import org.elasticsearch.xpack.ql.QlIllegalArgumentException; +import org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.Arithmetics; +import org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.Arithmetics.NumericArithmetic; +import org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.BinaryArithmeticOperation; +import org.elasticsearch.xpack.sql.expression.literal.interval.Interval; +import org.elasticsearch.xpack.sql.expression.literal.interval.IntervalArithmetics; +import org.elasticsearch.xpack.sql.expression.literal.interval.IntervalDayTime; +import org.elasticsearch.xpack.sql.expression.literal.interval.IntervalYearMonth; + +import java.io.IOException; +import java.time.OffsetTime; +import java.time.ZonedDateTime; +import java.time.temporal.Temporal; +import java.util.function.BiFunction; + + +public enum SqlBinaryArithmeticOperation implements BinaryArithmeticOperation { + + ADD((Object l, Object r) -> { + if (l instanceof Number) { + return Arithmetics.add((Number) l, (Number) r); + } + if (l instanceof IntervalYearMonth && r instanceof IntervalYearMonth) { + return ((IntervalYearMonth) l).add((IntervalYearMonth) r); + } + if (l instanceof IntervalDayTime && r instanceof IntervalDayTime) { + return ((IntervalDayTime) l).add((IntervalDayTime) r); + } + l = unwrapJodaTime(l); + r = unwrapJodaTime(r); + if ((l instanceof ZonedDateTime || l instanceof OffsetTime) && r instanceof IntervalYearMonth) { + return IntervalArithmetics.add((Temporal) l, ((IntervalYearMonth) r).interval()); + } + if ((l instanceof ZonedDateTime || l instanceof OffsetTime) && r instanceof IntervalDayTime) { + return IntervalArithmetics.add((Temporal) l, ((IntervalDayTime) r).interval()); + } + if ((r instanceof ZonedDateTime || r instanceof OffsetTime) && l instanceof IntervalYearMonth) { + return IntervalArithmetics.add((Temporal) r, ((IntervalYearMonth) l).interval()); + } + if ((r instanceof ZonedDateTime || r instanceof OffsetTime) && l instanceof IntervalDayTime) { + return IntervalArithmetics.add((Temporal) r, ((IntervalDayTime) l).interval()); + } + + throw new QlIllegalArgumentException("Cannot compute [+] between [{}] [{}]", l.getClass().getSimpleName(), + r.getClass().getSimpleName()); + }, "+"), + SUB((Object l, Object r) -> { + if (l instanceof Number) { + return Arithmetics.sub((Number) l, (Number) r); + } + if (l instanceof IntervalYearMonth && r instanceof IntervalYearMonth) { + return ((IntervalYearMonth) l).sub((IntervalYearMonth) r); + } + if (l instanceof IntervalDayTime && r instanceof IntervalDayTime) { + return ((IntervalDayTime) l).sub((IntervalDayTime) r); + } + l = unwrapJodaTime(l); + r = unwrapJodaTime(r); + if ((l instanceof ZonedDateTime || l instanceof OffsetTime) && r instanceof IntervalYearMonth) { + return IntervalArithmetics.sub((Temporal) l, ((IntervalYearMonth) r).interval()); + } + if ((l instanceof ZonedDateTime || l instanceof OffsetTime) && r instanceof IntervalDayTime) { + return IntervalArithmetics.sub((Temporal) l, ((IntervalDayTime) r).interval()); + } + if ((r instanceof ZonedDateTime || r instanceof OffsetTime) && l instanceof Interval) { + throw new QlIllegalArgumentException("Cannot subtract a date from an interval; do you mean the reverse?"); + } + + throw new QlIllegalArgumentException("Cannot compute [-] between [{}] [{}]", l.getClass().getSimpleName(), + r.getClass().getSimpleName()); + }, "-"), + MUL((Object l, Object r) -> { + if (l instanceof Number && r instanceof Number) { + return Arithmetics.mul((Number) l, (Number) r); + } + l = unwrapJodaTime(l); + r = unwrapJodaTime(r); + if (l instanceof Number && r instanceof IntervalYearMonth) { + return ((IntervalYearMonth) r).mul(((Number) l).intValue()); + } + if (r instanceof Number && l instanceof IntervalYearMonth) { + return ((IntervalYearMonth) l).mul(((Number) r).intValue()); + } + if (l instanceof Number && r instanceof IntervalDayTime) { + return ((IntervalDayTime) r).mul(((Number) l).longValue()); + } + if (r instanceof Number && l instanceof IntervalDayTime) { + return ((IntervalDayTime) l).mul(((Number) r).longValue()); + } + + throw new QlIllegalArgumentException("Cannot compute [*] between [{}] [{}]", l.getClass().getSimpleName(), + r.getClass().getSimpleName()); + }, "*"), + DIV(Arithmetics::div, "/"), + MOD(Arithmetics::mod, "%"); + + public static final String NAME = "abn-sql"; + + private final BiFunction process; + private final String symbol; + + SqlBinaryArithmeticOperation(BiFunction process, String symbol) { + this.process = process; + this.symbol = symbol; + } + + SqlBinaryArithmeticOperation(NumericArithmetic process, String symbol) { + this(process::wrap, symbol); + } + + @Override + public String symbol() { + return symbol; + } + + @Override + public final Object doApply(Object left, Object right) { + return process.apply(left, right); + } + + @Override + public String toString() { + return symbol; + } + + @Override + public String getWriteableName() { + return NAME; + } + + @Override + public void writeTo(StreamOutput out) throws IOException { + out.writeEnum(this); + } + + public static SqlBinaryArithmeticOperation read(StreamInput in) throws IOException { + return in.readEnum(SqlBinaryArithmeticOperation.class); + } + + private static Object unwrapJodaTime(Object o) { + return o instanceof JodaCompatibleZonedDateTime ? ((JodaCompatibleZonedDateTime) o).getZonedDateTime() : o; + } +} \ No newline at end of file diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/arithmetic/Sub.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/arithmetic/Sub.java new file mode 100644 index 0000000000000..77f8eed05afa3 --- /dev/null +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/arithmetic/Sub.java @@ -0,0 +1,46 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +package org.elasticsearch.xpack.sql.expression.predicate.operator.arithmetic; + +import org.elasticsearch.xpack.ql.expression.Expression; +import org.elasticsearch.xpack.ql.tree.NodeInfo; +import org.elasticsearch.xpack.ql.tree.Source; +import org.elasticsearch.xpack.sql.type.SqlDataTypes; + +import static org.elasticsearch.common.logging.LoggerMessageFormat.format; + +/** + * Subtraction function ({@code a - b}). + */ +public class Sub extends DateTimeArithmeticOperation { + + public Sub(Source source, Expression left, Expression right) { + super(source, left, right, SqlBinaryArithmeticOperation.SUB); + } + + @Override + protected NodeInfo info() { + return NodeInfo.create(this, Sub::new, left(), right()); + } + + @Override + protected Sub replaceChildren(Expression newLeft, Expression newRight) { + return new Sub(source(), newLeft, newRight); + } + + @Override + protected TypeResolution resolveWithIntervals() { + TypeResolution resolution = super.resolveWithIntervals(); + if (resolution.unresolved()) { + return resolution; + } + if ((SqlDataTypes.isDateOrTimeBased(right().dataType())) && SqlDataTypes.isInterval(left().dataType())) { + return new TypeResolution(format(null, "Cannot subtract a {}[{}] from an interval[{}]; do you mean the reverse?", + right().dataType().typeName(), right().source().text(), left().source().text())); + } + return TypeResolution.TYPE_RESOLVED; + } +} diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/comparison/In.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/comparison/In.java similarity index 93% rename from x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/comparison/In.java rename to x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/comparison/In.java index e2bf7a59030c4..5f075a8064cb4 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/comparison/In.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/comparison/In.java @@ -3,11 +3,10 @@ * 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.ql.expression.predicate.operator.comparison; +package org.elasticsearch.xpack.sql.expression.predicate.operator.comparison; import org.elasticsearch.xpack.ql.expression.Expression; import org.elasticsearch.xpack.ql.expression.Expressions; -import org.elasticsearch.xpack.ql.expression.Foldables; import org.elasticsearch.xpack.ql.expression.Nullability; import org.elasticsearch.xpack.ql.expression.TypeResolutions; import org.elasticsearch.xpack.ql.expression.function.scalar.ScalarFunction; @@ -16,7 +15,10 @@ import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import org.elasticsearch.xpack.ql.util.CollectionUtils; +import org.elasticsearch.xpack.sql.expression.Foldables; +import org.elasticsearch.xpack.sql.type.SqlDataTypes; import java.util.ArrayList; import java.util.LinkedHashSet; @@ -26,7 +28,6 @@ import static org.elasticsearch.common.logging.LoggerMessageFormat.format; import static org.elasticsearch.xpack.ql.expression.gen.script.ParamsBuilder.paramsBuilder; -import static org.elasticsearch.xpack.ql.type.DataTypes.areTypesCompatible; import static org.elasticsearch.xpack.ql.util.StringUtils.ordinal; public class In extends ScalarFunction { @@ -63,7 +64,7 @@ public List list() { @Override public DataType dataType() { - return DataType.BOOLEAN; + return DataTypes.BOOLEAN; } @Override @@ -125,7 +126,7 @@ protected TypeResolution resolveType() { DataType dt = value.dataType(); for (int i = 0; i < list.size(); i++) { Expression listValue = list.get(i); - if (areTypesCompatible(dt, listValue.dataType()) == false) { + if (SqlDataTypes.areCompatible(dt, listValue.dataType()) == false) { return new TypeResolution(format(null, "{} argument of [{}] must be [{}], found value [{}] type [{}]", ordinal(i + 1), sourceText(), diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/comparison/InPipe.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/comparison/InPipe.java similarity index 95% rename from x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/comparison/InPipe.java rename to x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/comparison/InPipe.java index 993bd1d80019a..a586e5801cf4d 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/comparison/InPipe.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/comparison/InPipe.java @@ -3,7 +3,7 @@ * 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.ql.expression.predicate.operator.comparison; +package org.elasticsearch.xpack.sql.expression.predicate.operator.comparison; import org.elasticsearch.xpack.ql.expression.Expression; import org.elasticsearch.xpack.ql.expression.gen.pipeline.MultiPipe; diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/comparison/InProcessor.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/comparison/InProcessor.java similarity index 93% rename from x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/comparison/InProcessor.java rename to x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/comparison/InProcessor.java index 2ceb90a39de5e..a81634cddb95e 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/predicate/operator/comparison/InProcessor.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/expression/predicate/operator/comparison/InProcessor.java @@ -3,11 +3,12 @@ * 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.ql.expression.predicate.operator.comparison; +package org.elasticsearch.xpack.sql.expression.predicate.operator.comparison; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.xpack.ql.expression.gen.processor.Processor; +import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.Comparisons; import java.io.IOException; import java.util.ArrayList; diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/optimizer/Optimizer.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/optimizer/Optimizer.java index 06e90a755ecfe..610989c49d68a 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/optimizer/Optimizer.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/optimizer/Optimizer.java @@ -26,20 +26,13 @@ import org.elasticsearch.xpack.ql.expression.predicate.Negatable; import org.elasticsearch.xpack.ql.expression.predicate.Predicates; import org.elasticsearch.xpack.ql.expression.predicate.Range; -import org.elasticsearch.xpack.ql.expression.predicate.conditional.ArbitraryConditionalFunction; -import org.elasticsearch.xpack.ql.expression.predicate.conditional.Case; -import org.elasticsearch.xpack.ql.expression.predicate.conditional.Coalesce; -import org.elasticsearch.xpack.ql.expression.predicate.conditional.IfConditional; import org.elasticsearch.xpack.ql.expression.predicate.logical.And; import org.elasticsearch.xpack.ql.expression.predicate.logical.Not; import org.elasticsearch.xpack.ql.expression.predicate.logical.Or; -import org.elasticsearch.xpack.ql.expression.predicate.nulls.IsNotNull; -import org.elasticsearch.xpack.ql.expression.predicate.nulls.IsNull; import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.BinaryComparison; import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.Equals; import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.GreaterThan; import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.GreaterThanOrEqual; -import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.In; import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.LessThan; import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.LessThanOrEqual; import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.NotEquals; @@ -55,7 +48,7 @@ import org.elasticsearch.xpack.ql.rule.Rule; import org.elasticsearch.xpack.ql.rule.RuleExecutor; import org.elasticsearch.xpack.ql.tree.Source; -import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import org.elasticsearch.xpack.ql.util.CollectionUtils; import org.elasticsearch.xpack.ql.util.Holder; import org.elasticsearch.xpack.sql.SqlIllegalArgumentException; @@ -75,6 +68,13 @@ import org.elasticsearch.xpack.sql.expression.function.aggregate.Stats; import org.elasticsearch.xpack.sql.expression.function.aggregate.TopHits; import org.elasticsearch.xpack.sql.expression.function.scalar.Cast; +import org.elasticsearch.xpack.sql.expression.predicate.conditional.ArbitraryConditionalFunction; +import org.elasticsearch.xpack.sql.expression.predicate.conditional.Case; +import org.elasticsearch.xpack.sql.expression.predicate.conditional.Coalesce; +import org.elasticsearch.xpack.sql.expression.predicate.conditional.IfConditional; +import org.elasticsearch.xpack.sql.expression.predicate.nulls.IsNotNull; +import org.elasticsearch.xpack.sql.expression.predicate.nulls.IsNull; +import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.In; import org.elasticsearch.xpack.sql.plan.logical.LocalRelation; import org.elasticsearch.xpack.sql.plan.logical.Pivot; import org.elasticsearch.xpack.sql.plan.logical.SubQueryAlias; @@ -673,12 +673,12 @@ static class FoldNull extends OptimizerExpressionRule { protected Expression rule(Expression e) { if (e instanceof IsNotNull) { if (((IsNotNull) e).field().nullable() == Nullability.FALSE) { - return new Literal(e.source(), Boolean.TRUE, DataType.BOOLEAN); + return new Literal(e.source(), Boolean.TRUE, DataTypes.BOOLEAN); } } else if (e instanceof IsNull) { if (((IsNull) e).field().nullable() == Nullability.FALSE) { - return new Literal(e.source(), Boolean.FALSE, DataType.BOOLEAN); + return new Literal(e.source(), Boolean.FALSE, DataTypes.BOOLEAN); } } else if (e instanceof In) { @@ -808,7 +808,7 @@ private Expression simplifyAndOr(BinaryPredicate bc) { } if (FALSE.equals(l) || FALSE.equals(r)) { - return new Literal(bc.source(), Boolean.FALSE, DataType.BOOLEAN); + return new Literal(bc.source(), Boolean.FALSE, DataTypes.BOOLEAN); } if (l.semanticEquals(r)) { return l; @@ -838,7 +838,7 @@ private Expression simplifyAndOr(BinaryPredicate bc) { if (bc instanceof Or) { if (TRUE.equals(l) || TRUE.equals(r)) { - return new Literal(bc.source(), Boolean.TRUE, DataType.BOOLEAN); + return new Literal(bc.source(), Boolean.TRUE, DataTypes.BOOLEAN); } if (FALSE.equals(l)) { @@ -883,10 +883,10 @@ private Expression simplifyNot(Not n) { Expression c = n.field(); if (TRUE.semanticEquals(c)) { - return new Literal(n.source(), Boolean.FALSE, DataType.BOOLEAN); + return new Literal(n.source(), Boolean.FALSE, DataTypes.BOOLEAN); } if (FALSE.semanticEquals(c)) { - return new Literal(n.source(), Boolean.TRUE, DataType.BOOLEAN); + return new Literal(n.source(), Boolean.TRUE, DataTypes.BOOLEAN); } if (c instanceof Negatable) { @@ -919,12 +919,12 @@ private Expression simplify(BinaryComparison bc) { // true for equality if (bc instanceof Equals || bc instanceof GreaterThanOrEqual || bc instanceof LessThanOrEqual) { if (l.nullable() == Nullability.FALSE && r.nullable() == Nullability.FALSE && l.semanticEquals(r)) { - return new Literal(bc.source(), Boolean.TRUE, DataType.BOOLEAN); + return new Literal(bc.source(), Boolean.TRUE, DataTypes.BOOLEAN); } } if (bc instanceof NullEquals) { if (l.semanticEquals(r)) { - return new Literal(bc.source(), Boolean.TRUE, DataType.BOOLEAN); + return new Literal(bc.source(), Boolean.TRUE, DataTypes.BOOLEAN); } if (Expressions.isNull(r)) { return new IsNull(bc.source(), l); @@ -934,7 +934,7 @@ private Expression simplify(BinaryComparison bc) { // false for equality if (bc instanceof NotEquals || bc instanceof GreaterThan || bc instanceof LessThan) { if (l.nullable() == Nullability.FALSE && r.nullable() == Nullability.FALSE && l.semanticEquals(r)) { - return new Literal(bc.source(), Boolean.FALSE, DataType.BOOLEAN); + return new Literal(bc.source(), Boolean.FALSE, DataTypes.BOOLEAN); } } @@ -1010,7 +1010,7 @@ private Expression propagate(And and) { if (comp != null) { // var cannot be equal to two different values at the same time if (comp != 0) { - return new Literal(and.source(), Boolean.FALSE, DataType.BOOLEAN); + return new Literal(and.source(), Boolean.FALSE, DataTypes.BOOLEAN); } } } @@ -1031,12 +1031,12 @@ private Expression propagate(And and) { NotEquals otherNotEq = (NotEquals) ex; if (otherNotEq.right().foldable()) { notEquals.add(otherNotEq); + } else { + exps.add(ex); + } } else { exps.add(ex); } - } else { - exps.add(ex); - } } // check @@ -1056,7 +1056,7 @@ private Expression propagate(And and) { // eq matches the boundary but should not be included (compare == 0 && !range.includeLower())) ) { - return new Literal(and.source(), Boolean.FALSE, DataType.BOOLEAN); + return new Literal(and.source(), Boolean.FALSE, DataTypes.BOOLEAN); } } if (range.upper().foldable()) { @@ -1067,7 +1067,7 @@ private Expression propagate(And and) { // eq matches the boundary but should not be included (compare == 0 && !range.includeUpper())) ) { - return new Literal(and.source(), Boolean.FALSE, DataType.BOOLEAN); + return new Literal(and.source(), Boolean.FALSE, DataTypes.BOOLEAN); } } @@ -1088,7 +1088,7 @@ private Expression propagate(And and) { } else { iter.remove(); // clashing and redundant: a = 1 AND a != 2 changed = true; - } + } } } } @@ -1103,12 +1103,12 @@ private Expression propagate(And and) { if ((compare == 0 && bc instanceof LessThan) || // a = 2 AND a < 2 0 < compare) { // a = 2 AND a />= ? if ((compare == 0 && bc instanceof GreaterThan) || // a = 2 AND a > 2 compare < 0) { // a = 2 AND a >/>= 3 return FALSE; - } + } } iter.remove(); @@ -1908,13 +1908,13 @@ protected LogicalPlan rule(LogicalPlan plan) { return plan.transformExpressionsDown(e -> { if (e instanceof Min) { Min min = (Min) e; - if (min.field().dataType().isString()) { + if (DataTypes.isString(min.field().dataType())) { return mins.computeIfAbsent(min.field(), k -> new First(min.source(), k, null)); } } if (e instanceof Max) { Max max = (Max) e; - if (max.field().dataType().isString()) { + if (DataTypes.isString(max.field().dataType())) { return maxs.computeIfAbsent(max.field(), k -> new Last(max.source(), k, null)); } } @@ -1950,7 +1950,7 @@ private static Expression foldBinaryLogic(Expression expression) { boolean nullLeft = Expressions.isNull(or.left()); boolean nullRight = Expressions.isNull(or.right()); if (nullLeft && nullRight) { - return new Literal(expression.source(), null, DataType.NULL); + return new Literal(expression.source(), null, DataTypes.NULL); } if (nullLeft) { return or.right(); @@ -1962,7 +1962,7 @@ private static Expression foldBinaryLogic(Expression expression) { if (expression instanceof And) { And and = (And) expression; if (Expressions.isNull(and.left()) || Expressions.isNull(and.right())) { - return new Literal(expression.source(), null, DataType.NULL); + return new Literal(expression.source(), null, DataTypes.NULL); } } return expression; diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/ExpressionBuilder.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/ExpressionBuilder.java index 3a00de63c1732..df9453228c7a8 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/ExpressionBuilder.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/ExpressionBuilder.java @@ -24,32 +24,17 @@ import org.elasticsearch.xpack.ql.expression.function.Function; import org.elasticsearch.xpack.ql.expression.function.UnresolvedFunction; import org.elasticsearch.xpack.ql.expression.function.UnresolvedFunction.ResolutionType; -import org.elasticsearch.xpack.ql.expression.literal.Interval; -import org.elasticsearch.xpack.ql.expression.literal.IntervalDayTime; -import org.elasticsearch.xpack.ql.expression.literal.IntervalYearMonth; -import org.elasticsearch.xpack.ql.expression.literal.Intervals; -import org.elasticsearch.xpack.ql.expression.literal.Intervals.TimeUnit; import org.elasticsearch.xpack.ql.expression.predicate.Range; -import org.elasticsearch.xpack.ql.expression.predicate.conditional.Case; -import org.elasticsearch.xpack.ql.expression.predicate.conditional.IfConditional; import org.elasticsearch.xpack.ql.expression.predicate.fulltext.MatchQueryPredicate; import org.elasticsearch.xpack.ql.expression.predicate.fulltext.MultiMatchQueryPredicate; import org.elasticsearch.xpack.ql.expression.predicate.fulltext.StringQueryPredicate; import org.elasticsearch.xpack.ql.expression.predicate.logical.And; import org.elasticsearch.xpack.ql.expression.predicate.logical.Not; import org.elasticsearch.xpack.ql.expression.predicate.logical.Or; -import org.elasticsearch.xpack.ql.expression.predicate.nulls.IsNotNull; -import org.elasticsearch.xpack.ql.expression.predicate.nulls.IsNull; -import org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.Add; -import org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.Div; -import org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.Mod; -import org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.Mul; import org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.Neg; -import org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.Sub; import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.Equals; import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.GreaterThan; import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.GreaterThanOrEqual; -import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.In; import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.LessThan; import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.LessThanOrEqual; import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.NotEquals; @@ -64,6 +49,21 @@ import org.elasticsearch.xpack.sql.expression.Exists; import org.elasticsearch.xpack.sql.expression.ScalarSubquery; import org.elasticsearch.xpack.sql.expression.function.scalar.Cast; +import org.elasticsearch.xpack.sql.expression.literal.interval.Interval; +import org.elasticsearch.xpack.sql.expression.literal.interval.IntervalDayTime; +import org.elasticsearch.xpack.sql.expression.literal.interval.IntervalYearMonth; +import org.elasticsearch.xpack.sql.expression.literal.interval.Intervals; +import org.elasticsearch.xpack.sql.expression.literal.interval.Intervals.TimeUnit; +import org.elasticsearch.xpack.sql.expression.predicate.conditional.Case; +import org.elasticsearch.xpack.sql.expression.predicate.conditional.IfConditional; +import org.elasticsearch.xpack.sql.expression.predicate.nulls.IsNotNull; +import org.elasticsearch.xpack.sql.expression.predicate.nulls.IsNull; +import org.elasticsearch.xpack.sql.expression.predicate.operator.arithmetic.Add; +import org.elasticsearch.xpack.sql.expression.predicate.operator.arithmetic.Div; +import org.elasticsearch.xpack.sql.expression.predicate.operator.arithmetic.Mod; +import org.elasticsearch.xpack.sql.expression.predicate.operator.arithmetic.Mul; +import org.elasticsearch.xpack.sql.expression.predicate.operator.arithmetic.Sub; +import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.In; import org.elasticsearch.xpack.sql.parser.SqlBaseParser.ArithmeticBinaryContext; import org.elasticsearch.xpack.sql.parser.SqlBaseParser.ArithmeticUnaryContext; import org.elasticsearch.xpack.sql.parser.SqlBaseParser.BooleanLiteralContext; @@ -114,6 +114,7 @@ import org.elasticsearch.xpack.sql.parser.SqlBaseParser.TimestampEscapedLiteralContext; import org.elasticsearch.xpack.sql.parser.SqlBaseParser.ValueExpressionDefaultContext; import org.elasticsearch.xpack.sql.proto.SqlTypedParamValue; +import org.elasticsearch.xpack.sql.type.SqlDataTypes; import java.time.Duration; import java.time.Period; @@ -128,7 +129,7 @@ import static java.util.Collections.emptyList; import static java.util.Collections.singletonList; -import static org.elasticsearch.xpack.ql.type.DataTypeConversion.conversionFor; +import static org.elasticsearch.xpack.ql.type.DataTypeConverter.converterFor; import static org.elasticsearch.xpack.sql.util.DateUtils.asDateOnly; import static org.elasticsearch.xpack.sql.util.DateUtils.asTimeOnly; import static org.elasticsearch.xpack.sql.util.DateUtils.ofEscapedLiteral; @@ -407,7 +408,7 @@ public Cast visitCastExpression(CastExpressionContext ctx) { private static DataType dataType(Source ctx, String string) { String type = string.toUpperCase(Locale.ROOT); - DataType dataType = type.startsWith("SQL_") ? DataType.fromOdbcType(type) : DataType.fromSqlOrEsType(type); + DataType dataType = type.startsWith("SQL_") ? SqlDataTypes.fromOdbcType(type) : SqlDataTypes.fromSqlOrEsType(type); if (dataType == null) { throw new ParsingException(ctx, "Does not recognize type [{}]", string); } @@ -519,7 +520,7 @@ public Object visitLogicalBinary(LogicalBinaryContext ctx) { @Override public Expression visitNullLiteral(NullLiteralContext ctx) { - return new Literal(source(ctx), null, DataType.NULL); + return new Literal(source(ctx), null, DataTypes.NULL); } @Override @@ -650,7 +651,7 @@ public Expression visitBooleanLiteral(BooleanLiteralContext ctx) { } catch(IllegalArgumentException iae) { throw new ParsingException(source(ctx), iae.getMessage()); } - return new Literal(source(ctx), Boolean.valueOf(value), DataType.BOOLEAN); + return new Literal(source(ctx), Boolean.valueOf(value), DataTypes.BOOLEAN); } @Override @@ -659,7 +660,7 @@ public Expression visitStringLiteral(StringLiteralContext ctx) { for (TerminalNode node : ctx.STRING()) { sb.append(unquoteString(text(node))); } - return new Literal(source(ctx), sb.toString(), DataType.KEYWORD); + return new Literal(source(ctx), sb.toString(), DataTypes.KEYWORD); } @Override @@ -667,7 +668,7 @@ public Literal visitDecimalLiteral(DecimalLiteralContext ctx) { Tuple tuple = withMinus(ctx); try { - return new Literal(tuple.v1(), Double.valueOf(StringUtils.parseDouble(tuple.v2())), DataType.DOUBLE); + return new Literal(tuple.v1(), Double.valueOf(StringUtils.parseDouble(tuple.v2())), DataTypes.DOUBLE); } catch (QlIllegalArgumentException siae) { throw new ParsingException(tuple.v1(), siae.getMessage()); } @@ -685,10 +686,10 @@ public Literal visitIntegerLiteral(IntegerLiteralContext ctx) { } Object val = Long.valueOf(value); - DataType type = DataType.LONG; + DataType type = DataTypes.LONG; // try to downsize to int if possible (since that's the most common type) if ((int) value == value) { - type = DataType.INTEGER; + type = DataTypes.INTEGER; val = Integer.valueOf((int) value); } return new Literal(tuple.v1(), val, type); @@ -697,7 +698,7 @@ public Literal visitIntegerLiteral(IntegerLiteralContext ctx) { @Override public Literal visitParamLiteral(ParamLiteralContext ctx) { SqlTypedParamValue param = param(ctx.PARAM()); - DataType dataType = DataType.fromTypeName(param.type); + DataType dataType = SqlDataTypes.fromTypeName(param.type); Source source = source(ctx); if (param.value == null) { // no conversion is required for null values @@ -716,7 +717,7 @@ public Literal visitParamLiteral(ParamLiteralContext ctx) { } // otherwise we need to make sure that xcontent-serialized value is converted to the correct type try { - return new Literal(source, conversionFor(sourceType, dataType).convert(param.value), dataType); + return new Literal(source, converterFor(sourceType, dataType).convert(param.value), dataType); } catch (QlIllegalArgumentException ex) { throw new ParsingException(ex, source, "Unexpected actual parameter type [{}] for type [{}]", sourceType, param.type); } @@ -762,7 +763,7 @@ public Literal visitDateEscapedLiteral(DateEscapedLiteralContext ctx) { Source source = source(ctx); // parse yyyy-MM-dd try { - return new Literal(source, asDateOnly(string), DataType.DATE); + return new Literal(source, asDateOnly(string), SqlDataTypes.DATE); } catch(DateTimeParseException ex) { throw new ParsingException(source, "Invalid date received; {}", ex.getMessage()); } @@ -775,7 +776,7 @@ public Literal visitTimeEscapedLiteral(TimeEscapedLiteralContext ctx) { // parse HH:mm:ss try { - return new Literal(source, asTimeOnly(string), DataType.TIME); + return new Literal(source, asTimeOnly(string), SqlDataTypes.TIME); } catch (DateTimeParseException ex) { throw new ParsingException(source, "Invalid time received; {}", ex.getMessage()); } @@ -788,7 +789,7 @@ public Literal visitTimestampEscapedLiteral(TimestampEscapedLiteralContext ctx) Source source = source(ctx); // parse yyyy-mm-dd hh:mm:ss(.f...) try { - return new Literal(source, ofEscapedLiteral(string), DataType.DATETIME); + return new Literal(source, ofEscapedLiteral(string), DataTypes.DATETIME); } catch (DateTimeParseException ex) { throw new ParsingException(source, "Invalid timestamp received; {}", ex.getMessage()); } @@ -837,7 +838,7 @@ public Literal visitGuidEscapedLiteral(GuidEscapedLiteralContext ctx) { } } - return new Literal(source(ctx), string, DataType.KEYWORD); + return new Literal(source(ctx), string, DataTypes.KEYWORD); } /** diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/LogicalPlanBuilder.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/LogicalPlanBuilder.java index 2d3b2d0dfbc67..9f377cd369e45 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/LogicalPlanBuilder.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/parser/LogicalPlanBuilder.java @@ -24,7 +24,7 @@ import org.elasticsearch.xpack.ql.plan.logical.Project; import org.elasticsearch.xpack.ql.plan.logical.UnresolvedRelation; import org.elasticsearch.xpack.ql.tree.Source; -import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import org.elasticsearch.xpack.sql.parser.SqlBaseParser.AliasedQueryContext; import org.elasticsearch.xpack.sql.parser.SqlBaseParser.AliasedRelationContext; import org.elasticsearch.xpack.sql.parser.SqlBaseParser.FromClauseContext; @@ -105,7 +105,7 @@ public LogicalPlan visitQueryNoWith(QueryNoWithContext ctx) { Token limit = limitClause.limit; if (limit != null && limitClause.INTEGER_VALUE() != null) { plan = new Limit(source(limitClause), new Literal(source(limitClause), - Integer.parseInt(limit.getText()), DataType.INTEGER), plan); + Integer.parseInt(limit.getText()), DataTypes.INTEGER), plan); } } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/Join.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/Join.java index 80103bcea0080..85d917bc2c0b2 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/Join.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/Join.java @@ -12,7 +12,7 @@ import org.elasticsearch.xpack.ql.plan.logical.LogicalPlan; import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; -import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import java.util.List; import java.util.Objects; @@ -102,7 +102,7 @@ public boolean resolved() { return childrenResolved() && duplicatesResolved() && expressionsResolved() && - (condition == null || DataType.BOOLEAN == condition.dataType()); + (condition == null || DataTypes.BOOLEAN == condition.dataType()); } @Override diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/command/ShowColumns.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/command/ShowColumns.java index 80795323b485c..d510e2c4926f8 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/command/ShowColumns.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plan/logical/command/ShowColumns.java @@ -16,6 +16,7 @@ import org.elasticsearch.xpack.ql.type.KeywordEsField; import org.elasticsearch.xpack.sql.session.Cursor.Page; import org.elasticsearch.xpack.sql.session.SqlSession; +import org.elasticsearch.xpack.sql.type.SqlDataTypes; import java.util.ArrayList; import java.util.List; @@ -84,7 +85,7 @@ private void fillInRows(Map mapping, String prefix, List output() { @Override public final void execute(SqlSession session, ActionListener listener) { - Stream values = Stream.of(DataType.values()); + Stream values = SqlDataTypes.types().stream(); if (type.intValue() != 0) { - values = values.filter(t -> type.equals(t.sqlType().getVendorTypeNumber())); + values = values.filter(t -> type.equals(sqlType(t).getVendorTypeNumber())); } List> rows = values // sort by SQL int type (that's what the JDBC/ODBC specs want) followed by name - .sorted(Comparator.comparing((DataType t) -> t.sqlType().getVendorTypeNumber()).thenComparing(DataType::sqlName)) + .sorted(Comparator.comparing((DataType t) -> sqlType(t).getVendorTypeNumber()) + .thenComparing((DataType t) -> sqlType(t).getName())) .map(t -> asList(t.toString(), - t.sqlType().getVendorTypeNumber(), - DataTypes.precision(t), + sqlType(t).getVendorTypeNumber(), precision(t), "'", "'", null, // don't be specific on nullable DatabaseMetaData.typeNullableUnknown, // all strings are case-sensitive - t.isString(), + isString(t), // everything is searchable, DatabaseMetaData.typeSearchable, // only numerics are signed - !t.isSigned(), + isSigned(t) == false, //no fixed precision scale SQL_FALSE Boolean.FALSE, // not auto-incremented Boolean.FALSE, null, - DataTypes.metaSqlMinimumScale(t), - DataTypes.metaSqlMaximumScale(t), + metaSqlMinimumScale(t), metaSqlMaximumScale(t), // SQL_DATA_TYPE - ODBC wants this to be not null - DataTypes.metaSqlDataType(t), - DataTypes.metaSqlDateTimeSub(t), + metaSqlDataType(t), metaSqlDateTimeSub(t), // Radix - DataTypes.metaSqlRadix(t), + metaSqlRadix(t), null )) .collect(toList()); diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/planner/QueryFolder.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/planner/QueryFolder.java index 663ef503cc16c..335df0603b148 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/planner/QueryFolder.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/planner/QueryFolder.java @@ -14,7 +14,6 @@ import org.elasticsearch.xpack.ql.expression.Expression; import org.elasticsearch.xpack.ql.expression.Expressions; import org.elasticsearch.xpack.ql.expression.FieldAttribute; -import org.elasticsearch.xpack.ql.expression.Foldables; import org.elasticsearch.xpack.ql.expression.Literal; import org.elasticsearch.xpack.ql.expression.NamedExpression; import org.elasticsearch.xpack.ql.expression.Order; @@ -31,17 +30,18 @@ import org.elasticsearch.xpack.ql.expression.gen.pipeline.UnaryPipe; import org.elasticsearch.xpack.ql.expression.gen.processor.Processor; import org.elasticsearch.xpack.ql.expression.gen.script.ScriptTemplate; -import org.elasticsearch.xpack.ql.expression.literal.IntervalYearMonth; -import org.elasticsearch.xpack.ql.expression.literal.Intervals; import org.elasticsearch.xpack.ql.rule.Rule; import org.elasticsearch.xpack.ql.rule.RuleExecutor; import org.elasticsearch.xpack.sql.SqlIllegalArgumentException; +import org.elasticsearch.xpack.sql.expression.Foldables; import org.elasticsearch.xpack.sql.expression.function.Score; import org.elasticsearch.xpack.sql.expression.function.aggregate.CompoundNumericAggregate; import org.elasticsearch.xpack.sql.expression.function.aggregate.TopHits; import org.elasticsearch.xpack.sql.expression.function.grouping.Histogram; import org.elasticsearch.xpack.sql.expression.function.scalar.datetime.DateTimeHistogramFunction; import org.elasticsearch.xpack.sql.expression.function.scalar.datetime.Year; +import org.elasticsearch.xpack.sql.expression.literal.interval.IntervalYearMonth; +import org.elasticsearch.xpack.sql.expression.literal.interval.Intervals; import org.elasticsearch.xpack.sql.plan.logical.Pivot; import org.elasticsearch.xpack.sql.plan.physical.AggregateExec; import org.elasticsearch.xpack.sql.plan.physical.EsQueryExec; @@ -88,11 +88,12 @@ import java.util.Map.Entry; import java.util.concurrent.atomic.AtomicReference; -import static org.elasticsearch.xpack.ql.type.DataType.DATE; import static org.elasticsearch.xpack.ql.util.CollectionUtils.combine; import static org.elasticsearch.xpack.sql.planner.QueryTranslator.and; import static org.elasticsearch.xpack.sql.planner.QueryTranslator.toAgg; import static org.elasticsearch.xpack.sql.planner.QueryTranslator.toQuery; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.DATE; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.isDateBased; /** * Folds the PhysicalPlan into a {@link Query}. @@ -318,7 +319,7 @@ else if (exp instanceof GroupingFunction) { Expression field = h.field(); // date histogram - if (h.dataType().isDateBased()) { + if (isDateBased(h.dataType())) { Object value = h.interval().value(); // interval of exactly 1 year if (value instanceof IntervalYearMonth @@ -502,7 +503,7 @@ else if (target instanceof Function) { if (matchingGroup != null) { if (exp instanceof Attribute || exp instanceof ScalarFunction || exp instanceof GroupingFunction) { Processor action = null; - boolean isDateBased = exp.dataType().isDateBased(); + boolean isDateBased = isDateBased(exp.dataType()); /* * special handling of dates since aggs return the typed Date object which needs * extraction instead of handling this in the scroller, the folder handles this @@ -547,11 +548,11 @@ else if (target instanceof Function) { // attributes can only refer to declared groups if (target instanceof Attribute) { Check.notNull(matchingGroup, "Cannot find group [{}]", Expressions.name(target)); - queryC = queryC.addColumn(new GroupByRef(matchingGroup.id(), null, target.dataType().isDateBased()), id); + queryC = queryC.addColumn(new GroupByRef(matchingGroup.id(), null, isDateBased(target.dataType())), id); } // handle histogram else if (target instanceof GroupingFunction) { - queryC = queryC.addColumn(new GroupByRef(matchingGroup.id(), null, target.dataType().isDateBased()), id); + queryC = queryC.addColumn(new GroupByRef(matchingGroup.id(), null, isDateBased(target.dataType())), id); } // handle literal else if (target.foldable()) { @@ -577,7 +578,7 @@ else if (target.foldable()) { matchingGroup = groupingContext.groupFor(target); Check.notNull(matchingGroup, "Cannot find group [{}]", Expressions.name(ne)); - queryC = queryC.addColumn(new GroupByRef(matchingGroup.id(), null, ne.dataType().isDateBased()), id); + queryC = queryC.addColumn(new GroupByRef(matchingGroup.id(), null, isDateBased(ne.dataType())), id); } // fallback else { @@ -642,14 +643,14 @@ private static Tuple addAggFunction(GroupByKey gro aggInput = new AggPathInput(f, new MetricAggRef(cAggPath, ia.innerName(), ia.innerKey() != null ? QueryTranslator.nameOf(ia.innerKey()) : null, - ia.dataType().isDateBased())); + isDateBased(ia.dataType()))); } else { LeafAgg leafAgg = toAgg(functionId, f); if (f instanceof TopHits) { aggInput = new AggPathInput(f, new TopHitsAggRef(leafAgg.id(), f.dataType())); } else { - aggInput = new AggPathInput(f, new MetricAggRef(leafAgg.id(), f.dataType().isDateBased())); + aggInput = new AggPathInput(f, new MetricAggRef(leafAgg.id(), isDateBased(f.dataType()))); } queryC = queryC.with(queryC.aggs().addAgg(leafAgg)); } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/planner/QueryTranslator.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/planner/QueryTranslator.java index 434b338020899..4285e2b57ca9b 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/planner/QueryTranslator.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/planner/QueryTranslator.java @@ -18,7 +18,6 @@ import org.elasticsearch.xpack.ql.expression.function.aggregate.AggregateFunction; import org.elasticsearch.xpack.ql.expression.function.aggregate.Count; import org.elasticsearch.xpack.ql.expression.function.scalar.ScalarFunction; -import org.elasticsearch.xpack.ql.expression.function.scalar.geo.GeoShape; import org.elasticsearch.xpack.ql.expression.gen.script.ScriptTemplate; import org.elasticsearch.xpack.ql.expression.predicate.Range; import org.elasticsearch.xpack.ql.expression.predicate.fulltext.MatchQueryPredicate; @@ -27,13 +26,10 @@ import org.elasticsearch.xpack.ql.expression.predicate.logical.And; import org.elasticsearch.xpack.ql.expression.predicate.logical.Not; import org.elasticsearch.xpack.ql.expression.predicate.logical.Or; -import org.elasticsearch.xpack.ql.expression.predicate.nulls.IsNotNull; -import org.elasticsearch.xpack.ql.expression.predicate.nulls.IsNull; import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.BinaryComparison; import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.Equals; import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.GreaterThan; import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.GreaterThanOrEqual; -import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.In; import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.LessThan; import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.LessThanOrEqual; import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.NotEquals; @@ -62,6 +58,10 @@ import org.elasticsearch.xpack.sql.expression.function.aggregate.TopHits; import org.elasticsearch.xpack.sql.expression.function.scalar.datetime.DateTimeFunction; import org.elasticsearch.xpack.sql.expression.function.scalar.geo.StDistance; +import org.elasticsearch.xpack.sql.expression.literal.geo.GeoShape; +import org.elasticsearch.xpack.sql.expression.predicate.nulls.IsNotNull; +import org.elasticsearch.xpack.sql.expression.predicate.nulls.IsNull; +import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.In; import org.elasticsearch.xpack.sql.querydsl.agg.AggFilter; import org.elasticsearch.xpack.sql.querydsl.agg.AndAggFilter; import org.elasticsearch.xpack.sql.querydsl.agg.AvgAgg; @@ -105,8 +105,8 @@ import static java.util.Collections.singletonList; import static org.elasticsearch.xpack.ql.expression.Expressions.id; -import static org.elasticsearch.xpack.ql.expression.Foldables.doubleValuesOf; -import static org.elasticsearch.xpack.ql.expression.Foldables.valueOf; +import static org.elasticsearch.xpack.sql.expression.Foldables.doubleValuesOf; +import static org.elasticsearch.xpack.sql.expression.Foldables.valueOf; final class QueryTranslator { diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlPlugin.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlPlugin.java index 59ebc6547d995..dbe14f99f3365 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlPlugin.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/SqlPlugin.java @@ -40,6 +40,7 @@ import org.elasticsearch.xpack.sql.action.SqlQueryAction; import org.elasticsearch.xpack.sql.action.SqlTranslateAction; import org.elasticsearch.xpack.sql.execution.PlanExecutor; +import org.elasticsearch.xpack.sql.type.SqlDataTypeRegistry; import java.util.Arrays; import java.util.Collection; @@ -100,7 +101,7 @@ Collection createComponents(Client client, String clusterName, NamedWrit if (false == enabled) { return emptyList(); } - IndexResolver indexResolver = new IndexResolver(client, clusterName); + IndexResolver indexResolver = new IndexResolver(client, clusterName, SqlDataTypeRegistry.INSTANCE); return Arrays.asList(sqlLicenseChecker, indexResolver, new PlanExecutor(client, indexResolver, namedWriteableRegistry)); } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/TransportSqlQueryAction.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/TransportSqlQueryAction.java index 0ed2baea42572..cc0e8088dc522 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/TransportSqlQueryAction.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/plugin/TransportSqlQueryAction.java @@ -30,6 +30,7 @@ import org.elasticsearch.xpack.sql.session.Cursors; import org.elasticsearch.xpack.sql.session.RowSet; import org.elasticsearch.xpack.sql.session.SchemaRowSet; +import org.elasticsearch.xpack.sql.type.SqlDataTypes; import java.util.ArrayList; import java.util.List; @@ -95,7 +96,7 @@ static SqlQueryResponse createResponseWithSchema(SqlQueryRequest request, Page p List columns = new ArrayList<>(rowSet.columnCount()); for (Schema.Entry entry : rowSet.schema()) { if (Mode.isDriver(request.mode())) { - columns.add(new ColumnInfo("", entry.name(), entry.type().typeName(), entry.type().displaySize)); + columns.add(new ColumnInfo("", entry.name(), entry.type().typeName(), SqlDataTypes.displaySize(entry.type()))); } else { columns.add(new ColumnInfo("", entry.name(), entry.type().typeName())); } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/agg/GroupByKey.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/agg/GroupByKey.java index cf2f7c56c03e4..69f6eea3acc37 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/agg/GroupByKey.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/agg/GroupByKey.java @@ -8,11 +8,17 @@ import org.elasticsearch.search.aggregations.bucket.composite.CompositeValuesSourceBuilder; import org.elasticsearch.search.aggregations.support.ValueType; import org.elasticsearch.xpack.ql.expression.gen.script.ScriptTemplate; -import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import org.elasticsearch.xpack.sql.querydsl.container.Sort.Direction; import java.util.Objects; +import static org.elasticsearch.xpack.ql.type.DataTypes.BOOLEAN; +import static org.elasticsearch.xpack.ql.type.DataTypes.DATETIME; +import static org.elasticsearch.xpack.ql.type.DataTypes.IP; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.DATE; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.TIME; + /** * A key for a SQL GroupBy which maps to value source for composite aggregation. */ @@ -37,17 +43,17 @@ public final CompositeValuesSourceBuilder asValueSource() { builder.valueType(ValueType.LONG); } else if (script.outputType().isRational()) { builder.valueType(ValueType.DOUBLE); - } else if (script.outputType().isString()) { + } else if (DataTypes.isString(script.outputType())) { builder.valueType(ValueType.STRING); - } else if (script.outputType() == DataType.DATE) { + } else if (script.outputType() == DATE) { builder.valueType(ValueType.LONG); - } else if (script.outputType() == DataType.TIME) { + } else if (script.outputType() == TIME) { builder.valueType(ValueType.LONG); - } else if (script.outputType() == DataType.DATETIME) { + } else if (script.outputType() == DATETIME) { builder.valueType(ValueType.LONG); - } else if (script.outputType() == DataType.BOOLEAN) { + } else if (script.outputType() == BOOLEAN) { builder.valueType(ValueType.BOOLEAN); - } else if (script.outputType() == DataType.IP) { + } else if (script.outputType() == IP) { builder.valueType(ValueType.IP); } } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/agg/TopHitsAgg.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/agg/TopHitsAgg.java index efc9aebf98dc1..7131e5f8a0d17 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/agg/TopHitsAgg.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/agg/TopHitsAgg.java @@ -10,6 +10,7 @@ import org.elasticsearch.search.sort.SortBuilder; import org.elasticsearch.search.sort.SortOrder; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.sql.type.SqlDataTypes; import java.util.ArrayList; import java.util.List; @@ -52,7 +53,7 @@ AggregationBuilder toBuilder() { .missing(LAST.position()) .unmappedType(fieldDataType.esType())); - return topHits(id()).docValueField(fieldName(), fieldDataType.format()).sorts(sortBuilderList).size(1); + return topHits(id()).docValueField(fieldName(), SqlDataTypes.format(fieldDataType)).sorts(sortBuilderList).size(1); } @Override diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/container/QueryContainer.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/container/QueryContainer.java index a049e7de145b9..0279dd49180e9 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/container/QueryContainer.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/container/QueryContainer.java @@ -22,7 +22,7 @@ import org.elasticsearch.xpack.ql.expression.gen.pipeline.ConstantInput; import org.elasticsearch.xpack.ql.expression.gen.pipeline.Pipe; import org.elasticsearch.xpack.ql.tree.Source; -import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import org.elasticsearch.xpack.sql.SqlIllegalArgumentException; import org.elasticsearch.xpack.sql.execution.search.SourceGenerator; import org.elasticsearch.xpack.sql.expression.function.Score; @@ -34,6 +34,7 @@ import org.elasticsearch.xpack.sql.querydsl.query.MatchAll; import org.elasticsearch.xpack.sql.querydsl.query.NestedQuery; import org.elasticsearch.xpack.sql.querydsl.query.Query; +import org.elasticsearch.xpack.sql.type.SqlDataTypes; import java.io.IOException; import java.util.AbstractMap; @@ -348,9 +349,9 @@ private FieldExtraction topHitFieldRef(FieldAttribute fieldAttr) { */ if (fieldAttr.field().isAlias() == false) { while (actualField.parent() != null - && actualField.parent().field().getDataType() != DataType.OBJECT - && actualField.parent().field().getDataType() != DataType.NESTED - && actualField.field().getDataType().isFromDocValuesOnly() == false) { + && actualField.parent().field().getDataType() != DataTypes.OBJECT + && actualField.parent().field().getDataType() != DataTypes.NESTED + && SqlDataTypes.isFromDocValuesOnly(actualField.field().getDataType()) == false) { actualField = actualField.parent(); } } @@ -365,7 +366,9 @@ private FieldExtraction topHitFieldRef(FieldAttribute fieldAttr) { private Tuple nestedHitFieldRef(FieldAttribute attr) { String name = aliasName(attr); Query q = rewriteToContainNestedField(query, attr.source(), - attr.nestedParent().name(), name, attr.field().getDataType().format(), attr.field().getDataType().isFromDocValuesOnly()); + attr.nestedParent().name(), name, + SqlDataTypes.format(attr.field().getDataType()), + SqlDataTypes.isFromDocValuesOnly(attr.field().getDataType())); SearchHitFieldRef nestedFieldRef = new SearchHitFieldRef(name, null, attr.field().getDataType(), attr.field().isAggregatable(), false, attr.parent().name()); diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/container/SearchHitFieldRef.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/container/SearchHitFieldRef.java index 7dec3498a465c..3c28c9129220a 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/container/SearchHitFieldRef.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/container/SearchHitFieldRef.java @@ -7,6 +7,7 @@ import org.elasticsearch.xpack.ql.execution.search.QlSourceBuilder; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.sql.type.SqlDataTypes; public class SearchHitFieldRef extends FieldReference { private final String name; @@ -26,7 +27,8 @@ public SearchHitFieldRef(String name, String fullFieldName, DataType dataType, b this.dataType = dataType; // these field types can only be extracted from docvalue_fields (ie, values already computed by Elasticsearch) // because, for us to be able to extract them from _source, we would need the mapping of those fields (which we don't have) - this.docValue = isAlias ? useDocValueInsteadOfSource : (dataType.isFromDocValuesOnly() ? useDocValueInsteadOfSource : false); + this.docValue = isAlias ? useDocValueInsteadOfSource : + (SqlDataTypes.isFromDocValuesOnly(dataType) ? useDocValueInsteadOfSource : false); this.hitName = hitName; } @@ -58,7 +60,7 @@ public void collectFields(QlSourceBuilder sourceBuilder) { return; } if (docValue) { - sourceBuilder.addDocField(name, dataType.format()); + sourceBuilder.addDocField(name, SqlDataTypes.format(dataType)); } else { sourceBuilder.addSourceField(name); } diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/query/TermsQuery.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/query/TermsQuery.java index 116b69ce7213b..6b12c83b4acb0 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/query/TermsQuery.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/querydsl/query/TermsQuery.java @@ -7,8 +7,9 @@ import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.xpack.ql.expression.Expression; -import org.elasticsearch.xpack.ql.expression.Foldables; import org.elasticsearch.xpack.ql.tree.Source; +import org.elasticsearch.xpack.ql.type.DataTypes; +import org.elasticsearch.xpack.sql.expression.Foldables; import java.util.Collections; import java.util.LinkedHashSet; @@ -26,7 +27,7 @@ public class TermsQuery extends LeafQuery { public TermsQuery(Source source, String term, List values) { super(source); this.term = term; - values.removeIf(e -> e.dataType().isNull()); + values.removeIf(e -> DataTypes.isNull(e.dataType())); if (values.isEmpty()) { this.values = Collections.emptySet(); } else { diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/session/Cursors.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/session/Cursors.java index 1141d665e87bf..a5a3ad82dd178 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/session/Cursors.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/session/Cursors.java @@ -19,7 +19,7 @@ import org.elasticsearch.xpack.sql.execution.search.extractor.SqlBucketExtractors; import org.elasticsearch.xpack.sql.execution.search.extractor.SqlHitExtractors; import org.elasticsearch.xpack.sql.expression.function.scalar.Processors; -import org.elasticsearch.xpack.sql.expression.literal.SqlLiterals; +import org.elasticsearch.xpack.sql.expression.literal.Literals; import org.elasticsearch.xpack.sql.plugin.TextFormatterCursor; import java.io.IOException; @@ -57,7 +57,7 @@ public static List getNamedWriteables() { entries.addAll(SqlBucketExtractors.getNamedWriteables()); // and custom types - entries.addAll(SqlLiterals.getNamedWriteables()); + entries.addAll(Literals.getNamedWriteables()); return entries; } diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/ExtTypes.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/ExtTypes.java similarity index 96% rename from x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/ExtTypes.java rename to x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/ExtTypes.java index 85dec87145666..2c07be3eb620d 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/type/ExtTypes.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/ExtTypes.java @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -package org.elasticsearch.xpack.ql.type; +package org.elasticsearch.xpack.sql.type; import java.sql.JDBCType; import java.sql.SQLType; diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/SqlDataTypeConverter.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/SqlDataTypeConverter.java new file mode 100644 index 0000000000000..e958ce1aa830d --- /dev/null +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/SqlDataTypeConverter.java @@ -0,0 +1,453 @@ +/* + * 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.io.stream.StreamInput; +import org.elasticsearch.common.io.stream.StreamOutput; +import org.elasticsearch.xpack.ql.QlIllegalArgumentException; +import org.elasticsearch.xpack.ql.type.Converter; +import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypeConverter; +import org.elasticsearch.xpack.sql.SqlIllegalArgumentException; +import org.elasticsearch.xpack.sql.expression.literal.interval.Intervals; +import org.elasticsearch.xpack.sql.util.DateUtils; + +import java.io.IOException; +import java.time.OffsetTime; +import java.time.ZonedDateTime; +import java.time.format.DateTimeParseException; +import java.util.function.Function; + +import static org.elasticsearch.xpack.ql.type.DataTypeConverter.DefaultConverter.BOOL_TO_INT; +import static org.elasticsearch.xpack.ql.type.DataTypeConverter.DefaultConverter.DATETIME_TO_BOOLEAN; +import static org.elasticsearch.xpack.ql.type.DataTypeConverter.DefaultConverter.DATETIME_TO_BYTE; +import static org.elasticsearch.xpack.ql.type.DataTypeConverter.DefaultConverter.DATETIME_TO_DOUBLE; +import static org.elasticsearch.xpack.ql.type.DataTypeConverter.DefaultConverter.DATETIME_TO_FLOAT; +import static org.elasticsearch.xpack.ql.type.DataTypeConverter.DefaultConverter.DATETIME_TO_INT; +import static org.elasticsearch.xpack.ql.type.DataTypeConverter.DefaultConverter.DATETIME_TO_LONG; +import static org.elasticsearch.xpack.ql.type.DataTypeConverter.DefaultConverter.DATETIME_TO_SHORT; +import static org.elasticsearch.xpack.ql.type.DataTypeConverter.DefaultConverter.IDENTITY; +import static org.elasticsearch.xpack.ql.type.DataTypeConverter.DefaultConverter.INTEGER_TO_LONG; +import static org.elasticsearch.xpack.ql.type.DataTypeConverter.DefaultConverter.RATIONAL_TO_LONG; +import static org.elasticsearch.xpack.ql.type.DataTypeConverter.DefaultConverter.TO_NULL; +import static org.elasticsearch.xpack.ql.type.DataTypes.BOOLEAN; +import static org.elasticsearch.xpack.ql.type.DataTypes.BYTE; +import static org.elasticsearch.xpack.ql.type.DataTypes.DATETIME; +import static org.elasticsearch.xpack.ql.type.DataTypes.DOUBLE; +import static org.elasticsearch.xpack.ql.type.DataTypes.FLOAT; +import static org.elasticsearch.xpack.ql.type.DataTypes.INTEGER; +import static org.elasticsearch.xpack.ql.type.DataTypes.KEYWORD; +import static org.elasticsearch.xpack.ql.type.DataTypes.LONG; +import static org.elasticsearch.xpack.ql.type.DataTypes.NULL; +import static org.elasticsearch.xpack.ql.type.DataTypes.SHORT; +import static org.elasticsearch.xpack.ql.type.DataTypes.TEXT; +import static org.elasticsearch.xpack.ql.type.DataTypes.isPrimitive; +import static org.elasticsearch.xpack.ql.type.DataTypes.isString; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.DATE; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.TIME; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.isInterval; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.isYearMonthInterval; + + +public final class SqlDataTypeConverter { + + private SqlDataTypeConverter() {} + + public static DataType commonType(DataType left, DataType right) { + DataType common = DataTypeConverter.commonType(left, right); + + if (common != null) { + return common; + } + + // interval and dates + if (left == DATE) { + if (isYearMonthInterval(right)) { + return left; + } + // promote + return DATETIME; + } + if (right == DATE) { + if (isYearMonthInterval(left)) { + return right; + } + // promote + return DATETIME; + } + if (left == TIME) { + if (right == DATE) { + return DATETIME; + } + if (isInterval(right)) { + return left; + } + } + if (right == TIME) { + if (left == DATE) { + return DATETIME; + } + if (isInterval(left)) { + return right; + } + } + if (left == DATETIME) { + if (right == DATE || right == TIME) { + return left; + } + if (isInterval(right)) { + return left; + } + } + if (right == DATETIME) { + if (left == DATE || left == TIME) { + return right; + } + if (isInterval(left)) { + return right; + } + } + // Interval * integer is a valid operation + if (isInterval(left)) { + if (right.isInteger()) { + return left; + } + } + if (isInterval(right)) { + if (left.isInteger()) { + return right; + } + } + if (isInterval(left)) { + // intervals widening + if (isInterval(right)) { + // null returned for incompatible intervals + return Intervals.compatibleInterval(left, right); + } + } + + return null; + } + + public static boolean canConvert(DataType from, DataType to) { + // Special handling for nulls and if conversion is not requires + if (from == to || from == NULL) { + return true; + } + // only primitives are supported so far + return isPrimitive(from) && isPrimitive(to) && converterFor(from, to) != null; + } + + public static Converter converterFor(DataType from, DataType to) { + // Special handling for nulls and if conversion is not requires + if (from == to) { + return IDENTITY; + } + if (to == NULL || from == NULL) { + return TO_NULL; + } + // proper converters + if (to == DATE) { + return conversionToDate(from); + } + if (to == TIME) { + return conversionToTime(from); + } + // extend the default converter with DATE and TIME + if (from == DATE || from == TIME) { + if (to == KEYWORD || to == TEXT) { + return conversionToString(from); + } + if (to == LONG) { + return conversionToLong(from); + } + if (to == INTEGER) { + return conversionToInt(from); + } + if (to == SHORT) { + return conversionToShort(from); + } + if (to == BYTE) { + return conversionToByte(from); + } + if (to == FLOAT) { + return conversionToFloat(from); + } + if (to == DOUBLE) { + return conversionToDouble(from); + } + if (to == DATETIME) { + return conversionToDateTime(from); + } + if (to == BOOLEAN) { + return conversionToBoolean(from); + } + } + // fallback to default + return DataTypeConverter.converterFor(from, to); + } + + private static Converter conversionToString(DataType from) { + if (from == DATE) { + return SqlConverter.DATE_TO_STRING; + } + if (from == TIME) { + return SqlConverter.TIME_TO_STRING; + } + return null; + } + + private static Converter conversionToLong(DataType from) { + if (from == DATE) { + return SqlConverter.DATE_TO_LONG; + } + if (from == TIME) { + return SqlConverter.TIME_TO_LONG; + } + return null; + } + + private static Converter conversionToInt(DataType from) { + if (from == DATE) { + return SqlConverter.DATE_TO_INT; + } + if (from == TIME) { + return SqlConverter.TIME_TO_INT; + } + return null; + } + + private static Converter conversionToShort(DataType from) { + if (from == DATE) { + return SqlConverter.DATE_TO_SHORT; + } + if (from == TIME) { + return SqlConverter.TIME_TO_SHORT; + } + return null; + } + + private static Converter conversionToByte(DataType from) { + if (from == DATE) { + return SqlConverter.DATE_TO_BYTE; + } + if (from == TIME) { + return SqlConverter.TIME_TO_BYTE; + } + return null; + } + + private static Converter conversionToFloat(DataType from) { + if (from == DATE) { + return SqlConverter.DATE_TO_FLOAT; + } + if (from == TIME) { + return SqlConverter.TIME_TO_FLOAT; + } + return null; + } + + private static Converter conversionToDouble(DataType from) { + if (from == DATE) { + return SqlConverter.DATE_TO_DOUBLE; + } + if (from == TIME) { + return SqlConverter.TIME_TO_DOUBLE; + } + return null; + } + + private static Converter conversionToDateTime(DataType from) { + if (from == DATE) { + return SqlConverter.DATE_TO_DATETIME; + } + + return DataTypeConverter.converterFor(from, DATETIME); + } + + private static Converter conversionToBoolean(DataType from) { + if (from == DATE) { + return SqlConverter.DATE_TO_BOOLEAN; + } + if (from == TIME) { + return SqlConverter.TIME_TO_BOOLEAN; + } + return null; + } + + private static Converter conversionToDate(DataType from) { + if (from.isRational()) { + return SqlConverter.RATIONAL_TO_DATE; + } + if (from.isInteger()) { + return SqlConverter.INTEGER_TO_DATE; + } + if (from == BOOLEAN) { + return SqlConverter.BOOL_TO_DATE; // We emit an int here which is ok because of Java's casting rules + } + if (isString(from)) { + return SqlConverter.STRING_TO_DATE; + } + if (from == DATETIME) { + return SqlConverter.DATETIME_TO_DATE; + } + return null; + } + + private static Converter conversionToTime(DataType from) { + if (from.isRational()) { + return SqlConverter.RATIONAL_TO_TIME; + } + if (from.isInteger()) { + return SqlConverter.INTEGER_TO_TIME; + } + if (from == BOOLEAN) { + return SqlConverter.BOOL_TO_TIME; // We emit an int here which is ok because of Java's casting rules + } + if (isString(from)) { + return SqlConverter.STRING_TO_TIME; + } + if (from == DATE) { + return SqlConverter.DATE_TO_TIME; + } + if (from == DATETIME) { + return SqlConverter.DATETIME_TO_TIME; + } + return null; + } + + public static Object convert(Object value, DataType dataType) { + DataType detectedType = SqlDataTypes.fromJava(value); + + if (detectedType == null) { + throw new SqlIllegalArgumentException("cannot detect datatype for [{}]", value); + } + + if (detectedType == dataType || value == null) { + return value; + } + + Converter converter = converterFor(detectedType, dataType); + + if (converter == null) { + throw new SqlIllegalArgumentException("cannot convert from [{}] to [{}]", value, dataType.typeName()); + } + + return converter.convert(value); + } + + /** + * Reference to a data type conversion that can be serialized. Note that the position in the enum + * is important because it is used for serialization. + */ + public enum SqlConverter implements Converter { + DATE_TO_STRING(o -> DateUtils.toDateString((ZonedDateTime) o)), + TIME_TO_STRING(o -> DateUtils.toTimeString((OffsetTime) o)), + + DATE_TO_LONG(delegate(DATETIME_TO_LONG)), + TIME_TO_LONG(fromTime(value -> value)), + + DATE_TO_INT(delegate(DATETIME_TO_INT)), + TIME_TO_INT(fromTime(DataTypeConverter::safeToInt)), + + DATE_TO_SHORT(delegate(DATETIME_TO_SHORT)), + TIME_TO_SHORT(fromTime(DataTypeConverter::safeToShort)), + + DATE_TO_BYTE(delegate(DATETIME_TO_BYTE)), + TIME_TO_BYTE(fromTime(DataTypeConverter::safeToByte)), + + DATE_TO_FLOAT(delegate(DATETIME_TO_FLOAT)), + TIME_TO_FLOAT(fromTime(value -> (float) value)), + + DATE_TO_DOUBLE(delegate(DATETIME_TO_DOUBLE)), + TIME_TO_DOUBLE(fromTime(Double::valueOf)), + + RATIONAL_TO_DATE(toDate(RATIONAL_TO_LONG)), + INTEGER_TO_DATE(toDate(INTEGER_TO_LONG)), + BOOL_TO_DATE(toDate(BOOL_TO_INT)), + STRING_TO_DATE(fromString(DateUtils::asDateOnly, "date")), + DATETIME_TO_DATE(fromDatetimeToDate()), + + RATIONAL_TO_TIME(toTime(RATIONAL_TO_LONG)), + INTEGER_TO_TIME(toTime(INTEGER_TO_LONG)), + BOOL_TO_TIME(toTime(BOOL_TO_INT)), + STRING_TO_TIME(fromString(DateUtils::asTimeOnly, "time")), + DATE_TO_TIME(fromDatetimeToTime()), + DATETIME_TO_TIME(fromDatetimeToTime()), + + DATE_TO_DATETIME(value -> value), + + DATE_TO_BOOLEAN(delegate(DATETIME_TO_BOOLEAN)), + TIME_TO_BOOLEAN(fromTime(value -> value != 0)); + + public static final String NAME = "dtc-sql"; + + private final Function converter; + + SqlConverter(Function converter) { + this.converter = converter; + } + + private static Function fromTime(Function converter) { + return l -> converter.apply(((OffsetTime) l).atDate(DateUtils.EPOCH).toInstant().toEpochMilli()); + } + + private static Function toDate(Converter conversion) { + return l -> DateUtils.asDateOnly(((Number) conversion.convert(l)).longValue()); + } + + private static Function toTime(Converter conversion) { + return l -> DateUtils.asTimeOnly(((Number) conversion.convert(l)).longValue()); + } + + private static Function fromDatetimeToDate() { + return l -> DateUtils.asDateOnly((ZonedDateTime) l); + } + + private static Function fromDatetimeToTime() { + return l -> ((ZonedDateTime) l).toOffsetDateTime().toOffsetTime(); + } + + private static Function delegate(Converter converter) { + return converter::convert; + } + + private static Function fromString(Function converter, String to) { + return (Object value) -> { + try { + return converter.apply(value.toString()); + } catch (NumberFormatException e) { + throw new QlIllegalArgumentException(e, "cannot cast [{}] to [{}]", value, to); + } catch (DateTimeParseException | IllegalArgumentException e) { + throw new QlIllegalArgumentException(e, "cannot cast [{}] to [{}]: {}", value, to, e.getMessage()); + } + }; + } + + @Override + public Object convert(Object l) { + if (l == null) { + return null; + } + return converter.apply(l); + } + + @Override + public String getWriteableName() { + return NAME; + } + + @Override + public void writeTo(StreamOutput out) throws IOException { + out.writeEnum(this); + } + + public static Converter read(StreamInput in) throws IOException { + return in.readEnum(SqlConverter.class); + } + } +} \ No newline at end of file diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/SqlDataTypeRegistry.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/SqlDataTypeRegistry.java new file mode 100644 index 0000000000000..12554a547bb9b --- /dev/null +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/SqlDataTypeRegistry.java @@ -0,0 +1,56 @@ +/* + * 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.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypeRegistry; +import org.elasticsearch.xpack.ql.type.DataTypes; + +import java.util.Collection; + +public class SqlDataTypeRegistry implements DataTypeRegistry { + + public static final DataTypeRegistry INSTANCE = new SqlDataTypeRegistry(); + + private SqlDataTypeRegistry() {} + + @Override + public Collection dataTypes() { + return SqlDataTypes.types(); + } + + @Override + public DataType fromEs(String typeName) { + return SqlDataTypes.fromEs(typeName); + } + + @Override + public DataType fromJava(Object value) { + return SqlDataTypes.fromJava(value); + } + + @Override + public boolean isUnsupported(DataType type) { + return DataTypes.isUnsupported(type); + } + + @Override + public boolean canConvert(DataType from, DataType to) { + return SqlDataTypeConverter.canConvert(from, to); + } + + @Override + public Object convert(Object value, DataType type) { + return SqlDataTypeConverter.convert(value, type); + } + + @Override + public DataType commonType(DataType left, DataType right) { + return SqlDataTypeConverter.commonType(left, right); + } + +} diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/SqlDataTypes.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/SqlDataTypes.java new file mode 100644 index 0000000000000..f75f823092737 --- /dev/null +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/type/SqlDataTypes.java @@ -0,0 +1,726 @@ +/* + * 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.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; +import org.elasticsearch.xpack.sql.expression.literal.geo.GeoShape; +import org.elasticsearch.xpack.sql.expression.literal.interval.Interval; +import org.elasticsearch.xpack.sql.expression.literal.interval.Intervals; + +import java.sql.JDBCType; +import java.sql.SQLType; +import java.time.OffsetTime; +import java.util.Arrays; +import java.util.Collection; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; +import java.util.Map.Entry; +import java.util.stream.Stream; + +import static java.util.Collections.unmodifiableMap; +import static java.util.stream.Collectors.toUnmodifiableList; +import static java.util.stream.Collectors.toUnmodifiableMap; +import static org.elasticsearch.xpack.ql.type.DataTypes.BINARY; +import static org.elasticsearch.xpack.ql.type.DataTypes.BOOLEAN; +import static org.elasticsearch.xpack.ql.type.DataTypes.BYTE; +import static org.elasticsearch.xpack.ql.type.DataTypes.DATETIME; +import static org.elasticsearch.xpack.ql.type.DataTypes.DOUBLE; +import static org.elasticsearch.xpack.ql.type.DataTypes.FLOAT; +import static org.elasticsearch.xpack.ql.type.DataTypes.HALF_FLOAT; +import static org.elasticsearch.xpack.ql.type.DataTypes.INTEGER; +import static org.elasticsearch.xpack.ql.type.DataTypes.IP; +import static org.elasticsearch.xpack.ql.type.DataTypes.KEYWORD; +import static org.elasticsearch.xpack.ql.type.DataTypes.LONG; +import static org.elasticsearch.xpack.ql.type.DataTypes.NESTED; +import static org.elasticsearch.xpack.ql.type.DataTypes.NULL; +import static org.elasticsearch.xpack.ql.type.DataTypes.OBJECT; +import static org.elasticsearch.xpack.ql.type.DataTypes.SCALED_FLOAT; +import static org.elasticsearch.xpack.ql.type.DataTypes.SHORT; +import static org.elasticsearch.xpack.ql.type.DataTypes.TEXT; +import static org.elasticsearch.xpack.ql.type.DataTypes.UNSUPPORTED; +import static org.elasticsearch.xpack.ql.util.CollectionUtils.mapSize; + +public class SqlDataTypes { + + // @formatter:off + // date-only, time-only + public static final DataType DATE = new DataType("DATE", null, Long.BYTES, false, false, true); + public static final DataType TIME = new DataType("TIME", null, Long.BYTES, false, false, true); + // interval + public static final DataType INTERVAL_YEAR = + new DataType("INTERVAL_YEAR", null, Integer.BYTES, false, false, false); + public static final DataType INTERVAL_MONTH = + new DataType("INTERVAL_MONTH", null, Integer.BYTES, false, false, false); + public static final DataType INTERVAL_DAY = + new DataType("INTERVAL_DAY", null, Long.BYTES, false, false, false); + public static final DataType INTERVAL_HOUR = + new DataType("INTERVAL_HOUR", null, Long.BYTES, false, false, false); + public static final DataType INTERVAL_MINUTE = + new DataType("INTERVAL_MINUTE", null, Long.BYTES, false, false, false); + public static final DataType INTERVAL_SECOND = + new DataType("INTERVAL_SECOND", null, Long.BYTES, false, false, false); + public static final DataType INTERVAL_YEAR_TO_MONTH = + new DataType("INTERVAL_YEAR_TO_MONTH", null, Integer.BYTES, false, false, false); + public static final DataType INTERVAL_DAY_TO_HOUR = + new DataType("INTERVAL_DAY_TO_HOUR", null, Long.BYTES, false, false, false); + public static final DataType INTERVAL_DAY_TO_MINUTE = + new DataType("INTERVAL_DAY_TO_MINUTE", null, Long.BYTES, false, false, false); + public static final DataType INTERVAL_DAY_TO_SECOND = + new DataType("INTERVAL_DAY_TO_SECOND", null, Long.BYTES, false, false, false); + public static final DataType INTERVAL_HOUR_TO_MINUTE = + new DataType("INTERVAL_HOUR_TO_MINUTE", null, Long.BYTES, false, false, false); + public static final DataType INTERVAL_HOUR_TO_SECOND = + new DataType("INTERVAL_HOUR_TO_SECOND", null, Long.BYTES, false, false, false); + public static final DataType INTERVAL_MINUTE_TO_SECOND = + new DataType("INTERVAL_MINUTE_TO_SECOND", null, Long.BYTES, false, false, false); + // geo + public static final DataType GEO_SHAPE = new DataType("geo_shape", Integer.MAX_VALUE, false, false, false); + public static final DataType GEO_POINT = new DataType("geo_point", Double.BYTES * 2, false, false, false); + public static final DataType SHAPE = new DataType("shape", Integer.MAX_VALUE, false, false, false); + // @formatter:on + + private static final Map ODBC_TO_ES = new HashMap<>(mapSize(38)); + + static { + // Numeric + ODBC_TO_ES.put("SQL_BIT", BOOLEAN); + ODBC_TO_ES.put("SQL_TINYINT", BYTE); + ODBC_TO_ES.put("SQL_SMALLINT", SHORT); + ODBC_TO_ES.put("SQL_INTEGER", INTEGER); + ODBC_TO_ES.put("SQL_BIGINT", LONG); + ODBC_TO_ES.put("SQL_REAL", FLOAT); + ODBC_TO_ES.put("SQL_FLOAT", DOUBLE); + ODBC_TO_ES.put("SQL_DOUBLE", DOUBLE); + ODBC_TO_ES.put("SQL_DECIMAL", DOUBLE); + ODBC_TO_ES.put("SQL_NUMERIC", DOUBLE); + + // String + ODBC_TO_ES.put("SQL_GUID", KEYWORD); + ODBC_TO_ES.put("SQL_CHAR", KEYWORD); + ODBC_TO_ES.put("SQL_WCHAR", KEYWORD); + ODBC_TO_ES.put("SQL_VARCHAR", TEXT); + ODBC_TO_ES.put("SQL_WVARCHAR", TEXT); + ODBC_TO_ES.put("SQL_LONGVARCHAR", TEXT); + ODBC_TO_ES.put("SQL_WLONGVARCHAR", TEXT); + + // Binary + ODBC_TO_ES.put("SQL_BINARY", BINARY); + ODBC_TO_ES.put("SQL_VARBINARY", BINARY); + ODBC_TO_ES.put("SQL_LONGVARBINARY", BINARY); + + // Date + ODBC_TO_ES.put("SQL_DATE", DATE); + ODBC_TO_ES.put("SQL_TIME", TIME); + ODBC_TO_ES.put("SQL_TIMESTAMP", DATETIME); + + // Intervals + ODBC_TO_ES.put("SQL_INTERVAL_YEAR", INTERVAL_YEAR); + ODBC_TO_ES.put("SQL_INTERVAL_MONTH", INTERVAL_MONTH); + ODBC_TO_ES.put("SQL_INTERVAL_DAY", INTERVAL_DAY); + ODBC_TO_ES.put("SQL_INTERVAL_HOUR", INTERVAL_HOUR); + ODBC_TO_ES.put("SQL_INTERVAL_MINUTE", INTERVAL_MINUTE); + ODBC_TO_ES.put("SQL_INTERVAL_SECOND", INTERVAL_SECOND); + ODBC_TO_ES.put("SQL_INTERVAL_YEAR_TO_MONTH", INTERVAL_YEAR_TO_MONTH); + ODBC_TO_ES.put("SQL_INTERVAL_DAY_TO_HOUR", INTERVAL_DAY_TO_HOUR); + ODBC_TO_ES.put("SQL_INTERVAL_DAY_TO_MINUTE", INTERVAL_DAY_TO_MINUTE); + ODBC_TO_ES.put("SQL_INTERVAL_DAY_TO_SECOND", INTERVAL_DAY_TO_SECOND); + ODBC_TO_ES.put("SQL_INTERVAL_HOUR_TO_MINUTE", INTERVAL_HOUR_TO_MINUTE); + ODBC_TO_ES.put("SQL_INTERVAL_HOUR_TO_SECOND", INTERVAL_HOUR_TO_SECOND); + ODBC_TO_ES.put("SQL_INTERVAL_MINUTE_TO_SECOND", INTERVAL_MINUTE_TO_SECOND); + } + + private static final Collection TYPES = Stream.concat(DataTypes.types().stream(), Arrays.asList( + DATE, + TIME, + INTERVAL_YEAR, + INTERVAL_MONTH, + INTERVAL_DAY, + INTERVAL_HOUR, + INTERVAL_MINUTE, + INTERVAL_SECOND, + INTERVAL_YEAR_TO_MONTH, + INTERVAL_DAY_TO_HOUR, + INTERVAL_DAY_TO_MINUTE, + INTERVAL_DAY_TO_SECOND, + INTERVAL_HOUR_TO_MINUTE, + INTERVAL_HOUR_TO_SECOND, + INTERVAL_MINUTE_TO_SECOND, + GEO_SHAPE, + GEO_POINT, + SHAPE) + .stream()) + .sorted(Comparator.comparing(DataType::typeName)) + .collect(toUnmodifiableList()); + + private static final Map NAME_TO_TYPE = TYPES.stream() + .collect(toUnmodifiableMap(DataType::typeName, t -> t)); + + private static final Map ES_TO_TYPE = TYPES.stream() + .filter(e -> e.esType() != null) + .collect(toUnmodifiableMap(DataType::esType, t -> t)); + + private static final Map SQL_TO_ES; + + static { + Map sqlToEs = new HashMap<>(mapSize(45)); + // first add ES types + for (DataType type : SqlDataTypes.types()) { + if (type != OBJECT && type != NESTED) { + sqlToEs.put(type.typeName().toUpperCase(Locale.ROOT), type); + } + } + + // reuse the ODBC definition (without SQL_) + // note that this will override existing types in particular FLOAT + for (Entry entry : ODBC_TO_ES.entrySet()) { + sqlToEs.put(entry.getKey().substring(4), entry.getValue()); + } + + // special ones + sqlToEs.put("BOOL", BOOLEAN); + sqlToEs.put("INT", INTEGER); + sqlToEs.put("STRING", KEYWORD); + + SQL_TO_ES = unmodifiableMap(sqlToEs); + } + + private SqlDataTypes() {} + + public static Collection types() { + return TYPES; + } + + public static DataType fromTypeName(String name) { + return NAME_TO_TYPE.get(name.toLowerCase(Locale.ROOT)); + } + + public static DataType fromEs(String name) { + DataType type = ES_TO_TYPE.get(name); + return type != null ? type : UNSUPPORTED; + } + + public static DataType fromJava(Object value) { + DataType type = DataTypes.fromJava(value); + + if (type != null) { + return type; + } + if (value instanceof OffsetTime) { + return TIME; + } + if (value instanceof Interval) { + return ((Interval) value).dataType(); + } + if (value instanceof GeoShape) { + return GEO_SHAPE; + } + + return null; + } + + public static boolean isNullOrInterval(DataType type) { + return type == NULL || isInterval(type); + } + + public static boolean isInterval(DataType dataType) { + return isYearMonthInterval(dataType) || isDayTimeInterval(dataType); + } + + public static boolean isYearMonthInterval(DataType dataType) { + return dataType == INTERVAL_YEAR || dataType == INTERVAL_MONTH || dataType == INTERVAL_YEAR_TO_MONTH; + } + + public static boolean isDayTimeInterval(DataType dataType) { + return dataType == INTERVAL_DAY || dataType == INTERVAL_HOUR || dataType == INTERVAL_MINUTE || dataType == INTERVAL_SECOND + || dataType == INTERVAL_DAY_TO_HOUR || dataType == INTERVAL_DAY_TO_MINUTE || dataType == INTERVAL_DAY_TO_SECOND + || dataType == INTERVAL_HOUR_TO_MINUTE || dataType == INTERVAL_HOUR_TO_SECOND + || dataType == INTERVAL_MINUTE_TO_SECOND; + } + + public static boolean isDateBased(DataType type) { + return type == DATE || type == DATETIME; + } + + public static boolean isTimeBased(DataType type) { + return type == TIME; + } + + public static boolean isDateOrTimeBased(DataType type) { + return isDateBased(type) || isTimeBased(type); + } + + public static boolean isGeo(DataType type) { + return type == GEO_POINT || type == GEO_SHAPE || type == SHAPE; + } + + public static String format(DataType type) { + return isDateOrTimeBased(type) ? "epoch_millis" : null; + } + + + public static boolean isFromDocValuesOnly(DataType dataType) { + return dataType == KEYWORD // because of ignore_above. Extracting this from _source wouldn't make sense + || dataType == DATE // because of date formats + || dataType == DATETIME + || dataType == SCALED_FLOAT // because of scaling_factor + || dataType == GEO_POINT + || dataType == GEO_SHAPE + || dataType == SHAPE; + } + + public static boolean areCompatible(DataType left, DataType right) { + if (left == right) { + return true; + } else { + return (left == NULL || right == NULL) + || (DataTypes.isString(left) && DataTypes.isString(right)) + || (left.isNumeric() && right.isNumeric()) + || (isDateBased(left) && isDateBased(right)) + || (isInterval(left) && isInterval(right) && Intervals.compatibleInterval(left, right) != null); + } + } + + public static DataType fromOdbcType(String odbcType) { + return ODBC_TO_ES.get(odbcType); + } + + public static DataType fromSqlOrEsType(String typeName) { + return SQL_TO_ES.get(typeName.toUpperCase(Locale.ROOT)); + } + + public static SQLType sqlType(DataType dataType) { + if (dataType == UNSUPPORTED) { + return JDBCType.OTHER; + } + if (dataType == NULL) { + return JDBCType.NULL; + } + if (dataType == BOOLEAN) { + return JDBCType.BOOLEAN; + } + if (dataType == BYTE) { + return JDBCType.TINYINT; + } + if (dataType == SHORT) { + return JDBCType.SMALLINT; + } + if (dataType == INTEGER) { + return JDBCType.INTEGER; + } + if (dataType == LONG) { + return JDBCType.BIGINT; + } + if (dataType == DOUBLE) { + return JDBCType.DOUBLE; + } + if (dataType == FLOAT) { + return JDBCType.REAL; + } + if (dataType == HALF_FLOAT) { + return JDBCType.FLOAT; + } + if (dataType == SCALED_FLOAT) { + return JDBCType.DOUBLE; + } + if (dataType == KEYWORD) { + return JDBCType.VARCHAR; + } + if (dataType == TEXT) { + return JDBCType.VARCHAR; + } + if (dataType == DATETIME) { + return JDBCType.TIMESTAMP; + } + if (dataType == IP) { + return JDBCType.VARCHAR; + } + if (dataType == BINARY) { + return JDBCType.BINARY; + } + if (dataType == OBJECT) { + return JDBCType.STRUCT; + } + if (dataType == NESTED) { + return JDBCType.STRUCT; + } + // + // SQL specific + // + if (dataType == DATE) { + return JDBCType.DATE; + } + if (dataType == TIME) { + return JDBCType.TIME; + } + if (dataType == GEO_SHAPE) { + return ExtTypes.GEOMETRY; + } + if (dataType == GEO_POINT) { + return ExtTypes.GEOMETRY; + } + if (dataType == SHAPE) { + return ExtTypes.GEOMETRY; + } + if (dataType == INTERVAL_YEAR) { + return ExtTypes.INTERVAL_YEAR; + } + if (dataType == INTERVAL_MONTH) { + return ExtTypes.INTERVAL_MONTH; + } + if (dataType == INTERVAL_DAY) { + return ExtTypes.INTERVAL_DAY; + } + if (dataType == INTERVAL_HOUR) { + return ExtTypes.INTERVAL_HOUR; + } + if (dataType == INTERVAL_MINUTE) { + return ExtTypes.INTERVAL_MINUTE; + } + if (dataType == INTERVAL_SECOND) { + return ExtTypes.INTERVAL_SECOND; + } + if (dataType == INTERVAL_YEAR_TO_MONTH) { + return ExtTypes.INTERVAL_YEAR_TO_MONTH; + } + if (dataType == INTERVAL_DAY_TO_HOUR) { + return ExtTypes.INTERVAL_DAY_TO_HOUR; + } + if (dataType == INTERVAL_DAY_TO_MINUTE) { + return ExtTypes.INTERVAL_DAY_TO_MINUTE; + } + if (dataType == INTERVAL_DAY_TO_SECOND) { + return ExtTypes.INTERVAL_DAY_TO_SECOND; + } + if (dataType == INTERVAL_HOUR_TO_MINUTE) { + return ExtTypes.INTERVAL_HOUR_TO_MINUTE; + } + if (dataType == INTERVAL_HOUR_TO_SECOND) { + return ExtTypes.INTERVAL_HOUR_TO_SECOND; + } + if (dataType == INTERVAL_MINUTE_TO_SECOND) { + return ExtTypes.INTERVAL_MINUTE_TO_SECOND; + } + + return null; + } + + /** + * 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 static int defaultPrecision(DataType dataType) { + if (dataType == UNSUPPORTED) { + return 0; + } + if (dataType == NULL) { + return 0; + } + if (dataType == BOOLEAN) { + return 1; + } + if (dataType == BYTE) { + return 3; + } + if (dataType == SHORT) { + return 5; + } + if (dataType == INTEGER) { + return 10; + } + if (dataType == LONG) { + return 19; + } + if (dataType == DOUBLE) { + return 15; + } + if (dataType == FLOAT) { + return 7; + } + if (dataType == HALF_FLOAT) { + return 3; + } + if (dataType == SCALED_FLOAT) { + return 15; + } + if (dataType == KEYWORD) { + return 15; + } + if (dataType == TEXT) { + return 32766; + } + if (dataType == DATETIME) { + return 3; + } + if (dataType == IP) { + return 39; + } + if (dataType == BINARY) { + return Integer.MAX_VALUE; + } + if (dataType == OBJECT) { + return 0; + } + if (dataType == NESTED) { + return 0; + } + // + // SQL specific + // + // since ODBC and JDBC interpret precision for Date as display size + // the precision is 23 (number of chars in ISO8601 with millis) + 6 chars for the timezone (e.g.: +05:00) + // see https://github.com/elastic/elasticsearch/issues/30386#issuecomment-386807288 + if (dataType == DATE) { + return 3; + } + if (dataType == TIME) { + return 3; + } + + if (dataType == GEO_SHAPE) { + return Integer.MAX_VALUE; + } + if (dataType == GEO_POINT) { + return Integer.MAX_VALUE; + } + if (dataType == SHAPE) { + return Integer.MAX_VALUE; + } + if (dataType == INTERVAL_YEAR) { + return 7; + } + if (dataType == INTERVAL_MONTH) { + return 7; + } + if (dataType == INTERVAL_DAY) { + return 23; + } + if (dataType == INTERVAL_HOUR) { + return 23; + } + if (dataType == INTERVAL_MINUTE) { + return 23; + } + if (dataType == INTERVAL_SECOND) { + return 23; + } + if (dataType == INTERVAL_YEAR_TO_MONTH) { + return 7; + } + if (dataType == INTERVAL_DAY_TO_HOUR) { + return 23; + } + if (dataType == INTERVAL_DAY_TO_MINUTE) { + return 23; + } + if (dataType == INTERVAL_DAY_TO_SECOND) { + return 23; + } + if (dataType == INTERVAL_HOUR_TO_MINUTE) { + return 23; + } + if (dataType == INTERVAL_HOUR_TO_SECOND) { + return 23; + } + if (dataType == INTERVAL_MINUTE_TO_SECOND) { + return 23; + } + + return 0; + } + + public static int displaySize(DataType dataType) { + if (dataType == UNSUPPORTED) { + return 0; + } + if (dataType == NULL) { + return 0; + } + if (dataType == BOOLEAN) { + return 1; + } + if (dataType == BYTE) { + return 5; + } + if (dataType == SHORT) { + return 6; + } + if (dataType == INTEGER) { + return 11; + } + if (dataType == LONG) { + return 20; + } + if (dataType == DOUBLE) { + return 25; + } + if (dataType == FLOAT) { + return 15; + } + if (dataType == HALF_FLOAT) { + return 25; + } + if (dataType == SCALED_FLOAT) { + return 25; + } + if (dataType == KEYWORD) { + return 32766; + } + if (dataType == TEXT) { + return Integer.MAX_VALUE; + } + if (dataType == DATETIME) { + return 29; + } + if (dataType == IP) { + return 0; + } + if (dataType == BINARY) { + return Integer.MAX_VALUE; + } + if (dataType == OBJECT) { + return 0; + } + if (dataType == NESTED) { + return 0; + } + // + // SQL specific + // + if (dataType == DATE) { + return 29; + } + if (dataType == TIME) { + return 18; + } + if (dataType == GEO_SHAPE) { + return Integer.MAX_VALUE; + } + if (dataType == GEO_POINT) { + //2 doubles + len("POINT( )") + return 25 * 2 + 8; + } + if (dataType == SHAPE) { + return Integer.MAX_VALUE; + } + if (dataType == INTERVAL_YEAR) { + return 7; + } + if (dataType == INTERVAL_MONTH) { + return 7; + } + if (dataType == INTERVAL_DAY) { + return 23; + } + if (dataType == INTERVAL_HOUR) { + return 23; + } + if (dataType == INTERVAL_MINUTE) { + return 23; + } + if (dataType == INTERVAL_SECOND) { + return 23; + } + if (dataType == INTERVAL_YEAR_TO_MONTH) { + return 7; + } + if (dataType == INTERVAL_DAY_TO_HOUR) { + return 23; + } + if (dataType == INTERVAL_DAY_TO_MINUTE) { + return 23; + } + if (dataType == INTERVAL_DAY_TO_SECOND) { + return 23; + } + if (dataType == INTERVAL_HOUR_TO_MINUTE) { + return 23; + } + if (dataType == INTERVAL_HOUR_TO_SECOND) { + return 23; + } + if (dataType == INTERVAL_MINUTE_TO_SECOND) { + return 23; + } + + return 0; + } + + // + // Metadata methods, mainly for ODBC. + // As these are fairly obscure and limited in use, there is no point to promote them as a full type methods + // hence why they appear here as utility methods. + // + + // https://docs.microsoft.com/en-us/sql/relational-databases/native-client-odbc-date-time/metadata-catalog + // https://github.com/elastic/elasticsearch/issues/30386 + public static Integer metaSqlDataType(DataType t) { + if (t == DATETIME) { + // ODBC SQL_DATETME + return Integer.valueOf(9); + } + // this is safe since the vendor SQL types are short despite the return value + return sqlType(t).getVendorTypeNumber(); + } + + // https://github.com/elastic/elasticsearch/issues/30386 + // https://docs.microsoft.com/en-us/sql/odbc/reference/syntax/sqlgettypeinfo-function + public static Integer metaSqlDateTimeSub(DataType t) { + if (t == DATETIME) { + // ODBC SQL_CODE_TIMESTAMP + return Integer.valueOf(3); + } + // ODBC null + return 0; + } + + public static Short metaSqlMinimumScale(DataType t) { + return metaSqlSameScale(t); + } + + public static Short metaSqlMaximumScale(DataType t) { + return metaSqlSameScale(t); + } + + // https://docs.microsoft.com/en-us/sql/odbc/reference/appendixes/decimal-digits + // https://github.com/elastic/elasticsearch/issues/40357 + // since the scale is fixed, minimum and maximum should return the same value + // hence why this method exists + private static Short metaSqlSameScale(DataType t) { + // TODO: return info for SCALED_FLOATS (should be based on field not type) + if (t.isInteger()) { + return Short.valueOf((short) 0); + } + if (isDateBased(t) || t.isRational()) { + return Short.valueOf((short) defaultPrecision(t)); + } + return null; + } + + // https://docs.microsoft.com/en-us/sql/odbc/reference/syntax/sqlgettypeinfo-function + public static Integer metaSqlRadix(DataType t) { + // RADIX - Determines how numbers returned by COLUMN_SIZE and DECIMAL_DIGITS should be interpreted. + // 10 means they represent the number of decimal digits allowed for the column. + // 2 means they represent the number of bits allowed for the column. + // null means radix is not applicable for the given type. + return t.isInteger() ? Integer.valueOf(10) : (t.isRational() ? Integer.valueOf(2) : null); + } + + //https://docs.microsoft.com/en-us/sql/odbc/reference/syntax/sqlgettypeinfo-function#comments + //https://docs.microsoft.com/en-us/sql/odbc/reference/appendixes/column-size + public static Integer precision(DataType t) { + if (t.isNumeric()) { + return defaultPrecision(t); + } + return displaySize(t); + } +} \ No newline at end of file diff --git a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/util/DateUtils.java b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/util/DateUtils.java index 9485c854d8671..448b6bc537602 100644 --- a/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/util/DateUtils.java +++ b/x-pack/plugin/sql/src/main/java/org/elasticsearch/xpack/sql/util/DateUtils.java @@ -9,7 +9,7 @@ import org.elasticsearch.common.time.DateFormatter; import org.elasticsearch.common.time.DateFormatters; import org.elasticsearch.xpack.ql.expression.Expression; -import org.elasticsearch.xpack.ql.expression.Foldables; +import org.elasticsearch.xpack.sql.expression.Foldables; import org.elasticsearch.xpack.sql.parser.ParsingException; import org.elasticsearch.xpack.sql.proto.StringUtils; diff --git a/x-pack/plugin/sql/src/main/resources/org/elasticsearch/xpack/sql/plugin/sql_whitelist.txt b/x-pack/plugin/sql/src/main/resources/org/elasticsearch/xpack/sql/plugin/sql_whitelist.txt index b38620c033c96..ea522a0e44084 100644 --- a/x-pack/plugin/sql/src/main/resources/org/elasticsearch/xpack/sql/plugin/sql_whitelist.txt +++ b/x-pack/plugin/sql/src/main/resources/org/elasticsearch/xpack/sql/plugin/sql_whitelist.txt @@ -8,13 +8,13 @@ #### Classes -class org.elasticsearch.xpack.ql.expression.function.scalar.geo.GeoShape { +class org.elasticsearch.xpack.sql.expression.literal.geo.GeoShape { } -class org.elasticsearch.xpack.ql.expression.literal.IntervalDayTime { +class org.elasticsearch.xpack.sql.expression.literal.interval.IntervalDayTime { } -class org.elasticsearch.xpack.ql.expression.literal.IntervalYearMonth { +class org.elasticsearch.xpack.sql.expression.literal.interval.IntervalYearMonth { } class java.time.OffsetTime { diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/TestUtils.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/SqlTestUtils.java similarity index 82% rename from x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/TestUtils.java rename to x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/SqlTestUtils.java index d34de666248a5..db75e724340e1 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/TestUtils.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/SqlTestUtils.java @@ -7,9 +7,12 @@ package org.elasticsearch.xpack.sql; import org.elasticsearch.common.unit.TimeValue; +import org.elasticsearch.xpack.ql.expression.Literal; +import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.sql.proto.Mode; import org.elasticsearch.xpack.sql.proto.Protocol; import org.elasticsearch.xpack.sql.session.Configuration; +import org.elasticsearch.xpack.sql.type.SqlDataTypes; import org.elasticsearch.xpack.sql.util.DateUtils; import java.time.ZoneId; @@ -24,9 +27,9 @@ import static org.elasticsearch.test.ESTestCase.randomZone; -public final class TestUtils { +public final class SqlTestUtils { - private TestUtils() {} + private SqlTestUtils() {} public static final Configuration TEST_CFG = new Configuration(DateUtils.UTC, Protocol.FETCH_SIZE, Protocol.REQUEST_TIMEOUT, Protocol.PAGE_TIMEOUT, null, Mode.PLAIN, @@ -67,4 +70,15 @@ public static String randomWhitespaces() { } return sj.toString(); } + + public static Literal literal(Object value) { + return literal(Source.EMPTY, value); + } + + public static Literal literal(Source source, Object value) { + if (value instanceof Literal) { + return (Literal) value; + } + return new Literal(source, value, SqlDataTypes.fromJava(value)); + } } diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/analysis/analyzer/FieldAttributeTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/analysis/analyzer/FieldAttributeTests.java index 1d60cae0e6740..14b1da838259e 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/analysis/analyzer/FieldAttributeTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/analysis/analyzer/FieldAttributeTests.java @@ -16,10 +16,9 @@ import org.elasticsearch.xpack.ql.index.IndexResolution; import org.elasticsearch.xpack.ql.plan.logical.LogicalPlan; import org.elasticsearch.xpack.ql.plan.logical.Project; -import org.elasticsearch.xpack.ql.type.DataType; import org.elasticsearch.xpack.ql.type.EsField; import org.elasticsearch.xpack.ql.type.TypesTests; -import org.elasticsearch.xpack.sql.TestUtils; +import org.elasticsearch.xpack.sql.SqlTestUtils; import org.elasticsearch.xpack.sql.expression.function.SqlFunctionRegistry; import org.elasticsearch.xpack.sql.parser.SqlParser; import org.elasticsearch.xpack.sql.stats.Metrics; @@ -27,8 +26,10 @@ import java.util.List; import java.util.Map; -import static org.elasticsearch.xpack.ql.type.DataType.BOOLEAN; -import static org.elasticsearch.xpack.ql.type.DataType.KEYWORD; +import static org.elasticsearch.xpack.ql.type.DataTypes.BOOLEAN; +import static org.elasticsearch.xpack.ql.type.DataTypes.KEYWORD; +import static org.elasticsearch.xpack.ql.type.DataTypes.TEXT; +import static org.elasticsearch.xpack.sql.types.SqlTypesTests.loadMapping; import static org.hamcrest.CoreMatchers.instanceOf; import static org.hamcrest.Matchers.hasItem; import static org.hamcrest.Matchers.hasItems; @@ -49,11 +50,11 @@ public FieldAttributeTests() { functionRegistry = new SqlFunctionRegistry(); verifier = new Verifier(new Metrics()); - Map mapping = TypesTests.loadMapping("mapping-multi-field-variation.json"); + Map mapping = loadMapping("mapping-multi-field-variation.json"); EsIndex test = new EsIndex("test", mapping); getIndexResult = IndexResolution.valid(test); - analyzer = new Analyzer(TestUtils.TEST_CFG, functionRegistry, getIndexResult, verifier); + analyzer = new Analyzer(SqlTestUtils.TEST_CFG, functionRegistry, getIndexResult, verifier); } private LogicalPlan plan(String sql) { @@ -113,7 +114,7 @@ public void testExactKeyword() { FieldAttribute attr = attribute("some.string"); assertThat(attr.path(), is("some")); assertThat(attr.name(), is("some.string")); - assertThat(attr.dataType(), is(DataType.TEXT)); + assertThat(attr.dataType(), is(TEXT)); assertTrue(attr.getExactInfo().hasExact()); FieldAttribute exact = attr.exactAttribute(); assertTrue(exact.getExactInfo().hasExact()); @@ -125,7 +126,7 @@ public void testAmbiguousExactKeyword() { FieldAttribute attr = attribute("some.ambiguous"); assertThat(attr.path(), is("some")); assertThat(attr.name(), is("some.ambiguous")); - assertThat(attr.dataType(), is(DataType.TEXT)); + assertThat(attr.dataType(), is(TEXT)); assertFalse(attr.getExactInfo().hasExact()); assertThat(attr.getExactInfo().errorMsg(), is("Multiple exact keyword candidates available for [ambiguous]; specify which one to use")); @@ -172,7 +173,7 @@ public void testFieldAmbiguity() { EsIndex index = new EsIndex("test", mapping); getIndexResult = IndexResolution.valid(index); - analyzer = new Analyzer(TestUtils.TEST_CFG, functionRegistry, getIndexResult, verifier); + analyzer = new Analyzer(SqlTestUtils.TEST_CFG, functionRegistry, getIndexResult, verifier); VerificationException ex = expectThrows(VerificationException.class, () -> plan("SELECT test.bar FROM test")); assertEquals( diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/analysis/analyzer/VerifierErrorMessagesTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/analysis/analyzer/VerifierErrorMessagesTests.java index 7cfcc2bdc7642..413898ea290d3 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/analysis/analyzer/VerifierErrorMessagesTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/analysis/analyzer/VerifierErrorMessagesTests.java @@ -6,24 +6,22 @@ package org.elasticsearch.xpack.sql.analysis.analyzer; import org.elasticsearch.test.ESTestCase; -import org.elasticsearch.xpack.ql.expression.predicate.conditional.Coalesce; -import org.elasticsearch.xpack.ql.expression.predicate.conditional.Greatest; -import org.elasticsearch.xpack.ql.expression.predicate.conditional.IfNull; -import org.elasticsearch.xpack.ql.expression.predicate.conditional.Least; -import org.elasticsearch.xpack.ql.expression.predicate.conditional.NullIf; import org.elasticsearch.xpack.ql.index.EsIndex; import org.elasticsearch.xpack.ql.index.IndexResolution; import org.elasticsearch.xpack.ql.plan.logical.LogicalPlan; -import org.elasticsearch.xpack.ql.type.DataType; import org.elasticsearch.xpack.ql.type.EsField; -import org.elasticsearch.xpack.ql.type.TypesTests; -import org.elasticsearch.xpack.sql.TestUtils; +import org.elasticsearch.xpack.sql.SqlTestUtils; import org.elasticsearch.xpack.sql.analysis.index.IndexResolverTests; import org.elasticsearch.xpack.sql.expression.function.SqlFunctionRegistry; import org.elasticsearch.xpack.sql.expression.function.scalar.math.Round; import org.elasticsearch.xpack.sql.expression.function.scalar.math.Truncate; import org.elasticsearch.xpack.sql.expression.function.scalar.string.Char; import org.elasticsearch.xpack.sql.expression.function.scalar.string.Space; +import org.elasticsearch.xpack.sql.expression.predicate.conditional.Coalesce; +import org.elasticsearch.xpack.sql.expression.predicate.conditional.Greatest; +import org.elasticsearch.xpack.sql.expression.predicate.conditional.IfNull; +import org.elasticsearch.xpack.sql.expression.predicate.conditional.Least; +import org.elasticsearch.xpack.sql.expression.predicate.conditional.NullIf; import org.elasticsearch.xpack.sql.parser.SqlParser; import org.elasticsearch.xpack.sql.stats.Metrics; @@ -34,19 +32,23 @@ import static java.util.Collections.emptyMap; import static java.util.Collections.singletonMap; +import static org.elasticsearch.xpack.ql.type.DataTypes.KEYWORD; +import static org.elasticsearch.xpack.ql.type.DataTypes.OBJECT; +import static org.elasticsearch.xpack.sql.types.SqlTypesTests.loadMapping; + public class VerifierErrorMessagesTests extends ESTestCase { private SqlParser parser = new SqlParser(); private IndexResolution indexResolution = IndexResolution.valid(new EsIndex("test", - TypesTests.loadMapping("mapping-multi-field-with-nested.json"))); + loadMapping("mapping-multi-field-with-nested.json"))); private String error(String sql) { return error(indexResolution, sql); } private String error(IndexResolution getIndexResult, String sql) { - Analyzer analyzer = new Analyzer(TestUtils.TEST_CFG, new SqlFunctionRegistry(), getIndexResult, new Verifier(new Metrics())); + Analyzer analyzer = new Analyzer(SqlTestUtils.TEST_CFG, new SqlFunctionRegistry(), getIndexResult, new Verifier(new Metrics())); VerificationException e = expectThrows(VerificationException.class, () -> analyzer.analyze(parser.createStatement(sql), true)); assertTrue(e.getMessage().startsWith("Found ")); String header = "Found 1 problem(s)\nline "; @@ -59,18 +61,18 @@ private LogicalPlan accept(String sql) { } private EsIndex getTestEsIndex() { - Map mapping = TypesTests.loadMapping("mapping-multi-field-with-nested.json"); + Map mapping = loadMapping("mapping-multi-field-with-nested.json"); return new EsIndex("test", mapping); } private LogicalPlan accept(IndexResolution resolution, String sql) { - Analyzer analyzer = new Analyzer(TestUtils.TEST_CFG, new SqlFunctionRegistry(), resolution, new Verifier(new Metrics())); + Analyzer analyzer = new Analyzer(SqlTestUtils.TEST_CFG, new SqlFunctionRegistry(), resolution, new Verifier(new Metrics())); return analyzer.analyze(parser.createStatement(sql), true); } private IndexResolution incompatible() { - Map basicMapping = TypesTests.loadMapping("mapping-basic.json", true); - Map incompatible = TypesTests.loadMapping("mapping-basic-incompatible.json"); + Map basicMapping = loadMapping("mapping-basic.json", true); + Map incompatible = loadMapping("mapping-basic-incompatible.json"); assertNotEquals(basicMapping, incompatible); IndexResolution resolution = IndexResolverTests.merge(new EsIndex("basic", basicMapping), @@ -114,8 +116,7 @@ public void testColumnWithNoSubFields() { public void testFieldAliasTypeWithoutHierarchy() { Map mapping = new LinkedHashMap<>(); - mapping.put("field", new EsField("field", DataType.OBJECT, - singletonMap("alias", new EsField("alias", DataType.KEYWORD, emptyMap(), true)), false)); + mapping.put("field", new EsField("field", OBJECT, singletonMap("alias", new EsField("alias", KEYWORD, emptyMap(), true)), false)); IndexResolution resolution = IndexResolution.valid(new EsIndex("test", mapping)); diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/analysis/index/IndexResolverTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/analysis/index/IndexResolverTests.java index 181d0791f93b8..f29f373272a1e 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/analysis/index/IndexResolverTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/analysis/index/IndexResolverTests.java @@ -14,7 +14,7 @@ import org.elasticsearch.xpack.ql.type.EsField; import org.elasticsearch.xpack.ql.type.InvalidMappedField; import org.elasticsearch.xpack.ql.type.KeywordEsField; -import org.elasticsearch.xpack.ql.type.TypesTests; +import org.elasticsearch.xpack.sql.type.SqlDataTypeRegistry; import java.util.ArrayList; import java.util.Collections; @@ -26,12 +26,20 @@ import static java.util.Collections.singletonMap; import static org.elasticsearch.common.logging.LoggerMessageFormat.format; +import static org.elasticsearch.xpack.ql.type.DataTypes.DATETIME; +import static org.elasticsearch.xpack.ql.type.DataTypes.INTEGER; +import static org.elasticsearch.xpack.ql.type.DataTypes.KEYWORD; +import static org.elasticsearch.xpack.ql.type.DataTypes.OBJECT; +import static org.elasticsearch.xpack.ql.type.DataTypes.TEXT; +import static org.elasticsearch.xpack.ql.type.DataTypes.UNSUPPORTED; +import static org.elasticsearch.xpack.ql.type.DataTypes.isPrimitive; +import static org.elasticsearch.xpack.sql.types.SqlTypesTests.loadMapping; public class IndexResolverTests extends ESTestCase { public void testMergeSameMapping() throws Exception { - Map oneMapping = TypesTests.loadMapping("mapping-basic.json", true); - Map sameMapping = TypesTests.loadMapping("mapping-basic.json", true); + Map oneMapping = loadMapping("mapping-basic.json", true); + Map sameMapping = loadMapping("mapping-basic.json", true); assertNotSame(oneMapping, sameMapping); assertEquals(oneMapping, sameMapping); @@ -42,8 +50,8 @@ public void testMergeSameMapping() throws Exception { } public void testMergeCompatibleMapping() throws Exception { - Map basicMapping = TypesTests.loadMapping("mapping-basic.json", true); - Map numericMapping = TypesTests.loadMapping("mapping-numeric.json", true); + Map basicMapping = loadMapping("mapping-basic.json", true); + Map numericMapping = loadMapping("mapping-numeric.json", true); assertNotEquals(basicMapping, numericMapping); @@ -54,8 +62,8 @@ public void testMergeCompatibleMapping() throws Exception { } public void testMergeIncompatibleTypes() throws Exception { - Map basicMapping = TypesTests.loadMapping("mapping-basic.json", true); - Map incompatible = TypesTests.loadMapping("mapping-basic-incompatible.json"); + Map basicMapping = loadMapping("mapping-basic.json", true); + Map incompatible = loadMapping("mapping-basic-incompatible.json"); assertNotEquals(basicMapping, incompatible); @@ -75,8 +83,8 @@ public void testMergeIncompatibleTypes() throws Exception { } public void testMergeIncompatibleCapabilities() throws Exception { - Map basicMapping = TypesTests.loadMapping("mapping-basic.json", true); - Map incompatible = TypesTests.loadMapping("mapping-basic-nodocvalues.json", true); + Map basicMapping = loadMapping("mapping-basic.json", true); + Map incompatible = loadMapping("mapping-basic-nodocvalues.json", true); assertNotEquals(basicMapping, incompatible); @@ -93,7 +101,7 @@ public void testMergeIncompatibleCapabilities() throws Exception { } public void testMultiLevelObjectMappings() throws Exception { - Map dottedMapping = TypesTests.loadMapping("mapping-dotted-field.json", true); + Map dottedMapping = loadMapping("mapping-dotted-field.json", true); IndexResolution resolution = merge(new EsIndex("a", dottedMapping)); @@ -102,7 +110,7 @@ public void testMultiLevelObjectMappings() throws Exception { } public void testMultiLevelNestedMappings() throws Exception { - Map nestedMapping = TypesTests.loadMapping("mapping-nested.json", true); + Map nestedMapping = loadMapping("mapping-nested.json", true); IndexResolution resolution = merge(new EsIndex("a", nestedMapping)); @@ -118,15 +126,15 @@ public void testMetaFieldsAreIgnored() throws Exception { addFieldCaps(fieldCaps, "text", "keyword", true, true); String wildcard = "*"; - IndexResolution resolution = IndexResolver.mergedMappings(wildcard, new String[] { "index" }, fieldCaps); + IndexResolution resolution = mergedMappings(wildcard, new String[] { "index" }, fieldCaps); assertTrue(resolution.isValid()); EsIndex esIndex = resolution.get(); assertEquals(wildcard, esIndex.name()); assertNull(esIndex.mapping().get("_version")); assertNull(esIndex.mapping().get("_size")); - assertEquals(DataType.INTEGER, esIndex.mapping().get("_meta_field").getDataType()); - assertEquals(DataType.KEYWORD, esIndex.mapping().get("text").getDataType()); + assertEquals(INTEGER, esIndex.mapping().get("_meta_field").getDataType()); + assertEquals(KEYWORD, esIndex.mapping().get("text").getDataType()); } public void testFlattenedHiddenSubfield() throws Exception { @@ -141,20 +149,20 @@ public void testFlattenedHiddenSubfield() throws Exception { addFieldCaps(fieldCaps, "text", "keyword", true, true); String wildcard = "*"; - IndexResolution resolution = IndexResolver.mergedMappings(wildcard, new String[] { "index" }, fieldCaps); + IndexResolution resolution = mergedMappings(wildcard, new String[] { "index" }, fieldCaps); assertTrue(resolution.isValid()); EsIndex esIndex = resolution.get(); assertEquals(wildcard, esIndex.name()); - assertEquals(DataType.UNSUPPORTED, esIndex.mapping().get("some_field").getDataType()); - assertEquals(DataType.UNSUPPORTED, esIndex.mapping().get("some_field").getProperties().get("_keyed").getDataType()); - assertEquals(DataType.OBJECT, esIndex.mapping().get("nested_field").getDataType()); - assertEquals(DataType.UNSUPPORTED, esIndex.mapping().get("nested_field").getProperties().get("sub_field").getDataType()); - assertEquals(DataType.UNSUPPORTED, + assertEquals(UNSUPPORTED, esIndex.mapping().get("some_field").getDataType()); + assertEquals(UNSUPPORTED, esIndex.mapping().get("some_field").getProperties().get("_keyed").getDataType()); + assertEquals(OBJECT, esIndex.mapping().get("nested_field").getDataType()); + assertEquals(UNSUPPORTED, esIndex.mapping().get("nested_field").getProperties().get("sub_field").getDataType()); + assertEquals(UNSUPPORTED, esIndex.mapping().get("nested_field").getProperties().get("sub_field").getProperties().get("_keyed").getDataType()); - assertEquals(DataType.KEYWORD, esIndex.mapping().get("text").getDataType()); - assertEquals(DataType.OBJECT, esIndex.mapping().get("another_field").getDataType()); - assertEquals(DataType.KEYWORD, esIndex.mapping().get("another_field").getProperties().get("_keyed").getDataType()); + assertEquals(KEYWORD, esIndex.mapping().get("text").getDataType()); + assertEquals(OBJECT, esIndex.mapping().get("another_field").getDataType()); + assertEquals(KEYWORD, esIndex.mapping().get("another_field").getProperties().get("_keyed").getDataType()); } public void testPropagateUnsupportedTypeToSubFields() throws Exception { @@ -168,17 +176,17 @@ public void testPropagateUnsupportedTypeToSubFields() throws Exception { addFieldCaps(fieldCaps, "a.b.c.e", "foo", true, true); String wildcard = "*"; - IndexResolution resolution = IndexResolver.mergedMappings(wildcard, new String[] { "index" }, fieldCaps); + IndexResolution resolution = mergedMappings(wildcard, new String[] { "index" }, fieldCaps); assertTrue(resolution.isValid()); EsIndex esIndex = resolution.get(); assertEquals(wildcard, esIndex.name()); - assertEquals(DataType.TEXT, esIndex.mapping().get("a").getDataType()); - assertEquals(DataType.UNSUPPORTED, esIndex.mapping().get("a").getProperties().get("b").getDataType()); - assertEquals(DataType.UNSUPPORTED, esIndex.mapping().get("a").getProperties().get("b").getProperties().get("c").getDataType()); - assertEquals(DataType.UNSUPPORTED, esIndex.mapping().get("a").getProperties().get("b").getProperties().get("c") + assertEquals(TEXT, esIndex.mapping().get("a").getDataType()); + assertEquals(UNSUPPORTED, esIndex.mapping().get("a").getProperties().get("b").getDataType()); + assertEquals(UNSUPPORTED, esIndex.mapping().get("a").getProperties().get("b").getProperties().get("c").getDataType()); + assertEquals(UNSUPPORTED, esIndex.mapping().get("a").getProperties().get("b").getProperties().get("c") .getProperties().get("d").getDataType()); - assertEquals(DataType.UNSUPPORTED, esIndex.mapping().get("a").getProperties().get("b").getProperties().get("c") + assertEquals(UNSUPPORTED, esIndex.mapping().get("a").getProperties().get("b").getProperties().get("c") .getProperties().get("e").getDataType()); } @@ -199,22 +207,22 @@ public void testRandomMappingFieldTypeMappedAsUnsupported() throws Exception { addFieldCaps(fieldCaps, "text", "keyword", true, true); String wildcard = "*"; - IndexResolution resolution = IndexResolver.mergedMappings(wildcard, new String[] { "index" }, fieldCaps); + IndexResolution resolution = mergedMappings(wildcard, new String[] { "index" }, fieldCaps); assertTrue(resolution.isValid()); EsIndex esIndex = resolution.get(); assertEquals(wildcard, esIndex.name()); - assertEquals(DataType.UNSUPPORTED, esIndex.mapping().get("some_field").getDataType()); - assertEquals(DataType.OBJECT, esIndex.mapping().get("nested_field").getDataType()); - assertEquals(DataType.UNSUPPORTED, esIndex.mapping().get("nested_field").getProperties().get("sub_field1").getDataType()); - assertEquals(DataType.UNSUPPORTED, + assertEquals(UNSUPPORTED, esIndex.mapping().get("some_field").getDataType()); + assertEquals(OBJECT, esIndex.mapping().get("nested_field").getDataType()); + assertEquals(UNSUPPORTED, esIndex.mapping().get("nested_field").getProperties().get("sub_field1").getDataType()); + assertEquals(UNSUPPORTED, esIndex.mapping().get("nested_field").getProperties().get("sub_field1").getProperties().get("bar").getDataType()); - assertEquals(DataType.UNSUPPORTED, esIndex.mapping().get("nested_field").getProperties().get("sub_field2").getDataType()); - assertEquals(DataType.UNSUPPORTED, + assertEquals(UNSUPPORTED, esIndex.mapping().get("nested_field").getProperties().get("sub_field2").getDataType()); + assertEquals(UNSUPPORTED, esIndex.mapping().get("nested_field").getProperties().get("sub_field2").getProperties().get("bar").getDataType()); - assertEquals(DataType.KEYWORD, esIndex.mapping().get("text").getDataType()); - assertEquals(DataType.OBJECT, esIndex.mapping().get("another_field").getDataType()); - assertEquals(DataType.UNSUPPORTED, esIndex.mapping().get("another_field").getProperties().get("_foo").getDataType()); + assertEquals(KEYWORD, esIndex.mapping().get("text").getDataType()); + assertEquals(OBJECT, esIndex.mapping().get("another_field").getDataType()); + assertEquals(UNSUPPORTED, esIndex.mapping().get("another_field").getProperties().get("_foo").getDataType()); } public void testMergeIncompatibleCapabilitiesOfObjectFields() throws Exception { @@ -243,7 +251,7 @@ public void testMergeIncompatibleCapabilitiesOfObjectFields() throws Exception { String wildcard = "*"; - IndexResolution resolution = IndexResolver.mergedMappings(wildcard, new String[] { "one-index" }, fieldCaps); + IndexResolution resolution = mergedMappings(wildcard, new String[] { "one-index" }, fieldCaps); assertTrue(resolution.isValid()); @@ -261,8 +269,8 @@ public void testMergeIncompatibleCapabilitiesOfObjectFields() throws Exception { } public void testSeparateSameMappingDifferentIndices() throws Exception { - Map oneMapping = TypesTests.loadMapping("mapping-basic.json", true); - Map sameMapping = TypesTests.loadMapping("mapping-basic.json", true); + Map oneMapping = loadMapping("mapping-basic.json", true); + Map sameMapping = loadMapping("mapping-basic.json", true); assertNotSame(oneMapping, sameMapping); assertEquals(oneMapping, sameMapping); @@ -274,8 +282,8 @@ public void testSeparateSameMappingDifferentIndices() throws Exception { } public void testSeparateIncompatibleTypes() throws Exception { - Map basicMapping = TypesTests.loadMapping("mapping-basic.json", true); - Map incompatible = TypesTests.loadMapping("mapping-basic-incompatible.json"); + Map basicMapping = loadMapping("mapping-basic.json", true); + Map incompatible = loadMapping("mapping-basic-incompatible.json"); assertNotEquals(basicMapping, incompatible); @@ -310,15 +318,15 @@ public void testIndexWithNoMapping() { Map> versionFC = singletonMap("_version", singletonMap("_index", new FieldCapabilities("_version", "_version", false, false, Collections.emptyMap()))); - assertTrue(IndexResolver.mergedMappings("*", new String[] { "empty" }, versionFC).isValid()); + assertTrue(mergedMappings("*", new String[] { "empty" }, versionFC).isValid()); } public static IndexResolution merge(EsIndex... indices) { - return IndexResolver.mergedMappings("*", Stream.of(indices).map(EsIndex::name).toArray(String[]::new), fromMappings(indices)); + return mergedMappings("*", Stream.of(indices).map(EsIndex::name).toArray(String[]::new), fromMappings(indices)); } public static List separate(EsIndex... indices) { - return IndexResolver.separateMappings("*", null, Stream.of(indices).map(EsIndex::name).toArray(String[]::new), + return separateMappings("*", null, Stream.of(indices).map(EsIndex::name).toArray(String[]::new), fromMappings(indices)); } @@ -339,7 +347,7 @@ public static Map> fromMappings(EsIndex.. if (entry.getValue().size() > 1) { for (EsIndex index : indices) { EsField field = index.mapping().get(fieldName); - UpdateableFieldCapabilities fieldCaps = (UpdateableFieldCapabilities) caps.get(field.getDataType().typeName()); + UpdateableFieldCapabilities fieldCaps = (UpdateableFieldCapabilities) caps.get(field.getDataType().esType()); fieldCaps.indices.add(index.name()); } //TODO: what about nonAgg/SearchIndices? @@ -356,7 +364,7 @@ private static void addFieldCaps(String parent, EsField field, String indexName, map = new HashMap<>(); merged.put(fieldName, map); } - FieldCapabilities caps = map.computeIfAbsent(field.getDataType().typeName(), + FieldCapabilities caps = map.computeIfAbsent(field.getDataType().esType(), esType -> new UpdateableFieldCapabilities(fieldName, esType, isSearchable(field.getDataType()), isAggregatable(field.getDataType()))); @@ -371,11 +379,11 @@ private static void addFieldCaps(String parent, EsField field, String indexName, } private static boolean isSearchable(DataType type) { - return type.isPrimitive(); + return isPrimitive(type); } private static boolean isAggregatable(DataType type) { - return type.isNumeric() || type == DataType.KEYWORD || type == DataType.DATETIME; + return type.isNumeric() || type == KEYWORD || type == DATETIME; } private static class UpdateableFieldCapabilities extends FieldCapabilities { @@ -421,4 +429,14 @@ private void addFieldCaps(Map> fieldCaps, cap.put(type, new FieldCapabilities(name, type, isSearchable, isAggregatable, Collections.emptyMap())); fieldCaps.put(name, cap); } -} + + private static IndexResolution mergedMappings(String indexPattern, String[] indexNames, + Map> fieldCaps) { + return IndexResolver.mergedMappings(SqlDataTypeRegistry.INSTANCE, indexPattern, indexNames, fieldCaps); + } + + private static List separateMappings(String indexPattern, String javaRegex, String[] indexNames, + Map> fieldCaps) { + return IndexResolver.separateMappings(SqlDataTypeRegistry.INSTANCE, indexPattern, javaRegex, indexNames, fieldCaps); + } +} \ No newline at end of file diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/execution/search/extractor/ComputingExtractorTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/execution/search/extractor/ComputingExtractorTests.java index 832bda0570e86..d81b31db5c95e 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/execution/search/extractor/ComputingExtractorTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/execution/search/extractor/ComputingExtractorTests.java @@ -10,12 +10,10 @@ import org.elasticsearch.common.io.stream.Writeable.Reader; import org.elasticsearch.search.SearchHit; import org.elasticsearch.xpack.ql.execution.search.extractor.ComputingExtractor; -import org.elasticsearch.xpack.ql.execution.search.extractor.HitExtractors; import org.elasticsearch.xpack.ql.expression.gen.processor.ChainingProcessor; import org.elasticsearch.xpack.ql.expression.gen.processor.ChainingProcessorTests; import org.elasticsearch.xpack.ql.expression.gen.processor.HitExtractorProcessor; import org.elasticsearch.xpack.ql.expression.gen.processor.Processor; -import org.elasticsearch.xpack.ql.type.DataType; import org.elasticsearch.xpack.sql.AbstractSqlWireSerializingTestCase; import org.elasticsearch.xpack.sql.expression.function.scalar.CastProcessorTests; import org.elasticsearch.xpack.sql.expression.function.scalar.Processors; @@ -31,6 +29,7 @@ import static java.util.Collections.singletonList; import static java.util.Collections.singletonMap; +import static org.elasticsearch.xpack.ql.type.DataTypes.DOUBLE; import static org.elasticsearch.xpack.ql.util.CollectionUtils.combine; import static org.elasticsearch.xpack.sql.util.DateUtils.UTC; @@ -50,7 +49,7 @@ public static Processor randomProcessor() { @Override protected NamedWriteableRegistry getNamedWriteableRegistry() { - return new NamedWriteableRegistry(combine(Processors.getNamedWriteables(), HitExtractors.getNamedWriteables())); + return new NamedWriteableRegistry(combine(Processors.getNamedWriteables(), SqlHitExtractors.getNamedWriteables())); } @Override @@ -74,7 +73,7 @@ protected ComputingExtractor mutateInstance(ComputingExtractor instance) throws public void testGet() { String fieldName = randomAlphaOfLength(5); ChainingProcessor extractor = new ChainingProcessor( - new HitExtractorProcessor(new FieldHitExtractor(fieldName, DataType.DOUBLE, UTC, true, false)), + new HitExtractorProcessor(new FieldHitExtractor(fieldName, DOUBLE, UTC, true, false)), new MathProcessor(MathOperation.LOG)); int times = between(1, 1000); @@ -87,4 +86,4 @@ public void testGet() { assertEquals(expected, extractor.process(hit)); } } -} +} \ No newline at end of file diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/execution/search/extractor/FieldHitExtractorTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/execution/search/extractor/FieldHitExtractorTests.java index 47242a2249233..e52ef992d547f 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/execution/search/extractor/FieldHitExtractorTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/execution/search/extractor/FieldHitExtractorTests.java @@ -13,9 +13,9 @@ import org.elasticsearch.search.SearchHit; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.xpack.ql.QlIllegalArgumentException; -import org.elasticsearch.xpack.ql.expression.function.scalar.geo.GeoShape; -import org.elasticsearch.xpack.ql.type.DataType; import org.elasticsearch.xpack.sql.AbstractSqlWireSerializingTestCase; +import org.elasticsearch.xpack.sql.expression.literal.geo.GeoShape; +import org.elasticsearch.xpack.sql.type.SqlDataTypes; import org.elasticsearch.xpack.sql.util.DateUtils; import java.io.IOException; @@ -34,6 +34,10 @@ import static java.util.Arrays.asList; import static java.util.Collections.singletonList; import static java.util.Collections.singletonMap; +import static org.elasticsearch.xpack.ql.type.DataTypes.DATETIME; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.GEO_POINT; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.GEO_SHAPE; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.SHAPE; import static org.elasticsearch.xpack.sql.util.DateUtils.UTC; import static org.hamcrest.Matchers.is; @@ -65,7 +69,7 @@ protected FieldHitExtractor mutateInstance(FieldHitExtractor instance) { return new FieldHitExtractor( instance.fieldName() + "mutated", instance.fullFieldName() + "mutated", - randomValueOtherThan(instance.dataType(), () -> randomFrom(DataType.values())), + randomValueOtherThan(instance.dataType(), () -> randomFrom(SqlDataTypes.types())), randomValueOtherThan(instance.zoneId(), ESTestCase::randomZone), randomBoolean(), instance.hitName() + "mutated", @@ -164,7 +168,7 @@ public void testGetDate() { SearchHit hit = new SearchHit(1); DocumentField field = new DocumentField("my_date_field", documentFieldValues); hit.fields(singletonMap("my_date_field", field)); - FieldHitExtractor extractor = new FieldHitExtractor("my_date_field", DataType.DATETIME, zoneId, true); + FieldHitExtractor extractor = new FieldHitExtractor("my_date_field", DATETIME, zoneId, true); assertEquals(DateUtils.asDateTime(millis, zoneId), extractor.extract(hit)); } @@ -462,7 +466,7 @@ public void testObjectsForSourceValue() throws IOException { public void testGeoShapeExtraction() { String fieldName = randomAlphaOfLength(5); - FieldHitExtractor fe = new FieldHitExtractor(fieldName, randomBoolean() ? DataType.GEO_SHAPE : DataType.SHAPE, UTC, false); + FieldHitExtractor fe = new FieldHitExtractor(fieldName, randomBoolean() ? GEO_SHAPE : SHAPE, UTC, false); Map map = new HashMap<>(); map.put(fieldName, "POINT (1 2)"); assertEquals(new GeoShape(1, 2), fe.extractFromSource(map)); @@ -474,7 +478,7 @@ public void testGeoShapeExtraction() { public void testMultipleGeoShapeExtraction() { String fieldName = randomAlphaOfLength(5); - FieldHitExtractor fe = new FieldHitExtractor(fieldName, randomBoolean() ? DataType.GEO_SHAPE : DataType.SHAPE, UTC, false); + FieldHitExtractor fe = new FieldHitExtractor(fieldName, randomBoolean() ? GEO_SHAPE : SHAPE, UTC, false); Map map = new HashMap<>(); map.put(fieldName, "POINT (1 2)"); assertEquals(new GeoShape(1, 2), fe.extractFromSource(map)); @@ -488,7 +492,7 @@ public void testMultipleGeoShapeExtraction() { assertThat(ex.getMessage(), is("Arrays (returned by [" + fieldName + "]) are not supported")); FieldHitExtractor lenientFe = new FieldHitExtractor(fieldName, - randomBoolean() ? DataType.GEO_SHAPE : DataType.SHAPE, UTC, false, true); + randomBoolean() ? GEO_SHAPE : SHAPE, UTC, false, true); assertEquals(new GeoShape(1, 2), lenientFe.extractFromSource(map2)); } @@ -525,7 +529,7 @@ public void testGeoPointExtractionFromSource() throws IOException { BytesReference sourceRef = BytesReference.bytes(source); hit.sourceRef(sourceRef); - FieldHitExtractor fe = new FieldHitExtractor(pathCombined, DataType.GEO_POINT, UTC, false); + FieldHitExtractor fe = new FieldHitExtractor(pathCombined, GEO_POINT, UTC, false); assertEquals(new GeoShape(lon, lat), fe.extract(hit)); } @@ -548,17 +552,17 @@ public void testMultipleGeoPointExtractionFromSource() throws IOException { BytesReference sourceRef = BytesReference.bytes(source); hit.sourceRef(sourceRef); - FieldHitExtractor fe = new FieldHitExtractor(fieldName, DataType.GEO_POINT, UTC, false); + FieldHitExtractor fe = new FieldHitExtractor(fieldName, GEO_POINT, UTC, false); QlIllegalArgumentException ex = expectThrows(QlIllegalArgumentException.class, () -> fe.extract(hit)); assertThat(ex.getMessage(), is("Arrays (returned by [" + fieldName + "]) are not supported")); - FieldHitExtractor lenientFe = new FieldHitExtractor(fieldName, DataType.GEO_POINT, UTC, false, true); + FieldHitExtractor lenientFe = new FieldHitExtractor(fieldName, GEO_POINT, UTC, false, true); assertEquals(new GeoShape(lon, lat), lenientFe.extract(hit)); } public void testGeoPointExtractionFromDocValues() { String fieldName = randomAlphaOfLength(5); - FieldHitExtractor fe = new FieldHitExtractor(fieldName, DataType.GEO_POINT, UTC, true); + FieldHitExtractor fe = new FieldHitExtractor(fieldName, GEO_POINT, UTC, true); SearchHit hit = new SearchHit(1); DocumentField field = new DocumentField(fieldName, singletonList("2, 1")); hit.fields(singletonMap(fieldName, field)); @@ -570,13 +574,13 @@ public void testGeoPointExtractionFromDocValues() { public void testGeoPointExtractionFromMultipleDocValues() { String fieldName = randomAlphaOfLength(5); SearchHit hit = new SearchHit(1); - FieldHitExtractor fe = new FieldHitExtractor(fieldName, DataType.GEO_POINT, UTC, true); + FieldHitExtractor fe = new FieldHitExtractor(fieldName, GEO_POINT, UTC, true); hit.fields(singletonMap(fieldName, new DocumentField(fieldName, Arrays.asList("2,1", "3,4")))); QlIllegalArgumentException ex = expectThrows(QlIllegalArgumentException.class, () -> fe.extract(hit)); assertThat(ex.getMessage(), is("Arrays (returned by [" + fieldName + "]) are not supported")); - FieldHitExtractor lenientFe = new FieldHitExtractor(fieldName, DataType.GEO_POINT, UTC, true, true); + FieldHitExtractor lenientFe = new FieldHitExtractor(fieldName, GEO_POINT, UTC, true, true); assertEquals(new GeoShape(1, 2), lenientFe.extract(hit)); } diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/execution/search/extractor/MetricAggExtractorTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/execution/search/extractor/MetricAggExtractorTests.java index 9a058ef30830a..d4951b0f618a0 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/execution/search/extractor/MetricAggExtractorTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/execution/search/extractor/MetricAggExtractorTests.java @@ -55,8 +55,7 @@ protected MetricAggExtractor mutateInstance(MetricAggExtractor instance) throws instance.name() + "mutated", instance.property() + "mutated", instance.innerKey() + "mutated", - randomValueOtherThan(instance.zoneId(), - ESTestCase::randomZone), randomBoolean()); + randomValueOtherThan(instance.zoneId(), ESTestCase::randomZone), randomBoolean()); } public void testNoAggs() { diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/execution/search/extractor/TopHitsAggExtractorTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/execution/search/extractor/TopHitsAggExtractorTests.java index 5f770f1027307..dd4158080fea0 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/execution/search/extractor/TopHitsAggExtractorTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/execution/search/extractor/TopHitsAggExtractorTests.java @@ -15,9 +15,10 @@ import org.elasticsearch.search.aggregations.bucket.MultiBucketsAggregation.Bucket; import org.elasticsearch.search.aggregations.metrics.InternalTopHits; import org.elasticsearch.test.ESTestCase; -import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import org.elasticsearch.xpack.sql.AbstractSqlWireSerializingTestCase; import org.elasticsearch.xpack.sql.SqlIllegalArgumentException; +import org.elasticsearch.xpack.sql.type.SqlDataTypes; import org.elasticsearch.xpack.sql.util.DateUtils; import java.time.ZoneId; @@ -31,7 +32,7 @@ public class TopHitsAggExtractorTests extends AbstractSqlWireSerializingTestCase { public static TopHitsAggExtractor randomTopHitsAggExtractor() { - return new TopHitsAggExtractor(randomAlphaOfLength(16), randomFrom(DataType.values()), randomZone()); + return new TopHitsAggExtractor(randomAlphaOfLength(16), randomFrom(SqlDataTypes.types()), randomZone()); } @Override @@ -53,7 +54,7 @@ protected ZoneId instanceZoneId(TopHitsAggExtractor instance) { protected TopHitsAggExtractor mutateInstance(TopHitsAggExtractor instance) { return new TopHitsAggExtractor( instance.name() + "mutated", - randomValueOtherThan(instance.fieldDataType(), () -> randomFrom(DataType.values())), + randomValueOtherThan(instance.fieldDataType(), () -> randomFrom(SqlDataTypes.types())), randomValueOtherThan(instance.zoneId(), ESTestCase::randomZone)); } @@ -74,7 +75,7 @@ public void testZeroNullValue() { } public void testExtractValue() { - TopHitsAggExtractor extractor = new TopHitsAggExtractor("topHitsAgg", DataType.KEYWORD, UTC); + TopHitsAggExtractor extractor = new TopHitsAggExtractor("topHitsAgg", DataTypes.KEYWORD, UTC); String value = "Str_Value"; Aggregation agg = new InternalTopHits(extractor.name(), 0, 1, null, searchHitsOf(value), null, null); @@ -84,7 +85,7 @@ public void testExtractValue() { public void testExtractDateValue() { ZoneId zoneId = randomZone(); - TopHitsAggExtractor extractor = new TopHitsAggExtractor("topHitsAgg", DataType.DATETIME, zoneId); + TopHitsAggExtractor extractor = new TopHitsAggExtractor("topHitsAgg", DataTypes.DATETIME, zoneId); long value = 123456789L; Aggregation agg = new InternalTopHits(extractor.name(), 0, 1, null, searchHitsOf(value), null, null); diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/ProcessorTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/ProcessorTests.java index 7e4758c6d95ff..913565f681c7a 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/ProcessorTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/ProcessorTests.java @@ -32,6 +32,7 @@ public static void init() throws Exception { public void testProcessorRegistration() throws Exception { LinkedHashSet registered = Processors.getNamedWriteables().stream() + .filter(e -> Processor.class == e.categoryClass) .map(e -> e.name) .collect(toCollection(LinkedHashSet::new)); diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/TypeResolutionTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/TypeResolutionTests.java new file mode 100644 index 0000000000000..e4c1a43410fe9 --- /dev/null +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/TypeResolutionTests.java @@ -0,0 +1,45 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +package org.elasticsearch.xpack.sql.expression; + +import org.elasticsearch.test.ESTestCase; +import org.elasticsearch.xpack.ql.expression.Expression.TypeResolution; +import org.elasticsearch.xpack.ql.expression.Literal; +import org.elasticsearch.xpack.sql.SqlTestUtils; +import org.elasticsearch.xpack.sql.expression.literal.interval.IntervalYearMonth; +import org.elasticsearch.xpack.sql.expression.predicate.operator.arithmetic.Mul; + +import java.time.Period; + +import static org.elasticsearch.xpack.ql.tree.Source.EMPTY; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.INTERVAL_YEAR_TO_MONTH; + +public class TypeResolutionTests extends ESTestCase { + + public void testMulIntervalAndNumber() { + Mul m = new Mul(EMPTY, L(1), randomYearInterval()); + assertEquals(TypeResolution.TYPE_RESOLVED, m.typeResolved()); + } + + public void testMulNumberAndInterval() { + Mul m = new Mul(EMPTY, randomYearInterval(), L(1)); + assertEquals(TypeResolution.TYPE_RESOLVED, m.typeResolved()); + } + + public void testMulTypeResolution() throws Exception { + Mul mul = new Mul(EMPTY, randomYearInterval(), randomYearInterval()); + assertTrue(mul.typeResolved().unresolved()); + } + + private static Literal randomYearInterval() { + return L(new IntervalYearMonth(Period.ofMonths(randomInt(123)), INTERVAL_YEAR_TO_MONTH)); + } + + private static Literal L(Object value) { + return SqlTestUtils.literal(value); + } +} diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/function/scalar/CastProcessorTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/function/scalar/CastProcessorTests.java index 5061d42e7947e..fb4441af3cec0 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/function/scalar/CastProcessorTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/function/scalar/CastProcessorTests.java @@ -9,13 +9,14 @@ import org.elasticsearch.common.io.stream.Writeable.Reader; import org.elasticsearch.test.AbstractWireSerializingTestCase; import org.elasticsearch.xpack.ql.QlIllegalArgumentException; -import org.elasticsearch.xpack.ql.type.DataTypeConversion.Conversion; +import org.elasticsearch.xpack.ql.type.DataTypeConverter.DefaultConverter; +import org.elasticsearch.xpack.sql.type.SqlDataTypeConverter.SqlConverter; import java.io.IOException; public class CastProcessorTests extends AbstractWireSerializingTestCase { public static CastProcessor randomCastProcessor() { - return new CastProcessor(randomFrom(Conversion.values())); + return new CastProcessor(randomFrom(SqlConverter.values())); } @Override @@ -30,19 +31,19 @@ protected Reader instanceReader() { @Override protected CastProcessor mutateInstance(CastProcessor instance) throws IOException { - return new CastProcessor(randomValueOtherThan(instance.converter(), () -> randomFrom(Conversion.values()))); + return new CastProcessor(randomValueOtherThan(instance.converter(), () -> randomFrom(SqlConverter.values()))); } public void testApply() { { - CastProcessor proc = new CastProcessor(Conversion.STRING_TO_INT); + CastProcessor proc = new CastProcessor(DefaultConverter.STRING_TO_INT); assertEquals(null, proc.process(null)); assertEquals(1, proc.process("1")); Exception e = expectThrows(QlIllegalArgumentException.class, () -> proc.process("1.2")); assertEquals("cannot cast [1.2] to [integer]", e.getMessage()); } { - CastProcessor proc = new CastProcessor(Conversion.BOOL_TO_INT); + CastProcessor proc = new CastProcessor(DefaultConverter.BOOL_TO_INT); assertEquals(null, proc.process(null)); assertEquals(1, proc.process(true)); assertEquals(0, proc.process(false)); diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/function/scalar/DatabaseFunctionTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/function/scalar/DatabaseFunctionTests.java index ab0b5dd06718c..706f1c2fc6b97 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/function/scalar/DatabaseFunctionTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/function/scalar/DatabaseFunctionTests.java @@ -12,7 +12,6 @@ import org.elasticsearch.xpack.ql.index.EsIndex; import org.elasticsearch.xpack.ql.index.IndexResolution; import org.elasticsearch.xpack.ql.plan.logical.Project; -import org.elasticsearch.xpack.ql.type.TypesTests; import org.elasticsearch.xpack.sql.analysis.analyzer.Analyzer; import org.elasticsearch.xpack.sql.analysis.analyzer.Verifier; import org.elasticsearch.xpack.sql.expression.function.SqlFunctionRegistry; @@ -21,6 +20,7 @@ import org.elasticsearch.xpack.sql.proto.Protocol; import org.elasticsearch.xpack.sql.session.Configuration; import org.elasticsearch.xpack.sql.stats.Metrics; +import org.elasticsearch.xpack.sql.types.SqlTypesTests; import org.elasticsearch.xpack.sql.util.DateUtils; public class DatabaseFunctionTests extends ESTestCase { @@ -28,7 +28,7 @@ public class DatabaseFunctionTests extends ESTestCase { public void testDatabaseFunctionOutput() { String clusterName = randomAlphaOfLengthBetween(1, 15); SqlParser parser = new SqlParser(); - EsIndex test = new EsIndex("test", TypesTests.loadMapping("mapping-basic.json", true)); + EsIndex test = new EsIndex("test", SqlTypesTests.loadMapping("mapping-basic.json", true)); Analyzer analyzer = new Analyzer( new Configuration(DateUtils.UTC, Protocol.FETCH_SIZE, Protocol.REQUEST_TIMEOUT, Protocol.PAGE_TIMEOUT, null, diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/function/scalar/UserFunctionTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/function/scalar/UserFunctionTests.java index 657d4d9e33ed1..f3dcc1d402d0b 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/function/scalar/UserFunctionTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/function/scalar/UserFunctionTests.java @@ -12,7 +12,6 @@ import org.elasticsearch.xpack.ql.index.EsIndex; import org.elasticsearch.xpack.ql.index.IndexResolution; import org.elasticsearch.xpack.ql.plan.logical.Project; -import org.elasticsearch.xpack.ql.type.TypesTests; import org.elasticsearch.xpack.sql.analysis.analyzer.Analyzer; import org.elasticsearch.xpack.sql.analysis.analyzer.Verifier; import org.elasticsearch.xpack.sql.expression.function.SqlFunctionRegistry; @@ -21,13 +20,14 @@ import org.elasticsearch.xpack.sql.proto.Protocol; import org.elasticsearch.xpack.sql.session.Configuration; import org.elasticsearch.xpack.sql.stats.Metrics; +import org.elasticsearch.xpack.sql.types.SqlTypesTests; import org.elasticsearch.xpack.sql.util.DateUtils; public class UserFunctionTests extends ESTestCase { public void testNoUsernameFunctionOutput() { SqlParser parser = new SqlParser(); - EsIndex test = new EsIndex("test", TypesTests.loadMapping("mapping-basic.json", true)); + EsIndex test = new EsIndex("test", SqlTypesTests.loadMapping("mapping-basic.json", true)); Analyzer analyzer = new Analyzer( new Configuration(DateUtils.UTC, Protocol.FETCH_SIZE, Protocol.REQUEST_TIMEOUT, Protocol.PAGE_TIMEOUT, null, diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/CurrentDateTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/CurrentDateTests.java index 1c6dcc19eb791..792fb2ddefa6d 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/CurrentDateTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/CurrentDateTests.java @@ -9,7 +9,7 @@ import org.elasticsearch.xpack.ql.expression.Expression; import org.elasticsearch.xpack.ql.tree.AbstractNodeTestCase; import org.elasticsearch.xpack.ql.tree.Source; -import org.elasticsearch.xpack.sql.TestUtils; +import org.elasticsearch.xpack.sql.SqlTestUtils; import java.time.ZoneId; import java.time.ZonedDateTime; @@ -18,7 +18,7 @@ public class CurrentDateTests extends AbstractNodeTestCase { public static CurrentDate randomCurrentDate() { - return new CurrentDate(Source.EMPTY, TestUtils.randomConfiguration()); + return new CurrentDate(Source.EMPTY, SqlTestUtils.randomConfiguration()); } @Override @@ -36,7 +36,7 @@ protected CurrentDate mutate(CurrentDate instance) { ZonedDateTime now = instance.configuration().now(); ZoneId mutatedZoneId = randomValueOtherThanMany(o -> Objects.equals(now.getOffset(), o.getRules().getOffset(now.toInstant())), () -> randomZone()); - return new CurrentDate(instance.source(), TestUtils.randomConfiguration(mutatedZoneId)); + return new CurrentDate(instance.source(), SqlTestUtils.randomConfiguration(mutatedZoneId)); } @Override diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/CurrentDateTimeTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/CurrentDateTimeTests.java index 8b2894c172c89..ab6a182be36d9 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/CurrentDateTimeTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/CurrentDateTimeTests.java @@ -8,19 +8,18 @@ import org.elasticsearch.test.ESTestCase; import org.elasticsearch.xpack.ql.expression.Expression; -import org.elasticsearch.xpack.ql.expression.Literal; import org.elasticsearch.xpack.ql.index.EsIndex; import org.elasticsearch.xpack.ql.index.IndexResolution; import org.elasticsearch.xpack.ql.session.Configuration; import org.elasticsearch.xpack.ql.tree.AbstractNodeTestCase; -import org.elasticsearch.xpack.ql.type.TypesTests; -import org.elasticsearch.xpack.sql.TestUtils; +import org.elasticsearch.xpack.sql.SqlTestUtils; import org.elasticsearch.xpack.sql.analysis.analyzer.Analyzer; import org.elasticsearch.xpack.sql.analysis.analyzer.Verifier; import org.elasticsearch.xpack.sql.expression.function.SqlFunctionRegistry; import org.elasticsearch.xpack.sql.parser.ParsingException; import org.elasticsearch.xpack.sql.parser.SqlParser; import org.elasticsearch.xpack.sql.stats.Metrics; +import org.elasticsearch.xpack.sql.types.SqlTypesTests; import java.time.ZoneId; import java.time.ZonedDateTime; @@ -28,11 +27,12 @@ import java.util.Objects; import static org.elasticsearch.xpack.ql.tree.Source.EMPTY; +import static org.elasticsearch.xpack.sql.SqlTestUtils.literal; public class CurrentDateTimeTests extends AbstractNodeTestCase { public static CurrentDateTime randomCurrentDateTime() { - return new CurrentDateTime(EMPTY, Literal.of(EMPTY, randomInt(9)), TestUtils.randomConfiguration()); + return new CurrentDateTime(EMPTY, literal(randomInt(9)), SqlTestUtils.randomConfiguration()); } @Override @@ -50,7 +50,7 @@ protected CurrentDateTime mutate(CurrentDateTime instance) { ZonedDateTime now = instance.configuration().now(); ZoneId mutatedZoneId = randomValueOtherThanMany(o -> Objects.equals(now.getOffset(), o.getRules().getOffset(now.toInstant())), ESTestCase::randomZone); - return new CurrentDateTime(instance.source(), Literal.of(EMPTY, randomInt(9)), TestUtils.randomConfiguration(mutatedZoneId)); + return new CurrentDateTime(instance.source(), literal(randomInt(9)), SqlTestUtils.randomConfiguration(mutatedZoneId)); } @Override @@ -63,20 +63,20 @@ public void testReplaceChildren() { public void testNanoPrecision() { ZonedDateTime zdt = ZonedDateTime.parse("2018-01-23T12:34:45.123456789Z"); - assertEquals(000_000_000, CurrentDateTime.nanoPrecision(zdt, Literal.of(EMPTY, 0)).getNano()); - assertEquals(100_000_000, CurrentDateTime.nanoPrecision(zdt, Literal.of(EMPTY, 1)).getNano()); - assertEquals(120_000_000, CurrentDateTime.nanoPrecision(zdt, Literal.of(EMPTY, 2)).getNano()); - assertEquals(123_000_000, CurrentDateTime.nanoPrecision(zdt, Literal.of(EMPTY, 3)).getNano()); - assertEquals(123_400_000, CurrentDateTime.nanoPrecision(zdt, Literal.of(EMPTY, 4)).getNano()); - assertEquals(123_450_000, CurrentDateTime.nanoPrecision(zdt, Literal.of(EMPTY, 5)).getNano()); - assertEquals(123_456_000, CurrentDateTime.nanoPrecision(zdt, Literal.of(EMPTY, 6)).getNano()); - assertEquals(123_456_700, CurrentDateTime.nanoPrecision(zdt, Literal.of(EMPTY, 7)).getNano()); - assertEquals(123_456_780, CurrentDateTime.nanoPrecision(zdt, Literal.of(EMPTY, 8)).getNano()); - assertEquals(123_456_789, CurrentDateTime.nanoPrecision(zdt, Literal.of(EMPTY, 9)).getNano()); + assertEquals(000_000_000, CurrentDateTime.nanoPrecision(zdt, literal(0)).getNano()); + assertEquals(100_000_000, CurrentDateTime.nanoPrecision(zdt, literal(1)).getNano()); + assertEquals(120_000_000, CurrentDateTime.nanoPrecision(zdt, literal(2)).getNano()); + assertEquals(123_000_000, CurrentDateTime.nanoPrecision(zdt, literal(3)).getNano()); + assertEquals(123_400_000, CurrentDateTime.nanoPrecision(zdt, literal(4)).getNano()); + assertEquals(123_450_000, CurrentDateTime.nanoPrecision(zdt, literal(5)).getNano()); + assertEquals(123_456_000, CurrentDateTime.nanoPrecision(zdt, literal(6)).getNano()); + assertEquals(123_456_700, CurrentDateTime.nanoPrecision(zdt, literal(7)).getNano()); + assertEquals(123_456_780, CurrentDateTime.nanoPrecision(zdt, literal(8)).getNano()); + assertEquals(123_456_789, CurrentDateTime.nanoPrecision(zdt, literal(9)).getNano()); } public void testDefaultPrecision() { - Configuration configuration = TestUtils.randomConfiguration(); + Configuration configuration = SqlTestUtils.randomConfiguration(); // null precision means default precision CurrentDateTime cdt = new CurrentDateTime(EMPTY, null, configuration); ZonedDateTime now = configuration.now(); @@ -89,9 +89,9 @@ public void testDefaultPrecision() { public void testInvalidPrecision() { SqlParser parser = new SqlParser(); IndexResolution indexResolution = IndexResolution.valid(new EsIndex("test", - TypesTests.loadMapping("mapping-multi-field-with-nested.json"))); + SqlTypesTests.loadMapping("mapping-multi-field-with-nested.json"))); - Analyzer analyzer = new Analyzer(TestUtils.TEST_CFG, new SqlFunctionRegistry(), indexResolution, new Verifier(new Metrics())); + Analyzer analyzer = new Analyzer(SqlTestUtils.TEST_CFG, new SqlFunctionRegistry(), indexResolution, new Verifier(new Metrics())); ParsingException e = expectThrows(ParsingException.class, () -> analyzer.analyze(parser.createStatement("SELECT CURRENT_TIMESTAMP(100000000000000)"), true)); assertEquals("line 1:27: invalid precision; [100000000000000] out of [integer] range", e.getMessage()); diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/CurrentTimeTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/CurrentTimeTests.java index 3c71b495ce0ec..b1fc816974712 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/CurrentTimeTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/CurrentTimeTests.java @@ -8,19 +8,18 @@ import org.elasticsearch.test.ESTestCase; import org.elasticsearch.xpack.ql.expression.Expression; -import org.elasticsearch.xpack.ql.expression.Literal; import org.elasticsearch.xpack.ql.index.EsIndex; import org.elasticsearch.xpack.ql.index.IndexResolution; import org.elasticsearch.xpack.ql.session.Configuration; import org.elasticsearch.xpack.ql.tree.AbstractNodeTestCase; -import org.elasticsearch.xpack.ql.type.TypesTests; -import org.elasticsearch.xpack.sql.TestUtils; +import org.elasticsearch.xpack.sql.SqlTestUtils; import org.elasticsearch.xpack.sql.analysis.analyzer.Analyzer; import org.elasticsearch.xpack.sql.analysis.analyzer.Verifier; import org.elasticsearch.xpack.sql.expression.function.SqlFunctionRegistry; import org.elasticsearch.xpack.sql.parser.ParsingException; import org.elasticsearch.xpack.sql.parser.SqlParser; import org.elasticsearch.xpack.sql.stats.Metrics; +import org.elasticsearch.xpack.sql.types.SqlTypesTests; import java.time.OffsetTime; import java.time.ZoneId; @@ -29,11 +28,12 @@ import java.util.Objects; import static org.elasticsearch.xpack.ql.tree.Source.EMPTY; +import static org.elasticsearch.xpack.sql.SqlTestUtils.literal; public class CurrentTimeTests extends AbstractNodeTestCase { public static CurrentTime randomCurrentTime() { - return new CurrentTime(EMPTY, Literal.of(EMPTY, randomInt(9)), TestUtils.randomConfiguration()); + return new CurrentTime(EMPTY, literal(randomInt(9)), SqlTestUtils.randomConfiguration()); } @Override @@ -51,7 +51,7 @@ protected CurrentTime mutate(CurrentTime instance) { ZonedDateTime now = instance.configuration().now(); ZoneId mutatedZoneId = randomValueOtherThanMany(o -> Objects.equals(now.getOffset(), o.getRules().getOffset(now.toInstant())), ESTestCase::randomZone); - return new CurrentTime(instance.source(), Literal.of(EMPTY, randomInt(9)), TestUtils.randomConfiguration(mutatedZoneId)); + return new CurrentTime(instance.source(), literal(randomInt(9)), SqlTestUtils.randomConfiguration(mutatedZoneId)); } @Override @@ -64,20 +64,20 @@ public void testReplaceChildren() { public void testNanoPrecision() { OffsetTime ot = OffsetTime.parse("12:34:45.123456789Z"); - assertEquals(000_000_000, CurrentTime.nanoPrecision(ot, Literal.of(EMPTY, 0)).getNano()); - assertEquals(100_000_000, CurrentTime.nanoPrecision(ot, Literal.of(EMPTY, 1)).getNano()); - assertEquals(120_000_000, CurrentTime.nanoPrecision(ot, Literal.of(EMPTY, 2)).getNano()); - assertEquals(123_000_000, CurrentTime.nanoPrecision(ot, Literal.of(EMPTY, 3)).getNano()); - assertEquals(123_400_000, CurrentTime.nanoPrecision(ot, Literal.of(EMPTY, 4)).getNano()); - assertEquals(123_450_000, CurrentTime.nanoPrecision(ot, Literal.of(EMPTY, 5)).getNano()); - assertEquals(123_456_000, CurrentTime.nanoPrecision(ot, Literal.of(EMPTY, 6)).getNano()); - assertEquals(123_456_700, CurrentTime.nanoPrecision(ot, Literal.of(EMPTY, 7)).getNano()); - assertEquals(123_456_780, CurrentTime.nanoPrecision(ot, Literal.of(EMPTY, 8)).getNano()); - assertEquals(123_456_789, CurrentTime.nanoPrecision(ot, Literal.of(EMPTY, 9)).getNano()); + assertEquals(000_000_000, CurrentTime.nanoPrecision(ot, literal(0)).getNano()); + assertEquals(100_000_000, CurrentTime.nanoPrecision(ot, literal(1)).getNano()); + assertEquals(120_000_000, CurrentTime.nanoPrecision(ot, literal(2)).getNano()); + assertEquals(123_000_000, CurrentTime.nanoPrecision(ot, literal(3)).getNano()); + assertEquals(123_400_000, CurrentTime.nanoPrecision(ot, literal(4)).getNano()); + assertEquals(123_450_000, CurrentTime.nanoPrecision(ot, literal(5)).getNano()); + assertEquals(123_456_000, CurrentTime.nanoPrecision(ot, literal(6)).getNano()); + assertEquals(123_456_700, CurrentTime.nanoPrecision(ot, literal(7)).getNano()); + assertEquals(123_456_780, CurrentTime.nanoPrecision(ot, literal(8)).getNano()); + assertEquals(123_456_789, CurrentTime.nanoPrecision(ot, literal(9)).getNano()); } public void testDefaultPrecision() { - Configuration configuration = TestUtils.randomConfiguration(); + Configuration configuration = SqlTestUtils.randomConfiguration(); // null precision means default precision CurrentTime ct = new CurrentTime(EMPTY, null, configuration); ZonedDateTime now = configuration.now(); @@ -90,9 +90,9 @@ public void testDefaultPrecision() { public void testInvalidPrecision() { SqlParser parser = new SqlParser(); IndexResolution indexResolution = IndexResolution.valid(new EsIndex("test", - TypesTests.loadMapping("mapping-multi-field-with-nested.json"))); + SqlTypesTests.loadMapping("mapping-multi-field-with-nested.json"))); - Analyzer analyzer = new Analyzer(TestUtils.TEST_CFG, new SqlFunctionRegistry(), indexResolution, new Verifier(new Metrics())); + Analyzer analyzer = new Analyzer(SqlTestUtils.TEST_CFG, new SqlFunctionRegistry(), indexResolution, new Verifier(new Metrics())); ParsingException e = expectThrows(ParsingException.class, () -> analyzer.analyze(parser.createStatement("SELECT CURRENT_TIME(100000000000000)"), true)); assertEquals("line 1:22: invalid precision; [100000000000000] out of [integer] range", e.getMessage()); diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/DayOfYearTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/DayOfYearTests.java index 44a7ca59e09a1..4a0abd148f8d6 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/DayOfYearTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/function/scalar/datetime/DayOfYearTests.java @@ -8,7 +8,7 @@ import org.elasticsearch.test.ESTestCase; import org.elasticsearch.xpack.ql.expression.Literal; import org.elasticsearch.xpack.ql.tree.Source; -import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import java.time.ZoneId; @@ -28,6 +28,6 @@ private Object extract(Object value, ZoneId zoneId) { } private DayOfYear build(Object value, ZoneId zoneId) { - return new DayOfYear(Source.EMPTY, new Literal(Source.EMPTY, value, DataType.DATETIME), zoneId); + return new DayOfYear(Source.EMPTY, new Literal(Source.EMPTY, value, DataTypes.DATETIME), zoneId); } } diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/function/scalar/geo/GeoProcessorTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/function/scalar/geo/GeoProcessorTests.java index 8382e2648af38..ba3f81ef538b1 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/function/scalar/geo/GeoProcessorTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/function/scalar/geo/GeoProcessorTests.java @@ -7,9 +7,9 @@ import org.elasticsearch.common.io.stream.Writeable.Reader; import org.elasticsearch.test.AbstractWireSerializingTestCase; -import org.elasticsearch.xpack.ql.expression.function.scalar.geo.GeoShape; import org.elasticsearch.xpack.sql.SqlIllegalArgumentException; import org.elasticsearch.xpack.sql.expression.function.scalar.geo.GeoProcessor.GeoOperation; +import org.elasticsearch.xpack.sql.expression.literal.geo.GeoShape; import java.io.IOException; diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/function/scalar/geo/StDistanceProcessorTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/function/scalar/geo/StDistanceProcessorTests.java index 0016c67d99c5e..59f26970e64aa 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/function/scalar/geo/StDistanceProcessorTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/function/scalar/geo/StDistanceProcessorTests.java @@ -10,13 +10,13 @@ import org.elasticsearch.common.io.stream.Writeable; import org.elasticsearch.test.AbstractWireSerializingTestCase; import org.elasticsearch.xpack.ql.expression.Literal; -import org.elasticsearch.xpack.ql.expression.function.scalar.geo.GeoShape; import org.elasticsearch.xpack.ql.expression.gen.processor.ChainingProcessor; import org.elasticsearch.xpack.ql.expression.gen.processor.ConstantProcessor; import org.elasticsearch.xpack.ql.expression.gen.processor.Processor; import org.elasticsearch.xpack.ql.type.DataTypes; import org.elasticsearch.xpack.sql.SqlIllegalArgumentException; import org.elasticsearch.xpack.sql.expression.function.scalar.Processors; +import org.elasticsearch.xpack.sql.expression.literal.geo.GeoShape; import static org.elasticsearch.xpack.ql.tree.Source.EMPTY; import static org.hamcrest.Matchers.instanceOf; diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/function/scalar/geo/StWkttosqlProcessorTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/function/scalar/geo/StWkttosqlProcessorTests.java index 86a8b75131796..76e3ab5228356 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/function/scalar/geo/StWkttosqlProcessorTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/function/scalar/geo/StWkttosqlProcessorTests.java @@ -7,7 +7,7 @@ import org.elasticsearch.test.ESTestCase; import org.elasticsearch.xpack.ql.QlIllegalArgumentException; -import org.elasticsearch.xpack.ql.expression.function.scalar.geo.GeoShape; +import org.elasticsearch.xpack.sql.expression.literal.geo.GeoShape; import static org.hamcrest.Matchers.instanceOf; diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/BinaryMathProcessorTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/BinaryMathProcessorTests.java index 45704b2c07573..c6314f28e272b 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/BinaryMathProcessorTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/function/scalar/math/BinaryMathProcessorTests.java @@ -12,6 +12,7 @@ import org.elasticsearch.xpack.ql.expression.gen.processor.ConstantProcessor; import org.elasticsearch.xpack.ql.expression.gen.processor.Processor; import org.elasticsearch.xpack.sql.SqlIllegalArgumentException; +import org.elasticsearch.xpack.sql.SqlTestUtils; import org.elasticsearch.xpack.sql.expression.function.scalar.Processors; import static org.elasticsearch.xpack.ql.tree.Source.EMPTY; @@ -118,6 +119,6 @@ public void testHandleNull() { } private static Literal l(Object value) { - return Literal.of(EMPTY, value); + return SqlTestUtils.literal(value); } } \ No newline at end of file diff --git a/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/expression/literal/IntervalsTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/literal/interval/IntervalsTests.java similarity index 88% rename from x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/expression/literal/IntervalsTests.java rename to x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/literal/interval/IntervalsTests.java index 6a04242f4ad3a..3cb8143162ad1 100644 --- a/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/expression/literal/IntervalsTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/literal/interval/IntervalsTests.java @@ -4,13 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ -package org.elasticsearch.xpack.ql.expression.literal; +package org.elasticsearch.xpack.sql.expression.literal.interval; import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.xpack.ql.ParsingException; -import org.elasticsearch.xpack.ql.expression.literal.Intervals.TimeUnit; +import org.elasticsearch.xpack.sql.expression.literal.interval.Intervals.TimeUnit; import java.time.Duration; import java.time.Period; @@ -20,23 +20,23 @@ import static java.lang.String.format; import static java.util.stream.Collectors.toList; -import static org.elasticsearch.xpack.ql.expression.literal.Intervals.intervalType; -import static org.elasticsearch.xpack.ql.expression.literal.Intervals.of; -import static org.elasticsearch.xpack.ql.expression.literal.Intervals.parseInterval; import static org.elasticsearch.xpack.ql.tree.Source.EMPTY; -import static org.elasticsearch.xpack.ql.type.DataType.INTERVAL_DAY; -import static org.elasticsearch.xpack.ql.type.DataType.INTERVAL_DAY_TO_HOUR; -import static org.elasticsearch.xpack.ql.type.DataType.INTERVAL_DAY_TO_MINUTE; -import static org.elasticsearch.xpack.ql.type.DataType.INTERVAL_DAY_TO_SECOND; -import static org.elasticsearch.xpack.ql.type.DataType.INTERVAL_HOUR; -import static org.elasticsearch.xpack.ql.type.DataType.INTERVAL_HOUR_TO_MINUTE; -import static org.elasticsearch.xpack.ql.type.DataType.INTERVAL_HOUR_TO_SECOND; -import static org.elasticsearch.xpack.ql.type.DataType.INTERVAL_MINUTE; -import static org.elasticsearch.xpack.ql.type.DataType.INTERVAL_MINUTE_TO_SECOND; -import static org.elasticsearch.xpack.ql.type.DataType.INTERVAL_MONTH; -import static org.elasticsearch.xpack.ql.type.DataType.INTERVAL_SECOND; -import static org.elasticsearch.xpack.ql.type.DataType.INTERVAL_YEAR; -import static org.elasticsearch.xpack.ql.type.DataType.INTERVAL_YEAR_TO_MONTH; +import static org.elasticsearch.xpack.sql.expression.literal.interval.Intervals.intervalType; +import static org.elasticsearch.xpack.sql.expression.literal.interval.Intervals.of; +import static org.elasticsearch.xpack.sql.expression.literal.interval.Intervals.parseInterval; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.INTERVAL_DAY; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.INTERVAL_DAY_TO_HOUR; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.INTERVAL_DAY_TO_MINUTE; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.INTERVAL_DAY_TO_SECOND; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.INTERVAL_HOUR; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.INTERVAL_HOUR_TO_MINUTE; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.INTERVAL_HOUR_TO_SECOND; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.INTERVAL_MINUTE; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.INTERVAL_MINUTE_TO_SECOND; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.INTERVAL_MONTH; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.INTERVAL_SECOND; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.INTERVAL_YEAR; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.INTERVAL_YEAR_TO_MONTH; public class IntervalsTests extends ESTestCase { diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/parser/ParameterTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/parser/ParameterTests.java index 195bf35ada227..cb3784a1fa916 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/parser/ParameterTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/parser/ParameterTests.java @@ -8,11 +8,10 @@ import org.elasticsearch.test.ESTestCase; import org.elasticsearch.xpack.ql.expression.Expression; import org.elasticsearch.xpack.ql.expression.Literal; -import org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.Add; -import org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.Mul; -import org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.Sub; import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.Equals; -import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.sql.expression.predicate.operator.arithmetic.Add; +import org.elasticsearch.xpack.sql.expression.predicate.operator.arithmetic.Mul; +import org.elasticsearch.xpack.sql.expression.predicate.operator.arithmetic.Sub; import org.elasticsearch.xpack.sql.parser.ParsingException; import org.elasticsearch.xpack.sql.parser.SqlParser; import org.elasticsearch.xpack.sql.proto.SqlTypedParamValue; @@ -20,34 +19,33 @@ import java.util.Arrays; import java.util.Collections; +import static org.elasticsearch.xpack.ql.type.DataTypes.KEYWORD; +import static org.elasticsearch.xpack.ql.type.DataTypes.LONG; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.instanceOf; - public class ParameterTests extends ESTestCase { public void testSingleParameter() { Expression expression = new SqlParser().createExpression("a = \n?", Collections.singletonList( - new SqlTypedParamValue(DataType.KEYWORD.typeName(), "foo") + new SqlTypedParamValue(KEYWORD.typeName(), "foo") )); logger.info(expression); assertThat(expression, instanceOf(Equals.class)); Expression right = ((Equals) expression).right(); assertThat(right, instanceOf(Literal.class)); Literal param = (Literal) right; - assertThat(param.dataType(), equalTo(DataType.KEYWORD)); - assertThat(param.dataType(), equalTo(DataType.KEYWORD)); + assertThat(param.dataType(), equalTo(KEYWORD)); + assertThat(param.dataType(), equalTo(KEYWORD)); assertThat(param.value(), equalTo("foo")); } public void testMultipleParameters() { Expression expression = new SqlParser().createExpression("(? + ? * ?) - ?", Arrays.asList( - new SqlTypedParamValue(DataType.LONG.typeName(), 1L), - new SqlTypedParamValue(DataType.LONG.typeName(), 2L), - new SqlTypedParamValue(DataType.LONG.typeName(), 3L), - new SqlTypedParamValue(DataType.LONG.typeName(), 4L) + new SqlTypedParamValue(LONG.typeName(), 1L), new SqlTypedParamValue(LONG.typeName(), 2L), + new SqlTypedParamValue(LONG.typeName(), 3L), new SqlTypedParamValue(LONG.typeName(), 4L) )); assertThat(expression, instanceOf(Sub.class)); Sub sub = (Sub) expression; @@ -64,9 +62,8 @@ public void testMultipleParameters() { public void testNotEnoughParameters() { ParsingException ex = expectThrows(ParsingException.class, () -> new SqlParser().createExpression("(? + ? * ?) - ?", Arrays.asList( - new SqlTypedParamValue(DataType.LONG.typeName(), 1L), - new SqlTypedParamValue(DataType.LONG.typeName(), 2L), - new SqlTypedParamValue(DataType.LONG.typeName(), 3L) + new SqlTypedParamValue(LONG.typeName(), 1L), new SqlTypedParamValue(LONG.typeName(), 2L), + new SqlTypedParamValue(LONG.typeName(), 3L) ))); assertThat(ex.getMessage(), containsString("Not enough actual parameters")); } diff --git a/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/expression/predicate/conditional/CaseTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/CaseTests.java similarity index 81% rename from x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/expression/predicate/conditional/CaseTests.java rename to x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/CaseTests.java index 1d6477b0ebf05..173650c66bfd2 100644 --- a/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/expression/predicate/conditional/CaseTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/CaseTests.java @@ -3,7 +3,7 @@ * 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.ql.expression.predicate.conditional; +package org.elasticsearch.xpack.sql.expression.predicate.conditional; import org.elasticsearch.xpack.ql.expression.Expression; import org.elasticsearch.xpack.ql.expression.Expression.TypeResolution; @@ -14,7 +14,6 @@ import org.elasticsearch.xpack.ql.tree.NodeSubclassTests; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.tree.SourceTests; -import org.elasticsearch.xpack.ql.type.DataType; import java.util.ArrayList; import java.util.Arrays; @@ -26,6 +25,9 @@ import static org.elasticsearch.xpack.ql.expression.function.scalar.FunctionTestUtils.randomStringLiteral; import static org.elasticsearch.xpack.ql.tree.Source.EMPTY; import static org.elasticsearch.xpack.ql.tree.SourceTests.randomSource; +import static org.elasticsearch.xpack.ql.type.DataTypes.KEYWORD; +import static org.elasticsearch.xpack.ql.type.DataTypes.NULL; +import static org.elasticsearch.xpack.sql.SqlTestUtils.literal; /** * Needed to override tests in {@link NodeSubclassTests} as Case is special since its children are not usual @@ -84,40 +86,39 @@ public void testDataTypes() { // ELSE 'default' // END Case c = new Case(EMPTY, Arrays.asList( - new IfConditional(EMPTY, new Equals(EMPTY, Literal.of(EMPTY, 1), Literal.of(EMPTY, 1)), Literal.NULL), - Literal.of(EMPTY, "default"))); - assertEquals(DataType.KEYWORD, c.dataType()); + new IfConditional(EMPTY, new Equals(EMPTY, literal(1), literal(1)), Literal.NULL), literal("default"))); + assertEquals(KEYWORD, c.dataType()); // CASE WHEN 1 = 1 THEN 'foo' // ELSE NULL // END c = new Case(EMPTY, Arrays.asList( - new IfConditional(EMPTY, new Equals(EMPTY, Literal.of(EMPTY, 1), Literal.of(EMPTY, 1)), Literal.of(EMPTY, "foo")), + new IfConditional(EMPTY, new Equals(EMPTY, literal(1), literal(1)), literal("foo")), Literal.NULL)); - assertEquals(DataType.KEYWORD, c.dataType()); + assertEquals(KEYWORD, c.dataType()); // CASE WHEN 1 = 1 THEN NULL // ELSE NULL // END c = new Case(EMPTY, Arrays.asList( - new IfConditional(EMPTY, new Equals(EMPTY, Literal.of(EMPTY, 1), Literal.of(EMPTY, 1)), Literal.NULL), + new IfConditional(EMPTY, new Equals(EMPTY, literal(1), literal(1)), Literal.NULL), Literal.NULL)); - assertEquals(DataType.NULL, c.dataType()); + assertEquals(NULL, c.dataType()); // CASE WHEN 1 = 1 THEN NULL // WHEN 2 = 2 THEN 'foo' // ELSE NULL // END c = new Case(EMPTY, Arrays.asList( - new IfConditional(EMPTY, new Equals(EMPTY, Literal.of(EMPTY, 1), Literal.of(EMPTY, 1)), Literal.NULL), - new IfConditional(EMPTY, new Equals(EMPTY, Literal.of(EMPTY, 2), Literal.of(EMPTY, 2)), Literal.of(EMPTY, "foo")), + new IfConditional(EMPTY, new Equals(EMPTY, literal(1), literal(1)), Literal.NULL), + new IfConditional(EMPTY, new Equals(EMPTY, literal(2), literal(2)), literal("foo")), Literal.NULL)); - assertEquals(DataType.KEYWORD, c.dataType()); + assertEquals(KEYWORD, c.dataType()); } public void testAllConditionsFolded() { - Case c = new Case(EMPTY, Collections.singletonList(Literal.of(EMPTY, "foo"))); - assertEquals(DataType.KEYWORD, c.dataType()); + Case c = new Case(EMPTY, Collections.singletonList(literal("foo"))); + assertEquals(KEYWORD, c.dataType()); assertEquals(TypeResolution.TYPE_RESOLVED, c.typeResolved()); assertNotNull(c.info()); } diff --git a/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/expression/predicate/conditional/IifTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/IifTests.java similarity index 92% rename from x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/expression/predicate/conditional/IifTests.java rename to x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/IifTests.java index 778b775061412..e861dc0de9e25 100644 --- a/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/expression/predicate/conditional/IifTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/predicate/conditional/IifTests.java @@ -3,17 +3,17 @@ * 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.ql.expression.predicate.conditional; +package org.elasticsearch.xpack.sql.expression.predicate.conditional; import org.elasticsearch.xpack.ql.expression.Expression; -import org.elasticsearch.xpack.ql.expression.Literal; import org.elasticsearch.xpack.ql.expression.function.scalar.FunctionTestUtils; import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.Equals; import org.elasticsearch.xpack.ql.tree.AbstractNodeTestCase; import org.elasticsearch.xpack.ql.tree.NodeSubclassTests; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.tree.SourceTests; -import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; +import org.elasticsearch.xpack.sql.SqlTestUtils; import java.util.ArrayList; import java.util.Arrays; @@ -75,8 +75,8 @@ public void testReplaceChildren() { } public void testConditionFolded() { - Iif iif = new Iif(EMPTY, Collections.singletonList(Literal.of(EMPTY, "foo"))); - assertEquals(DataType.KEYWORD, iif.dataType()); + Iif iif = new Iif(EMPTY, Collections.singletonList(SqlTestUtils.literal("foo"))); + assertEquals(DataTypes.KEYWORD, iif.dataType()); assertEquals(Expression.TypeResolution.TYPE_RESOLVED, iif.typeResolved()); assertNotNull(iif.info()); } diff --git a/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/expression/predicate/nulls/CheckNullProcessorTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/predicate/nulls/CheckNullProcessorTests.java similarity index 94% rename from x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/expression/predicate/nulls/CheckNullProcessorTests.java rename to x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/predicate/nulls/CheckNullProcessorTests.java index 912b1b025f8e6..3a6a9c5f9ae12 100644 --- a/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/expression/predicate/nulls/CheckNullProcessorTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/predicate/nulls/CheckNullProcessorTests.java @@ -3,7 +3,7 @@ * 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.ql.expression.predicate.nulls; +package org.elasticsearch.xpack.sql.expression.predicate.nulls; import org.elasticsearch.common.io.stream.NamedWriteableRegistry; import org.elasticsearch.common.io.stream.Writeable.Reader; @@ -11,6 +11,7 @@ import org.elasticsearch.xpack.ql.expression.gen.processor.ConstantProcessor; import org.elasticsearch.xpack.ql.expression.gen.processor.Processor; import org.elasticsearch.xpack.ql.expression.processor.Processors; +import org.elasticsearch.xpack.sql.expression.predicate.nulls.CheckNullProcessor; public class CheckNullProcessorTests extends AbstractWireSerializingTestCase { diff --git a/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/expression/predicate/operator/arithmetic/BinaryArithmeticTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/predicate/operator/arithmetic/SqlBinaryArithmeticTests.java similarity index 91% rename from x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/expression/predicate/operator/arithmetic/BinaryArithmeticTests.java rename to x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/predicate/operator/arithmetic/SqlBinaryArithmeticTests.java index 6ba08c3933d90..3b3f6c003732f 100644 --- a/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/expression/predicate/operator/arithmetic/BinaryArithmeticTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/predicate/operator/arithmetic/SqlBinaryArithmeticTests.java @@ -4,15 +4,16 @@ * you may not use this file except in compliance with the Elastic License. */ -package org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic; +package org.elasticsearch.xpack.sql.expression.predicate.operator.arithmetic; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.xpack.ql.QlIllegalArgumentException; import org.elasticsearch.xpack.ql.expression.Literal; -import org.elasticsearch.xpack.ql.expression.literal.IntervalDayTime; -import org.elasticsearch.xpack.ql.expression.literal.IntervalYearMonth; import org.elasticsearch.xpack.ql.type.DataType; import org.elasticsearch.xpack.ql.util.DateUtils; +import org.elasticsearch.xpack.sql.expression.literal.interval.IntervalDayTime; +import org.elasticsearch.xpack.sql.expression.literal.interval.IntervalYearMonth; +import org.elasticsearch.xpack.sql.type.SqlDataTypes; import java.time.Duration; import java.time.OffsetTime; @@ -22,14 +23,14 @@ import static org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.Arithmetics.mod; import static org.elasticsearch.xpack.ql.tree.Source.EMPTY; -import static org.elasticsearch.xpack.ql.type.DataType.INTERVAL_DAY; -import static org.elasticsearch.xpack.ql.type.DataType.INTERVAL_DAY_TO_HOUR; -import static org.elasticsearch.xpack.ql.type.DataType.INTERVAL_HOUR; -import static org.elasticsearch.xpack.ql.type.DataType.INTERVAL_MONTH; -import static org.elasticsearch.xpack.ql.type.DataType.INTERVAL_YEAR; -import static org.elasticsearch.xpack.ql.type.DataType.INTERVAL_YEAR_TO_MONTH; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.INTERVAL_DAY; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.INTERVAL_DAY_TO_HOUR; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.INTERVAL_HOUR; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.INTERVAL_MONTH; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.INTERVAL_YEAR; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.INTERVAL_YEAR_TO_MONTH; -public class BinaryArithmeticTests extends ESTestCase { +public class SqlBinaryArithmeticTests extends ESTestCase { public void testAddNumbers() { assertEquals(Long.valueOf(3), add(1L, 2L)); @@ -289,12 +290,12 @@ private static T mul(Object l, Object r) { } private static Literal L(Object value) { - return Literal.of(EMPTY, value); + return value instanceof Literal ? (Literal) value : new Literal(EMPTY, value, SqlDataTypes.fromJava(value)); } private static Literal interval(TemporalAmount value, DataType intervalType) { Object i = value instanceof Period ? new IntervalYearMonth((Period) value, intervalType) : new IntervalDayTime((Duration) value, intervalType); - return Literal.of(EMPTY, i); + return new Literal(EMPTY, i, SqlDataTypes.fromJava(i)); } -} +} \ No newline at end of file diff --git a/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/expression/predicate/operator/comparison/InProcessorTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/predicate/operator/comparison/InProcessorTests.java similarity index 87% rename from x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/expression/predicate/operator/comparison/InProcessorTests.java rename to x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/predicate/operator/comparison/InProcessorTests.java index d35feadd1eedf..02233cc1f4c90 100644 --- a/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/expression/predicate/operator/comparison/InProcessorTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/predicate/operator/comparison/InProcessorTests.java @@ -3,14 +3,17 @@ * 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.ql.expression.predicate.operator.comparison; +package org.elasticsearch.xpack.sql.expression.predicate.operator.comparison; import org.elasticsearch.common.io.stream.NamedWriteableRegistry; import org.elasticsearch.common.io.stream.Writeable.Reader; import org.elasticsearch.test.AbstractWireSerializingTestCase; +import org.elasticsearch.xpack.ql.TestUtils; import org.elasticsearch.xpack.ql.expression.Literal; import org.elasticsearch.xpack.ql.expression.gen.processor.ConstantProcessor; import org.elasticsearch.xpack.ql.expression.processor.Processors; +import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.In; +import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.InProcessor; import java.util.Arrays; @@ -58,6 +61,6 @@ public void testHandleNullOnRightValue() { } private static Literal L(Object value) { - return Literal.of(EMPTY, value); + return TestUtils.of(EMPTY, value); } } diff --git a/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/expression/predicate/operator/comparison/InTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/predicate/operator/comparison/InTests.java similarity index 86% rename from x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/expression/predicate/operator/comparison/InTests.java rename to x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/predicate/operator/comparison/InTests.java index 4faf583279e8e..4d437edd00b69 100644 --- a/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/expression/predicate/operator/comparison/InTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/expression/predicate/operator/comparison/InTests.java @@ -3,10 +3,12 @@ * 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.ql.expression.predicate.operator.comparison; +package org.elasticsearch.xpack.sql.expression.predicate.operator.comparison; import org.elasticsearch.test.ESTestCase; +import org.elasticsearch.xpack.ql.TestUtils; import org.elasticsearch.xpack.ql.expression.Literal; +import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.In; import java.util.Arrays; @@ -45,6 +47,6 @@ public void testHandleNullsOnRightValue() { } private static Literal L(Object value) { - return Literal.of(EMPTY, value); + return TestUtils.of(EMPTY, value); } } diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/optimizer/OptimizerRunTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/optimizer/OptimizerRunTests.java index 91737e05f5784..4a54a1e48b78b 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/optimizer/OptimizerRunTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/optimizer/OptimizerRunTests.java @@ -11,12 +11,12 @@ import org.elasticsearch.xpack.ql.index.IndexResolution; import org.elasticsearch.xpack.ql.plan.logical.LogicalPlan; import org.elasticsearch.xpack.ql.type.EsField; -import org.elasticsearch.xpack.ql.type.TypesTests; -import org.elasticsearch.xpack.sql.TestUtils; +import org.elasticsearch.xpack.sql.SqlTestUtils; import org.elasticsearch.xpack.sql.analysis.analyzer.Analyzer; import org.elasticsearch.xpack.sql.analysis.analyzer.Verifier; import org.elasticsearch.xpack.sql.parser.SqlParser; import org.elasticsearch.xpack.sql.stats.Metrics; +import org.elasticsearch.xpack.sql.types.SqlTypesTests; import java.util.Map; @@ -32,11 +32,11 @@ public OptimizerRunTests() { parser = new SqlParser(); functionRegistry = new FunctionRegistry(); - Map mapping = TypesTests.loadMapping("mapping-multi-field-variation.json"); + Map mapping = SqlTypesTests.loadMapping("mapping-multi-field-variation.json"); EsIndex test = new EsIndex("test", mapping); getIndexResult = IndexResolution.valid(test); - analyzer = new Analyzer(TestUtils.TEST_CFG, functionRegistry, getIndexResult, new Verifier(new Metrics())); + analyzer = new Analyzer(SqlTestUtils.TEST_CFG, functionRegistry, getIndexResult, new Verifier(new Metrics())); optimizer = new Optimizer(); } diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/optimizer/OptimizerTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/optimizer/OptimizerTests.java index 860b759bb8f3f..f3e62ca4e69a3 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/optimizer/OptimizerTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/optimizer/OptimizerTests.java @@ -12,7 +12,6 @@ import org.elasticsearch.xpack.ql.expression.Expression.TypeResolution; import org.elasticsearch.xpack.ql.expression.Expressions; import org.elasticsearch.xpack.ql.expression.FieldAttribute; -import org.elasticsearch.xpack.ql.expression.Foldables; import org.elasticsearch.xpack.ql.expression.Literal; import org.elasticsearch.xpack.ql.expression.NamedExpression; import org.elasticsearch.xpack.ql.expression.Nullability; @@ -24,16 +23,6 @@ import org.elasticsearch.xpack.ql.expression.predicate.BinaryOperator; import org.elasticsearch.xpack.ql.expression.predicate.Predicates; import org.elasticsearch.xpack.ql.expression.predicate.Range; -import org.elasticsearch.xpack.ql.expression.predicate.conditional.ArbitraryConditionalFunction; -import org.elasticsearch.xpack.ql.expression.predicate.conditional.Case; -import org.elasticsearch.xpack.ql.expression.predicate.conditional.Coalesce; -import org.elasticsearch.xpack.ql.expression.predicate.conditional.ConditionalFunction; -import org.elasticsearch.xpack.ql.expression.predicate.conditional.Greatest; -import org.elasticsearch.xpack.ql.expression.predicate.conditional.IfConditional; -import org.elasticsearch.xpack.ql.expression.predicate.conditional.IfNull; -import org.elasticsearch.xpack.ql.expression.predicate.conditional.Iif; -import org.elasticsearch.xpack.ql.expression.predicate.conditional.Least; -import org.elasticsearch.xpack.ql.expression.predicate.conditional.NullIf; import org.elasticsearch.xpack.ql.expression.predicate.fulltext.FullTextPredicate; import org.elasticsearch.xpack.ql.expression.predicate.fulltext.MatchQueryPredicate; import org.elasticsearch.xpack.ql.expression.predicate.fulltext.MultiMatchQueryPredicate; @@ -42,17 +31,9 @@ import org.elasticsearch.xpack.ql.expression.predicate.logical.BinaryLogic; import org.elasticsearch.xpack.ql.expression.predicate.logical.Not; import org.elasticsearch.xpack.ql.expression.predicate.logical.Or; -import org.elasticsearch.xpack.ql.expression.predicate.nulls.IsNotNull; -import org.elasticsearch.xpack.ql.expression.predicate.nulls.IsNull; -import org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.Add; -import org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.Div; -import org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.Mod; -import org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.Mul; -import org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.Sub; import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.Equals; import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.GreaterThan; import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.GreaterThanOrEqual; -import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.In; import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.LessThan; import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.LessThanOrEqual; import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.NotEquals; @@ -70,10 +51,12 @@ import org.elasticsearch.xpack.ql.tree.NodeInfo; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import org.elasticsearch.xpack.ql.type.EsField; import org.elasticsearch.xpack.ql.util.CollectionUtils; import org.elasticsearch.xpack.ql.util.StringUtils; import org.elasticsearch.xpack.sql.analysis.analyzer.Analyzer.PruneSubqueryAliases; +import org.elasticsearch.xpack.sql.expression.Foldables; import org.elasticsearch.xpack.sql.expression.function.aggregate.Avg; import org.elasticsearch.xpack.sql.expression.function.aggregate.ExtendedStats; import org.elasticsearch.xpack.sql.expression.function.aggregate.First; @@ -106,6 +89,24 @@ import org.elasticsearch.xpack.sql.expression.function.scalar.string.Ascii; import org.elasticsearch.xpack.sql.expression.function.scalar.string.Concat; import org.elasticsearch.xpack.sql.expression.function.scalar.string.Repeat; +import org.elasticsearch.xpack.sql.expression.predicate.conditional.ArbitraryConditionalFunction; +import org.elasticsearch.xpack.sql.expression.predicate.conditional.Case; +import org.elasticsearch.xpack.sql.expression.predicate.conditional.Coalesce; +import org.elasticsearch.xpack.sql.expression.predicate.conditional.ConditionalFunction; +import org.elasticsearch.xpack.sql.expression.predicate.conditional.Greatest; +import org.elasticsearch.xpack.sql.expression.predicate.conditional.IfConditional; +import org.elasticsearch.xpack.sql.expression.predicate.conditional.IfNull; +import org.elasticsearch.xpack.sql.expression.predicate.conditional.Iif; +import org.elasticsearch.xpack.sql.expression.predicate.conditional.Least; +import org.elasticsearch.xpack.sql.expression.predicate.conditional.NullIf; +import org.elasticsearch.xpack.sql.expression.predicate.nulls.IsNotNull; +import org.elasticsearch.xpack.sql.expression.predicate.nulls.IsNull; +import org.elasticsearch.xpack.sql.expression.predicate.operator.arithmetic.Add; +import org.elasticsearch.xpack.sql.expression.predicate.operator.arithmetic.Div; +import org.elasticsearch.xpack.sql.expression.predicate.operator.arithmetic.Mod; +import org.elasticsearch.xpack.sql.expression.predicate.operator.arithmetic.Mul; +import org.elasticsearch.xpack.sql.expression.predicate.operator.arithmetic.Sub; +import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.In; import org.elasticsearch.xpack.sql.optimizer.Optimizer.BinaryComparisonSimplification; import org.elasticsearch.xpack.sql.optimizer.Optimizer.BooleanLiteralsOnTheRight; import org.elasticsearch.xpack.sql.optimizer.Optimizer.BooleanSimplification; @@ -141,8 +142,15 @@ import static org.elasticsearch.xpack.ql.expression.Literal.FALSE; import static org.elasticsearch.xpack.ql.expression.Literal.NULL; import static org.elasticsearch.xpack.ql.expression.Literal.TRUE; -import static org.elasticsearch.xpack.ql.expression.Literal.of; import static org.elasticsearch.xpack.ql.tree.Source.EMPTY; +import static org.elasticsearch.xpack.ql.type.DataTypes.BOOLEAN; +import static org.elasticsearch.xpack.ql.type.DataTypes.BYTE; +import static org.elasticsearch.xpack.ql.type.DataTypes.DATETIME; +import static org.elasticsearch.xpack.ql.type.DataTypes.INTEGER; +import static org.elasticsearch.xpack.ql.type.DataTypes.KEYWORD; +import static org.elasticsearch.xpack.ql.type.DataTypes.TEXT; +import static org.elasticsearch.xpack.sql.SqlTestUtils.literal; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.DATE; import static org.elasticsearch.xpack.sql.util.DateUtils.UTC; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.is; @@ -184,7 +192,7 @@ public Nullability nullable() { @Override public DataType dataType() { - return DataType.BOOLEAN; + return BOOLEAN; } @Override @@ -208,7 +216,7 @@ private static LogicalPlan FROM() { } private static Literal L(Object value) { - return of(EMPTY, value); + return literal(value); } private static Alias a(String name, Expression e) { @@ -220,7 +228,7 @@ private static FieldAttribute getFieldAttribute() { } private static FieldAttribute getFieldAttribute(String name) { - return new FieldAttribute(EMPTY, name, new EsField(name + "f", DataType.INTEGER, emptyMap(), true)); + return new FieldAttribute(EMPTY, name, new EsField(name + "f", INTEGER, emptyMap(), true)); } public void testPruneSubqueryAliases() { @@ -359,21 +367,21 @@ public void testConstantNot() { public void testConstantFoldingLikes() { assertEquals(TRUE, - new ConstantFolding().rule(new Like(EMPTY, of(EMPTY, "test_emp"), new LikePattern("test%", (char) 0))) + new ConstantFolding().rule(new Like(EMPTY, literal("test_emp"), new LikePattern("test%", (char) 0))) .canonical()); assertEquals(TRUE, - new ConstantFolding().rule(new RLike(EMPTY, of(EMPTY, "test_emp"), "test.emp")).canonical()); + new ConstantFolding().rule(new RLike(EMPTY, literal("test_emp"), "test.emp")).canonical()); } public void testConstantFoldingDatetime() { - Expression cast = new Cast(EMPTY, of(EMPTY, "2018-01-19T10:23:27Z"), DataType.DATETIME); + Expression cast = new Cast(EMPTY, literal("2018-01-19T10:23:27Z"), DATETIME); assertEquals(2018, foldFunction(new Year(EMPTY, cast, UTC))); assertEquals(1, foldFunction(new MonthOfYear(EMPTY, cast, UTC))); assertEquals(19, foldFunction(new DayOfMonth(EMPTY, cast, UTC))); assertEquals(19, foldFunction(new DayOfYear(EMPTY, cast, UTC))); assertEquals(3, foldFunction(new IsoWeekOfYear(EMPTY, cast, UTC))); assertNull(foldFunction( - new IsoWeekOfYear(EMPTY, new Literal(EMPTY, null, DataType.NULL), UTC))); + new IsoWeekOfYear(EMPTY, new Literal(EMPTY, null, DataTypes.NULL), UTC))); } public void testConstantFoldingIn() { @@ -392,7 +400,7 @@ public void testConstantFoldingIn_LeftValueNotFoldable() { assertEquals(1, p.projections().size()); Alias a = (Alias) p.projections().get(0); In i = (In) a.child(); - assertThat(Foldables.valuesOf(i.list(), DataType.INTEGER), contains(1 ,2 ,3 ,4)); + assertThat(Foldables.valuesOf(i.list(), INTEGER), contains(1, 2, 3, 4)); } public void testConstantFoldingIn_RightValueIsNull() { @@ -443,7 +451,7 @@ public void testNullFoldingIsNull() { public void testNullFoldingIsNullWithCast() { FoldNull foldNull = new FoldNull(); - Cast cast = new Cast(EMPTY, L("foo"), DataType.DATE); + Cast cast = new Cast(EMPTY, L("foo"), DATE); IsNull isNull = new IsNull(EMPTY, cast); final IsNull isNullOpt = (IsNull) foldNull.rule(isNull); assertEquals(isNull, isNullOpt); @@ -452,7 +460,7 @@ public void testNullFoldingIsNullWithCast() { () -> isNullOpt.asPipe().asProcessor().process(null)); assertEquals("cannot cast [foo] to [date]: Text 'foo' could not be parsed at index 0", sqlIAE.getMessage()); - isNull = new IsNull(EMPTY, new Cast(EMPTY, NULL, randomFrom(DataType.values()))); + isNull = new IsNull(EMPTY, new Cast(EMPTY, NULL, randomFrom(DataTypes.types()))); assertTrue((Boolean) ((IsNull) foldNull.rule(isNull)).asPipe().asProcessor().process(null)); } @@ -461,7 +469,7 @@ public void testNullFoldingIsNotNull() { assertEquals(true, foldNull.rule(new IsNotNull(EMPTY, TRUE)).fold()); assertEquals(false, foldNull.rule(new IsNotNull(EMPTY, NULL)).fold()); - Cast cast = new Cast(EMPTY, L("foo"), DataType.DATE); + Cast cast = new Cast(EMPTY, L("foo"), DATE); IsNotNull isNotNull = new IsNotNull(EMPTY, cast); assertEquals(isNotNull, foldNull.rule(isNotNull)); } @@ -469,7 +477,7 @@ public void testNullFoldingIsNotNull() { public void testNullFoldingIsNotNullWithCast() { FoldNull foldNull = new FoldNull(); - Cast cast = new Cast(EMPTY, L("foo"), DataType.DATE); + Cast cast = new Cast(EMPTY, L("foo"), DATE); IsNotNull isNotNull = new IsNotNull(EMPTY, cast); final IsNotNull isNotNullOpt = (IsNotNull) foldNull.rule(isNotNull); assertEquals(isNotNull, isNotNullOpt); @@ -478,7 +486,7 @@ public void testNullFoldingIsNotNullWithCast() { () -> isNotNullOpt.asPipe().asProcessor().process(null)); assertEquals("cannot cast [foo] to [date]: Text 'foo' could not be parsed at index 0", sqlIAE.getMessage()); - isNotNull = new IsNotNull(EMPTY, new Cast(EMPTY, NULL, randomFrom(DataType.values()))); + isNotNull = new IsNotNull(EMPTY, new Cast(EMPTY, NULL, randomFrom(DataTypes.types()))); assertFalse((Boolean) ((IsNotNull) foldNull.rule(isNotNull)).asPipe().asProcessor().process(null)); } @@ -502,11 +510,11 @@ public void testGenericNullableExpression() { public void testNullFoldingOnCast() { FoldNull foldNull = new FoldNull(); - Cast cast = new Cast(EMPTY, NULL, randomFrom(DataType.values())); + Cast cast = new Cast(EMPTY, NULL, randomFrom(DataTypes.types())); assertEquals(Nullability.TRUE, cast.nullable()); assertNull(foldNull.rule(cast).fold()); - cast = new Cast(EMPTY, L("foo"), DataType.DATE); + cast = new Cast(EMPTY, L("foo"), DATE); assertEquals(Nullability.UNKNOWN, cast.nullable()); assertEquals(cast, foldNull.rule(cast)); } @@ -572,7 +580,7 @@ public void testSimplifyCoalesceRandomNullsWithValue() { randomListOfNulls()))); assertEquals(1, e.children().size()); assertEquals(TRUE, e.children().get(0)); - assertEquals(DataType.BOOLEAN, e.dataType()); + assertEquals(BOOLEAN, e.dataType()); } private List randomListOfNulls() { @@ -586,7 +594,7 @@ public void testSimplifyCoalesceFirstLiteral() { assertEquals(Coalesce.class, e.getClass()); assertEquals(1, e.children().size()); assertEquals(TRUE, e.children().get(0)); - assertEquals(DataType.BOOLEAN, e.dataType()); + assertEquals(BOOLEAN, e.dataType()); } public void testSimplifyIfNullNulls() { @@ -600,13 +608,13 @@ public void testSimplifyIfNullWithNullAndValue() { assertEquals(IfNull.class, e.getClass()); assertEquals(1, e.children().size()); assertEquals(ONE, e.children().get(0)); - assertEquals(DataType.INTEGER, e.dataType()); + assertEquals(INTEGER, e.dataType()); e = new SimplifyConditional().rule(new IfNull(EMPTY, ONE, NULL)); assertEquals(IfNull.class, e.getClass()); assertEquals(1, e.children().size()); assertEquals(ONE, e.children().get(0)); - assertEquals(DataType.INTEGER, e.dataType()); + assertEquals(INTEGER, e.dataType()); } public void testFoldNullNotAppliedOnNullIf() { @@ -634,7 +642,7 @@ public void testSimplifyGreatestRandomNullsWithValue() { assertEquals(2, e.children().size()); assertEquals(ONE, e.children().get(0)); assertEquals(TWO, e.children().get(1)); - assertEquals(DataType.INTEGER, e.dataType()); + assertEquals(INTEGER, e.dataType()); } public void testSimplifyLeastNulls() { @@ -656,7 +664,7 @@ public void testSimplifyLeastRandomNullsWithValue() { assertEquals(2, e.children().size()); assertEquals(ONE, e.children().get(0)); assertEquals(TWO, e.children().get(1)); - assertEquals(DataType.INTEGER, e.dataType()); + assertEquals(INTEGER, e.dataType()); } public void testConcatFoldingIsNotNull() { @@ -707,11 +715,10 @@ public void testSimplifyCaseConditionsFoldWhenFalse() { // END Case c = new Case(EMPTY, Arrays.asList( - new IfConditional(EMPTY, new Equals(EMPTY, getFieldAttribute(), ONE), Literal.of(EMPTY, "foo1")), - new IfConditional(EMPTY, new Equals(EMPTY, ONE, TWO), Literal.of(EMPTY, "bar1")), - new IfConditional(EMPTY, new Equals(EMPTY, TWO, ONE), Literal.of(EMPTY, "bar2")), - new IfConditional(EMPTY, new GreaterThan(EMPTY, getFieldAttribute(), ONE), Literal.of(EMPTY, "foo2")), - Literal.of(EMPTY, "default"))); + new IfConditional(EMPTY, new Equals(EMPTY, getFieldAttribute(), ONE), literal("foo1")), + new IfConditional(EMPTY, new Equals(EMPTY, ONE, TWO), literal("bar1")), + new IfConditional(EMPTY, new Equals(EMPTY, TWO, ONE), literal("bar2")), + new IfConditional(EMPTY, new GreaterThan(EMPTY, getFieldAttribute(), ONE), literal("foo2")), literal("default"))); assertFalse(c.foldable()); Expression e = new SimplifyCase().rule(c); assertEquals(Case.class, e.getClass()); @@ -734,9 +741,8 @@ public void testSimplifyCaseConditionsFoldCompletely_FoldableElse() { // 'foo2' Case c = new Case(EMPTY, Arrays.asList( - new IfConditional(EMPTY, new Equals(EMPTY, ONE, TWO), Literal.of(EMPTY, "foo1")), - new IfConditional(EMPTY, new Equals(EMPTY, ONE, ONE), Literal.of(EMPTY, "foo2")), - Literal.of(EMPTY, "default"))); + new IfConditional(EMPTY, new Equals(EMPTY, ONE, TWO), literal("foo1")), + new IfConditional(EMPTY, new Equals(EMPTY, ONE, ONE), literal("foo2")), literal("default"))); assertFalse(c.foldable()); SimplifyCase rule = new SimplifyCase(); @@ -760,7 +766,7 @@ public void testSimplifyCaseConditionsFoldCompletely_NonFoldableElse() { // myField (non-foldable) Case c = new Case(EMPTY, Arrays.asList( - new IfConditional(EMPTY, new Equals(EMPTY, ONE, TWO), Literal.of(EMPTY, "foo1")), + new IfConditional(EMPTY, new Equals(EMPTY, ONE, TWO), literal("foo1")), getFieldAttribute("myField"))); assertFalse(c.foldable()); @@ -775,7 +781,7 @@ public void testSimplifyCaseConditionsFoldCompletely_NonFoldableElse() { public void testSimplifyIif_ConditionTrue_FoldableResult() { SimplifyCase rule = new SimplifyCase(); - Iif iif = new Iif(EMPTY, new Equals(EMPTY, ONE, ONE), Literal.of(EMPTY, "foo"), Literal.of(EMPTY, "bar")); + Iif iif = new Iif(EMPTY, new Equals(EMPTY, ONE, ONE), literal("foo"), literal("bar")); assertTrue(iif.foldable()); Expression e = rule.rule(iif); @@ -789,7 +795,7 @@ public void testSimplifyIif_ConditionTrue_FoldableResult() { public void testSimplifyIif_ConditionTrue_NonFoldableResult() { SimplifyCase rule = new SimplifyCase(); - Iif iif = new Iif(EMPTY, new Equals(EMPTY, ONE, ONE), getFieldAttribute("myField"), Literal.of(EMPTY, "bar")); + Iif iif = new Iif(EMPTY, new Equals(EMPTY, ONE, ONE), getFieldAttribute("myField"), literal("bar")); assertFalse(iif.foldable()); Expression e = rule.rule(iif); @@ -804,7 +810,7 @@ public void testSimplifyIif_ConditionTrue_NonFoldableResult() { public void testSimplifyIif_ConditionFalse_FoldableResult() { SimplifyCase rule = new SimplifyCase(); - Iif iif = new Iif(EMPTY, new Equals(EMPTY, ONE, TWO), Literal.of(EMPTY, "foo"), Literal.of(EMPTY, "bar")); + Iif iif = new Iif(EMPTY, new Equals(EMPTY, ONE, TWO), literal("foo"), literal("bar")); assertTrue(iif.foldable()); Expression e = rule.rule(iif); @@ -818,7 +824,7 @@ public void testSimplifyIif_ConditionFalse_FoldableResult() { public void testSimplifyIif_ConditionFalse_NonFoldableResult() { SimplifyCase rule = new SimplifyCase(); - Iif iif = new Iif(EMPTY, new Equals(EMPTY, ONE, TWO), Literal.of(EMPTY, "foo"), getFieldAttribute("myField")); + Iif iif = new Iif(EMPTY, new Equals(EMPTY, ONE, TWO), literal("foo"), getFieldAttribute("myField")); assertFalse(iif.foldable()); Expression e = rule.rule(iif); @@ -1797,7 +1803,7 @@ public void testPropagateEquals_VarEq2OrVarRangeGt3Lt4OrVarGt2OrVarNe2() { } public void testTranslateMinToFirst() { - Min min1 = new Min(EMPTY, new FieldAttribute(EMPTY, "str", new EsField("str", DataType.KEYWORD, emptyMap(), true))); + Min min1 = new Min(EMPTY, new FieldAttribute(EMPTY, "str", new EsField("str", KEYWORD, emptyMap(), true))); Min min2 = new Min(EMPTY, getFieldAttribute()); OrderBy plan = new OrderBy(EMPTY, new Aggregate(EMPTY, FROM(), emptyList(), @@ -1823,7 +1829,7 @@ public void testTranslateMinToFirst() { } public void testTranslateMaxToLast() { - Max max1 = new Max(EMPTY, new FieldAttribute(EMPTY, "str", new EsField("str", DataType.KEYWORD, emptyMap(), true))); + Max max1 = new Max(EMPTY, new FieldAttribute(EMPTY, "str", new EsField("str", KEYWORD, emptyMap(), true))); Max max2 = new Max(EMPTY, getFieldAttribute()); OrderBy plan = new OrderBy(EMPTY, new Aggregate(EMPTY, FROM(), emptyList(), Arrays.asList(a("max1", max1), a("max2", max2))), @@ -1847,9 +1853,9 @@ public void testTranslateMaxToLast() { } public void testSortAggregateOnOrderByWithTwoFields() { - FieldAttribute firstField = new FieldAttribute(EMPTY, "first_field", new EsField("first_field", DataType.BYTE, emptyMap(), true)); + FieldAttribute firstField = new FieldAttribute(EMPTY, "first_field", new EsField("first_field", BYTE, emptyMap(), true)); FieldAttribute secondField = new FieldAttribute(EMPTY, "second_field", - new EsField("second_field", DataType.BYTE, emptyMap(), true)); + new EsField("second_field", BYTE, emptyMap(), true)); Alias firstAlias = new Alias(EMPTY, "first_alias", firstField); Alias secondAlias = new Alias(EMPTY, "second_alias", secondField); Order firstOrderBy = new Order(EMPTY, firstField, OrderDirection.ASC, Order.NullsPosition.LAST); @@ -1879,9 +1885,9 @@ public void testSortAggregateOnOrderByWithTwoFields() { } public void testSortAggregateOnOrderByOnlyAliases() { - FieldAttribute firstField = new FieldAttribute(EMPTY, "first_field", new EsField("first_field", DataType.BYTE, emptyMap(), true)); + FieldAttribute firstField = new FieldAttribute(EMPTY, "first_field", new EsField("first_field", BYTE, emptyMap(), true)); FieldAttribute secondField = new FieldAttribute(EMPTY, "second_field", - new EsField("second_field", DataType.BYTE, emptyMap(), true)); + new EsField("second_field", BYTE, emptyMap(), true)); Alias firstAlias = new Alias(EMPTY, "first_alias", firstField); Alias secondAlias = new Alias(EMPTY, "second_alias", secondField); Order firstOrderBy = new Order(EMPTY, firstAlias, OrderDirection.ASC, Order.NullsPosition.LAST); @@ -1934,8 +1940,8 @@ public void testPivotRewrite() { * or SELECT STDDEV_POP(agg_field), VAR_POP(agg_field) FROM table WHERE MATCH(match_field,'A') AND/OR QUERY('match_field:A') */ public void testAggregatesPromoteToStats_WithFullTextPredicatesConditions() { - FieldAttribute matchField = new FieldAttribute(EMPTY, "match_field", new EsField("match_field", DataType.TEXT, emptyMap(), true)); - FieldAttribute aggField = new FieldAttribute(EMPTY, "agg_field", new EsField("agg_field", DataType.INTEGER, emptyMap(), true)); + FieldAttribute matchField = new FieldAttribute(EMPTY, "match_field", new EsField("match_field", TEXT, emptyMap(), true)); + FieldAttribute aggField = new FieldAttribute(EMPTY, "agg_field", new EsField("agg_field", INTEGER, emptyMap(), true)); FullTextPredicate matchPredicate = new MatchQueryPredicate(EMPTY, matchField, "A", StringUtils.EMPTY); FullTextPredicate multiMatchPredicate = new MultiMatchQueryPredicate(EMPTY, "match_field", "A", StringUtils.EMPTY); diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/parser/EscapedFunctionsTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/parser/EscapedFunctionsTests.java index e5fdeaa6be705..2852619edb004 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/parser/EscapedFunctionsTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/parser/EscapedFunctionsTests.java @@ -15,7 +15,6 @@ import org.elasticsearch.xpack.ql.expression.predicate.regex.LikePattern; import org.elasticsearch.xpack.ql.plan.logical.Limit; import org.elasticsearch.xpack.ql.plan.logical.LogicalPlan; -import org.elasticsearch.xpack.ql.type.DataType; import org.elasticsearch.xpack.sql.plan.logical.With; import org.elasticsearch.xpack.sql.proto.SqlTypedParamValue; import org.junit.Assert; @@ -25,7 +24,12 @@ import static java.lang.String.format; import static java.util.Arrays.asList; -import static org.elasticsearch.xpack.sql.TestUtils.randomWhitespaces; +import static org.elasticsearch.xpack.ql.type.DataTypes.DATETIME; +import static org.elasticsearch.xpack.ql.type.DataTypes.KEYWORD; +import static org.elasticsearch.xpack.ql.type.DataTypes.LONG; +import static org.elasticsearch.xpack.sql.SqlTestUtils.randomWhitespaces; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.DATE; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.TIME; import static org.hamcrest.Matchers.endsWith; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; @@ -157,9 +161,8 @@ public void testFunctionWithFunctionWithArg() { public void testFunctionWithFunctionWithArgAndParams() { String e = "POWER(?, {fn POWER({fn ABS(?)}, {fN ABS(?)})})"; Function f = (Function) parser.createExpression(e, - asList(new SqlTypedParamValue(DataType.LONG.typeName(), 1), - new SqlTypedParamValue(DataType.LONG.typeName(), 1), - new SqlTypedParamValue(DataType.LONG.typeName(), 1))); + asList(new SqlTypedParamValue(LONG.typeName(), 1), new SqlTypedParamValue(LONG.typeName(), 1), + new SqlTypedParamValue(LONG.typeName(), 1))); assertEquals(e, f.sourceText()); assertEquals(2, f.arguments().size()); @@ -183,7 +186,7 @@ public void testFunctionWithFunctionWithArgAndParams() { public void testDateLiteral() { Literal l = dateLiteral("2012-01-01"); - assertThat(l.dataType(), is(DataType.DATE)); + assertThat(l.dataType(), is(DATE)); } public void testDateLiteralValidation() { @@ -195,7 +198,7 @@ public void testDateLiteralValidation() { public void testTimeLiteral() { Literal l = timeLiteral("12:23:56"); - assertThat(l.dataType(), is(DataType.TIME)); + assertThat(l.dataType(), is(TIME)); } public void testTimeLiteralValidation() { @@ -207,7 +210,7 @@ public void testTimeLiteralValidation() { public void testTimestampLiteral() { Literal l = timestampLiteral("2012-01-01 10:01:02.3456"); - assertThat(l.dataType(), is(DataType.DATETIME)); + assertThat(l.dataType(), is(DATETIME)); } public void testTimestampLiteralValidation() { @@ -219,10 +222,10 @@ public void testTimestampLiteralValidation() { public void testGUID() { Literal l = guidLiteral("12345678-90ab-cdef-0123-456789abcdef"); - assertThat(l.dataType(), is(DataType.KEYWORD)); + assertThat(l.dataType(), is(KEYWORD)); l = guidLiteral("12345678-90AB-cdef-0123-456789ABCdef"); - assertThat(l.dataType(), is(DataType.KEYWORD)); + assertThat(l.dataType(), is(KEYWORD)); } public void testGUIDValidationHexa() { diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/parser/ExpressionTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/parser/ExpressionTests.java index 220d770717ac7..ab037f7a58f6a 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/parser/ExpressionTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/parser/ExpressionTests.java @@ -9,19 +9,18 @@ import org.elasticsearch.xpack.ql.expression.Expression; import org.elasticsearch.xpack.ql.expression.Literal; import org.elasticsearch.xpack.ql.expression.function.UnresolvedFunction; -import org.elasticsearch.xpack.ql.expression.literal.Interval; -import org.elasticsearch.xpack.ql.expression.predicate.conditional.Case; -import org.elasticsearch.xpack.ql.expression.predicate.conditional.IfConditional; -import org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.Add; -import org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.Mul; import org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.Neg; -import org.elasticsearch.xpack.ql.expression.predicate.operator.arithmetic.Sub; import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.Equals; import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.NotEquals; import org.elasticsearch.xpack.ql.expression.predicate.operator.comparison.NullEquals; -import org.elasticsearch.xpack.ql.type.DataType; -import org.elasticsearch.xpack.sql.TestUtils; +import org.elasticsearch.xpack.sql.SqlTestUtils; import org.elasticsearch.xpack.sql.expression.function.scalar.Cast; +import org.elasticsearch.xpack.sql.expression.literal.interval.Interval; +import org.elasticsearch.xpack.sql.expression.predicate.conditional.Case; +import org.elasticsearch.xpack.sql.expression.predicate.conditional.IfConditional; +import org.elasticsearch.xpack.sql.expression.predicate.operator.arithmetic.Add; +import org.elasticsearch.xpack.sql.expression.predicate.operator.arithmetic.Mul; +import org.elasticsearch.xpack.sql.expression.predicate.operator.arithmetic.Sub; import java.time.Duration; import java.time.Period; @@ -29,6 +28,10 @@ import java.util.Locale; import static java.lang.String.format; +import static org.elasticsearch.xpack.ql.type.DataTypes.BOOLEAN; +import static org.elasticsearch.xpack.ql.type.DataTypes.DOUBLE; +import static org.elasticsearch.xpack.ql.type.DataTypes.INTEGER; +import static org.elasticsearch.xpack.ql.type.DataTypes.LONG; import static org.hamcrest.Matchers.startsWith; public class ExpressionTests extends ESTestCase { @@ -47,7 +50,7 @@ public void testLiteralBoolean() { assertEquals(Literal.class, lt.getClass()); Literal l = (Literal) lt; assertEquals(Boolean.TRUE, l.value()); - assertEquals(DataType.BOOLEAN, l.dataType()); + assertEquals(BOOLEAN, l.dataType()); } public void testLiteralDouble() { @@ -55,7 +58,7 @@ public void testLiteralDouble() { assertEquals(Literal.class, lt.getClass()); Literal l = (Literal) lt; assertEquals(Double.MAX_VALUE, l.value()); - assertEquals(DataType.DOUBLE, l.dataType()); + assertEquals(DOUBLE, l.dataType()); } public void testLiteralDoubleNegative() { @@ -63,7 +66,7 @@ public void testLiteralDoubleNegative() { assertEquals(Literal.class, lt.getClass()); Literal l = (Literal) lt; assertEquals(Double.MIN_VALUE, l.value()); - assertEquals(DataType.DOUBLE, l.dataType()); + assertEquals(DOUBLE, l.dataType()); } public void testLiteralDoublePositive() { @@ -71,7 +74,7 @@ public void testLiteralDoublePositive() { assertEquals(Literal.class, lt.getClass()); Literal l = (Literal) lt; assertEquals(Double.MAX_VALUE, l.value()); - assertEquals(DataType.DOUBLE, l.dataType()); + assertEquals(DOUBLE, l.dataType()); } public void testLiteralLong() { @@ -79,14 +82,14 @@ public void testLiteralLong() { assertEquals(Literal.class, lt.getClass()); Literal l = (Literal) lt; assertEquals(Long.MAX_VALUE, l.value()); - assertEquals(DataType.LONG, l.dataType()); + assertEquals(LONG, l.dataType()); } public void testLiteralLongNegative() { Expression lt = parser.createExpression(String.valueOf(Long.MIN_VALUE)); assertTrue(lt.foldable()); assertEquals(Long.MIN_VALUE, lt.fold()); - assertEquals(DataType.LONG, lt.dataType()); + assertEquals(LONG, lt.dataType()); } public void testLiteralLongPositive() { @@ -94,7 +97,7 @@ public void testLiteralLongPositive() { assertEquals(Literal.class, lt.getClass()); Literal l = (Literal) lt; assertEquals(Long.MAX_VALUE, l.value()); - assertEquals(DataType.LONG, l.dataType()); + assertEquals(LONG, l.dataType()); } public void testLiteralInteger() { @@ -102,7 +105,7 @@ public void testLiteralInteger() { assertEquals(Literal.class, lt.getClass()); Literal l = (Literal) lt; assertEquals(Integer.MAX_VALUE, l.value()); - assertEquals(DataType.INTEGER, l.dataType()); + assertEquals(INTEGER, l.dataType()); } public void testLiteralIntegerWithShortValue() { @@ -110,7 +113,7 @@ public void testLiteralIntegerWithShortValue() { assertEquals(Literal.class, lt.getClass()); Literal l = (Literal) lt; assertEquals((int) Short.MAX_VALUE, l.value()); - assertEquals(DataType.INTEGER, l.dataType()); + assertEquals(INTEGER, l.dataType()); } public void testLiteralIntegerWithByteValue() { @@ -118,7 +121,7 @@ public void testLiteralIntegerWithByteValue() { assertEquals(Literal.class, lt.getClass()); Literal l = (Literal) lt; assertEquals((int) Byte.MAX_VALUE, l.value()); - assertEquals(DataType.INTEGER, l.dataType()); + assertEquals(INTEGER, l.dataType()); } public void testLiteralIntegerInvalid() { @@ -189,7 +192,7 @@ public void testLiteralTimesLiteral() { assertEquals(Mul.class, expr.getClass()); Mul mul = (Mul) expr; assertEquals("10 *2", mul.sourceText()); - assertEquals(DataType.INTEGER, mul.dataType()); + assertEquals(INTEGER, mul.dataType()); } public void testFunctionTimesLiteral() { @@ -219,13 +222,13 @@ public void testNegativeLiteral() { double value = randomDouble(); StringBuilder sb = new StringBuilder("-"); for (int i = 0; i < numberOfParentheses; i++) { - sb.append("(").append(TestUtils.randomWhitespaces()); + sb.append("(").append(SqlTestUtils.randomWhitespaces()); } sb.append(value); for (int i = 0; i < numberOfParentheses; i++) { sb.append(")"); if (i < numberOfParentheses - 1) { - sb.append(TestUtils.randomWhitespaces()); + sb.append(SqlTestUtils.randomWhitespaces()); } } expr = parser.createExpression(sb.toString()); @@ -288,26 +291,26 @@ public void testCastWithUnquotedDataType() { Expression expr = parser.createExpression("CAST(10* 2 AS long)"); assertEquals(Cast.class, expr.getClass()); Cast cast = (Cast) expr; - assertEquals(DataType.INTEGER, cast.from()); - assertEquals(DataType.LONG, cast.to()); - assertEquals(DataType.LONG, cast.dataType()); + assertEquals(INTEGER, cast.from()); + assertEquals(LONG, cast.to()); + assertEquals(LONG, cast.dataType()); assertEquals(Mul.class, cast.field().getClass()); Mul mul = (Mul) cast.field(); assertEquals("10* 2", mul.sourceText()); - assertEquals(DataType.INTEGER, mul.dataType()); + assertEquals(INTEGER, mul.dataType()); } public void testCastWithQuotedDataType() { Expression expr = parser.createExpression("CAST(10*2 AS \"LonG\")"); assertEquals(Cast.class, expr.getClass()); Cast cast = (Cast) expr; - assertEquals(DataType.INTEGER, cast.from()); - assertEquals(DataType.LONG, cast.to()); - assertEquals(DataType.LONG, cast.dataType()); + assertEquals(INTEGER, cast.from()); + assertEquals(LONG, cast.to()); + assertEquals(LONG, cast.dataType()); assertEquals(Mul.class, cast.field().getClass()); Mul mul = (Mul) cast.field(); assertEquals("10*2", mul.sourceText()); - assertEquals(DataType.INTEGER, mul.dataType()); + assertEquals(INTEGER, mul.dataType()); } public void testCastWithInvalidDataType() { @@ -319,39 +322,39 @@ public void testCastOperatorPrecedence() { Expression expr = parser.createExpression("(10* 2::long)"); assertEquals(Mul.class, expr.getClass()); Mul mul = (Mul) expr; - assertEquals(DataType.LONG, mul.dataType()); - assertEquals(DataType.INTEGER, mul.left().dataType()); + assertEquals(LONG, mul.dataType()); + assertEquals(INTEGER, mul.left().dataType()); assertEquals(Cast.class, mul.right().getClass()); Cast cast = (Cast) mul.right(); - assertEquals(DataType.INTEGER, cast.from()); - assertEquals(DataType.LONG, cast.to()); - assertEquals(DataType.LONG, cast.dataType()); + assertEquals(INTEGER, cast.from()); + assertEquals(LONG, cast.to()); + assertEquals(LONG, cast.dataType()); } public void testCastOperatorWithUnquotedDataType() { Expression expr = parser.createExpression("(10* 2)::long"); assertEquals(Cast.class, expr.getClass()); Cast cast = (Cast) expr; - assertEquals(DataType.INTEGER, cast.from()); - assertEquals(DataType.LONG, cast.to()); - assertEquals(DataType.LONG, cast.dataType()); + assertEquals(INTEGER, cast.from()); + assertEquals(LONG, cast.to()); + assertEquals(LONG, cast.dataType()); assertEquals(Mul.class, cast.field().getClass()); Mul mul = (Mul) cast.field(); assertEquals("10* 2", mul.sourceText()); - assertEquals(DataType.INTEGER, mul.dataType()); + assertEquals(INTEGER, mul.dataType()); } public void testCastOperatorWithQuotedDataType() { Expression expr = parser.createExpression("(10*2)::\"LonG\""); assertEquals(Cast.class, expr.getClass()); Cast cast = (Cast) expr; - assertEquals(DataType.INTEGER, cast.from()); - assertEquals(DataType.LONG, cast.to()); - assertEquals(DataType.LONG, cast.dataType()); + assertEquals(INTEGER, cast.from()); + assertEquals(LONG, cast.to()); + assertEquals(LONG, cast.dataType()); assertEquals(Mul.class, cast.field().getClass()); Mul mul = (Mul) cast.field(); assertEquals("10*2", mul.sourceText()); - assertEquals(DataType.INTEGER, mul.dataType()); + assertEquals(INTEGER, mul.dataType()); } public void testCastOperatorWithInvalidDataType() { @@ -363,13 +366,13 @@ public void testConvertWithUnquotedDataType() { Expression expr = parser.createExpression("CONVERT(10*2, long)"); assertEquals(Cast.class, expr.getClass()); Cast cast = (Cast) expr; - assertEquals(DataType.INTEGER, cast.from()); - assertEquals(DataType.LONG, cast.to()); - assertEquals(DataType.LONG, cast.dataType()); + assertEquals(INTEGER, cast.from()); + assertEquals(LONG, cast.to()); + assertEquals(LONG, cast.dataType()); assertEquals(Mul.class, cast.field().getClass()); Mul mul = (Mul) cast.field(); assertEquals("10*2", mul.sourceText()); - assertEquals(DataType.INTEGER, mul.dataType()); + assertEquals(INTEGER, mul.dataType()); } public void testConvertWithQuotedDataType() { @@ -378,31 +381,31 @@ public void testConvertWithQuotedDataType() { assertEquals(Cast.class, expr.getClass()); Cast cast = (Cast) expr; assertEquals(e, cast.sourceText()); - assertEquals(DataType.INTEGER, cast.from()); - assertEquals(DataType.LONG, cast.to()); - assertEquals(DataType.LONG, cast.dataType()); + assertEquals(INTEGER, cast.from()); + assertEquals(LONG, cast.to()); + assertEquals(LONG, cast.dataType()); assertEquals(Mul.class, cast.field().getClass()); Mul mul = (Mul) cast.field(); assertEquals("10*2", mul.sourceText()); - assertEquals(DataType.INTEGER, mul.dataType()); + assertEquals(INTEGER, mul.dataType()); } public void testConvertWithUnquotedODBCDataType() { Expression expr = parser.createExpression("CONVERT(1, Sql_BigInt)"); assertEquals(Cast.class, expr.getClass()); Cast cast = (Cast) expr; - assertEquals(DataType.INTEGER, cast.from()); - assertEquals(DataType.LONG, cast.to()); - assertEquals(DataType.LONG, cast.dataType()); + assertEquals(INTEGER, cast.from()); + assertEquals(LONG, cast.to()); + assertEquals(LONG, cast.dataType()); } public void testConvertWithQuotedODBCDataType() { Expression expr = parser.createExpression("CONVERT(1, \"sql_BIGint\")"); assertEquals(Cast.class, expr.getClass()); Cast cast = (Cast) expr; - assertEquals(DataType.INTEGER, cast.from()); - assertEquals(DataType.LONG, cast.to()); - assertEquals(DataType.LONG, cast.dataType()); + assertEquals(INTEGER, cast.from()); + assertEquals(LONG, cast.to()); + assertEquals(LONG, cast.dataType()); } public void testConvertWithInvalidODBCDataType() { diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/parser/LikeEscapingParsingTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/parser/LikeEscapingParsingTests.java index 1bdd8d897ae93..0072693a7b6d2 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/parser/LikeEscapingParsingTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/parser/LikeEscapingParsingTests.java @@ -9,11 +9,11 @@ import org.elasticsearch.xpack.ql.expression.Expression; import org.elasticsearch.xpack.ql.expression.predicate.regex.Like; import org.elasticsearch.xpack.ql.expression.predicate.regex.LikePattern; -import org.elasticsearch.xpack.ql.type.DataType; import org.elasticsearch.xpack.sql.proto.SqlTypedParamValue; import static java.util.Collections.singletonList; import static org.elasticsearch.common.logging.LoggerMessageFormat.format; +import static org.elasticsearch.xpack.ql.type.DataTypes.KEYWORD; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; @@ -32,7 +32,7 @@ private LikePattern like(String pattern) { Expression exp = null; boolean parameterized = randomBoolean(); if (parameterized) { - exp = parser.createExpression("exp LIKE ?", singletonList(new SqlTypedParamValue(DataType.KEYWORD.typeName(), pattern))); + exp = parser.createExpression("exp LIKE ?", singletonList(new SqlTypedParamValue(KEYWORD.typeName(), pattern))); } else { exp = parser.createExpression(format(null, "exp LIKE '{}'", pattern)); } diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/plan/logical/command/ShowFunctionsTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/plan/logical/command/ShowFunctionsTests.java index fac4cfb9fd75d..c7b06571a01e7 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/plan/logical/command/ShowFunctionsTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/plan/logical/command/ShowFunctionsTests.java @@ -8,7 +8,7 @@ import org.elasticsearch.test.ESTestCase; import org.elasticsearch.xpack.ql.tree.Source; -import org.elasticsearch.xpack.sql.TestUtils; +import org.elasticsearch.xpack.sql.SqlTestUtils; import org.elasticsearch.xpack.sql.expression.function.SqlFunctionRegistry; import org.elasticsearch.xpack.sql.session.SchemaRowSet; import org.elasticsearch.xpack.sql.session.SqlSession; @@ -19,7 +19,7 @@ public class ShowFunctionsTests extends ESTestCase { public void testShowFunctions() throws Exception { ShowFunctions showFunctions = new ShowFunctions(Source.EMPTY, null); - SqlSession session = new SqlSession(TestUtils.TEST_CFG, null, new SqlFunctionRegistry(), null, null, null, null, null, null); + SqlSession session = new SqlSession(SqlTestUtils.TEST_CFG, null, new SqlFunctionRegistry(), null, null, null, null, null, null); showFunctions.execute(session, wrap(p -> { SchemaRowSet r = (SchemaRowSet) p.rowSet(); diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/plan/logical/command/sys/SysColumnsTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/plan/logical/command/sys/SysColumnsTests.java index 5bdeff1f20e42..8531cf3a901e8 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/plan/logical/command/sys/SysColumnsTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/plan/logical/command/sys/SysColumnsTests.java @@ -15,8 +15,7 @@ import org.elasticsearch.xpack.ql.index.IndexResolver.IndexInfo; import org.elasticsearch.xpack.ql.index.IndexResolver.IndexType; import org.elasticsearch.xpack.ql.type.EsField; -import org.elasticsearch.xpack.ql.type.TypesTests; -import org.elasticsearch.xpack.sql.TestUtils; +import org.elasticsearch.xpack.sql.SqlTestUtils; import org.elasticsearch.xpack.sql.analysis.analyzer.Analyzer; import org.elasticsearch.xpack.sql.analysis.analyzer.Verifier; import org.elasticsearch.xpack.sql.parser.SqlParser; @@ -36,6 +35,7 @@ import static java.util.Collections.emptyList; import static java.util.Collections.singletonList; import static org.elasticsearch.action.ActionListener.wrap; +import static org.elasticsearch.xpack.sql.types.SqlTypesTests.loadMapping; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyBoolean; import static org.mockito.Mockito.doAnswer; @@ -47,14 +47,14 @@ public class SysColumnsTests extends ESTestCase { static final String CLUSTER_NAME = "cluster"; private final SqlParser parser = new SqlParser(); - private final Map mapping = TypesTests.loadMapping("mapping-multi-field-with-nested.json", true); + private final Map mapping = loadMapping("mapping-multi-field-with-nested.json", true); private final IndexInfo index = new IndexInfo("test_emp", IndexType.STANDARD_INDEX); private final IndexInfo alias = new IndexInfo("alias", IndexType.ALIAS); public void testSysColumns() { List> rows = new ArrayList<>(); - SysColumns.fillInRows("test", "index", TypesTests.loadMapping("mapping-multi-field-variation.json", true), null, rows, null, + SysColumns.fillInRows("test", "index", loadMapping("mapping-multi-field-variation.json", true), null, rows, null, randomValueOtherThanMany(Mode::isDriver, () -> randomFrom(Mode.values()))); // nested fields are ignored assertEquals(15, rows.size()); @@ -142,7 +142,7 @@ public void testSysColumns() { public void testSysColumnsInOdbcMode() { List> rows = new ArrayList<>(); - SysColumns.fillInRows("test", "index", TypesTests.loadMapping("mapping-multi-field-variation.json", true), null, rows, null, + SysColumns.fillInRows("test", "index", loadMapping("mapping-multi-field-variation.json", true), null, rows, null, Mode.ODBC); assertEquals(15, rows.size()); assertEquals(24, rows.get(0).size()); @@ -277,7 +277,7 @@ public void testSysColumnsInOdbcMode() { public void testSysColumnsInJdbcMode() { List> rows = new ArrayList<>(); - SysColumns.fillInRows("test", "index", TypesTests.loadMapping("mapping-multi-field-variation.json", true), null, rows, null, + SysColumns.fillInRows("test", "index", loadMapping("mapping-multi-field-variation.json", true), null, rows, null, Mode.JDBC); assertEquals(15, rows.size()); assertEquals(24, rows.get(0).size()); @@ -519,14 +519,14 @@ private void executeCommand(String sql, List params, Consume private Tuple sql(String sql, List params, Map mapping) { EsIndex test = new EsIndex("test", mapping); - Analyzer analyzer = new Analyzer(TestUtils.TEST_CFG, new FunctionRegistry(), IndexResolution.valid(test), + Analyzer analyzer = new Analyzer(SqlTestUtils.TEST_CFG, new FunctionRegistry(), IndexResolution.valid(test), new Verifier(new Metrics())); Command cmd = (Command) analyzer.analyze(parser.createStatement(sql, params), true); IndexResolver resolver = mock(IndexResolver.class); when(resolver.clusterName()).thenReturn(CLUSTER_NAME); - SqlSession session = new SqlSession(TestUtils.TEST_CFG, null, null, resolver, null, null, null, null, null); + SqlSession session = new SqlSession(SqlTestUtils.TEST_CFG, null, null, resolver, null, null, null, null, null); return new Tuple<>(cmd, session); } } diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/plan/logical/command/sys/SysTablesTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/plan/logical/command/sys/SysTablesTests.java index 73b4f349790d1..5869aaeb09195 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/plan/logical/command/sys/SysTablesTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/plan/logical/command/sys/SysTablesTests.java @@ -16,8 +16,7 @@ import org.elasticsearch.xpack.ql.index.IndexResolver.IndexType; import org.elasticsearch.xpack.ql.type.DataTypes; import org.elasticsearch.xpack.ql.type.EsField; -import org.elasticsearch.xpack.ql.type.TypesTests; -import org.elasticsearch.xpack.sql.TestUtils; +import org.elasticsearch.xpack.sql.SqlTestUtils; import org.elasticsearch.xpack.sql.analysis.analyzer.Analyzer; import org.elasticsearch.xpack.sql.analysis.analyzer.Verifier; import org.elasticsearch.xpack.sql.parser.SqlParser; @@ -29,6 +28,7 @@ import org.elasticsearch.xpack.sql.session.SchemaRowSet; import org.elasticsearch.xpack.sql.session.SqlSession; import org.elasticsearch.xpack.sql.stats.Metrics; +import org.elasticsearch.xpack.sql.types.SqlTypesTests; import org.elasticsearch.xpack.sql.util.DateUtils; import java.util.Comparator; @@ -51,7 +51,7 @@ public class SysTablesTests extends ESTestCase { private static final String CLUSTER_NAME = "cluster"; private final SqlParser parser = new SqlParser(); - private final Map mapping = TypesTests.loadMapping("mapping-multi-field-with-nested.json", true); + private final Map mapping = SqlTypesTests.loadMapping("mapping-multi-field-with-nested.json", true); private final IndexInfo index = new IndexInfo("test", IndexType.STANDARD_INDEX); private final IndexInfo alias = new IndexInfo("alias", IndexType.ALIAS); private final IndexInfo frozen = new IndexInfo("frozen", IndexType.FROZEN_INDEX); @@ -350,7 +350,7 @@ private SqlTypedParamValue param(Object value) { private Tuple sql(String sql, List params, Configuration cfg) { EsIndex test = new EsIndex("test", mapping); - Analyzer analyzer = new Analyzer(TestUtils.TEST_CFG, new FunctionRegistry(), IndexResolution.valid(test), + Analyzer analyzer = new Analyzer(SqlTestUtils.TEST_CFG, new FunctionRegistry(), IndexResolution.valid(test), new Verifier(new Metrics())); Command cmd = (Command) analyzer.analyze(parser.createStatement(sql, params), true); @@ -371,7 +371,7 @@ private void executeCommand(String sql, Consumer consumer, Configu private void executeCommand(String sql, List params, Consumer consumer, IndexInfo... infos) throws Exception { - executeCommand(sql, params, consumer, TestUtils.TEST_CFG, infos); + executeCommand(sql, params, consumer, SqlTestUtils.TEST_CFG, infos); } @SuppressWarnings({ "unchecked", "rawtypes" }) diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/plan/logical/command/sys/SysTypesTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/plan/logical/command/sys/SysTypesTests.java index 1f1fe89fde903..17bc17bbec4b8 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/plan/logical/command/sys/SysTypesTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/plan/logical/command/sys/SysTypesTests.java @@ -11,14 +11,15 @@ import org.elasticsearch.xpack.ql.index.EsIndex; import org.elasticsearch.xpack.ql.index.IndexResolution; import org.elasticsearch.xpack.ql.index.IndexResolver; -import org.elasticsearch.xpack.ql.type.DataType; -import org.elasticsearch.xpack.ql.type.TypesTests; -import org.elasticsearch.xpack.sql.TestUtils; +import org.elasticsearch.xpack.ql.type.DataTypes; +import org.elasticsearch.xpack.sql.SqlTestUtils; import org.elasticsearch.xpack.sql.analysis.analyzer.Analyzer; import org.elasticsearch.xpack.sql.parser.SqlParser; import org.elasticsearch.xpack.sql.plan.logical.command.Command; import org.elasticsearch.xpack.sql.session.SchemaRowSet; import org.elasticsearch.xpack.sql.session.SqlSession; +import org.elasticsearch.xpack.sql.type.SqlDataTypes; +import org.elasticsearch.xpack.sql.types.SqlTypesTests; import java.sql.JDBCType; import java.util.List; @@ -32,12 +33,12 @@ public class SysTypesTests extends ESTestCase { private final SqlParser parser = new SqlParser(); private Tuple sql(String sql) { - EsIndex test = new EsIndex("test", TypesTests.loadMapping("mapping-multi-field-with-nested.json", true)); - Analyzer analyzer = new Analyzer(TestUtils.TEST_CFG, new FunctionRegistry(), IndexResolution.valid(test), null); + EsIndex test = new EsIndex("test", SqlTypesTests.loadMapping("mapping-multi-field-with-nested.json", true)); + Analyzer analyzer = new Analyzer(SqlTestUtils.TEST_CFG, new FunctionRegistry(), IndexResolution.valid(test), null); Command cmd = (Command) analyzer.analyze(parser.createStatement(sql), false); IndexResolver resolver = mock(IndexResolver.class); - SqlSession session = new SqlSession(TestUtils.TEST_CFG, null, null, resolver, null, null, null, null, null); + SqlSession session = new SqlSession(SqlTestUtils.TEST_CFG, null, null, resolver, null, null, null, null, null); return new Tuple<>(cmd, session); } @@ -45,17 +46,17 @@ public void testSysTypes() { Command cmd = sql("SYS TYPES").v1(); List names = asList("BYTE", "LONG", "BINARY", "NULL", "INTEGER", "SHORT", "HALF_FLOAT", "FLOAT", "DOUBLE", "SCALED_FLOAT", - "KEYWORD", "TEXT", "IP", "BOOLEAN", "DATE", "TIME", "DATETIME", + "IP", "KEYWORD", "TEXT", "BOOLEAN", "DATE", "TIME", "DATETIME", "INTERVAL_YEAR", "INTERVAL_MONTH", "INTERVAL_DAY", "INTERVAL_HOUR", "INTERVAL_MINUTE", "INTERVAL_SECOND", "INTERVAL_YEAR_TO_MONTH", "INTERVAL_DAY_TO_HOUR", "INTERVAL_DAY_TO_MINUTE", "INTERVAL_DAY_TO_SECOND", "INTERVAL_HOUR_TO_MINUTE", "INTERVAL_HOUR_TO_SECOND", "INTERVAL_MINUTE_TO_SECOND", - "GEO_SHAPE", "GEO_POINT", "SHAPE", "UNSUPPORTED", "OBJECT", "NESTED"); + "GEO_POINT", "GEO_SHAPE", "SHAPE", "UNSUPPORTED", "NESTED", "OBJECT"); cmd.execute(session(), wrap(p -> { SchemaRowSet r = (SchemaRowSet) p.rowSet(); assertEquals(19, r.columnCount()); - assertEquals(DataType.values().length, r.size()); - assertFalse(r.schema().types().contains(DataType.NULL)); + assertEquals(SqlDataTypes.types().size(), r.size()); + assertFalse(r.schema().types().contains(DataTypes.NULL)); // test numeric as signed assertFalse(r.column(9, Boolean.class)); // make sure precision is returned as boolean (not int) @@ -76,7 +77,7 @@ public void testSysTypesDefaultFiltering() { cmd.execute(session(), wrap(p -> { SchemaRowSet r = (SchemaRowSet) p.rowSet(); - assertEquals(DataType.values().length, r.size()); + assertEquals(SqlDataTypes.types().size(), r.size()); }, ex -> fail(ex.getMessage()))); } @@ -107,15 +108,15 @@ public void testSysTypesMultipleMatches() { cmd.execute(session(), wrap(p -> { SchemaRowSet r = (SchemaRowSet) p.rowSet(); assertEquals(3, r.size()); + assertEquals("IP", r.column(0)); + assertTrue(r.advanceRow()); assertEquals("KEYWORD", r.column(0)); assertTrue(r.advanceRow()); assertEquals("TEXT", r.column(0)); - assertTrue(r.advanceRow()); - assertEquals("IP", r.column(0)); }, ex -> fail(ex.getMessage()))); } private static SqlSession session() { - return new SqlSession(TestUtils.TEST_CFG, null, null, null, null, null, null, null, null); + return new SqlSession(SqlTestUtils.TEST_CFG, null, null, null, null, null, null, null, null); } } diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/planner/PostOptimizerVerifierTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/planner/PostOptimizerVerifierTests.java index d47fe7c4813d5..dae2efb865b17 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/planner/PostOptimizerVerifierTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/planner/PostOptimizerVerifierTests.java @@ -10,8 +10,7 @@ import org.elasticsearch.xpack.ql.index.EsIndex; import org.elasticsearch.xpack.ql.index.IndexResolution; import org.elasticsearch.xpack.ql.type.EsField; -import org.elasticsearch.xpack.ql.type.TypesTests; -import org.elasticsearch.xpack.sql.TestUtils; +import org.elasticsearch.xpack.sql.SqlTestUtils; import org.elasticsearch.xpack.sql.analysis.analyzer.Analyzer; import org.elasticsearch.xpack.sql.analysis.analyzer.Verifier; import org.elasticsearch.xpack.sql.expression.function.SqlFunctionRegistry; @@ -19,6 +18,7 @@ import org.elasticsearch.xpack.sql.parser.SqlParser; import org.elasticsearch.xpack.sql.plan.physical.PhysicalPlan; import org.elasticsearch.xpack.sql.stats.Metrics; +import org.elasticsearch.xpack.sql.types.SqlTypesTests; import org.junit.After; import org.junit.Before; @@ -36,10 +36,10 @@ public class PostOptimizerVerifierTests extends ESTestCase { public void init() { parser = new SqlParser(); - Map mapping = TypesTests.loadMapping("mapping-multi-field-variation.json"); + Map mapping = SqlTypesTests.loadMapping("mapping-multi-field-variation.json"); EsIndex test = new EsIndex("test", mapping); indexResolution = IndexResolution.valid(test); - analyzer = new Analyzer(TestUtils.TEST_CFG, new SqlFunctionRegistry(), indexResolution, new Verifier(new Metrics())); + analyzer = new Analyzer(SqlTestUtils.TEST_CFG, new SqlFunctionRegistry(), indexResolution, new Verifier(new Metrics())); optimizer = new Optimizer(); planner = new Planner(); } diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/planner/QueryFolderTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/planner/QueryFolderTests.java index 101cdbc827fc8..6da981eba349b 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/planner/QueryFolderTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/planner/QueryFolderTests.java @@ -11,8 +11,7 @@ import org.elasticsearch.xpack.ql.index.EsIndex; import org.elasticsearch.xpack.ql.index.IndexResolution; import org.elasticsearch.xpack.ql.type.EsField; -import org.elasticsearch.xpack.ql.type.TypesTests; -import org.elasticsearch.xpack.sql.TestUtils; +import org.elasticsearch.xpack.sql.SqlTestUtils; import org.elasticsearch.xpack.sql.analysis.analyzer.Analyzer; import org.elasticsearch.xpack.sql.analysis.analyzer.Verifier; import org.elasticsearch.xpack.sql.expression.function.SqlFunctionRegistry; @@ -24,6 +23,7 @@ import org.elasticsearch.xpack.sql.session.EmptyExecutable; import org.elasticsearch.xpack.sql.session.SingletonExecutable; import org.elasticsearch.xpack.sql.stats.Metrics; +import org.elasticsearch.xpack.sql.types.SqlTypesTests; import org.junit.AfterClass; import org.junit.BeforeClass; @@ -45,10 +45,10 @@ public class QueryFolderTests extends ESTestCase { public static void init() { parser = new SqlParser(); - Map mapping = TypesTests.loadMapping("mapping-multi-field-variation.json"); + Map mapping = SqlTypesTests.loadMapping("mapping-multi-field-variation.json"); EsIndex test = new EsIndex("test", mapping); IndexResolution getIndexResult = IndexResolution.valid(test); - analyzer = new Analyzer(TestUtils.TEST_CFG, new SqlFunctionRegistry(), getIndexResult, new Verifier(new Metrics())); + analyzer = new Analyzer(SqlTestUtils.TEST_CFG, new SqlFunctionRegistry(), getIndexResult, new Verifier(new Metrics())); optimizer = new Optimizer(); planner = new Planner(); } diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/planner/QueryTranslatorTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/planner/QueryTranslatorTests.java index 1c11ee3a4460c..53fce394ac6c2 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/planner/QueryTranslatorTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/planner/QueryTranslatorTests.java @@ -23,11 +23,9 @@ import org.elasticsearch.xpack.ql.plan.logical.Filter; import org.elasticsearch.xpack.ql.plan.logical.LogicalPlan; import org.elasticsearch.xpack.ql.plan.logical.Project; -import org.elasticsearch.xpack.ql.type.DataType; import org.elasticsearch.xpack.ql.type.EsField; -import org.elasticsearch.xpack.ql.type.TypesTests; import org.elasticsearch.xpack.sql.SqlIllegalArgumentException; -import org.elasticsearch.xpack.sql.TestUtils; +import org.elasticsearch.xpack.sql.SqlTestUtils; import org.elasticsearch.xpack.sql.analysis.analyzer.Analyzer; import org.elasticsearch.xpack.sql.analysis.analyzer.Verifier; import org.elasticsearch.xpack.sql.expression.function.SqlFunctionRegistry; @@ -56,6 +54,7 @@ import org.elasticsearch.xpack.sql.querydsl.query.TermsQuery; import org.elasticsearch.xpack.sql.querydsl.query.WildcardQuery; import org.elasticsearch.xpack.sql.stats.Metrics; +import org.elasticsearch.xpack.sql.types.SqlTypesTests; import org.elasticsearch.xpack.sql.util.DateUtils; import org.junit.AfterClass; import org.junit.BeforeClass; @@ -67,10 +66,18 @@ import java.util.Map; import java.util.stream.Stream; +import static org.elasticsearch.xpack.ql.type.DataTypes.BOOLEAN; +import static org.elasticsearch.xpack.ql.type.DataTypes.DATETIME; +import static org.elasticsearch.xpack.ql.type.DataTypes.DOUBLE; +import static org.elasticsearch.xpack.ql.type.DataTypes.INTEGER; +import static org.elasticsearch.xpack.ql.type.DataTypes.KEYWORD; +import static org.elasticsearch.xpack.ql.type.DataTypes.LONG; +import static org.elasticsearch.xpack.ql.type.DataTypes.TEXT; import static org.elasticsearch.xpack.sql.expression.function.scalar.math.MathProcessor.MathOperation.E; import static org.elasticsearch.xpack.sql.expression.function.scalar.math.MathProcessor.MathOperation.PI; import static org.elasticsearch.xpack.sql.planner.QueryTranslator.DATE_FORMAT; import static org.elasticsearch.xpack.sql.planner.QueryTranslator.TIME_FORMAT; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.DATE; import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.Matchers.endsWith; import static org.hamcrest.Matchers.instanceOf; @@ -87,10 +94,10 @@ public class QueryTranslatorTests extends ESTestCase { public static void init() { parser = new SqlParser(); - Map mapping = TypesTests.loadMapping("mapping-multi-field-variation.json"); + Map mapping = SqlTypesTests.loadMapping("mapping-multi-field-variation.json"); EsIndex test = new EsIndex("test", mapping); IndexResolution getIndexResult = IndexResolution.valid(test); - analyzer = new Analyzer(TestUtils.TEST_CFG, new SqlFunctionRegistry(), getIndexResult, new Verifier(new Metrics())); + analyzer = new Analyzer(SqlTestUtils.TEST_CFG, new SqlFunctionRegistry(), getIndexResult, new Verifier(new Metrics())); optimizer = new Optimizer(); planner = new Planner(); } @@ -240,38 +247,38 @@ public void testDateRangeCast() { } public void testDateRangeWithCurrentTimestamp() { - testDateRangeWithCurrentFunctions("CURRENT_TIMESTAMP()", DATE_FORMAT, TestUtils.TEST_CFG.now()); + testDateRangeWithCurrentFunctions("CURRENT_TIMESTAMP()", DATE_FORMAT, SqlTestUtils.TEST_CFG.now()); testDateRangeWithCurrentFunctions_AndRangeOptimization("CURRENT_TIMESTAMP()", DATE_FORMAT, - TestUtils.TEST_CFG.now().minusDays(1L).minusSeconds(1L), - TestUtils.TEST_CFG.now().plusDays(1L).plusSeconds(1L)); + SqlTestUtils.TEST_CFG.now().minusDays(1L).minusSeconds(1L), + SqlTestUtils.TEST_CFG.now().plusDays(1L).plusSeconds(1L)); } public void testDateRangeWithCurrentDate() { - testDateRangeWithCurrentFunctions("CURRENT_DATE()", DATE_FORMAT, DateUtils.asDateOnly(TestUtils.TEST_CFG.now())); + testDateRangeWithCurrentFunctions("CURRENT_DATE()", DATE_FORMAT, DateUtils.asDateOnly(SqlTestUtils.TEST_CFG.now())); testDateRangeWithCurrentFunctions_AndRangeOptimization("CURRENT_DATE()", DATE_FORMAT, - DateUtils.asDateOnly(TestUtils.TEST_CFG.now().minusDays(1L)).minusSeconds(1), - DateUtils.asDateOnly(TestUtils.TEST_CFG.now().plusDays(1L)).plusSeconds(1)); + DateUtils.asDateOnly(SqlTestUtils.TEST_CFG.now().minusDays(1L)).minusSeconds(1), + DateUtils.asDateOnly(SqlTestUtils.TEST_CFG.now().plusDays(1L)).plusSeconds(1)); } public void testDateRangeWithToday() { - testDateRangeWithCurrentFunctions("TODAY()", DATE_FORMAT, DateUtils.asDateOnly(TestUtils.TEST_CFG.now())); + testDateRangeWithCurrentFunctions("TODAY()", DATE_FORMAT, DateUtils.asDateOnly(SqlTestUtils.TEST_CFG.now())); testDateRangeWithCurrentFunctions_AndRangeOptimization("TODAY()", DATE_FORMAT, - DateUtils.asDateOnly(TestUtils.TEST_CFG.now().minusDays(1L)).minusSeconds(1), - DateUtils.asDateOnly(TestUtils.TEST_CFG.now().plusDays(1L)).plusSeconds(1)); + DateUtils.asDateOnly(SqlTestUtils.TEST_CFG.now().minusDays(1L)).minusSeconds(1), + DateUtils.asDateOnly(SqlTestUtils.TEST_CFG.now().plusDays(1L)).plusSeconds(1)); } public void testDateRangeWithNow() { - testDateRangeWithCurrentFunctions("NOW()", DATE_FORMAT, TestUtils.TEST_CFG.now()); + testDateRangeWithCurrentFunctions("NOW()", DATE_FORMAT, SqlTestUtils.TEST_CFG.now()); testDateRangeWithCurrentFunctions_AndRangeOptimization("NOW()", DATE_FORMAT, - TestUtils.TEST_CFG.now().minusDays(1L).minusSeconds(1L), - TestUtils.TEST_CFG.now().plusDays(1L).plusSeconds(1L)); + SqlTestUtils.TEST_CFG.now().minusDays(1L).minusSeconds(1L), + SqlTestUtils.TEST_CFG.now().plusDays(1L).plusSeconds(1L)); } public void testDateRangeWithCurrentTime() { - testDateRangeWithCurrentFunctions("CURRENT_TIME()", TIME_FORMAT, TestUtils.TEST_CFG.now()); + testDateRangeWithCurrentFunctions("CURRENT_TIME()", TIME_FORMAT, SqlTestUtils.TEST_CFG.now()); testDateRangeWithCurrentFunctions_AndRangeOptimization("CURRENT_TIME()", TIME_FORMAT, - TestUtils.TEST_CFG.now().minusDays(1L).minusSeconds(1L), - TestUtils.TEST_CFG.now().plusDays(1L).plusSeconds(1L)); + SqlTestUtils.TEST_CFG.now().minusDays(1L).minusSeconds(1L), + SqlTestUtils.TEST_CFG.now().plusDays(1L).plusSeconds(1L)); } private void testDateRangeWithCurrentFunctions(String function, String pattern, ZonedDateTime now) { @@ -323,7 +330,7 @@ private void testDateRangeWithCurrentFunctions_AndRangeOptimization(String funct EsQueryExec eqe = (EsQueryExec) p; assertEquals(1, eqe.output().size()); assertEquals("test.some.string", eqe.output().get(0).qualifiedName()); - assertEquals(DataType.TEXT, eqe.output().get(0).dataType()); + assertEquals(TEXT, eqe.output().get(0).dataType()); Query query = eqe.queryContainer().query(); // the range queries optimization should create a single "range" query with "from" and "to" populated with the values @@ -960,7 +967,7 @@ public void testGroupByDateHistogram() { assertEquals(1000, h.interval().fold()); Expression field = h.field(); assertEquals(FieldAttribute.class, field.getClass()); - assertEquals(DataType.INTEGER, field.dataType()); + assertEquals(INTEGER, field.dataType()); } public void testGroupByHistogram() { @@ -975,7 +982,7 @@ public void testGroupByHistogram() { assertEquals("+2-0", h.interval().fold().toString()); Expression field = h.field(); assertEquals(FieldAttribute.class, field.getClass()); - assertEquals(DataType.DATETIME, field.dataType()); + assertEquals(DATETIME, field.dataType()); } public void testGroupByHistogramQueryTranslator() { @@ -984,7 +991,7 @@ public void testGroupByHistogramQueryTranslator() { EsQueryExec eqe = (EsQueryExec) p; assertEquals(1, eqe.output().size()); assertEquals("MAX(int)", eqe.output().get(0).qualifiedName()); - assertEquals(DataType.INTEGER, eqe.output().get(0).dataType()); + assertEquals(INTEGER, eqe.output().get(0).dataType()); assertThat(eqe.queryContainer().aggs().asAggBuilder().toString().replaceAll("\\s+", ""), containsString("\"date_histogram\":{\"field\":\"date\",\"missing_bucket\":true,\"value_type\":\"date\",\"order\":\"asc\"," + "\"fixed_interval\":\"62208000000ms\",\"time_zone\":\"Z\"}}}]}")); @@ -996,7 +1003,7 @@ public void testGroupByYearQueryTranslator() { EsQueryExec eqe = (EsQueryExec) p; assertEquals(1, eqe.output().size()); assertEquals("YEAR(date)", eqe.output().get(0).qualifiedName()); - assertEquals(DataType.INTEGER, eqe.output().get(0).dataType()); + assertEquals(INTEGER, eqe.output().get(0).dataType()); assertThat(eqe.queryContainer().aggs().asAggBuilder().toString().replaceAll("\\s+", ""), endsWith("\"date_histogram\":{\"field\":\"date\",\"missing_bucket\":true,\"value_type\":\"date\",\"order\":\"asc\"," + "\"calendar_interval\":\"1y\",\"time_zone\":\"Z\"}}}]}}}")); @@ -1008,7 +1015,7 @@ public void testGroupByYearAndScalarsQueryTranslator() { EsQueryExec eqe = (EsQueryExec) p; assertEquals(1, eqe.output().size()); assertEquals("YEAR(CAST(date + INTERVAL 5 months AS DATE))", eqe.output().get(0).qualifiedName()); - assertEquals(DataType.INTEGER, eqe.output().get(0).dataType()); + assertEquals(INTEGER, eqe.output().get(0).dataType()); assertThat(eqe.queryContainer().aggs().asAggBuilder().toString().replaceAll("\\s+", ""), endsWith("\"date_histogram\":{\"script\":{\"source\":\"InternalSqlScriptUtils.cast(" + "InternalSqlScriptUtils.add(InternalSqlScriptUtils.docValue(doc,params.v0)," + @@ -1030,7 +1037,7 @@ public void testGroupByHistogramWithDate() { assertEquals("+0-2", h.interval().fold().toString()); Expression field = h.field(); assertEquals(Cast.class, field.getClass()); - assertEquals(DataType.DATE, field.dataType()); + assertEquals(DATE, field.dataType()); } public void testGroupByHistogramWithDateAndSmallInterval() { @@ -1157,7 +1164,7 @@ public void testGroupByCastScalar() { assertEquals(EsQueryExec.class, p.getClass()); assertEquals(1, p.output().size()); assertEquals("CAST(ABS(EXTRACT(YEAR FROM date)) AS BIGINT)", p.output().get(0).qualifiedName()); - assertEquals(DataType.LONG, p.output().get(0).dataType()); + assertEquals(LONG, p.output().get(0).dataType()); assertThat( ((EsQueryExec) p).queryContainer().aggs().asAggBuilder().toString() .replaceAll("\\s+", ""), @@ -1174,7 +1181,7 @@ public void testGroupByCastScalarWithAlias() { assertEquals(EsQueryExec.class, p.getClass()); assertEquals(1, p.output().size()); assertEquals("cast", p.output().get(0).qualifiedName()); - assertEquals(DataType.LONG, p.output().get(0).dataType()); + assertEquals(LONG, p.output().get(0).dataType()); assertThat( ((EsQueryExec) p).queryContainer().aggs().asAggBuilder().toString() .replaceAll("\\s+", ""), @@ -1191,7 +1198,7 @@ public void testGroupByCastScalarWithNumericRef() { assertEquals(EsQueryExec.class, p.getClass()); assertEquals(1, p.output().size()); assertEquals("CAST(ABS(EXTRACT(YEAR FROM date)) AS BIGINT)", p.output().get(0).qualifiedName()); - assertEquals(DataType.LONG, p.output().get(0).dataType()); + assertEquals(LONG, p.output().get(0).dataType()); assertThat( ((EsQueryExec) p).queryContainer().aggs().asAggBuilder().toString() .replaceAll("\\s+", ""), @@ -1210,7 +1217,7 @@ public void testGroupByConvertScalar() { assertEquals(EsQueryExec.class, p.getClass()); assertEquals(1, p.output().size()); assertEquals("CONVERT(ABS(EXTRACT(YEAR FROM date)), SQL_BIGINT)", p.output().get(0).qualifiedName()); - assertEquals(DataType.LONG, p.output().get(0).dataType()); + assertEquals(LONG, p.output().get(0).dataType()); assertThat( ((EsQueryExec) p).queryContainer().aggs().asAggBuilder().toString() .replaceAll("\\s+", ""), @@ -1226,7 +1233,7 @@ public void testGroupByConvertScalar() { assertEquals(EsQueryExec.class, p.getClass()); assertEquals(1, p.output().size()); assertEquals("EXTRACT(HOUR FROM CONVERT(date, SQL_TIMESTAMP))", p.output().get(0).qualifiedName()); - assertEquals(DataType.INTEGER, p.output().get(0).dataType()); + assertEquals(INTEGER, p.output().get(0).dataType()); assertThat( ((EsQueryExec) p).queryContainer().aggs().asAggBuilder().toString() .replaceAll("\\s+", ""), @@ -1245,7 +1252,7 @@ public void testGroupByConvertScalarWithAlias() { assertEquals(EsQueryExec.class, p.getClass()); assertEquals(1, p.output().size()); assertEquals("convert", p.output().get(0).qualifiedName()); - assertEquals(DataType.LONG, p.output().get(0).dataType()); + assertEquals(LONG, p.output().get(0).dataType()); assertThat( ((EsQueryExec) p).queryContainer().aggs().asAggBuilder().toString() .replaceAll("\\s+", ""), @@ -1260,7 +1267,7 @@ public void testGroupByConvertScalarWithAlias() { assertEquals(EsQueryExec.class, p.getClass()); assertEquals(1, p.output().size()); assertEquals("x", p.output().get(0).qualifiedName()); - assertEquals(DataType.INTEGER, p.output().get(0).dataType()); + assertEquals(INTEGER, p.output().get(0).dataType()); assertThat( ((EsQueryExec) p).queryContainer().aggs().asAggBuilder().toString() .replaceAll("\\s+", ""), @@ -1278,7 +1285,7 @@ public void testGroupByConvertScalarWithNumericRef() { assertEquals(EsQueryExec.class, p.getClass()); assertEquals(1, p.output().size()); assertEquals("CONVERT(ABS(EXTRACT(YEAR FROM date)), SQL_BIGINT)", p.output().get(0).qualifiedName()); - assertEquals(DataType.LONG, p.output().get(0).dataType()); + assertEquals(LONG, p.output().get(0).dataType()); assertThat( ((EsQueryExec) p).queryContainer().aggs().asAggBuilder().toString() .replaceAll("\\s+", ""), @@ -1295,7 +1302,7 @@ public void testGroupByConstantScalar() { assertEquals(EsQueryExec.class, p.getClass()); assertEquals(1, p.output().size()); assertEquals("PI() * int", p.output().get(0).qualifiedName()); - assertEquals(DataType.DOUBLE, p.output().get(0).dataType()); + assertEquals(DOUBLE, p.output().get(0).dataType()); assertThat( ((EsQueryExec) p).queryContainer().aggs().asAggBuilder().toString() .replaceAll("\\s+", ""), @@ -1312,7 +1319,7 @@ public void testGroupByConstantScalarWithAlias() { assertEquals(EsQueryExec.class, p.getClass()); assertEquals(1, p.output().size()); assertEquals("value", p.output().get(0).qualifiedName()); - assertEquals(DataType.DOUBLE, p.output().get(0).dataType()); + assertEquals(DOUBLE, p.output().get(0).dataType()); assertThat( ((EsQueryExec) p).queryContainer().aggs().asAggBuilder().toString() .replaceAll("\\s+", ""), @@ -1326,9 +1333,9 @@ public void testGroupByConstantScalarWithAlias() { assertEquals(EsQueryExec.class, p.getClass()); assertEquals(2, p.output().size()); assertEquals("multi_language", p.output().get(0).qualifiedName()); - assertEquals(DataType.BOOLEAN, p.output().get(0).dataType()); + assertEquals(BOOLEAN, p.output().get(0).dataType()); assertEquals("count(*)", p.output().get(1).qualifiedName()); - assertEquals(DataType.LONG, p.output().get(1).dataType()); + assertEquals(LONG, p.output().get(1).dataType()); assertThat( ((EsQueryExec) p).queryContainer().aggs().asAggBuilder().toString() .replaceAll("\\s+", ""), @@ -1346,7 +1353,7 @@ public void testGroupByConstantScalarWithNumericRef() { assertEquals(EsQueryExec.class, p.getClass()); assertEquals(1, p.output().size()); assertEquals("PI() * int", p.output().get(0).qualifiedName()); - assertEquals(DataType.DOUBLE, p.output().get(0).dataType()); + assertEquals(DOUBLE, p.output().get(0).dataType()); assertThat( ((EsQueryExec) p).queryContainer().aggs().asAggBuilder().toString() .replaceAll("\\s+", ""), @@ -1360,7 +1367,7 @@ public void testGroupByConstantScalarWithNumericRef() { assertEquals(EsQueryExec.class, p.getClass()); assertEquals(1, p.output().size()); assertEquals("PI() * int", p.output().get(0).qualifiedName()); - assertEquals(DataType.DOUBLE, p.output().get(0).dataType()); + assertEquals(DOUBLE, p.output().get(0).dataType()); assertThat( ((EsQueryExec) p).queryContainer().aggs().asAggBuilder().toString() .replaceAll("\\s+", ""), @@ -1374,7 +1381,7 @@ public void testGroupByConstantScalarWithNumericRef() { assertEquals(EsQueryExec.class, p.getClass()); assertEquals(1, p.output().size()); assertEquals("date + 1 * INTERVAL '1' DAY", p.output().get(0).qualifiedName()); - assertEquals(DataType.DATETIME, p.output().get(0).dataType()); + assertEquals(DATETIME, p.output().get(0).dataType()); assertThat( ((EsQueryExec) p).queryContainer().aggs().asAggBuilder().toString() .replaceAll("\\s+", ""), @@ -1391,7 +1398,7 @@ public void testOrderByWithCastWithMissingRefs() { assertEquals(EsQueryExec.class, p.getClass()); assertEquals(1, p.output().size()); assertEquals("test.keyword", p.output().get(0).qualifiedName()); - assertEquals(DataType.KEYWORD, p.output().get(0).dataType()); + assertEquals(KEYWORD, p.output().get(0).dataType()); assertThat( ((EsQueryExec) p).queryContainer().toString() .replaceAll("\\s+", ""), @@ -1409,7 +1416,7 @@ public void testTopHitsAggregationWithOneArg() { EsQueryExec eqe = (EsQueryExec) p; assertEquals(1, eqe.output().size()); assertEquals("FIRST(keyword)", eqe.output().get(0).qualifiedName()); - assertEquals(DataType.KEYWORD, eqe.output().get(0).dataType()); + assertEquals(KEYWORD, eqe.output().get(0).dataType()); assertThat(eqe.queryContainer().aggs().asAggBuilder().toString().replaceAll("\\s+", ""), endsWith("\"top_hits\":{\"from\":0,\"size\":1,\"version\":false,\"seq_no_primary_term\":false," + "\"explain\":false,\"docvalue_fields\":[{\"field\":\"keyword\"}]," + @@ -1421,7 +1428,7 @@ public void testTopHitsAggregationWithOneArg() { EsQueryExec eqe = (EsQueryExec) p; assertEquals(1, eqe.output().size()); assertEquals("MIN(keyword)", eqe.output().get(0).qualifiedName()); - assertEquals(DataType.KEYWORD, eqe.output().get(0).dataType()); + assertEquals(KEYWORD, eqe.output().get(0).dataType()); assertThat(eqe.queryContainer().aggs().asAggBuilder().toString().replaceAll("\\s+", ""), endsWith("\"top_hits\":{\"from\":0,\"size\":1,\"version\":false,\"seq_no_primary_term\":false," + "\"explain\":false,\"docvalue_fields\":[{\"field\":\"keyword\"}]," + @@ -1433,7 +1440,7 @@ public void testTopHitsAggregationWithOneArg() { EsQueryExec eqe = (EsQueryExec) p; assertEquals(1, eqe.output().size()); assertEquals("LAST(date)", eqe.output().get(0).qualifiedName()); - assertEquals(DataType.DATETIME, eqe.output().get(0).dataType()); + assertEquals(DATETIME, eqe.output().get(0).dataType()); assertThat(eqe.queryContainer().aggs().asAggBuilder().toString().replaceAll("\\s+", ""), endsWith("\"top_hits\":{\"from\":0,\"size\":1,\"version\":false,\"seq_no_primary_term\":false," + "\"explain\":false,\"docvalue_fields\":[{\"field\":\"date\",\"format\":\"epoch_millis\"}]," + @@ -1445,7 +1452,7 @@ public void testTopHitsAggregationWithOneArg() { EsQueryExec eqe = (EsQueryExec) p; assertEquals(1, eqe.output().size()); assertEquals("MAX(keyword)", eqe.output().get(0).qualifiedName()); - assertEquals(DataType.KEYWORD, eqe.output().get(0).dataType()); + assertEquals(KEYWORD, eqe.output().get(0).dataType()); assertThat(eqe.queryContainer().aggs().asAggBuilder().toString().replaceAll("\\s+", ""), endsWith("\"top_hits\":{\"from\":0,\"size\":1,\"version\":false,\"seq_no_primary_term\":false," + "\"explain\":false,\"docvalue_fields\":[{\"field\":\"keyword\"}]," + @@ -1460,7 +1467,7 @@ public void testTopHitsAggregationWithTwoArgs() { EsQueryExec eqe = (EsQueryExec) p; assertEquals(1, eqe.output().size()); assertEquals("FIRST(keyword, int)", eqe.output().get(0).qualifiedName()); - assertEquals(DataType.KEYWORD, eqe.output().get(0).dataType()); + assertEquals(KEYWORD, eqe.output().get(0).dataType()); assertThat(eqe.queryContainer().aggs().asAggBuilder().toString().replaceAll("\\s+", ""), endsWith("\"top_hits\":{\"from\":0,\"size\":1,\"version\":false,\"seq_no_primary_term\":false," + "\"explain\":false,\"docvalue_fields\":[{\"field\":\"keyword\"}]," + @@ -1474,7 +1481,7 @@ public void testTopHitsAggregationWithTwoArgs() { EsQueryExec eqe = (EsQueryExec) p; assertEquals(1, eqe.output().size()); assertEquals("LAST(date, int)", eqe.output().get(0).qualifiedName()); - assertEquals(DataType.DATETIME, eqe.output().get(0).dataType()); + assertEquals(DATETIME, eqe.output().get(0).dataType()); assertThat(eqe.queryContainer().aggs().asAggBuilder().toString().replaceAll("\\s+", ""), endsWith("\"top_hits\":{\"from\":0,\"size\":1,\"version\":false,\"seq_no_primary_term\":false," + "\"explain\":false,\"docvalue_fields\":[{\"field\":\"date\",\"format\":\"epoch_millis\"}]," + diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/plugin/CursorTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/plugin/CursorTests.java index 47d90fafc11a1..dc08c5d552784 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/plugin/CursorTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/plugin/CursorTests.java @@ -13,7 +13,7 @@ import org.elasticsearch.common.logging.LoggerMessageFormat; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.xpack.sql.SqlIllegalArgumentException; -import org.elasticsearch.xpack.sql.TestUtils; +import org.elasticsearch.xpack.sql.SqlTestUtils; import org.elasticsearch.xpack.sql.action.BasicFormatter; import org.elasticsearch.xpack.sql.action.SqlQueryResponse; import org.elasticsearch.xpack.sql.execution.search.ScrollCursor; @@ -43,7 +43,7 @@ public void testEmptyCursorClearCursor() { Client clientMock = mock(Client.class); Cursor cursor = Cursor.EMPTY; PlainActionFuture future = newFuture(); - cursor.clear(TestUtils.TEST_CFG, clientMock, future); + cursor.clear(SqlTestUtils.TEST_CFG, clientMock, future); assertFalse(future.actionGet()); verifyZeroInteractions(clientMock); } @@ -55,7 +55,7 @@ public void testScrollCursorClearCursor() { String cursorString = randomAlphaOfLength(10); Cursor cursor = new ScrollCursor(cursorString, Collections.emptyList(), new BitSet(0), randomInt()); - cursor.clear(TestUtils.TEST_CFG, clientMock, listenerMock); + cursor.clear(SqlTestUtils.TEST_CFG, clientMock, listenerMock); ArgumentCaptor request = ArgumentCaptor.forClass(ClearScrollRequest.class); verify(clientMock).clearScroll(request.capture(), any(ActionListener.class)); diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/querydsl/container/QueryContainerTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/querydsl/container/QueryContainerTests.java index 91abbe7935135..e35b38ff4ada5 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/querydsl/container/QueryContainerTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/querydsl/container/QueryContainerTests.java @@ -13,7 +13,6 @@ import org.elasticsearch.xpack.ql.expression.FieldAttribute; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.tree.SourceTests; -import org.elasticsearch.xpack.ql.type.DataType; import org.elasticsearch.xpack.ql.type.EsField; import org.elasticsearch.xpack.sql.querydsl.query.BoolQuery; import org.elasticsearch.xpack.sql.querydsl.query.MatchAll; @@ -29,6 +28,7 @@ import static java.util.Collections.emptyMap; import static java.util.Collections.singletonMap; +import static org.elasticsearch.xpack.ql.type.DataTypes.TEXT; public class QueryContainerTests extends ESTestCase { private Source source = SourceTests.randomSource(); @@ -74,7 +74,7 @@ public void testRewriteToContainsNestedFieldWhenDoesNotContainNestedFieldAndCant public void testColumnMaskShouldDuplicateSameAttributes() { - EsField esField = new EsField("str", DataType.TEXT, emptyMap(), true); + EsField esField = new EsField("str", TEXT, emptyMap(), true); Attribute first = new FieldAttribute(Source.EMPTY, "first", esField); Attribute second = new FieldAttribute(Source.EMPTY, "second", esField); diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/querydsl/query/MatchQueryTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/querydsl/query/MatchQueryTests.java index 6c36d46dc1a15..2928ab3b98946 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/querydsl/query/MatchQueryTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/querydsl/query/MatchQueryTests.java @@ -12,7 +12,6 @@ import org.elasticsearch.xpack.ql.expression.predicate.fulltext.MatchQueryPredicate; import org.elasticsearch.xpack.ql.tree.Source; import org.elasticsearch.xpack.ql.tree.SourceTests; -import org.elasticsearch.xpack.ql.type.DataType; import org.elasticsearch.xpack.ql.type.EsField; import org.elasticsearch.xpack.ql.util.StringUtils; @@ -23,6 +22,7 @@ import static java.util.Collections.emptyMap; import static org.elasticsearch.test.EqualsHashCodeTestUtils.checkEqualsAndHashCode; import static org.elasticsearch.xpack.ql.tree.Source.EMPTY; +import static org.elasticsearch.xpack.ql.type.DataTypes.KEYWORD; import static org.hamcrest.Matchers.equalTo; public class MatchQueryTests extends ESTestCase { @@ -68,7 +68,7 @@ public void testQueryBuilding() { private static MatchQueryBuilder getBuilder(String options) { final Source source = new Source(1, 1, StringUtils.EMPTY); - FieldAttribute fa = new FieldAttribute(EMPTY, "a", new EsField("af", DataType.KEYWORD, emptyMap(), true)); + FieldAttribute fa = new FieldAttribute(EMPTY, "a", new EsField("af", KEYWORD, emptyMap(), true)); final MatchQueryPredicate mmqp = new MatchQueryPredicate(source, fa, "eggplant", options); final MatchQuery mmq = new MatchQuery(source, "eggplant", "foo", mmqp); return (MatchQueryBuilder) mmq.asBuilder(); @@ -76,7 +76,7 @@ private static MatchQueryBuilder getBuilder(String options) { public void testToString() { final Source source = new Source(1, 1, StringUtils.EMPTY); - FieldAttribute fa = new FieldAttribute(EMPTY, "a", new EsField("af", DataType.KEYWORD, emptyMap(), true)); + FieldAttribute fa = new FieldAttribute(EMPTY, "a", new EsField("af", KEYWORD, emptyMap(), true)); final MatchQueryPredicate mmqp = new MatchQueryPredicate(source, fa, "eggplant", ""); final MatchQuery mmq = new MatchQuery(source, "eggplant", "foo", mmqp); assertEquals("MatchQuery@1:2[eggplant:foo]", mmq.toString()); diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/stats/VerifierMetricsTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/stats/VerifierMetricsTests.java index ffb3e9ff04ade..55eb0c234f533 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/stats/VerifierMetricsTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/stats/VerifierMetricsTests.java @@ -11,12 +11,12 @@ import org.elasticsearch.xpack.ql.index.EsIndex; import org.elasticsearch.xpack.ql.index.IndexResolution; import org.elasticsearch.xpack.ql.type.EsField; -import org.elasticsearch.xpack.ql.type.TypesTests; -import org.elasticsearch.xpack.sql.TestUtils; +import org.elasticsearch.xpack.sql.SqlTestUtils; import org.elasticsearch.xpack.sql.analysis.analyzer.Analyzer; import org.elasticsearch.xpack.sql.analysis.analyzer.Verifier; import org.elasticsearch.xpack.sql.expression.function.SqlFunctionRegistry; import org.elasticsearch.xpack.sql.parser.SqlParser; +import org.elasticsearch.xpack.sql.types.SqlTypesTests; import java.util.Map; @@ -229,7 +229,7 @@ private void sqlWithVerifier(String sql, Verifier verifier) { } private Counters sql(String sql, Verifier v) { - Map mapping = TypesTests.loadMapping("mapping-basic.json"); + Map mapping = SqlTypesTests.loadMapping("mapping-basic.json"); EsIndex test = new EsIndex("test", mapping); Verifier verifier = v; @@ -239,9 +239,9 @@ private Counters sql(String sql, Verifier v) { verifier = new Verifier(metrics); } - Analyzer analyzer = new Analyzer(TestUtils.TEST_CFG, new SqlFunctionRegistry(), IndexResolution.valid(test), verifier); + Analyzer analyzer = new Analyzer(SqlTestUtils.TEST_CFG, new SqlFunctionRegistry(), IndexResolution.valid(test), verifier); analyzer.analyze(parser.createStatement(sql), true); return metrics == null ? null : metrics.stats(); } -} +} \ No newline at end of file diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/tree/SqlNodeSubclassTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/tree/SqlNodeSubclassTests.java index 4937b618cf35c..abbfc98418609 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/tree/SqlNodeSubclassTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/tree/SqlNodeSubclassTests.java @@ -11,7 +11,6 @@ import org.elasticsearch.xpack.ql.tree.Node; import org.elasticsearch.xpack.ql.tree.NodeSubclassTests; import org.elasticsearch.xpack.ql.tree.SourceTests; -import org.elasticsearch.xpack.ql.util.CollectionUtils; import org.elasticsearch.xpack.sql.expression.function.aggregate.Avg; import org.elasticsearch.xpack.sql.expression.function.aggregate.CompoundNumericAggregate; import org.elasticsearch.xpack.sql.expression.function.aggregate.Percentile; @@ -19,10 +18,17 @@ import org.elasticsearch.xpack.sql.expression.function.aggregate.Percentiles; import org.elasticsearch.xpack.sql.expression.function.grouping.Histogram; import org.elasticsearch.xpack.sql.expression.function.scalar.datetime.CurrentDateTime; +import org.elasticsearch.xpack.sql.expression.predicate.conditional.IfConditional; +import org.elasticsearch.xpack.sql.expression.predicate.conditional.IfNull; +import org.elasticsearch.xpack.sql.expression.predicate.conditional.Iif; +import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.In; +import org.elasticsearch.xpack.sql.expression.predicate.operator.comparison.InPipe; -import java.util.Arrays; import java.util.List; +import static java.util.Arrays.asList; +import static org.elasticsearch.xpack.ql.type.DataTypes.INTEGER; + /** * Looks for all subclasses of {@link Node} and verifies that they * implement {@link Node#info()} and @@ -49,8 +55,8 @@ */ public class SqlNodeSubclassTests> extends NodeSubclassTests { - private static final List> CLASSES_WITH_MIN_TWO_CHILDREN = CollectionUtils.combine( - NodeSubclassTests.CLASSES_WITH_MIN_TWO_CHILDREN, Arrays.asList(Percentile.class, Percentiles.class, PercentileRanks.class)); + private static final List> CLASSES_WITH_MIN_TWO_CHILDREN = asList(Percentile.class, Percentiles.class, PercentileRanks.class, + Iif.class, IfConditional.class, IfNull.class, In.class, InPipe.class); public SqlNodeSubclassTests(Class subclass) { @@ -80,7 +86,7 @@ protected Object pluggableMakeArg(Class> toBuildClass, Class conversion.convert(Double.MAX_VALUE)); + assertEquals("[" + Double.MAX_VALUE + "] out of [long] range", e.getMessage()); + } + { + Converter conversion = converterFor(INTEGER, to); + assertNull(conversion.convert(null)); + assertEquals(10L, conversion.convert(10)); + assertEquals(-134L, conversion.convert(-134)); + } + { + Converter conversion = converterFor(BOOLEAN, to); + assertNull(conversion.convert(null)); + assertEquals(1L, conversion.convert(true)); + assertEquals(0L, conversion.convert(false)); + } + { + Converter conversion = converterFor(DATE, to); + assertNull(conversion.convert(null)); + assertEquals(123379200000L, conversion.convert(asDateOnly(123456789101L))); + assertEquals(-123465600000L, conversion.convert(asDateOnly(-123456789101L))); + } + { + Converter conversion = converterFor(TIME, to); + assertNull(conversion.convert(null)); + assertEquals(123456L, conversion.convert(asTimeOnly(123456L))); + assertEquals(77589101L, conversion.convert(asTimeOnly(123456789101L))); + assertEquals(86276544L, conversion.convert(asTimeOnly(-123456L))); + assertEquals(8810899L, conversion.convert(asTimeOnly(-123456789101L))); + } + { + Converter conversion = converterFor(DATETIME, to); + assertNull(conversion.convert(null)); + assertEquals(123456789101L, conversion.convert(asDateTime(123456789101L))); + assertEquals(-123456789101L, conversion.convert(asDateTime(-123456789101L))); + } + { + Converter conversion = converterFor(KEYWORD, to); + assertNull(conversion.convert(null)); + assertEquals(1L, conversion.convert("1")); + assertEquals(0L, conversion.convert("-0")); + Exception e = expectThrows(QlIllegalArgumentException.class, () -> conversion.convert("0xff")); + assertEquals("cannot cast [0xff] to [long]", e.getMessage()); + } + } + + public void testConversionToDate() { + DataType to = DATE; + { + Converter conversion = converterFor(DOUBLE, to); + assertNull(conversion.convert(null)); + assertEquals(date(10L), conversion.convert(10.0)); + assertEquals(date(10L), conversion.convert(10.1)); + assertEquals(date(11L), conversion.convert(10.6)); + Exception e = expectThrows(QlIllegalArgumentException.class, () -> conversion.convert(Double.MAX_VALUE)); + assertEquals("[" + Double.MAX_VALUE + "] out of [long] range", e.getMessage()); + } + { + Converter conversion = converterFor(INTEGER, to); + assertNull(conversion.convert(null)); + assertEquals(date(10L), conversion.convert(10)); + assertEquals(date(-134L), conversion.convert(-134)); + } + { + Converter conversion = converterFor(BOOLEAN, to); + assertNull(conversion.convert(null)); + assertEquals(date(1), conversion.convert(true)); + assertEquals(date(0), conversion.convert(false)); + } + { + assertNull(converterFor(TIME, to)); + } + { + Converter conversion = converterFor(DATETIME, to); + assertNull(conversion.convert(null)); + assertEquals(date(123456780000L), conversion.convert(asDateTime(123456789101L))); + assertEquals(date(-123456789101L), conversion.convert(asDateTime(-123456789101L))); + } + { + Converter conversion = converterFor(KEYWORD, to); + assertNull(conversion.convert(null)); + + assertEquals(date(0L), conversion.convert("1970-01-01")); + assertEquals(date(1483228800000L), conversion.convert("2017-01-01")); + assertEquals(date(-1672531200000L), conversion.convert("1917-01-01")); + assertEquals(date(18000000L), conversion.convert("1970-01-01")); + + // double check back and forth conversion + + ZonedDateTime zdt = org.elasticsearch.common.time.DateUtils.nowWithMillisResolution(); + Converter forward = converterFor(DATE, KEYWORD); + Converter back = converterFor(KEYWORD, DATE); + assertEquals(asDateOnly(zdt), back.convert(forward.convert(zdt))); + Exception e = expectThrows(QlIllegalArgumentException.class, () -> conversion.convert("0xff")); + assertEquals("cannot cast [0xff] to [date]: Text '0xff' could not be parsed at index 0", e.getMessage()); + } + } + + public void testConversionToTime() { + DataType to = TIME; + { + Converter conversion = converterFor(DOUBLE, to); + assertNull(conversion.convert(null)); + assertEquals(time(10L), conversion.convert(10.0)); + assertEquals(time(10L), conversion.convert(10.1)); + assertEquals(time(11L), conversion.convert(10.6)); + Exception e = expectThrows(QlIllegalArgumentException.class, () -> conversion.convert(Double.MAX_VALUE)); + assertEquals("[" + Double.MAX_VALUE + "] out of [long] range", e.getMessage()); + } + { + Converter conversion = converterFor(INTEGER, to); + assertNull(conversion.convert(null)); + assertEquals(time(10L), conversion.convert(10)); + assertEquals(time(-134L), conversion.convert(-134)); + } + { + Converter conversion = converterFor(BOOLEAN, to); + assertNull(conversion.convert(null)); + assertEquals(time(1), conversion.convert(true)); + assertEquals(time(0), conversion.convert(false)); + } + { + Converter conversion = converterFor(DATE, to); + assertNull(conversion.convert(null)); + assertEquals(time(123379200000L), conversion.convert(asDateOnly(123456789101L))); + assertEquals(time(-123465600000L), conversion.convert(asDateOnly(-123456789101L))); + } + { + Converter conversion = converterFor(DATETIME, to); + assertNull(conversion.convert(null)); + assertEquals(time(77589101L), conversion.convert(asDateTime(123456789101L))); + assertEquals(time(8810899L), conversion.convert(asDateTime(-123456789101L))); + } + { + Converter conversion = converterFor(KEYWORD, to); + assertNull(conversion.convert(null)); + + assertEquals(time(0L), conversion.convert("00:00:00Z")); + assertEquals(time(1000L), conversion.convert("00:00:01Z")); + assertEquals(time(1234L), conversion.convert("00:00:01.234Z")); + assertEquals(time(63296789L).withOffsetSameInstant(ZoneOffset.ofHours(-5)), conversion.convert("12:34:56.789-05:00")); + + // double check back and forth conversion + OffsetTime ot = org.elasticsearch.common.time.DateUtils.nowWithMillisResolution().toOffsetDateTime().toOffsetTime(); + Converter forward = converterFor(TIME, KEYWORD); + Converter back = converterFor(KEYWORD, TIME); + assertEquals(ot, back.convert(forward.convert(ot))); + Exception e = expectThrows(QlIllegalArgumentException.class, () -> conversion.convert("0xff")); + assertEquals("cannot cast [0xff] to [time]: Text '0xff' could not be parsed at index 0", e.getMessage()); + } + } + + public void testConversionToDateTime() { + DataType to = DATETIME; + { + Converter conversion = converterFor(DOUBLE, to); + assertNull(conversion.convert(null)); + assertEquals(dateTime(10L), conversion.convert(10.0)); + assertEquals(dateTime(10L), conversion.convert(10.1)); + assertEquals(dateTime(11L), conversion.convert(10.6)); + Exception e = expectThrows(QlIllegalArgumentException.class, () -> conversion.convert(Double.MAX_VALUE)); + assertEquals("[" + Double.MAX_VALUE + "] out of [long] range", e.getMessage()); + } + { + Converter conversion = converterFor(INTEGER, to); + assertNull(conversion.convert(null)); + assertEquals(dateTime(10L), conversion.convert(10)); + assertEquals(dateTime(-134L), conversion.convert(-134)); + } + { + Converter conversion = converterFor(BOOLEAN, to); + assertNull(conversion.convert(null)); + assertEquals(dateTime(1), conversion.convert(true)); + assertEquals(dateTime(0), conversion.convert(false)); + } + { + Converter conversion = converterFor(DATE, to); + assertNull(conversion.convert(null)); + assertEquals(dateTime(123379200000L), conversion.convert(asDateOnly(123456789101L))); + assertEquals(dateTime(-123465600000L), conversion.convert(asDateOnly(-123456789101L))); + } + { + assertNull(converterFor(TIME, to)); + } + { + Converter conversion = converterFor(KEYWORD, to); + assertNull(conversion.convert(null)); + + assertEquals(dateTime(0L), conversion.convert("1970-01-01")); + assertEquals(dateTime(1000L), conversion.convert("1970-01-01T00:00:01Z")); + assertEquals(dateTime(1483228800000L), conversion.convert("2017-01-01T00:00:00Z")); + assertEquals(dateTime(1483228800000L), conversion.convert("2017-01-01T00:00:00Z")); + assertEquals(dateTime(18000000L), conversion.convert("1970-01-01T00:00:00-05:00")); + + // double check back and forth conversion + + ZonedDateTime dt = org.elasticsearch.common.time.DateUtils.nowWithMillisResolution(); + Converter forward = converterFor(DATETIME, KEYWORD); + Converter back = converterFor(KEYWORD, DATETIME); + assertEquals(dt, back.convert(forward.convert(dt))); + Exception e = expectThrows(QlIllegalArgumentException.class, () -> conversion.convert("0xff")); + assertEquals("cannot cast [0xff] to [datetime]: failed to parse date field [0xff] with format [date_optional_time]", + e.getMessage()); + } + } + + public void testConversionToFloat() { + DataType to = FLOAT; + { + Converter conversion = converterFor(DOUBLE, to); + assertNull(conversion.convert(null)); + assertEquals(10.0f, (float) conversion.convert(10.0d), 0.00001); + assertEquals(10.1f, (float) conversion.convert(10.1d), 0.00001); + assertEquals(10.6f, (float) conversion.convert(10.6d), 0.00001); + } + { + Converter conversion = converterFor(INTEGER, to); + assertNull(conversion.convert(null)); + assertEquals(10.0f, (float) conversion.convert(10), 0.00001); + assertEquals(-134.0f, (float) conversion.convert(-134), 0.00001); + } + { + Converter conversion = converterFor(BOOLEAN, to); + assertNull(conversion.convert(null)); + assertEquals(1.0f, (float) conversion.convert(true), 0); + assertEquals(0.0f, (float) conversion.convert(false), 0); + } + { + Converter conversion = converterFor(DATE, to); + assertNull(conversion.convert(null)); + assertEquals(1.233792E11f, (float) conversion.convert(asDateOnly(123456789101L)), 0); + assertEquals(-1.234656E11f, (float) conversion.convert(asDateOnly(-123456789101L)), 0); + } + { + Converter conversion = converterFor(TIME, to); + assertNull(conversion.convert(null)); + assertEquals(123456.0f, (float) conversion.convert(asTimeOnly(123456L)), 0); + assertEquals(7.7589104E7f, (float) conversion.convert(asTimeOnly(123456789101L)), 0); + assertEquals(8.6276544E7f, (float) conversion.convert(asTimeOnly(-123456L)), 0); + assertEquals(8810899.0f, (float) conversion.convert(asTimeOnly(-123456789101L)), 0); + } + { + Converter conversion = converterFor(DATETIME, to); + assertNull(conversion.convert(null)); + assertEquals(1.23456789101E11f, (float) conversion.convert(asDateTime(123456789101L)), 0); + assertEquals(-1.23456789101E11f, (float) conversion.convert(asDateTime(-123456789101L)), 0); + } + { + Converter conversion = converterFor(KEYWORD, to); + assertNull(conversion.convert(null)); + assertEquals(1.0f, (float) conversion.convert("1"), 0); + assertEquals(0.0f, (float) conversion.convert("-0"), 0); + assertEquals(12.776f, (float) conversion.convert("12.776"), 0.00001); + Exception e = expectThrows(QlIllegalArgumentException.class, () -> conversion.convert("0xff")); + assertEquals("cannot cast [0xff] to [float]", e.getMessage()); + } + } + + public void testConversionToDouble() { + DataType to = DOUBLE; + { + Converter conversion = converterFor(FLOAT, to); + 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); + } + { + Converter conversion = converterFor(INTEGER, to); + assertNull(conversion.convert(null)); + assertEquals(10.0, (double) conversion.convert(10), 0.00001); + assertEquals(-134.0, (double) conversion.convert(-134), 0.00001); + } + { + Converter conversion = converterFor(BOOLEAN, to); + assertNull(conversion.convert(null)); + assertEquals(1.0, (double) conversion.convert(true), 0); + assertEquals(0.0, (double) conversion.convert(false), 0); + } + { + Converter conversion = converterFor(DATE, to); + assertNull(conversion.convert(null)); + assertEquals(1.233792E11, (double) conversion.convert(asDateOnly(123456789101L)), 0); + assertEquals(-1.234656E11, (double) conversion.convert(asDateOnly(-123456789101L)), 0); + } + { + Converter conversion = converterFor(TIME, to); + assertNull(conversion.convert(null)); + assertEquals(123456.0, (double) conversion.convert(asTimeOnly(123456L)), 0); + assertEquals(7.7589101E7, (double) conversion.convert(asTimeOnly(123456789101L)), 0); + assertEquals(8.6276544E7, (double) conversion.convert(asTimeOnly(-123456L)), 0); + assertEquals(8810899.0, (double) conversion.convert(asTimeOnly(-123456789101L)), 0); + } + { + Converter conversion = converterFor(DATETIME, to); + assertNull(conversion.convert(null)); + assertEquals(1.23456789101E11, (double) conversion.convert(asDateTime(123456789101L)), 0); + assertEquals(-1.23456789101E11, (double) conversion.convert(asDateTime(-123456789101L)), 0); + } + { + Converter conversion = converterFor(KEYWORD, to); + assertNull(conversion.convert(null)); + assertEquals(1.0, (double) conversion.convert("1"), 0); + assertEquals(0.0, (double) conversion.convert("-0"), 0); + assertEquals(12.776, (double) conversion.convert("12.776"), 0.00001); + Exception e = expectThrows(QlIllegalArgumentException.class, () -> conversion.convert("0xff")); + assertEquals("cannot cast [0xff] to [double]", e.getMessage()); + } + } + + public void testConversionToBoolean() { + DataType to = BOOLEAN; + { + Converter conversion = converterFor(FLOAT, to); + assertNull(conversion.convert(null)); + assertEquals(true, conversion.convert(10.0f)); + assertEquals(true, conversion.convert(-10.0f)); + assertEquals(false, conversion.convert(0.0f)); + } + { + Converter conversion = converterFor(INTEGER, to); + assertNull(conversion.convert(null)); + assertEquals(true, conversion.convert(10)); + assertEquals(true, conversion.convert(-10)); + assertEquals(false, conversion.convert(0)); + } + { + Converter conversion = converterFor(LONG, to); + assertNull(conversion.convert(null)); + assertEquals(true, conversion.convert(10L)); + assertEquals(true, conversion.convert(-10L)); + assertEquals(false, conversion.convert(0L)); + } + { + Converter conversion = converterFor(DOUBLE, to); + assertNull(conversion.convert(null)); + assertEquals(true, conversion.convert(10.0d)); + assertEquals(true, conversion.convert(-10.0d)); + assertEquals(false, conversion.convert(0.0d)); + } + { + Converter conversion = converterFor(DATE, to); + assertNull(conversion.convert(null)); + assertEquals(true, conversion.convert(asDateOnly(123456789101L))); + assertEquals(true, conversion.convert(asDateOnly(-123456789101L))); + assertEquals(false, conversion.convert(asDateOnly(0L))); + } + { + Converter conversion = converterFor(TIME, to); + assertNull(conversion.convert(null)); + assertEquals(true, conversion.convert(asTimeOnly(123456789101L))); + assertEquals(true, conversion.convert(asTimeOnly(-123456789101L))); + assertEquals(false, conversion.convert(asTimeOnly(0L))); + } + { + Converter conversion = converterFor(DATETIME, to); + assertNull(conversion.convert(null)); + assertEquals(true, conversion.convert(asDateTime(123456789101L))); + assertEquals(true, conversion.convert(asDateTime(-123456789101L))); + assertEquals(false, conversion.convert(asDateTime(0L))); + } + { + Converter conversion = converterFor(KEYWORD, to); + assertNull(conversion.convert(null)); + // We only handled upper and lower case true and false + assertEquals(true, conversion.convert("true")); + assertEquals(false, conversion.convert("false")); + assertEquals(true, conversion.convert("True")); + assertEquals(false, conversion.convert("fAlSe")); + // Everything else should fail + Exception e = expectThrows(QlIllegalArgumentException.class, () -> conversion.convert("10")); + assertEquals("cannot cast [10] to [boolean]", e.getMessage()); + e = expectThrows(QlIllegalArgumentException.class, () -> conversion.convert("-1")); + assertEquals("cannot cast [-1] to [boolean]", e.getMessage()); + e = expectThrows(QlIllegalArgumentException.class, () -> conversion.convert("0")); + assertEquals("cannot cast [0] to [boolean]", e.getMessage()); + e = expectThrows(QlIllegalArgumentException.class, () -> conversion.convert("blah")); + assertEquals("cannot cast [blah] to [boolean]", e.getMessage()); + e = expectThrows(QlIllegalArgumentException.class, () -> conversion.convert("Yes")); + assertEquals("cannot cast [Yes] to [boolean]", e.getMessage()); + e = expectThrows(QlIllegalArgumentException.class, () -> conversion.convert("nO")); + assertEquals("cannot cast [nO] to [boolean]", e.getMessage()); + } + } + + public void testConversionToInt() { + DataType to = INTEGER; + { + Converter conversion = converterFor(DOUBLE, to); + assertNull(conversion.convert(null)); + assertEquals(10, conversion.convert(10.0)); + assertEquals(10, conversion.convert(10.1)); + assertEquals(11, conversion.convert(10.6)); + Exception e = expectThrows(QlIllegalArgumentException.class, () -> conversion.convert(Long.MAX_VALUE)); + assertEquals("[" + Long.MAX_VALUE + "] out of [integer] range", e.getMessage()); + } + { + Converter conversion = converterFor(DATE, to); + assertNull(conversion.convert(null)); + assertEquals(0, conversion.convert(asDateOnly(12345678L))); + assertEquals(86400000, conversion.convert(asDateOnly(123456789L))); + assertEquals(172800000, conversion.convert(asDateOnly(223456789L))); + assertEquals(-172800000, conversion.convert(asDateOnly(-123456789L))); + Exception e = expectThrows(QlIllegalArgumentException.class, () -> conversion.convert(asDateOnly(Long.MAX_VALUE))); + assertEquals("[9223372036828800000] out of [integer] range", e.getMessage()); + } + { + Converter conversion = converterFor(TIME, to); + assertNull(conversion.convert(null)); + assertEquals(123456, conversion.convert(asTimeOnly(123456L))); + assertEquals(77589101, conversion.convert(asTimeOnly(123456789101L))); + assertEquals(86276544, conversion.convert(asTimeOnly(-123456L))); + assertEquals(8810899, conversion.convert(asTimeOnly(-123456789101L))); + assertEquals(25975807, conversion.convert(asTimeOnly(Long.MAX_VALUE))); + } + { + Converter conversion = converterFor(DATETIME, to); + assertNull(conversion.convert(null)); + assertEquals(12345678, conversion.convert(asDateTime(12345678L))); + assertEquals(223456789, conversion.convert(asDateTime(223456789L))); + assertEquals(-123456789, conversion.convert(asDateTime(-123456789L))); + Exception e = expectThrows(QlIllegalArgumentException.class, () -> conversion.convert(asDateTime(Long.MAX_VALUE))); + assertEquals("[" + Long.MAX_VALUE + "] out of [integer] range", e.getMessage()); + } + } + + public void testConversionToShort() { + DataType to = SHORT; + { + Converter conversion = converterFor(DOUBLE, to); + assertNull(conversion.convert(null)); + assertEquals((short) 10, conversion.convert(10.0)); + assertEquals((short) 10, conversion.convert(10.1)); + assertEquals((short) 11, conversion.convert(10.6)); + Exception e = expectThrows(QlIllegalArgumentException.class, () -> conversion.convert(Integer.MAX_VALUE)); + assertEquals("[" + Integer.MAX_VALUE + "] out of [short] range", e.getMessage()); + } + { + Converter conversion = converterFor(DATE, to); + assertNull(conversion.convert(null)); + assertEquals((short) 0, conversion.convert(asDateOnly(12345678L))); + Exception e = expectThrows(QlIllegalArgumentException.class, () -> conversion.convert(asDateOnly(123456789L))); + assertEquals("[86400000] out of [short] range", e.getMessage()); + } + { + Converter conversion = converterFor(TIME, to); + assertNull(conversion.convert(null)); + assertEquals((short) 12345, conversion.convert(asTimeOnly(12345L))); + Exception e1 = expectThrows(QlIllegalArgumentException.class, () -> conversion.convert(asTimeOnly(-123456789L))); + assertEquals("[49343211] out of [short] range", e1.getMessage()); + Exception e2 = expectThrows(QlIllegalArgumentException.class, () -> conversion.convert(asTimeOnly(123456789L))); + assertEquals("[37056789] out of [short] range", e2.getMessage()); + } + { + Converter conversion = converterFor(DATETIME, to); + assertNull(conversion.convert(null)); + assertEquals((short) 12345, conversion.convert(asDateTime(12345L))); + assertEquals((short) -12345, conversion.convert(asDateTime(-12345L))); + Exception e = expectThrows(QlIllegalArgumentException.class, () -> conversion.convert(asDateTime(Integer.MAX_VALUE))); + assertEquals("[" + Integer.MAX_VALUE + "] out of [short] range", e.getMessage()); + } + } + + public void testConversionToByte() { + DataType to = BYTE; + { + Converter conversion = converterFor(DOUBLE, to); + assertNull(conversion.convert(null)); + assertEquals((byte) 10, conversion.convert(10.0)); + assertEquals((byte) 10, conversion.convert(10.1)); + assertEquals((byte) 11, conversion.convert(10.6)); + Exception e = expectThrows(QlIllegalArgumentException.class, () -> conversion.convert(Short.MAX_VALUE)); + assertEquals("[" + Short.MAX_VALUE + "] out of [byte] range", e.getMessage()); + } + { + Converter conversion = converterFor(DATE, to); + assertNull(conversion.convert(null)); + assertEquals((byte) 0, conversion.convert(asDateOnly(12345678L))); + Exception e = expectThrows(QlIllegalArgumentException.class, () -> conversion.convert(asDateOnly(123456789L))); + assertEquals("[86400000] out of [byte] range", e.getMessage()); + } + { + Converter conversion = converterFor(TIME, to); + assertNull(conversion.convert(null)); + assertEquals((byte) 123, conversion.convert(asTimeOnly(123L))); + Exception e1 = expectThrows(QlIllegalArgumentException.class, () -> conversion.convert(asTimeOnly(-123L))); + assertEquals("[86399877] out of [byte] range", e1.getMessage()); + Exception e2 = expectThrows(QlIllegalArgumentException.class, () -> conversion.convert(asTimeOnly(123456789L))); + assertEquals("[37056789] out of [byte] range", e2.getMessage()); + } + { + Converter conversion = converterFor(DATETIME, to); + assertNull(conversion.convert(null)); + assertEquals((byte) 123, conversion.convert(asDateTime(123L))); + assertEquals((byte) -123, conversion.convert(asDateTime(-123L))); + Exception e = expectThrows(QlIllegalArgumentException.class, () -> conversion.convert(asDateTime(Integer.MAX_VALUE))); + assertEquals("[" + Integer.MAX_VALUE + "] out of [byte] range", e.getMessage()); + } + } + + public void testConversionToNull() { + Converter conversion = converterFor(DOUBLE, NULL); + assertNull(conversion.convert(null)); + assertNull(conversion.convert(10.0)); + } + + public void testConversionFromNull() { + Converter conversion = converterFor(NULL, INTEGER); + assertNull(conversion.convert(null)); + assertNull(conversion.convert(10)); + } + + public void testConversionToIdentity() { + Converter conversion = converterFor(INTEGER, INTEGER); + assertNull(conversion.convert(null)); + assertEquals(10, conversion.convert(10)); + } + + public void testCommonType() { + assertEquals(BOOLEAN, commonType(BOOLEAN, NULL)); + assertEquals(BOOLEAN, commonType(NULL, BOOLEAN)); + assertEquals(BOOLEAN, commonType(BOOLEAN, BOOLEAN)); + assertEquals(NULL, commonType(NULL, NULL)); + assertEquals(INTEGER, commonType(INTEGER, KEYWORD)); + assertEquals(LONG, commonType(TEXT, LONG)); + assertEquals(SHORT, commonType(SHORT, BYTE)); + assertEquals(FLOAT, commonType(BYTE, FLOAT)); + assertEquals(FLOAT, commonType(FLOAT, INTEGER)); + assertEquals(DOUBLE, commonType(DOUBLE, FLOAT)); + + // strings + assertEquals(TEXT, commonType(TEXT, KEYWORD)); + assertEquals(TEXT, commonType(KEYWORD, TEXT)); + + // numeric and intervals + assertEquals(INTERVAL_YEAR_TO_MONTH, commonType(INTERVAL_YEAR_TO_MONTH, LONG)); + assertEquals(INTERVAL_HOUR_TO_MINUTE, commonType(INTEGER, INTERVAL_HOUR_TO_MINUTE)); + + // dates/datetimes and intervals + assertEquals(DATETIME, commonType(DATE, DATETIME)); + assertEquals(DATETIME, commonType(DATETIME, DATE)); + assertEquals(DATETIME, commonType(TIME, DATETIME)); + assertEquals(DATETIME, commonType(DATETIME, TIME)); + assertEquals(DATETIME, commonType(DATETIME, randomInterval())); + assertEquals(DATETIME, commonType(randomInterval(), DATETIME)); + assertEquals(DATETIME, commonType(DATE, TIME)); + assertEquals(DATETIME, commonType(TIME, DATE)); + assertEquals(DATE, commonType(DATE, INTERVAL_YEAR)); + assertEquals(DATETIME, commonType(DATE, INTERVAL_HOUR_TO_MINUTE)); + assertEquals(TIME, commonType(TIME, randomInterval())); + assertEquals(TIME, commonType(randomInterval(), TIME)); + + assertEquals(INTERVAL_YEAR_TO_MONTH, commonType(INTERVAL_YEAR_TO_MONTH, INTERVAL_MONTH)); + assertEquals(INTERVAL_HOUR_TO_SECOND, commonType(INTERVAL_HOUR_TO_MINUTE, INTERVAL_HOUR_TO_SECOND)); + assertNull(commonType(INTERVAL_SECOND, INTERVAL_YEAR)); + } + + public void testEsDataTypes() { + for (DataType type : types()) { + if (type != DATE) { // Doesn't have a corresponding type in ES + assertEquals(type, fromTypeName(type.typeName())); + } + } + } + + public void testConversionToUnsupported() { + assertNull(converterFor(INTEGER, UNSUPPORTED)); + } + + public void testStringToIp() { + Converter conversion = converterFor(KEYWORD, IP); + assertNull(conversion.convert(null)); + assertEquals("192.168.1.1", conversion.convert("192.168.1.1")); + Exception e = expectThrows(QlIllegalArgumentException.class, () -> conversion.convert("10.1.1.300")); + assertEquals("[10.1.1.300] is not a valid IPv4 or IPv6 address", e.getMessage()); + } + + public void testIpToString() { + Source s = new Source(Location.EMPTY, "10.0.0.1"); + Converter ipToString = converterFor(IP, KEYWORD); + assertEquals("10.0.0.1", ipToString.convert(new Literal(s, "10.0.0.1", IP))); + Converter stringToIp = converterFor(KEYWORD, IP); + assertEquals("10.0.0.1", ipToString.convert(stringToIp.convert(new Literal(s, "10.0.0.1", KEYWORD)))); + } + + private DataType randomInterval() { + return randomFrom(SqlDataTypes.types().stream() + .filter(SqlDataTypes::isInterval) + .collect(toList())); + } + + static ZonedDateTime dateTime(long millisSinceEpoch) { + return DateUtils.asDateTime(millisSinceEpoch); + } + + static ZonedDateTime date(long millisSinceEpoch) { + return DateUtils.asDateOnly(millisSinceEpoch); + } + + static OffsetTime time(long millisSinceEpoch) { + return DateUtils.asTimeOnly(millisSinceEpoch); + } +} \ No newline at end of file diff --git a/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/type/DataTypesTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/type/SqlDataTypesTests.java similarity index 59% rename from x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/type/DataTypesTests.java rename to x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/type/SqlDataTypesTests.java index bfc6282340ecd..dce63dbc69559 100644 --- a/x-pack/plugin/ql/src/test/java/org/elasticsearch/xpack/ql/type/DataTypesTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/type/SqlDataTypesTests.java @@ -3,47 +3,51 @@ * 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.ql.type; +package org.elasticsearch.xpack.sql.type; import org.elasticsearch.test.ESTestCase; +import org.elasticsearch.xpack.ql.type.DataType; +import org.elasticsearch.xpack.ql.type.DataTypes; import java.util.ArrayList; import java.util.Arrays; -import java.util.EnumSet; import java.util.List; -import java.util.stream.Stream; +import static java.util.Arrays.asList; import static java.util.stream.Collectors.toList; -import static org.elasticsearch.xpack.ql.type.DataType.DATETIME; -import static org.elasticsearch.xpack.ql.type.DataType.FLOAT; -import static org.elasticsearch.xpack.ql.type.DataType.INTERVAL_DAY; -import static org.elasticsearch.xpack.ql.type.DataType.INTERVAL_DAY_TO_HOUR; -import static org.elasticsearch.xpack.ql.type.DataType.INTERVAL_DAY_TO_MINUTE; -import static org.elasticsearch.xpack.ql.type.DataType.INTERVAL_DAY_TO_SECOND; -import static org.elasticsearch.xpack.ql.type.DataType.INTERVAL_HOUR; -import static org.elasticsearch.xpack.ql.type.DataType.INTERVAL_HOUR_TO_MINUTE; -import static org.elasticsearch.xpack.ql.type.DataType.INTERVAL_HOUR_TO_SECOND; -import static org.elasticsearch.xpack.ql.type.DataType.INTERVAL_MINUTE; -import static org.elasticsearch.xpack.ql.type.DataType.INTERVAL_MINUTE_TO_SECOND; -import static org.elasticsearch.xpack.ql.type.DataType.INTERVAL_MONTH; -import static org.elasticsearch.xpack.ql.type.DataType.INTERVAL_SECOND; -import static org.elasticsearch.xpack.ql.type.DataType.INTERVAL_YEAR; -import static org.elasticsearch.xpack.ql.type.DataType.INTERVAL_YEAR_TO_MONTH; -import static org.elasticsearch.xpack.ql.type.DataType.KEYWORD; -import static org.elasticsearch.xpack.ql.type.DataType.LONG; -import static org.elasticsearch.xpack.ql.type.DataTypes.compatibleInterval; -import static org.elasticsearch.xpack.ql.type.DataTypes.metaSqlDataType; -import static org.elasticsearch.xpack.ql.type.DataTypes.metaSqlDateTimeSub; -import static org.elasticsearch.xpack.ql.type.DataTypes.metaSqlMaximumScale; -import static org.elasticsearch.xpack.ql.type.DataTypes.metaSqlMinimumScale; -import static org.elasticsearch.xpack.ql.type.DataTypes.metaSqlRadix; - -public class DataTypesTests extends ESTestCase { +import static org.elasticsearch.xpack.ql.type.DataTypes.DATETIME; +import static org.elasticsearch.xpack.ql.type.DataTypes.FLOAT; +import static org.elasticsearch.xpack.ql.type.DataTypes.KEYWORD; +import static org.elasticsearch.xpack.ql.type.DataTypes.LONG; +import static org.elasticsearch.xpack.sql.expression.literal.interval.Intervals.compatibleInterval; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.INTERVAL_DAY; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.INTERVAL_DAY_TO_HOUR; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.INTERVAL_DAY_TO_MINUTE; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.INTERVAL_DAY_TO_SECOND; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.INTERVAL_HOUR; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.INTERVAL_HOUR_TO_MINUTE; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.INTERVAL_HOUR_TO_SECOND; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.INTERVAL_MINUTE; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.INTERVAL_MINUTE_TO_SECOND; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.INTERVAL_MONTH; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.INTERVAL_SECOND; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.INTERVAL_YEAR; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.INTERVAL_YEAR_TO_MONTH; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.defaultPrecision; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.isInterval; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.metaSqlDataType; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.metaSqlDateTimeSub; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.metaSqlMaximumScale; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.metaSqlMinimumScale; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.metaSqlRadix; +import static org.elasticsearch.xpack.sql.type.SqlDataTypes.sqlType; + +public class SqlDataTypesTests extends ESTestCase { public void testMetaDataType() { assertEquals(Integer.valueOf(9), metaSqlDataType(DATETIME)); DataType t = randomDataTypeNoDateTime(); - assertEquals(t.sqlType().getVendorTypeNumber(), metaSqlDataType(t)); + assertEquals(sqlType(t).getVendorTypeNumber(), metaSqlDataType(t)); } public void testMetaDateTypeSub() { @@ -54,14 +58,14 @@ public void testMetaDateTypeSub() { public void testMetaMinimumScale() { assertEquals(Short.valueOf((short) 3), metaSqlMinimumScale(DATETIME)); assertEquals(Short.valueOf((short) 0), metaSqlMinimumScale(LONG)); - assertEquals(Short.valueOf((short) FLOAT.defaultPrecision), metaSqlMaximumScale(FLOAT)); + assertEquals(Short.valueOf((short) defaultPrecision(FLOAT)), metaSqlMaximumScale(FLOAT)); assertNull(metaSqlMinimumScale(KEYWORD)); } public void testMetaMaximumScale() { assertEquals(Short.valueOf((short) 3), metaSqlMaximumScale(DATETIME)); assertEquals(Short.valueOf((short) 0), metaSqlMaximumScale(LONG)); - assertEquals(Short.valueOf((short) FLOAT.defaultPrecision), metaSqlMaximumScale(FLOAT)); + assertEquals(Short.valueOf((short) defaultPrecision(FLOAT)), metaSqlMaximumScale(FLOAT)); assertNull(metaSqlMaximumScale(KEYWORD)); } @@ -75,8 +79,20 @@ public void testMetaRadix() { // type checks public void testIsInterval() throws Exception { - for (DataType dataType : EnumSet.range(INTERVAL_YEAR, INTERVAL_MINUTE_TO_SECOND)) { - assertTrue(dataType.isInterval()); + for (DataType dataType : asList(INTERVAL_YEAR, + INTERVAL_MONTH, + INTERVAL_DAY, + INTERVAL_HOUR, + INTERVAL_MINUTE, + INTERVAL_SECOND, + INTERVAL_YEAR_TO_MONTH, + INTERVAL_DAY_TO_HOUR, + INTERVAL_DAY_TO_MINUTE, + INTERVAL_DAY_TO_SECOND, + INTERVAL_HOUR_TO_MINUTE, + INTERVAL_HOUR_TO_SECOND, + INTERVAL_MINUTE_TO_SECOND)) { + assertTrue(dataType + " is not an interval", isInterval(dataType)); } } @@ -131,16 +147,16 @@ public void testEsToDataType() throws Exception { "interval_hour_to_minute", "interval_hour_to_second", "interval_minute_to_second")); - types.addAll(Stream.of(DataType.values()) - .filter(DataType::isPrimitive) - .map(DataType::name) + types.addAll(SqlDataTypes.types().stream() + .filter(DataTypes::isPrimitive) + .map(DataType::typeName) .collect(toList())); String type = randomFrom(types.toArray(new String[0])); - DataType dataType = DataType.fromSqlOrEsType(type); - assertNotNull(dataType); + DataType dataType = SqlDataTypes.fromSqlOrEsType(type); + assertNotNull("cound not find " + type, dataType); } private DataType randomDataTypeNoDateTime() { - return randomValueOtherThan(DataType.DATETIME, () -> randomFrom(DataType.values())); + return randomValueOtherThan(DATETIME, () -> randomFrom(SqlDataTypes.types())); } -} +} \ No newline at end of file diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/types/SqlTypesTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/types/SqlTypesTests.java new file mode 100644 index 0000000000000..30de718093a1a --- /dev/null +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/types/SqlTypesTests.java @@ -0,0 +1,84 @@ +/* + * 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.types; + +import org.elasticsearch.test.ESTestCase; +import org.elasticsearch.xpack.ql.type.EsField; +import org.elasticsearch.xpack.ql.type.KeywordEsField; +import org.elasticsearch.xpack.ql.type.TextEsField; +import org.elasticsearch.xpack.ql.type.TypesTests; +import org.elasticsearch.xpack.sql.type.SqlDataTypeRegistry; +import org.elasticsearch.xpack.sql.type.SqlDataTypes; + +import java.util.Map; + +import static org.elasticsearch.xpack.ql.type.DataTypes.DATETIME; +import static org.hamcrest.Matchers.instanceOf; +import static org.hamcrest.Matchers.is; + +public class SqlTypesTests extends ESTestCase { + + + public void testGeoField() { + Map mapping = loadMapping("mapping-geo.json"); + assertThat(mapping.size(), is(2)); + EsField gp = mapping.get("location"); + assertThat(gp.getDataType().typeName(), is("geo_point")); + EsField gs = mapping.get("site"); + assertThat(gs.getDataType().typeName(), is("geo_shape")); + } + + + public void testTextField() { + Map mapping = loadMapping("mapping-text.json"); + assertThat(mapping.size(), is(1)); + EsField type = mapping.get("full_name"); + assertThat(type, instanceOf(TextEsField.class)); + assertThat(type.isAggregatable(), is(false)); + TextEsField ttype = (TextEsField) type; + assertThat(SqlDataTypes.defaultPrecision(ttype.getDataType()), is(32766)); + assertThat(ttype.isAggregatable(), is(false)); + } + + public void testKeywordField() { + Map mapping = loadMapping("mapping-keyword.json"); + + assertThat(mapping.size(), is(1)); + EsField field = mapping.get("full_name"); + assertThat(field, instanceOf(KeywordEsField.class)); + assertThat(field.isAggregatable(), is(true)); + assertThat(((KeywordEsField) field).getPrecision(), is(256)); + } + + public void testDateField() { + Map mapping = loadMapping("mapping-date.json"); + + assertThat(mapping.size(), is(1)); + EsField field = mapping.get("date"); + assertThat(field.getDataType(), is(DATETIME)); + assertThat(field.isAggregatable(), is(true)); + assertThat(SqlDataTypes.defaultPrecision(field.getDataType()), is(3)); + } + + public void testDocValueField() { + Map mapping = loadMapping("mapping-docvalues.json"); + + assertThat(mapping.size(), is(1)); + EsField field = mapping.get("session_id"); + assertThat(field, instanceOf(KeywordEsField.class)); + assertThat(((KeywordEsField) field).getPrecision(), is(15)); + assertThat(field.isAggregatable(), is(false)); + } + + public static Map loadMapping(String name) { + return TypesTests.loadMapping(SqlDataTypeRegistry.INSTANCE, name); + } + + public static Map loadMapping(String name, boolean ordered) { + return TypesTests.loadMapping(SqlDataTypeRegistry.INSTANCE, name, ordered); + } +} \ No newline at end of file