aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVolodymyr Vysotskyi <vvovyk@gmail.com>2018-04-05 15:35:42 +0300
committerVolodymyr Vysotskyi <vvovyk@gmail.com>2018-05-04 20:30:50 +0300
commit4c4953bcab4886be14fc9b7f95a77caa86a7629f (patch)
treeb9ed1a17179063c47bd9f7a2e20f5601807b3580
parent79e27eadb86dfaa0e2d8bc514f3069bf02dc2762 (diff)
DRILL-6094: Decimal data type enhancements
Add ExprVisitors for VARDECIMAL Modify writers/readers to support VARDECIMAL - Added usage of VarDecimal for parquet, hive, maprdb, jdbc; - Added options to store decimals as int32 and int64 or fixed_len_byte_array or binary; Add UDFs for VARDECIMAL data type - modify type inference rules - remove UDFs for obsolete DECIMAL types Enable DECIMAL data type by default Add unit tests for DECIMAL data type Fix mapping for NLJ when literal with non-primitive type is used in join conditions Refresh protobuf C++ source files Changes in C++ files Add support for decimal logical type in Avro. Add support for date, time and timestamp logical types. Update Avro version to 1.8.2.
-rw-r--r--common/src/main/java/org/apache/drill/common/types/Types.java7
-rw-r--r--common/src/main/java/org/apache/drill/common/util/CoreDecimalUtility.java47
-rw-r--r--common/src/main/java/org/apache/drill/common/util/DecimalScalePrecisionDivideFunction.java62
-rw-r--r--contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/mapr/db/json/CompareFunctionsProcessor.java11
-rw-r--r--contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/mapr/db/json/MaprDBJsonRecordReader.java11
-rw-r--r--contrib/native/client/src/clientlib/decimalUtils.cpp15
-rw-r--r--contrib/native/client/src/clientlib/fieldmeta.cpp3
-rw-r--r--contrib/native/client/src/clientlib/metadata.cpp51
-rw-r--r--contrib/native/client/src/clientlib/recordBatch.cpp4
-rw-r--r--contrib/native/client/src/include/drill/decimalUtils.hpp1
-rw-r--r--contrib/native/client/src/include/drill/protobuf/Types.pb.h5
-rw-r--r--contrib/native/client/src/include/drill/recordBatch.hpp55
-rw-r--r--contrib/native/client/src/protobuf/Types.pb.cc11
-rw-r--r--contrib/storage-hive/core/src/main/codegen/data/HiveTypes.tdd2
-rw-r--r--contrib/storage-hive/core/src/main/codegen/templates/ObjectInspectors.java44
-rw-r--r--contrib/storage-hive/core/src/main/java/org/apache/drill/exec/expr/fn/HiveFunctionRegistry.java5
-rw-r--r--contrib/storage-hive/core/src/main/java/org/apache/drill/exec/store/hive/HiveFieldConverter.java112
-rw-r--r--contrib/storage-hive/core/src/main/java/org/apache/drill/exec/store/hive/HiveUtilities.java14
-rw-r--r--contrib/storage-hive/core/src/main/java/org/apache/drill/exec/store/hive/readers/HiveAbstractReader.java2
-rw-r--r--contrib/storage-hive/hive-exec-shade/pom.xml4
-rwxr-xr-xcontrib/storage-jdbc/src/main/java/org/apache/drill/exec/store/jdbc/JdbcRecordReader.java84
-rw-r--r--contrib/storage-mongo/src/main/java/org/apache/drill/exec/store/mongo/MongoCompareFunctionProcessor.java13
-rw-r--r--exec/java-exec/pom.xml49
-rw-r--r--exec/java-exec/src/main/codegen/config.fmpp1
-rw-r--r--exec/java-exec/src/main/codegen/data/Casts.tdd138
-rw-r--r--exec/java-exec/src/main/codegen/data/ComparisonTypesDecimal.tdd4
-rw-r--r--exec/java-exec/src/main/codegen/data/CountAggrTypes.tdd2
-rw-r--r--exec/java-exec/src/main/codegen/data/DecimalAggrTypes1.tdd49
-rw-r--r--exec/java-exec/src/main/codegen/data/DecimalAggrTypes2.tdd12
-rw-r--r--exec/java-exec/src/main/codegen/data/DecimalAggrTypes3.tdd43
-rw-r--r--exec/java-exec/src/main/codegen/data/MathFunc.tdd24
-rw-r--r--exec/java-exec/src/main/codegen/data/NumericTypes.tdd3
-rw-r--r--exec/java-exec/src/main/codegen/templates/CastHigh.java18
-rw-r--r--exec/java-exec/src/main/codegen/templates/DateIntervalFunctionTemplates/ToTimeStampFunction.java48
-rw-r--r--exec/java-exec/src/main/codegen/templates/Decimal/CastDecimalDenseDecimalSparse.java170
-rw-r--r--exec/java-exec/src/main/codegen/templates/Decimal/CastDecimalFloat.java69
-rw-r--r--exec/java-exec/src/main/codegen/templates/Decimal/CastDecimalInt.java88
-rw-r--r--exec/java-exec/src/main/codegen/templates/Decimal/CastDecimalSparseDecimalDense.java185
-rw-r--r--exec/java-exec/src/main/codegen/templates/Decimal/CastDecimalVarDecimal.java (renamed from exec/java-exec/src/main/codegen/templates/Decimal/CastDecimalSparseVarDecimal.java)59
-rw-r--r--exec/java-exec/src/main/codegen/templates/Decimal/CastDecimalVarchar.java203
-rw-r--r--exec/java-exec/src/main/codegen/templates/Decimal/CastDownwardDecimal.java209
-rw-r--r--exec/java-exec/src/main/codegen/templates/Decimal/CastFloatDecimal.java87
-rw-r--r--exec/java-exec/src/main/codegen/templates/Decimal/CastIntDecimal.java100
-rw-r--r--exec/java-exec/src/main/codegen/templates/Decimal/CastSrcDecimalSimple.java294
-rw-r--r--exec/java-exec/src/main/codegen/templates/Decimal/CastVarCharDecimal.java513
-rw-r--r--exec/java-exec/src/main/codegen/templates/Decimal/CastVarDecimalDecimal.java (renamed from exec/java-exec/src/main/codegen/templates/Decimal/CastDecimalSimilar.java)89
-rw-r--r--exec/java-exec/src/main/codegen/templates/Decimal/DecimalAggrTypeFunctions1.java356
-rw-r--r--exec/java-exec/src/main/codegen/templates/Decimal/DecimalAggrTypeFunctions2.java42
-rw-r--r--exec/java-exec/src/main/codegen/templates/Decimal/DecimalAggrTypeFunctions3.java184
-rw-r--r--exec/java-exec/src/main/codegen/templates/Decimal/DecimalFunctions.java2498
-rw-r--r--exec/java-exec/src/main/codegen/templates/MathFunctions.java10
-rw-r--r--exec/java-exec/src/main/codegen/templates/NumericToCharFunctions.java65
-rw-r--r--exec/java-exec/src/main/codegen/templates/ParquetOutputRecordWriter.java44
-rw-r--r--exec/java-exec/src/main/codegen/templates/ParquetTypeHelper.java29
-rw-r--r--exec/java-exec/src/main/codegen/templates/SqlAccessors.java31
-rw-r--r--exec/java-exec/src/main/codegen/templates/VarCharAggrFunctions1.java7
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/ExecConstants.java10
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/compile/bytecode/ScalarReplacementTypes.java4
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/compile/sig/ConstantExpressionIdentifier.java6
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/expr/CloneVisitor.java6
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/expr/EqualityVisitor.java17
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/expr/EvaluationVisitor.java48
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/expr/ExpressionTreeMaterializer.java62
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/expr/GetSetVectorHelper.java32
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/expr/HashVisitor.java11
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/expr/annotations/FunctionTemplate.java10
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/Hash32AsDouble.java161
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/Hash32Functions.java175
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/Hash32FunctionsWithSeed.java153
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/Hash32WithSeedAsDouble.java178
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/Hash64AsDouble.java189
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/Hash64Functions.java163
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/Hash64FunctionsWithSeed.java139
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/Hash64WithSeedAsDouble.java159
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/interpreter/InterpreterEvaluator.java7
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/output/DecimalReturnTypeInference.java113
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/ScanBatch.java4
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/join/JoinUtils.java13
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/join/NestedLoopJoinBatch.java7
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/planner/ParquetPartitionDescriptor.java26
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/planner/common/DrillValuesRelBase.java4
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillAggregateRel.java20
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillConstExecutor.java32
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillOptiq.java52
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillReduceAggregatesRule.java18
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/SqlConverter.java14
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/TypeInferenceUtils.java208
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/handlers/FindLimit0Visitor.java11
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/planner/types/DrillRelDataTypeSystem.java1
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/planner/types/decimal/DecimalScalePrecisionAddFunction.java (renamed from common/src/main/java/org/apache/drill/common/util/DecimalScalePrecisionAddFunction.java)8
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/planner/types/decimal/DecimalScalePrecisionDivideFunction.java38
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/planner/types/decimal/DecimalScalePrecisionModFunction.java (renamed from common/src/main/java/org/apache/drill/common/util/DecimalScalePrecisionModFunction.java)5
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/planner/types/decimal/DecimalScalePrecisionMulFunction.java (renamed from common/src/main/java/org/apache/drill/common/util/DecimalScalePrecisionMulFunction.java)11
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/planner/types/decimal/DrillBaseComputeScalePrecision.java (renamed from common/src/main/java/org/apache/drill/common/util/DrillBaseComputeScalePrecision.java)17
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/record/VectorContainer.java3
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/resolver/ExactFunctionResolver.java17
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/resolver/ResolverTypePrecedence.java38
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/resolver/TypeCastRules.java187
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/server/options/SystemOptionManager.java2
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/store/avro/AvroDrillTable.java48
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/store/avro/AvroRecordReader.java82
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/store/mock/ColumnDef.java2
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/ParquetFilterBuilder.java13
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/ParquetFormatPlugin.java6
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/ParquetReaderUtility.java2
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/ParquetRecordWriter.java39
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/columnreaders/ColumnReaderFactory.java80
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/columnreaders/FixedByteAlignedReader.java50
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/columnreaders/NullableFixedByteAlignedReaders.java130
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/columnreaders/ParquetFixedWidthDictionaryReaders.java97
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/columnreaders/ParquetToDrillTypeConverter.java21
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/columnreaders/VarLengthColumnReaders.java141
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/decimal/BinaryDecimalParquetValueWriter.java34
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/decimal/DecimalValueWriter.java61
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/decimal/FixedLenDecimalParquetValueWriter.java50
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/decimal/Int32DecimalParquetValueWriter.java51
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/decimal/Int64DecimalParquetValueWriter.java50
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet2/DrillParquetGroupConverter.java186
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/store/pojo/PojoDataType.java5
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/store/pojo/PojoWriters.java22
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/vector/complex/MapUtility.java7
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/work/ExecErrorConstants.java3
-rw-r--r--exec/java-exec/src/main/java/org/apache/drill/exec/work/prepare/PreparedStatementProvider.java1
-rw-r--r--exec/java-exec/src/main/resources/drill-module.conf4
-rw-r--r--exec/java-exec/src/test/java/org/apache/drill/PlanningBase.java19
-rw-r--r--exec/java-exec/src/test/java/org/apache/drill/TestDisabledFunctionality.java19
-rw-r--r--exec/java-exec/src/test/java/org/apache/drill/TestFrameworkTest.java2
-rw-r--r--exec/java-exec/src/test/java/org/apache/drill/TestFunctionsQuery.java87
-rw-r--r--exec/java-exec/src/test/java/org/apache/drill/exec/TestEmptyInputSql.java58
-rw-r--r--exec/java-exec/src/test/java/org/apache/drill/exec/TestWindowFunctions.java18
-rw-r--r--exec/java-exec/src/test/java/org/apache/drill/exec/cache/TestBatchSerialization.java1
-rw-r--r--exec/java-exec/src/test/java/org/apache/drill/exec/fn/impl/TestAggregateFunctions.java245
-rw-r--r--exec/java-exec/src/test/java/org/apache/drill/exec/fn/impl/TestCastFunctions.java158
-rw-r--r--exec/java-exec/src/test/java/org/apache/drill/exec/fn/impl/TestVarDecimalFunctions.java743
-rw-r--r--exec/java-exec/src/test/java/org/apache/drill/exec/physical/impl/TestDecimal.java26
-rw-r--r--exec/java-exec/src/test/java/org/apache/drill/exec/physical/impl/join/TestNestedLoopJoin.java26
-rw-r--r--exec/java-exec/src/test/java/org/apache/drill/exec/physical/impl/writer/TestParquetWriter.java326
-rw-r--r--exec/java-exec/src/test/java/org/apache/drill/exec/physical/impl/xsort/managed/TestCopier.java5
-rw-r--r--exec/java-exec/src/test/java/org/apache/drill/exec/physical/impl/xsort/managed/TestSorter.java9
-rw-r--r--exec/java-exec/src/test/java/org/apache/drill/exec/planner/logical/TestCaseNullableTypes.java18
-rw-r--r--exec/java-exec/src/test/java/org/apache/drill/exec/store/avro/AvroFormatTest.java72
-rw-r--r--exec/java-exec/src/test/java/org/apache/drill/exec/store/avro/AvroTestUtil.java26
-rw-r--r--exec/java-exec/src/test/java/org/apache/drill/exec/store/parquet/TestFixedlenDecimal.java25
-rw-r--r--exec/java-exec/src/test/java/org/apache/drill/exec/store/parquet/TestParquetComplex.java41
-rw-r--r--exec/java-exec/src/test/java/org/apache/drill/exec/store/parquet/TestVarlenDecimal.java105
-rw-r--r--exec/java-exec/src/test/java/org/apache/drill/exec/store/parquet/columnreaders/TestColumnReaderFactory.java10
-rw-r--r--exec/java-exec/src/test/java/org/apache/drill/test/rowSet/test/TestFillEmpties.java1
-rw-r--r--exec/java-exec/src/test/resources/decimal/cast_decimal_float.json4
-rw-r--r--exec/java-exec/src/test/resources/decimal/cast_decimal_int.json4
-rw-r--r--exec/java-exec/src/test/resources/decimal/cast_decimal_vardecimal.json56
-rw-r--r--exec/java-exec/src/test/resources/decimal/cast_float_decimal.json4
-rw-r--r--exec/java-exec/src/test/resources/decimal/cast_int_decimal.json8
-rw-r--r--exec/java-exec/src/test/resources/decimal/cast_simple_decimal.json4
-rw-r--r--exec/java-exec/src/test/resources/decimal/cast_vardecimal_decimal.json47
-rw-r--r--exec/java-exec/src/test/resources/decimal/simple_decimal_arithmetic.json4
-rw-r--r--exec/java-exec/src/test/resources/decimal/simple_decimal_math.json2
-rw-r--r--exec/java-exec/src/test/resources/decimal/test_decimal_complex.json4
-rw-r--r--exec/java-exec/src/test/resources/decimal/test_decimal_sort_complex.json2
-rw-r--r--exec/java-exec/src/test/resources/parquet/repeatedIntLondFixedLenBinaryDecimal.parquetbin0 -> 863 bytes
-rw-r--r--exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillMetaImpl.java2
-rw-r--r--exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/TypeConvertingSqlAccessor.java46
-rw-r--r--exec/jdbc/src/test/java/org/apache/drill/jdbc/ResultSetGetMethodConversionsTest.java9
-rw-r--r--exec/vector/src/main/codegen/data/ValueVectorTypes.tdd4
-rw-r--r--exec/vector/src/main/codegen/templates/AbstractFieldReader.java46
-rw-r--r--exec/vector/src/main/codegen/templates/AbstractFieldWriter.java15
-rw-r--r--exec/vector/src/main/codegen/templates/AbstractPromotableFieldWriter.java24
-rw-r--r--exec/vector/src/main/codegen/templates/BaseWriter.java6
-rw-r--r--exec/vector/src/main/codegen/templates/BasicTypeHelper.java39
-rw-r--r--exec/vector/src/main/codegen/templates/ColumnAccessors.java38
-rw-r--r--exec/vector/src/main/codegen/templates/ComplexCopier.java12
-rw-r--r--exec/vector/src/main/codegen/templates/ComplexReaders.java66
-rw-r--r--exec/vector/src/main/codegen/templates/ComplexWriters.java42
-rw-r--r--exec/vector/src/main/codegen/templates/HolderReaderImpl.java13
-rw-r--r--exec/vector/src/main/codegen/templates/ListWriters.java18
-rw-r--r--exec/vector/src/main/codegen/templates/MapWriters.java4
-rw-r--r--exec/vector/src/main/codegen/templates/NullReader.java48
-rw-r--r--exec/vector/src/main/codegen/templates/NullableValueVectors.java16
-rw-r--r--exec/vector/src/main/codegen/templates/RepeatedValueVectors.java18
-rw-r--r--exec/vector/src/main/codegen/templates/UnionListWriter.java12
-rw-r--r--exec/vector/src/main/codegen/templates/UnionWriter.java16
-rw-r--r--exec/vector/src/main/codegen/templates/ValueHolders.java141
-rw-r--r--exec/vector/src/main/codegen/templates/VariableLengthVectors.java22
-rw-r--r--exec/vector/src/main/java/org/apache/drill/exec/util/DecimalUtility.java204
-rw-r--r--exec/vector/src/main/java/org/apache/drill/exec/vector/ValueHolderHelper.java19
-rw-r--r--exec/vector/src/main/java/org/apache/drill/exec/vector/complex/impl/MapOrListWriterImpl.java5
-rw-r--r--logical/src/main/antlr3/org/apache/drill/common/expression/parser/ExprLexer.g2
-rw-r--r--logical/src/main/java/org/apache/drill/common/expression/ExpressionStringBuilder.java9
-rw-r--r--logical/src/main/java/org/apache/drill/common/expression/ValueExpressions.java43
-rw-r--r--logical/src/main/java/org/apache/drill/common/expression/visitors/AbstractExprVisitor.java6
-rw-r--r--logical/src/main/java/org/apache/drill/common/expression/visitors/AggregateChecker.java6
-rw-r--r--logical/src/main/java/org/apache/drill/common/expression/visitors/ConstantChecker.java10
-rw-r--r--logical/src/main/java/org/apache/drill/common/expression/visitors/ExprVisitor.java2
-rw-r--r--logical/src/main/java/org/apache/drill/common/expression/visitors/ExpressionValidator.java6
-rw-r--r--logical/src/main/java/org/apache/drill/common/expression/visitors/SimpleExprVisitor.java7
-rw-r--r--pom.xml39
-rw-r--r--protocol/src/main/java/org/apache/drill/common/types/MinorType.java4
196 files changed, 5435 insertions, 7613 deletions
diff --git a/common/src/main/java/org/apache/drill/common/types/Types.java b/common/src/main/java/org/apache/drill/common/types/Types.java
index ae269252f..1346f478d 100644
--- a/common/src/main/java/org/apache/drill/common/types/Types.java
+++ b/common/src/main/java/org/apache/drill/common/types/Types.java
@@ -318,6 +318,7 @@ public class Types {
case DECIMAL28SPARSE:
case DECIMAL38DENSE:
case DECIMAL38SPARSE:
+ case VARDECIMAL:
case MONEY: return 2 + precision; // precision of the column plus a sign and a decimal point
case VARCHAR:
@@ -575,7 +576,7 @@ public class Types {
case "double":
return MinorType.FLOAT8;
case "decimal":
- return MinorType.DECIMAL38SPARSE;
+ return MinorType.VARDECIMAL;
case "symbol":
case "char":
case "utf8":
@@ -638,13 +639,9 @@ public class Types {
case FLOAT8:
return "double";
case VARDECIMAL:
- return "decimal";
case DECIMAL9:
- return "decimal";
case DECIMAL18:
- return "decimal";
case DECIMAL28SPARSE:
- return "decimal";
case DECIMAL38SPARSE:
return "decimal";
case VARCHAR:
diff --git a/common/src/main/java/org/apache/drill/common/util/CoreDecimalUtility.java b/common/src/main/java/org/apache/drill/common/util/CoreDecimalUtility.java
index 4b4b950ff..0e8a1c721 100644
--- a/common/src/main/java/org/apache/drill/common/util/CoreDecimalUtility.java
+++ b/common/src/main/java/org/apache/drill/common/util/CoreDecimalUtility.java
@@ -31,42 +31,6 @@ public class CoreDecimalUtility {
return (input.unscaledValue().longValue());
}
- public static int getMaxPrecision(TypeProtos.MinorType decimalType) {
- if (decimalType == TypeProtos.MinorType.DECIMAL9) {
- return 9;
- } else if (decimalType == TypeProtos.MinorType.DECIMAL18) {
- return 18;
- } else if (decimalType == TypeProtos.MinorType.DECIMAL28SPARSE) {
- return 28;
- } else if (decimalType == TypeProtos.MinorType.DECIMAL38SPARSE) {
- return 38;
- }
- return 0;
- }
-
- /*
- * Function returns the Minor decimal type given the precision
- */
- public static TypeProtos.MinorType getDecimalDataType(int precision) {
- if (precision <= 9) {
- return TypeProtos.MinorType.DECIMAL9;
- } else if (precision <= 18) {
- return TypeProtos.MinorType.DECIMAL18;
- } else if (precision <= 28) {
- return TypeProtos.MinorType.DECIMAL28SPARSE;
- } else {
- return TypeProtos.MinorType.DECIMAL38SPARSE;
- }
- }
-
- /*
- * Given a precision it provides the max precision of that decimal data type;
- * For eg: given the precision 12, we would use DECIMAL18 to store the data
- * which has a max precision range of 18 digits
- */
- public static int getPrecisionRange(int precision) {
- return getMaxPrecision(getDecimalDataType(precision));
- }
public static int getDecimal9FromBigDecimal(BigDecimal input, int scale, int precision) {
// Truncate/ or pad to set the input to the correct scale
input = input.setScale(scale, BigDecimal.ROUND_HALF_UP);
@@ -82,11 +46,10 @@ public class CoreDecimalUtility {
}
public static boolean isDecimalType(TypeProtos.MinorType minorType) {
- if (minorType == TypeProtos.MinorType.VARDECIMAL || minorType == TypeProtos.MinorType.DECIMAL9 ||
- minorType == TypeProtos.MinorType.DECIMAL18 || minorType == TypeProtos.MinorType.DECIMAL28SPARSE ||
- minorType == TypeProtos.MinorType.DECIMAL38SPARSE) {
- return true;
- }
- return false;
+ return minorType == TypeProtos.MinorType.VARDECIMAL ||
+ minorType == TypeProtos.MinorType.DECIMAL9 ||
+ minorType == TypeProtos.MinorType.DECIMAL18 ||
+ minorType == TypeProtos.MinorType.DECIMAL28SPARSE ||
+ minorType == TypeProtos.MinorType.DECIMAL38SPARSE;
}
}
diff --git a/common/src/main/java/org/apache/drill/common/util/DecimalScalePrecisionDivideFunction.java b/common/src/main/java/org/apache/drill/common/util/DecimalScalePrecisionDivideFunction.java
deleted file mode 100644
index 74e6dbf22..000000000
--- a/common/src/main/java/org/apache/drill/common/util/DecimalScalePrecisionDivideFunction.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.drill.common.util;
-
-
-/*
- * Here we compute the scale and precision of the output decimal data type
- * based on the input scale and precision. Since division operation can be
- * a multiplication operation we compute the scale to be the sum of the inputs.
- * Eg: Input1 : precision = 5, scale = 3 ==> max integer digits = 2
- * Input2 : precision = 7, scale = 4 ==> max integer digits = 3
- *
- * Output: max integer digits ==> 2 (left integer digits) + 4 (right scale, when divide results in multiplication)
- * max scale ==> 3 + 4 = 7
- *
- * Minimum precision required ==> 6 + 7 = 13
- *
- * Since our minimum precision required is 13, we will use DECIMAL18 as the output type
- * but since this is divide we will grant the remaining digits in DECIMAL18 to scale
- * so we have the following
- * output scale ==> 7 + (18 - 13) = 12
- * output precision ==> 18
- */
-public class DecimalScalePrecisionDivideFunction extends DrillBaseComputeScalePrecision {
-
- public DecimalScalePrecisionDivideFunction(int leftPrecision, int leftScale, int rightPrecision, int rightScale) {
- super(leftPrecision, leftScale, rightPrecision, rightScale);
- }
-
- @Override
- public void computeScalePrecision(int leftPrecision, int leftScale, int rightPrecision, int rightScale) {
-
- // compute the output scale and precision here
- outputScale = leftScale + rightScale;
- int leftIntegerDigits = leftPrecision - leftScale;
- int maxResultIntegerDigits = leftIntegerDigits + rightScale;
-
-
- outputPrecision = CoreDecimalUtility.getPrecisionRange(outputScale + maxResultIntegerDigits);
-
- // Output precision should be greater or equal to the input precision
- outputPrecision = Math.max(outputPrecision, Math.max(leftPrecision, rightPrecision));
-
- // Try and increase the scale if we have any room
- outputScale = (outputPrecision - maxResultIntegerDigits >= 0) ? (outputPrecision - maxResultIntegerDigits) : 0;
- }
-}
diff --git a/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/mapr/db/json/CompareFunctionsProcessor.java b/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/mapr/db/json/CompareFunctionsProcessor.java
index 36e7309fe..341093947 100644
--- a/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/mapr/db/json/CompareFunctionsProcessor.java
+++ b/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/mapr/db/json/CompareFunctionsProcessor.java
@@ -31,12 +31,12 @@ import org.apache.drill.common.expression.ValueExpressions.LongExpression;
import org.apache.drill.common.expression.ValueExpressions.QuotedString;
import org.apache.drill.common.expression.ValueExpressions.TimeExpression;
import org.apache.drill.common.expression.ValueExpressions.TimeStampExpression;
+import org.apache.drill.common.expression.ValueExpressions.VarDecimalExpression;
import org.apache.drill.common.expression.visitors.AbstractExprVisitor;
import org.joda.time.LocalTime;
import org.ojai.Value;
import org.ojai.types.ODate;
import org.ojai.types.OTime;
-import org.ojai.types.OTimestamp;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
@@ -173,6 +173,14 @@ class CompareFunctionsProcessor extends AbstractExprVisitor<Boolean, LogicalExpr
return true;
}
+ // MaprDB does not support decimals completely, therefore double value is used.
+ // See com.mapr.db.impl.ConditionImpl.is(FieldPath path, QueryCondition.Op op, BigDecimal value) method
+ if (valueArg instanceof VarDecimalExpression) {
+ this.value = KeyValueBuilder.initFrom(((VarDecimalExpression) valueArg).getBigDecimal().doubleValue());
+ this.path = path;
+ return true;
+ }
+
if (valueArg instanceof TimeStampExpression) {
// disable pushdown of TimeStampExpression type until bug 22824 is fixed.
//
@@ -196,6 +204,7 @@ class CompareFunctionsProcessor extends AbstractExprVisitor<Boolean, LogicalExpr
.add(LongExpression.class)
.add(QuotedString.class)
.add(TimeExpression.class)
+ .add(VarDecimalExpression.class)
.build();
}
diff --git a/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/mapr/db/json/MaprDBJsonRecordReader.java b/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/mapr/db/json/MaprDBJsonRecordReader.java
index 9f93e18b3..fde4d2850 100644
--- a/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/mapr/db/json/MaprDBJsonRecordReader.java
+++ b/contrib/format-maprdb/src/main/java/org/apache/drill/exec/store/mapr/db/json/MaprDBJsonRecordReader.java
@@ -304,7 +304,7 @@ public class MaprDBJsonRecordReader extends AbstractRecordReader {
writeDouble(writer, fieldName, reader);
break;
case DECIMAL:
- throw unsupportedError("Decimal type is currently not supported.");
+ writeDecimal(writer, fieldName, reader);
case DATE:
writeDate(writer, fieldName, reader);
break;
@@ -365,6 +365,15 @@ public class MaprDBJsonRecordReader extends AbstractRecordReader {
}
}
+ private void writeDecimal(MapOrListWriterImpl writer, String fieldName, DBDocumentReaderBase reader) {
+ if (allTextMode) {
+ writeString(writer, fieldName, String.valueOf(reader.getDecimal()));
+ } else {
+ writer.varDecimal(fieldName, reader.getDecimalScale(), reader.getDecimalPrecision())
+ .writeVarDecimal(reader.getDecimal());
+ }
+ }
+
private void writeFloat(MapOrListWriterImpl writer, String fieldName, DBDocumentReaderBase reader) {
if (allTextMode) {
writeString(writer, fieldName, String.valueOf(reader.getFloat()));
diff --git a/contrib/native/client/src/clientlib/decimalUtils.cpp b/contrib/native/client/src/clientlib/decimalUtils.cpp
index 6e26c5528..465eefeb5 100644
--- a/contrib/native/client/src/clientlib/decimalUtils.cpp
+++ b/contrib/native/client/src/clientlib/decimalUtils.cpp
@@ -95,6 +95,21 @@ DecimalValue getDecimalValueFromByteBuf(SlicedByteBuf& data, size_t startIndex,
return val;
}
+DecimalValue getDecimalValueFromByteBuf(SlicedByteBuf& data, size_t length, int scale) {
+
+ cpp_int decimalDigits;
+ // casts the first unsigned byte to signed to determine the sign of the value
+ decimalDigits = decimalDigits | cpp_int(static_cast<int8_t>(data.getByte(0))) << (length - 1) * 8;
+ for (int pos = length - 1; pos > 0; pos--) {
+ decimalDigits = decimalDigits | cpp_int(data.getByte(pos)) << (length - pos - 1) * 8;
+ }
+
+ DecimalValue val;
+ val.m_unscaledValue = decimalDigits;
+ val.m_scale = scale;
+ return val;
+}
+
DecimalValue getDecimalValueFromDense(SlicedByteBuf& data, size_t startIndex, int nDecimalDigits, int scale, int maxPrecision, int width)
{
/* This method converts the dense representation to
diff --git a/contrib/native/client/src/clientlib/fieldmeta.cpp b/contrib/native/client/src/clientlib/fieldmeta.cpp
index 797b038eb..b48f3bc06 100644
--- a/contrib/native/client/src/clientlib/fieldmeta.cpp
+++ b/contrib/native/client/src/clientlib/fieldmeta.cpp
@@ -71,6 +71,7 @@ static const std::string& getSQLType(common::MinorType type, common::DataMode mo
case common::DECIMAL28DENSE:
case common::DECIMAL28SPARSE:
case common::DECIMAL38DENSE:
+ case common::VARDECIMAL:
case common::DECIMAL38SPARSE: return SQLDecimal;
case common::VARCHAR: return SQLVarchar;
@@ -133,6 +134,7 @@ static bool isSigned(common::MinorType type, common::DataMode mode) {
case common::DECIMAL28DENSE:
case common::DECIMAL38DENSE:
case common::DECIMAL38SPARSE:
+ case common::VARDECIMAL:
case common::INTERVALYEAR:
case common::INTERVALDAY:
@@ -304,6 +306,7 @@ static uint32_t getDisplaySize(const ::common::MajorType& type) {
case ::common::DECIMAL28SPARSE:
case ::common::DECIMAL38DENSE:
case ::common::DECIMAL38SPARSE:
+ case ::common::VARDECIMAL:
case ::common::MONEY: return 2 + precision; // precision of the column plus a sign and a decimal point
case ::common::VARCHAR:
diff --git a/contrib/native/client/src/clientlib/metadata.cpp b/contrib/native/client/src/clientlib/metadata.cpp
index 637c83b33..0f1cf2eab 100644
--- a/contrib/native/client/src/clientlib/metadata.cpp
+++ b/contrib/native/client/src/clientlib/metadata.cpp
@@ -110,6 +110,7 @@ static const convert_support_set s_convertMap = boost::assign::list_of
(ConvertSupport(common::TINYINT, common::DECIMAL18))
(ConvertSupport(common::TINYINT, common::DECIMAL28SPARSE))
(ConvertSupport(common::TINYINT, common::DECIMAL38SPARSE))
+ (ConvertSupport(common::TINYINT, common::VARDECIMAL))
(ConvertSupport(common::TINYINT, common::DATE))
(ConvertSupport(common::TINYINT, common::TIME))
(ConvertSupport(common::TINYINT, common::TIMESTAMP))
@@ -128,6 +129,7 @@ static const convert_support_set s_convertMap = boost::assign::list_of
(ConvertSupport(common::SMALLINT, common::DECIMAL18))
(ConvertSupport(common::SMALLINT, common::DECIMAL28SPARSE))
(ConvertSupport(common::SMALLINT, common::DECIMAL38SPARSE))
+ (ConvertSupport(common::SMALLINT, common::VARDECIMAL))
(ConvertSupport(common::SMALLINT, common::DATE))
(ConvertSupport(common::SMALLINT, common::TIME))
(ConvertSupport(common::SMALLINT, common::TIMESTAMP))
@@ -146,6 +148,7 @@ static const convert_support_set s_convertMap = boost::assign::list_of
(ConvertSupport(common::INT, common::DECIMAL18))
(ConvertSupport(common::INT, common::DECIMAL28SPARSE))
(ConvertSupport(common::INT, common::DECIMAL38SPARSE))
+ (ConvertSupport(common::INT, common::VARDECIMAL))
(ConvertSupport(common::INT, common::DATE))
(ConvertSupport(common::INT, common::TIME))
(ConvertSupport(common::INT, common::TIMESTAMP))
@@ -164,6 +167,7 @@ static const convert_support_set s_convertMap = boost::assign::list_of
(ConvertSupport(common::BIGINT, common::DECIMAL18))
(ConvertSupport(common::BIGINT, common::DECIMAL28SPARSE))
(ConvertSupport(common::BIGINT, common::DECIMAL38SPARSE))
+ (ConvertSupport(common::BIGINT, common::VARDECIMAL))
(ConvertSupport(common::BIGINT, common::DATE))
(ConvertSupport(common::BIGINT, common::TIME))
(ConvertSupport(common::BIGINT, common::TIMESTAMP))
@@ -182,6 +186,7 @@ static const convert_support_set s_convertMap = boost::assign::list_of
(ConvertSupport(common::DECIMAL9, common::DECIMAL18))
(ConvertSupport(common::DECIMAL9, common::DECIMAL28SPARSE))
(ConvertSupport(common::DECIMAL9, common::DECIMAL38SPARSE))
+ (ConvertSupport(common::DECIMAL9, common::VARDECIMAL))
(ConvertSupport(common::DECIMAL9, common::DATE))
(ConvertSupport(common::DECIMAL9, common::TIME))
(ConvertSupport(common::DECIMAL9, common::TIMESTAMP))
@@ -200,6 +205,7 @@ static const convert_support_set s_convertMap = boost::assign::list_of
(ConvertSupport(common::DECIMAL18, common::DECIMAL18))
(ConvertSupport(common::DECIMAL18, common::DECIMAL28SPARSE))
(ConvertSupport(common::DECIMAL18, common::DECIMAL38SPARSE))
+ (ConvertSupport(common::DECIMAL18, common::VARDECIMAL))
(ConvertSupport(common::DECIMAL18, common::DATE))
(ConvertSupport(common::DECIMAL18, common::TIME))
(ConvertSupport(common::DECIMAL18, common::TIMESTAMP))
@@ -218,6 +224,7 @@ static const convert_support_set s_convertMap = boost::assign::list_of
(ConvertSupport(common::DECIMAL28SPARSE, common::DECIMAL18))
(ConvertSupport(common::DECIMAL28SPARSE, common::DECIMAL28SPARSE))
(ConvertSupport(common::DECIMAL28SPARSE, common::DECIMAL38SPARSE))
+ (ConvertSupport(common::DECIMAL28SPARSE, common::VARDECIMAL))
(ConvertSupport(common::DECIMAL28SPARSE, common::DATE))
(ConvertSupport(common::DECIMAL28SPARSE, common::TIME))
(ConvertSupport(common::DECIMAL28SPARSE, common::TIMESTAMP))
@@ -236,6 +243,7 @@ static const convert_support_set s_convertMap = boost::assign::list_of
(ConvertSupport(common::DECIMAL38SPARSE, common::DECIMAL18))
(ConvertSupport(common::DECIMAL38SPARSE, common::DECIMAL28SPARSE))
(ConvertSupport(common::DECIMAL38SPARSE, common::DECIMAL38SPARSE))
+ (ConvertSupport(common::DECIMAL38SPARSE, common::VARDECIMAL))
(ConvertSupport(common::DECIMAL38SPARSE, common::DATE))
(ConvertSupport(common::DECIMAL38SPARSE, common::TIME))
(ConvertSupport(common::DECIMAL38SPARSE, common::TIMESTAMP))
@@ -248,12 +256,32 @@ static const convert_support_set s_convertMap = boost::assign::list_of
(ConvertSupport(common::DECIMAL38SPARSE, common::VARBINARY))
(ConvertSupport(common::DECIMAL38SPARSE, common::INTERVALYEAR))
(ConvertSupport(common::DECIMAL38SPARSE, common::INTERVALDAY))
+ (ConvertSupport(common::VARDECIMAL, common::INT))
+ (ConvertSupport(common::VARDECIMAL, common::BIGINT))
+ (ConvertSupport(common::VARDECIMAL, common::DECIMAL9))
+ (ConvertSupport(common::VARDECIMAL, common::DECIMAL18))
+ (ConvertSupport(common::VARDECIMAL, common::DECIMAL28SPARSE))
+ (ConvertSupport(common::VARDECIMAL, common::DECIMAL38SPARSE))
+ (ConvertSupport(common::VARDECIMAL, common::VARDECIMAL))
+ (ConvertSupport(common::VARDECIMAL, common::DATE))
+ (ConvertSupport(common::VARDECIMAL, common::TIME))
+ (ConvertSupport(common::VARDECIMAL, common::TIMESTAMP))
+ (ConvertSupport(common::VARDECIMAL, common::INTERVAL))
+ (ConvertSupport(common::VARDECIMAL, common::FLOAT4))
+ (ConvertSupport(common::VARDECIMAL, common::FLOAT8))
+ (ConvertSupport(common::VARDECIMAL, common::BIT))
+ (ConvertSupport(common::VARDECIMAL, common::VARCHAR))
+ (ConvertSupport(common::VARDECIMAL, common::VAR16CHAR))
+ (ConvertSupport(common::VARDECIMAL, common::VARBINARY))
+ (ConvertSupport(common::VARDECIMAL, common::INTERVALYEAR))
+ (ConvertSupport(common::VARDECIMAL, common::INTERVALDAY))
(ConvertSupport(common::MONEY, common::INT))
(ConvertSupport(common::MONEY, common::BIGINT))
(ConvertSupport(common::MONEY, common::DECIMAL9))
(ConvertSupport(common::MONEY, common::DECIMAL18))
(ConvertSupport(common::MONEY, common::DECIMAL28SPARSE))
(ConvertSupport(common::MONEY, common::DECIMAL38SPARSE))
+ (ConvertSupport(common::MONEY, common::VARDECIMAL))
(ConvertSupport(common::MONEY, common::DATE))
(ConvertSupport(common::MONEY, common::TIME))
(ConvertSupport(common::MONEY, common::TIMESTAMP))
@@ -272,6 +300,7 @@ static const convert_support_set s_convertMap = boost::assign::list_of
(ConvertSupport(common::DATE, common::DECIMAL18))
(ConvertSupport(common::DATE, common::DECIMAL28SPARSE))
(ConvertSupport(common::DATE, common::DECIMAL38SPARSE))
+ (ConvertSupport(common::DATE, common::VARDECIMAL))
(ConvertSupport(common::DATE, common::DATE))
(ConvertSupport(common::DATE, common::TIME))
(ConvertSupport(common::DATE, common::TIMESTAMP))
@@ -290,6 +319,7 @@ static const convert_support_set s_convertMap = boost::assign::list_of
(ConvertSupport(common::TIME, common::DECIMAL18))
(ConvertSupport(common::TIME, common::DECIMAL28SPARSE))
(ConvertSupport(common::TIME, common::DECIMAL38SPARSE))
+ (ConvertSupport(common::TIME, common::VARDECIMAL))
(ConvertSupport(common::TIME, common::DATE))
(ConvertSupport(common::TIME, common::TIME))
(ConvertSupport(common::TIME, common::TIMESTAMP))
@@ -308,6 +338,7 @@ static const convert_support_set s_convertMap = boost::assign::list_of
(ConvertSupport(common::TIMESTAMPTZ, common::DECIMAL18))
(ConvertSupport(common::TIMESTAMPTZ, common::DECIMAL28SPARSE))
(ConvertSupport(common::TIMESTAMPTZ, common::DECIMAL38SPARSE))
+ (ConvertSupport(common::TIMESTAMPTZ, common::VARDECIMAL))
(ConvertSupport(common::TIMESTAMPTZ, common::DATE))
(ConvertSupport(common::TIMESTAMPTZ, common::TIME))
(ConvertSupport(common::TIMESTAMPTZ, common::TIMESTAMP))
@@ -326,6 +357,7 @@ static const convert_support_set s_convertMap = boost::assign::list_of
(ConvertSupport(common::TIMESTAMP, common::DECIMAL18))
(ConvertSupport(common::TIMESTAMP, common::DECIMAL28SPARSE))
(ConvertSupport(common::TIMESTAMP, common::DECIMAL38SPARSE))
+ (ConvertSupport(common::TIMESTAMP, common::VARDECIMAL))
(ConvertSupport(common::TIMESTAMP, common::DATE))
(ConvertSupport(common::TIMESTAMP, common::TIME))
(ConvertSupport(common::TIMESTAMP, common::TIMESTAMP))
@@ -344,6 +376,7 @@ static const convert_support_set s_convertMap = boost::assign::list_of
(ConvertSupport(common::INTERVAL, common::DECIMAL18))
(ConvertSupport(common::INTERVAL, common::DECIMAL28SPARSE))
(ConvertSupport(common::INTERVAL, common::DECIMAL38SPARSE))
+ (ConvertSupport(common::INTERVAL, common::VARDECIMAL))
(ConvertSupport(common::INTERVAL, common::DATE))
(ConvertSupport(common::INTERVAL, common::TIME))
(ConvertSupport(common::INTERVAL, common::TIMESTAMP))
@@ -362,6 +395,7 @@ static const convert_support_set s_convertMap = boost::assign::list_of
(ConvertSupport(common::FLOAT4, common::DECIMAL18))
(ConvertSupport(common::FLOAT4, common::DECIMAL28SPARSE))
(ConvertSupport(common::FLOAT4, common::DECIMAL38SPARSE))
+ (ConvertSupport(common::FLOAT4, common::VARDECIMAL))
(ConvertSupport(common::FLOAT4, common::DATE))
(ConvertSupport(common::FLOAT4, common::TIME))
(ConvertSupport(common::FLOAT4, common::TIMESTAMP))
@@ -380,6 +414,7 @@ static const convert_support_set s_convertMap = boost::assign::list_of
(ConvertSupport(common::FLOAT8, common::DECIMAL18))
(ConvertSupport(common::FLOAT8, common::DECIMAL28SPARSE))
(ConvertSupport(common::FLOAT8, common::DECIMAL38SPARSE))
+ (ConvertSupport(common::FLOAT8, common::VARDECIMAL))
(ConvertSupport(common::FLOAT8, common::DATE))
(ConvertSupport(common::FLOAT8, common::TIME))
(ConvertSupport(common::FLOAT8, common::TIMESTAMP))
@@ -399,6 +434,7 @@ static const convert_support_set s_convertMap = boost::assign::list_of
(ConvertSupport(common::BIT, common::DECIMAL18))
(ConvertSupport(common::BIT, common::DECIMAL28SPARSE))
(ConvertSupport(common::BIT, common::DECIMAL38SPARSE))
+ (ConvertSupport(common::BIT, common::VARDECIMAL))
(ConvertSupport(common::BIT, common::DATE))
(ConvertSupport(common::BIT, common::TIME))
(ConvertSupport(common::BIT, common::TIMESTAMP))
@@ -418,6 +454,7 @@ static const convert_support_set s_convertMap = boost::assign::list_of
(ConvertSupport(common::FIXEDCHAR, common::DECIMAL18))
(ConvertSupport(common::FIXEDCHAR, common::DECIMAL28SPARSE))
(ConvertSupport(common::FIXEDCHAR, common::DECIMAL38SPARSE))
+ (ConvertSupport(common::FIXEDCHAR, common::VARDECIMAL))
(ConvertSupport(common::FIXEDCHAR, common::DATE))
(ConvertSupport(common::FIXEDCHAR, common::TIME))
(ConvertSupport(common::FIXEDCHAR, common::TIMESTAMP))
@@ -437,6 +474,7 @@ static const convert_support_set s_convertMap = boost::assign::list_of
(ConvertSupport(common::FIXED16CHAR, common::DECIMAL18))
(ConvertSupport(common::FIXED16CHAR, common::DECIMAL28SPARSE))
(ConvertSupport(common::FIXED16CHAR, common::DECIMAL38SPARSE))
+ (ConvertSupport(common::FIXED16CHAR, common::VARDECIMAL))
(ConvertSupport(common::FIXED16CHAR, common::DATE))
(ConvertSupport(common::FIXED16CHAR, common::TIME))
(ConvertSupport(common::FIXED16CHAR, common::TIMESTAMP))
@@ -455,6 +493,7 @@ static const convert_support_set s_convertMap = boost::assign::list_of
(ConvertSupport(common::FIXEDBINARY, common::DECIMAL18))
(ConvertSupport(common::FIXEDBINARY, common::DECIMAL28SPARSE))
(ConvertSupport(common::FIXEDBINARY, common::DECIMAL38SPARSE))
+ (ConvertSupport(common::FIXEDBINARY, common::VARDECIMAL))
(ConvertSupport(common::FIXEDBINARY, common::DATE))
(ConvertSupport(common::FIXEDBINARY, common::TIME))
(ConvertSupport(common::FIXEDBINARY, common::TIMESTAMP))
@@ -474,6 +513,7 @@ static const convert_support_set s_convertMap = boost::assign::list_of
(ConvertSupport(common::VARCHAR, common::DECIMAL18))
(ConvertSupport(common::VARCHAR, common::DECIMAL28SPARSE))
(ConvertSupport(common::VARCHAR, common::DECIMAL38SPARSE))
+ (ConvertSupport(common::VARCHAR, common::VARDECIMAL))
(ConvertSupport(common::VARCHAR, common::DATE))
(ConvertSupport(common::VARCHAR, common::TIME))
(ConvertSupport(common::VARCHAR, common::TIMESTAMP))
@@ -493,6 +533,7 @@ static const convert_support_set s_convertMap = boost::assign::list_of
(ConvertSupport(common::VAR16CHAR, common::DECIMAL18))
(ConvertSupport(common::VAR16CHAR, common::DECIMAL28SPARSE))
(ConvertSupport(common::VAR16CHAR, common::DECIMAL38SPARSE))
+ (ConvertSupport(common::VAR16CHAR, common::VARDECIMAL))
(ConvertSupport(common::VAR16CHAR, common::DATE))
(ConvertSupport(common::VAR16CHAR, common::TIME))
(ConvertSupport(common::VAR16CHAR, common::TIMESTAMP))
@@ -511,6 +552,7 @@ static const convert_support_set s_convertMap = boost::assign::list_of
(ConvertSupport(common::VARBINARY, common::DECIMAL18))
(ConvertSupport(common::VARBINARY, common::DECIMAL28SPARSE))
(ConvertSupport(common::VARBINARY, common::DECIMAL38SPARSE))
+ (ConvertSupport(common::VARBINARY, common::VARDECIMAL))
(ConvertSupport(common::VARBINARY, common::DATE))
(ConvertSupport(common::VARBINARY, common::TIME))
(ConvertSupport(common::VARBINARY, common::TIMESTAMP))
@@ -529,6 +571,7 @@ static const convert_support_set s_convertMap = boost::assign::list_of
(ConvertSupport(common::UINT1, common::DECIMAL18))
(ConvertSupport(common::UINT1, common::DECIMAL28SPARSE))
(ConvertSupport(common::UINT1, common::DECIMAL38SPARSE))
+ (ConvertSupport(common::UINT1, common::VARDECIMAL))
(ConvertSupport(common::UINT1, common::DATE))
(ConvertSupport(common::UINT1, common::TIME))
(ConvertSupport(common::UINT1, common::TIMESTAMP))
@@ -547,6 +590,7 @@ static const convert_support_set s_convertMap = boost::assign::list_of
(ConvertSupport(common::UINT2, common::DECIMAL18))
(ConvertSupport(common::UINT2, common::DECIMAL28SPARSE))
(ConvertSupport(common::UINT2, common::DECIMAL38SPARSE))
+ (ConvertSupport(common::UINT2, common::VARDECIMAL))
(ConvertSupport(common::UINT2, common::DATE))
(ConvertSupport(common::UINT2, common::TIME))
(ConvertSupport(common::UINT2, common::TIMESTAMP))
@@ -565,6 +609,7 @@ static const convert_support_set s_convertMap = boost::assign::list_of
(ConvertSupport(common::UINT4, common::DECIMAL18))
(ConvertSupport(common::UINT4, common::DECIMAL28SPARSE))
(ConvertSupport(common::UINT4, common::DECIMAL38SPARSE))
+ (ConvertSupport(common::UINT4, common::VARDECIMAL))
(ConvertSupport(common::UINT4, common::DATE))
(ConvertSupport(common::UINT4, common::TIME))
(ConvertSupport(common::UINT4, common::TIMESTAMP))
@@ -583,6 +628,7 @@ static const convert_support_set s_convertMap = boost::assign::list_of
(ConvertSupport(common::UINT8, common::DECIMAL18))
(ConvertSupport(common::UINT8, common::DECIMAL28SPARSE))
(ConvertSupport(common::UINT8, common::DECIMAL38SPARSE))
+ (ConvertSupport(common::UINT8, common::VARDECIMAL))
(ConvertSupport(common::UINT8, common::DATE))
(ConvertSupport(common::UINT8, common::TIME))
(ConvertSupport(common::UINT8, common::TIMESTAMP))
@@ -601,6 +647,7 @@ static const convert_support_set s_convertMap = boost::assign::list_of
(ConvertSupport(common::DECIMAL28DENSE, common::DECIMAL18))
(ConvertSupport(common::DECIMAL28DENSE, common::DECIMAL28SPARSE))
(ConvertSupport(common::DECIMAL28DENSE, common::DECIMAL38SPARSE))
+ (ConvertSupport(common::DECIMAL28DENSE, common::VARDECIMAL))
(ConvertSupport(common::DECIMAL28DENSE, common::DATE))
(ConvertSupport(common::DECIMAL28DENSE, common::TIME))
(ConvertSupport(common::DECIMAL28DENSE, common::TIMESTAMP))
@@ -619,6 +666,7 @@ static const convert_support_set s_convertMap = boost::assign::list_of
(ConvertSupport(common::DECIMAL38DENSE, common::DECIMAL18))
(ConvertSupport(common::DECIMAL38DENSE, common::DECIMAL28SPARSE))
(ConvertSupport(common::DECIMAL38DENSE, common::DECIMAL38SPARSE))
+ (ConvertSupport(common::DECIMAL38DENSE, common::VARDECIMAL))
(ConvertSupport(common::DECIMAL38DENSE, common::DATE))
(ConvertSupport(common::DECIMAL38DENSE, common::TIME))
(ConvertSupport(common::DECIMAL38DENSE, common::TIMESTAMP))
@@ -638,6 +686,7 @@ static const convert_support_set s_convertMap = boost::assign::list_of
(ConvertSupport(common::DM_UNKNOWN, common::DECIMAL18))
(ConvertSupport(common::DM_UNKNOWN, common::DECIMAL28SPARSE))
(ConvertSupport(common::DM_UNKNOWN, common::DECIMAL38SPARSE))
+ (ConvertSupport(common::DM_UNKNOWN, common::VARDECIMAL))
(ConvertSupport(common::DM_UNKNOWN, common::DATE))
(ConvertSupport(common::DM_UNKNOWN, common::TIME))
(ConvertSupport(common::DM_UNKNOWN, common::TIMESTAMP))
@@ -656,6 +705,7 @@ static const convert_support_set s_convertMap = boost::assign::list_of
(ConvertSupport(common::INTERVALYEAR, common::DECIMAL18))
(ConvertSupport(common::INTERVALYEAR, common::DECIMAL28SPARSE))
(ConvertSupport(common::INTERVALYEAR, common::DECIMAL38SPARSE))
+ (ConvertSupport(common::INTERVALYEAR, common::VARDECIMAL))
(ConvertSupport(common::INTERVALYEAR, common::DATE))
(ConvertSupport(common::INTERVALYEAR, common::TIME))
(ConvertSupport(common::INTERVALYEAR, common::TIMESTAMP))
@@ -674,6 +724,7 @@ static const convert_support_set s_convertMap = boost::assign::list_of
(ConvertSupport(common::INTERVALDAY, common::DECIMAL18))
(ConvertSupport(common::INTERVALDAY, common::DECIMAL28SPARSE))
(ConvertSupport(common::INTERVALDAY, common::DECIMAL38SPARSE))
+ (ConvertSupport(common::INTERVALDAY, common::VARDECIMAL))
(ConvertSupport(common::INTERVALDAY, common::DATE))
(ConvertSupport(common::INTERVALDAY, common::TIME))
(ConvertSupport(common::INTERVALDAY, common::TIMESTAMP))
diff --git a/contrib/native/client/src/clientlib/recordBatch.cpp b/contrib/native/client/src/clientlib/recordBatch.cpp
index d7c196d00..1c897d694 100644
--- a/contrib/native/client/src/clientlib/recordBatch.cpp
+++ b/contrib/native/client/src/clientlib/recordBatch.cpp
@@ -201,6 +201,8 @@ ValueVectorBase* ValueVectorFactory::allocateValueVector(const Drill::FieldMetad
return new ValueVectorDecimal28Sparse(b,f.getValueCount(), f.getScale());
case common::DECIMAL38SPARSE:
return new ValueVectorDecimal38Sparse(b,f.getValueCount(), f.getScale());
+ case common::VARDECIMAL:
+ return new ValueVectorVarDecimal(b, f.getValueCount(), f.getScale());
case common::DATE:
return new ValueVectorTyped<DateHolder, int64_t>(b,f.getValueCount());
case common::TIMESTAMP:
@@ -251,6 +253,8 @@ ValueVectorBase* ValueVectorFactory::allocateValueVector(const Drill::FieldMetad
return new NullableValueVectorDecimal28Sparse(b,f.getValueCount(), f.getScale());
case common::DECIMAL38SPARSE:
return new NullableValueVectorDecimal38Sparse(b,f.getValueCount(), f.getScale());
+ case common::VARDECIMAL:
+ return new NullableValueVectorVarDecimal(b, f.getValueCount(), f.getScale());
case common::DATE:
return new NullableValueVectorTyped<DateHolder,
ValueVectorTyped<DateHolder, int64_t> >(b,f.getValueCount());
diff --git a/contrib/native/client/src/include/drill/decimalUtils.hpp b/contrib/native/client/src/include/drill/decimalUtils.hpp
index 2ace85772..5f9d37a99 100644
--- a/contrib/native/client/src/include/drill/decimalUtils.hpp
+++ b/contrib/native/client/src/include/drill/decimalUtils.hpp
@@ -41,6 +41,7 @@ struct DecimalValue
// These functions need not be exported. They are used by the templates that return the DecimalValue class.
DecimalValue getDecimalValueFromByteBuf(SlicedByteBuf& data, size_t startIndex, int nDecimalDigits, int scale, bool truncateScale);
+DecimalValue getDecimalValueFromByteBuf(SlicedByteBuf& data, size_t length, int scale);
DecimalValue getDecimalValueFromDense(SlicedByteBuf& data, size_t startIndex, int nDecimalDigits, int scale, int maxPrecision, int width);
inline DecimalValue getDecimalValueFromIntermediate(SlicedByteBuf& data, size_t startIndex, int nDecimalDigits, int scale)
diff --git a/contrib/native/client/src/include/drill/protobuf/Types.pb.h b/contrib/native/client/src/include/drill/protobuf/Types.pb.h
index f9200ec09..b1dec7bd6 100644
--- a/contrib/native/client/src/include/drill/protobuf/Types.pb.h
+++ b/contrib/native/client/src/include/drill/protobuf/Types.pb.h
@@ -74,11 +74,12 @@ enum MinorType {
INTERVALDAY = 39,
LIST = 40,
GENERIC_OBJECT = 41,
- UNION = 42
+ UNION = 42,
+ VARDECIMAL = 43
};
bool MinorType_IsValid(int value);
const MinorType MinorType_MIN = LATE;
-const MinorType MinorType_MAX = UNION;
+const MinorType MinorType_MAX = VARDECIMAL;
const int MinorType_ARRAYSIZE = MinorType_MAX + 1;
const ::google::protobuf::EnumDescriptor* MinorType_descriptor();
diff --git a/contrib/native/client/src/include/drill/recordBatch.hpp b/contrib/native/client/src/include/drill/recordBatch.hpp
index 30287b6ad..435eb7715 100644
--- a/contrib/native/client/src/include/drill/recordBatch.hpp
+++ b/contrib/native/client/src/include/drill/recordBatch.hpp
@@ -346,7 +346,8 @@ template <int DECIMAL_DIGITS, int WIDTH_IN_BYTES, bool IS_SPARSE, int MAX_PRECIS
strncpy(buf, str.c_str(), nChars);
} else {
size_t idxDecimalMark = str.length() - m_scale;
- const std::string& decStr= str.substr(0, idxDecimalMark) + "." + str.substr(idxDecimalMark, m_scale);
+ const std::string& decStr =
+ (idxDecimalMark == 0 ? "0" : str.substr(0, idxDecimalMark)) + "." + str.substr(idxDecimalMark, m_scale);
strncpy(buf, decStr.c_str(), nChars);
}
return;
@@ -734,6 +735,49 @@ class DECLSPEC_DRILL_CLIENT ValueVectorVarChar:public ValueVectorVarWidth{
}
};
+class DECLSPEC_DRILL_CLIENT ValueVectorVarDecimal:public ValueVectorVarWidth{
+ public:
+ ValueVectorVarDecimal(SlicedByteBuf *b, size_t rowCount, size_t scale):
+ ValueVectorVarWidth(b, rowCount),
+ m_scale(scale)
+ {
+ }
+ DecimalValue get(size_t index) const {
+ size_t length = getSize(index);
+ ByteBuf_t buff = getRaw(index);
+ SlicedByteBuf intermediateData(&buff[0], 0, length);
+ return getDecimalValueFromByteBuf(intermediateData, length, this->m_scale);
+ }
+
+ void getValueAt(size_t index, char* buf, size_t nChars) const {
+ const DecimalValue& val = this->get(index);
+ std::string str = boost::lexical_cast<std::string>(val.m_unscaledValue);
+ if (str[0] == '-') {
+ str = str.substr(1);
+ while (str.length() < m_scale) {
+ str = "0" + str;
+ }
+ str = "-" + str;
+ } else {
+ while (str.length() < m_scale) {
+ str = "0" + str;
+ }
+ }
+ if (m_scale == 0) {
+ strncpy(buf, str.c_str(), nChars);
+ } else {
+ size_t idxDecimalMark = str.length() - m_scale;
+ const std::string& decStr =
+ (idxDecimalMark == 0 ? "0" : str.substr(0, idxDecimalMark)) + "." + str.substr(idxDecimalMark, m_scale);
+ strncpy(buf, decStr.c_str(), nChars);
+ }
+ return;
+ }
+
+ private:
+ int32_t m_scale;
+};
+
class DECLSPEC_DRILL_CLIENT ValueVectorVarBinary:public ValueVectorVarWidth{
public:
ValueVectorVarBinary(SlicedByteBuf *b, size_t rowCount):ValueVectorVarWidth(b, rowCount){
@@ -764,10 +808,11 @@ typedef ValueVectorDecimal<6, 24, true, 38> ValueVectorDecimal38Sparse;
typedef NullableValueVectorTyped<int32_t, ValueVectorDecimal9> NullableValueVectorDecimal9;
typedef NullableValueVectorTyped<int64_t, ValueVectorDecimal18> NullableValueVectorDecimal18;
-typedef NullableValueVectorTyped<DecimalValue , ValueVectorDecimal28Dense> NullableValueVectorDecimal28Dense;
-typedef NullableValueVectorTyped<DecimalValue , ValueVectorDecimal38Dense> NullableValueVectorDecimal38Dense;
-typedef NullableValueVectorTyped<DecimalValue , ValueVectorDecimal28Sparse> NullableValueVectorDecimal28Sparse;
-typedef NullableValueVectorTyped<DecimalValue , ValueVectorDecimal38Sparse> NullableValueVectorDecimal38Sparse;
+typedef NullableValueVectorTyped<DecimalValue, ValueVectorDecimal28Dense> NullableValueVectorDecimal28Dense;
+typedef NullableValueVectorTyped<DecimalValue, ValueVectorDecimal38Dense> NullableValueVectorDecimal38Dense;
+typedef NullableValueVectorTyped<DecimalValue, ValueVectorDecimal28Sparse> NullableValueVectorDecimal28Sparse;
+typedef NullableValueVectorTyped<DecimalValue, ValueVectorDecimal38Sparse> NullableValueVectorDecimal38Sparse;
+typedef NullableValueVectorTyped<DecimalValue, ValueVectorVarDecimal> NullableValueVectorVarDecimal;
typedef ValueVectorTyped<DateHolder, int64_t> ValueVectorDate;
typedef ValueVectorTyped<DateTimeHolder, int64_t> ValueVectorTimestamp;
diff --git a/contrib/native/client/src/protobuf/Types.pb.cc b/contrib/native/client/src/protobuf/Types.pb.cc
index ec8a1c84f..675bba02d 100644
--- a/contrib/native/client/src/protobuf/Types.pb.cc
+++ b/contrib/native/client/src/protobuf/Types.pb.cc
@@ -93,7 +93,7 @@ void protobuf_AddDesc_Types_2eproto() {
"de\030\002 \001(\0162\020.common.DataMode\022\r\n\005width\030\003 \001("
"\005\022\021\n\tprecision\030\004 \001(\005\022\r\n\005scale\030\005 \001(\005\022\020\n\010t"
"imeZone\030\006 \001(\005\022#\n\010sub_type\030\007 \003(\0162\021.common"
- ".MinorType*\233\004\n\tMinorType\022\010\n\004LATE\020\000\022\007\n\003MA"
+ ".MinorType*\253\004\n\tMinorType\022\010\n\004LATE\020\000\022\007\n\003MA"
"P\020\001\022\013\n\007TINYINT\020\003\022\014\n\010SMALLINT\020\004\022\007\n\003INT\020\005\022"
"\n\n\006BIGINT\020\006\022\014\n\010DECIMAL9\020\007\022\r\n\tDECIMAL18\020\010"
"\022\023\n\017DECIMAL28SPARSE\020\t\022\023\n\017DECIMAL38SPARSE"
@@ -106,10 +106,10 @@ void protobuf_AddDesc_Types_2eproto() {
"\n\005UINT4\020\037\022\t\n\005UINT8\020 \022\022\n\016DECIMAL28DENSE\020!"
"\022\022\n\016DECIMAL38DENSE\020\"\022\016\n\nDM_UNKNOWN\020%\022\020\n\014"
"INTERVALYEAR\020&\022\017\n\013INTERVALDAY\020\'\022\010\n\004LIST\020"
- "(\022\022\n\016GENERIC_OBJECT\020)\022\t\n\005UNION\020**=\n\010Data"
- "Mode\022\017\n\013DM_OPTIONAL\020\000\022\017\n\013DM_REQUIRED\020\001\022\017"
- "\n\013DM_REPEATED\020\002B-\n\035org.apache.drill.comm"
- "on.typesB\nTypeProtosH\001", 862);
+ "(\022\022\n\016GENERIC_OBJECT\020)\022\t\n\005UNION\020*\022\016\n\nVARD"
+ "ECIMAL\020+*=\n\010DataMode\022\017\n\013DM_OPTIONAL\020\000\022\017\n"
+ "\013DM_REQUIRED\020\001\022\017\n\013DM_REPEATED\020\002B-\n\035org.a"
+ "pache.drill.common.typesB\nTypeProtosH\001", 878);
::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
"Types.proto", &protobuf_RegisterTypes);
MajorType::default_instance_ = new MajorType();
@@ -167,6 +167,7 @@ bool MinorType_IsValid(int value) {
case 40:
case 41:
case 42:
+ case 43:
return true;
default:
return false;
diff --git a/contrib/storage-hive/core/src/main/codegen/data/HiveTypes.tdd b/contrib/storage-hive/core/src/main/codegen/data/HiveTypes.tdd
index e13dc3644..864610c7b 100644
--- a/contrib/storage-hive/core/src/main/codegen/data/HiveTypes.tdd
+++ b/contrib/storage-hive/core/src/main/codegen/data/HiveTypes.tdd
@@ -104,7 +104,7 @@
hiveType: "DECIMAL",
hiveOI: "HiveDecimalObjectInspector",
javaType: "org.apache.hadoop.hive.common.type.HiveDecimal",
- drillType: "Decimal38Sparse",
+ drillType: "VarDecimal",
needOIForDrillType: true
},
{
diff --git a/contrib/storage-hive/core/src/main/codegen/templates/ObjectInspectors.java b/contrib/storage-hive/core/src/main/codegen/templates/ObjectInspectors.java
index 9c4531416..a539b7f1d 100644
--- a/contrib/storage-hive/core/src/main/codegen/templates/ObjectInspectors.java
+++ b/contrib/storage-hive/core/src/main/codegen/templates/ObjectInspectors.java
@@ -100,12 +100,12 @@ public class Drill${entry.drillType}${entry.hiveOI} {
}
@Override
- public String getPrimitiveJavaObject(Object o){
+ public String getPrimitiveJavaObject(Object o) {
<#if mode == "Optional">
if (o == null) {
return null;
}
- final NullableVarCharHolder h = (NullableVarCharHolder)o;
+ final NullableVarCharHolder h = (NullableVarCharHolder) o;
<#else>
final VarCharHolder h = (VarCharHolder)o;
</#if>
@@ -118,9 +118,9 @@ public class Drill${entry.drillType}${entry.hiveOI} {
if (o == null) {
return null;
}
- final NullableVarBinaryHolder h = (NullableVarBinaryHolder)o;
+ final NullableVarBinaryHolder h = (NullableVarBinaryHolder) o;
<#else>
- final VarBinaryHolder h = (VarBinaryHolder)o;
+ final VarBinaryHolder h = (VarBinaryHolder) o;
</#if>
final byte[] buf = new byte[h.end-h.start];
h.buffer.getBytes(h.start, buf, 0, h.end-h.start);
@@ -133,9 +133,9 @@ public class Drill${entry.drillType}${entry.hiveOI} {
if (o == null) {
return null;
}
- final NullableVarBinaryHolder h = (NullableVarBinaryHolder)o;
+ final NullableVarBinaryHolder h = (NullableVarBinaryHolder) o;
<#else>
- final VarBinaryHolder h = (VarBinaryHolder)o;
+ final VarBinaryHolder h = (VarBinaryHolder) o;
</#if>
final byte[] buf = new byte[h.end-h.start];
h.buffer.getBytes(h.start, buf, 0, h.end-h.start);
@@ -174,18 +174,18 @@ public class Drill${entry.drillType}${entry.hiveOI} {
return Boolean.valueOf(((BitHolder)o).value != 0);
</#if>
}
-<#elseif entry.drillType == "Decimal38Sparse">
+<#elseif entry.drillType == "VarDecimal">
@Override
- public HiveDecimal getPrimitiveJavaObject(Object o){
+ public HiveDecimal getPrimitiveJavaObject(Object o) {
<#if mode == "Optional">
if (o == null) {
return null;
}
- final NullableDecimal38SparseHolder h = (NullableDecimal38SparseHolder) o;
+ final NullableVarDecimalHolder h = (NullableVarDecimalHolder) o;
<#else>
- final Decimal38SparseHolder h = (Decimal38SparseHolder) o;
+ final VarDecimalHolder h = (VarDecimalHolder) o;
</#if>
- return HiveDecimal.create(DecimalUtility.getBigDecimalFromSparse(h.buffer, h.start, h.nDecimalDigits, h.scale));
+ return HiveDecimal.create(DecimalUtility.getBigDecimalFromDrillBuf(h.buffer, h.start, h.end - h.start, h.scale));
}
@Override
@@ -194,17 +194,17 @@ public class Drill${entry.drillType}${entry.hiveOI} {
if (o == null) {
return null;
}
- final NullableDecimal38SparseHolder h = (NullableDecimal38SparseHolder) o;
+ final NullableVarDecimalHolder h = (NullableVarDecimalHolder) o;
<#else>
- final Decimal38SparseHolder h = (Decimal38SparseHolder) o;
+ final VarDecimalHolder h = (VarDecimalHolder) o;
</#if>
return new HiveDecimalWritable(
- HiveDecimal.create(DecimalUtility.getBigDecimalFromSparse(h.buffer, h.start, h.nDecimalDigits, h.scale)));
+ HiveDecimal.create(DecimalUtility.getBigDecimalFromDrillBuf(h.buffer, h.start, h.end - h.start, h.scale)));
}
<#elseif entry.drillType == "TimeStamp">
@Override
- public java.sql.Timestamp getPrimitiveJavaObject(Object o){
+ public java.sql.Timestamp getPrimitiveJavaObject(Object o) {
<#if mode == "Optional">
if (o == null) {
return null;
@@ -237,7 +237,7 @@ public class Drill${entry.drillType}${entry.hiveOI} {
<#elseif entry.drillType == "Date">
@Override
- public java.sql.Date getPrimitiveJavaObject(Object o){
+ public java.sql.Date getPrimitiveJavaObject(Object o) {
<#if mode == "Optional">
if (o == null) {
return null;
@@ -270,11 +270,11 @@ public class Drill${entry.drillType}${entry.hiveOI} {
<#else>
@Override
- public ${entry.javaType} get(Object o){
+ public ${entry.javaType} get(Object o) {
<#if mode == "Optional">
- return ((Nullable${entry.drillType}Holder)o).value;
+ return ((Nullable${entry.drillType}Holder) o).value;
<#else>
- return ((${entry.drillType}Holder)o).value;
+ return ((${entry.drillType}Holder) o).value;
</#if>
}
@@ -295,9 +295,9 @@ public class Drill${entry.drillType}${entry.hiveOI} {
if (o == null) {
return null;
}
- return new ${entry.javaType?cap_first}(((Nullable${entry.drillType}Holder)o).value);
+ return new ${entry.javaType?cap_first}(((Nullable${entry.drillType}Holder) o).value);
<#else>
- return new ${entry.javaType?cap_first}(((${entry.drillType}Holder)o).value);
+ return new ${entry.javaType?cap_first}(((${entry.drillType}Holder) o).value);
</#if>
}
</#if>
@@ -310,7 +310,7 @@ public class Drill${entry.drillType}${entry.hiveOI} {
}
final Nullable${entry.drillType}Holder h = (Nullable${entry.drillType}Holder) o;
<#else>
- final ${entry.drillType}Holder h = (${entry.drillType}Holder)o;
+ final ${entry.drillType}Holder h = (${entry.drillType}Holder) o;
</#if>
return new ${entry.javaType?cap_first}Writable(h.value);
}
diff --git a/contrib/storage-hive/core/src/main/java/org/apache/drill/exec/expr/fn/HiveFunctionRegistry.java b/contrib/storage-hive/core/src/main/java/org/apache/drill/exec/expr/fn/HiveFunctionRegistry.java
index f6232f680..92e7f83cc 100644
--- a/contrib/storage-hive/core/src/main/java/org/apache/drill/exec/expr/fn/HiveFunctionRegistry.java
+++ b/contrib/storage-hive/core/src/main/java/org/apache/drill/exec/expr/fn/HiveFunctionRegistry.java
@@ -32,7 +32,6 @@ import org.apache.drill.common.scanner.ClassPathScanner;
import org.apache.drill.common.scanner.persistence.ScanResult;
import org.apache.drill.common.types.TypeProtos;
import org.apache.drill.common.types.TypeProtos.MajorType;
-import org.apache.drill.common.types.TypeProtos.MinorType;
import org.apache.drill.common.types.Types;
import org.apache.drill.exec.expr.fn.impl.hive.ObjectInspectorHelper;
import org.apache.drill.exec.planner.sql.DrillOperatorTable;
@@ -267,9 +266,9 @@ public class HiveFunctionRegistry implements PluggableFunctionRegistry{
.build(logger);
}
- return TypeInferenceUtils.createCalciteTypeWithNullability(
+ return TypeInferenceUtils.convertToCalciteType(
opBinding.getTypeFactory(),
- TypeInferenceUtils.getCalciteTypeFromDrillType(hiveFuncHolder.getReturnType().getMinorType()),
+ hiveFuncHolder.getReturnType(),
hiveFuncHolder.getReturnType().getMode() != TypeProtos.DataMode.REQUIRED);
}
}
diff --git a/contrib/storage-hive/core/src/main/java/org/apache/drill/exec/store/hive/HiveFieldConverter.java b/contrib/storage-hive/core/src/main/java/org/apache/drill/exec/store/hive/HiveFieldConverter.java
index 2fab5a4d4..6caecbb82 100644
--- a/contrib/storage-hive/core/src/main/java/org/apache/drill/exec/store/hive/HiveFieldConverter.java
+++ b/contrib/storage-hive/core/src/main/java/org/apache/drill/exec/store/hive/HiveFieldConverter.java
@@ -17,27 +17,19 @@
*/
package org.apache.drill.exec.store.hive;
+import java.math.RoundingMode;
import java.util.Map;
-import org.apache.drill.exec.expr.holders.Decimal18Holder;
-import org.apache.drill.exec.expr.holders.Decimal28SparseHolder;
-import org.apache.drill.exec.expr.holders.Decimal38SparseHolder;
-import org.apache.drill.exec.expr.holders.Decimal9Holder;
-import org.apache.drill.exec.ops.FragmentContext;
-import org.apache.drill.exec.util.DecimalUtility;
import org.apache.drill.exec.vector.NullableBigIntVector;
import org.apache.drill.exec.vector.NullableBitVector;
import org.apache.drill.exec.vector.NullableDateVector;
-import org.apache.drill.exec.vector.NullableDecimal18Vector;
-import org.apache.drill.exec.vector.NullableDecimal28SparseVector;
-import org.apache.drill.exec.vector.NullableDecimal38SparseVector;
-import org.apache.drill.exec.vector.NullableDecimal9Vector;
import org.apache.drill.exec.vector.NullableFloat4Vector;
import org.apache.drill.exec.vector.NullableFloat8Vector;
import org.apache.drill.exec.vector.NullableIntVector;
import org.apache.drill.exec.vector.NullableTimeStampVector;
import org.apache.drill.exec.vector.NullableVarBinaryVector;
import org.apache.drill.exec.vector.NullableVarCharVector;
+import org.apache.drill.exec.vector.NullableVarDecimalVector;
import org.apache.drill.exec.vector.ValueVector;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.PrimitiveObjectInspector.PrimitiveCategory;
@@ -55,7 +47,6 @@ import org.apache.hadoop.hive.serde2.objectinspector.primitive.LongObjectInspect
import org.apache.hadoop.hive.serde2.objectinspector.primitive.ShortObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.StringObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.TimestampObjectInspector;
-import org.apache.hadoop.hive.serde2.typeinfo.DecimalTypeInfo;
import org.apache.hadoop.hive.serde2.typeinfo.PrimitiveTypeInfo;
import org.apache.hadoop.hive.serde2.typeinfo.TypeInfo;
import org.apache.hadoop.io.Text;
@@ -92,33 +83,18 @@ public abstract class HiveFieldConverter {
primMap.put(PrimitiveCategory.TIMESTAMP, Timestamp.class);
primMap.put(PrimitiveCategory.DATE, Date.class);
primMap.put(PrimitiveCategory.CHAR, Char.class);
+ primMap.put(PrimitiveCategory.DECIMAL, VarDecimal.class);
}
- public static HiveFieldConverter create(TypeInfo typeInfo, FragmentContext fragmentContext)
+ public static HiveFieldConverter create(TypeInfo typeInfo)
throws IllegalAccessException, InstantiationException {
switch (typeInfo.getCategory()) {
case PRIMITIVE:
final PrimitiveCategory pCat = ((PrimitiveTypeInfo) typeInfo).getPrimitiveCategory();
- if (pCat != PrimitiveCategory.DECIMAL) {
- Class<? extends HiveFieldConverter> clazz = primMap.get(pCat);
- if (clazz != null) {
- return clazz.newInstance();
- }
- } else {
- // For decimal, based on precision return appropriate converter.
- DecimalTypeInfo decimalTypeInfo = (DecimalTypeInfo) typeInfo;
- int precision = decimalTypeInfo.precision();
- int scale = decimalTypeInfo.scale();
- if (precision <= 9) {
- return new Decimal9(precision, scale);
- } else if (precision <= 18) {
- return new Decimal18(precision, scale);
- } else if (precision <= 28) {
- return new Decimal28(precision, scale, fragmentContext);
- } else {
- return new Decimal38(precision, scale, fragmentContext);
- }
+ Class<? extends HiveFieldConverter> clazz = primMap.get(pCat);
+ if (clazz != null) {
+ return clazz.newInstance();
}
throwUnsupportedHiveDataTypeError(pCat.toString());
@@ -151,75 +127,15 @@ public abstract class HiveFieldConverter {
}
}
- public static class Decimal9 extends HiveFieldConverter {
- private final Decimal9Holder holder = new Decimal9Holder();
-
- public Decimal9(int precision, int scale) {
- holder.scale = scale;
- holder.precision = precision;
- }
-
- @Override
- public void setSafeValue(ObjectInspector oi, Object hiveFieldValue, ValueVector outputVV, int outputIndex) {
- holder.value = DecimalUtility.getDecimal9FromBigDecimal(
- ((HiveDecimalObjectInspector)oi).getPrimitiveJavaObject(hiveFieldValue).bigDecimalValue(),
- holder.scale, holder.precision);
- ((NullableDecimal9Vector) outputVV).getMutator().setSafe(outputIndex, holder);
- }
- }
-
- public static class Decimal18 extends HiveFieldConverter {
- private final Decimal18Holder holder = new Decimal18Holder();
-
- public Decimal18(int precision, int scale) {
- holder.scale = scale;
- holder.precision = precision;
- }
-
- @Override
- public void setSafeValue(ObjectInspector oi, Object hiveFieldValue, ValueVector outputVV, int outputIndex) {
- holder.value = DecimalUtility.getDecimal18FromBigDecimal(
- ((HiveDecimalObjectInspector)oi).getPrimitiveJavaObject(hiveFieldValue).bigDecimalValue(),
- holder.scale, holder.precision);
- ((NullableDecimal18Vector) outputVV).getMutator().setSafe(outputIndex, holder);
- }
- }
-
- public static class Decimal28 extends HiveFieldConverter {
- private final Decimal28SparseHolder holder = new Decimal28SparseHolder();
-
- public Decimal28(int precision, int scale, FragmentContext context) {
- holder.scale = scale;
- holder.precision = precision;
- holder.buffer = context.getManagedBuffer(Decimal28SparseHolder.nDecimalDigits * DecimalUtility.INTEGER_SIZE);
- holder.start = 0;
- }
-
- @Override
- public void setSafeValue(ObjectInspector oi, Object hiveFieldValue, ValueVector outputVV, int outputIndex) {
- DecimalUtility.getSparseFromBigDecimal(
- ((HiveDecimalObjectInspector)oi).getPrimitiveJavaObject(hiveFieldValue).bigDecimalValue(),
- holder.buffer, holder.start, holder.scale, holder.precision, Decimal28SparseHolder.nDecimalDigits);
- ((NullableDecimal28SparseVector) outputVV).getMutator().setSafe(outputIndex, holder);
- }
- }
-
- public static class Decimal38 extends HiveFieldConverter {
- private final Decimal38SparseHolder holder = new Decimal38SparseHolder();
-
- public Decimal38(int precision, int scale, FragmentContext context) {
- holder.scale = scale;
- holder.precision = precision;
- holder.buffer = context.getManagedBuffer(Decimal38SparseHolder.nDecimalDigits * DecimalUtility.INTEGER_SIZE);
- holder.start = 0;
- }
-
+ public static class VarDecimal extends HiveFieldConverter {
@Override
public void setSafeValue(ObjectInspector oi, Object hiveFieldValue, ValueVector outputVV, int outputIndex) {
- DecimalUtility.getSparseFromBigDecimal(
- ((HiveDecimalObjectInspector)oi).getPrimitiveJavaObject(hiveFieldValue).bigDecimalValue(),
- holder.buffer, holder.start, holder.scale, holder.precision, Decimal38SparseHolder.nDecimalDigits);
- ((NullableDecimal38SparseVector) outputVV).getMutator().setSafe(outputIndex, holder);
+ ((NullableVarDecimalVector) outputVV).getMutator()
+ .setSafe(
+ outputIndex,
+ ((HiveDecimalObjectInspector) oi)
+ .getPrimitiveJavaObject(hiveFieldValue).bigDecimalValue()
+ .setScale(outputVV.getField().getScale(), RoundingMode.HALF_UP));
}
}
diff --git a/contrib/storage-hive/core/src/main/java/org/apache/drill/exec/store/hive/HiveUtilities.java b/contrib/storage-hive/core/src/main/java/org/apache/drill/exec/store/hive/HiveUtilities.java
index 5ff55060a..91d0567af 100644
--- a/contrib/storage-hive/core/src/main/java/org/apache/drill/exec/store/hive/HiveUtilities.java
+++ b/contrib/storage-hive/core/src/main/java/org/apache/drill/exec/store/hive/HiveUtilities.java
@@ -50,6 +50,7 @@ import org.apache.drill.exec.vector.NullableIntVector;
import org.apache.drill.exec.vector.NullableTimeStampVector;
import org.apache.drill.exec.vector.NullableVarBinaryVector;
import org.apache.drill.exec.vector.NullableVarCharVector;
+import org.apache.drill.exec.vector.NullableVarDecimalVector;
import org.apache.drill.exec.vector.ValueVector;
import org.apache.drill.exec.work.ExecErrorConstants;
@@ -80,6 +81,7 @@ import org.joda.time.DateTimeZone;
import javax.annotation.Nullable;
import java.math.BigDecimal;
+import java.math.RoundingMode;
import java.sql.Date;
import java.sql.Timestamp;
import java.util.List;
@@ -293,6 +295,15 @@ public class HiveUtilities {
}
break;
}
+ case VARDECIMAL: {
+ final BigDecimal value = ((HiveDecimal) val).bigDecimalValue()
+ .setScale(vector.getField().getScale(), RoundingMode.HALF_UP);
+ final NullableVarDecimalVector v = ((NullableVarDecimalVector) vector);
+ for (int i = start; i < end; i++) {
+ v.getMutator().setSafe(i, value);
+ }
+ break;
+ }
}
}
@@ -346,8 +357,7 @@ public class HiveUtilities {
.message(ExecErrorConstants.DECIMAL_DISABLE_ERR_MSG)
.build(logger);
}
- DecimalTypeInfo decimalTypeInfo = (DecimalTypeInfo) primitiveTypeInfo;
- return DecimalUtility.getDecimalDataType(decimalTypeInfo.precision());
+ return MinorType.VARDECIMAL;
}
case DOUBLE:
return TypeProtos.MinorType.FLOAT8;
diff --git a/contrib/storage-hive/core/src/main/java/org/apache/drill/exec/store/hive/readers/HiveAbstractReader.java b/contrib/storage-hive/core/src/main/java/org/apache/drill/exec/store/hive/readers/HiveAbstractReader.java
index a922b4ca0..d0d9ed067 100644
--- a/contrib/storage-hive/core/src/main/java/org/apache/drill/exec/store/hive/readers/HiveAbstractReader.java
+++ b/contrib/storage-hive/core/src/main/java/org/apache/drill/exec/store/hive/readers/HiveAbstractReader.java
@@ -227,7 +227,7 @@ public abstract class HiveAbstractReader extends AbstractRecordReader {
selectedColumnObjInspectors.add(fieldOI);
selectedColumnTypes.add(typeInfo);
- selectedColumnFieldConverters.add(HiveFieldConverter.create(typeInfo, fragmentContext));
+ selectedColumnFieldConverters.add(HiveFieldConverter.create(typeInfo));
}
for(int i=0; i<selectedColumnNames.size(); ++i){
diff --git a/contrib/storage-hive/hive-exec-shade/pom.xml b/contrib/storage-hive/hive-exec-shade/pom.xml
index 3d4dcebc3..ad572efaf 100644
--- a/contrib/storage-hive/hive-exec-shade/pom.xml
+++ b/contrib/storage-hive/hive-exec-shade/pom.xml
@@ -117,6 +117,10 @@
<pattern>org.apache.parquet.</pattern>
<shadedPattern>hive.org.apache.parquet.</shadedPattern>
</relocation>
+ <relocation>
+ <pattern>org.apache.avro.</pattern>
+ <shadedPattern>hive.org.apache.avro.</shadedPattern>
+ </relocation>
</relocations>
<filters>
<filter>
diff --git a/contrib/storage-jdbc/src/main/java/org/apache/drill/exec/store/jdbc/JdbcRecordReader.java b/contrib/storage-jdbc/src/main/java/org/apache/drill/exec/store/jdbc/JdbcRecordReader.java
index bea99c71a..5f3f7131b 100755
--- a/contrib/storage-jdbc/src/main/java/org/apache/drill/exec/store/jdbc/JdbcRecordReader.java
+++ b/contrib/storage-jdbc/src/main/java/org/apache/drill/exec/store/jdbc/JdbcRecordReader.java
@@ -35,9 +35,9 @@ import javax.sql.DataSource;
import org.apache.drill.common.AutoCloseables;
import org.apache.drill.common.exceptions.ExecutionSetupException;
import org.apache.drill.common.exceptions.UserException;
+import org.apache.drill.common.types.TypeProtos;
import org.apache.drill.common.types.TypeProtos.MajorType;
import org.apache.drill.common.types.TypeProtos.MinorType;
-import org.apache.drill.common.types.Types;
import org.apache.drill.exec.exception.SchemaChangeException;
import org.apache.drill.exec.expr.TypeHelper;
import org.apache.drill.exec.ops.OperatorContext;
@@ -54,6 +54,7 @@ import org.apache.drill.exec.vector.NullableTimeStampVector;
import org.apache.drill.exec.vector.NullableTimeVector;
import org.apache.drill.exec.vector.NullableVarBinaryVector;
import org.apache.drill.exec.vector.NullableVarCharVector;
+import org.apache.drill.exec.vector.NullableVarDecimalVector;
import org.apache.drill.exec.vector.ValueVector;
import com.google.common.base.Charsets;
@@ -104,7 +105,7 @@ class JdbcRecordReader extends AbstractRecordReader {
.put(java.sql.Types.BLOB, MinorType.VARBINARY)
.put(java.sql.Types.NUMERIC, MinorType.FLOAT8)
- .put(java.sql.Types.DECIMAL, MinorType.FLOAT8)
+ .put(java.sql.Types.DECIMAL, MinorType.VARDECIMAL)
.put(java.sql.Types.REAL, MinorType.FLOAT8)
.put(java.sql.Types.DATE, MinorType.DATE)
@@ -137,29 +138,45 @@ class JdbcRecordReader extends AbstractRecordReader {
private Copier<?> getCopier(int jdbcType, int offset, ResultSet result, ValueVector v) {
- if (v instanceof NullableBigIntVector) {
- return new BigIntCopier(offset, result, (NullableBigIntVector.Mutator) v.getMutator());
- } else if (v instanceof NullableFloat4Vector) {
- return new Float4Copier(offset, result, (NullableFloat4Vector.Mutator) v.getMutator());
- } else if (v instanceof NullableFloat8Vector) {
- return new Float8Copier(offset, result, (NullableFloat8Vector.Mutator) v.getMutator());
- } else if (v instanceof NullableIntVector) {
- return new IntCopier(offset, result, (NullableIntVector.Mutator) v.getMutator());
- } else if (v instanceof NullableVarCharVector) {
- return new VarCharCopier(offset, result, (NullableVarCharVector.Mutator) v.getMutator());
- } else if (v instanceof NullableVarBinaryVector) {
- return new VarBinaryCopier(offset, result, (NullableVarBinaryVector.Mutator) v.getMutator());
- } else if (v instanceof NullableDateVector) {
- return new DateCopier(offset, result, (NullableDateVector.Mutator) v.getMutator());
- } else if (v instanceof NullableTimeVector) {
- return new TimeCopier(offset, result, (NullableTimeVector.Mutator) v.getMutator());
- } else if (v instanceof NullableTimeStampVector) {
- return new TimeStampCopier(offset, result, (NullableTimeStampVector.Mutator) v.getMutator());
- } else if (v instanceof NullableBitVector) {
- return new BitCopier(offset, result, (NullableBitVector.Mutator) v.getMutator());
+ switch (jdbcType) {
+ case java.sql.Types.BIGINT:
+ return new BigIntCopier(offset, result, (NullableBigIntVector.Mutator) v.getMutator());
+ case java.sql.Types.FLOAT:
+ return new Float4Copier(offset, result, (NullableFloat4Vector.Mutator) v.getMutator());
+ case java.sql.Types.DOUBLE:
+ case java.sql.Types.NUMERIC:
+ case java.sql.Types.REAL:
+ return new Float8Copier(offset, result, (NullableFloat8Vector.Mutator) v.getMutator());
+ case java.sql.Types.TINYINT:
+ case java.sql.Types.SMALLINT:
+ case java.sql.Types.INTEGER:
+ return new IntCopier(offset, result, (NullableIntVector.Mutator) v.getMutator());
+ case java.sql.Types.CHAR:
+ case java.sql.Types.VARCHAR:
+ case java.sql.Types.LONGVARCHAR:
+ case java.sql.Types.CLOB:
+ case java.sql.Types.NCHAR:
+ case java.sql.Types.NVARCHAR:
+ case java.sql.Types.LONGNVARCHAR:
+ return new VarCharCopier(offset, result, (NullableVarCharVector.Mutator) v.getMutator());
+ case java.sql.Types.VARBINARY:
+ case java.sql.Types.LONGVARBINARY:
+ case java.sql.Types.BLOB:
+ return new VarBinaryCopier(offset, result, (NullableVarBinaryVector.Mutator) v.getMutator());
+ case java.sql.Types.DATE:
+ return new DateCopier(offset, result, (NullableDateVector.Mutator) v.getMutator());
+ case java.sql.Types.TIME:
+ return new TimeCopier(offset, result, (NullableTimeVector.Mutator) v.getMutator());
+ case java.sql.Types.TIMESTAMP:
+ return new TimeStampCopier(offset, result, (NullableTimeStampVector.Mutator) v.getMutator());
+ case java.sql.Types.BOOLEAN:
+ case java.sql.Types.BIT:
+ return new BitCopier(offset, result, (NullableBitVector.Mutator) v.getMutator());
+ case java.sql.Types.DECIMAL:
+ return new DecimalCopier(offset, result, (NullableVarDecimalVector.Mutator) v.getMutator());
+ default:
+ throw new IllegalArgumentException("Unknown how to handle vector.");
}
-
- throw new IllegalArgumentException("Unknown how to handle vector.");
}
@Override
@@ -197,9 +214,14 @@ class JdbcRecordReader extends AbstractRecordReader {
continue;
}
- final MajorType type = Types.optional(minorType);
+ final MajorType type = MajorType.newBuilder()
+ .setMode(TypeProtos.DataMode.OPTIONAL)
+ .setMinorType(minorType)
+ .setScale(scale)
+ .setPrecision(width)
+ .build();
final MaterializedField field = MaterializedField.create(name, type);
- final Class<? extends ValueVector> clazz = (Class<? extends ValueVector>) TypeHelper.getValueVectorClass(
+ final Class<? extends ValueVector> clazz = TypeHelper.getValueVectorClass(
minorType, type.getMode());
ValueVector vector = output.addField(field, clazz);
vectorBuilder.add(vector);
@@ -225,10 +247,10 @@ class JdbcRecordReader extends AbstractRecordReader {
int counter = 0;
Boolean b = true;
try {
- while (counter < 4095 && b == true) { // loop at 4095 since nullables use one more than record count and we
+ while (counter < 4095 && b) { // loop at 4095 since nullables use one more than record count and we
// allocate on powers of two.
b = resultSet.next();
- if(b == false) {
+ if (!b) {
break;
}
for (Copier<?> c : copiers) {
@@ -335,9 +357,9 @@ class JdbcRecordReader extends AbstractRecordReader {
}
- private class DecimalCopier extends Copier<NullableFloat8Vector.Mutator> {
+ private class DecimalCopier extends Copier<NullableVarDecimalVector.Mutator> {
- public DecimalCopier(int columnIndex, ResultSet result, NullableFloat8Vector.Mutator mutator) {
+ public DecimalCopier(int columnIndex, ResultSet result, NullableVarDecimalVector.Mutator mutator) {
super(columnIndex, result, mutator);
}
@@ -345,7 +367,7 @@ class JdbcRecordReader extends AbstractRecordReader {
void copy(int index) throws SQLException {
BigDecimal decimal = result.getBigDecimal(columnIndex);
if (decimal != null) {
- mutator.setSafe(index, decimal.doubleValue());
+ mutator.setSafe(index, decimal);
}
}
diff --git a/contrib/storage-mongo/src/main/java/org/apache/drill/exec/store/mongo/MongoCompareFunctionProcessor.java b/contrib/storage-mongo/src/main/java/org/apache/drill/exec/store/mongo/MongoCompareFunctionProcessor.java
index 130ea0f06..b12887d7c 100644
--- a/contrib/storage-mongo/src/main/java/org/apache/drill/exec/store/mongo/MongoCompareFunctionProcessor.java
+++ b/contrib/storage-mongo/src/main/java/org/apache/drill/exec/store/mongo/MongoCompareFunctionProcessor.java
@@ -30,6 +30,7 @@ import org.apache.drill.common.expression.ValueExpressions.IntExpression;
import org.apache.drill.common.expression.ValueExpressions.LongExpression;
import org.apache.drill.common.expression.ValueExpressions.QuotedString;
import org.apache.drill.common.expression.ValueExpressions.TimeExpression;
+import org.apache.drill.common.expression.ValueExpressions.VarDecimalExpression;
import org.apache.drill.common.expression.visitors.AbstractExprVisitor;
import com.google.common.collect.ImmutableMap;
@@ -110,7 +111,7 @@ public class MongoCompareFunctionProcessor extends
@Override
public Boolean visitConvertExpression(ConvertExpression e,
LogicalExpression valueArg) throws RuntimeException {
- if (e.getConvertFunction() == ConvertExpression.CONVERT_FROM
+ if (ConvertExpression.CONVERT_FROM.equals(e.getConvertFunction())
&& e.getInput() instanceof SchemaPath) {
String encodingType = e.getEncodingType();
switch (encodingType) {
@@ -219,6 +220,14 @@ public class MongoCompareFunctionProcessor extends
return true;
}
+ // Mongo does not support decimals, therefore double value is used.
+ // See list of supported types in BsonValueCodecProvider.
+ if (valueArg instanceof VarDecimalExpression) {
+ this.value = ((VarDecimalExpression) valueArg).getBigDecimal().doubleValue();
+ this.path = path;
+ return true;
+ }
+
return false;
}
@@ -230,7 +239,7 @@ public class MongoCompareFunctionProcessor extends
.add(DateExpression.class).add(DoubleExpression.class)
.add(FloatExpression.class).add(IntExpression.class)
.add(LongExpression.class).add(QuotedString.class)
- .add(TimeExpression.class).build();
+ .add(TimeExpression.class).add(VarDecimalExpression.class).build();
}
private static final ImmutableMap<String, String> COMPARE_FUNCTIONS_TRANSPOSE_MAP;
diff --git a/exec/java-exec/pom.xml b/exec/java-exec/pom.xml
index 8e3e4cfdb..cbc3a02aa 100644
--- a/exec/java-exec/pom.xml
+++ b/exec/java-exec/pom.xml
@@ -511,48 +511,43 @@
<dependency>
<groupId>org.apache.avro</groupId>
<artifactId>avro</artifactId>
- <version>1.7.7</version>
- <exclusions>
- <exclusion>
- <groupId>org.xerial.snappy</groupId>
- <artifactId>snappy-java</artifactId>
- </exclusion>
- <exclusion>
- <groupId>io.netty</groupId>
- <artifactId>netty</artifactId>
- </exclusion>
- <exclusion>
- <groupId>io.netty</groupId>
- <artifactId>netty-all</artifactId>
- </exclusion>
- </exclusions>
</dependency>
<dependency>
<groupId>org.apache.avro</groupId>
<artifactId>avro-mapred</artifactId>
- <version>1.7.7</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.hadoop</groupId>
+ <artifactId>hadoop-hdfs</artifactId>
+ <scope>test</scope>
+ <classifier>tests</classifier>
<exclusions>
<exclusion>
- <groupId>org.mortbay.jetty</groupId>
- <artifactId>servlet-api</artifactId>
+ <groupId>io.netty</groupId>
+ <artifactId>netty</artifactId>
</exclusion>
<exclusion>
- <groupId>io.netty</groupId>
- <artifactId>netty</artifactId>
+ <groupId>io.netty</groupId>
+ <artifactId>netty-all</artifactId>
</exclusion>
<exclusion>
- <groupId>io.netty</groupId>
- <artifactId>netty-all</artifactId>
+ <groupId>commons-codec</groupId>
+ <artifactId>commons-codec</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
- <groupId>org.apache.hadoop</groupId>
- <artifactId>hadoop-hdfs</artifactId>
- <scope>test</scope>
+ <groupId>org.apache.avro</groupId>
+ <artifactId>avro</artifactId>
+ <version>${avro.version}</version>
<classifier>tests</classifier>
+ <scope>test</scope>
<exclusions>
<exclusion>
+ <groupId>org.xerial.snappy</groupId>
+ <artifactId>snappy-java</artifactId>
+ </exclusion>
+ <exclusion>
<groupId>io.netty</groupId>
<artifactId>netty</artifactId>
</exclusion>
@@ -560,10 +555,6 @@
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
</exclusion>
- <exclusion>
- <groupId>commons-codec</groupId>
- <artifactId>commons-codec</artifactId>
- </exclusion>
</exclusions>
</dependency>
<dependency>
diff --git a/exec/java-exec/src/main/codegen/config.fmpp b/exec/java-exec/src/main/codegen/config.fmpp
index c70f6da6e..50f110dd1 100644
--- a/exec/java-exec/src/main/codegen/config.fmpp
+++ b/exec/java-exec/src/main/codegen/config.fmpp
@@ -31,6 +31,7 @@ data: {
aggrtypes1: tdd(../data/AggrTypes1.tdd),
decimalaggrtypes1: tdd(../data/DecimalAggrTypes1.tdd),
decimalaggrtypes2: tdd(../data/DecimalAggrTypes2.tdd),
+ decimalaggrtypes3: tdd(../data/DecimalAggrTypes3.tdd),
aggrtypes2: tdd(../data/AggrTypes2.tdd),
aggrtypes3: tdd(../data/AggrTypes3.tdd),
covarTypes: tdd(../data/CovarTypes.tdd),
diff --git a/exec/java-exec/src/main/codegen/data/Casts.tdd b/exec/java-exec/src/main/codegen/data/Casts.tdd
index 63fa0e4cb..e43572a87 100644
--- a/exec/java-exec/src/main/codegen/data/Casts.tdd
+++ b/exec/java-exec/src/main/codegen/data/Casts.tdd
@@ -80,149 +80,65 @@
{from: "IntervalYear", to: "Interval", major: "IntervalSimpleToComplex", months: "in.value", days: "0", millis: "0"},
{from: "IntervalDay", to: "Interval", major: "IntervalSimpleToComplex", months: "0", days: "in.days", millis: "in.milliseconds"},
{from: "Interval", to: "IntervalYear", major: "IntervalComplexToSimple"},
- {from: "Interval", to: "IntervalDay", major: "IntervalComplexToSimple"}
-
- {from: "Decimal9", to: "Decimal18", major: "DecimalSimpleDecimalSimple", javatype: "long"},
-
- {from: "Decimal9", to: "Decimal28Dense", major: "DecimalSimpleDecimalDense", arraySize: "3"},
- {from: "Decimal9", to: "Decimal38Dense", major: "DecimalSimpleDecimalDense", arraySize: "4"},
- {from: "Decimal18", to: "Decimal28Dense", major: "DecimalSimpleDecimalDense", arraySize: "3"},
- {from: "Decimal18", to: "Decimal38Dense", major: "DecimalSimpleDecimalDense", arraySize: "4"},
-
- {from: "Decimal9", to: "Decimal28Sparse", major: "DecimalSimpleDecimalSparse", arraySize: "5"},
- {from: "Decimal9", to: "Decimal38Sparse", major: "DecimalSimpleDecimalSparse", arraySize: "6"},
- {from: "Decimal18", to: "Decimal28Sparse", major: "DecimalSimpleDecimalSparse", arraySize: "5"},
- {from: "Decimal18", to: "Decimal38Sparse", major: "DecimalSimpleDecimalSparse", arraySize: "6"},
-
- {from: "Decimal28Dense", to: "Decimal28Sparse", major: "DecimalDenseDecimalSparse", arraySize: "5"},
- {from: "Decimal28Dense", to: "Decimal38Sparse", major: "DecimalDenseDecimalSparse",arraySize: "6"},
- {from: "Decimal38Dense", to: "Decimal38Sparse", major: "DecimalDenseDecimalSparse", arraySize: "6"},
-
- {from: "Decimal28Sparse", to: "Decimal28Dense", major: "DecimalSparseDecimalDense", arraySize: "3"},
- {from: "Decimal28Sparse", to: "Decimal38Dense", major: "DecimalSparseDecimalDense", arraySize: "4"},
- {from: "Decimal38Sparse", to: "Decimal38Dense", major: "DecimalSparseDecimalDense", arraySize: "4"},
-
- {from: "Decimal28Sparse", to: "VarDecimal", major: "DecimalSparseVarDecimal", arraySize: "6"},
- {from: "Decimal38Sparse", to: "VarDecimal", major: "DecimalSparseVarDecimal", arraySize: "6"},
-
- {from: "Decimal28Dense", to: "Decimal38Dense", major: "DecimalSimilar", arraySize: "4"},
- {from: "Decimal28Sparse", to: "Decimal38Sparse", major: "DecimalSimilar", arraySize: "6"},
-
- {from: "Int", to: "Decimal9", major: "IntDecimal", javatype: "int"},
- {from: "Int", to: "Decimal18", major: "IntDecimal", javatype: "long"},
- {from: "Int", to: "Decimal28Sparse", major: "IntDecimal", arraySize: "5"},
- {from: "Int", to: "Decimal38Sparse", major: "IntDecimal", arraySize: "6"},
- {from: "Int", to: "VarDecimal", major: "IntDecimal", arraySize: "6"},
-
- {from: "BigInt", to: "Decimal9", major: "BigIntDecimal", javatype: "int"},
- {from: "BigInt", to: "Decimal18", major: "BigIntDecimal", javatype: "long"},
- {from: "BigInt", to: "Decimal28Sparse", major: "BigIntDecimal", arraySize: "5"},
- {from: "BigInt", to: "Decimal38Sparse", major: "BigIntDecimal", arraySize: "6"},
- {from: "BigInt", to: "VarDecimal", major: "BigIntDecimal", arraySize: "6"},
-
- {from: "Decimal9", to: "Int", major: "DecimalSimpleInt", javatype: "int"},
- {from: "Decimal18", to: "Int", major: "DecimalSimpleInt", javatype: "int"},
- {from: "Decimal28Sparse", to: "Int", major: "DecimalComplexInt", javatype: "int"},
- {from: "Decimal38Sparse", to: "Int", major: "DecimalComplexInt", javatype: "int"},
+ {from: "Interval", to: "IntervalDay", major: "IntervalComplexToSimple"},
+
+ {from: "Decimal9", to: "VarDecimal", major: "DecimalToVarDecimal"},
+ {from: "Decimal18", to: "VarDecimal", major: "DecimalToVarDecimal"},
+ {from: "Decimal28Sparse", to: "VarDecimal", major: "DecimalToVarDecimal"},
+ {from: "Decimal38Sparse", to: "VarDecimal", major: "DecimalToVarDecimal"},
+ {from: "VarDecimal", to: "VarDecimal", major: "DecimalToVarDecimal"},
+
+ {from: "VarDecimal", to: "Decimal9", major: "VarDecimalToDecimal"},
+ {from: "VarDecimal", to: "Decimal18", major: "VarDecimalToDecimal"},
+ {from: "VarDecimal", to: "Decimal28Sparse", major: "VarDecimalToDecimal", arraySize: "5"},
+ {from: "VarDecimal", to: "Decimal38Sparse", major: "VarDecimalToDecimal", arraySize: "6"},
+
+ {from: "Int", to: "VarDecimal", major: "IntDecimal"},
+
+ {from: "BigInt", to: "VarDecimal", major: "BigIntDecimal"},
+
{from: "VarDecimal", to: "Int", major: "DecimalComplexInt", javatype: "int"},
- {from: "Decimal9", to: "BigInt", major: "DecimalSimpleBigInt", javatype: "long"},
- {from: "Decimal18", to: "BigInt", major: "DecimalSimpleBigInt", javatype: "long"},
- {from: "Decimal28Sparse", to: "BigInt", major: "DecimalComplexBigInt", javatype: "long"},
- {from: "Decimal38Sparse", to: "BigInt", major: "DecimalComplexBigInt", javatype: "long"},
{from: "VarDecimal", to: "BigInt", major: "DecimalComplexBigInt", javatype: "long"},
- {from: "Decimal9", to: "Float4", major: "DecimalSimpleFloat", javatype: "float"},
- {from: "Decimal18", to: "Float4", major: "DecimalSimpleFloat", javatype: "float"},
- {from: "Decimal28Sparse", to: "Float4", major: "DecimalComplexFloat", javatype: "float"},
- {from: "Decimal28Dense", to: "Float4", major: "DecimalComplexFloat", javatype: "float"},
- {from: "Decimal38Sparse", to: "Float4", major: "DecimalComplexFloat", javatype: "float"},
- {from: "Decimal38Dense", to: "Float4", major: "DecimalComplexFloat", javatype: "float"},
{from: "VarDecimal", to: "Float4", major: "DecimalComplexFloat", javatype: "float"},
- {from: "Float4", to: "Decimal9", major: "FloatDecimalSimple", javatype: "int"},
- {from: "Float4", to: "Decimal18", major: "FloatDecimalSimple", javatype: "long"},
- {from: "Float4", to: "Decimal28Sparse", major: "FloatDecimalComplex", arraySize: "5"},
- {from: "Float4", to: "Decimal38Sparse", major: "FloatDecimalComplex", arraySize: "6"},
- {from: "Float4", to: "VarDecimal", major: "FloatDecimalComplex", arraySize: "6"},
-
- {from: "Float8", to: "Decimal9", major: "DoubleDecimalSimple", javatype: "int"},
- {from: "Float8", to: "Decimal18", major: "DoubleDecimalSimple", javatype: "long"},
- {from: "Float8", to: "Decimal28Sparse", major: "DoubleDecimalComplex", arraySize: "5"},
- {from: "Float8", to: "Decimal38Sparse", major: "DoubleDecimalComplex", arraySize: "6"}
- {from: "Float8", to: "VarDecimal", major: "DoubleDecimalComplex", arraySize: "6"}
-
- {from: "Decimal9", to: "Float8", major: "DecimalSimpleDouble", javatype: "double"},
- {from: "Decimal18", to: "Float8", major: "DecimalSimpleDouble", javatype: "double"},
- {from: "Decimal28Sparse", to: "Float8", major: "DecimalComplexDouble", javatype: "double"},
- {from: "Decimal28Dense", to: "Float8", major: "DecimalComplexDouble", javatype: "double"},
- {from: "Decimal38Sparse", to: "Float8", major: "DecimalComplexDouble", javatype: "double"},
- {from: "Decimal38Dense", to: "Float8", major: "DecimalComplexDouble", javatype: "double"},
- {from: "VarDecimal", to: "Float8", major: "DecimalComplexDouble", javatype: "double"},
-
- {from: "VarChar", to: "Decimal9", major: "VarCharDecimalSimple", javatype: "int"},
- {from: "VarChar", to: "Decimal18", major: "VarCharDecimalSimple", javatype: "long"},
- {from: "VarChar", to: "Decimal28Sparse", major: "VarCharDecimalComplex", arraySize: "5"},
- {from: "VarChar", to: "Decimal38Sparse", major: "VarCharDecimalComplex", arraySize: "6"},
- {from: "VarChar", to: "VarDecimal", major: "VarCharDecimalComplex", arraySize: "6"},
+ {from: "Float4", to: "VarDecimal", major: "FloatDecimalComplex"},
- {from: "Decimal9", to: "VarChar", major: "DecimalSimpleVarChar", bufferSize: "11", javatype: "int"},
- {from: "Decimal18", to: "VarChar", major: "DecimalSimpleVarChar", bufferSize: "20", javatype: "long"},
- {from: "Decimal28Sparse", to: "VarChar", major: "DecimalComplexVarChar", bufferSize: "30", arraySize: "5"},
- {from: "Decimal38Sparse", to: "VarChar", major: "DecimalComplexVarChar", bufferSize: "40", arraySize: "6"},
- {from: "VarDecimal", to: "VarChar", major: "DecimalComplexVarChar", bufferSize: "40", arraySize: "6"},
+ {from: "Float8", to: "VarDecimal", major: "DoubleDecimalComplex"},
- {from: "Decimal18", to: "Decimal9", major: "DownwardDecimalSimpleDecimalSimple", javatype: "int"},
+ {from: "VarDecimal", to: "Float8", major: "DecimalComplexDouble", javatype: "double"},
- {from: "Decimal28Sparse", to: "Decimal18", major: "DownwardDecimalSimpleDecimalComplex", javatype: "long"},
- {from: "Decimal28Sparse", to: "Decimal9", major: "DownwardDecimalSimpleDecimalComplex", javatype: "int"},
+ {from: "VarChar", to: "VarDecimal", major: "VarCharDecimalComplex"},
- {from: "Decimal38Sparse", to: "Decimal28Sparse", major: "DownwardDecimalComplexDecimalComplex", arraySize: "5"},
- {from: "Decimal38Sparse", to: "Decimal18", major: "DownwardDecimalComplexDecimalSimple", javatype: "long"},
- {from: "Decimal38Sparse", to: "Decimal9", major: "DownwardDecimalComplexDecimalSimple", javatype: "int"},
+ {from: "VarDecimal", to: "VarChar", major: "DecimalComplexVarChar"},
{from: "VarChar", to: "NullableInt", major: "EmptyString", javaType:"Integer", primeType:"int"},
{from: "VarChar", to: "NullableBigInt", major: "EmptyString", javaType: "Long", primeType: "long"},
{from: "VarChar", to: "NullableFloat4", major: "EmptyString", javaType:"Float", parse:"Float"},
{from: "VarChar", to: "NullableFloat8", major: "EmptyString", javaType:"Double", parse:"Double"},
- {from: "VarChar", to: "NullableDecimal9", major: "EmptyStringVarCharDecimalSimple", javatype: "int"},
- {from: "VarChar", to: "NullableDecimal18", major: "EmptyStringVarCharDecimalSimple", javatype: "long"},
- {from: "VarChar", to: "NullableDecimal28Sparse", major: "EmptyStringVarCharDecimalComplex", arraySize: "5"},
- {from: "VarChar", to: "NullableDecimal38Sparse", major: "EmptyStringVarCharDecimalComplex", arraySize: "6"},
- {from: "VarChar", to: "NullableVarDecimal", major: "EmptyStringVarCharDecimalComplex", arraySize: "6"},
+ {from: "VarChar", to: "NullableVarDecimal", major: "EmptyStringVarCharDecimalComplex"},
{from: "NullableVarChar", to: "NullableInt", major: "EmptyString", javaType:"Integer", primeType:"int"},
{from: "NullableVarChar", to: "NullableBigInt", major: "EmptyString", javaType: "Long", primeType: "long"},
{from: "NullableVarChar", to: "NullableFloat4", major: "EmptyString", javaType:"Float", parse:"Float"},
{from: "NullableVarChar", to: "NullableFloat8", major: "EmptyString", javaType:"Double", parse:"Double"},
- {from: "NullableVarChar", to: "NullableDecimal9", major: "EmptyStringVarCharDecimalSimple", javatype: "int"},
- {from: "NullableVarChar", to: "NullableDecimal18", major: "EmptyStringVarCharDecimalSimple", javatype: "long"},
- {from: "NullableVarChar", to: "NullableDecimal28Sparse", major: "EmptyStringVarCharDecimalComplex", arraySize: "5"},
- {from: "NullableVarChar", to: "NullableDecimal38Sparse", major: "EmptyStringVarCharDecimalComplex", arraySize: "6"},
- {from: "NullableVarChar", to: "NullableVarDecimal", major: "EmptyStringVarCharDecimalComplex", arraySize: "6"},
+ {from: "NullableVarChar", to: "NullableVarDecimal", major: "EmptyStringVarCharDecimalComplex"},
{from: "NullableVar16Char", to: "NullableInt", major: "EmptyString", javaType:"Integer", primeType:"int"},
{from: "NullableVar16Char", to: "NullableBigInt", major: "EmptyString", javaType: "Long", primeType: "long"},
{from: "NullableVar16Char", to: "NullableFloat4", major: "EmptyString", javaType:"Float", parse:"Float"},
{from: "NullableVar16Char", to: "NullableFloat8", major: "EmptyString", javaType:"Double", parse:"Double"},
- {from: "NullableVar16Char", to: "NullableDecimal9", major: "EmptyStringVarCharDecimalSimple", javatype: "int"},
- {from: "NullableVar16Char", to: "NullableDecimal18", major: "EmptyStringVarCharDecimalSimple", javatype: "long"},
- {from: "NullableVar16Char", to: "NullableDecimal28Sparse", major: "EmptyStringVarCharDecimalComplex", arraySize: "5"},
- {from: "NullableVar16Char", to: "NullableDecimal38Sparse", major: "EmptyStringVarCharDecimalComplex", arraySize: "6"},
- {from: "NullableVar16Char", to: "NullableVarDecimal", major: "EmptyStringVarCharDecimalComplex", arraySize: "6"},
+ {from: "NullableVar16Char", to: "NullableVarDecimal", major: "EmptyStringVarCharDecimalComplex"},
{from: "NullableVarBinary", to: "NullableInt", major: "EmptyString", javaType:"Integer", primeType:"int"},
{from: "NullableVarBinary", to: "NullableBigInt", major: "EmptyString", javaType: "Long", primeType: "long"},
{from: "NullableVarBinary", to: "NullableFloat4", major: "EmptyString", javaType:"Float", parse:"Float"},
{from: "NullableVarBinary", to: "NullableFloat8", major: "EmptyString", javaType:"Double", parse:"Double"},
- {from: "NullableVarBinary", to: "NullableDecimal9", major: "EmptyStringVarCharDecimalSimple", javatype: "int"},
- {from: "NullableVarBinary", to: "NullableDecimal18", major: "EmptyStringVarCharDecimalSimple", javatype: "long"},
- {from: "NullableVarBinary", to: "NullableDecimal28Sparse", major: "EmptyStringVarCharDecimalComplex", arraySize: "5"},
- {from: "NullableVarBinary", to: "NullableDecimal38Sparse", major: "EmptyStringVarCharDecimalComplex", arraySize: "6"},
- {from: "NullableVarBinary", to: "NullableVarDecimal", major: "EmptyStringVarCharDecimalComplex", arraySize: "6"},
+ {from: "NullableVarBinary", to: "NullableVarDecimal", major: "EmptyStringVarCharDecimalComplex"},
]
-}
+}
diff --git a/exec/java-exec/src/main/codegen/data/ComparisonTypesDecimal.tdd b/exec/java-exec/src/main/codegen/data/ComparisonTypesDecimal.tdd
index db73825d9..f5b912e83 100644
--- a/exec/java-exec/src/main/codegen/data/ComparisonTypesDecimal.tdd
+++ b/exec/java-exec/src/main/codegen/data/ComparisonTypesDecimal.tdd
@@ -13,11 +13,9 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
-#
-# TODO: the assumption that VarDecimal takes 6 bytes might not always apply
{
{ decimalTypes: [
- {name: "VarDecimal", storage: "6"},
+ {name: "VarDecimal"},
{name: "Decimal28Sparse", storage: "5"},
{name: "Decimal38Sparse", storage: "6"},
{name: "Decimal28Dense", storage: "4"},
diff --git a/exec/java-exec/src/main/codegen/data/CountAggrTypes.tdd b/exec/java-exec/src/main/codegen/data/CountAggrTypes.tdd
index 188517a68..21fcf2043 100644
--- a/exec/java-exec/src/main/codegen/data/CountAggrTypes.tdd
+++ b/exec/java-exec/src/main/codegen/data/CountAggrTypes.tdd
@@ -40,6 +40,8 @@
"NullableVarBinary",
"RepeatedVarBinary"
"VarDecimal",
+ "NullableVarDecimal",
+ "RepeatedVarDecimal",
"Decimal9",
"NullableDecimal9",
"RepeatedDecimal9",
diff --git a/exec/java-exec/src/main/codegen/data/DecimalAggrTypes1.tdd b/exec/java-exec/src/main/codegen/data/DecimalAggrTypes1.tdd
index f24629140..7da2d071f 100644
--- a/exec/java-exec/src/main/codegen/data/DecimalAggrTypes1.tdd
+++ b/exec/java-exec/src/main/codegen/data/DecimalAggrTypes1.tdd
@@ -17,43 +17,24 @@
{
aggrtypes: [
{className: "Max", funcName: "max", types: [
- {inputType: "Decimal9", outputType: "Decimal9", runningType: "Decimal9", initValue: "Integer.MIN_VALUE"},
- {inputType: "NullableDecimal9", outputType: "Decimal9", runningType: "Decimal9", initValue: "Integer.MIN_VALUE"},
- {inputType: "Decimal18", outputType: "Decimal18", runningType: "Decimal18", initValue: "Long.MIN_VALUE"},
- {inputType: "NullableDecimal18", outputType: "Decimal18", runningType: "Decimal18", initValue: "Long.MIN_VALUE"},
- {inputType: "Decimal28Sparse", outputType: "Decimal28Sparse", runningType: "Decimal28Sparse"},
- {inputType: "NullableDecimal28Sparse", outputType: "Decimal28Sparse", runningType: "Decimal28Sparse"},
- {inputType: "Decimal38Sparse", outputType: "Decimal38Sparse", runningType: "Decimal38Sparse"},
- {inputType: "NullableDecimal38Sparse", outputType: "Decimal38Sparse", runningType: "Decimal38Sparse"},
- {inputType: "VarDecimal", outputType: "VarDecimal", runningType: "VarDecimal"},
- {inputType: "NullableVarDecimal", outputType: "VarDecimal", runningType: "VarDecimal"}
+ {inputType: "VarDecimal", outputType: "NullableVarDecimal"},
+ {inputType: "NullableVarDecimal", outputType: "NullableVarDecimal"}
]
},
{className: "Min", funcName: "min", types: [
- {inputType: "Decimal9", outputType: "Decimal9", runningType: "Decimal9", initValue: "Integer.MAX_VALUE"},
- {inputType: "NullableDecimal9", outputType: "Decimal9", runningType: "Decimal9", initValue: "Integer.MAX_VALUE"},
- {inputType: "Decimal18", outputType: "Decimal18", runningType: "Decimal18", initValue: "Integer.MAX_VALUE"},
- {inputType: "NullableDecimal18", outputType: "Decimal18", runningType: "Decimal18", initValue: "Integer.MAX_VALUE"},
- {inputType: "Decimal28Sparse", outputType: "Decimal28Sparse", runningType: "Decimal28Sparse"},
- {inputType: "NullableDecimal28Sparse", outputType: "Decimal28Sparse", runningType: "Decimal28Sparse"},
- {inputType: "Decimal38Sparse", outputType: "Decimal38Sparse", runningType: "Decimal38Sparse"},
- {inputType: "NullableDecimal38Sparse", outputType: "Decimal38Sparse", runningType: "Decimal38Sparse"},
- {inputType: "VarDecimal", outputType: "VarDecimal", runningType: "VarDecimal"},
- {inputType: "NullableVarDecimal", outputType: "VarDecimal", runningType: "VarDecimal"}
+ {inputType: "VarDecimal", outputType: "NullableVarDecimal"},
+ {inputType: "NullableVarDecimal", outputType: "NullableVarDecimal"}
]
+ },
+ {className: "Sum", funcName: "sum", types: [
+ {inputType: "VarDecimal", outputType: "NullableVarDecimal"},
+ {inputType: "NullableVarDecimal", outputType: "NullableVarDecimal"}
+ ]
+ },
+ {className: "SumZero", funcName: "$sum0", types: [
+ {inputType: "VarDecimal", outputType: "NullableVarDecimal"},
+ {inputType: "NullableVarDecimal", outputType: "NullableVarDecimal"}
+ ]
}
- {className: "Sum", funcName: "sum", types: [
- {inputType: "Decimal9", outputType: "Decimal38Sparse", major: "Numeric"},
- {inputType: "NullableDecimal9", outputType: "Decimal38Sparse", major: "Numeric"},
- {inputType: "Decimal18", outputType: "Decimal38Sparse", major: "Numeric"},
- {inputType: "NullableDecimal18", outputType: "Decimal38Sparse", major: "Numeric"},
- {inputType: "Decimal28Sparse", outputType: "Decimal38Sparse", major: "Numeric"},
- {inputType: "NullableDecimal28Sparse", outputType: "Decimal38Sparse", major: "Numeric"},
- {inputType: "Decimal38Sparse", outputType: "Decimal38Sparse", major: "Numeric"},
- {inputType: "NullableDecimal38Sparse", outputType: "Decimal38Sparse", major: "Numeric"},
- {inputType: "VarDecimal", outputType: "VarDecimal", major: "Numeric"},
- {inputType: "NullableVarDecimal", outputType: "VarDecimal", major: "Numeric"}
- ]
- }
- ]
+ ]
}
diff --git a/exec/java-exec/src/main/codegen/data/DecimalAggrTypes2.tdd b/exec/java-exec/src/main/codegen/data/DecimalAggrTypes2.tdd
index faa0afd9f..36a92336a 100644
--- a/exec/java-exec/src/main/codegen/data/DecimalAggrTypes2.tdd
+++ b/exec/java-exec/src/main/codegen/data/DecimalAggrTypes2.tdd
@@ -17,16 +17,8 @@
{
aggrtypes: [
{className: "Avg", funcName: "avg", types: [
- {inputType: "Decimal9", outputType: "Decimal38Sparse", countRunningType: "BigInt", major: "Numeric"},
- {inputType: "NullableDecimal9", outputType: "Decimal38Sparse", countRunningType: "BigInt", major: "Numeric"},
- {inputType: "Decimal18", outputType: "Decimal38Sparse", countRunningType: "BigInt", major: "Numeric"},
- {inputType: "NullableDecimal18", outputType: "Decimal38Sparse", countRunningType: "BigInt", major: "Numeric"},
- {inputType: "Decimal28Sparse", outputType: "Decimal38Sparse", countRunningType: "BigInt", major: "Numeric"},
- {inputType: "NullableDecimal28Sparse", outputType: "Decimal38Sparse", countRunningType: "BigInt", major: "Numeric"},
- {inputType: "Decimal38Sparse", outputType: "Decimal38Sparse", countRunningType: "BigInt", major: "Numeric"},
- {inputType: "NullableDecimal38Sparse", outputType: "Decimal38Sparse", countRunningType: "BigInt", major: "Numeric"},
- {inputType: "VarDecimal", outputType: "VarDecimal", countRunningType: "BigInt", major: "Numeric"},
- {inputType: "NullableVarDecimal", outputType: "VarDecimal", countRunningType: "BigInt", major: "Numeric"}
+ {inputType: "VarDecimal", outputType: "NullableVarDecimal", countRunningType: "BigInt"},
+ {inputType: "NullableVarDecimal", outputType: "NullableVarDecimal", countRunningType: "BigInt"}
]
}
]
diff --git a/exec/java-exec/src/main/codegen/data/DecimalAggrTypes3.tdd b/exec/java-exec/src/main/codegen/data/DecimalAggrTypes3.tdd
new file mode 100644
index 000000000..670c53d30
--- /dev/null
+++ b/exec/java-exec/src/main/codegen/data/DecimalAggrTypes3.tdd
@@ -0,0 +1,43 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http:# www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+{
+ aggrtypes: [
+ {className: "StdDevPop", funcName: "stddev_pop", aliasName: "", types: [
+ {inputType: "VarDecimal", outputType: "NullableVarDecimal"},
+ {inputType: "NullableVarDecimal", outputType: "NullableVarDecimal"},
+ ]
+ },
+
+ {className: "VariancePop", funcName: "var_pop", aliasName: "", types: [
+ {inputType: "VarDecimal", outputType: "NullableVarDecimal"},
+ {inputType: "NullableVarDecimal", outputType: "NullableVarDecimal"},
+ ]
+ },
+
+ {className: "StdDevSample", funcName: "stddev_samp", aliasName: "stddev", types: [
+ {inputType: "VarDecimal", outputType: "NullableVarDecimal"},
+ {inputType: "NullableVarDecimal", outputType: "NullableVarDecimal"},
+ ]
+ },
+
+ {className: "VarianceSample", funcName: "var_samp", aliasName: "variance", types: [
+ {inputType: "VarDecimal", outputType: "NullableVarDecimal"},
+ {inputType: "NullableVarDecimal", outputType: "NullableVarDecimal"},
+ ]
+ }
+ ]
+}
diff --git a/exec/java-exec/src/main/codegen/data/MathFunc.tdd b/exec/java-exec/src/main/codegen/data/MathFunc.tdd
index cd449166d..51a1b289e 100644
--- a/exec/java-exec/src/main/codegen/data/MathFunc.tdd
+++ b/exec/java-exec/src/main/codegen/data/MathFunc.tdd
@@ -199,9 +199,7 @@ logBaseMathFunction : [
{input: "UInt1"},
{input: "UInt2"},
{input: "UInt4"},
- {input: "UInt8"},
- {input: "Decimal9"},
- {input: "Decimal18"}
+ {input: "UInt8"}
]
}
],
@@ -216,9 +214,7 @@ extendedUnaryMathFunctions : [
{input: "UInt1"},
{input: "UInt2"},
{input: "UInt4"},
- {input: "UInt8"},
- {input: "Decimal9"},
- {input: "Decimal18"}
+ {input: "UInt8"}
]
},
@@ -232,9 +228,7 @@ extendedUnaryMathFunctions : [
{input: "UInt1"},
{input: "UInt2"},
{input: "UInt4"},
- {input: "UInt8"},
- {input: "Decimal9"},
- {input: "Decimal18"}
+ {input: "UInt8"}
]
},
@@ -248,9 +242,7 @@ extendedUnaryMathFunctions : [
{input: "UInt1"},
{input: "UInt2"},
{input: "UInt4"},
- {input: "UInt8"},
- {input: "Decimal9"},
- {input: "Decimal18"}
+ {input: "UInt8"}
]
},
@@ -278,9 +270,7 @@ extendedUnaryMathFunctions : [
{input: "UInt1"},
{input: "UInt2"},
{input: "UInt4"},
- {input: "UInt8"},
- {input: "Decimal9"},
- {input: "Decimal18"}
+ {input: "UInt8"}
]
},
@@ -294,9 +284,7 @@ extendedUnaryMathFunctions : [
{input: "UInt1"},
{input: "UInt2"},
{input: "UInt4"},
- {input: "UInt8"},
- {input: "Decimal9"},
- {input: "Decimal18"}
+ {input: "UInt8"}
]
}
],
diff --git a/exec/java-exec/src/main/codegen/data/NumericTypes.tdd b/exec/java-exec/src/main/codegen/data/NumericTypes.tdd
index afc0ee817..9f33353a8 100644
--- a/exec/java-exec/src/main/codegen/data/NumericTypes.tdd
+++ b/exec/java-exec/src/main/codegen/data/NumericTypes.tdd
@@ -15,8 +15,7 @@
# limitations under the License.
{
- numeric: ["Int", "BigInt", "TinyInt", "SmallInt", "UInt1", "UInt2", "UInt4", "UInt8", "Float4", "Float8", "VarDecimal",
- "Decimal9", "Decimal18", "Decimal28Dense", "Decimal28Sparse", "Decimal38Dense", "Decimal38Sparse"],
+ numeric: ["Int", "BigInt", "TinyInt", "SmallInt", "UInt1", "UInt2", "UInt4", "UInt8", "Float4", "Float8", "VarDecimal"],
numericFunctions: [
{className: "IsNumeric", funcName: "isnumeric", aliasName: "", outputType: "Int", types: [
diff --git a/exec/java-exec/src/main/codegen/templates/CastHigh.java b/exec/java-exec/src/main/codegen/templates/CastHigh.java
index 26d6be80d..1a876c8a2 100644
--- a/exec/java-exec/src/main/codegen/templates/CastHigh.java
+++ b/exec/java-exec/src/main/codegen/templates/CastHigh.java
@@ -42,26 +42,30 @@ public class CastHighFunctions {
<#list casthigh.types as type>
@SuppressWarnings("unused")
- @FunctionTemplate(name = "casthigh", scope = FunctionTemplate.FunctionScope.SIMPLE, nulls=NullHandling.NULL_IF_NULL)
+ @FunctionTemplate(name = "casthigh",
+ scope = FunctionTemplate.FunctionScope.SIMPLE,
+ <#if type.from.contains("Decimal")>
+ returnType = FunctionTemplate.ReturnType.DECIMAL_AGGREGATE,
+ </#if>
+ nulls = NullHandling.NULL_IF_NULL)
public static class CastHigh${type.from} implements DrillSimpleFunc {
@Param ${type.from}Holder in;
<#if type.from.contains("Decimal")>
- @Output ${type.from}Holder out;
+ @Output ${type.from}Holder out;
<#else>
- @Output ${type.to}Holder out;
+ @Output ${type.to}Holder out;
</#if>
public void setup() {}
public void eval() {
- <#if type.value >
- out.value = (double) in.value;
+ <#if type.value>
+ out.value = (double) in.value;
<#else>
- out = in;
+ out = in;
</#if>
}
}
</#list>
}
-
diff --git a/exec/java-exec/src/main/codegen/templates/DateIntervalFunctionTemplates/ToTimeStampFunction.java b/exec/java-exec/src/main/codegen/templates/DateIntervalFunctionTemplates/ToTimeStampFunction.java
index 63c761497..b6cbfeb2c 100644
--- a/exec/java-exec/src/main/codegen/templates/DateIntervalFunctionTemplates/ToTimeStampFunction.java
+++ b/exec/java-exec/src/main/codegen/templates/DateIntervalFunctionTemplates/ToTimeStampFunction.java
@@ -40,41 +40,27 @@ import org.apache.drill.exec.record.RecordBatch;
* This class is generated using freemarker and the ${.template_name} template.
*/
-@FunctionTemplate(name = "to_timestamp" , scope = FunctionTemplate.FunctionScope.SIMPLE, nulls = NullHandling.NULL_IF_NULL)
+@FunctionTemplate(name = "to_timestamp",
+ scope = FunctionTemplate.FunctionScope.SIMPLE,
+ nulls = NullHandling.NULL_IF_NULL)
public class G${numerics}ToTimeStamp implements DrillSimpleFunc {
+ @Param ${numerics}Holder left;
+ @Output TimeStampHolder out;
- @Param ${numerics}Holder left;
- <#if numerics.startsWith("Decimal")>
- @Workspace java.math.BigInteger millisConstant;
- </#if>
- @Output TimeStampHolder out;
-
- public void setup() {
- <#if numerics.startsWith("Decimal")>
- millisConstant = java.math.BigInteger.valueOf(1000);
- </#if>
- }
+ public void setup() {
+ }
- public void eval() {
- long inputMillis = 0;
+ public void eval() {
+ long inputMillis = 0;
- <#if (numerics.contains("Decimal"))>
- <#if (numerics == "VarDecimal")>
- java.math.BigDecimal input = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromDrillBuf(left.buffer, left.start, left.end - left.start, left.scale);
- inputMillis = input.multiply(new java.math.BigDecimal(1000)).longValue();
- <#elseif (numerics == "Decimal9") || (numerics == "Decimal18")>
- java.math.BigInteger value = java.math.BigInteger.valueOf(left.value);
- value = value.multiply(millisConstant);
- inputMillis = (new java.math.BigDecimal(value, left.scale)).longValue();
- <#elseif (numerics == "Decimal28Sparse") || (numerics == "Decimal38Sparse")>
- java.math.BigDecimal input = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromSparse(left.buffer, left.start, left.nDecimalDigits, left.scale);
- inputMillis = input.multiply(new java.math.BigDecimal(1000)).longValue();
- </#if>
- <#else>
- inputMillis = (long) (left.value * 1000l);
- </#if>
- out.value = new org.joda.time.DateTime(inputMillis).withZoneRetainFields(org.joda.time.DateTimeZone.UTC).getMillis();
- }
+ <#if (numerics == "VarDecimal")>
+ java.math.BigDecimal input = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromDrillBuf(left.buffer, left.start, left.end - left.start, left.scale);
+ inputMillis = input.multiply(new java.math.BigDecimal(1000)).longValue();
+ <#else>
+ inputMillis = (long) (left.value * 1000L);
+ </#if>
+ out.value = new org.joda.time.DateTime(inputMillis).withZoneRetainFields(org.joda.time.DateTimeZone.UTC).getMillis();
+ }
}
</#list> \ No newline at end of file
diff --git a/exec/java-exec/src/main/codegen/templates/Decimal/CastDecimalDenseDecimalSparse.java b/exec/java-exec/src/main/codegen/templates/Decimal/CastDecimalDenseDecimalSparse.java
deleted file mode 100644
index d637dde65..000000000
--- a/exec/java-exec/src/main/codegen/templates/Decimal/CastDecimalDenseDecimalSparse.java
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-<@pp.dropOutputFile />
-
-<#list cast.types as type>
-<#if type.major == "DecimalDenseDecimalSparse">
-
-<@pp.changeOutputFile name="/org/apache/drill/exec/expr/fn/impl/gcast/Cast${type.from}${type.to}.java" />
-
-<#include "/@includes/license.ftl" />
-
-package org.apache.drill.exec.expr.fn.impl.gcast;
-
-<#include "/@includes/vv_imports.ftl" />
-
-import org.apache.drill.exec.expr.DrillSimpleFunc;
-import org.apache.drill.exec.expr.annotations.FunctionTemplate;
-import org.apache.drill.exec.expr.annotations.FunctionTemplate.NullHandling;
-import org.apache.drill.exec.expr.annotations.Output;
-import org.apache.drill.exec.expr.annotations.Param;
-import org.apache.drill.exec.expr.holders.*;
-import org.apache.drill.exec.record.RecordBatch;
-import org.apache.drill.exec.expr.annotations.Workspace;
-
-import io.netty.buffer.ByteBuf;
-import io.netty.buffer.DrillBuf;
-
-import java.nio.ByteBuffer;
-/*
- * This class is generated using freemarker and the ${.template_name} template.
- */
-
-@SuppressWarnings("unused")
-@FunctionTemplate(name = "cast${type.to?upper_case}",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_CAST,
- nulls = NullHandling.NULL_IF_NULL)
-public class Cast${type.from}${type.to} implements DrillSimpleFunc{
-
- @Param ${type.from}Holder in;
- @Inject DrillBuf buffer;
- @Param BigIntHolder precision;
- @Param BigIntHolder scale;
- @Output ${type.to}Holder out;
-
- public void setup() {
- int size = (${type.arraySize} * (org.apache.drill.exec.util.DecimalUtility.INTEGER_SIZE));
- buffer = buffer.reallocIfNeeded(size);
- }
-
- public void eval() {
- out.buffer = buffer;
- out.start = 0;
-
- // Re initialize the buffer everytime
- for (int i = 0; i < ${type.arraySize}; i++) {
- out.setInteger(i, 0, out.start, out.buffer);
- }
- out.scale = (int) scale.value;
- out.precision = (int) precision.value;
- out.setSign(in.getSign(in.start, in.buffer), out.start, out.buffer);
-
- /* We store base 1 Billion integers in our representation, which requires
- * 30 bits, but a typical integer requires 32 bits. In our dense representation
- * we shift bits around to utilize the two available bits, to get back to our sparse
- * representation rearrange the bits so that we use 32 bits represent the digits.
- */
-
- byte[] intermediateBytes = new byte[(in.nDecimalDigits * org.apache.drill.exec.util.DecimalUtility.INTEGER_SIZE) + 1];
-
- int[] mask = {0x03, 0x0F, 0x3F, 0xFF};
- int[] reverseMask = {0xFC, 0xF0, 0xC0, 0x00};
-
- <#if (type.from == "Decimal38Dense")>
- int maskIndex = 0;
- int shiftOrder = 6;
- byte shiftBits = 0x00;
- intermediateBytes[0] = (byte) (in.buffer.getByte(0) & 0x7F);
- <#elseif (type.from == "Decimal28Dense")>
- int maskIndex = 1;
- int shiftOrder = 4;
- byte shiftBits = (byte) ((in.buffer.getByte(0) & 0x03) << shiftOrder);
- intermediateBytes[0] = (byte) (((in.buffer.getByte(0) & 0x3C) & 0xFF) >>> 2);
- </#if>
-
- int intermediateIndex = 1;
- int inputIndex = in.start + 1;
-
- while (intermediateIndex < in.WIDTH) {
-
- intermediateBytes[intermediateIndex] = (byte) ((shiftBits) | (((in.buffer.getByte(inputIndex) & reverseMask[maskIndex]) & 0xFF) >>> (8 - shiftOrder)));
-
- shiftBits = (byte) ((in.buffer.getByte(inputIndex) & mask[maskIndex]) << shiftOrder);
-
- inputIndex++;
- intermediateIndex++;
-
- if (((intermediateIndex - 1) % org.apache.drill.exec.util.DecimalUtility.INTEGER_SIZE) == 0) {
- shiftBits = (byte) ((shiftBits & 0xFF) >>> 2);
- maskIndex++;
- shiftOrder -= 2;
- }
-
- }
-
- /* copy the last byte */
- intermediateBytes[intermediateIndex] = shiftBits;
-
- /* We have shifted the bits around and now each digit is represented by 32 digits
- * Now we transfer the bytes into a integer array and separate out the scale and
- * integer part of the decimal. Also pad the scale part with zeroes if needed
- */
- int[] intermediate = new int[(intermediateBytes.length/org.apache.drill.exec.util.DecimalUtility.INTEGER_SIZE) + 1];
-
- java.nio.ByteBuffer wrapper = java.nio.ByteBuffer.wrap(intermediateBytes);
- intermediate[0] = wrapper.get(0);
-
- int intermediateIdx = 1;
-
- for (int i = 1; i < intermediate.length; i++) {
- intermediate[i] = wrapper.getInt(intermediateIdx);
- intermediateIdx += 4;
- }
-
- int actualDigits;
- int srcIndex = intermediate.length - 1;
- int dstIndex = out.nDecimalDigits - 1;
-
- // break the scale and integer part and pad zeroes
- if (in.scale > 0 && (actualDigits = (in.scale % org.apache.drill.exec.util.DecimalUtility.MAX_DIGITS)) > 0) {
-
- int paddedDigits = org.apache.drill.exec.util.DecimalUtility.MAX_DIGITS - actualDigits;
- int padding = (int) (Math.pow(10, paddedDigits));
- int transferDigitMask = (int) (Math.pow(10, actualDigits));
-
- /* copy the remaining scale over to the last deciml digit */
- out.setInteger(dstIndex, ((intermediate[srcIndex] % transferDigitMask) * (padding)), out.start, out.buffer);
- dstIndex--;
-
- while (srcIndex > 0) {
- out.setInteger(dstIndex, ((intermediate[srcIndex]/transferDigitMask) + ((intermediate[srcIndex - 1] % transferDigitMask) * padding)), out.start, out.buffer);
-
- dstIndex--;
- srcIndex--;
- }
-
- out.setInteger(dstIndex, (intermediate[0]/transferDigitMask), out.start, out.buffer);
- } else {
- for (; srcIndex >= 0; srcIndex--, dstIndex--)
- out.setInteger(dstIndex, intermediate[srcIndex], out.start, out.buffer);
- }
- }
-}
-</#if>
-</#list> \ No newline at end of file
diff --git a/exec/java-exec/src/main/codegen/templates/Decimal/CastDecimalFloat.java b/exec/java-exec/src/main/codegen/templates/Decimal/CastDecimalFloat.java
index fe794094f..15686bacb 100644
--- a/exec/java-exec/src/main/codegen/templates/Decimal/CastDecimalFloat.java
+++ b/exec/java-exec/src/main/codegen/templates/Decimal/CastDecimalFloat.java
@@ -19,47 +19,7 @@
<#list cast.types as type>
-<#if type.major == "DecimalSimpleFloat" || type.major == "DecimalSimpleDouble"> <#-- Cast function template for conversion from Decimal9, Decimal18 to Float4 and Float8-->
-
-<@pp.changeOutputFile name="/org/apache/drill/exec/expr/fn/impl/gcast/Cast${type.from}${type.to}.java" />
-
-<#include "/@includes/license.ftl" />
-
-package org.apache.drill.exec.expr.fn.impl.gcast;
-
-import org.apache.drill.exec.expr.DrillSimpleFunc;
-import org.apache.drill.exec.expr.annotations.FunctionTemplate;
-import org.apache.drill.exec.expr.annotations.FunctionTemplate.NullHandling;
-import org.apache.drill.exec.expr.annotations.Output;
-import org.apache.drill.exec.expr.annotations.Param;
-import org.apache.drill.exec.expr.holders.*;
-import org.apache.drill.exec.record.RecordBatch;
-import org.apache.drill.exec.util.DecimalUtility;
-import org.apache.drill.exec.expr.annotations.Workspace;
-import io.netty.buffer.ByteBuf;
-import java.nio.ByteBuffer;
-
-/*
- * This class is generated using freemarker and the ${.template_name} template.
- */
-
-@SuppressWarnings("unused")
-@FunctionTemplate(name = "cast${type.to?upper_case}", scope = FunctionTemplate.FunctionScope.SIMPLE, nulls=NullHandling.NULL_IF_NULL)
-public class Cast${type.from}${type.to} implements DrillSimpleFunc {
-
-@Param ${type.from}Holder in;
-@Output ${type.to}Holder out;
-
- public void setup() {
- }
-
- public void eval() {
-
- // Divide the decimal with the scale to get the floating point value
- out.value = ((${type.javatype}) (in.value)) / (org.apache.drill.exec.util.DecimalUtility.getPowerOfTen((int) in.scale));
- }
-}
-<#elseif type.major == "DecimalComplexFloat" || type.major == "DecimalComplexDouble"> <#-- Cast function template for conversion from Decimal9, Decimal18 to Float4 -->
+<#if type.major == "DecimalComplexFloat" || type.major == "DecimalComplexDouble"> <#-- Cast function template for conversion from VarDecimal to Float4 -->
<@pp.changeOutputFile name="/org/apache/drill/exec/expr/fn/impl/gcast/Cast${type.from}${type.to}.java" />
@@ -86,26 +46,21 @@ import java.nio.ByteBuffer;
*/
@SuppressWarnings("unused")
-@FunctionTemplate(name = "cast${type.to?upper_case}", scope = FunctionTemplate.FunctionScope.SIMPLE, nulls=NullHandling.NULL_IF_NULL)
+@FunctionTemplate(name = "cast${type.to?upper_case}",
+ scope = FunctionTemplate.FunctionScope.SIMPLE,
+ nulls = NullHandling.NULL_IF_NULL)
public class Cast${type.from}${type.to} implements DrillSimpleFunc {
-@Param ${type.from}Holder in;
-@Output ${type.to}Holder out;
-
- public void setup() {
- }
+ @Param ${type.from}Holder in;
+ @Output ${type.to}Holder out;
- public void eval() {
+ public void setup() {
+ }
- <#if type.from == "VarDecimal">
- java.math.BigDecimal bigDecimal = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromDrillBuf(in.buffer, in.start, in.end - in.start, in.scale);
- <#elseif type.from == "Decimal28Dense" || type.from == "Decimal38Dense">
- java.math.BigDecimal bigDecimal = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromDense(in.buffer, in.start, in.nDecimalDigits, in.scale, in.maxPrecision, in.WIDTH);
- <#else>
- java.math.BigDecimal bigDecimal = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromDrillBuf(in.buffer, in.start, in.nDecimalDigits, in.scale, true);
- </#if>
- out.value = bigDecimal.${type.javatype}Value();
- }
+ public void eval() {
+ java.math.BigDecimal bigDecimal = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromDrillBuf(in.buffer, in.start, in.end - in.start, in.scale);
+ out.value = bigDecimal.${type.javatype}Value();
+ }
}
</#if>
</#list>
diff --git a/exec/java-exec/src/main/codegen/templates/Decimal/CastDecimalInt.java b/exec/java-exec/src/main/codegen/templates/Decimal/CastDecimalInt.java
index 3641818a9..e5123b237 100644
--- a/exec/java-exec/src/main/codegen/templates/Decimal/CastDecimalInt.java
+++ b/exec/java-exec/src/main/codegen/templates/Decimal/CastDecimalInt.java
@@ -19,17 +19,13 @@
<#list cast.types as type>
-
-<#if type.major == "DecimalSimpleInt" || type.major == "DecimalSimpleBigInt"> <#-- Cast function template for conversion from Decimal9, Decimal18 to Int and BigInt -->
-
+<#if type.major == "DecimalComplexInt" || type.major == "DecimalComplexBigInt"> <#-- Cast function template for conversion from VarDecimal to Int and BigInt -->
<@pp.changeOutputFile name="/org/apache/drill/exec/expr/fn/impl/gcast/Cast${type.from}${type.to}.java" />
<#include "/@includes/license.ftl" />
package org.apache.drill.exec.expr.fn.impl.gcast;
-<#include "/@includes/vv_imports.ftl" />
-
import org.apache.drill.exec.expr.DrillSimpleFunc;
import org.apache.drill.exec.expr.annotations.FunctionTemplate;
import org.apache.drill.exec.expr.annotations.FunctionTemplate.NullHandling;
@@ -45,86 +41,24 @@ import java.nio.ByteBuffer;
/*
* This class is generated using freemarker and the ${.template_name} template.
*/
+
@SuppressWarnings("unused")
@FunctionTemplate(name = "cast${type.to?upper_case}",
scope = FunctionTemplate.FunctionScope.SIMPLE,
nulls = NullHandling.NULL_IF_NULL)
public class Cast${type.from}${type.to} implements DrillSimpleFunc {
-@Param ${type.from}Holder in;
-@Output ${type.to}Holder out;
-
- public void setup() {
- }
-
- public void eval() {
-
- int carry = (org.apache.drill.exec.util.DecimalUtility.getFirstFractionalDigit(in.value, in.scale) > 4)
- ? (int) java.lang.Math.signum(in.value) : 0;
- // Assign the integer part of the decimal to the output holder
- out.value = (${type.javatype}) (org.apache.drill.exec.util.DecimalUtility.adjustScaleDivide(in.value, (int) in.scale) + carry);
- }
-}
-
-<#elseif type.major == "DecimalComplexInt" || type.major == "DecimalComplexBigInt"> <#-- Cast function template for conversion from Decimal28Sparse, Decimal38Sparse to Int and BigInt -->
-<@pp.changeOutputFile name="/org/apache/drill/exec/expr/fn/impl/gcast/Cast${type.from}${type.to}.java" />
-
-<#include "/@includes/license.ftl" />
-
-package org.apache.drill.exec.expr.fn.impl.gcast;
-
-import org.apache.drill.exec.expr.DrillSimpleFunc;
-import org.apache.drill.exec.expr.annotations.FunctionTemplate;
-import org.apache.drill.exec.expr.annotations.FunctionTemplate.NullHandling;
-import org.apache.drill.exec.expr.annotations.Output;
-import org.apache.drill.exec.expr.annotations.Param;
-import org.apache.drill.exec.expr.holders.*;
-import org.apache.drill.exec.record.RecordBatch;
-import org.apache.drill.exec.util.DecimalUtility;
-import org.apache.drill.exec.expr.annotations.Workspace;
-import io.netty.buffer.ByteBuf;
-import java.nio.ByteBuffer;
-
-/*
- * This class is generated using freemarker and the ${.template_name} template.
- */
-
-@SuppressWarnings("unused")
-@FunctionTemplate(name = "cast${type.to?upper_case}", scope = FunctionTemplate.FunctionScope.SIMPLE, nulls=NullHandling.NULL_IF_NULL)
-public class Cast${type.from}${type.to} implements DrillSimpleFunc {
-
-@Param ${type.from}Holder in;
-@Output ${type.to}Holder out;
-
- public void setup() {
- }
+ @Param ${type.from}Holder in;
+ @Output ${type.to}Holder out;
- public void eval() {
+ public void setup() {
+ }
-<#if type.from.contains("VarDecimal")>
- java.math.BigDecimal bd = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromDrillBuf(in.buffer, in.start, in.end - in.start, in.scale);
- bd.setScale(0, java.math.BigDecimal.ROUND_HALF_UP);
- long lval = bd.longValue(); // round off to nearest integer
- out.value = (${type.javatype}) lval;
-<#else>
- int carry = (org.apache.drill.exec.util.DecimalUtility.getFirstFractionalDigit(in.buffer, in.scale, in.start, in.nDecimalDigits) > 4) ? 1 : 0;
-
- // Get the index, where the integer part of the decimal ends
- int integerEndIndex = in.nDecimalDigits - org.apache.drill.exec.util.DecimalUtility.roundUp(in.scale);
-
- for (int i = 0 ; i < integerEndIndex; i++) {
- // We store values as base 1 billion integers, use this to compute the output (we don't care about overflows)
- out.value = (${type.javatype}) ((out.value * org.apache.drill.exec.util.DecimalUtility.DIGITS_BASE) + in.getInteger(i, in.start, in.buffer));
- }
-
- out.value += carry;
-
- if (in.getSign(in.start, in.buffer) == true) {
- out.value *= -1;
- }
-</#if>
- }
+ public void eval() {
+ java.math.BigDecimal bd = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromDrillBuf(in.buffer, in.start, in.end - in.start, in.scale);
+ long lval = bd.setScale(0, java.math.BigDecimal.ROUND_HALF_UP).longValue(); // round off to nearest integer
+ out.value = (${type.javatype}) lval;
+ }
}
-
</#if> <#-- type.major -->
</#list>
diff --git a/exec/java-exec/src/main/codegen/templates/Decimal/CastDecimalSparseDecimalDense.java b/exec/java-exec/src/main/codegen/templates/Decimal/CastDecimalSparseDecimalDense.java
deleted file mode 100644
index 69010efcc..000000000
--- a/exec/java-exec/src/main/codegen/templates/Decimal/CastDecimalSparseDecimalDense.java
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-<@pp.dropOutputFile />
-
-<#list cast.types as type>
-<#if type.major == "DecimalSparseDecimalDense">
-
-<@pp.changeOutputFile name="/org/apache/drill/exec/expr/fn/impl/gcast/Cast${type.from}${type.to}.java" />
-
-<#include "/@includes/license.ftl" />
-
-package org.apache.drill.exec.expr.fn.impl.gcast;
-
-<#include "/@includes/vv_imports.ftl" />
-
-import org.apache.drill.exec.expr.DrillSimpleFunc;
-import org.apache.drill.exec.expr.annotations.FunctionTemplate;
-import org.apache.drill.exec.expr.annotations.FunctionTemplate.NullHandling;
-import org.apache.drill.exec.expr.annotations.Output;
-import org.apache.drill.exec.expr.annotations.Param;
-import org.apache.drill.exec.expr.holders.*;
-import org.apache.drill.exec.record.RecordBatch;
-import org.apache.drill.exec.expr.annotations.Workspace;
-
-import io.netty.buffer.ByteBuf;
-import io.netty.buffer.DrillBuf;
-
-import java.nio.ByteBuffer;
-
-/*
- * This class is generated using freemarker and the ${.template_name} template.
- */
-
-@SuppressWarnings("unused")
-@FunctionTemplate(name = "cast${type.to?upper_case}",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_CAST,
- nulls = NullHandling.NULL_IF_NULL)
-public class Cast${type.from}${type.to} implements DrillSimpleFunc{
-
- @Param ${type.from}Holder in;
- @Inject DrillBuf buffer;
- @Param BigIntHolder precision;
- @Param BigIntHolder scale;
- @Output ${type.to}Holder out;
-
- public void setup() {
- int size = (${type.arraySize} * (org.apache.drill.exec.util.DecimalUtility.INTEGER_SIZE));
- buffer = buffer.reallocIfNeeded(size);
- }
-
- public void eval() {
-
- out.buffer = buffer;
- out.start = 0;
-
- // Re initialize the buffer everytime
- for (int i = 0; i < ${type.arraySize}; i++) {
- out.setInteger(i, 0, out.start, out.buffer);
- }
-
- out.scale = (int) scale.value;
- out.precision = (int) precision.value;
-
- /* Before converting from a sparse representation to a dense representation
- * we need to convert it to an intermediate representation. In the sparse
- * representation we separate out the scale and the integer part of the decimal
- * and pad the scale part with additional zeroes for ease of performing arithmetic
- * operations. In the intermediate representation we strip out the extra zeroes and
- * combine the scale and integer part.
- */
- int[] intermediate = new int[in.nDecimalDigits - 1];
-
- int index = in.nDecimalDigits - 1;
- int actualDigits;
-
- if (in.scale > 0 && (actualDigits = (in.scale % org.apache.drill.exec.util.DecimalUtility.MAX_DIGITS)) > 0) {
-
- int paddedDigits = org.apache.drill.exec.util.DecimalUtility.MAX_DIGITS - actualDigits;
-
- int paddedMask = (int) Math.pow(10, paddedDigits);
-
- /* We have a scale that does not completely occupy a decimal
- * digit, so we have padded zeroes to it for ease of arithmetic
- * Truncate the extra zeroes added and move the digits to the right
- */
- int temp = (in.getInteger(index, in.start, in.buffer)/paddedMask);
- index--;
-
- while(index >= 0) {
-
- int transferDigits = (in.getInteger(index, in.start, in.buffer) % (paddedMask));
-
- intermediate[index] = (int) (temp + (Math.pow(10, actualDigits) * transferDigits));
-
- temp = (in.getInteger(index, in.start, in.buffer)/(paddedMask));
-
- index--;
- }
- } else {
-
- /* If the scale does not exist or it perfectly fits within a decimal digit
- * then we have padded no zeroes, which means there can atmost be only 38 digits, which
- * need only 5 decimal digit to be stored, simply copy over the integers
- */
- for (int i = 1; i < in.nDecimalDigits; i++)
- intermediate[i - 1] = in.getInteger(i, in.start, in.buffer);
-
- }
-
- /* Now we have an intermediate representation in the array intermediate[]
- * Every number in the intermediate representation is base 1 billion number
- * To represent it we require only 30 bits, but every integer has 32 bits.
- * By shifting the bits around we can utilize the extra two bits on every
- * number and create a dense representation
- */
-
- /* Allocate a byte array */
- int size = (((intermediate.length - 1) * org.apache.drill.exec.util.DecimalUtility.INTEGER_SIZE) + 1);
- byte[] intermediateBytes = new byte[size];
- java.nio.ByteBuffer wrapper = java.nio.ByteBuffer.wrap(intermediateBytes);
-
- wrapper.put((byte) intermediate[0]);
-
- for (int i = 1; i < intermediate.length; i++) {
- wrapper.put(java.nio.ByteBuffer.allocate(org.apache.drill.exec.util.DecimalUtility.INTEGER_SIZE).putInt(intermediate[i]).array());
- }
-
- final int[] mask = {0x03, 0x0F, 0x3F, 0xFF};
- int maskIndex = 0;
- int shiftOrder = 2;
-
- // Start just after the last integer and shift bits to the right
- index = size - (org.apache.drill.exec.util.DecimalUtility.INTEGER_SIZE+ 1);
-
- while (index >= 0) {
-
- /* get the last bits that need to shifted to the next byte */
- byte shiftBits = (byte) ((intermediateBytes[index] & mask[maskIndex]) << (8 - shiftOrder));
-
- int shiftOrder1 = ((index % org.apache.drill.exec.util.DecimalUtility.INTEGER_SIZE) == 0) ? shiftOrder - 2 : shiftOrder;
-
- /* transfer the bits from the left to the right */
- intermediateBytes[index + 1] = (byte) (((intermediateBytes[index + 1] & 0xFF) >>> (shiftOrder1)) | shiftBits);
-
- index--;
-
- if ((index % org.apache.drill.exec.util.DecimalUtility.INTEGER_SIZE) == 0) {
- /* We are on a border */
- shiftOrder += 2;
- maskIndex++;
- }
- }
-
- <#if (type.from == "Decimal28Sparse") && (type.to == "Decimal38Dense")>
- /* Decimal38Dense representation has four bytes more than that needed to
- * represent Decimal28Dense. So our first four bytes are empty in that scenario
- */
- int dstIndex = 4;
- <#else>
- int dstIndex = 0;
- </#if>
-
- // Set the bytes in the buffer
- out.buffer.setBytes(dstIndex, intermediateBytes, 1, (size - 1));
- out.setSign(in.getSign(in.start, in.buffer), out.start, out.buffer);
- }
-}
-</#if>
-</#list> \ No newline at end of file
diff --git a/exec/java-exec/src/main/codegen/templates/Decimal/CastDecimalSparseVarDecimal.java b/exec/java-exec/src/main/codegen/templates/Decimal/CastDecimalVarDecimal.java
index ae068c377..aeffe5a87 100644
--- a/exec/java-exec/src/main/codegen/templates/Decimal/CastDecimalSparseVarDecimal.java
+++ b/exec/java-exec/src/main/codegen/templates/Decimal/CastDecimalVarDecimal.java
@@ -18,7 +18,7 @@
<@pp.dropOutputFile />
<#list cast.types as type>
-<#if type.major == "DecimalSparseVarDecimal">
+<#if type.major == "DecimalToVarDecimal">
<@pp.changeOutputFile name="/org/apache/drill/exec/expr/fn/impl/gcast/Cast${type.from}${type.to}.java" />
@@ -45,34 +45,45 @@ import java.nio.ByteBuffer;
/*
* This class is generated using freemarker and the ${.template_name} template.
*/
-
@SuppressWarnings("unused")
@FunctionTemplate(name = "cast${type.to?upper_case}",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_CAST,
- nulls = NullHandling.NULL_IF_NULL)
-public class Cast${type.from}${type.to} implements DrillSimpleFunc{
+ scope = FunctionTemplate.FunctionScope.SIMPLE,
+ returnType = FunctionTemplate.ReturnType.DECIMAL_CAST,
+ nulls = NullHandling.NULL_IF_NULL)
+public class Cast${type.from}${type.to} implements DrillSimpleFunc {
- @Param ${type.from}Holder in;
- @Inject DrillBuf buffer;
- @Param BigIntHolder precision;
- @Param BigIntHolder scale;
- @Output ${type.to}Holder out;
+ @Param ${type.from}Holder in;
+ @Inject DrillBuf buffer;
+ @Param IntHolder precision;
+ @Param IntHolder scale;
+ @Output ${type.to}Holder out;
- public void setup() {
- // VarDecimal size in bytes is determined once the input BigDecimal is known
- }
+ public void setup() {
+ }
- public void eval() {
- java.math.BigDecimal bd = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromDrillBuf(in.buffer, in.start, in.nDecimalDigits, in.scale, true);
- out.scale = (int) scale.value;
- int len = bd.unscaledValue().toByteArray().length;
- buffer = buffer.reallocIfNeeded(len);
- out.start = 0;
- out.buffer = buffer;
- org.apache.drill.exec.util.DecimalUtility.getVarDecimalFromBigDecimal(bd, out.buffer, out.start);
- out.end = out.start + len;
- }
+ public void eval() {
+ java.math.BigDecimal bd =
+ <#if type.from == "Decimal9" || type.from == "Decimal18">
+ java.math.BigDecimal.valueOf(in.value)
+ <#else>
+ org.apache.drill.exec.util.DecimalUtility
+ <#if type.from.contains("Sparse")>
+ .getBigDecimalFromDrillBuf(in.buffer, in.start, in.nDecimalDigits, in.scale, true)
+ <#elseif type.from == "VarDecimal">
+ .getBigDecimalFromDrillBuf(in.buffer, in.start, in.end - in.start, in.scale)
+ </#if>
+ </#if>
+ .setScale(scale.value, java.math.RoundingMode.HALF_UP)
+ .round(new java.math.MathContext(precision.value, java.math.RoundingMode.HALF_UP));
+ out.scale = scale.value;
+ out.precision = precision.value;
+ out.start = 0;
+ byte[] bytes = bd.unscaledValue().toByteArray();
+ int len = bytes.length;
+ out.buffer = buffer.reallocIfNeeded(len);
+ out.buffer.setBytes(out.start, bytes);
+ out.end = out.start + len;
+ }
}
</#if>
</#list>
diff --git a/exec/java-exec/src/main/codegen/templates/Decimal/CastDecimalVarchar.java b/exec/java-exec/src/main/codegen/templates/Decimal/CastDecimalVarchar.java
index c4ac6d7cf..369ba0204 100644
--- a/exec/java-exec/src/main/codegen/templates/Decimal/CastDecimalVarchar.java
+++ b/exec/java-exec/src/main/codegen/templates/Decimal/CastDecimalVarchar.java
@@ -20,7 +20,7 @@
<#list cast.types as type>
-<#if type.major == "DecimalSimpleVarChar"> <#-- Cast function template for conversion from Decimal9, Decimal18 to VarChar -->
+<#if type.major == "DecimalComplexVarChar"> <#-- Cast function template for conversion from VarDecimal to VarChar -->
<@pp.changeOutputFile name="/org/apache/drill/exec/expr/fn/impl/gcast/Cast${type.from}${type.to}.java" />
@@ -41,8 +41,6 @@ import org.apache.drill.exec.util.DecimalUtility;
import org.apache.drill.exec.expr.annotations.Workspace;
import io.netty.buffer.ByteBuf;
-import io.netty.buffer.DrillBuf;
-import io.netty.buffer.SwappedByteBuf;
import java.nio.ByteBuffer;
@@ -56,188 +54,23 @@ import java.nio.ByteBuffer;
returnType = FunctionTemplate.ReturnType.STRING_CAST,
nulls = NullHandling.NULL_IF_NULL)
public class Cast${type.from}${type.to} implements DrillSimpleFunc {
-
- @Param ${type.from}Holder in;
- @Param BigIntHolder len;
- @Inject DrillBuf buffer;
- @Output ${type.to}Holder out;
-
- public void setup() {
- buffer = buffer.reallocIfNeeded(${type.bufferSize});
- }
-
- public void eval() {
-
- StringBuilder str = new StringBuilder();
-
- ${type.javatype} value = in.value;
- if (value < 0) {
- // Negative value, add '-' to the string
- str.append("-");
-
- // Negate the number
- value *= -1;
- }
-
- ${type.javatype} separator = (${type.javatype}) org.apache.drill.exec.util.DecimalUtility.getPowerOfTen((int) in.scale);
-
- str.append(value / separator);
-
- if (in.scale > 0) {
- str.append(".");
-
- String fractionalPart = String.valueOf(value % separator);
-
- /* Since we are taking modulus to find fractional part,
- * we will miss printing the leading zeroes in the fractional part
- * Account for those zeroes
- *
- * Eg: 1.0002
- * Scale: 3
- *
- * Stored as: 10002
- *
- * We print integer part by 10002/1000 = 1
- * We print fractional part by 10002 % 1000 = 2
- *
- * We missed the initial zeroes in the fractional part. Below logic accounts for this case
- */
- str.append(org.apache.drill.exec.util.DecimalUtility.toStringWithZeroes((value % separator), in.scale));
- }
-
- out.buffer = buffer;
- out.start = 0;
- out.end = Math.min((int)len.value, str.length()); // truncate if target type has length smaller than that of input's string
- out.buffer.setBytes(0, String.valueOf(str.substring(0,out.end)).getBytes());
- }
-}
-<#elseif type.major == "DecimalComplexVarChar"> <#-- Cast function template for conversion from Decimal28Sparse, Decimal38Sparse to VarChar -->
-
-<@pp.changeOutputFile name="/org/apache/drill/exec/expr/fn/impl/gcast/Cast${type.from}${type.to}.java" />
-
-<#include "/@includes/license.ftl" />
-
-package org.apache.drill.exec.expr.fn.impl.gcast;
-
-<#include "/@includes/vv_imports.ftl" />
-
-import org.apache.drill.exec.expr.DrillSimpleFunc;
-import org.apache.drill.exec.expr.annotations.FunctionTemplate;
-import org.apache.drill.exec.expr.annotations.FunctionTemplate.NullHandling;
-import org.apache.drill.exec.expr.annotations.Output;
-import org.apache.drill.exec.expr.annotations.Param;
-import org.apache.drill.exec.expr.holders.*;
-import org.apache.drill.exec.record.RecordBatch;
-import org.apache.drill.exec.util.DecimalUtility;
-import org.apache.drill.exec.expr.annotations.Workspace;
-
-import io.netty.buffer.ByteBuf;
-
-import java.nio.ByteBuffer;
-
-/*
- * This class is generated using freemarker and the ${.template_name} template.
- */
-
-@SuppressWarnings("unused")
-@FunctionTemplate(name = "cast${type.to?upper_case}",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.STRING_CAST,
- nulls = NullHandling.NULL_IF_NULL)
-public class Cast${type.from}${type.to} implements DrillSimpleFunc {
-
- @Param ${type.from}Holder in;
- @Param BigIntHolder len;
- @Inject DrillBuf buffer;
- @Output ${type.to}Holder out;
-
- public void setup() {
- buffer = buffer.reallocIfNeeded((int) len.value);
- }
-
- public void eval() {
-
-<#if type.from.contains("VarDecimal")>
- java.math.BigDecimal bigDecimal = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromDrillBuf(in.buffer, in.start, in.end - in.start, in.scale);
- String str = bigDecimal.toString();
- out.buffer = buffer;
- out.start = 0;
- out.end = Math.min((int)len.value, str.length());
- out.buffer.setBytes(0, String.valueOf(str.substring(0, out.end)).getBytes());
-<#else>
- StringBuilder str = new StringBuilder();
- int index = 0;
- int fractionalStartIndex = ${type.arraySize} - org.apache.drill.exec.util.DecimalUtility.roundUp(in.scale);
-
- // Find the first non-zero value in the integer part of the decimal
- while (index < fractionalStartIndex && in.getInteger(index, in.start, in.buffer) == 0) {
- index++;
- }
-
-
- // If we have valid digits print '-' sign
- if ((in.getSign(in.start, in.buffer) == true) && index < ${type.arraySize}) {
- str.append("-");
- }
-
- // If all the integer digits are zero, print a single zero
- if (index == fractionalStartIndex) {
- str.append("0");
- }
-
- boolean fillZeroes = false;
-
- // convert the integer part
- while (index < fractionalStartIndex) {
- int value = in.getInteger(index++, in.start, in.buffer);
-
- if (fillZeroes == true) {
- str.append(org.apache.drill.exec.util.DecimalUtility.toStringWithZeroes(value, org.apache.drill.exec.util.DecimalUtility.MAX_DIGITS));
- } else {
- str.append(value);
- fillZeroes = true;
- }
- //str.append(value);
- }
-
- if (fractionalStartIndex < ${type.arraySize}) {
- // We have fractional part, print '.'
- str.append(".");
-
- /* convert the fractional part (except the last decimal digit,
- * as it might have padding that needs to be stripped
- */
- while (fractionalStartIndex < ${type.arraySize} - 1) {
- int value = in.getInteger(fractionalStartIndex++, in.start, in.buffer);
-
- // Fill zeroes at the beginning of the decimal digit
- str.append(org.apache.drill.exec.util.DecimalUtility.toStringWithZeroes(value, org.apache.drill.exec.util.DecimalUtility.MAX_DIGITS));
- }
-
- // Last decimal digit, strip the extra zeroes we may have padded
- int actualDigits = in.scale % org.apache.drill.exec.util.DecimalUtility.MAX_DIGITS;
-
- int lastFractionalDigit = in.getInteger(${type.arraySize} - 1, in.start, in.buffer);
-
- if (actualDigits != 0) {
-
- // Strip padded zeroes at the end that is not part of the scale
- lastFractionalDigit /= (int) (org.apache.drill.exec.util.DecimalUtility.getPowerOfTen((int) (org.apache.drill.exec.util.DecimalUtility.MAX_DIGITS - actualDigits)));
- str.append(org.apache.drill.exec.util.DecimalUtility.toStringWithZeroes(lastFractionalDigit, actualDigits));
- } else {
- // Last digit does not have any padding print as is
- str.append(org.apache.drill.exec.util.DecimalUtility.toStringWithZeroes(lastFractionalDigit, org.apache.drill.exec.util.DecimalUtility.MAX_DIGITS));
- }
-
-
- }
-
- out.buffer = buffer;
- out.start = 0;
- out.end = Math.min((int)len.value, str.length()); // truncate if target type has length smaller than that of input's string
- out.buffer.setBytes(0, String.valueOf(str.substring(0,out.end)).getBytes());
-</#if>
- }
+ @Param ${type.from}Holder in;
+ @Param BigIntHolder len;
+ @Inject DrillBuf buffer;
+ @Output ${type.to}Holder out;
+
+ public void setup() {
+ }
+
+ public void eval() {
+ java.math.BigDecimal bigDecimal = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromDrillBuf(in.buffer, in.start, in.end - in.start, in.scale);
+ String str = bigDecimal.toString();
+ out.buffer = buffer;
+ out.start = 0;
+ out.end = Math.min((int) len.value, str.length());
+ buffer = buffer.reallocIfNeeded((int) out.end);
+ out.buffer.setBytes(0, str.substring(0, out.end).getBytes());
+ }
}
</#if> <#-- type.major -->
</#list>
diff --git a/exec/java-exec/src/main/codegen/templates/Decimal/CastDownwardDecimal.java b/exec/java-exec/src/main/codegen/templates/Decimal/CastDownwardDecimal.java
deleted file mode 100644
index a1ed7c8d7..000000000
--- a/exec/java-exec/src/main/codegen/templates/Decimal/CastDownwardDecimal.java
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-<@pp.dropOutputFile />
-
-<#list cast.types as type>
-
-<#if type.major == "DownwardDecimalSimpleDecimalSimple"> <#-- Cast function template for conversion from Decimal18, Decimal9 -->
-<@pp.changeOutputFile name="/org/apache/drill/exec/expr/fn/impl/gcast/Cast${type.from}${type.to}.java" />
-
-<#include "/@includes/license.ftl" />
-
-package org.apache.drill.exec.expr.fn.impl.gcast;
-
-<#include "/@includes/vv_imports.ftl" />
-
-import org.apache.drill.exec.expr.DrillSimpleFunc;
-import org.apache.drill.exec.expr.annotations.FunctionTemplate;
-import org.apache.drill.exec.expr.annotations.FunctionTemplate.NullHandling;
-import org.apache.drill.exec.expr.annotations.Output;
-import org.apache.drill.exec.expr.annotations.Param;
-import org.apache.drill.exec.expr.holders.*;
-import org.apache.drill.exec.record.RecordBatch;
-import org.apache.drill.exec.util.DecimalUtility;
-import org.apache.drill.exec.expr.annotations.Workspace;
-
-import io.netty.buffer.ByteBuf;
-import io.netty.buffer.DrillBuf;
-
-import java.nio.ByteBuffer;
-
-/*
- * This class is generated using freemarker and the ${.template_name} template.
- */
-
-@SuppressWarnings("unused")
-@FunctionTemplate(name = "cast${type.to?upper_case}",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_CAST,
- nulls = NullHandling.NULL_IF_NULL)
-public class Cast${type.from}${type.to} implements DrillSimpleFunc {
-
- @Param ${type.from}Holder in;
- @Param BigIntHolder precision;
- @Param BigIntHolder scale;
- @Output ${type.to}Holder out;
-
- public void setup() {
- }
-
- public void eval() {
- out.scale = (int) scale.value;
- out.precision = (int) precision.value;
- out.value = (int) in.value;
- // Check if we need to truncate or round up
- if (out.scale > in.scale) {
- out.value *= (int) org.apache.drill.exec.util.DecimalUtility.getPowerOfTen(out.scale - in.scale);
- } else if (out.scale < in.scale) {
- // need to round up since we are truncating fractional part
- int scaleFactor = (int) (org.apache.drill.exec.util.DecimalUtility.getPowerOfTen((int) in.scale));
- int newScaleFactor = (int) (org.apache.drill.exec.util.DecimalUtility.getPowerOfTen((int) scale.value));
- int truncScaleFactor = (int) (org.apache.drill.exec.util.DecimalUtility.getPowerOfTen( (int) (Math.abs(in.scale - scale.value))));
- int truncFactor = (int) (in.scale - scale.value);
-
- // Assign the integer part
- out.value = (int) (in.value / scaleFactor);
-
- // Get the fractional part
- int fractionalPart = (int) (in.value % scaleFactor);
-
- // From the entire fractional part extract the digits upto which rounding is needed
- int newFractionalPart = (int) (org.apache.drill.exec.util.DecimalUtility.adjustScaleDivide(fractionalPart, truncFactor));
- int truncatedFraction = fractionalPart % truncScaleFactor;
-
- // Get the truncated fractional part and extract the first digit to see if we need to add 1
- int digit = Math.abs((int) org.apache.drill.exec.util.DecimalUtility.adjustScaleDivide(truncatedFraction, truncFactor - 1));
-
- if (digit > 4) {
- if (in.value > 0) {
- newFractionalPart++;
- } else if (in.value < 0) {
- newFractionalPart--;
- }
- }
- out.value = (int) ((out.value * newScaleFactor) + newFractionalPart);
- }
- }
-}
-<#elseif type.major == "DownwardDecimalComplexDecimalSimple"> <#-- Cast function template for conversion from Decimal28/Decimal9 to Decimal18/Decimal9 -->
-<@pp.changeOutputFile name="/org/apache/drill/exec/expr/fn/impl/gcast/Cast${type.from}${type.to}.java" />
-
-<#include "/@includes/license.ftl" />
-
-package org.apache.drill.exec.expr.fn.impl.gcast;
-
-<#include "/@includes/vv_imports.ftl" />
-
-import org.apache.drill.exec.expr.DrillSimpleFunc;
-import org.apache.drill.exec.expr.annotations.FunctionTemplate;
-import org.apache.drill.exec.expr.annotations.FunctionTemplate.NullHandling;
-import org.apache.drill.exec.expr.annotations.Output;
-import org.apache.drill.exec.expr.annotations.Param;
-import org.apache.drill.exec.expr.holders.*;
-import org.apache.drill.exec.record.RecordBatch;
-import org.apache.drill.exec.util.DecimalUtility;
-import org.apache.drill.exec.expr.annotations.Workspace;
-
-import io.netty.buffer.ByteBuf;
-
-import java.nio.ByteBuffer;
-
-/*
- * This class is generated using freemarker and the ${.template_name} template.
- */
-
-@SuppressWarnings("unused")
-@FunctionTemplate(name = "cast${type.to?upper_case}",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_CAST,
- nulls = NullHandling.NULL_IF_NULL)
-public class Cast${type.from}${type.to} implements DrillSimpleFunc {
-
- @Param ${type.from}Holder in;
- @Param BigIntHolder precision;
- @Param BigIntHolder scale;
- @Output ${type.to}Holder out;
-
- public void setup() {
- }
-
- public void eval() {
- java.math.BigDecimal temp = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromSparse(in.buffer, in.start, in.nDecimalDigits, in.scale);
- temp = temp.setScale((int) scale.value, java.math.BigDecimal.ROUND_HALF_UP);
- out.value = temp.unscaledValue().${type.javatype}Value();
- out.precision = (int) precision.value;
- out.scale = (int) scale.value;
- }
-}
-<#elseif type.major == "DownwardDecimalComplexDecimalComplex"> <#-- Cast function template for conversion from Decimal28/Decimal9 to Decimal18/Decimal9 -->
-<@pp.changeOutputFile name="/org/apache/drill/exec/expr/fn/impl/gcast/Cast${type.from}${type.to}.java" />
-
-<#include "/@includes/license.ftl" />
-
-package org.apache.drill.exec.expr.fn.impl.gcast;
-
-<#include "/@includes/vv_imports.ftl" />
-
-import org.apache.drill.exec.expr.DrillSimpleFunc;
-import org.apache.drill.exec.expr.annotations.FunctionTemplate;
-import org.apache.drill.exec.expr.annotations.FunctionTemplate.NullHandling;
-import org.apache.drill.exec.expr.annotations.Output;
-import org.apache.drill.exec.expr.annotations.Param;
-import org.apache.drill.exec.expr.holders.*;
-import org.apache.drill.exec.record.RecordBatch;
-import org.apache.drill.exec.util.DecimalUtility;
-import org.apache.drill.exec.expr.annotations.Workspace;
-
-import io.netty.buffer.ByteBuf;
-
-import java.nio.ByteBuffer;
-
-/*
- * This class is generated using freemarker and the ${.template_name} template.
- */
-
-@SuppressWarnings("unused")
-@FunctionTemplate(name = "cast${type.to?upper_case}",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_CAST,
- nulls = NullHandling.NULL_IF_NULL)
-public class Cast${type.from}${type.to} implements DrillSimpleFunc {
-
- @Param ${type.from}Holder in;
- @Param BigIntHolder precision;
- @Param BigIntHolder scale;
- @Inject DrillBuf buffer;
- @Output ${type.to}Holder out;
-
- public void setup() {
- int size = (${type.arraySize} * (org.apache.drill.exec.util.DecimalUtility.INTEGER_SIZE));
- buffer = buffer.reallocIfNeeded(size);
- }
-
- public void eval() {
- java.math.BigDecimal temp = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromSparse(in.buffer, in.start, in.nDecimalDigits, in.scale);
- temp = temp.setScale((int) scale.value, java.math.BigDecimal.ROUND_HALF_UP);
- out.precision = (int) precision.value;
- out.scale = (int) scale.value;
- out.buffer = buffer;
- out.start = 0;
- org.apache.drill.exec.util.DecimalUtility.getSparseFromBigDecimal(temp, out.buffer, out.start, out.scale, out.precision, out.nDecimalDigits);
- }
-}
-</#if> <#-- type.major -->
-</#list> \ No newline at end of file
diff --git a/exec/java-exec/src/main/codegen/templates/Decimal/CastFloatDecimal.java b/exec/java-exec/src/main/codegen/templates/Decimal/CastFloatDecimal.java
index ba8f6510e..f051310d2 100644
--- a/exec/java-exec/src/main/codegen/templates/Decimal/CastFloatDecimal.java
+++ b/exec/java-exec/src/main/codegen/templates/Decimal/CastFloatDecimal.java
@@ -20,8 +20,8 @@
<#list cast.types as type>
-<#-- Cast function template for conversion from Float to Decimal9, Decimal18, Decimal28, Decimal38 -->
-<#if type.major == "FloatDecimalComplex" || type.major == "DoubleDecimalComplex" || type.major == "FloatDecimalSimple" || type.major == "DoubleDecimalSimple">
+<#-- Cast function template for conversion from Float to VarDecimal -->
+<#if type.major == "FloatDecimalComplex" || type.major == "DoubleDecimalComplex">
<@pp.changeOutputFile name="/org/apache/drill/exec/expr/fn/impl/gcast/Cast${type.from}${type.to}.java" />
@@ -52,59 +52,38 @@ import java.nio.ByteBuffer;
@SuppressWarnings("unused")
@FunctionTemplate(name = "cast${type.to?upper_case}",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_CAST,
- nulls = NullHandling.NULL_IF_NULL)
+ scope = FunctionTemplate.FunctionScope.SIMPLE,
+ returnType = FunctionTemplate.ReturnType.DECIMAL_CAST,
+ nulls = NullHandling.NULL_IF_NULL)
public class Cast${type.from}${type.to} implements DrillSimpleFunc {
-
-@Param ${type.from}Holder in;
-<#if type.major == "FloatDecimalComplex" || type.major == "DoubleDecimalComplex">
-@Inject DrillBuf buffer;
-</#if>
-@Param BigIntHolder precision;
-@Param BigIntHolder scale;
-@Output ${type.to}Holder out;
-
- public void setup() {
- <#if type.major == "FloatDecimalComplex" || type.major == "DoubleDecimalComplex">
- int size = ${type.arraySize} * (org.apache.drill.exec.util.DecimalUtility.INTEGER_SIZE);
- buffer = buffer.reallocIfNeeded(size);
- </#if>
- }
-
- public void eval() {
-
- out.scale = (int) scale.value;
-
- <#if !type.to.endsWith("VarDecimal")>
- out.precision = (int) precision.value;
- </#if>
-
- <#if type.to.endsWith("VarDecimal")>
- // TODO: the entire set of logic, above, appears to be using BigDecimal constructors completely wrong!!!!
- // for the time being, this new logic is added for VarDecimal only.
- double d = in.value;
- for (int i = 0; i < out.scale; ++i) { // loop to compute unscaled value
- d *= 10.0;
- }
- long lval = (long)(d >= 0.0 ? d + 0.5 : d - 0.5); // round off unscaled integer, from float8 to nearest integer
- java.math.BigInteger bi = new java.math.BigInteger(Long.toString(lval));
- java.math.BigDecimal bd = new java.math.BigDecimal(bi, out.scale);
- int len = org.apache.drill.exec.util.DecimalUtility.getVarDecimalFromBigDecimal(bd, out.buffer, out.start);
- out.end = out.start + len;
- <#elseif type.major == "FloatDecimalComplex" || type.major == "DoubleDecimalComplex">
- out.start = 0;
- out.buffer = buffer;
-
- // Assign the integer part of the decimal to the output holder
- org.apache.drill.exec.util.DecimalUtility.getSparseFromBigDecimal(new java.math.BigDecimal(String.valueOf(in.value)), out.buffer, out.start, out.scale, out.precision, out.nDecimalDigits);
-
- <#elseif type.to.endsWith("Decimal9")>
- out.value = org.apache.drill.exec.util.DecimalUtility.getDecimal9FromBigDecimal(new java.math.BigDecimal(String.valueOf(in.value)), out.scale, out.precision);
- <#elseif type.to.endsWith("Decimal18")>
- out.value = org.apache.drill.exec.util.DecimalUtility.getDecimal18FromBigDecimal(new java.math.BigDecimal(String.valueOf(in.value)), out.scale, out.precision);
- </#if>
- }
+ @Param ${type.from}Holder in;
+ @Inject DrillBuf buffer;
+ @Param IntHolder precision;
+ @Param IntHolder scale;
+ @Output ${type.to}Holder out;
+
+ public void setup() {
+ }
+
+ public void eval() {
+ out.scale = scale.value;
+ out.precision = precision.value;
+
+ out.start = 0;
+ java.math.BigDecimal bd =
+ new java.math.BigDecimal(
+ String.valueOf(in.value),
+ new java.math.MathContext(
+ precision.value,
+ java.math.RoundingMode.HALF_UP))
+ .setScale(scale.value, java.math.RoundingMode.HALF_UP);
+
+ byte[] bytes = bd.unscaledValue().toByteArray();
+ int len = bytes.length;
+ out.buffer = buffer.reallocIfNeeded(len);
+ out.buffer.setBytes(out.start, bytes);
+ out.end = out.start + len;
+ }
}
</#if>
</#list>
diff --git a/exec/java-exec/src/main/codegen/templates/Decimal/CastIntDecimal.java b/exec/java-exec/src/main/codegen/templates/Decimal/CastIntDecimal.java
index 15304daf5..162c5629e 100644
--- a/exec/java-exec/src/main/codegen/templates/Decimal/CastIntDecimal.java
+++ b/exec/java-exec/src/main/codegen/templates/Decimal/CastIntDecimal.java
@@ -48,79 +48,35 @@ import java.nio.ByteBuffer;
@SuppressWarnings("unused")
@FunctionTemplate(name = "cast${type.to?upper_case}",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_CAST,
- nulls = NullHandling.NULL_IF_NULL)
+ scope = FunctionTemplate.FunctionScope.SIMPLE,
+ returnType = FunctionTemplate.ReturnType.DECIMAL_CAST,
+ nulls = NullHandling.NULL_IF_NULL)
public class Cast${type.from}${type.to} implements DrillSimpleFunc {
-
- @Param ${type.from}Holder in;
- <#if type.to.startsWith("Decimal28") || type.to.startsWith("Decimal38") || type.to.endsWith("VarDecimal")>
- @Inject DrillBuf buffer;
- </#if>
- @Param BigIntHolder precision;
- @Param BigIntHolder scale;
- @Output ${type.to}Holder out;
-
- public void setup() {
- <#if type.to.startsWith("Decimal28") || type.to.startsWith("Decimal38")>
- int size = ${type.arraySize} * (org.apache.drill.exec.util.DecimalUtility.INTEGER_SIZE);
- buffer = buffer.reallocIfNeeded(size);
- </#if>
-
- }
-
- public void eval() {
- out.scale = (int) scale.value;
-
- <#if !type.to.endsWith("VarDecimal")>
- out.precision = (int) precision.value;
- </#if>
-
- <#if type.to.endsWith("VarDecimal")>
- out.start = 0;
- out.buffer = buffer;
- StringBuilder sb = new StringBuilder();
- sb.append(Long.toString((long)in.value));
- for (int i = 0; i < out.scale; ++i) { // add 0's to get unscaled integer
- sb.append("0");
- }
- java.math.BigInteger bi = new java.math.BigInteger(sb.toString());
- java.math.BigDecimal bd = new java.math.BigDecimal(bi, out.scale);
- int len = org.apache.drill.exec.util.DecimalUtility.getVarDecimalFromBigDecimal(bd, out.buffer, out.start);
- out.end = out.start + len;
- <#elseif type.to == "Decimal9" || type.to == "Decimal18">
- out.value = (${type.javatype}) in.value;
-
- // converting from integer to decimal, pad zeroes if scale is non zero
- out.value = (${type.javatype}) org.apache.drill.exec.util.DecimalUtility.adjustScaleMultiply(out.value, (int) scale.value);
-
- <#else>
-
- out.start = 0;
- out.buffer = buffer;
-
- // Initialize the buffer
- for (int i = 0; i < ${type.arraySize}; i++) {
- out.setInteger(i, 0, out.start, out.buffer);
- }
-
- // check if input is a negative number and store the sign
- if (in.value < 0) {
- out.setSign(true, out.start, out.buffer);
- }
-
- // Figure out how many array positions to be left for the scale part
- int scaleSize = org.apache.drill.exec.util.DecimalUtility.roundUp((int) scale.value);
- int integerIndex = (${type.arraySize} - scaleSize - 1);
-
- long inValue = in.value;
- while (inValue != 0 && integerIndex >= 0) {
- out.setInteger(integerIndex--, (int) Math.abs((inValue % org.apache.drill.exec.util.DecimalUtility.DIGITS_BASE)), out.start, out.buffer);
- inValue = inValue / org.apache.drill.exec.util.DecimalUtility.DIGITS_BASE;
- }
-
- </#if>
- }
+ @Param ${type.from}Holder in;
+ @Inject DrillBuf buffer;
+ @Param IntHolder precision;
+ @Param IntHolder scale;
+ @Output ${type.to}Holder out;
+
+ public void setup() {
+ }
+
+ public void eval() {
+ out.scale = scale.value;
+ out.precision = precision.value;
+
+ out.start = 0;
+ out.buffer = buffer;
+ java.math.BigDecimal bd = new java.math.BigDecimal(in.value,
+ new java.math.MathContext(precision.value, java.math.RoundingMode.HALF_UP))
+ .setScale(out.scale, java.math.BigDecimal.ROUND_DOWN);
+
+ byte[] bytes = bd.unscaledValue().toByteArray();
+ int len = bytes.length;
+ out.buffer = out.buffer.reallocIfNeeded(len);
+ out.buffer.setBytes(out.start, bytes);
+ out.end = out.start + len;
+ }
}
</#if> <#-- type.major -->
</#list>
diff --git a/exec/java-exec/src/main/codegen/templates/Decimal/CastSrcDecimalSimple.java b/exec/java-exec/src/main/codegen/templates/Decimal/CastSrcDecimalSimple.java
deleted file mode 100644
index 541b40a3e..000000000
--- a/exec/java-exec/src/main/codegen/templates/Decimal/CastSrcDecimalSimple.java
+++ /dev/null
@@ -1,294 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-<@pp.dropOutputFile />
-
-<#list cast.types as type>
-
-<#-- Template code for converting from Decimal9, Decimal18 to Decimal28Dense and Decimal38Dense -->
-<#if type.major == "DecimalSimpleDecimalDense">
-
-<@pp.changeOutputFile name="/org/apache/drill/exec/expr/fn/impl/gcast/Cast${type.from}${type.to}.java" />
-
-<#include "/@includes/license.ftl" />
-
-package org.apache.drill.exec.expr.fn.impl.gcast;
-
-<#include "/@includes/vv_imports.ftl" />
-
-import org.apache.drill.exec.expr.DrillSimpleFunc;
-import org.apache.drill.exec.expr.annotations.FunctionTemplate;
-import org.apache.drill.exec.expr.annotations.FunctionTemplate.NullHandling;
-import org.apache.drill.exec.expr.annotations.Output;
-import org.apache.drill.exec.expr.annotations.Param;
-import org.apache.drill.exec.expr.holders.*;
-import org.apache.drill.exec.record.RecordBatch;
-import org.apache.drill.exec.expr.annotations.Workspace;
-
-import io.netty.buffer.ByteBuf;
-import io.netty.buffer.DrillBuf;
-
-import java.nio.ByteBuffer;
-
-/*
- * This class is generated using freemarker and the ${.template_name} template.
- */
-
-@SuppressWarnings("unused")
-@FunctionTemplate(name = "cast${type.to?upper_case}",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_CAST,
- nulls = NullHandling.NULL_IF_NULL)
-public class Cast${type.from}${type.to} implements DrillSimpleFunc {
-
- @Param ${type.from}Holder in;
- <#if type.to.startsWith("Decimal28") || type.to.startsWith("Decimal38")>
- @Inject DrillBuf buffer;
- </#if>
- @Param BigIntHolder precision;
- @Param BigIntHolder scale;
- @Output ${type.to}Holder out;
-
- public void setup() {
- int size = (${type.arraySize} * (org.apache.drill.exec.util.DecimalUtility.INTEGER_SIZE));
- buffer = buffer.reallocIfNeeded(size);
- }
-
- public void eval() {
-
- out.buffer = buffer;
- out.start = 0;
-
- // Re initialize the buffer everytime
- for (int i = 0; i < ${type.arraySize}; i++) {
- out.setInteger(i, 0, out.start, out.buffer);
- }
-
- out.scale = (int) scale.value;
- out.precision = (int) precision.value;
-
- out.buffer = buffer;
- out.start = 0;
- out.setSign((in.value < 0), out.start, out.buffer);
-
- /* Since we will be dividing the decimal value with base 1 billion
- * we don't want negative results if the decimal is negative.
- */
- long value = (in.value < 0) ? (in.value * -1) : in.value;
-
- int index = out.nDecimalDigits - 1;
-
- // store the decimal value as sequence of integers of base 1 billion.
- while (value > 0) {
-
- out.setInteger(index, (int) (value % org.apache.drill.exec.util.DecimalUtility.DIGITS_BASE), out.start, out.buffer);
- value = value/org.apache.drill.exec.util.DecimalUtility.DIGITS_BASE;
- index--;
- }
-
- /* We have stored the decimal value in the intermediate format, which is basically that the
- * scale and integer part of the decimal together, with no additional zeroes padded to the
- * scale. Now we simply need to shift the bits around to get a more compact representation
- */
- int[] mask = {0x03, 0x0F, 0x3F, 0xFF};
- int maskIndex = 0;
- int shiftOrder = 2;
-
- // Start shifting bits just after the first integer
- int byteIndex = in.WIDTH - (org.apache.drill.exec.util.DecimalUtility.INTEGER_SIZE + 1);
-
- while (byteIndex >= 0) {
-
- /* get the last bits that need to shifted to the next byte */
- byte shiftBits = (byte) ((out.buffer.getByte(byteIndex) & mask[maskIndex]) << (8 - shiftOrder));
-
- int shiftOrder1 = ((byteIndex % 4) == 0) ? shiftOrder - 2 : shiftOrder;
-
- /* transfer the bits from the left to the right */
- out.buffer.setByte(byteIndex + 1, (byte) (((out.buffer.getByte(byteIndex + 1) & 0xFF) >>> (shiftOrder1)) | shiftBits));
-
- byteIndex--;
-
- if (byteIndex % 4 == 0) {
- /* We are on a border */
- shiftOrder += 2;
- maskIndex++;
- }
- }
- }
-}
-
-<#-- Template code for converting from Decimal9, Decimal18 to Decimal28Sparse and Decimal38Sparse -->
-<#elseif type.major == "DecimalSimpleDecimalSparse">
-<@pp.changeOutputFile name="/org/apache/drill/exec/expr/fn/impl/gcast/Cast${type.from}${type.to}.java" />
-
-<#include "/@includes/license.ftl" />
-
-package org.apache.drill.exec.expr.fn.impl.gcast;
-
-<#include "/@includes/vv_imports.ftl" />
-
-import org.apache.drill.exec.expr.DrillSimpleFunc;
-import org.apache.drill.exec.expr.annotations.FunctionTemplate;
-import org.apache.drill.exec.expr.annotations.FunctionTemplate.NullHandling;
-import org.apache.drill.exec.expr.annotations.Output;
-import org.apache.drill.exec.expr.annotations.Param;
-import org.apache.drill.exec.expr.holders.*;
-import org.apache.drill.exec.record.RecordBatch;
-import org.apache.drill.exec.expr.annotations.Workspace;
-
-import io.netty.buffer.ByteBuf;
-
-import java.nio.ByteBuffer;
-
-/*
- * This class is generated using freemarker and the ${.template_name} template.
- */
-
-@SuppressWarnings("unused")
-@FunctionTemplate(name = "cast${type.to?upper_case}",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_CAST,
- nulls = NullHandling.NULL_IF_NULL)
-public class Cast${type.from}${type.to} implements DrillSimpleFunc{
-
- @Param ${type.from}Holder in;
- @Inject DrillBuf buffer;
- @Param BigIntHolder precision;
- @Param BigIntHolder scale;
- @Output ${type.to}Holder out;
-
- public void setup() {
- int size = (${type.arraySize} * (org.apache.drill.exec.util.DecimalUtility.INTEGER_SIZE));
- buffer = buffer.reallocIfNeeded(size);
- }
-
- public void eval() {
- out.buffer = buffer;
- out.start = 0;
-
- // Re initialize the buffer everytime
- for (int i = 0; i < ${type.arraySize}; i++) {
- out.setInteger(i, 0, out.start, out.buffer);
- }
- out.scale = (int) scale.value;
- out.precision = (int) precision.value;
-
- out.buffer = buffer;
- out.start = 0;
-
- /* Since we will be dividing the decimal value with base 1 billion
- * we don't want negative results if the decimal is negative.
- */
- long value = (in.value < 0) ? (in.value * -1) : in.value;
-
- int index = out.nDecimalDigits - 1;
-
- // Separate out the scale part and store it
- int remainingScale = in.scale;
-
- while(remainingScale > 0) {
-
- int power = (remainingScale % org.apache.drill.exec.util.DecimalUtility.MAX_DIGITS);
- int padding = 1;
-
- if (power == 0) {
- power = 9;
- } else {
- padding = (int) (org.apache.drill.exec.util.DecimalUtility.getPowerOfTen((int) (org.apache.drill.exec.util.DecimalUtility.MAX_DIGITS - power)));
- }
-
- int mask = (int) org.apache.drill.exec.util.DecimalUtility.getPowerOfTen(power);
-
- out.setInteger(index, (int) ((value % mask) * padding), out.start, out.buffer);
-
- value = value/mask;
-
- remainingScale -= power;
-
- index--;
- }
-
- while (value > 0) {
- out.setInteger(index, (int) (value % org.apache.drill.exec.util.DecimalUtility.DIGITS_BASE), out.start, out.buffer);
- value = value/org.apache.drill.exec.util.DecimalUtility.DIGITS_BASE;
- index--;
- }
-
- // Round up or down the scale
- if (in.scale != out.scale) {
- org.apache.drill.exec.util.DecimalUtility.roundDecimal(out.buffer, out.start, out.nDecimalDigits, out.scale, in.scale);
- }
- // Set the sign
- out.setSign((in.value < 0), out.start, out.buffer);
- }
-}
-
-<#-- Template code for converting from Decimal9 to Decimal18 -->
-<#elseif type.major == "DecimalSimpleDecimalSimple">
-
-<@pp.changeOutputFile name="/org/apache/drill/exec/expr/fn/impl/gcast/Cast${type.from}${type.to}.java" />
-
-<#include "/@includes/license.ftl" />
-
-package org.apache.drill.exec.expr.fn.impl.gcast;
-
-<#include "/@includes/vv_imports.ftl" />
-
-import org.apache.drill.exec.expr.DrillSimpleFunc;
-import org.apache.drill.exec.expr.annotations.FunctionTemplate;
-import org.apache.drill.exec.expr.annotations.FunctionTemplate.NullHandling;
-import org.apache.drill.exec.expr.annotations.Output;
-import org.apache.drill.exec.expr.annotations.Param;
-import org.apache.drill.exec.expr.holders.*;
-import org.apache.drill.exec.record.RecordBatch;
-import org.apache.drill.exec.expr.annotations.Workspace;
-
-import io.netty.buffer.ByteBuf;
-
-import java.nio.ByteBuffer;
-
-/*
- * This class is generated using freemarker and the ${.template_name} template.
- */
-
-@SuppressWarnings("unused")
-@FunctionTemplate(name = "cast${type.to?upper_case}",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_CAST,
- nulls = NullHandling.NULL_IF_NULL)
-public class Cast${type.from}${type.to} implements DrillSimpleFunc {
-
- @Param ${type.from}Holder in;
- @Param BigIntHolder precision;
- @Param BigIntHolder scale;
- @Output ${type.to}Holder out;
-
- public void setup() {
- }
-
- public void eval() {
- out.scale = (int) scale.value;
- out.precision = (int) precision.value;
- out.value = in.value;
-
- // Truncate or pad additional zeroes if the output scale is different from input scale
- out.value = (${type.javatype}) (org.apache.drill.exec.util.DecimalUtility.adjustScaleMultiply(out.value, (int) (out.scale - in.scale)));
- }
-}
-</#if>
-</#list> \ No newline at end of file
diff --git a/exec/java-exec/src/main/codegen/templates/Decimal/CastVarCharDecimal.java b/exec/java-exec/src/main/codegen/templates/Decimal/CastVarCharDecimal.java
index 851d424af..a6e209d1d 100644
--- a/exec/java-exec/src/main/codegen/templates/Decimal/CastVarCharDecimal.java
+++ b/exec/java-exec/src/main/codegen/templates/Decimal/CastVarCharDecimal.java
@@ -19,211 +19,7 @@
<#list cast.types as type>
-<#if type.major == "VarCharDecimalSimple" || type.major == "EmptyStringVarCharDecimalSimple"> <#-- Cast function template for conversion from VarChar to Decimal9, Decimal18 -->
-
-<#if type.major == "VarCharDecimalSimple">
-<@pp.changeOutputFile name="/org/apache/drill/exec/expr/fn/impl/gcast/Cast${type.from}${type.to}.java"/>
-<#elseif type.major == "EmptyStringVarCharDecimalSimple">
-<@pp.changeOutputFile name="/org/apache/drill/exec/expr/fn/impl/gcast/CastEmptyString${type.from}To${type.to}.java"/>
-</#if>
-
-<#include "/@includes/license.ftl" />
-
-package org.apache.drill.exec.expr.fn.impl.gcast;
-
-<#include "/@includes/vv_imports.ftl" />
-
-import org.apache.drill.exec.expr.DrillSimpleFunc;
-import org.apache.drill.exec.expr.annotations.FunctionTemplate;
-import org.apache.drill.exec.expr.annotations.FunctionTemplate.NullHandling;
-import org.apache.drill.exec.expr.annotations.Output;
-import org.apache.drill.exec.expr.annotations.Param;
-import org.apache.drill.exec.expr.holders.*;
-import org.apache.drill.exec.record.RecordBatch;
-import org.apache.drill.exec.util.DecimalUtility;
-import org.apache.drill.exec.expr.annotations.Workspace;
-
-import io.netty.buffer.ByteBuf;
-import io.netty.buffer.DrillBuf;
-
-import java.nio.ByteBuffer;
-
-/*
- * This class is generated using freemarker and the ${.template_name} template.
- */
-
-@SuppressWarnings("unused")
-<#if type.major == "VarCharDecimalSimple">
-@FunctionTemplate(name = "cast${type.to?upper_case}",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_CAST,
- nulls = NullHandling.NULL_IF_NULL)
-public class Cast${type.from}${type.to} implements DrillSimpleFunc {
-<#elseif type.major == "EmptyStringVarCharDecimalSimple">
-@FunctionTemplate(name ="castEmptyString${type.from}To${type.to?upper_case}",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_CAST,
- nulls = NullHandling.INTERNAL)
-public class CastEmptyString${type.from}To${type.to} implements DrillSimpleFunc {
-</#if>
- @Param ${type.from}Holder in;
- @Param BigIntHolder precision;
- @Param BigIntHolder scale;
-
- <#if type.major == "VarCharDecimalSimple">
- @Output ${type.to}Holder out;
- <#elseif type.major == "EmptyStringVarCharDecimalSimple">
- @Output ${type.to}Holder out;
- </#if>
-
- public void setup() {
- }
-
- public void eval() {
- <#if type.major == "EmptyStringVarCharDecimalSimple">
- // Check if the input is null or empty string
- if(<#if type.from == "NullableVarChar"> in.isSet == 0 || </#if> in.end == in.start) {
- out.isSet = 0;
- return;
- }
- out.isSet = 1;
- </#if>
-
- // Assign the scale and precision
- out.scale = (int) scale.value;
-
- <#if type.to.endsWith("VarDecimal")>
-
- // VarDecimal gets its own cast logic
- byte[] buf = new byte[in.end - in.start];
- buffer.getBytes(in.start, buf, 0, in.end - in.start);
- String s = new String(buf, Charsets.UTF_8);
- Double d = Double.valueOf(s);
- for (int i = 0; i < out.scale; ++i) { // loop to compute unscaled value
- d *= 10.0;
- }
- long lval = (long)(d >= 0.0 ? d + 0.5 : d - 0.5); // round off unscaled integer, and hope it's close enough
- java.math.BigInteger bi = new java.math.BigInteger(Long.toString(lval));
- java.math.BigDecimal bd = new java.math.BigDecimal(bi, out.scale);
- int len = org.apache.drill.exec.util.DecimalUtility.getVarDecimalFromBigDecimal(bd, out.buffer, out.start);
- out.end = out.start + len;
-
- <#else> // !VarDecimal
-
- out.precision = (int) precision.value;
-
- int readIndex = in.start;
- int endIndex = in.end;
-
- <#if type.major == "VarCharDecimalSimple">
- // Check if its an empty string
- if (endIndex - readIndex == 0) {
- throw new org.apache.drill.common.exceptions.DrillRuntimeException("Empty String, cannot cast to Decimal");
- }
- </#if>
-
- // Starting position of fractional part
- int scaleIndex = -1;
- // true if we have a negative sign at the beginning
- boolean negative = false;
-
- // Check the first byte for '-'
- byte next = (in.buffer.getByte(readIndex));
-
- // If its a negative number
- if (next == '-') {
- negative = true;
- readIndex++;
- }
-
-
- /* Below two fields are used to compute if the precision is sufficient to store
- * the scale along with the integer digits in the string
- */
- int integerStartIndex = readIndex;
- int integerEndIndex = endIndex;
- boolean leadingDigitFound = false;
- boolean round = false;
-
- int radix = 10;
-
- // Start parsing the digits
- while (readIndex < endIndex) {
- next = in.buffer.getByte(readIndex++);
-
- if (next == '.') {
- scaleIndex = readIndex;
- // Integer end index is just before the scale part begins
- integerEndIndex = scaleIndex - 1;
- // If the number of fractional digits is > scale specified we might have to truncate
- if ((scaleIndex + out.scale) < endIndex ) {
- endIndex = scaleIndex + out.scale;
- round = true;
- }
- continue;
- } else {
- // If its not a '.' we expect only numbers
- next = (byte) Character.digit(next, radix);
- }
-
- if (next == -1) {
- // not a valid digit
- byte[] buf = new byte[in.end - in.start];
- in.buffer.getBytes(in.start, buf, 0, in.end - in.start);
- throw new org.apache.drill.common.exceptions.DrillRuntimeException(new String(buf, com.google.common.base.Charsets.UTF_8));
- } else if (leadingDigitFound == false) {
- if (next == 0) {
- // Ignore the leading zeroes while validating if input digits will fit within the given precision
- integerStartIndex++;
- } else {
- leadingDigitFound = true;
- }
- }
- out.value *= radix;
- out.value += next;
- }
-
- // Check if the provided precision is enough to store the given input
- if (((integerEndIndex - integerStartIndex) + out.scale) > out.precision) {
- byte[] buf = new byte[in.end - in.start];
- in.buffer.getBytes(in.start, buf, 0, in.end - in.start);
- throw new org.apache.drill.common.exceptions.DrillRuntimeException("Precision is insufficient for the provided input: " + new String(buf, com.google.common.base.Charsets.UTF_8) + " Precision: " + out.precision +
- " Total Digits: " + (out.scale + (integerEndIndex - integerStartIndex)));
- // TODO: Use JDK's java.nio.charset.StandardCharsets.UTF_8.
- }
-
- // Check if we need to round up
- if (round == true) {
- next = in.buffer.getByte(endIndex);
- next = (byte) Character.digit(next, radix);
- if (next == -1) {
- // not a valid digit
- byte[] buf = new byte[in.end - in.start];
- in.buffer.getBytes(in.start, buf, 0, in.end - in.start);
- throw new org.apache.drill.common.exceptions.DrillRuntimeException(new String(buf, com.google.common.base.Charsets.UTF_8));
- }
- if (next > 4) {
- out.value++;
- }
- }
-
- // Number of fractional digits in the input
- int fractionalDigits = (scaleIndex == -1) ? 0 : ((endIndex - scaleIndex));
-
- // Pad the number with zeroes if number of fractional digits is less than scale
- if (fractionalDigits < scale.value) {
- out.value = (${type.javatype}) (org.apache.drill.exec.util.DecimalUtility.adjustScaleMultiply(out.value, (int) (scale.value - fractionalDigits)));
- }
-
- // Negate the number if we saw a -ve sign
- if (negative == true) {
- out.value *= -1;
- }
- </#if>
- }
-}
-
-<#elseif type.major == "VarCharDecimalComplex" || type.major == "EmptyStringVarCharDecimalComplex"> <#-- Cast function template for conversion from VarChar to Decimal28, Decimal38 -->
+<#if type.major == "VarCharDecimalComplex" || type.major == "EmptyStringVarCharDecimalComplex"> <#-- Cast function template for conversion from VarChar to VarDecimal -->
<#if type.major == "VarCharDecimalComplex">
<@pp.changeOutputFile name="/org/apache/drill/exec/expr/fn/impl/gcast/Cast${type.from}${type.to}.java"/>
@@ -258,276 +54,57 @@ import java.nio.ByteBuffer;
@SuppressWarnings("unused")
<#if type.major == "VarCharDecimalComplex">
@FunctionTemplate(name = "cast${type.to?upper_case}",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_CAST,
- nulls = NullHandling.NULL_IF_NULL)
+ scope = FunctionTemplate.FunctionScope.SIMPLE,
+ returnType = FunctionTemplate.ReturnType.DECIMAL_CAST,
+ nulls = NullHandling.NULL_IF_NULL)
public class Cast${type.from}${type.to} implements DrillSimpleFunc {
<#elseif type.major == "EmptyStringVarCharDecimalComplex">
@FunctionTemplate(name = "castEmptyString${type.from}To${type.to?upper_case}",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_CAST,
- nulls = NullHandling.INTERNAL)
+ scope = FunctionTemplate.FunctionScope.SIMPLE,
+ returnType = FunctionTemplate.ReturnType.DECIMAL_CAST,
+ nulls = NullHandling.INTERNAL)
public class CastEmptyString${type.from}To${type.to} implements DrillSimpleFunc {
</#if>
- @Param ${type.from}Holder in;
- @Inject DrillBuf buffer;
- @Param BigIntHolder precision;
- @Param BigIntHolder scale;
-
- <#if type.major == "VarCharDecimalComplex">
- @Output ${type.to}Holder out;
- <#elseif type.major == "EmptyStringVarCharDecimalComplex">
- @Output ${type.to}Holder out;
- </#if>
-
- public void setup() {
- int size = ${type.arraySize} * (org.apache.drill.exec.util.DecimalUtility.INTEGER_SIZE);
- buffer = buffer.reallocIfNeeded(size);
+ @Param ${type.from}Holder in;
+ @Inject DrillBuf buffer;
+ @Param IntHolder precision;
+ @Param IntHolder scale;
+
+ @Output ${type.to}Holder out;
+
+ public void setup() {
+ }
+
+ public void eval() {
+ <#if type.major == "EmptyStringVarCharDecimalComplex">
+ // Check if the input is null or empty string
+ if (<#if type.from == "NullableVarChar"> in.isSet == 0 || </#if> in.end == in.start) {
+ out.isSet = 0;
+ return;
}
+ out.isSet = 1;
+ </#if>
- public void eval() {
- <#if type.major == "EmptyStringVarCharDecimalComplex">
- // Check if the input is null or empty string
- if(<#if type.from == "NullableVarChar"> in.isSet == 0 || </#if> in.end == in.start) {
- out.isSet = 0;
- return;
- }
- out.isSet = 1;
- </#if>
-
- out.buffer = buffer;
- out.start = 0;
-
- out.scale = (int) scale.value;
-
- <#if type.to.endsWith("VarDecimal")>
-
- // VarDecimal gets its own cast logic
- byte[] buf = new byte[in.end - in.start];
- buffer.getBytes(in.start, buf, 0, in.end - in.start);
- String s = new String(buf, Charsets.UTF_8);
- Double d = Double.valueOf(s);
- for (int i = 0; i < out.scale; ++i) { // loop to compute unscaled value
- d *= 10.0;
- }
- long lval = (long)(d >= 0.0 ? d + 0.5 : d - 0.5); // round off unscaled integer, and hope it's close enough
- java.math.BigInteger bi = new java.math.BigInteger(Long.toString(lval));
- java.math.BigDecimal bd = new java.math.BigDecimal(bi, out.scale);
- int len = org.apache.drill.exec.util.DecimalUtility.getVarDecimalFromBigDecimal(bd, out.buffer, out.start);
- out.end = out.start + len;
-
- <#else>
-
- out.precision = (int) precision.value;
- boolean sign = false;
-
- // Initialize the output buffer
- for (int i = 0; i < ${type.arraySize}; i++) {
- out.setInteger(i, 0, out.start, out.buffer);
- }
-
- int startIndex;
- int readIndex = in.start;
- int integerDigits = 0;
- int fractionalDigits = 0;
- int scaleIndex = -1;
- int scaleEndIndex = in.end;
-
- byte[] buf1 = new byte[in.end - in.start];
- in.buffer.getBytes(in.start, buf1, 0, in.end - in.start);
-
- Byte next = in.buffer.getByte(readIndex);
-
-
- if (next == '-') {
- readIndex++;
- sign = true;
- }
-
- if (next == '.') {
- readIndex++;
- scaleIndex = readIndex; // Fractional part starts at the first position
- }
-
- <#if type.major == "VarCharDecimalComplex">
- // Check if its an empty string
- if (in.end - readIndex == 0) {
- throw new org.apache.drill.common.exceptions.DrillRuntimeException("Empty String, cannot cast to Decimal");
- }
- </#if>
-
- // Store start index for the second pass
- startIndex = readIndex;
-
- int radix = 10;
- boolean leadingDigitFound = false;
- boolean round = false;
-
- /* This is the first pass, we get the number of integer digits and based on the provided scale
- * we compute which index into the ByteBuf we start storing the integer part of the Decimal
- */
- if (scaleIndex == -1) {
-
- while (readIndex < in.end) {
- next = in.buffer.getByte(readIndex++);
-
- if (next == '.') {
-
- // We have found the decimal point. we can compute the starting index into the Decimal's bytebuf
- scaleIndex = readIndex;
- // We may have to truncate fractional part if > scale
- if ((in.end - scaleIndex) > out.scale) {
- scaleEndIndex = scaleIndex + out.scale;
- round = true;
- }
- break;
- }
-
- // If its not a '.' we expect only numbers
- next = (byte) Character.digit(next, radix);
-
- if (next == -1) {
- // not a valid digit
- byte[] buf = new byte[in.end - in.start];
- in.buffer.getBytes(in.start, buf, 0, in.end - in.start);
- throw new NumberFormatException(new String(buf, com.google.common.base.Charsets.UTF_8));
- }
-
- if (leadingDigitFound == false && next != 0) {
- leadingDigitFound = true;
- }
-
- if (leadingDigitFound == true) {
- integerDigits++;
- }
- }
- }
-
- <#-- TODO: Pull out much of this code into something parallel to
- ByteFunctionHelpers but for DECIMAL type implementations. -->
-
- /* Based on the number of integer digits computed and the scale throw an
- * exception if the provided precision is not sufficient to store the value
- */
- if (integerDigits + out.scale > out.precision) {
- byte[] buf = new byte[in.end - in.start];
- in.buffer.getBytes(in.start, buf, 0, in.end - in.start);
- throw new org.apache.drill.common.exceptions.DrillRuntimeException("Precision is insufficient for the provided input: " + new String(buf, com.google.common.base.Charsets.UTF_8) + " Precision: " + out.precision + " Total Digits: " + (out.scale + integerDigits));
- <#-- TODO: Revisit message. (Message would be clearer and shorter
- as something like "Precision of X digits is insufficient for
- the provided input of "XXXXX.XXXXX" (X total digits)." (An
- occurrence of "Precision is insufficient for the provided input:
- 123456789.987654321 Precision: 5 Total Digits: 9" seemed to
- mean that 5 post-decimal digits and 9 total digits were allowed.)
- -->
- }
-
-
- // Compute the number of slots needed in the ByteBuf to store the integer and fractional part
- int scaleRoundedUp = org.apache.drill.exec.util.DecimalUtility.roundUp(out.scale);
- int integerRoundedUp = org.apache.drill.exec.util.DecimalUtility.roundUp(integerDigits);
-
- int ndigits = 0;
-
- int decimalBufferIndex = ${type.arraySize} - scaleRoundedUp - 1;
-
- /* Compute the end index of the integer part.
- * If we haven't seen a '.' then entire string is integer.
- * If we have seen a '.' it ends before the '.'
- */
- int integerEndIndex = (scaleIndex == -1) ? (in.end - 1) : (scaleIndex - 2);
-
- // Traverse and extract the integer part
- while (integerEndIndex >= startIndex) {
- next = in.buffer.getByte(integerEndIndex--);
-
- next = (byte) Character.digit(next, radix);
-
- int value = (((int) org.apache.drill.exec.util.DecimalUtility.getPowerOfTen(ndigits)) * next) + (out.getInteger(decimalBufferIndex, out.start, out.buffer));
- out.setInteger(decimalBufferIndex, value, out.start, out.buffer);
-
- ndigits++;
-
- /* We store the entire decimal as base 1 billion values, which has maximum of 9 digits (MAX_DIGITS)
- * Once we have stored MAX_DIGITS in a given slot move to the next slot.
- */
- if (ndigits >= org.apache.drill.exec.util.DecimalUtility.MAX_DIGITS) {
- ndigits = 0;
- decimalBufferIndex--;
- }
- }
-
- // Traverse and extract the fractional part
- decimalBufferIndex = (scaleRoundedUp > 0) ? (${type.arraySize} - scaleRoundedUp) : (${type.arraySize} - 1);
- ndigits = 0;
-
- if (scaleIndex != -1) {
- while (scaleIndex < scaleEndIndex) {
-
- // check if we have scanned MAX_DIGITS and we need to move to the next index
- if (ndigits >= org.apache.drill.exec.util.DecimalUtility.MAX_DIGITS) {
- ndigits = 0;
- decimalBufferIndex++;
- }
-
- next = in.buffer.getByte(scaleIndex++);
-
- // We expect only numbers beyond this
- next = (byte) Character.digit(next, radix);
-
- if (next == -1) {
- // not a valid digit
- byte[] buf = new byte[in.end - in.start];
- in.buffer.getBytes(in.start, buf, 0, in.end - in.start);
- throw new NumberFormatException(new String(buf, com.google.common.base.Charsets.UTF_8));
- }
- int value = (out.getInteger(decimalBufferIndex, out.start, out.buffer) * radix) + next;
- out.setInteger(decimalBufferIndex, value, out.start, out.buffer);
-
- // added another digit to the current index
- ndigits++;
- }
-
- // round up the decimal if we had to chop off a part of it
- if (round == true) {
- next = in.buffer.getByte(scaleEndIndex);
-
- // We expect only numbers beyond this
- next = (byte) Character.digit(next, radix);
-
- if (next == -1) {
- // not a valid digit
- byte[] buf = new byte[in.end - in.start];
- in.buffer.getBytes(in.start, buf, 0, in.end - in.start);
- throw new NumberFormatException(new String(buf, com.google.common.base.Charsets.UTF_8));
- }
- if (next > 4) {
- // Need to round up
- out.setInteger(decimalBufferIndex, out.getInteger(decimalBufferIndex, out.start, out.buffer)+1, out.start, out.buffer);
- }
- }
- // Pad zeroes in the fractional part so that number of digits = MAX_DIGITS
- if (out.scale > 0) {
- int padding = (int) org.apache.drill.exec.util.DecimalUtility.getPowerOfTen((int) (org.apache.drill.exec.util.DecimalUtility.MAX_DIGITS - ndigits));
- out.setInteger(decimalBufferIndex, out.getInteger(decimalBufferIndex, out.start, out.buffer) * padding, out.start, out.buffer);
- }
-
- int carry = 0;
- do {
- // propagate the carry
- int tempValue = out.getInteger(decimalBufferIndex, out.start, out.buffer) + carry;
- if (tempValue >= org.apache.drill.exec.util.DecimalUtility.DIGITS_BASE) {
- carry = tempValue / org.apache.drill.exec.util.DecimalUtility.DIGITS_BASE;
- tempValue = (tempValue % org.apache.drill.exec.util.DecimalUtility.DIGITS_BASE);
- } else {
- carry = 0;
- }
- out.setInteger(decimalBufferIndex--, tempValue, out.start, out.buffer);
- } while (carry > 0 && decimalBufferIndex >= 0);
- }
- out.setSign(sign, out.start, out.buffer);
- </#if>
- }
+ out.start = 0;
+
+ out.scale = scale.value;
+ out.precision = precision.value;
+
+ byte[] buf = new byte[in.end - in.start];
+ in.buffer.getBytes(in.start, buf, 0, in.end - in.start);
+ String s = new String(buf, com.google.common.base.Charsets.UTF_8);
+ java.math.BigDecimal bd =
+ new java.math.BigDecimal(s,
+ new java.math.MathContext(
+ precision.value,
+ java.math.RoundingMode.HALF_UP))
+ .setScale(scale.value, java.math.RoundingMode.HALF_UP);
+ byte[] bytes = bd.unscaledValue().toByteArray();
+ int len = bytes.length;
+ out.buffer = buffer.reallocIfNeeded(len);
+ out.buffer.setBytes(out.start, bytes);
+ out.end = out.start + len;
+ }
}
</#if> <#-- type.major -->
</#list>
diff --git a/exec/java-exec/src/main/codegen/templates/Decimal/CastDecimalSimilar.java b/exec/java-exec/src/main/codegen/templates/Decimal/CastVarDecimalDecimal.java
index 8b97b1a81..8ef2bf9a0 100644
--- a/exec/java-exec/src/main/codegen/templates/Decimal/CastDecimalSimilar.java
+++ b/exec/java-exec/src/main/codegen/templates/Decimal/CastVarDecimalDecimal.java
@@ -17,10 +17,8 @@
*/
<@pp.dropOutputFile />
-<#-- Template for converting between similar types of decimal. Decimal28Dense -> Decimal38Dense & Decimal28Sparse -> Decimal38Sparse -->
-
<#list cast.types as type>
-<#if type.major == "DecimalSimilar">
+<#if type.major == "VarDecimalToDecimal">
<@pp.changeOutputFile name="/org/apache/drill/exec/expr/fn/impl/gcast/Cast${type.from}${type.to}.java" />
@@ -47,51 +45,48 @@ import java.nio.ByteBuffer;
/*
* This class is generated using freemarker and the ${.template_name} template.
*/
-
@SuppressWarnings("unused")
@FunctionTemplate(name = "cast${type.to?upper_case}",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_CAST,
- nulls = NullHandling.NULL_IF_NULL)
-public class Cast${type.from}${type.to} implements DrillSimpleFunc{
-
- @Param ${type.from}Holder in;
- @Inject DrillBuf buffer;
- @Param BigIntHolder precision;
- @Param BigIntHolder scale;
- @Output ${type.to}Holder out;
-
- public void setup() {
- int size = (${type.arraySize} * (org.apache.drill.exec.util.DecimalUtility.INTEGER_SIZE));
- buffer = buffer.reallocIfNeeded(size);
- }
-
- public void eval() {
-
- out.buffer = buffer;
- out.start = 0;
- out.scale = (int) scale.value;
- out.precision = (int) precision.value;
- boolean sign = (in.getSign(in.start, in.buffer));
-
- // Re initialize the buffer everytime
- for (int i = 0; i < ${type.arraySize}; i++) {
- out.setInteger(i, 0, out.start, out.buffer);
- }
-
- int inputIdx = in.nDecimalDigits - 1;
- int outputIdx = out.nDecimalDigits - 1;
-
- for (; inputIdx >= 0; inputIdx--, outputIdx--) {
- out.setInteger(outputIdx, in.getInteger(inputIdx, in.start, in.buffer), out.start, out.buffer);
- }
-
- // round up or down the scale
- if (in.scale != out.scale) {
- org.apache.drill.exec.util.DecimalUtility.roundDecimal(out.buffer, out.start, out.nDecimalDigits, out.scale, in.scale);
- }
- out.setSign(sign, out.start, out.buffer);
- }
+ scope = FunctionTemplate.FunctionScope.SIMPLE,
+ returnType = FunctionTemplate.ReturnType.DECIMAL_CAST,
+ nulls = NullHandling.NULL_IF_NULL)
+public class Cast${type.from}${type.to} implements DrillSimpleFunc {
+
+ @Param ${type.from}Holder in;
+ <#if type.to.endsWith("Sparse") || type.to.endsWith("Dense")>
+ @Inject DrillBuf buffer;
+ </#if>
+ @Param IntHolder precision;
+ @Param IntHolder scale;
+ @Output ${type.to}Holder out;
+
+ public void setup() {
+ <#if type.to.endsWith("Sparse") || type.to.endsWith("Dense")>
+ int size = ${type.arraySize} * (org.apache.drill.exec.util.DecimalUtility.INTEGER_SIZE);
+ buffer = buffer.reallocIfNeeded(size);
+ </#if>
+ }
+
+ public void eval() {
+ out.scale = scale.value;
+ out.precision = precision.value;
+ java.math.BigDecimal bd =
+ org.apache.drill.exec.util.DecimalUtility
+ .getBigDecimalFromDrillBuf(in.buffer, in.start, in.end - in.start, in.scale)
+ .setScale(scale.value, java.math.RoundingMode.HALF_UP)
+ .round(new java.math.MathContext(precision.value, java.math.RoundingMode.HALF_UP));
+
+ <#if type.to.endsWith("Decimal9")>
+ out.value = org.apache.drill.exec.util.DecimalUtility.getDecimal9FromBigDecimal(bd, out.scale, out.precision);
+ <#elseif type.to.endsWith("Decimal18")>
+ out.value = org.apache.drill.exec.util.DecimalUtility.getDecimal18FromBigDecimal(bd, out.scale, out.precision);
+ <#elseif type.to.endsWith("Sparse")>
+ out.start = 0;
+ out.buffer = buffer;
+ org.apache.drill.exec.util.DecimalUtility
+ .getSparseFromBigDecimal(bd, out.buffer, out.start, out.scale, out.precision, out.nDecimalDigits);
+ </#if>
+ }
}
-</#if> <#-- type.major -->
+</#if>
</#list>
diff --git a/exec/java-exec/src/main/codegen/templates/Decimal/DecimalAggrTypeFunctions1.java b/exec/java-exec/src/main/codegen/templates/Decimal/DecimalAggrTypeFunctions1.java
index 893438ff4..6b23f92ed 100644
--- a/exec/java-exec/src/main/codegen/templates/Decimal/DecimalAggrTypeFunctions1.java
+++ b/exec/java-exec/src/main/codegen/templates/Decimal/DecimalAggrTypeFunctions1.java
@@ -17,15 +17,13 @@
*/
<@pp.dropOutputFile />
-
-
<#list decimalaggrtypes1.aggrtypes as aggrtype>
<@pp.changeOutputFile name="/org/apache/drill/exec/expr/fn/impl/gaggr/Decimal${aggrtype.className}Functions.java" />
<#include "/@includes/license.ftl" />
<#-- A utility class that is used to generate java code for aggr functions for decimal data type that maintain a single -->
-<#-- running counter to hold the result. This includes: MIN, MAX, COUNT. -->
+<#-- running counter to hold the result. This includes: MIN, MAX, SUM, $SUM0. -->
/*
* This class is automatically generated from AggrTypeFunctions1.tdd using FreeMarker.
@@ -54,204 +52,192 @@ import io.netty.buffer.ByteBuf;
@SuppressWarnings("unused")
public class Decimal${aggrtype.className}Functions {
- static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(${aggrtype.className}Functions.class);
-<#list aggrtype.types as type>
+ <#list aggrtype.types as type>
+ <#if aggrtype.funcName.contains("sum")>
+ @FunctionTemplate(name = "${aggrtype.funcName}",
+ scope = FunctionTemplate.FunctionScope.POINT_AGGREGATE,
+ returnType = FunctionTemplate.ReturnType.DECIMAL_SUM_AGGREGATE)
+ public static class ${type.inputType}${aggrtype.className} implements DrillAggFunc {
+ @Param ${type.inputType}Holder in;
+ @Inject DrillBuf buffer;
+ @Workspace ObjectHolder value;
+ @Workspace IntHolder outputScale;
+ @Output ${type.outputType}Holder out;
+ @Workspace BigIntHolder nonNullCount;
+
+ public void setup() {
+ value = new ObjectHolder();
+ value.obj = java.math.BigDecimal.ZERO;
+ outputScale = new IntHolder();
+ outputScale.value = Integer.MIN_VALUE;
+ nonNullCount = new BigIntHolder();
+ }
-@FunctionTemplate(name = "${aggrtype.funcName}",
- scope = FunctionTemplate.FunctionScope.POINT_AGGREGATE,
- <#if aggrtype.funcName == "sum"> returnType = FunctionTemplate.ReturnType.DECIMAL_SUM_AGGREGATE
- <#else>returnType = FunctionTemplate.ReturnType.DECIMAL_AGGREGATE</#if>)
-public static class ${type.inputType}${aggrtype.className} implements DrillAggFunc{
+ @Override
+ public void add() {
+ <#if type.inputType?starts_with("Nullable")>
+ sout: {
+ if (in.isSet == 0) {
+ // processing nullable input and the value is null, so don't do anything...
+ break sout;
+ }
+ </#if>
+ nonNullCount.value = 1;
+ java.math.BigDecimal currentValue = org.apache.drill.exec.util.DecimalUtility
+ .getBigDecimalFromDrillBuf(in.buffer, in.start, in.end - in.start, in.scale);
+ value.obj = ((java.math.BigDecimal) value.obj).add(currentValue);
+ if (outputScale.value == Integer.MIN_VALUE) {
+ outputScale.value = in.scale;
+ }
+ <#if type.inputType?starts_with("Nullable")>
+ } // end of sout block
+ </#if>
+ }
- @Param ${type.inputType}Holder in;
- <#if aggrtype.funcName == "sum">
- @Inject DrillBuf buffer;
- @Workspace ObjectHolder value;
- @Workspace IntHolder outputScale;
- <#elseif type.outputType.endsWith("Sparse")>
- @Inject DrillBuf buffer;
- @Workspace IntHolder scale;
- @Workspace IntHolder precision;
- @Workspace ObjectHolder value;
- <#else>
- @Workspace ${type.runningType}Holder value;
- </#if>
- @Output ${type.outputType}Holder out;
+ @Override
+ public void output() {
+ if (nonNullCount.value > 0) {
+ out.isSet = 1;
+ out.start = 0;
+ out.scale = Math.min(outputScale.value,
+ org.apache.drill.exec.planner.types.DrillRelDataTypeSystem.DRILL_REL_DATATYPE_SYSTEM.getMaxNumericScale());
+ out.precision =
+ org.apache.drill.exec.planner.types.DrillRelDataTypeSystem.DRILL_REL_DATATYPE_SYSTEM.getMaxNumericPrecision();
+ value.obj = ((java.math.BigDecimal) value.obj).setScale(out.scale, java.math.BigDecimal.ROUND_HALF_UP);
+ byte[] bytes = ((java.math.BigDecimal) value.obj).unscaledValue().toByteArray();
+ int len = bytes.length;
+ out.buffer = buffer.reallocIfNeeded(len);
+ out.buffer.setBytes(0, bytes);
+ out.end = len;
+ } else {
+ out.isSet = 0;
+ }
+ }
- public void setup() {
- <#if aggrtype.funcName == "count">
- value = new ${type.runningType}Holder();
- value.value = 0;
- <#elseif aggrtype.funcName == "max" || aggrtype.funcName == "min">
- <#if type.outputType.endsWith("Sparse")>
- scale.value = 0;
- precision.value = 0;
- value = new ObjectHolder();
- //${type.runningType}Holder tmp = new ${type.runningType}Holder();
- byte[] byteArray = new byte[${type.runningType}Holder.WIDTH];
- org.apache.drill.exec.util.Text tmp = new org.apache.drill.exec.util.Text(byteArray);
- value.obj = tmp;
- <#if aggrtype.funcName == "max">
- for (int i = 0; i < ${type.runningType}Holder.nDecimalDigits; i++) {
- org.apache.drill.exec.expr.fn.impl.ByteFunctionHelpers.setInteger(tmp.getBytes(), i, 0xFFFFFFFF);
+ @Override
+ public void reset() {
+ value = new ObjectHolder();
+ value.obj = java.math.BigDecimal.ZERO;
+ outputScale = new IntHolder();
+ outputScale.value = Integer.MIN_VALUE;
+ nonNullCount.value = 0;
}
- org.apache.drill.exec.expr.fn.impl.ByteFunctionHelpers.setSign(tmp.getBytes(), true);
- <#elseif aggrtype.funcName == "min">
- for (int i = 0; i < ${type.runningType}Holder.nDecimalDigits; i++) {
- org.apache.drill.exec.expr.fn.impl.ByteFunctionHelpers.setInteger(tmp.getBytes(), i, 0x7FFFFFFF);
+ }
+ <#elseif aggrtype.funcName == "max" || aggrtype.funcName == "min">
+
+ @FunctionTemplate(name = "${aggrtype.funcName}",
+ scope = FunctionTemplate.FunctionScope.POINT_AGGREGATE,
+ returnType = FunctionTemplate.ReturnType.DECIMAL_AGGREGATE)
+ public static class ${type.inputType}${aggrtype.className} implements DrillAggFunc {
+ @Param ${type.inputType}Holder in;
+ @Inject DrillBuf buffer;
+ @Workspace IntHolder scale;
+ @Workspace IntHolder precision;
+ @Workspace ObjectHolder tempResult;
+ @Output ${type.outputType}Holder out;
+ @Workspace BigIntHolder nonNullCount;
+ @Inject DrillBuf buf;
+
+ public void setup() {
+ tempResult = new ObjectHolder();
+ nonNullCount = new BigIntHolder();
}
- // Set sign to be positive so initial value is maximum
- org.apache.drill.exec.expr.fn.impl.ByteFunctionHelpers.setSign(tmp.getBytes(), false);
- </#if>
- <#elseif type.outputType == "Decimal9" || type.outputType == "Decimal18">
- value = new ${type.runningType}Holder();
- value.value = ${type.initValue};
- </#if>
- <#elseif aggrtype.funcName == "sum">
- buffer = buffer.reallocIfNeeded(${type.outputType}Holder.WIDTH);
- value = new ObjectHolder();
- value.obj = java.math.BigDecimal.ZERO;
- outputScale = new IntHolder();
- outputScale.value = Integer.MIN_VALUE;
- </#if>
- }
+ @Override
+ public void add() {
+ <#if type.inputType?starts_with("Nullable")>
+ sout: {
+ if (in.isSet == 0) {
+ // processing nullable input and the value is null, so don't do anything...
+ break sout;
+ }
+ </#if>
+ nonNullCount.value = 1;
+ org.apache.drill.exec.expr.fn.impl.DrillByteArray tmp = (org.apache.drill.exec.expr.fn.impl.DrillByteArray) tempResult.obj;
+ <#if aggrtype.funcName == "max">
+ int cmp = 0;
+ if (tmp != null) {
+ cmp = org.apache.drill.exec.util.DecimalUtility
+ .compareVarLenBytes(in.buffer, in.start, in.end, in.scale,
+ tmp.getBytes(), scale.value, false);
+ } else {
+ cmp = 1;
+ tmp = new org.apache.drill.exec.expr.fn.impl.DrillByteArray();
+ tempResult.obj = tmp;
+ }
- @Override
- public void add() {
- <#if type.inputType?starts_with("Nullable")>
- sout: {
- if (in.isSet == 0) {
- // processing nullable input and the value is null, so don't do anything...
- break sout;
- }
- </#if>
- <#if aggrtype.funcName == "count">
- value.value++;
- <#elseif aggrtype.funcName == "max">
- <#if type.outputType.endsWith("Sparse")>
- //${type.runningType}Holder tmp = (${type.runningType}Holder) value.obj;
- org.apache.drill.exec.util.Text tmp = (org.apache.drill.exec.util.Text) value.obj;
- int cmp = org.apache.drill.exec.util.DecimalUtility.compareSparseSamePrecScale(in.buffer, in.start, tmp.getBytes(), tmp.getLength());
- if (cmp == 1) {
- //in.buffer.getBytes(in.start, tmp.getBytes(), 0, ${type.runningType}Holder.WIDTH);
- for (int i = 0; i < ${type.runningType}Holder.nDecimalDigits; i++) {
- org.apache.drill.exec.expr.fn.impl.ByteFunctionHelpers.setInteger(tmp.getBytes(), i, ${type.runningType}Holder.getInteger(i, in.start, in.buffer));
+ if (cmp > 0) {
+ int inputLength = in.end - in.start;
+ if (tmp.getLength() >= inputLength) {
+ in.buffer.getBytes(in.start, tmp.getBytes(), 0, inputLength);
+ tmp.setLength(inputLength);
+ } else {
+ byte[] tempArray = new byte[in.end - in.start];
+ in.buffer.getBytes(in.start, tempArray, 0, in.end - in.start);
+ tmp.setBytes(tempArray);
+ }
+ scale.value = in.scale;
+ precision.value = in.precision;
}
- org.apache.drill.exec.expr.fn.impl.ByteFunctionHelpers.setSign(tmp.getBytes(), in.getSign(in.start, in.buffer));
- scale.value = in.scale;
- precision.value = in.precision;
- }
- <#elseif type.outputType == "Decimal9" || type.outputType == "Decimal18">
- value.value = Math.max(value.value, in.value);
- </#if>
- <#elseif aggrtype.funcName == "min">
- <#if type.outputType.endsWith("Sparse")>
- //${type.runningType}Holder tmp = (${type.runningType}Holder) value.obj;
- org.apache.drill.exec.util.Text tmp = (org.apache.drill.exec.util.Text) value.obj;
- int cmp = org.apache.drill.exec.util.DecimalUtility.compareSparseSamePrecScale(in.buffer, in.start, tmp.getBytes(), tmp.getLength());
- if (cmp == -1) {
- //in.buffer.getBytes(in.start, tmp.getBytes(), 0, ${type.runningType}Holder.WIDTH);
- for (int i = 0; i < ${type.runningType}Holder.nDecimalDigits; i++) {
- org.apache.drill.exec.expr.fn.impl.ByteFunctionHelpers.setInteger(tmp.getBytes(), i, ${type.runningType}Holder.getInteger(i, in.start, in.buffer));
+ <#elseif aggrtype.funcName == "min">
+ int cmp = 0;
+ if (tmp != null) {
+ cmp = org.apache.drill.exec.util.DecimalUtility
+ .compareVarLenBytes(in.buffer, in.start, in.end, in.scale,
+ tmp.getBytes(), scale.value, false);
+ } else {
+ cmp = -1;
+ tmp = new org.apache.drill.exec.expr.fn.impl.DrillByteArray();
+ tempResult.obj = tmp;
}
- org.apache.drill.exec.expr.fn.impl.ByteFunctionHelpers.setSign(tmp.getBytes(), in.getSign(in.start, in.buffer));
- scale.value = in.scale;
- precision.value = in.precision;
- }
- <#elseif type.outputType == "Decimal9" || type.outputType == "Decimal18">
- value.value = Math.min(value.value, in.value);
- </#if>
- <#elseif aggrtype.funcName == "sum">
- <#if type.inputType.endsWith("Decimal9") || type.inputType.endsWith("Decimal18")>
- java.math.BigDecimal currentValue = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromPrimitiveTypes(in.value, in.scale, in.precision);
- <#else>
- java.math.BigDecimal currentValue = in.getBigDecimal();
- </#if>
- value.obj = ((java.math.BigDecimal)(value.obj)).add(currentValue);
- if (outputScale.value == Integer.MIN_VALUE) {
- outputScale.value = in.scale;
- }
- </#if>
- <#if type.inputType?starts_with("Nullable")>
- } // end of sout block
- </#if>
- }
- @Override
- public void output() {
- <#if aggrtype.funcName == "count">
- out.value = value.value;
- <#elseif aggrtype.funcName == "sum">
- out.buffer = buffer;
- out.start = 0;
- out.scale = outputScale.value;
- value.obj = ((java.math.BigDecimal) (value.obj)).setScale(out.scale, java.math.BigDecimal.ROUND_HALF_UP);
-<#if type.inputType.contains("VarDecimal")>
- int len = org.apache.drill.exec.util.DecimalUtility.getVarDecimalFromBigDecimal((java.math.BigDecimal) value.obj, out.buffer, out.start);
- out.end = out.start + len;
-<#else>
- out.precision = 38;
- org.apache.drill.exec.util.DecimalUtility.getSparseFromBigDecimal((java.math.BigDecimal) value.obj, out.buffer, out.start, out.scale, out.precision, out.nDecimalDigits);
-</#if>
- <#else>
- <#if type.outputType.endsWith("Sparse")>
- org.apache.drill.exec.util.Text tmp = (org.apache.drill.exec.util.Text) value.obj;
- buffer = buffer.reallocIfNeeded(tmp.getLength());
- //buffer.setBytes(0, tmp.getBytes(), 0, tmp.getLength());
- for (int i = 0; i < ${type.runningType}Holder.nDecimalDigits; i++) {
- ${type.runningType}Holder.setInteger(i, org.apache.drill.exec.expr.fn.impl.ByteFunctionHelpers.getInteger(tmp.getBytes(), i), 0, buffer);
+ if (cmp < 0) {
+ int inputLength = in.end - in.start;
+ if (tmp.getLength() >= inputLength) {
+ in.buffer.getBytes(in.start, tmp.getBytes(), 0, inputLength);
+ tmp.setLength(inputLength);
+ } else {
+ byte[] tempArray = new byte[in.end - in.start];
+ in.buffer.getBytes(in.start, tempArray, 0, in.end - in.start);
+ tmp.setBytes(tempArray);
+ }
+ scale.value = in.scale;
+ precision.value = in.precision;
+ }
+ </#if>
+ <#if type.inputType?starts_with("Nullable")>
+ } // end of sout block
+ </#if>
}
- out.buffer = buffer;
- out.start = 0;
- out.setSign(org.apache.drill.exec.expr.fn.impl.ByteFunctionHelpers.getSign(tmp.getBytes()), out.start, out.buffer);
- out.scale = scale.value;
- out.precision = precision.value;
- <#elseif type.outputType == "Decimal9" || type.outputType == "Decimal18">
- out.value = value.value;
- out.scale = value.scale;
- out.precision = value.precision;
- </#if>
- </#if>
- }
-
- @Override
- public void reset() {
- <#if aggrtype.funcName == "count">
- value.value = 0;
- <#elseif aggrtype.funcName == "max" || aggrtype.funcName == "min">
- <#if type.outputType.endsWith("Sparse")>
- org.apache.drill.exec.util.Text tmp = (org.apache.drill.exec.util.Text) value.obj;
- for (int i = 0; i < ${type.runningType}Holder.nDecimalDigits; i++) {
- org.apache.drill.exec.expr.fn.impl.ByteFunctionHelpers.setInteger(tmp.getBytes(), i, 0xFFFFFFFF);
+ @Override
+ public void output() {
+ if (nonNullCount.value > 0) {
+ out.isSet = 1;
+ org.apache.drill.exec.expr.fn.impl.DrillByteArray tmp = (org.apache.drill.exec.expr.fn.impl.DrillByteArray) tempResult.obj;
+ buf = buf.reallocIfNeeded(tmp.getLength());
+ buf.setBytes(0, tmp.getBytes(), 0, tmp.getLength());
+ out.start = 0;
+ out.end = tmp.getLength();
+ out.buffer = buf;
+
+ out.scale = scale.value;
+ out.precision = precision.value;
+ } else {
+ out.isSet = 0;
+ }
}
- scale.value = 0;
- precision.value = 0;
- <#if aggrtype.funcName == "min">
- // Set sign to be positive so initial value is maximum
- org.apache.drill.exec.expr.fn.impl.ByteFunctionHelpers.setSign(tmp.getBytes(), false);
- <#elseif aggrtype.funcName == "max">
- org.apache.drill.exec.expr.fn.impl.ByteFunctionHelpers.setSign(tmp.getBytes(), true);
- </#if>
- <#elseif type.outputType == "Decimal9" || type.outputType == "Decimal18">
- value = new ${type.runningType}Holder();
- value.value = ${type.initValue};
- </#if>
- <#elseif aggrtype.funcName == "sum">
- value = new ObjectHolder();
- value.obj = java.math.BigDecimal.ZERO;
- outputScale = new IntHolder();
- outputScale.value = Integer.MIN_VALUE;
- </#if>
+ @Override
+ public void reset() {
+ scale.value = 0;
+ precision.value = 0;
+ tempResult.obj = null;
+ nonNullCount.value = 0;
+ }
}
-
- }
-
-
+ </#if>
</#list>
}
</#list>
-
diff --git a/exec/java-exec/src/main/codegen/templates/Decimal/DecimalAggrTypeFunctions2.java b/exec/java-exec/src/main/codegen/templates/Decimal/DecimalAggrTypeFunctions2.java
index df1eb7e81..c633b678c 100644
--- a/exec/java-exec/src/main/codegen/templates/Decimal/DecimalAggrTypeFunctions2.java
+++ b/exec/java-exec/src/main/codegen/templates/Decimal/DecimalAggrTypeFunctions2.java
@@ -27,7 +27,7 @@ import org.apache.drill.exec.expr.annotations.Workspace;
<#include "/@includes/license.ftl" />
<#-- A utility class that is used to generate java code for aggr functions for decimal data type that maintain a single -->
-<#-- running counter to hold the result. This includes: MIN, MAX, COUNT. -->
+<#-- running counter to hold the result. This includes: AVG. -->
/*
* This class is automatically generated from AggrTypeFunctions1.tdd using FreeMarker.
@@ -59,9 +59,9 @@ public class Decimal${aggrtype.className}Functions {
<#list aggrtype.types as type>
@FunctionTemplate(name = "${aggrtype.funcName}",
- scope = FunctionTemplate.FunctionScope.POINT_AGGREGATE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_SUM_AGGREGATE)
-public static class ${type.inputType}${aggrtype.className} implements DrillAggFunc{
+ scope = FunctionTemplate.FunctionScope.POINT_AGGREGATE,
+ returnType = FunctionTemplate.ReturnType.DECIMAL_AVG_AGGREGATE)
+public static class ${type.inputType}${aggrtype.className} implements DrillAggFunc {
@Param ${type.inputType}Holder in;
@Inject DrillBuf buffer;
@@ -71,7 +71,6 @@ public static class ${type.inputType}${aggrtype.className} implements DrillAggFu
@Output ${type.outputType}Holder out;
public void setup() {
- buffer.reallocIfNeeded(${type.outputType}Holder.WIDTH);
value = new ObjectHolder();
value.obj = java.math.BigDecimal.ZERO;
count = new ${type.countRunningType}Holder();
@@ -83,18 +82,15 @@ public static class ${type.inputType}${aggrtype.className} implements DrillAggFu
@Override
public void add() {
<#if type.inputType?starts_with("Nullable")>
- sout: {
+ sout: {
if (in.isSet == 0) {
// processing nullable input and the value is null, so don't do anything...
break sout;
}
</#if>
count.value++;
- <#if type.inputType.endsWith("Decimal9") || type.inputType.endsWith("Decimal18")>
- java.math.BigDecimal currentValue = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromPrimitiveTypes(in.value, in.scale, in.precision);
- <#else>
- java.math.BigDecimal currentValue = in.getBigDecimal();
- </#if>
+ java.math.BigDecimal currentValue = org.apache.drill.exec.util.DecimalUtility
+ .getBigDecimalFromDrillBuf(in.buffer, in.start, in.end - in.start, in.scale);
value.obj = ((java.math.BigDecimal)(value.obj)).add(currentValue);
if (outputScale.value == Integer.MIN_VALUE) {
outputScale.value = in.scale;
@@ -106,14 +102,21 @@ public static class ${type.inputType}${aggrtype.className} implements DrillAggFu
@Override
public void output() {
- out.buffer = buffer;
- out.start = 0;
- out.scale = outputScale.value;
- java.math.BigDecimal average = ((java.math.BigDecimal)(value.obj)).divide(java.math.BigDecimal.valueOf(count.value, 0), out.scale, java.math.BigDecimal.ROUND_HALF_UP);
-<#if !type.inputType.contains("VarDecimal")>
- out.precision = 38;
- org.apache.drill.exec.util.DecimalUtility.getSparseFromBigDecimal(average, out.buffer, out.start, out.scale, out.precision, out.nDecimalDigits);
-</#if>
+ if (count.value > 0) {
+ out.isSet = 1;
+ out.start = 0;
+ out.scale = Math.max(outputScale.value, 6);
+ java.math.BigDecimal average = ((java.math.BigDecimal) value.obj)
+ .divide(java.math.BigDecimal.valueOf(count.value), out.scale, java.math.BigDecimal.ROUND_HALF_UP);
+ out.precision = org.apache.drill.exec.planner.types.DrillRelDataTypeSystem.DRILL_REL_DATATYPE_SYSTEM.getMaxNumericPrecision();
+ byte[] bytes = average.unscaledValue().toByteArray();
+ int len = bytes.length;
+ out.buffer = buffer.reallocIfNeeded(len);
+ out.buffer.setBytes(0, bytes);
+ out.end = len;
+ } else {
+ out.isSet = 0;
+ }
}
@Override
@@ -127,7 +130,6 @@ public static class ${type.inputType}${aggrtype.className} implements DrillAggFu
}
}
-
</#list>
}
</#list>
diff --git a/exec/java-exec/src/main/codegen/templates/Decimal/DecimalAggrTypeFunctions3.java b/exec/java-exec/src/main/codegen/templates/Decimal/DecimalAggrTypeFunctions3.java
new file mode 100644
index 000000000..3058381d9
--- /dev/null
+++ b/exec/java-exec/src/main/codegen/templates/Decimal/DecimalAggrTypeFunctions3.java
@@ -0,0 +1,184 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+<@pp.dropOutputFile />
+
+<#list decimalaggrtypes3.aggrtypes as aggrtype>
+<@pp.changeOutputFile name="/org/apache/drill/exec/expr/fn/impl/gaggr/Decimal${aggrtype.className}Functions.java" />
+
+<#include "/@includes/license.ftl" />
+
+/*
+ * This class is generated using freemarker and the ${.template_name} template.
+ */
+
+<#-- A utility class that is used to generate java code for aggr functions such as stddev, variance -->
+
+package org.apache.drill.exec.expr.fn.impl.gaggr;
+
+import org.apache.drill.exec.expr.DrillAggFunc;
+import org.apache.drill.exec.expr.annotations.FunctionTemplate;
+import org.apache.drill.exec.expr.annotations.FunctionTemplate.NullHandling;
+import org.apache.drill.exec.expr.annotations.FunctionTemplate.FunctionScope;
+import org.apache.drill.exec.expr.annotations.Output;
+import org.apache.drill.exec.expr.annotations.Param;
+import org.apache.drill.exec.expr.annotations.Workspace;
+import org.apache.drill.exec.expr.holders.*;
+import javax.inject.Inject;
+import io.netty.buffer.DrillBuf;
+
+@SuppressWarnings("unused")
+
+public class Decimal${aggrtype.className}Functions {
+<#list aggrtype.types as type>
+
+ <#if aggrtype.aliasName == "">
+ @FunctionTemplate(name = "${aggrtype.funcName}",
+ <#else>
+ @FunctionTemplate(names = {"${aggrtype.funcName}", "${aggrtype.aliasName}"},
+ </#if>
+ scope = FunctionTemplate.FunctionScope.POINT_AGGREGATE,
+ returnType = FunctionTemplate.ReturnType.DECIMAL_AVG_AGGREGATE)
+ public static class ${type.inputType}${aggrtype.className} implements DrillAggFunc {
+ @Param ${type.inputType}Holder in;
+ @Inject DrillBuf buffer;
+ @Workspace ObjectHolder avg;
+ @Workspace ObjectHolder dev;
+ @Workspace BigIntHolder count;
+ @Workspace IntHolder scale;
+ @Output ${type.outputType}Holder out;
+ @Workspace BigIntHolder nonNullCount;
+
+ public void setup() {
+ avg = new ObjectHolder();
+ dev = new ObjectHolder();
+ count = new BigIntHolder();
+ scale = new IntHolder();
+ scale.value = Integer.MIN_VALUE;
+ // Initialize the workspace variables
+ avg.obj = java.math.BigDecimal.ZERO;
+ dev.obj = java.math.BigDecimal.ZERO;
+ count.value = 1;
+ nonNullCount = new BigIntHolder();
+ }
+
+ @Override
+ public void add() {
+ <#if type.inputType?starts_with("Nullable")>
+ sout: {
+ if (in.isSet == 0) {
+ // processing nullable input and the value is null, so don't do anything...
+ break sout;
+ }
+ </#if>
+
+ nonNullCount.value = 1;
+
+ if (scale.value == Integer.MIN_VALUE) {
+ scale.value = Math.max(in.scale, 6);
+ }
+
+ // Welford's approach to compute standard deviation
+ // avg.value += ((in.value - temp) / count.value);
+ // dev.value += (in.value - temp) * (in.value - avg.value);
+ java.math.BigDecimal temp = (java.math.BigDecimal) avg.obj;
+ java.math.BigDecimal input = org.apache.drill.exec.util.DecimalUtility
+ .getBigDecimalFromDrillBuf(in.buffer, in.start, in.end - in.start, in.scale);
+ avg.obj = ((java.math.BigDecimal) avg.obj)
+ .add(input.subtract(temp)
+ .divide(java.math.BigDecimal.valueOf(count.value),
+ new java.math.MathContext(
+ org.apache.drill.exec.planner.types.DrillRelDataTypeSystem.DRILL_REL_DATATYPE_SYSTEM.getMaxNumericPrecision(),
+ java.math.RoundingMode.HALF_UP)));
+ dev.obj = ((java.math.BigDecimal) dev.obj)
+ .add(input.subtract(temp).multiply(input.subtract(((java.math.BigDecimal) avg.obj))));
+ count.value++;
+ <#if type.inputType?starts_with("Nullable")>
+ } // end of sout block
+ </#if>
+ }
+
+ @Override
+ public void output() {
+ if (nonNullCount.value > 0) {
+ out.isSet = 1;
+ <#if aggrtype.funcName == "stddev_pop">
+ if (count.value > 1) {
+ // out.value = Math.sqrt((dev.value / (count.value - 1)));
+ java.math.BigDecimal result =
+ org.apache.drill.exec.util.DecimalUtility.sqrt(((java.math.BigDecimal) dev.obj)
+ .setScale(scale.value, java.math.RoundingMode.HALF_UP)
+ .divide(java.math.BigDecimal.valueOf(count.value - 1),
+ java.math.RoundingMode.HALF_UP),
+ scale.value);
+ <#elseif aggrtype.funcName == "var_pop">
+ if (count.value > 1) {
+ // out.value = (dev.value / (count.value - 1));
+ java.math.BigDecimal result =
+ ((java.math.BigDecimal) dev.obj)
+ .setScale(scale.value, java.math.RoundingMode.HALF_UP)
+ .divide(java.math.BigDecimal.valueOf(count.value - 1),
+ java.math.RoundingMode.HALF_UP);
+ <#elseif aggrtype.funcName == "stddev_samp">
+ if (count.value > 2) {
+ // out.value = Math.sqrt((dev.value / (count.value - 2)));
+ java.math.BigDecimal result =
+ org.apache.drill.exec.util.DecimalUtility.sqrt(((java.math.BigDecimal) dev.obj)
+ .setScale(scale.value, java.math.RoundingMode.HALF_UP)
+ .divide(java.math.BigDecimal.valueOf(count.value - 2),
+ java.math.RoundingMode.HALF_UP),
+ scale.value);
+ <#elseif aggrtype.funcName == "var_samp">
+ if (count.value > 2) {
+ // out.value = (dev.value / (count.value - 2));
+ java.math.BigDecimal result =
+ ((java.math.BigDecimal) dev.obj)
+ .setScale(scale.value, java.math.RoundingMode.HALF_UP)
+ .divide(java.math.BigDecimal.valueOf(count.value - 2),
+ java.math.RoundingMode.HALF_UP);
+ </#if>
+ out.scale = scale.value;
+ result = result.setScale(out.scale, java.math.RoundingMode.HALF_UP);
+ out.start = 0;
+ out.precision = org.apache.drill.exec.planner.types.DrillRelDataTypeSystem.DRILL_REL_DATATYPE_SYSTEM.getMaxNumericPrecision();
+ byte[] bytes = result.unscaledValue().toByteArray();
+ int len = bytes.length;
+ out.buffer = buffer.reallocIfNeeded(len);
+ out.buffer.setBytes(0, bytes);
+ out.end = len;
+ } else {
+ out.start = 0;
+ out.end = 0;
+ out.buffer = buffer;
+ }
+ } else {
+ out.isSet = 0;
+ }
+ }
+
+ @Override
+ public void reset() {
+ avg.obj = java.math.BigDecimal.ZERO;
+ dev.obj = java.math.BigDecimal.ZERO;
+ count.value = 1;
+ nonNullCount.value = 0;
+ }
+ }
+
+</#list>
+}
+</#list>
diff --git a/exec/java-exec/src/main/codegen/templates/Decimal/DecimalFunctions.java b/exec/java-exec/src/main/codegen/templates/Decimal/DecimalFunctions.java
index 53af71f62..059080e15 100644
--- a/exec/java-exec/src/main/codegen/templates/Decimal/DecimalFunctions.java
+++ b/exec/java-exec/src/main/codegen/templates/Decimal/DecimalFunctions.java
@@ -86,25 +86,12 @@ import org.apache.drill.exec.expr.annotations.Workspace;
</#macro>
<#macro varCompareBlock leftType rightType absCompare output nullCompare nullComparesHigh>
- outside:
- {
- <@compareNullsSubblock leftType=leftType rightType=rightType output=output breakTarget="outside" nullCompare=nullCompare nullComparesHigh=nullComparesHigh />
-
- ${output} = org.apache.drill.exec.util.DecimalUtility.compareVarLenBytes(left.buffer, left.start, left.end, left.scale, right.buffer, right.start, right.end, right.scale, ${absCompare});
- } // outside
-</#macro>
-
-<#macro adjustScale javaType leftType rightType>
-
- // Adjust the scale of the two inputs to be the same
+ outside:
+ {
+ <@compareNullsSubblock leftType = leftType rightType=rightType output = output breakTarget = "outside" nullCompare = nullCompare nullComparesHigh=nullComparesHigh />
- if (left.scale < right.scale) {
- left.value = (${javaType}) (org.apache.drill.exec.util.DecimalUtility.adjustScaleMultiply(left.value, (int) (right.scale - left.scale)));
- left.scale = right.scale;
- } else if (right.scale < left.scale) {
- right.value = (${javaType}) (org.apache.drill.exec.util.DecimalUtility.adjustScaleMultiply(right.value, (int) (left.scale - right.scale)));
- right.scale = left.scale;
- }
+ ${output} = org.apache.drill.exec.util.DecimalUtility.compareVarLenBytes(left.buffer, left.start, left.end, left.scale, right.buffer, right.start, right.end, right.scale, ${absCompare});
+ } // outside
</#macro>
<#-- For each DECIMAL... type (in DecimalTypes.tdd) ... -->
@@ -137,1373 +124,215 @@ import java.nio.ByteBuffer;
@SuppressWarnings("unused")
public class ${type.name}Functions {
- private static void initBuffer(DrillBuf buffer) {
- // for VarDecimal, this method of setting initial size is actually only a very rough heuristic.
- int size = (${type.storage} * (org.apache.drill.exec.util.DecimalUtility.INTEGER_SIZE));
- buffer = buffer.reallocIfNeeded(size);
- }
-
- @FunctionTemplate(name = "subtract",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_ADD_SCALE,
- nulls = NullHandling.NULL_IF_NULL,
- checkPrecisionRange = true)
- public static class ${type.name}SubtractFunction implements DrillSimpleFunc {
-
- @Param ${type.name}Holder left;
- @Param ${type.name}Holder right;
- @Inject DrillBuf buffer;
- @Workspace int outputScale;
- @Output ${type.name}Holder result;
-
- public void setup() {
- initBuffer(buffer);
- }
-
- public void eval(){
- outputScale=Math.max(left.scale,right.scale); // output scale is the maximum of the two scales, to represent result exactly
- result.scale=outputScale;
- result.buffer=buffer;
- result.start = 0;
-
- java.math.BigDecimal leftInput=org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromDrillBuf(left.buffer,left.start,left.end-left.start,left.scale);
- java.math.BigDecimal rightInput=org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromDrillBuf(right.buffer,right.start,right.end-right.start,right.scale);
- java.math.BigDecimal addResult=leftInput.subtract(rightInput);
-
- // Set the scale
- addResult.setScale(result.scale,java.math.BigDecimal.ROUND_HALF_UP);
- byte[]bytes=addResult.unscaledValue().toByteArray();
- int len=bytes.length;
- buffer=buffer.reallocIfNeeded(len);
- buffer.setBytes(0,bytes);
- result.end=len;
- }
+<#list ["Subtract", "Add", "Multiply", "Divide", "Mod"] as functionName>
+ @FunctionTemplate(name = "${functionName?lower_case}",
+ scope = FunctionTemplate.FunctionScope.SIMPLE,
+ <#if functionName == "Subtract" || functionName == "Add">
+ returnType = FunctionTemplate.ReturnType.DECIMAL_ADD_SCALE,
+ <#elseif functionName == "Multiply">
+ returnType = FunctionTemplate.ReturnType.DECIMAL_SUM_SCALE,
+ <#elseif functionName == "Divide">
+ returnType = FunctionTemplate.ReturnType.DECIMAL_DIV_SCALE,
+ <#elseif functionName == "Mod">
+ returnType = FunctionTemplate.ReturnType.DECIMAL_MOD_SCALE,
+ </#if>
+ nulls = NullHandling.NULL_IF_NULL,
+ checkPrecisionRange = true)
+ public static class ${type.name}${functionName}Function implements DrillSimpleFunc {
+ @Param ${type.name}Holder left;
+ @Param ${type.name}Holder right;
+ @Inject DrillBuf buffer;
+ @Output ${type.name}Holder result;
+
+ public void setup() {
}
- @FunctionTemplate(name = "add",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_ADD_SCALE,
- nulls = NullHandling.NULL_IF_NULL,
- checkPrecisionRange = true)
- public static class ${type.name}AddFunction implements DrillSimpleFunc {
-
- @Param ${type.name}Holder left;
- @Param ${type.name}Holder right;
- @Workspace int outputScale;
- @Inject DrillBuf buffer;
- @Output ${type.name}Holder result;
-
- public void setup() {
- initBuffer(buffer);
- }
-
- public void eval() {
- outputScale=Math.max(left.scale,right.scale); // output scale is the maximum of the two scales, to represent result exactly
- result.scale=outputScale;
- result.buffer=buffer;
- result.start = 0;
-
- java.math.BigDecimal leftInput=org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromDrillBuf(left.buffer,left.start,left.end-left.start,left.scale);
- java.math.BigDecimal rightInput=org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromDrillBuf(right.buffer,right.start,right.end-right.start,right.scale);
- java.math.BigDecimal addResult=leftInput.add(rightInput);
-
- // Set the scale
- addResult.setScale(result.scale,java.math.BigDecimal.ROUND_HALF_UP);
-
- byte[]bytes=addResult.unscaledValue().toByteArray();
- int len=bytes.length;
- buffer=buffer.reallocIfNeeded(len);
- buffer.setBytes(0,bytes);
- result.end=len;
- }
- }
-
- @FunctionTemplate(name = "multiply",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_SUM_SCALE,
- nulls = NullHandling.NULL_IF_NULL,
- checkPrecisionRange = true)
- public static class ${type.name}MultiplyFunction implements DrillSimpleFunc {
-
- @Param ${type.name}Holder left;
- @Param ${type.name}Holder right;
- @Inject DrillBuf buffer;
- @Workspace int outputScale;
- @Output ${type.name}Holder result;
-
- public void setup() {
- initBuffer(buffer);
- }
-
- public void eval() {
- outputScale=left.scale + right.scale; // sum of scales is guaranteed to represent multiplication result exactly
- result.scale=outputScale;
- result.buffer=buffer;
- result.start = 0;
-
- java.math.BigDecimal leftInput=org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromDrillBuf(left.buffer,left.start,left.end-left.start,left.scale);
- java.math.BigDecimal rightInput=org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromDrillBuf(right.buffer,right.start,right.end-right.start,right.scale);
- java.math.BigDecimal output=leftInput.multiply(rightInput);
-
- // Set the scale
- output.setScale(result.scale,java.math.BigDecimal.ROUND_HALF_UP);
-
- byte[]bytes=output.unscaledValue().toByteArray();
- int len=bytes.length;
- buffer=buffer.reallocIfNeeded(len);
- buffer.setBytes(0,bytes);
- result.end=len;
- }
- }
-
- @FunctionTemplate(name = "exact_divide",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_DIV_SCALE,
- nulls = NullHandling.NULL_IF_NULL,
- checkPrecisionRange = true)
- public static class ${type.name}DivideFunction implements DrillSimpleFunc {
- @Param ${type.name}Holder left;
- @Param ${type.name}Holder right;
- @Output ${type.name}Holder result;
- @Inject DrillBuf buffer;
- @Workspace int outputScale;
-
- public void setup() {
- initBuffer(buffer);
- }
-
- public void eval() {
- outputScale = left.scale + right.scale; // preferred scale is heuristically set to sum of scales, even though rounding may be required
- result.scale = outputScale;
- result.buffer = buffer;
- result.start = 0;
-
- java.math.BigDecimal numerator = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromDrillBuf(left.buffer, left.start, left.end - left.start, left.scale);
- java.math.BigDecimal denominator = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromDrillBuf(right.buffer, right.start, right.end - right.start, right.scale);
-
- java.math.BigDecimal output = numerator.divide(denominator, (int) result.scale, java.math.BigDecimal.ROUND_HALF_UP);
-
- byte[]bytes=output.unscaledValue().toByteArray();
- int len=bytes.length;
- buffer=buffer.reallocIfNeeded(len);
- buffer.setBytes(0,bytes);
- result.end=len;
- }
- }
-
- @FunctionTemplate(name = "mod",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_MOD_SCALE,
- nulls = NullHandling.NULL_IF_NULL,
- checkPrecisionRange = true)
- public static class ${type.name}ModFunction implements DrillSimpleFunc {
-
- @Param ${type.name}Holder left;
- @Param ${type.name}Holder right;
- @Output ${type.name}Holder result;
- @Inject DrillBuf buffer;
- @Workspace int outputScale;
-
- public void setup() {
- initBuffer(buffer);
- }
-
- public void eval() {
- outputScale = Math.max(left.scale,right.scale); // for mod, as for add & subtract, use larger of the two input scales
- result.scale = outputScale;
- result.buffer = buffer;
- result.start = 0;
-
- java.math.BigDecimal numerator = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromDrillBuf(left.buffer, left.start, left.end - left.start, left.scale);
- java.math.BigDecimal denominator = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromDrillBuf(right.buffer, right.start, right.end - right.start, right.scale);
-
- java.math.BigDecimal output = numerator.remainder(denominator);
- output.setScale(result.scale, java.math.BigDecimal.ROUND_HALF_UP);
-
- byte[]bytes=output.unscaledValue().toByteArray();
- int len=bytes.length;
- buffer=buffer.reallocIfNeeded(len);
- buffer.setBytes(0,bytes);
- result.end=len;
- }
- }
-
- @FunctionTemplate(name = "abs",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_MAX_SCALE,
- nulls = NullHandling.NULL_IF_NULL)
- public static class ${type.name}AbsFunction implements DrillSimpleFunc {
-
- @Param ${type.name}Holder in;
- @Output ${type.name}Holder result;
- @Inject DrillBuf buffer;
-
- public void setup() {
- initBuffer(buffer);
- }
-
- public void eval() {
- result.scale = in.scale;
- result.buffer = buffer;
- result.start = 0;
-
- java.math.BigDecimal bd = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromDrillBuf(in.buffer, in.start, in.end - in.start, in.scale);
- java.math.BigDecimal output = bd.abs();
- output.setScale(result.scale, java.math.BigDecimal.ROUND_HALF_UP);
-
- byte[]bytes=output.unscaledValue().toByteArray();
- int len=bytes.length;
- buffer=buffer.reallocIfNeeded(len);
- buffer.setBytes(0,bytes);
- result.end=len;
- }
- }
-
- @FunctionTemplate(name = "sign", scope = FunctionTemplate.FunctionScope.SIMPLE, nulls = NullHandling.NULL_IF_NULL)
- public static class ${type.name}SignFunction implements DrillSimpleFunc {
-
- @Param ${type.name}Holder in;
- @Output IntHolder out;
-
- public void setup() {}
-
- public void eval() {
- java.math.BigDecimal bd = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromDrillBuf(in.buffer, in.start, in.end - in.start, in.scale);
- out.value = bd.signum();
- }
- }
-
- @FunctionTemplate(names = {"ceil", "ceiling"},
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_ZERO_SCALE,
- nulls = NullHandling.NULL_IF_NULL)
- public static class ${type.name}CeilFunction implements DrillSimpleFunc {
-
- @Param ${type.name}Holder in;
- @Output ${type.name}Holder out;
- @Inject DrillBuf buffer;
-
- public void setup() {
- initBuffer(buffer);
- }
-
- public void eval() {
- out.scale = 0;
- out.buffer = buffer;
- out.start = 0;
- java.math.BigDecimal bd = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromDrillBuf(in.buffer, in.start, in.end - in.start, in.scale);
- bd.setScale(0, java.math.BigDecimal.ROUND_CEILING);
- byte[] bytes=bd.unscaledValue().toByteArray();
- int len=bytes.length;
- buffer=buffer.reallocIfNeeded(len);
- buffer.setBytes(0,bytes);
- out.end=len;
- }
- }
-
- @FunctionTemplate(name = "floor",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_ZERO_SCALE,
- nulls = NullHandling.NULL_IF_NULL)
- public static class ${type.name}FloorFunction implements DrillSimpleFunc {
-
- @Param ${type.name}Holder in;
- @Output ${type.name}Holder out;
- @Inject DrillBuf buffer;
-
- public void setup() {
- initBuffer(buffer);
- }
-
- public void eval() {
- out.scale = 0;
- out.buffer = buffer;
- out.start = 0;
- java.math.BigDecimal bd = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromDrillBuf(in.buffer, in.start, in.end - in.start, in.scale);
- bd.setScale(0, java.math.BigDecimal.ROUND_FLOOR);
- byte[] bytes=bd.unscaledValue().toByteArray();
- int len=bytes.length;
- buffer=buffer.reallocIfNeeded(len);
- buffer.setBytes(0,bytes);
- out.end=len;
- }
- }
-
- @FunctionTemplate(names = {"trunc", "truncate"},
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_ZERO_SCALE,
- nulls = NullHandling.NULL_IF_NULL)
- public static class ${type.name}TruncateFunction implements DrillSimpleFunc {
-
- @Param ${type.name}Holder in;
- @Output ${type.name}Holder out;
- @Inject DrillBuf buffer;
-
- public void setup() {
- initBuffer(buffer);
- }
-
- public void eval() {
- out.scale = 0;
- out.buffer = buffer;
- out.start = 0;
- java.math.BigDecimal bd = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromDrillBuf(in.buffer, in.start, in.end - in.start, in.scale);
- bd.setScale(0, java.math.BigDecimal.ROUND_DOWN);
- byte[] bytes=bd.unscaledValue().toByteArray();
- int len=bytes.length;
- buffer=buffer.reallocIfNeeded(len);
- buffer.setBytes(0,bytes);
- out.end=len;
- }
- }
-
- @FunctionTemplate(names = {"trunc", "truncate"},
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_SET_SCALE,
- nulls = NullHandling.NULL_IF_NULL)
- public static class ${type.name}TruncateScaleFunction implements DrillSimpleFunc {
-
- @Param ${type.name}Holder left;
- @Param IntHolder right;
- @Output ${type.name}Holder result;
- @Inject DrillBuf buffer;
-
- public void setup() {
- initBuffer(buffer);
- }
-
- public void eval() {
- result.scale = left.scale;
- result.buffer = left.buffer;
- result.start = left.start;
- result.end = left.end;
-
- // compute truncated value iff the indicated scale is less than the input's scale.
- // otherwise, we just copy the input (left) to the result, with the same scale.
- if (right.value < left.scale) {
- result.buffer = buffer;
- result.start = 0;
- result.scale = right.value;
- java.math.BigDecimal bd = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromDrillBuf(left.buffer, left.start, left.end - left.start, left.scale);
- bd.setScale(result.scale, java.math.BigDecimal.ROUND_DOWN);
- byte[] bytes=bd.unscaledValue().toByteArray();
- int len=bytes.length;
- buffer=buffer.reallocIfNeeded(len);
- buffer.setBytes(0,bytes);
- result.end=len;
- }
- }
- }
-
- @FunctionTemplate(name = "round",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_ZERO_SCALE,
- nulls = NullHandling.NULL_IF_NULL)
- public static class ${type.name}RoundFunction implements DrillSimpleFunc {
-
- @Param ${type.name}Holder in;
- @Output ${type.name}Holder out;
- @Inject DrillBuf buffer;
-
- public void setup() {
- initBuffer(buffer);
- }
+ public void eval() {
+ result.start = 0;
+
+ java.math.BigDecimal leftInput =
+ org.apache.drill.exec.util.DecimalUtility
+ .getBigDecimalFromDrillBuf(left.buffer, left.start, left.end - left.start, left.scale);
+ java.math.BigDecimal rightInput =
+ org.apache.drill.exec.util.DecimalUtility
+ .getBigDecimalFromDrillBuf(right.buffer, right.start, right.end - right.start, right.scale);
+ org.apache.drill.exec.planner.types.decimal.DrillBaseComputeScalePrecision typeInference =
+ <#if functionName == "Subtract" || functionName == "Add">
+ new org.apache.drill.exec.planner.types.decimal.DecimalScalePrecisionAddFunction(
+ <#elseif functionName == "Multiply">
+ new org.apache.drill.exec.planner.types.decimal.DecimalScalePrecisionMulFunction(
+ <#elseif functionName == "Divide">
+ new org.apache.drill.exec.planner.types.decimal.DecimalScalePrecisionDivideFunction(
+ <#elseif functionName == "Mod">
+ new org.apache.drill.exec.planner.types.decimal.DecimalScalePrecisionModFunction(
+ </#if>
+ left.precision, left.scale,
+ right.precision, right.scale);
+
+ result.scale = typeInference.getOutputScale();
+ result.precision = typeInference.getOutputPrecision();
+
+ java.math.BigDecimal opResult =
+ <#if functionName == "Subtract" || functionName == "Add"
+ || functionName == "Multiply"|| functionName == "Divide">
+ leftInput.${functionName?lower_case}(rightInput,
+ <#elseif functionName == "Mod">
+ leftInput.remainder(rightInput,
+ </#if>
+ new java.math.MathContext(result.precision, java.math.RoundingMode.HALF_UP))
+ .setScale(result.scale, java.math.BigDecimal.ROUND_HALF_UP);
- public void eval() {
- out.scale = 0;
- out.buffer = buffer;
- out.start = 0;
- java.math.BigDecimal bd = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromDrillBuf(in.buffer, in.start, in.end - in.start, in.scale);
- bd.setScale(0, java.math.BigDecimal.ROUND_HALF_UP);
- byte[] bytes=bd.unscaledValue().toByteArray();
- int len=bytes.length;
- buffer=buffer.reallocIfNeeded(len);
- buffer.setBytes(0,bytes);
- out.end=len;
- }
+ byte[] bytes = opResult.unscaledValue().toByteArray();
+ int len = bytes.length;
+ result.buffer = buffer.reallocIfNeeded(len);
+ result.buffer.setBytes(0, bytes);
+ result.end = len;
}
+ }
- @FunctionTemplate(name = "round",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_SET_SCALE,
- nulls = NullHandling.NULL_IF_NULL)
- public static class ${type.name}RoundScaleFunction implements DrillSimpleFunc {
-
- @Param ${type.name}Holder left;
- @Param IntHolder right;
- @Output ${type.name}Holder result;
- @Inject DrillBuf buffer;
-
- public void setup() {
- initBuffer(buffer);
- }
+</#list>
- public void eval() {
- result.scale = right.value;
- result.buffer = buffer;
- result.start = 0;
- java.math.BigDecimal bd = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromDrillBuf(left.buffer, left.start, left.end - left.start, left.scale);
- bd.setScale(result.scale, java.math.BigDecimal.ROUND_HALF_UP);
- byte[] bytes=bd.unscaledValue().toByteArray();
- int len=bytes.length;
- buffer=buffer.reallocIfNeeded(len);
- buffer.setBytes(0,bytes);
- result.end=len;
- }
+<#list ["Abs", "Ceil", "Floor", "Trunc", "Round"] as functionName>
+ <#if functionName == "Ceil">
+ @FunctionTemplate(names = {"ceil", "ceiling"},
+ <#elseif functionName == "Trunc">
+ @FunctionTemplate(names = {"trunc", "truncate"},
+ <#else>
+ @FunctionTemplate(name = "${functionName?lower_case}",
+ </#if>
+ scope = FunctionTemplate.FunctionScope.SIMPLE,
+ <#if functionName == "Abs">
+ returnType = FunctionTemplate.ReturnType.DECIMAL_MAX_SCALE,
+ <#elseif functionName == "Ceil" || functionName == "Floor"
+ || functionName == "Trunc" || functionName == "Round">
+ returnType = FunctionTemplate.ReturnType.DECIMAL_ZERO_SCALE,
+ </#if>
+ nulls = NullHandling.NULL_IF_NULL)
+ public static class ${type.name}${functionName}Function implements DrillSimpleFunc {
+ @Param ${type.name}Holder in;
+ @Output ${type.name}Holder result;
+ @Inject DrillBuf buffer;
+
+ public void setup() {
}
- <#-- Handle 2 x 2 combinations of nullable and non-nullable arguments. -->
- <#list ["Nullable${type.name}", "${type.name}"] as leftType >
- <#list ["Nullable${type.name}", "${type.name}"] as rightType >
-
- <#-- Comparison function for sorting and grouping relational operators
- (not for comparison expression operators (=, <, etc.)). -->
- @FunctionTemplate(name = FunctionGenerationHelper.COMPARE_TO_NULLS_HIGH,
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_MAX_SCALE,
- nulls = NullHandling.INTERNAL)
- public static class GCompare${leftType}Vs${rightType}NullHigh implements DrillSimpleFunc {
-
- @Param ${leftType}Holder left;
- @Param ${rightType}Holder right;
- @Output IntHolder out;
-
- public void setup() {}
-
public void eval() {
- <@varCompareBlock leftType=leftType rightType=rightType absCompare="false" output="out.value" nullCompare=true nullComparesHigh=true />
+ result.start = 0;
+ result.precision = in.precision;
+
+ java.math.BigDecimal opResult =
+ org.apache.drill.exec.util.DecimalUtility
+ .getBigDecimalFromDrillBuf(in.buffer, in.start, in.end - in.start, in.scale)
+ <#if functionName == "Abs">
+ .abs();
+ result.scale = in.scale;
+ <#elseif functionName == "Ceil">
+ .setScale(0, java.math.BigDecimal.ROUND_CEILING);
+ <#elseif functionName == "Floor">
+ .setScale(0, java.math.BigDecimal.ROUND_FLOOR);
+ <#elseif functionName == "Trunc">
+ .setScale(0, java.math.BigDecimal.ROUND_DOWN);
+ <#elseif functionName == "Round">
+ .setScale(0, java.math.BigDecimal.ROUND_HALF_UP);
+ </#if>
+
+ byte[] bytes = opResult.unscaledValue().toByteArray();
+ int len = bytes.length;
+ result.buffer = buffer.reallocIfNeeded(len);
+ result.buffer.setBytes(0, bytes);
+ result.end = len;
}
}
-
-
- <#-- Comparison function for sorting and grouping relational operators
- (not for comparison expression operators (=, <, etc.)). -->
- @FunctionTemplate(name = FunctionGenerationHelper.COMPARE_TO_NULLS_LOW,
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_MAX_SCALE,
- nulls = NullHandling.INTERNAL)
- public static class GCompare${leftType}Vs${rightType}NullLow implements DrillSimpleFunc {
-
- @Param ${leftType}Holder left;
- @Param ${rightType}Holder right;
+</#list>
+ @FunctionTemplate(name = "sign",
+ scope = FunctionTemplate.FunctionScope.SIMPLE,
+ nulls = NullHandling.NULL_IF_NULL)
+ public static class ${type.name}SignFunction implements DrillSimpleFunc {
+ @Param ${type.name}Holder in;
@Output IntHolder out;
public void setup() {}
public void eval() {
- <@varCompareBlock leftType=leftType rightType=rightType absCompare="false" output="out.value" nullCompare=true nullComparesHigh=false />
+ // TODO: optimize to get only bytes that corresponds to sign.
+ // Should be taken into account case when leading zero bytes are stored in buff.
+ java.math.BigDecimal bd =
+ org.apache.drill.exec.util.DecimalUtility
+ .getBigDecimalFromDrillBuf(in.buffer, in.start, in.end - in.start, in.scale);
+ out.value = bd.signum();
}
}
- </#list>
- </#list>
-
- <#-- Comparison function for comparison expression operator (=, &lt;, etc.),
- not for sorting and grouping relational operators.) -->
- @FunctionTemplate(name = "less than",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_MAX_SCALE,
- nulls = NullHandling.NULL_IF_NULL)
- public static class ${type.name}LessThan implements DrillSimpleFunc {
-
- @Param ${type.name}Holder left;
- @Param ${type.name}Holder right;
- @Output BitHolder out;
- public void setup() {}
-
- public void eval() {
- int cmp;
- <@varCompareBlock leftType="leftType" rightType="rightType" absCompare="false" output="cmp" nullCompare=false nullComparesHigh=false />
- out.value = cmp == -1 ? 1 : 0;
- }
- }
-
-
- // TODO: RESOLVE: Here there are spaces in function template names, but
- // elsewhere there are underlines. Are things being looked up correctly?
- <#-- Comparison function for comparison expression operator (=, &lt;, etc.),
- not for sorting and grouping relational operators.) -->
- @FunctionTemplate(name = "less than or equal to",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_MAX_SCALE,
- nulls = NullHandling.NULL_IF_NULL)
- public static class ${type.name}LessThanEq implements DrillSimpleFunc {
-
- @Param ${type.name}Holder left;
- @Param ${type.name}Holder right;
- @Output BitHolder out;
- public void setup() {}
-
- public void eval() {
- int cmp;
- <@varCompareBlock leftType="leftType" rightType="rightType" absCompare="false" output="cmp" nullCompare=false nullComparesHigh=false />
- out.value = cmp < 1 ? 1 : 0;
- }
- }
-
-
- <#-- Comparison function for comparison expression operator (=, &lt;, etc.),
- not for sorting and grouping relational operators.) -->
- @FunctionTemplate(name = "greater than",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_MAX_SCALE,
- nulls = NullHandling.NULL_IF_NULL)
- public static class ${type.name}GreaterThan implements DrillSimpleFunc {
-
- @Param ${type.name}Holder left;
- @Param ${type.name}Holder right;
- @Output BitHolder out;
- public void setup() {}
-
- public void eval() {
- int cmp;
- <@varCompareBlock leftType="leftType" rightType="rightType" absCompare="false" output="cmp" nullCompare=false nullComparesHigh=false />
- out.value = cmp == 1 ? 1 : 0;
- }
- }
-
-
- <#-- Comparison function for comparison expression operator (=, &lt;, etc.),
- not for sorting and grouping relational operators.) -->
- @FunctionTemplate(name = "greater than or equal to",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_MAX_SCALE,
- nulls = NullHandling.NULL_IF_NULL)
- public static class ${type.name}GreaterThanEq implements DrillSimpleFunc {
-
- @Param ${type.name}Holder left;
- @Param ${type.name}Holder right;
- @Output BitHolder out;
- public void setup() {}
-
- public void eval() {
- int cmp;
- <@varCompareBlock leftType="leftType" rightType="rightType" absCompare="false" output="cmp" nullCompare=false nullComparesHigh=false />
- out.value = cmp > -1 ? 1 : 0;
- }
- }
-
-
- <#-- Comparison function for comparison expression operator (=, &lt;, etc.),
- not for sorting and grouping relational operators.) -->
- @FunctionTemplate(name = "Equal",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_MAX_SCALE,
- nulls = NullHandling.NULL_IF_NULL)
- public static class ${type.name}Equal implements DrillSimpleFunc {
-
- @Param ${type.name}Holder left;
- @Param ${type.name}Holder right;
- @Output BitHolder out;
- public void setup() {}
-
- public void eval() {
- int cmp;
- <@varCompareBlock leftType="leftType" rightType="rightType" absCompare="false" output="cmp" nullCompare=false nullComparesHigh=false />
- out.value = cmp == 0 ? 1 : 0;
- }
- }
-
-
- <#-- Comparison function for comparison expression operator (=, &lt;, etc.),
- not for sorting and grouping relational operators.) -->
- @FunctionTemplate(name = "not equal",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_MAX_SCALE,
- nulls = NullHandling.NULL_IF_NULL)
- public static class ${type.name}NotEqual implements DrillSimpleFunc {
-
- @Param ${type.name}Holder left;
- @Param ${type.name}Holder right;
- @Output BitHolder out;
- public void setup() {}
-
- public void eval() {
- int cmp;
- <@varCompareBlock leftType="leftType" rightType="rightType" absCompare="false" output="cmp" nullCompare=false nullComparesHigh=false />
- out.value = cmp != 0 ? 1 : 0;
- }
- }
-}
-
-<#elseif type.name.endsWith("Sparse")>
-
-<@pp.changeOutputFile name="/org/apache/drill/exec/expr/fn/impl/${type.name}Functions.java" />
-
-<#include "/@includes/license.ftl" />
+ @FunctionTemplate(names = {"trunc", "truncate"},
+ scope = FunctionTemplate.FunctionScope.SIMPLE,
+ returnType = FunctionTemplate.ReturnType.DECIMAL_SET_SCALE,
+ nulls = NullHandling.NULL_IF_NULL)
+ public static class ${type.name}TruncateScaleFunction implements DrillSimpleFunc {
+ @Param ${type.name}Holder left;
+ @Param IntHolder right;
+ @Output ${type.name}Holder result;
+ @Inject DrillBuf buffer;
-package org.apache.drill.exec.expr.fn.impl;
-
-<#include "/@includes/vv_imports.ftl" />
-
-import org.apache.drill.exec.expr.DrillSimpleFunc;
-import org.apache.drill.exec.expr.annotations.FunctionTemplate;
-import org.apache.drill.exec.expr.annotations.FunctionTemplate.NullHandling;
-import org.apache.drill.exec.expr.annotations.Output;
-import org.apache.drill.exec.expr.annotations.Param;
-import org.apache.drill.exec.expr.annotations.Workspace;
-import org.apache.drill.exec.expr.fn.FunctionGenerationHelper;
-import org.apache.drill.exec.expr.holders.*;
-import org.apache.drill.exec.record.RecordBatch;
-
-import io.netty.buffer.ByteBuf;
-import io.netty.buffer.DrillBuf;
-
-import java.nio.ByteBuffer;
-/*
- * This class is generated using freemarker and the ${.template_name} template.
- */
-
-@SuppressWarnings("unused")
-public class ${type.name}Functions {
-
- @FunctionTemplate(name = "subtract",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_ADD_SCALE,
- nulls = NullHandling.NULL_IF_NULL,
- checkPrecisionRange = true)
- public static class ${type.name}SubtractFunction implements DrillSimpleFunc {
-
- @Param ${type.name}Holder left;
- @Param ${type.name}Holder right;
- @Inject DrillBuf buffer;
- @Workspace int outputScale;
- @Workspace int outputPrecision;
- @Output ${type.name}Holder result;
-
- public void setup() {
- int size = (${type.storage} * (org.apache.drill.exec.util.DecimalUtility.INTEGER_SIZE));
- buffer = buffer.reallocIfNeeded(size);
- outputPrecision = Integer.MIN_VALUE;
- }
-
- public void eval() {
- if (outputPrecision == Integer.MIN_VALUE) {
- org.apache.drill.common.util.DecimalScalePrecisionAddFunction resultScalePrec =
- new org.apache.drill.common.util.DecimalScalePrecisionAddFunction((int) left.precision, (int) left.scale, (int) right.precision, (int) right.scale);
- outputScale = resultScalePrec.getOutputScale();
- outputPrecision = resultScalePrec.getOutputPrecision();
- }
- result.precision = outputPrecision;
- result.scale = outputScale;
- result.buffer = buffer;
- result.start = 0;
-
- java.math.BigDecimal leftInput = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromSparse(left.buffer, left.start, left.nDecimalDigits, left.scale);
- java.math.BigDecimal rightInput = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromSparse(right.buffer, right.start, right.nDecimalDigits, right.scale);
- java.math.BigDecimal addResult = leftInput.subtract(rightInput);
-
- // Set the scale
- addResult.setScale(result.scale, java.math.BigDecimal.ROUND_HALF_UP);
- org.apache.drill.exec.util.DecimalUtility.getSparseFromBigDecimal(addResult, result.buffer, result.start, result.scale, result.precision, result.nDecimalDigits);
- }
+ public void setup() {
}
- @FunctionTemplate(name = "add",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_ADD_SCALE,
- nulls = NullHandling.NULL_IF_NULL,
- checkPrecisionRange = true)
- public static class ${type.name}AddFunction implements DrillSimpleFunc {
-
- @Param ${type.name}Holder left;
- @Param ${type.name}Holder right;
- @Workspace int outputScale;
- @Workspace int outputPrecision;
- @Inject DrillBuf buffer;
- @Output ${type.name}Holder result;
-
- public void setup() {
- int size = (${type.storage} * (org.apache.drill.exec.util.DecimalUtility.INTEGER_SIZE));
- buffer = buffer.reallocIfNeeded(size);
- outputPrecision = Integer.MIN_VALUE;
- }
-
- public void eval() {
- if (outputPrecision == Integer.MIN_VALUE) {
- org.apache.drill.common.util.DecimalScalePrecisionAddFunction resultScalePrec =
- new org.apache.drill.common.util.DecimalScalePrecisionAddFunction((int) left.precision, (int) left.scale, (int) right.precision, (int) right.scale);
- outputScale = resultScalePrec.getOutputScale();
- outputPrecision = resultScalePrec.getOutputPrecision();
- }
- result.precision = outputPrecision;
- result.scale = outputScale;
- result.buffer = buffer;
- result.start = 0;
-
- java.math.BigDecimal leftInput = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromSparse(left.buffer, left.start, left.nDecimalDigits, left.scale);
- java.math.BigDecimal rightInput = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromSparse(right.buffer, right.start, right.nDecimalDigits, right.scale);
- java.math.BigDecimal addResult = leftInput.add(rightInput);
-
- // Set the scale
- addResult.setScale(result.scale, java.math.BigDecimal.ROUND_HALF_UP);
- org.apache.drill.exec.util.DecimalUtility.getSparseFromBigDecimal(addResult, result.buffer, result.start, result.scale, result.precision, result.nDecimalDigits);
- }
- }
-
- @FunctionTemplate(name = "multiply",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_SUM_SCALE,
- nulls = NullHandling.NULL_IF_NULL,
- checkPrecisionRange = true)
- public static class ${type.name}MultiplyFunction implements DrillSimpleFunc {
-
- @Param ${type.name}Holder left;
- @Param ${type.name}Holder right;
- @Inject DrillBuf buffer;
- @Workspace int[] tempResult;
- @Workspace int outputScale;
- @Workspace int outputPrecision;
- @Output ${type.name}Holder result;
-
- public void setup() {
- int size = (${type.storage} * (org.apache.drill.exec.util.DecimalUtility.INTEGER_SIZE));
- buffer = buffer.reallocIfNeeded(size);
- tempResult = new int[${type.storage} * ${type.storage}];
- outputPrecision = Integer.MIN_VALUE;
- }
-
- public void eval() {
- if (outputPrecision == Integer.MIN_VALUE) {
- org.apache.drill.common.util.DecimalScalePrecisionMulFunction resultScalePrec =
- new org.apache.drill.common.util.DecimalScalePrecisionMulFunction((int) left.precision, (int) left.scale, (int) right.precision, (int) right.scale);
- outputScale = resultScalePrec.getOutputScale();
- outputPrecision = resultScalePrec.getOutputPrecision();
- }
- // Set the scale and precision
- result.scale = outputScale;
- result.precision = outputPrecision;
- result.buffer = buffer;
- result.start = 0;
-
- // Re initialize the temporary array
- for (int i = 0; i < ${type.storage} * ${type.storage}; i++) {
- tempResult[i] = 0;
- }
-
- // Remove the leading zeroes from the integer part of the input
- int leftIndex = 0;
- int leftStopIndex = left.nDecimalDigits - org.apache.drill.exec.util.DecimalUtility.roundUp(left.scale);
-
- while (leftIndex < leftStopIndex) {
- if (left.getInteger(leftIndex, left.start, left.buffer) > 0)
- break;
- leftIndex++;
- }
-
- int leftIntegerSize = leftStopIndex - leftIndex;
-
- /* Remove the leading zeroes from the integer part of the input */
- int rightIndex = 0;
- int rightStopIndex = right.nDecimalDigits - org.apache.drill.exec.util.DecimalUtility.roundUp(right.scale);
-
- while(rightIndex < rightStopIndex) {
- if (right.getInteger(rightIndex, right.start, right.buffer) > 0)
- break;
- rightIndex++;
- }
-
- int rightIntegerSize = rightStopIndex - rightIndex;
-
- int resultIntegerSize = leftIntegerSize + rightIntegerSize;
- int resultScaleSize = org.apache.drill.exec.util.DecimalUtility.roundUp(left.scale + right.scale);
-
- int leftSize = left.nDecimalDigits - 1;
- int rightSize = right.nDecimalDigits - 1;
-
- int resultIndex = tempResult.length - 1;
- int currentIndex = 0;
-
- for (int i = leftSize; i >= leftIndex; i--) {
-
- currentIndex = resultIndex;
- int carry = 0;
-
- for (int j = rightSize; j >= rightIndex; j--) {
-
- long mulResult = (long) right.getInteger(j, right.start, right.buffer) * (long) left.getInteger(i, left.start, left.buffer);
-
- long tempSum = tempResult[currentIndex] + mulResult + carry;
-
- if (tempSum >= org.apache.drill.exec.util.DecimalUtility.DIGITS_BASE) {
- tempResult[currentIndex] = (int) (tempSum % org.apache.drill.exec.util.DecimalUtility.DIGITS_BASE);
- carry = (int) (tempSum / org.apache.drill.exec.util.DecimalUtility.DIGITS_BASE);
- } else {
- tempResult[currentIndex] = (int) tempSum;
- carry = 0;
- }
-
- currentIndex--;
- }
- /* Propagate the carry */
- if (carry > 0)
- tempResult[currentIndex] += carry;
-
- resultIndex--;
- }
-
- /* We have computed the result of the multiplication; check if we need to
- * round a portion of the fractional part
- */
- resultScaleSize = org.apache.drill.exec.util.DecimalUtility.roundUp(result.scale);
-
- if (result.scale < (left.scale + right.scale)) {
- /* The scale of the output data type is less than the scale
- * we obtained as a result of multiplication, we need to round
- * a chunk of the fractional part
- */
- int lastScaleIndex = currentIndex + resultIntegerSize + resultScaleSize - 1;
-
- // Compute the power of 10 necessary to find if we need to round up
- int roundFactor = (int) (org.apache.drill.exec.util.DecimalUtility.getPowerOfTen(
- org.apache.drill.exec.util.DecimalUtility.MAX_DIGITS - ((result.scale + 1) % org.apache.drill.exec.util.DecimalUtility.MAX_DIGITS)));
-
- // Index of rounding digit
- int roundIndex = currentIndex + resultIntegerSize + org.apache.drill.exec.util.DecimalUtility.roundUp(result.scale + 1) - 1;
-
- // Check the first chopped digit to see if we need to round up
- int carry = ((tempResult[roundIndex] / roundFactor) % 10) > 4 ? 1 : 0;
-
- if (result.scale > 0) {
-
- // Compute the power of 10 necessary to chop of the fractional part
- int scaleFactor = (int) (org.apache.drill.exec.util.DecimalUtility.getPowerOfTen(
- org.apache.drill.exec.util.DecimalUtility.MAX_DIGITS - (result.scale % org.apache.drill.exec.util.DecimalUtility.MAX_DIGITS)));
- // Chop the unwanted fractional part
- tempResult[lastScaleIndex] /= scaleFactor;
- tempResult[lastScaleIndex] *= scaleFactor;
-
- // Adjust the carry so that it gets added to the correct digit
- carry *= scaleFactor;
- }
-
- // Propagate the carry
- while (carry > 0 && lastScaleIndex >= 0) {
- int tempSum = tempResult[lastScaleIndex] + carry;
- if (tempSum >= org.apache.drill.exec.util.DecimalUtility.DIGITS_BASE) {
- tempResult[lastScaleIndex] = (tempSum % org.apache.drill.exec.util.DecimalUtility.DIGITS_BASE);
- carry = (int) (tempSum / org.apache.drill.exec.util.DecimalUtility.DIGITS_BASE);
- } else {
- tempResult[lastScaleIndex] = tempSum;
- carry = 0;
- }
- lastScaleIndex--;
- }
-
- // Check if carry has increased integer digit
- if ((lastScaleIndex + 1) < currentIndex) {
- resultIntegerSize++;
- currentIndex = lastScaleIndex + 1;
- }
- }
-
- if (resultIntegerSize > result.nDecimalDigits) {
- throw new org.apache.drill.common.exceptions.DrillRuntimeException("Cannot fit multiplication result in the given decimal type");
- }
-
- int outputIndex = result.nDecimalDigits - 1;
-
- for (int i = (currentIndex + resultIntegerSize + resultScaleSize - 1); i >= currentIndex; i--) {
- result.setInteger(outputIndex--, tempResult[i], result.start, result.buffer);
- }
-
- // Set the remaining digits to be zero
- while(outputIndex >= 0) {
- result.setInteger(outputIndex--, 0, result.start, result.buffer);
- }
- result.setSign(left.getSign(left.start, left.buffer) != right.getSign(right.start, right.buffer), result.start, result.buffer);
- }
- }
-
- @FunctionTemplate(name = "exact_divide",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_DIV_SCALE,
- nulls = NullHandling.NULL_IF_NULL,
- checkPrecisionRange = true)
- public static class ${type.name}DivideFunction implements DrillSimpleFunc {
-
- @Param ${type.name}Holder left;
- @Param ${type.name}Holder right;
- @Output ${type.name}Holder result;
- @Inject DrillBuf buffer;
- @Workspace int outputScale;
- @Workspace int outputPrecision;
-
- public void setup() {
- int size = (${type.storage} * (org.apache.drill.exec.util.DecimalUtility.INTEGER_SIZE));
- buffer = buffer.reallocIfNeeded(size);
- outputPrecision = Integer.MIN_VALUE;
- }
-
- public void eval() {
- if (outputPrecision == Integer.MIN_VALUE) {
- org.apache.drill.common.util.DecimalScalePrecisionDivideFunction resultScalePrec =
- new org.apache.drill.common.util.DecimalScalePrecisionDivideFunction((int) left.precision, (int) left.scale, (int) right.precision, (int) right.scale);
- outputScale = resultScalePrec.getOutputScale();
- outputPrecision = resultScalePrec.getOutputPrecision();
- }
- result.scale = outputScale;
- result.precision = outputPrecision;
- result.buffer = buffer;
- result.start = 0;
-
- java.math.BigDecimal numerator = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromDrillBuf(left.buffer, left.start, left.nDecimalDigits, left.scale, true);
- java.math.BigDecimal denominator = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromDrillBuf(right.buffer, right.start, right.nDecimalDigits, right.scale, true);
-
- java.math.BigDecimal output = numerator.divide(denominator, (int) result.scale, java.math.BigDecimal.ROUND_HALF_UP);
-
- org.apache.drill.exec.util.DecimalUtility.getSparseFromBigDecimal(output, result.buffer, result.start, result.scale, result.precision, result.nDecimalDigits);
- }
- }
-
- @FunctionTemplate(name = "mod",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_MOD_SCALE,
- nulls = NullHandling.NULL_IF_NULL,
- checkPrecisionRange = true)
- public static class ${type.name}ModFunction implements DrillSimpleFunc {
-
- @Param ${type.name}Holder left;
- @Param ${type.name}Holder right;
- @Output ${type.name}Holder result;
- @Inject DrillBuf buffer;
- @Workspace int outputScale;
- @Workspace int outputPrecision;
-
- public void setup() {
- int size = (${type.storage} * (org.apache.drill.exec.util.DecimalUtility.INTEGER_SIZE));
- buffer = buffer.reallocIfNeeded(size);
- outputPrecision = Integer.MIN_VALUE;
- }
-
- public void eval() {
- if (outputPrecision == Integer.MIN_VALUE) {
- org.apache.drill.common.util.DecimalScalePrecisionModFunction resultScalePrec =
- new org.apache.drill.common.util.DecimalScalePrecisionModFunction((int) left.precision, (int) left.scale, (int) right.precision, (int) right.scale);
- outputScale = resultScalePrec.getOutputScale();
- outputPrecision = resultScalePrec.getOutputPrecision();
- }
- result.scale = outputScale;
- result.precision = outputPrecision;
- result.buffer = buffer;
- result.start = 0;
-
- java.math.BigDecimal numerator = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromDrillBuf(left.buffer, left.start, left.nDecimalDigits, left.scale, true);
- java.math.BigDecimal denominator = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromDrillBuf(right.buffer, right.start, right.nDecimalDigits, right.scale, true);
-
- java.math.BigDecimal output = numerator.remainder(denominator);
- output.setScale(result.scale, java.math.BigDecimal.ROUND_HALF_UP);
-
- org.apache.drill.exec.util.DecimalUtility.getSparseFromBigDecimal(output, result.buffer, result.start, result.scale, result.precision, result.nDecimalDigits);
- }
- }
-
- @FunctionTemplate(name = "abs",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_MAX_SCALE,
- nulls = NullHandling.NULL_IF_NULL)
- public static class ${type.name}AbsFunction implements DrillSimpleFunc {
-
- @Param ${type.name}Holder in;
- @Output ${type.name}Holder out;
- public void setup() {
-
- }
-
- public void eval() {
- out.scale = in.scale;
- out.precision = in.precision;
- out.buffer = in.buffer;
- out.start = in.start;
-
- // Set the output buffer with the positive sign
- out.buffer.setInt(out.start, (out.buffer.getInt(out.start) & 0x7fffffff));
- }
- }
-
- @FunctionTemplate(name = "sign", scope = FunctionTemplate.FunctionScope.SIMPLE, nulls = NullHandling.NULL_IF_NULL)
- public static class ${type.name}SignFunction implements DrillSimpleFunc {
-
- @Param ${type.name}Holder in;
- @Output IntHolder out;
-
- public void setup() {}
-
- public void eval() {
-
- boolean zeroValue = true;
-
- if (in.getSign(in.start, in.buffer) == true) {
- out.value = -1;
- } else {
- for (int i = 0; i < ${type.storage}; i++) {
- if (in.getInteger(i, in.start, in.buffer) != 0) {
- zeroValue = false;
- break;
- }
- }
- out.value = (zeroValue == true) ? 0 : 1;
- }
- }
- }
-
- @FunctionTemplate(names = {"ceil", "ceiling"},
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_ZERO_SCALE,
- nulls = NullHandling.NULL_IF_NULL)
- public static class ${type.name}CeilFunction implements DrillSimpleFunc {
-
- @Param ${type.name}Holder in;
- @Output ${type.name}Holder out;
- public void setup() {
-
- }
-
- public void eval() {
- out.scale = 0;
- out.precision = in.precision;
- out.buffer = in.buffer;
- out.start = in.start;
- boolean sign = in.getSign(in.start, in.buffer);
-
- // Indicates whether we need to add 1 to the integer part, while performing ceil
- int carry = 0;
-
- int scaleStartIndex = ${type.storage} - org.apache.drill.exec.util.DecimalUtility.roundUp(in.scale);
- int srcIntIndex = scaleStartIndex - 1;
-
- if (sign == false) {
- // For negative values ceil we don't need to increment the integer part
- while (scaleStartIndex < ${type.storage}) {
- if (out.getInteger(scaleStartIndex, out.start, out.buffer) != 0) {
- carry = 1;
- break;
- }
- scaleStartIndex++;
- }
- }
-
- // Truncate the fractional part, move the integer part
- int destIndex = ${type.storage} - 1;
- while (srcIntIndex >= 0) {
- out.setInteger(destIndex--, out.getInteger(srcIntIndex--, out.start, out.buffer), out.start, out.buffer);
- }
-
- // Set the remaining portion of the decimal to be zeroes
- while (destIndex >= 0) {
- out.setInteger(destIndex--, 0, out.start, out.buffer);
- }
-
- // Add the carry
- if (carry != 0) {
- destIndex = ${type.storage} - 1;
-
- while (destIndex >= 0) {
- int intValue = out.getInteger(destIndex, out.start, out.buffer);
- intValue += carry;
-
- if (intValue >= org.apache.drill.exec.util.DecimalUtility.DIGITS_BASE) {
- out.setInteger(destIndex--, intValue % org.apache.drill.exec.util.DecimalUtility.DIGITS_BASE, out.start, out.buffer);
- carry = intValue / org.apache.drill.exec.util.DecimalUtility.DIGITS_BASE;
- } else {
- out.setInteger(destIndex--, intValue, out.start, out.buffer);
- break;
- }
- }
- }
- // Set the sign
- out.setSign(sign, out.start, out.buffer);
- }
- }
-
- @FunctionTemplate(name = "floor",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_ZERO_SCALE,
- nulls = NullHandling.NULL_IF_NULL)
- public static class ${type.name}FloorFunction implements DrillSimpleFunc {
-
- @Param ${type.name}Holder in;
- @Output ${type.name}Holder out;
- public void setup() {
-
- }
-
- public void eval() {
- out.scale = 0;
- out.precision = in.precision;
- out.buffer = in.buffer;
- out.start = in.start;
- boolean sign = in.getSign(in.start, in.buffer);
-
- // Indicates whether we need to decrement 1 from the integer part, while performing floor, done for -ve values
- int carry = 0;
-
- int scaleStartIndex = ${type.storage} - org.apache.drill.exec.util.DecimalUtility.roundUp(in.scale);
- int srcIntIndex = scaleStartIndex - 1;
-
- if (sign == true) {
- // For negative values ceil we don't need to increment the integer part
- while (scaleStartIndex < ${type.storage}) {
- if (out.getInteger(scaleStartIndex, out.start, out.buffer) != 0) {
- carry = 1;
- break;
- }
- scaleStartIndex++;
- }
- }
-
- // Truncate the fractional part, move the integer part
- int destIndex = ${type.storage} - 1;
- while (srcIntIndex >= 0) {
- out.setInteger(destIndex--, out.getInteger(srcIntIndex--, out.start, out.buffer), out.start, out.buffer);
- }
-
- // Set the remaining portion of the decimal to be zeroes
- while (destIndex >= 0) {
- out.setInteger(destIndex--, 0, out.start, out.buffer);
- }
- // Add the carry
- if (carry != 0) {
- destIndex = ${type.storage} - 1;
-
- while (destIndex >= 0) {
- int intValue = out.getInteger(destIndex, out.start, out.buffer);
- intValue += carry;
-
- if (intValue >= org.apache.drill.exec.util.DecimalUtility.DIGITS_BASE) {
- out.setInteger(destIndex--, intValue % org.apache.drill.exec.util.DecimalUtility.DIGITS_BASE, out.start, out.buffer);
- carry = intValue / org.apache.drill.exec.util.DecimalUtility.DIGITS_BASE;
- } else {
- out.setInteger(destIndex--, intValue, out.start, out.buffer);
- break;
- }
- }
- }
- // Set the sign
- out.setSign(sign, out.start, out.buffer);
- }
- }
-
- @FunctionTemplate(names = {"trunc", "truncate"},
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_ZERO_SCALE,
- nulls = NullHandling.NULL_IF_NULL)
- public static class ${type.name}TruncateFunction implements DrillSimpleFunc {
-
- @Param ${type.name}Holder in;
- @Output ${type.name}Holder out;
- public void setup() {
-
- }
-
- public void eval() {
- out.scale = 0;
- out.precision = in.precision;
- out.buffer = in.buffer;
- out.start = in.start;
- boolean sign = in.getSign(in.start, in.buffer);
-
- // Integer part's src index
- int srcIntIndex = ${type.storage} - org.apache.drill.exec.util.DecimalUtility.roundUp(in.scale) - 1;
-
- // Truncate the fractional part, move the integer part
- int destIndex = ${type.storage} - 1;
- while (srcIntIndex >= 0) {
- out.setInteger(destIndex--, out.getInteger(srcIntIndex--, out.start, out.buffer), out.start, out.buffer);
- }
-
- // Set the remaining portion of the decimal to be zeroes
- while (destIndex >= 0) {
- out.setInteger(destIndex--, 0, out.start, out.buffer);
- }
- // Set the sign
- out.setSign(sign, out.start, out.buffer);
- }
- }
-
- @FunctionTemplate(names = {"trunc", "truncate"},
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_SET_SCALE,
- nulls = NullHandling.NULL_IF_NULL)
- public static class ${type.name}TruncateScaleFunction implements DrillSimpleFunc {
-
- @Param ${type.name}Holder left;
- @Param IntHolder right;
- @Output ${type.name}Holder result;
- public void setup() {
-
- }
-
- public void eval() {
- result.scale = right.value;
- result.precision = left.precision;
- result.buffer = left.buffer;
- result.start = left.start;
- boolean sign = left.getSign(left.start, left.buffer);
-
- int newScaleRoundedUp = org.apache.drill.exec.util.DecimalUtility.roundUp(right.value);
- int origScaleRoundedUp = org.apache.drill.exec.util.DecimalUtility.roundUp(left.scale);
-
- if (right.value < left.scale) {
- // Get the source index beyond which we will truncate
- int srcIntIndex = ${type.storage} - origScaleRoundedUp - 1;
- int srcIndex = srcIntIndex + newScaleRoundedUp;
-
- // Truncate the remaining fractional part, move the integer part
- int destIndex = ${type.storage} - 1;
- if (srcIndex != destIndex) {
- while (srcIndex >= 0) {
- result.setInteger(destIndex--, result.getInteger(srcIndex--, result.start, result.buffer), result.start, result.buffer);
- }
-
- // Set the remaining portion of the decimal to be zeroes
- while (destIndex >= 0) {
- result.setInteger(destIndex--, 0, result.start, result.buffer);
- }
- }
-
- // We truncated the decimal digit. Now we need to truncate within the base 1 billion fractional digit
- int truncateFactor = org.apache.drill.exec.util.DecimalUtility.MAX_DIGITS - (right.value % org.apache.drill.exec.util.DecimalUtility.MAX_DIGITS);
- if (truncateFactor != org.apache.drill.exec.util.DecimalUtility.MAX_DIGITS) {
- truncateFactor = (int) org.apache.drill.exec.util.DecimalUtility.getPowerOfTen(truncateFactor);
- int fractionalDigits = result.getInteger(${type.storage} - 1, result.start, result.buffer);
- fractionalDigits /= truncateFactor;
- result.setInteger(${type.storage} - 1, fractionalDigits * truncateFactor, result.start, result.buffer);
- }
- } else if (right.value > left.scale) {
- // Add fractional digits to the decimal
-
- // Check if we need to shift the decimal digits to the left
- if (newScaleRoundedUp > origScaleRoundedUp) {
- int srcIndex = 0;
- int destIndex = newScaleRoundedUp - origScaleRoundedUp;
-
- // Check while extending scale, we are not overwriting integer part
- while (srcIndex < destIndex) {
- if (result.getInteger(srcIndex++, result.start, result.buffer) != 0) {
- throw new org.apache.drill.common.exceptions.DrillRuntimeException("Truncate resulting in loss of integer part, reduce scale specified");
- }
- }
-
- srcIndex = 0;
- while (destIndex < ${type.storage}) {
- result.setInteger(srcIndex++, result.getInteger(destIndex++, result.start, result.buffer), result.start, result.buffer);
- }
-
- // Clear the remaining part
- while (srcIndex < ${type.storage}) {
- result.setInteger(srcIndex++, 0, result.start, result.buffer);
- }
- }
- }
- // Set the sign
- result.setSign(sign, result.start, result.buffer);
- }
+ public void eval() {
+ result.start = 0;
+ result.scale = right.value;
+ result.precision = left.precision;
+ java.math.BigDecimal opResult =
+ org.apache.drill.exec.util.DecimalUtility
+ .getBigDecimalFromDrillBuf(left.buffer, left.start, left.end - left.start, left.scale)
+ .setScale(result.scale, java.math.BigDecimal.ROUND_DOWN);
+ byte[] bytes = opResult.unscaledValue().toByteArray();
+ int len = bytes.length;
+ result.buffer = buffer.reallocIfNeeded(len);
+ result.buffer.setBytes(0, bytes);
+ result.end = len;
}
+ }
- @FunctionTemplate(name = "round",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_ZERO_SCALE,
- nulls = NullHandling.NULL_IF_NULL)
- public static class ${type.name}RoundFunction implements DrillSimpleFunc {
-
- @Param ${type.name}Holder in;
- @Output ${type.name}Holder out;
- public void setup() {
-
- }
-
- public void eval() {
- out.scale = 0;
- out.precision = in.precision;
- out.buffer = in.buffer;
- out.start = in.start;
- boolean sign = in.getSign(in.start, in.buffer);
-
- boolean roundUp = false;
-
- // Get the first fractional digit to see if want to round up or not
- int scaleIndex = ${type.storage} - org.apache.drill.exec.util.DecimalUtility.roundUp(in.scale);
- if (scaleIndex < ${type.storage}) {
- int fractionalPart = out.getInteger(scaleIndex, out.start, out.buffer);
- int digit = fractionalPart / (org.apache.drill.exec.util.DecimalUtility.DIGITS_BASE / 10);
-
- if (digit > 4) {
- roundUp = true;
- }
- }
-
- // Integer part's src index
- int srcIntIndex = scaleIndex - 1;
-
- // Truncate the fractional part, move the integer part
- int destIndex = ${type.storage} - 1;
- while (srcIntIndex >= 0) {
- out.setInteger(destIndex--, out.getInteger(srcIntIndex--, out.start, out.buffer), out.start, out.buffer);
- }
-
- // Set the remaining portion of the decimal to be zeroes
- while (destIndex >= 0) {
- out.setInteger(destIndex--, 0, out.start, out.buffer);
- }
+ @FunctionTemplate(name = "round",
+ scope = FunctionTemplate.FunctionScope.SIMPLE,
+ returnType = FunctionTemplate.ReturnType.DECIMAL_SET_SCALE,
+ nulls = NullHandling.NULL_IF_NULL)
+ public static class ${type.name}RoundScaleFunction implements DrillSimpleFunc {
+ @Param ${type.name}Holder left;
+ @Param IntHolder right;
+ @Output ${type.name}Holder result;
+ @Inject DrillBuf buffer;
- // Perform the roundup
- srcIntIndex = ${type.storage} - 1;
- if (roundUp == true) {
- while (srcIntIndex >= 0) {
- int value = out.getInteger(srcIntIndex, out.start, out.buffer) + 1;
- if (value >= org.apache.drill.exec.util.DecimalUtility.DIGITS_BASE) {
- out.setInteger(srcIntIndex--, value % org.apache.drill.exec.util.DecimalUtility.DIGITS_BASE, out.start, out.buffer);
- value = value / org.apache.drill.exec.util.DecimalUtility.DIGITS_BASE;
- } else {
- out.setInteger(srcIntIndex--, value, out.start, out.buffer);
- break;
- }
- }
- }
- // Set the sign
- out.setSign(sign, out.start, out.buffer);
- }
+ public void setup() {
}
- @FunctionTemplate(name = "round",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_SET_SCALE,
- nulls = NullHandling.NULL_IF_NULL)
- public static class ${type.name}RoundScaleFunction implements DrillSimpleFunc {
-
- @Param ${type.name}Holder left;
- @Param IntHolder right;
- @Output ${type.name}Holder result;
- public void setup() {
-
- }
-
- public void eval() {
- result.scale = right.value;
- result.precision = left.precision;
- result.buffer = left.buffer;
- result.start = left.start;
- boolean sign = left.getSign(left.start, left.buffer);
-
- org.apache.drill.exec.util.DecimalUtility.roundDecimal(result.buffer, result.start, result.nDecimalDigits, result.scale, left.scale);
- // Set the sign
- result.setSign(sign, result.start, result.buffer);
- }
+ public void eval() {
+ result.scale = right.value;
+ result.precision = left.precision;
+ result.start = 0;
+ java.math.BigDecimal bd =
+ org.apache.drill.exec.util.DecimalUtility
+ .getBigDecimalFromDrillBuf(left.buffer, left.start, left.end - left.start, left.scale)
+ .setScale(result.scale, java.math.BigDecimal.ROUND_HALF_UP);
+ byte[] bytes = bd.unscaledValue().toByteArray();
+ int len = bytes.length;
+ result.buffer = buffer.reallocIfNeeded(len);
+ result.buffer.setBytes(0, bytes);
+ result.end = len;
}
+ }
- <#-- Handle 2 x 2 combinations of nullable and non-nullable arguments. -->
- <#list ["Nullable${type.name}", "${type.name}"] as leftType >
- <#list ["Nullable${type.name}", "${type.name}"] as rightType >
+ <#-- Handle 2 x 2 combinations of nullable and non-nullable arguments. -->
+ <#list ["Nullable${type.name}", "${type.name}"] as leftType >
+ <#list ["Nullable${type.name}", "${type.name}"] as rightType >
<#-- Comparison function for sorting and grouping relational operators
(not for comparison expression operators (=, <, etc.)). -->
@FunctionTemplate(name = FunctionGenerationHelper.COMPARE_TO_NULLS_HIGH,
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_MAX_SCALE,
- nulls = NullHandling.INTERNAL)
+ scope = FunctionTemplate.FunctionScope.SIMPLE,
+ returnType = FunctionTemplate.ReturnType.DECIMAL_MAX_SCALE,
+ nulls = NullHandling.INTERNAL)
public static class GCompare${leftType}Vs${rightType}NullHigh implements DrillSimpleFunc {
@Param ${leftType}Holder left;
@@ -1513,7 +342,7 @@ public class ${type.name}Functions {
public void setup() {}
public void eval() {
- <@compareBlock leftType=leftType rightType=rightType absCompare="false" output="out.value" nullCompare=true nullComparesHigh=true />
+ <@varCompareBlock leftType = leftType rightType = rightType absCompare="false" output = "out.value" nullCompare = true nullComparesHigh = true />
}
}
@@ -1522,9 +351,9 @@ public class ${type.name}Functions {
<#-- Comparison function for sorting and grouping relational operators
(not for comparison expression operators (=, <, etc.)). -->
@FunctionTemplate(name = FunctionGenerationHelper.COMPARE_TO_NULLS_LOW,
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_MAX_SCALE,
- nulls = NullHandling.INTERNAL)
+ scope = FunctionTemplate.FunctionScope.SIMPLE,
+ returnType = FunctionTemplate.ReturnType.DECIMAL_MAX_SCALE,
+ nulls = NullHandling.INTERNAL)
public static class GCompare${leftType}Vs${rightType}NullLow implements DrillSimpleFunc {
@Param ${leftType}Holder left;
@@ -1534,937 +363,132 @@ public class ${type.name}Functions {
public void setup() {}
public void eval() {
- <@compareBlock leftType=leftType rightType=rightType absCompare="false" output="out.value" nullCompare=true nullComparesHigh=false />
+ <@varCompareBlock leftType = leftType rightType = rightType absCompare = "false" output = "out.value" nullCompare = true nullComparesHigh = false />
}
}
- </#list>
- </#list>
+ </#list>
+ </#list>
-
- <#-- Comparison function for comparison expression operator (=, &lt;, etc.),
- not for sorting and grouping relational operators.) -->
- @FunctionTemplate(name = "less than",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_MAX_SCALE,
- nulls = NullHandling.NULL_IF_NULL)
- public static class ${type.name}LessThan implements DrillSimpleFunc {
-
- @Param ${type.name}Holder left;
- @Param ${type.name}Holder right;
- @Output BitHolder out;
- public void setup() {}
-
- public void eval() {
- int cmp;
- <@compareBlock leftType="leftType" rightType="rightType" absCompare="false" output="cmp" nullCompare=false nullComparesHigh=false />
- out.value = cmp == -1 ? 1 : 0;
- }
- }
-
-
- // TODO: RESOLVE: Here there are spaces in function template names, but
- // elsewhere there are underlines. Are things being looked up correctly?
- <#-- Comparison function for comparison expression operator (=, &lt;, etc.),
+ <#-- Comparison function for comparison expression operator (=, &lt;, etc.),
not for sorting and grouping relational operators.) -->
- @FunctionTemplate(name = "less than or equal to",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_MAX_SCALE,
- nulls = NullHandling.NULL_IF_NULL)
- public static class ${type.name}LessThanEq implements DrillSimpleFunc {
-
- @Param ${type.name}Holder left;
- @Param ${type.name}Holder right;
- @Output BitHolder out;
- public void setup() {}
-
- public void eval() {
- int cmp;
- <@compareBlock leftType="leftType" rightType="rightType" absCompare="false" output="cmp" nullCompare=false nullComparesHigh=false />
- out.value = cmp < 1 ? 1 : 0;
- }
- }
-
-
- <#-- Comparison function for comparison expression operator (=, &lt;, etc.),
- not for sorting and grouping relational operators.) -->
- @FunctionTemplate(name = "greater than",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_MAX_SCALE,
- nulls = NullHandling.NULL_IF_NULL)
- public static class ${type.name}GreaterThan implements DrillSimpleFunc {
-
- @Param ${type.name}Holder left;
- @Param ${type.name}Holder right;
- @Output BitHolder out;
- public void setup() {}
-
- public void eval() {
- int cmp;
- <@compareBlock leftType="leftType" rightType="rightType" absCompare="false" output="cmp" nullCompare=false nullComparesHigh=false />
- out.value = cmp == 1 ? 1 : 0;
- }
- }
-
-
- <#-- Comparison function for comparison expression operator (=, &lt;, etc.),
- not for sorting and grouping relational operators.) -->
- @FunctionTemplate(name = "greater than or equal to",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_MAX_SCALE,
- nulls = NullHandling.NULL_IF_NULL)
- public static class ${type.name}GreaterThanEq implements DrillSimpleFunc {
-
- @Param ${type.name}Holder left;
- @Param ${type.name}Holder right;
- @Output BitHolder out;
- public void setup() {}
-
- public void eval() {
- int cmp;
- <@compareBlock leftType="leftType" rightType="rightType" absCompare="false" output="cmp" nullCompare=false nullComparesHigh=false />
- out.value = cmp > -1 ? 1 : 0;
- }
- }
-
-
- <#-- Comparison function for comparison expression operator (=, &lt;, etc.),
- not for sorting and grouping relational operators.) -->
- @FunctionTemplate(name = "Equal",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_MAX_SCALE,
- nulls = NullHandling.NULL_IF_NULL)
- public static class ${type.name}Equal implements DrillSimpleFunc {
-
- @Param ${type.name}Holder left;
- @Param ${type.name}Holder right;
- @Output BitHolder out;
- public void setup() {}
-
- public void eval() {
- int cmp;
- <@compareBlock leftType="leftType" rightType="rightType" absCompare="false" output="cmp" nullCompare=false nullComparesHigh=false />
- out.value = cmp == 0 ? 1 : 0;
- }
- }
-
-
- <#-- Comparison function for comparison expression operator (=, &lt;, etc.),
- not for sorting and grouping relational operators.) -->
- @FunctionTemplate(name = "not equal",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_MAX_SCALE,
- nulls = NullHandling.NULL_IF_NULL)
- public static class ${type.name}NotEqual implements DrillSimpleFunc {
-
- @Param ${type.name}Holder left;
- @Param ${type.name}Holder right;
- @Output BitHolder out;
- public void setup() {}
-
- public void eval() {
- int cmp;
- <@compareBlock leftType="leftType" rightType="rightType" absCompare="false" output="cmp" nullCompare=false nullComparesHigh=false />
- out.value = cmp != 0 ? 1 : 0;
- }
- }
-}
-
-<#elseif type.name.endsWith("Dense")>
-
-<@pp.changeOutputFile name="/org/apache/drill/exec/expr/fn/impl/${type.name}Functions.java" />
-
-<#include "/@includes/license.ftl" />
-
-package org.apache.drill.exec.expr.fn.impl;
-
-<#include "/@includes/vv_imports.ftl" />
-
-import org.apache.drill.exec.expr.DrillSimpleFunc;
-import org.apache.drill.exec.expr.annotations.FunctionTemplate;
-import org.apache.drill.exec.expr.annotations.FunctionTemplate.NullHandling;
-import org.apache.drill.exec.expr.annotations.Output;
-import org.apache.drill.exec.expr.annotations.Param;
-import org.apache.drill.exec.expr.fn.FunctionGenerationHelper;
-import org.apache.drill.exec.expr.holders.*;
-import org.apache.drill.exec.record.RecordBatch;
-
-import io.netty.buffer.ByteBuf;
-
-import java.nio.ByteBuffer;
-
-/*
- * This class is generated using freemarker and the ${.template_name} template.
- */
-
-@SuppressWarnings("unused")
-public class ${type.name}Functions {
-
-
- <#-- Handle 2 x 2 combinations of nullable and non-nullable arguments. -->
- <#list ["Nullable${type.name}", "${type.name}"] as leftType >
- <#list ["Nullable${type.name}", "${type.name}"] as rightType >
-
- <#-- Comparison function for sorting and grouping relational operators
- (not for comparison expression operators (=, <, etc.)). -->
- @FunctionTemplate(name = FunctionGenerationHelper.COMPARE_TO_NULLS_HIGH,
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_MAX_SCALE,
- nulls = NullHandling.INTERNAL)
- public static class GCompare${leftType}Vs${rightType}NullHigh implements DrillSimpleFunc {
-
- @Param ${leftType}Holder left;
- @Param ${rightType}Holder right;
- @Output IntHolder out;
-
+ @FunctionTemplate(name = FunctionGenerationHelper.LT,
+ scope = FunctionTemplate.FunctionScope.SIMPLE,
+ nulls = NullHandling.NULL_IF_NULL)
+ public static class ${type.name}LessThan implements DrillSimpleFunc {
+
+ @Param ${type.name}Holder left;
+ @Param ${type.name}Holder right;
+ @Output BitHolder out;
public void setup() {}
public void eval() {
- outside:
- {
- <@compareNullsSubblock leftType=leftType rightType=rightType output="out.value" breakTarget="outside" nullCompare=true nullComparesHigh=true />
-
- out.value = org.apache.drill.exec.util.DecimalUtility.compareDenseBytes(left.buffer, left.start, left.getSign(left.start, left.buffer), right.buffer, right.start, right.getSign(right.start, right.buffer), left.WIDTH);
- } // outside
+ int cmp;
+ <@varCompareBlock leftType = "leftType" rightType = "rightType" absCompare = "false" output = "cmp" nullCompare = false nullComparesHigh = false />
+ out.value = cmp == -1 ? 1 : 0;
}
}
- <#-- Comparison function for sorting and grouping relational operators
- (not for comparison expression operators (=, <, etc.)). -->
- @FunctionTemplate(name = FunctionGenerationHelper.COMPARE_TO_NULLS_LOW,
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_MAX_SCALE,
- nulls = NullHandling.INTERNAL)
- public static class GCompare${leftType}Vs${rightType}NullLow implements DrillSimpleFunc {
+ <#-- Comparison function for comparison expression operator (=, &lt;, etc.),
+ not for sorting and grouping relational operators.) -->
+ @FunctionTemplate(name = FunctionGenerationHelper.LE,
+ scope = FunctionTemplate.FunctionScope.SIMPLE,
+ nulls = NullHandling.NULL_IF_NULL)
+ public static class ${type.name}LessThanEq implements DrillSimpleFunc {
- @Param ${leftType}Holder left;
- @Param ${rightType}Holder right;
- @Output IntHolder out;
+ @Param ${type.name}Holder left;
+ @Param ${type.name}Holder right;
+ @Output BitHolder out;
public void setup() {}
public void eval() {
- outside:
- {
- <@compareNullsSubblock leftType=leftType rightType=rightType output="out.value" breakTarget="outside" nullCompare=true nullComparesHigh=false />
-
- out.value = org.apache.drill.exec.util.DecimalUtility.compareDenseBytes(left.buffer, left.start, left.getSign(left.start, left.buffer), right.buffer, right.start, right.getSign(right.start, right.buffer), left.WIDTH);
- } // outside
+ int cmp;
+ <@varCompareBlock leftType = "leftType" rightType = "rightType" absCompare = "false" output = "cmp" nullCompare = false nullComparesHigh = false />
+ out.value = cmp < 1 ? 1 : 0;
}
}
- </#list>
- </#list>
-
-
- <#-- Comparison function for comparison expression operator (=, &lt;, etc.),
+ <#-- Comparison function for comparison expression operator (=, &lt;, etc.),
not for sorting and grouping relational operators.) -->
- @FunctionTemplate(name = "less than",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_MAX_SCALE,
- nulls = NullHandling.NULL_IF_NULL)
- public static class ${type.name}LessThan implements DrillSimpleFunc {
-
- @Param ${type.name}Holder left;
- @Param ${type.name}Holder right;
- @Output BitHolder out;
- public void setup() {}
-
- public void eval() {
- int cmp = org.apache.drill.exec.util.DecimalUtility.compareDenseBytes(left.buffer, left.start, left.getSign(left.start, left.buffer), right.buffer, right.start, right.getSign(right.start, right.buffer), left.WIDTH);
- out.value = cmp == -1 ? 1 : 0;
- }
- }
-
- <#-- Comparison function for comparison expression operator (=, &lt;, etc.),
- not for sorting and grouping relational operators.) -->
- @FunctionTemplate(name = "less than or equal to",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_MAX_SCALE,
- nulls = NullHandling.NULL_IF_NULL)
- public static class ${type.name}LessThanEq implements DrillSimpleFunc {
-
- @Param ${type.name}Holder left;
- @Param ${type.name}Holder right;
- @Output BitHolder out;
- public void setup() {}
-
- public void eval() {
- int cmp = org.apache.drill.exec.util.DecimalUtility.compareDenseBytes(left.buffer, left.start, left.getSign(left.start, left.buffer), right.buffer, right.start, right.getSign(right.start, right.buffer), left.WIDTH);
- out.value = cmp < 1 ? 1 : 0;
- }
- }
+ @FunctionTemplate(name = FunctionGenerationHelper.GT,
+ scope = FunctionTemplate.FunctionScope.SIMPLE,
+ nulls = NullHandling.NULL_IF_NULL)
+ public static class ${type.name}GreaterThan implements DrillSimpleFunc {
- <#-- Comparison function for comparison expression operator (=, &lt;, etc.),
- not for sorting and grouping relational operators.) -->
- @FunctionTemplate(name = "greater than",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_MAX_SCALE,
- nulls = NullHandling.NULL_IF_NULL)
- public static class ${type.name}GreaterThan implements DrillSimpleFunc {
-
- @Param ${type.name}Holder left;
- @Param ${type.name}Holder right;
- @Output BitHolder out;
- public void setup() {}
-
- public void eval() {
- int cmp = org.apache.drill.exec.util.DecimalUtility.compareDenseBytes(left.buffer, left.start, left.getSign(left.start, left.buffer), right.buffer, right.start, right.getSign(right.start, right.buffer), left.WIDTH);
- out.value = cmp == 1 ? 1 : 0;
- }
- }
+ @Param ${type.name}Holder left;
+ @Param ${type.name}Holder right;
+ @Output BitHolder out;
- <#-- Comparison function for comparison expression operator (=, &lt;, etc.),
- not for sorting and grouping relational operators.) -->
- @FunctionTemplate(name = "greater than or equal to",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_MAX_SCALE,
- nulls = NullHandling.NULL_IF_NULL)
- public static class ${type.name}GreaterThanEq implements DrillSimpleFunc {
-
- @Param ${type.name}Holder left;
- @Param ${type.name}Holder right;
- @Output BitHolder out;
- public void setup() {}
-
- public void eval() {
- int cmp = org.apache.drill.exec.util.DecimalUtility.compareDenseBytes(left.buffer, left.start, left.getSign(left.start, left.buffer), right.buffer, right.start, right.getSign(right.start, right.buffer), left.WIDTH);
- out.value = cmp > -1 ? 1 : 0;
- }
- }
+ public void setup() {}
- <#-- Comparison function for comparison expression operator (=, &lt;, etc.),
- not for sorting and grouping relational operators.) -->
- @FunctionTemplate(name = "Equal",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_MAX_SCALE,
- nulls = NullHandling.NULL_IF_NULL)
- public static class ${type.name}Equal implements DrillSimpleFunc {
-
- @Param ${type.name}Holder left;
- @Param ${type.name}Holder right;
- @Output BitHolder out;
- public void setup() {}
-
- public void eval() {
- int cmp = org.apache.drill.exec.util.DecimalUtility.compareDenseBytes(left.buffer, left.start, left.getSign(left.start, left.buffer), right.buffer, right.start, right.getSign(right.start, right.buffer), left.WIDTH);
- out.value = cmp == 0 ? 1 : 0;
- }
+ public void eval() {
+ int cmp;
+ <@varCompareBlock leftType = "leftType" rightType = "rightType" absCompare = "false" output = "cmp" nullCompare = false nullComparesHigh = false />
+ out.value = cmp == 1 ? 1 : 0;
}
+ }
-
- <#-- Comparison function for comparison expression operator (=, &lt;, etc.),
+ <#-- Comparison function for comparison expression operator (=, &lt;, etc.),
not for sorting and grouping relational operators.) -->
- @FunctionTemplate(name = "not equal",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_MAX_SCALE,
- nulls = NullHandling.NULL_IF_NULL)
- public static class ${type.name}NotEqual implements DrillSimpleFunc {
-
- @Param ${type.name}Holder left;
- @Param ${type.name}Holder right;
- @Output BitHolder out;
- public void setup() {}
-
- public void eval() {
-
- int cmp = org.apache.drill.exec.util.DecimalUtility.compareDenseBytes(left.buffer, left.start, left.getSign(left.start, left.buffer), right.buffer, right.start, right.getSign(right.start, right.buffer), left.WIDTH);
- out.value = cmp != 0 ? 1 : 0;
- }
- }
-}
-
-<#elseif type.name.endsWith("Decimal9") || type.name.endsWith("Decimal18")>
-
-<@pp.changeOutputFile name="/org/apache/drill/exec/expr/fn/impl/${type.name}Functions.java" />
-
-<#include "/@includes/license.ftl" />
-
-package org.apache.drill.exec.expr.fn.impl;
-
-<#include "/@includes/vv_imports.ftl" />
-
-import org.apache.drill.exec.expr.DrillSimpleFunc;
-import org.apache.drill.exec.expr.annotations.FunctionTemplate;
-import org.apache.drill.exec.expr.annotations.FunctionTemplate.NullHandling;
-import org.apache.drill.exec.expr.annotations.Output;
-import org.apache.drill.exec.expr.annotations.Param;
-import org.apache.drill.exec.expr.annotations.Workspace;
-import org.apache.drill.exec.expr.fn.FunctionGenerationHelper;
-import org.apache.drill.exec.expr.holders.*;
-import org.apache.drill.exec.record.RecordBatch;
-
-import io.netty.buffer.ByteBuf;
-
-import java.nio.ByteBuffer;
-
-@SuppressWarnings("unused")
-public class ${type.name}Functions {
-
- @FunctionTemplate(name = "add",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_ADD_SCALE,
- nulls = NullHandling.NULL_IF_NULL,
- checkPrecisionRange = true)
- public static class ${type.name}AddFunction implements DrillSimpleFunc {
-
- @Param ${type.name}Holder left;
- @Param ${type.name}Holder right;
- @Workspace int outputScale;
- @Workspace int outputPrecision;
- @Output ${type.name}Holder result;
-
- public void setup() {
- outputPrecision = Integer.MIN_VALUE;
- }
-
-
- public void eval() {
- if (outputPrecision == Integer.MIN_VALUE) {
- org.apache.drill.common.util.DecimalScalePrecisionAddFunction resultScalePrec =
- new org.apache.drill.common.util.DecimalScalePrecisionAddFunction((int) left.precision, (int) left.scale, (int) right.precision, (int) right.scale);
- outputScale = resultScalePrec.getOutputScale();
- outputPrecision = resultScalePrec.getOutputPrecision();
- }
- <@adjustScale javaType=type.storage leftType="leftType" rightType="rightType"/>
-
- result.value = left.value + right.value;
- result.precision = outputPrecision;
- result.scale = outputScale;
- }
- }
-
- @FunctionTemplate(name = "subtract",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_ADD_SCALE,
- nulls = NullHandling.NULL_IF_NULL,
- checkPrecisionRange = true)
- public static class ${type.name}SubtractFunction implements DrillSimpleFunc {
-
- @Param ${type.name}Holder left;
- @Param ${type.name}Holder right;
- @Workspace int outputScale;
- @Workspace int outputPrecision;
- @Output ${type.name}Holder result;
-
- public void setup() {
- outputPrecision = Integer.MIN_VALUE;
- }
-
- public void eval() {
- if (outputPrecision == Integer.MIN_VALUE) {
- org.apache.drill.common.util.DecimalScalePrecisionAddFunction resultScalePrec =
- new org.apache.drill.common.util.DecimalScalePrecisionAddFunction((int) left.precision, (int) left.scale, (int) right.precision, (int) right.scale);
- outputScale = resultScalePrec.getOutputScale();
- outputPrecision = resultScalePrec.getOutputPrecision();
- }
- <@adjustScale javaType=type.storage leftType="leftType" rightType="rightType"/>
-
- result.value = left.value - right.value;
- result.precision = outputPrecision;
- result.scale = outputScale;
- }
- }
-
- @FunctionTemplate(name = "multiply",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_SUM_SCALE,
- nulls = NullHandling.NULL_IF_NULL,
- checkPrecisionRange = true)
- public static class ${type.name}MultiplyFunction implements DrillSimpleFunc {
-
- @Param ${type.name}Holder left;
- @Param ${type.name}Holder right;
- @Workspace int outputScale;
- @Workspace int outputPrecision;
- @Output ${type.name}Holder result;
-
- public void setup() {
- outputPrecision = Integer.MIN_VALUE;
- }
-
- public void eval() {
- if (outputPrecision == Integer.MIN_VALUE) {
- org.apache.drill.common.util.DecimalScalePrecisionMulFunction resultScalePrec =
- new org.apache.drill.common.util.DecimalScalePrecisionMulFunction((int) left.precision, (int) left.scale, (int) right.precision, (int) right.scale);
- outputScale = resultScalePrec.getOutputScale();
- outputPrecision = resultScalePrec.getOutputPrecision();
- }
- result.value = left.value * right.value;
- result.precision = outputPrecision;
- result.scale = outputScale;
- }
- }
-
- @FunctionTemplate(name = "abs",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_MAX_SCALE,
- nulls = NullHandling.NULL_IF_NULL)
- public static class ${type.name}AbsFunction implements DrillSimpleFunc {
-
- @Param ${type.name}Holder in;
- @Output ${type.name}Holder out;
-
- public void setup() {}
-
- public void eval() {
- out.precision = out.maxPrecision;
- out.scale = in.scale;
-
- out.value = in.value;
-
- if (out.value < 0){
- out.value *= -1;
- }
- }
- }
-
- @FunctionTemplate(name = "exact_divide",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_DIV_SCALE,
- nulls = NullHandling.NULL_IF_NULL,
- checkPrecisionRange = true)
- public static class ${type.name}DivideFunction implements DrillSimpleFunc {
-
- @Param ${type.name}Holder left;
- @Param ${type.name}Holder right;
- @Output ${type.name}Holder result;
- @Workspace int outputScale;
- @Workspace int outputPrecision;
-
- public void setup() {
- outputPrecision = Integer.MIN_VALUE;
- }
-
- public void eval() {
-
- if (outputPrecision == Integer.MIN_VALUE) {
- org.apache.drill.common.util.DecimalScalePrecisionDivideFunction resultScalePrec =
- new org.apache.drill.common.util.DecimalScalePrecisionDivideFunction((int) left.precision, (int) left.scale, (int) right.precision, (int) right.scale);
- outputScale = resultScalePrec.getOutputScale();
- outputPrecision = resultScalePrec.getOutputPrecision();
- }
- result.scale = outputScale;
- result.precision = outputPrecision;
-
- java.math.BigDecimal numerator = new java.math.BigDecimal(java.math.BigInteger.valueOf(left.value), left.scale);
- java.math.BigDecimal denominator = new java.math.BigDecimal(java.math.BigInteger.valueOf(right.value), right.scale);
-
- java.math.BigDecimal output = numerator.divide(denominator, (int) result.scale, java.math.BigDecimal.ROUND_HALF_UP);
-
- result.value = output.unscaledValue().${type.storage}Value();
- }
- }
-
- @FunctionTemplate(name = "mod",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_MOD_SCALE,
- nulls = NullHandling.NULL_IF_NULL,
- checkPrecisionRange = true)
- public static class ${type.name}ModFunction implements DrillSimpleFunc {
-
- @Param ${type.name}Holder left;
- @Param ${type.name}Holder right;
- @Workspace int outputScale;
- @Workspace int outputPrecision;
- @Output ${type.name}Holder result;
-
- public void setup() {
- outputPrecision = Integer.MIN_VALUE;
- }
-
- public void eval() {
- if (outputPrecision == Integer.MIN_VALUE) {
- org.apache.drill.common.util.DecimalScalePrecisionModFunction resultScalePrec =
- new org.apache.drill.common.util.DecimalScalePrecisionModFunction((int) left.precision, (int) left.scale, (int) right.precision, (int) right.scale);
- outputScale = resultScalePrec.getOutputScale();
- outputPrecision = resultScalePrec.getOutputPrecision();
- }
- result.precision = outputPrecision;
- result.scale = outputScale;
- java.math.BigDecimal numerator = new java.math.BigDecimal(java.math.BigInteger.valueOf(left.value), left.scale);
- java.math.BigDecimal denominator = new java.math.BigDecimal(java.math.BigInteger.valueOf(right.value), right.scale);
-
- java.math.BigDecimal output = numerator.remainder(denominator);
- output.setScale(result.scale, java.math.BigDecimal.ROUND_HALF_UP);
-
- result.value = output.unscaledValue().${type.storage}Value();
- }
- }
-
- @FunctionTemplate(name = "sign", scope = FunctionTemplate.FunctionScope.SIMPLE, nulls = NullHandling.NULL_IF_NULL)
- public static class ${type.name}SignFunction implements DrillSimpleFunc {
-
- @Param ${type.name}Holder in;
- @Output IntHolder out;
-
- public void setup() {}
-
- public void eval() {
-
- out.value = (in.value < 0) ? -1 : ((in.value > 0) ? 1 : 0);
- }
- }
-
- @FunctionTemplate(names = {"trunc", "truncate"},
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_ZERO_SCALE,
- nulls = NullHandling.NULL_IF_NULL)
- public static class ${type.name}TruncFunction implements DrillSimpleFunc {
-
- @Param ${type.name}Holder in;
- @Output ${type.name}Holder out;
-
- public void setup() {}
-
- public void eval() {
-
- out.value =(${type.storage}) (org.apache.drill.exec.util.DecimalUtility.adjustScaleDivide(in.value, (int) in.scale));
- out.precision = out.maxPrecision;
- out.scale = 0;
- }
- }
-
- @FunctionTemplate(names = {"trunc", "truncate"},
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_SET_SCALE,
- nulls = NullHandling.NULL_IF_NULL)
- public static class ${type.name}TruncateScaleFunction implements DrillSimpleFunc {
-
- @Param ${type.name}Holder left;
- @Param IntHolder right;
- @Output ${type.name}Holder out;
-
- public void setup() {}
-
- public void eval() {
-
- out.value = (${type.storage}) (org.apache.drill.exec.util.DecimalUtility.adjustScaleDivide(left.value, (int) (left.scale - right.value)));
- out.precision = out.maxPrecision;
- out.scale = right.value;
- }
- }
-
- @FunctionTemplate(names = {"ceil", "ceiling"},
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_ZERO_SCALE,
- nulls = NullHandling.NULL_IF_NULL)
- public static class ${type.name}CeilFunction implements DrillSimpleFunc {
-
- @Param ${type.name}Holder in;
- @Output ${type.name}Holder out;
-
- public void setup() {
-
- }
-
- public void eval() {
- ${type.storage} scaleFactor = (${type.storage}) (org.apache.drill.exec.util.DecimalUtility.getPowerOfTen((int) in.scale));
-
- // Get the integer part
- ${type.storage} integerPart = in.value / scaleFactor;
-
- // Get the fractional part, if its non-zero increment the integer part
- ${type.storage} fractionalPart = (${type.storage}) (in.value % scaleFactor);
- if (fractionalPart != 0 && in.value >= 0) {
- integerPart++;
- }
-
- out.scale = 0;
- out.value = integerPart;
- }
- }
-
- @FunctionTemplate(name = "floor",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_ZERO_SCALE,
- nulls = NullHandling.NULL_IF_NULL)
- public static class ${type.name}FloorFunction implements DrillSimpleFunc {
-
- @Param ${type.name}Holder in;
- @Output ${type.name}Holder out;
-
- public void setup() {
- }
-
- public void eval() {
-
- ${type.storage} scaleFactor = (${type.storage}) (org.apache.drill.exec.util.DecimalUtility.getPowerOfTen((int) in.scale));
- out.scale = 0;
- out.value = (in.value / scaleFactor);
-
- // For negative values we have to decrement by 1
- if (in.value < 0) {
- ${type.storage} fractionalPart = (${type.storage}) (in.value % scaleFactor);
- if (fractionalPart != 0) {
- out.value--;
- }
- }
- }
- }
-
- @FunctionTemplate(name = "round",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_ZERO_SCALE,
- nulls = NullHandling.NULL_IF_NULL)
- public static class ${type.name}RoundFunction implements DrillSimpleFunc {
+ @FunctionTemplate(name = FunctionGenerationHelper.GE,
+ scope = FunctionTemplate.FunctionScope.SIMPLE,
+ nulls = NullHandling.NULL_IF_NULL)
+ public static class ${type.name}GreaterThanEq implements DrillSimpleFunc {
- @Param ${type.name}Holder in;
- @Output ${type.name}Holder out;
-
- public void setup() {
- }
-
- public void eval() {
-
- ${type.storage} scaleFactor = (${type.storage}) (org.apache.drill.exec.util.DecimalUtility.getPowerOfTen((int) in.scale));
- ${type.storage} extractDigit = scaleFactor / 10;
-
- out.scale = 0;
- // Assign the integer part to the output
- out.value = in.value / scaleFactor;
-
- // Get the fractional part
- ${type.storage} fractionalPart = in.value % scaleFactor;
- // Get the first digit to check for rounding
- int digit = Math.abs((int) (fractionalPart / extractDigit));
-
- if (digit > 4) {
- if (in.value > 0) {
- out.value++;
- } else if (in.value < 0) {
- out.value--;
- }
- }
- }
- }
-
- @FunctionTemplate(name = "round",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_SET_SCALE,
- nulls = NullHandling.NULL_IF_NULL)
- public static class ${type.name}RoundScaleFunction implements DrillSimpleFunc {
-
- @Param ${type.name}Holder left;
- @Param IntHolder right;
- @Output ${type.name}Holder out;
-
-
- public void setup() {
- }
-
- public void eval() {
-
- ${type.storage} scaleFactor = (${type.storage}) (org.apache.drill.exec.util.DecimalUtility.getPowerOfTen((int) left.scale));
- ${type.storage} newScaleFactor = (${type.storage}) (org.apache.drill.exec.util.DecimalUtility.getPowerOfTen((int) right.value));
- ${type.storage} truncScaleFactor = (${type.storage}) (org.apache.drill.exec.util.DecimalUtility.getPowerOfTen( Math.abs(left.scale - right.value)));
- int truncFactor = (int) (left.scale - right.value);
-
- // If rounding scale is >= current scale
- if (right.value >= left.scale) {
- out.value = (${type.storage}) (org.apache.drill.exec.util.DecimalUtility.adjustScaleMultiply(left.value, (int) (right.value - left.scale)));
- }
- else {
- out.scale = right.value;
- // Assign the integer part to the output
- out.value = left.value / scaleFactor;
-
- // Get the fractional part
- ${type.storage} fractionalPart = left.value % scaleFactor;
-
- // From the entire fractional part extract the digits upto which rounding is needed
- ${type.storage} newFractionalPart = (${type.storage}) (org.apache.drill.exec.util.DecimalUtility.adjustScaleDivide(fractionalPart, truncFactor));
- ${type.storage} truncatedFraction = fractionalPart % truncScaleFactor;
-
-
- // Get the truncated fractional part and extract the first digit to see if we need to add 1
- int digit = Math.abs((int) org.apache.drill.exec.util.DecimalUtility.adjustScaleDivide(truncatedFraction, truncFactor - 1));
-
- if (digit > 4) {
- if (left.value > 0) {
- newFractionalPart++;
- } else if (left.value < 0) {
- newFractionalPart--;
- }
- }
-
- out.value = (out.value * newScaleFactor) + newFractionalPart;
- }
- }
- }
-
- <#-- Handle 2 x 2 combinations of nullable and non-nullable arguments. -->
- <#list ["Nullable${type.name}", "${type.name}"] as leftType >
- <#list ["Nullable${type.name}", "${type.name}"] as rightType >
-
- <#-- Comparison function for sorting and grouping relational operators
- (not for comparison expression operators (=, <, etc.)). -->
- @FunctionTemplate(name = FunctionGenerationHelper.COMPARE_TO_NULLS_HIGH,
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_MAX_SCALE,
- nulls = NullHandling.INTERNAL)
- public static class GCompare${leftType}Vs${rightType}NullHigh implements DrillSimpleFunc {
-
- @Param ${leftType}Holder left;
- @Param ${rightType}Holder right;
- @Output IntHolder out;
+ @Param ${type.name}Holder left;
+ @Param ${type.name}Holder right;
+ @Output BitHolder out;
public void setup() {}
public void eval() {
- outside:
- {
- <@compareNullsSubblock leftType=leftType rightType=rightType output="out.value" breakTarget="outside" nullCompare=true nullComparesHigh=true />
-
- <@adjustScale javaType=type.storage leftType="leftType" rightType="rightType"/>
- out.value = (left.value < right.value) ? -1 : (left.value > right.value) ? 1 : 0;
- } // outside
+ int cmp;
+ <@varCompareBlock leftType = "leftType" rightType = "rightType" absCompare = "false" output = "cmp" nullCompare = false nullComparesHigh = false />
+ out.value = cmp > -1 ? 1 : 0;
}
}
- <#-- Comparison function for sorting and grouping relational operators
- (not for comparison expression operators (=, <, etc.)). -->
- @FunctionTemplate(name = FunctionGenerationHelper.COMPARE_TO_NULLS_LOW,
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_MAX_SCALE,
- nulls = NullHandling.INTERNAL)
- public static class GCompare${leftType}Vs${rightType}NullLow implements DrillSimpleFunc {
+ <#-- Comparison function for comparison expression operator (=, &lt;, etc.),
+ not for sorting and grouping relational operators.) -->
+ @FunctionTemplate(name = FunctionGenerationHelper.EQ,
+ scope = FunctionTemplate.FunctionScope.SIMPLE,
+ nulls = NullHandling.NULL_IF_NULL)
+ public static class ${type.name}Equal implements DrillSimpleFunc {
- @Param ${leftType}Holder left;
- @Param ${rightType}Holder right;
- @Output IntHolder out;
+ @Param ${type.name}Holder left;
+ @Param ${type.name}Holder right;
+ @Output BitHolder out;
public void setup() {}
public void eval() {
- outside:
- {
- <@compareNullsSubblock leftType=leftType rightType=rightType output="out.value" breakTarget="outside" nullCompare=true nullComparesHigh=false />
- <@adjustScale javaType=type.storage leftType="leftType" rightType="rightType"/>
- out.value = (left.value < right.value) ? -1 : (left.value > right.value) ? 1 : 0;
- } // outside
+ int cmp;
+ <@varCompareBlock leftType = "leftType" rightType = "rightType" absCompare = "false" output = "cmp" nullCompare = false nullComparesHigh = false />
+ out.value = cmp == 0 ? 1 : 0;
}
}
- </#list>
- </#list>
-
- <#-- Comparison function for comparison expression operator (=, &lt;, etc.),
+ <#-- Comparison function for comparison expression operator (=, &lt;, etc.),
not for sorting and grouping relational operators.) -->
- @FunctionTemplate(name = "less than",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_MAX_SCALE,
- nulls = NullHandling.NULL_IF_NULL)
- public static class ${type.name}LessThan implements DrillSimpleFunc {
-
- @Param ${type.name}Holder left;
- @Param ${type.name}Holder right;
- @Output BitHolder out;
- public void setup() {}
-
- public void eval() {
- <@adjustScale javaType=type.storage leftType="leftType" rightType="rightType"/>
- out.value = (left.value < right.value) ? 1 : 0;
- }
- }
-
- <#-- Comparison function for comparison expression operator (=, &lt;, etc.),
- not for sorting and grouping relational operators.) -->
- @FunctionTemplate(name = "less than or equal to",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_MAX_SCALE,
- nulls = NullHandling.NULL_IF_NULL)
- public static class ${type.name}LessThanEq implements DrillSimpleFunc {
-
- @Param ${type.name}Holder left;
- @Param ${type.name}Holder right;
- @Output BitHolder out;
- public void setup() {}
-
- public void eval() {
- <@adjustScale javaType=type.storage leftType="leftType" rightType="rightType"/>
- out.value = (left.value <= right.value) ? 1 : 0;
- }
- }
-
- <#-- Comparison function for comparison expression operator (=, &lt;, etc.),
- not for sorting and grouping relational operators.) -->
- @FunctionTemplate(name = "greater than",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_MAX_SCALE,
- nulls = NullHandling.NULL_IF_NULL)
- public static class ${type.name}GreaterThan implements DrillSimpleFunc {
-
- @Param ${type.name}Holder left;
- @Param ${type.name}Holder right;
- @Output BitHolder out;
- public void setup() {}
-
- public void eval() {
- <@adjustScale javaType=type.storage leftType="leftType" rightType="rightType"/>
- out.value = (left.value > right.value) ? 1 : 0;
- }
- }
-
- <#-- Comparison function for comparison expression operator (=, &lt;, etc.),
- not for sorting and grouping relational operators.) -->
- @FunctionTemplate(name = "greater than or equal to",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_MAX_SCALE,
- nulls = NullHandling.NULL_IF_NULL)
- public static class ${type.name}GreaterThanEq implements DrillSimpleFunc {
-
- @Param ${type.name}Holder left;
- @Param ${type.name}Holder right;
- @Output BitHolder out;
- public void setup() {}
-
- public void eval() {
- <@adjustScale javaType=type.storage leftType="leftType" rightType="rightType"/>
- out.value = (left.value >= right.value) ? 1 : 0;
- }
- }
-
- <#-- Comparison function for comparison expression operator (=, &lt;, etc.),
- not for sorting and grouping relational operators.) -->
- @FunctionTemplate(name = "Equal",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_MAX_SCALE,
- nulls = NullHandling.NULL_IF_NULL)
- public static class ${type.name}Equal implements DrillSimpleFunc {
-
- @Param ${type.name}Holder left;
- @Param ${type.name}Holder right;
- @Output BitHolder out;
- public void setup() {}
-
- public void eval() {
- <@adjustScale javaType=type.storage leftType="leftType" rightType="rightType"/>
- out.value = (left.value == right.value) ? 1 : 0;
- }
- }
+ @FunctionTemplate(name = FunctionGenerationHelper.NE,
+ scope = FunctionTemplate.FunctionScope.SIMPLE,
+ nulls = NullHandling.NULL_IF_NULL)
+ public static class ${type.name}NotEqual implements DrillSimpleFunc {
+ @Param ${type.name}Holder left;
+ @Param ${type.name}Holder right;
+ @Output BitHolder out;
- <#-- Comparison function for comparison expression operator (=, &lt;, etc.),
- not for sorting and grouping relational operators.) -->
- @FunctionTemplate(name = "not equal",
- scope = FunctionTemplate.FunctionScope.SIMPLE,
- returnType = FunctionTemplate.ReturnType.DECIMAL_MAX_SCALE,
- nulls = NullHandling.NULL_IF_NULL)
- public static class ${type.name}NotEqual implements DrillSimpleFunc {
-
- @Param ${type.name}Holder left;
- @Param ${type.name}Holder right;
- @Output BitHolder out;
- public void setup() {}
+ public void setup() {}
- public void eval() {
- <@adjustScale javaType=type.storage leftType="leftType" rightType="rightType"/>
- out.value = (left.value != right.value) ? 1 : 0;
- }
+ public void eval() {
+ int cmp;
+ <@varCompareBlock leftType = "leftType" rightType = "rightType" absCompare = "false" output = "cmp" nullCompare = false nullComparesHigh = false />
+ out.value = cmp != 0 ? 1 : 0;
}
+ }
}
-
</#if>
</#list>
diff --git a/exec/java-exec/src/main/codegen/templates/MathFunctions.java b/exec/java-exec/src/main/codegen/templates/MathFunctions.java
index d1366cb09..a17865cbf 100644
--- a/exec/java-exec/src/main/codegen/templates/MathFunctions.java
+++ b/exec/java-exec/src/main/codegen/templates/MathFunctions.java
@@ -227,12 +227,7 @@ public static class ${func.className}${type.input} implements DrillSimpleFunc {
}
public void eval() {
- <#if type.input?matches("^Decimal[1-9]*")>
- double dblval = new java.math.BigDecimal(in.value).setScale(in.scale).doubleValue();
- out.value = ${func.javaFunc}(dblval);
- <#else>
out.value = ${func.javaFunc}(in.value);
- </#if>
}
}
@@ -257,12 +252,7 @@ public static class ${func.className}${type.input} implements DrillSimpleFunc {
}
public void eval() {
- <#if type.input?matches("^Decimal[1-9]*")>
- double dblval = new java.math.BigDecimal(val.value).setScale(val.scale).doubleValue();
- out.value = ${func.javaFunc}(dblval)/ ${func.javaFunc}(base.value);
- <#else>
out.value = ${func.javaFunc}(val.value)/ ${func.javaFunc}(base.value);
- </#if>
}
}
</#list>
diff --git a/exec/java-exec/src/main/codegen/templates/NumericToCharFunctions.java b/exec/java-exec/src/main/codegen/templates/NumericToCharFunctions.java
index 3fc45dffb..b192be36e 100644
--- a/exec/java-exec/src/main/codegen/templates/NumericToCharFunctions.java
+++ b/exec/java-exec/src/main/codegen/templates/NumericToCharFunctions.java
@@ -48,45 +48,36 @@ import java.text.DecimalFormat;
* This class is generated using freemarker and the ${.template_name} template.
*/
@SuppressWarnings("unused")
-@FunctionTemplate(name = "to_char", scope = FunctionTemplate.FunctionScope.SIMPLE, nulls = NullHandling.NULL_IF_NULL)
+@FunctionTemplate(name = "to_char",
+ scope = FunctionTemplate.FunctionScope.SIMPLE,
+ nulls = NullHandling.NULL_IF_NULL)
public class G${type}ToChar implements DrillSimpleFunc {
- @Param ${type}Holder left;
- @Param VarCharHolder right;
- @Inject DrillBuf buffer;
- @Workspace java.text.NumberFormat outputFormat;
- @Output VarCharHolder out;
+ @Param ${type}Holder left;
+ @Param VarCharHolder right;
+ @Inject DrillBuf buffer;
+ @Workspace java.text.NumberFormat outputFormat;
+ @Output VarCharHolder out;
- public void setup() {
- buffer = buffer.reallocIfNeeded(100);
- byte[] buf = new byte[right.end - right.start];
- right.buffer.getBytes(right.start, buf, 0, right.end - right.start);
- String inputFormat = new String(buf);
- outputFormat = new java.text.DecimalFormat(inputFormat);
- }
+ public void setup() {
+ buffer = buffer.reallocIfNeeded(100);
+ byte[] buf = new byte[right.end - right.start];
+ right.buffer.getBytes(right.start, buf, 0, right.end - right.start);
+ String inputFormat = new String(buf);
+ outputFormat = new java.text.DecimalFormat(inputFormat);
+ }
- public void eval() {
-
- <#if type == "VarDecimal">
- java.math.BigDecimal bigDecimal = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromDrillBuf(left.buffer, left.start, left.end - left.start, left.scale);
- String str = outputFormat.format(bigDecimal);
- <#elseif type == "Decimal9" || type == "Decimal18">
- java.math.BigDecimal bigDecimal = new java.math.BigDecimal(java.math.BigInteger.valueOf(left.value), left.scale);
- String str = outputFormat.format(bigDecimal);
- <#elseif type == "Decimal28Sparse" || type == "Decimal38Sparse">
- java.math.BigDecimal bigDecimal = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromDrillBuf(left.buffer, left.start, left.nDecimalDigits, left.scale, true);
- String str = outputFormat.format(bigDecimal);
- <#elseif type == "Decimal28Dense" || type == "Decimal38Dense">
- java.math.BigDecimal bigDecimal = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromDense(left.buffer, left.start, left.nDecimalDigits, left.scale, left.maxPrecision, left.WIDTH);
- String str = outputFormat.format(bigDecimal);
- <#else>
- String str = outputFormat.format(left.value);
- </#if>
- out.buffer = buffer;
- out.start = 0;
- out.end = Math.min(100, str.length()); // truncate if target type has length smaller than that of input's string
- out.buffer.setBytes(0, str.substring(0,out.end).getBytes());
-
- }
+ public void eval() {
+ <#if type == "VarDecimal">
+ java.math.BigDecimal bigDecimal = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromDrillBuf(left.buffer, left.start, left.end - left.start, left.scale);
+ String str = outputFormat.format(bigDecimal);
+ <#else>
+ String str = outputFormat.format(left.value);
+ </#if>
+ out.buffer = buffer;
+ out.start = 0;
+ out.end = Math.min(100, str.length()); // truncate if target type has length smaller than that of input's string
+ out.buffer.setBytes(0, str.substring(0, out.end).getBytes());
+ }
}
-</#list> \ No newline at end of file
+</#list>
diff --git a/exec/java-exec/src/main/codegen/templates/ParquetOutputRecordWriter.java b/exec/java-exec/src/main/codegen/templates/ParquetOutputRecordWriter.java
index 26a33b9dc..20f4d6023 100644
--- a/exec/java-exec/src/main/codegen/templates/ParquetOutputRecordWriter.java
+++ b/exec/java-exec/src/main/codegen/templates/ParquetOutputRecordWriter.java
@@ -28,17 +28,21 @@ import java.util.Arrays;
package org.apache.drill.exec.store;
import com.google.common.collect.Lists;
+import com.google.common.primitives.Ints;
+import com.google.common.primitives.Longs;
import org.apache.drill.common.types.TypeProtos.MinorType;
import org.apache.drill.exec.expr.TypeHelper;
import org.apache.drill.exec.expr.holders.*;
import org.apache.drill.exec.record.BatchSchema;
import org.apache.drill.exec.store.EventBasedRecordWriter.FieldConverter;
import org.apache.drill.exec.store.parquet.ParquetTypeHelper;
+import org.apache.drill.exec.store.parquet.decimal.DecimalValueWriter;
import org.apache.drill.exec.vector.*;
import org.apache.drill.exec.util.DecimalUtility;
import org.apache.drill.exec.vector.complex.reader.FieldReader;
import org.apache.parquet.io.api.RecordConsumer;
import org.apache.parquet.schema.MessageType;
+import org.apache.parquet.schema.PrimitiveType;
import org.apache.parquet.io.api.Binary;
import io.netty.buffer.DrillBuf;
import org.apache.drill.exec.record.BatchSchema;
@@ -75,6 +79,8 @@ public abstract class ParquetOutputRecordWriter extends AbstractRecordWriter imp
this.consumer = consumer;
}
+ protected abstract PrimitiveType getPrimitiveType(MaterializedField field);
+
<#list vv.types as type>
<#list type.minor as minor>
<#list vv.modes as mode>
@@ -86,19 +92,25 @@ public abstract class ParquetOutputRecordWriter extends AbstractRecordWriter imp
public class ${mode.prefix}${minor.class}ParquetConverter extends FieldConverter {
private Nullable${minor.class}Holder holder = new Nullable${minor.class}Holder();
<#if minor.class?contains("Interval")>
- private final byte[] output = new byte[12];
+ private final byte[] output = new byte[12];
+ <#elseif minor.class == "VarDecimal">
+ private final DecimalValueWriter decimalValueWriter;
</#if>
public ${mode.prefix}${minor.class}ParquetConverter(int fieldId, String fieldName, FieldReader reader) {
super(fieldId, fieldName, reader);
+ <#if minor.class == "VarDecimal">
+ decimalValueWriter = DecimalValueWriter.
+ getDecimalValueWriterForType(getPrimitiveType(reader.getField()).getPrimitiveTypeName());
+ </#if>
}
@Override
public void writeField() throws IOException {
<#if mode.prefix == "Nullable" >
- if (!reader.isSet()) {
- return;
- }
+ if (!reader.isSet()) {
+ return;
+ }
<#elseif mode.prefix == "Repeated" >
// empty lists are represented by simply not starting a field, rather than starting one and putting in 0 elements
if (reader.size() == 0) {
@@ -229,18 +241,26 @@ public abstract class ParquetOutputRecordWriter extends AbstractRecordWriter imp
<#else>
</#if>
- <#elseif minor.class == "VarChar" || minor.class == "Var16Char" || minor.class == "VarBinary">
+ <#elseif minor.class == "VarChar" || minor.class == "Var16Char"
+ || minor.class == "VarBinary" || minor.class == "VarDecimal">
<#if mode.prefix == "Repeated">
reader.read(i, holder);
- //consumer.startField(fieldName, fieldId);
+ <#if minor.class == "VarDecimal">
+ decimalValueWriter.writeValue(consumer, holder.buffer,
+ holder.start, holder.end, reader.getField().getPrecision());
+ <#else>
consumer.addBinary(Binary.fromByteBuffer(holder.buffer.nioBuffer(holder.start, holder.end - holder.start)));
- //consumer.endField(fieldName, fieldId);
+ </#if>
<#else>
- reader.read(holder);
- DrillBuf buf = holder.buffer;
- consumer.startField(fieldName, fieldId);
- consumer.addBinary(Binary.fromByteBuffer(holder.buffer.nioBuffer(holder.start, holder.end - holder.start)));
- consumer.endField(fieldName, fieldId);
+ reader.read(holder);
+ consumer.startField(fieldName, fieldId);
+ <#if minor.class == "VarDecimal">
+ decimalValueWriter.writeValue(consumer, holder.buffer,
+ holder.start, holder.end, reader.getField().getPrecision());
+ <#else>
+ consumer.addBinary(Binary.fromByteBuffer(holder.buffer.nioBuffer(holder.start, holder.end - holder.start)));
+ </#if>
+ consumer.endField(fieldName, fieldId);
</#if>
</#if>
<#if mode.prefix == "Repeated">
diff --git a/exec/java-exec/src/main/codegen/templates/ParquetTypeHelper.java b/exec/java-exec/src/main/codegen/templates/ParquetTypeHelper.java
index c4166f9df..d2f27cca9 100644
--- a/exec/java-exec/src/main/codegen/templates/ParquetTypeHelper.java
+++ b/exec/java-exec/src/main/codegen/templates/ParquetTypeHelper.java
@@ -15,11 +15,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import org.apache.drill.common.types.MinorType;
-import org.apache.parquet.format.ConvertedType;
-import org.apache.parquet.schema.DecimalMetadata;
-import org.apache.parquet.schema.OriginalType;
-import org.apache.parquet.schema.PrimitiveType.PrimitiveTypeName;
<@pp.dropOutputFile />
<@pp.changeOutputFile name="org/apache/drill/exec/store/parquet/ParquetTypeHelper.java" />
@@ -29,6 +24,7 @@ package org.apache.drill.exec.store.parquet;
import org.apache.drill.common.types.TypeProtos.DataMode;
import org.apache.drill.common.types.TypeProtos.MinorType;
+import org.apache.drill.exec.planner.types.DrillRelDataTypeSystem;
import org.apache.drill.exec.record.MaterializedField;
import org.apache.parquet.schema.OriginalType;
import org.apache.parquet.schema.DecimalMetadata;
@@ -85,7 +81,8 @@ public class ParquetTypeHelper {
minor.class == "Decimal28Dense" ||
minor.class == "Decimal38Dense" ||
minor.class == "Decimal28Sparse" ||
- minor.class == "Decimal38Sparse">
+ minor.class == "Decimal38Sparse" ||
+ minor.class == "VarDecimal">
typeMap.put(MinorType.${minor.class?upper_case}, PrimitiveTypeName.FIXED_LEN_BYTE_ARRAY);
<#elseif
minor.class == "VarChar" ||
@@ -106,8 +103,8 @@ public class ParquetTypeHelper {
<#list vv.types as type>
<#list type.minor as minor>
- <#if minor.class.startsWith("Decimal")>
- originalTypeMap.put(MinorType.${minor.class?upper_case},OriginalType.DECIMAL);
+ <#if minor.class.contains("Decimal")>
+ originalTypeMap.put(MinorType.${minor.class?upper_case}, OriginalType.DECIMAL);
</#if>
</#list>
</#list>
@@ -157,10 +154,26 @@ public class ParquetTypeHelper {
case DECIMAL28SPARSE:
return 12;
case DECIMAL38SPARSE:
+ case VARDECIMAL:
return 16;
default:
return 0;
}
}
+ public static int getMaxPrecisionForPrimitiveType(PrimitiveTypeName type) {
+ switch(type) {
+ case INT32:
+ return 9;
+ case INT64:
+ return 18;
+ case FIXED_LEN_BYTE_ARRAY:
+ return DrillRelDataTypeSystem.DRILL_REL_DATATYPE_SYSTEM.getMaxNumericPrecision();
+ default:
+ throw new UnsupportedOperationException(String.format(
+ "Specified PrimitiveTypeName %s cannot be used to determine max precision",
+ type));
+ }
+ }
+
}
diff --git a/exec/java-exec/src/main/codegen/templates/SqlAccessors.java b/exec/java-exec/src/main/codegen/templates/SqlAccessors.java
index fe650ac9c..7e5e99ba9 100644
--- a/exec/java-exec/src/main/codegen/templates/SqlAccessors.java
+++ b/exec/java-exec/src/main/codegen/templates/SqlAccessors.java
@@ -129,19 +129,24 @@ public class ${name}Accessor extends AbstractSqlAccessor {
<#case "VarDecimal">
@Override
- public String getString(int index){
-<#if mode=="Nullable">
- if(ac.isNull(index)){
- return null;
- }
-</#if>
- try {
- BigDecimal bd=getBigDecimal(index);
- return bd.toString();
- } catch (Throwable t) {
- // TODO: we cannot throw the exception, so return its string representation, for now. This should be handled better.
- return t.toString();
- }
+ public String getString(int index) {
+ <#if mode == "Nullable">
+ if (ac.isNull(index)) {
+ return null;
+ }
+ </#if>
+ BigDecimal bd = getBigDecimal(index);
+ return bd.toString();
+ }
+
+ @Override
+ public BigDecimal getBigDecimal(int index) {
+ <#if mode == "Nullable">
+ if (ac.isNull(index)) {
+ return null;
+ }
+ </#if>
+ return ac.getObject(index);
}
<#break>
diff --git a/exec/java-exec/src/main/codegen/templates/VarCharAggrFunctions1.java b/exec/java-exec/src/main/codegen/templates/VarCharAggrFunctions1.java
index c0930f3ea..a5afce98c 100644
--- a/exec/java-exec/src/main/codegen/templates/VarCharAggrFunctions1.java
+++ b/exec/java-exec/src/main/codegen/templates/VarCharAggrFunctions1.java
@@ -35,6 +35,7 @@ package org.apache.drill.exec.expr.fn.impl.gaggr;
import org.apache.drill.exec.expr.DrillAggFunc;
import org.apache.drill.exec.expr.annotations.FunctionTemplate;
import org.apache.drill.exec.expr.annotations.FunctionTemplate.FunctionScope;
+import org.apache.drill.exec.expr.annotations.FunctionTemplate.ReturnType;
import org.apache.drill.exec.expr.annotations.Output;
import org.apache.drill.exec.expr.annotations.Param;
import org.apache.drill.exec.expr.annotations.Workspace;
@@ -56,7 +57,11 @@ public class ${aggrtype.className}VarBytesFunctions {
<#list aggrtype.types as type>
<#if type.major == "VarBytes">
-@FunctionTemplate(name = "${aggrtype.funcName}", scope = FunctionTemplate.FunctionScope.POINT_AGGREGATE)
+@FunctionTemplate(name = "${aggrtype.funcName}",
+ <#if type.inputType.contains("VarChar")>
+ returnType = ReturnType.SAME_IN_OUT_LENGTH,
+ </#if>
+ scope = FunctionTemplate.FunctionScope.POINT_AGGREGATE)
public static class ${type.inputType}${aggrtype.className} implements DrillAggFunc{
@Param ${type.inputType}Holder in;
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/ExecConstants.java b/exec/java-exec/src/main/java/org/apache/drill/exec/ExecConstants.java
index 42fd7e074..671ce4bdc 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/ExecConstants.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/ExecConstants.java
@@ -243,6 +243,16 @@ public final class ExecConstants {
public static final OptionValidator PARQUET_WRITER_ENABLE_DICTIONARY_ENCODING_VALIDATOR = new BooleanValidator(
PARQUET_WRITER_ENABLE_DICTIONARY_ENCODING);
+ public static final String PARQUET_WRITER_USE_PRIMITIVE_TYPES_FOR_DECIMALS
+ = "store.parquet.writer.use_primitive_types_for_decimals";
+ public static final OptionValidator PARQUET_WRITER_USE_PRIMITIVE_TYPES_FOR_DECIMALS_VALIDATOR = new BooleanValidator(
+ PARQUET_WRITER_USE_PRIMITIVE_TYPES_FOR_DECIMALS);
+
+ public static final String PARQUET_WRITER_LOGICAL_TYPE_FOR_DECIMALS
+ = "store.parquet.writer.logical_type_for_decimals";
+ public static final OptionValidator PARQUET_WRITER_LOGICAL_TYPE_FOR_DECIMALS_VALIDATOR
+ = new EnumeratedStringValidator(PARQUET_WRITER_LOGICAL_TYPE_FOR_DECIMALS, "fixed_len_byte_array", "binary");
+
public static final String PARQUET_VECTOR_FILL_THRESHOLD = "store.parquet.vector_fill_threshold";
public static final OptionValidator PARQUET_VECTOR_FILL_THRESHOLD_VALIDATOR = new PositiveLongValidator(PARQUET_VECTOR_FILL_THRESHOLD, 99l);
public static final String PARQUET_VECTOR_FILL_CHECK_THRESHOLD = "store.parquet.vector_fill_check_threshold";
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/compile/bytecode/ScalarReplacementTypes.java b/exec/java-exec/src/main/java/org/apache/drill/exec/compile/bytecode/ScalarReplacementTypes.java
index 001762f7e..e1cc745f3 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/compile/bytecode/ScalarReplacementTypes.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/compile/bytecode/ScalarReplacementTypes.java
@@ -51,12 +51,14 @@ import org.apache.drill.exec.expr.holders.NullableTimeHolder;
import org.apache.drill.exec.expr.holders.NullableTimeStampHolder;
import org.apache.drill.exec.expr.holders.NullableVarBinaryHolder;
import org.apache.drill.exec.expr.holders.NullableVarCharHolder;
+import org.apache.drill.exec.expr.holders.NullableVarDecimalHolder;
import org.apache.drill.exec.expr.holders.TimeHolder;
import org.apache.drill.exec.expr.holders.TimeStampHolder;
import org.apache.drill.exec.expr.holders.VarBinaryHolder;
import org.apache.drill.exec.expr.holders.VarCharHolder;
import com.google.common.collect.ImmutableSet;
+import org.apache.drill.exec.expr.holders.VarDecimalHolder;
/**
* Reference list of classes we will perform scalar replacement on.
@@ -87,6 +89,7 @@ public class ScalarReplacementTypes {
TimeStampHolder.class,
VarCharHolder.class,
VarBinaryHolder.class,
+ VarDecimalHolder.class,
NullableBitHolder.class,
NullableIntHolder.class,
NullableBigIntHolder.class,
@@ -94,6 +97,7 @@ public class ScalarReplacementTypes {
NullableFloat8Holder.class,
NullableVarCharHolder.class,
NullableVarBinaryHolder.class,
+ NullableVarDecimalHolder.class,
NullableDecimal9Holder.class,
NullableDecimal18Holder.class,
NullableDecimal28SparseHolder.class,
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/compile/sig/ConstantExpressionIdentifier.java b/exec/java-exec/src/main/java/org/apache/drill/exec/compile/sig/ConstantExpressionIdentifier.java
index 1a0b7d539..d7646633d 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/compile/sig/ConstantExpressionIdentifier.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/compile/sig/ConstantExpressionIdentifier.java
@@ -47,6 +47,7 @@ import org.apache.drill.common.expression.ValueExpressions.LongExpression;
import org.apache.drill.common.expression.ValueExpressions.QuotedString;
import org.apache.drill.common.expression.ValueExpressions.TimeExpression;
import org.apache.drill.common.expression.ValueExpressions.TimeStampExpression;
+import org.apache.drill.common.expression.ValueExpressions.VarDecimalExpression;
import org.apache.drill.common.expression.visitors.ExprVisitor;
import com.google.common.collect.Lists;
@@ -187,6 +188,11 @@ public class ConstantExpressionIdentifier implements ExprVisitor<Boolean, Identi
}
@Override
+ public Boolean visitVarDecimalConstant(VarDecimalExpression decExpr, IdentityHashMap<LogicalExpression, Object> value) {
+ return true;
+ }
+
+ @Override
public Boolean visitDoubleConstant(DoubleExpression dExpr, IdentityHashMap<LogicalExpression, Object> value){
return true;
}
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/CloneVisitor.java b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/CloneVisitor.java
index 84d120357..9c2e394aa 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/CloneVisitor.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/CloneVisitor.java
@@ -44,6 +44,7 @@ import org.apache.drill.common.expression.ValueExpressions.LongExpression;
import org.apache.drill.common.expression.ValueExpressions.QuotedString;
import org.apache.drill.common.expression.ValueExpressions.TimeExpression;
import org.apache.drill.common.expression.ValueExpressions.TimeStampExpression;
+import org.apache.drill.common.expression.ValueExpressions.VarDecimalExpression;
import org.apache.drill.common.expression.visitors.AbstractExprVisitor;
import org.apache.drill.exec.expr.fn.DrillFuncHolder;
@@ -131,6 +132,11 @@ public class CloneVisitor extends AbstractExprVisitor<LogicalExpression,Void,Run
}
@Override
+ public LogicalExpression visitVarDecimalConstant(VarDecimalExpression decExpr, Void value) throws RuntimeException {
+ return visitUnknown(decExpr, value);
+ }
+
+ @Override
public LogicalExpression visitDateConstant(DateExpression intExpr, Void value) throws RuntimeException {
return visitUnknown(intExpr, value);
}
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/EqualityVisitor.java b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/EqualityVisitor.java
index 3f322b8da..94f8b7948 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/EqualityVisitor.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/EqualityVisitor.java
@@ -43,6 +43,7 @@ import org.apache.drill.common.expression.ValueExpressions.LongExpression;
import org.apache.drill.common.expression.ValueExpressions.QuotedString;
import org.apache.drill.common.expression.ValueExpressions.TimeExpression;
import org.apache.drill.common.expression.ValueExpressions.TimeStampExpression;
+import org.apache.drill.common.expression.ValueExpressions.VarDecimalExpression;
import org.apache.drill.common.expression.visitors.AbstractExprVisitor;
import java.util.List;
@@ -228,7 +229,21 @@ class EqualityVisitor extends AbstractExprVisitor<Boolean,LogicalExpression,Runt
if (!decExpr.getMajorType().equals(((Decimal38Expression) value).getMajorType())) {
return false;
}
- return false;
+ return true;
+ }
+
+ @Override
+ public Boolean visitVarDecimalConstant(VarDecimalExpression decExpr, LogicalExpression value) throws RuntimeException {
+ if (!(value instanceof VarDecimalExpression)) {
+ return false;
+ }
+ if (!decExpr.getMajorType().equals(value.getMajorType())) {
+ return false;
+ }
+ if (!decExpr.getBigDecimal().equals(((VarDecimalExpression) value).getBigDecimal())) {
+ return false;
+ }
+ return true;
}
@Override
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/EvaluationVisitor.java b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/EvaluationVisitor.java
index dcc2668a5..64cfe6695 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/EvaluationVisitor.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/EvaluationVisitor.java
@@ -53,6 +53,7 @@ import org.apache.drill.common.expression.ValueExpressions.LongExpression;
import org.apache.drill.common.expression.ValueExpressions.QuotedString;
import org.apache.drill.common.expression.ValueExpressions.TimeExpression;
import org.apache.drill.common.expression.ValueExpressions.TimeStampExpression;
+import org.apache.drill.common.expression.ValueExpressions.VarDecimalExpression;
import org.apache.drill.common.expression.visitors.AbstractExprVisitor;
import org.apache.drill.common.types.TypeProtos.MajorType;
import org.apache.drill.common.types.TypeProtos.MinorType;
@@ -657,8 +658,10 @@ public class EvaluationVisitor {
JType holderType = generator.getHolderType(majorType);
JVar var = generator.declareClassField("dec28", holderType);
JExpression stringLiteral = JExpr.lit(e.getBigDecimal().toString());
+ JExpression buffer = generator.getMappingSet().getIncoming().invoke("getContext").invoke("getManagedBuffer");
setup.assign(var,
- generator.getModel().ref(ValueHolderHelper.class).staticInvoke("getDecimal28Holder").arg(stringLiteral));
+ generator.getModel().ref(ValueHolderHelper.class).staticInvoke("getDecimal28Holder")
+ .arg(buffer).arg(stringLiteral));
return new HoldingContainer(majorType, var, null, null);
}
@@ -670,8 +673,25 @@ public class EvaluationVisitor {
JType holderType = generator.getHolderType(majorType);
JVar var = generator.declareClassField("dec38", holderType);
JExpression stringLiteral = JExpr.lit(e.getBigDecimal().toString());
+ JExpression buffer = generator.getMappingSet().getIncoming().invoke("getContext").invoke("getManagedBuffer");
+ setup.assign(var,
+ generator.getModel().ref(ValueHolderHelper.class).staticInvoke("getDecimal38Holder")
+ .arg(buffer).arg(stringLiteral));
+ return new HoldingContainer(majorType, var, null, null);
+ }
+
+ @Override
+ public HoldingContainer visitVarDecimalConstant(VarDecimalExpression e, ClassGenerator<?> generator)
+ throws RuntimeException {
+ MajorType majorType = e.getMajorType();
+ JBlock setup = generator.getBlock(BlockType.SETUP);
+ JType holderType = generator.getHolderType(majorType);
+ JVar var = generator.declareClassField("varDec", holderType);
+ JExpression stringLiteral = JExpr.lit(e.getBigDecimal().toString());
+ JExpression buffer = generator.getMappingSet().getIncoming().invoke("getContext").invoke("getManagedBuffer");
setup.assign(var,
- generator.getModel().ref(ValueHolderHelper.class).staticInvoke("getVarCharHolder").arg(stringLiteral));
+ generator.getModel().ref(ValueHolderHelper.class).staticInvoke("getVarDecimalHolder")
+ .arg(buffer).arg(stringLiteral));
return new HoldingContainer(majorType, var, null, null);
}
@@ -997,6 +1017,16 @@ public class EvaluationVisitor {
}
@Override
+ public HoldingContainer visitVarDecimalConstant(VarDecimalExpression decExpr, ClassGenerator<?> generator) throws RuntimeException {
+ HoldingContainer hc = getPrevious(decExpr, generator.getMappingSet());
+ if (hc == null) {
+ hc = super.visitVarDecimalConstant(decExpr, generator);
+ put(decExpr, hc, generator.getMappingSet());
+ }
+ return hc;
+ }
+
+ @Override
public HoldingContainer visitDoubleConstant(DoubleExpression dExpr, ClassGenerator<?> generator) throws RuntimeException {
HoldingContainer hc = getPrevious(dExpr, generator.getMappingSet());
if (hc == null) {
@@ -1221,6 +1251,20 @@ public class EvaluationVisitor {
}
@Override
+ public HoldingContainer visitVarDecimalConstant(VarDecimalExpression e, ClassGenerator<?> generator)
+ throws RuntimeException {
+ if (constantBoundaries.contains(e)) {
+ generator.getMappingSet().enterConstant();
+ HoldingContainer c = super.visitVarDecimalConstant(e, generator);
+ return renderConstantExpression(generator, c);
+ } else if (generator.getMappingSet().isWithinConstant()) {
+ return super.visitVarDecimalConstant(e, generator).setConstant(true);
+ } else {
+ return super.visitVarDecimalConstant(e, generator);
+ }
+ }
+
+ @Override
public HoldingContainer visitIntConstant(IntExpression e, ClassGenerator<?> generator) throws RuntimeException {
if (constantBoundaries.contains(e)) {
generator.getMappingSet().enterConstant();
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/ExpressionTreeMaterializer.java b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/ExpressionTreeMaterializer.java
index 6e8e31592..ff38e0c88 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/ExpressionTreeMaterializer.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/ExpressionTreeMaterializer.java
@@ -62,6 +62,7 @@ import org.apache.drill.common.expression.ValueExpressions.LongExpression;
import org.apache.drill.common.expression.ValueExpressions.QuotedString;
import org.apache.drill.common.expression.ValueExpressions.TimeExpression;
import org.apache.drill.common.expression.ValueExpressions.TimeStampExpression;
+import org.apache.drill.common.expression.ValueExpressions.VarDecimalExpression;
import org.apache.drill.common.expression.fn.CastFunctions;
import org.apache.drill.common.expression.visitors.AbstractExprVisitor;
import org.apache.drill.common.expression.visitors.ConditionalExprOptimizer;
@@ -210,7 +211,11 @@ public class ExpressionTreeMaterializer {
return fromExpr;
}
- if (!Types.isFixedWidthType(toType) && !Types.isUnion(toType)) {
+ if (CoreDecimalUtility.isDecimalType(toType)) {
+ // Add the scale and precision to the arguments of the implicit cast
+ castArgs.add(new ValueExpressions.IntExpression(toType.getPrecision(), null));
+ castArgs.add(new ValueExpressions.IntExpression(toType.getScale(), null));
+ } else if (!Types.isFixedWidthType(toType) && !Types.isUnion(toType)) {
/* We are implicitly casting to VARCHAR so we don't have a max length,
* using an arbitrary value. We trim down the size of the stored bytes
@@ -218,11 +223,7 @@ public class ExpressionTreeMaterializer {
*/
castArgs.add(new ValueExpressions.LongExpression(Types.MAX_VARCHAR_LENGTH, null));
}
- else if (CoreDecimalUtility.isDecimalType(toType)) {
- // Add the scale and precision to the arguments of the implicit cast
- castArgs.add(new ValueExpressions.LongExpression(toType.getPrecision(), null));
- castArgs.add(new ValueExpressions.LongExpression(toType.getScale(), null));
- }
+
FunctionCall castCall = new FunctionCall(castFuncName, castArgs, ExpressionPosition.UNKNOWN);
FunctionResolver resolver;
if (exactResolver) {
@@ -381,14 +382,8 @@ public class ExpressionTreeMaterializer {
}
private int computePrecision(LogicalExpression currentArg) {
- int precision = currentArg.getMajorType().getPrecision();
- if (currentArg.getMajorType().getMinorType() == MinorType.INT) {
- precision = DecimalUtility.MAX_DIGITS_INT;
- }
- else if (currentArg.getMajorType().getMinorType() == MinorType.BIGINT) {
- precision = DecimalUtility.MAX_DIGITS_BIGINT;
- }
- return precision;
+ int precision = currentArg.getMajorType().getPrecision();
+ return DecimalUtility.getDefaultPrecision(currentArg.getMajorType().getMinorType(), precision);
}
@Override
@@ -444,7 +439,19 @@ public class ExpressionTreeMaterializer {
}
}
- return matchedFuncHolder.getExpr(call.getName(), argsWithCast, call.getPosition());
+ FunctionHolderExpression funcExpr = matchedFuncHolder.getExpr(call.getName(), argsWithCast, call.getPosition());
+ MajorType funcExprMajorType = funcExpr.getMajorType();
+ if (DecimalUtility.isObsoleteDecimalType(funcExprMajorType.getMinorType())) {
+ MajorType majorType =
+ MajorType.newBuilder()
+ .setMinorType(MinorType.VARDECIMAL)
+ .setMode(funcExprMajorType.getMode())
+ .setScale(funcExprMajorType.getScale())
+ .setPrecision(funcExprMajorType.getPrecision())
+ .build();
+ return addCastExpression(funcExpr, majorType, functionLookupContext, errorCollector);
+ }
+ return funcExpr;
}
// as no drill func is found, search for a non-Drill function.
@@ -813,6 +820,11 @@ public class ExpressionTreeMaterializer {
}
@Override
+ public LogicalExpression visitVarDecimalConstant(VarDecimalExpression decExpr, FunctionLookupContext functionLookupContext) {
+ return decExpr;
+ }
+
+ @Override
public LogicalExpression visitDoubleConstant(DoubleExpression dExpr, FunctionLookupContext functionLookupContext) {
return dExpr;
}
@@ -868,12 +880,11 @@ public class ExpressionTreeMaterializer {
List<LogicalExpression> newArgs = Lists.newArrayList();
newArgs.add(input); //input_expr
- //VarLen type
- if (!Types.isFixedWidthType(type)) {
+ if (CoreDecimalUtility.isDecimalType(type)) {
+ newArgs.add(new ValueExpressions.IntExpression(type.getPrecision(), null));
+ newArgs.add(new ValueExpressions.IntExpression(type.getScale(), null));
+ } else if (!Types.isFixedWidthType(type)) { //VarLen type
newArgs.add(new ValueExpressions.LongExpression(type.getPrecision(), null));
- } if (CoreDecimalUtility.isDecimalType(type)) {
- newArgs.add(new ValueExpressions.LongExpression(type.getPrecision(), null));
- newArgs.add(new ValueExpressions.LongExpression(type.getScale(), null));
}
FunctionCall fc = new FunctionCall(castFuncWithType, newArgs, e.getPosition());
@@ -912,17 +923,8 @@ public class ExpressionTreeMaterializer {
case DECIMAL28SPARSE:
case DECIMAL38DENSE:
case DECIMAL38SPARSE:
- if (to.getScale() == from.getScale() && to.getPrecision() == from.getPrecision()) {
- return true;
- }
- return false;
-
case VARDECIMAL:
- // for VARDECIMAL, precision does not matter (it's variable precision, to fit the number), but scale matters
- if (to.getScale() == from.getScale()) {
- return true;
- }
- return false;
+ return to.getScale() == from.getScale() && to.getPrecision() == from.getPrecision();
case FIXED16CHAR:
case FIXEDBINARY:
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/GetSetVectorHelper.java b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/GetSetVectorHelper.java
index 8ceb3d95c..3b7e2b4de 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/GetSetVectorHelper.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/GetSetVectorHelper.java
@@ -87,22 +87,23 @@ public class GetSetVectorHelper {
eval.assign(out.getHolder().ref("start"), JExpr.cast(model._ref(int.class), se));
eval.assign(out.getHolder().ref("end"), JExpr.cast(model._ref(int.class), se.shr(JExpr.lit(32))));
eval.assign(out.getHolder().ref("scale"), vector.invoke("getField").invoke("getScale"));
+ eval.assign(out.getHolder().ref("precision"), vector.invoke("getField").invoke("getPrecision"));
return;
}
- case INTERVAL:{
+ case INTERVAL: {
JVar start = eval.decl(model.INT, "start", JExpr.lit(TypeHelper.getSize(type)).mul(indexVariable));
JVar data = eval.decl(model.ref(DrillBuf.class), "data", vector.invoke("getBuffer"));
eval.assign(out.getHolder().ref("months"), data.invoke("getInt").arg(start));
eval.assign(out.getHolder().ref("days"), data.invoke("getInt").arg(start.plus(JExpr.lit(4))));
eval.assign(out.getHolder().ref("milliseconds"), data.invoke("getInt").arg(start.plus(JExpr.lit(8))));
return;
- }
+ }
case INTERVALDAY: {
JVar start = eval.decl(model.INT, "start", JExpr.lit(TypeHelper.getSize(type)).mul(indexVariable));
eval.assign(out.getHolder().ref("days"), vector.invoke("getBuffer").invoke("getInt").arg(start));
eval.assign(out.getHolder().ref("milliseconds"), vector.invoke("getBuffer").invoke("getInt").arg(start.plus(JExpr.lit(4))));
return;
- }
+ }
case VAR16CHAR:
case VARBINARY:
case VARCHAR: {
@@ -111,7 +112,7 @@ public class GetSetVectorHelper {
eval.assign(out.getHolder().ref("start"), JExpr.cast(model._ref(int.class), se));
eval.assign(out.getHolder().ref("end"), JExpr.cast(model._ref(int.class), se.shr(JExpr.lit(32))));
return;
- }
+ }
}
}
@@ -149,38 +150,37 @@ public class GetSetVectorHelper {
case BIT:
case DECIMAL9:
case DECIMAL18:
- return setMethod //
+ return setMethod
.arg(in.getValue());
case DECIMAL28DENSE:
case DECIMAL28SPARSE:
case DECIMAL38DENSE:
case DECIMAL38SPARSE:
- return setMethod //
- .arg(in.f("start")) //
+ return setMethod
+ .arg(in.f("start"))
.arg(in.f("buffer"));
case INTERVAL:{
- return setMethod //
- .arg(in.f("months")) //
- .arg(in.f("days")) //
+ return setMethod
+ .arg(in.f("months"))
+ .arg(in.f("days"))
.arg(in.f("milliseconds"));
}
case INTERVALDAY: {
- return setMethod //
- .arg(in.f("days")) //
+ return setMethod
+ .arg(in.f("days"))
.arg(in.f("milliseconds"));
}
case VAR16CHAR:
case VARBINARY:
case VARCHAR:
case VARDECIMAL:
- return setMethod //
- .arg(in.f("start")) //
- .arg(in.f("end")) //
+ return setMethod
+ .arg(in.f("start"))
+ .arg(in.f("end"))
.arg(in.f("buffer"));
}
}
-
return setMethod.arg(in.getHolder());
}
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/HashVisitor.java b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/HashVisitor.java
index 53fbaa3a6..87d66883a 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/HashVisitor.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/HashVisitor.java
@@ -17,14 +17,12 @@
*/
package org.apache.drill.exec.expr;
-import com.google.common.collect.Lists;
import org.apache.drill.common.expression.BooleanOperator;
import org.apache.drill.common.expression.CastExpression;
import org.apache.drill.common.expression.ConvertExpression;
import org.apache.drill.common.expression.FunctionCall;
import org.apache.drill.common.expression.FunctionHolderExpression;
import org.apache.drill.common.expression.IfExpression;
-import org.apache.drill.common.expression.IfExpression.IfCondition;
import org.apache.drill.common.expression.LogicalExpression;
import org.apache.drill.common.expression.NullExpression;
import org.apache.drill.common.expression.SchemaPath;
@@ -44,10 +42,8 @@ import org.apache.drill.common.expression.ValueExpressions.LongExpression;
import org.apache.drill.common.expression.ValueExpressions.QuotedString;
import org.apache.drill.common.expression.ValueExpressions.TimeExpression;
import org.apache.drill.common.expression.ValueExpressions.TimeStampExpression;
+import org.apache.drill.common.expression.ValueExpressions.VarDecimalExpression;
import org.apache.drill.common.expression.visitors.AbstractExprVisitor;
-import org.apache.drill.exec.expr.fn.DrillFuncHolder;
-
-import java.util.List;
public class HashVisitor extends AbstractExprVisitor<Integer,Void,RuntimeException> {
@Override
@@ -176,6 +172,11 @@ public class HashVisitor extends AbstractExprVisitor<Integer,Void,RuntimeExcepti
return compute(e, 25);
}
+ @Override
+ public Integer visitVarDecimalConstant(VarDecimalExpression decExpr, Void value) throws RuntimeException {
+ return compute(decExpr, 26);
+ }
+
private int compute(LogicalExpression e, int seed) {
int hash = seed;
for (LogicalExpression child : e) {
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/annotations/FunctionTemplate.java b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/annotations/FunctionTemplate.java
index ac4ba07bb..1a5470ba2 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/annotations/FunctionTemplate.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/annotations/FunctionTemplate.java
@@ -20,7 +20,6 @@ package org.apache.drill.exec.expr.annotations;
import org.apache.drill.common.expression.LogicalExpression;
import org.apache.drill.common.types.TypeProtos;
import org.apache.drill.exec.expr.fn.FunctionAttributes;
-import org.apache.drill.exec.expr.fn.FunctionInitializer;
import org.apache.drill.exec.expr.fn.output.ConcatReturnTypeInference;
import org.apache.drill.exec.expr.fn.output.DecimalReturnTypeInference;
import org.apache.drill.exec.expr.fn.output.DefaultReturnTypeInference;
@@ -89,7 +88,7 @@ public @interface FunctionTemplate {
boolean isNiladic() default false;
boolean checkPrecisionRange() default false;
- public enum NullHandling {
+ enum NullHandling {
/**
* Method handles nulls.
*/
@@ -108,7 +107,7 @@ public @interface FunctionTemplate {
* Function scope is used to indicate function output rows relation:
* simple / scalar (1 -> 1) or aggregate (n -> 1).
*/
- public enum FunctionScope {
+ enum FunctionScope {
SIMPLE,
POINT_AGGREGATE,
HOLISTIC_AGGREGATE,
@@ -119,7 +118,7 @@ public @interface FunctionTemplate {
* Return type enum is used to indicate which return type calculation logic
* should be used for functions.
*/
- public enum ReturnType {
+ enum ReturnType {
DEFAULT(DefaultReturnTypeInference.INSTANCE),
STRING_CAST(StringCastReturnTypeInference.INSTANCE),
@@ -129,6 +128,7 @@ public @interface FunctionTemplate {
DECIMAL_AGGREGATE(DecimalReturnTypeInference.DecimalAggReturnTypeInference.INSTANCE),
DECIMAL_SUM_AGGREGATE(DecimalReturnTypeInference.DecimalSumAggReturnTypeInference.INSTANCE),
+ DECIMAL_AVG_AGGREGATE(DecimalReturnTypeInference.DecimalAvgAggReturnTypeInference.INSTANCE),
DECIMAL_MAX_SCALE(DecimalReturnTypeInference.DecimalMaxScaleReturnTypeInference.INSTANCE),
DECIMAL_SUM_SCALE(DecimalReturnTypeInference.DecimalSumScaleReturnTypeInference.INSTANCE),
DECIMAL_CAST(DecimalReturnTypeInference.DecimalCastReturnTypeInference.INSTANCE),
@@ -150,7 +150,7 @@ public @interface FunctionTemplate {
}
- public enum FunctionCostCategory {
+ enum FunctionCostCategory {
SIMPLE(1), MEDIUM(20), COMPLEX(50);
private final int value;
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/Hash32AsDouble.java b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/Hash32AsDouble.java
index e134c9d84..c9502fb19 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/Hash32AsDouble.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/Hash32AsDouble.java
@@ -23,20 +23,12 @@ import org.apache.drill.exec.expr.annotations.Output;
import org.apache.drill.exec.expr.annotations.Param;
import org.apache.drill.exec.expr.annotations.FunctionTemplate.FunctionScope;
import org.apache.drill.exec.expr.holders.BigIntHolder;
-import org.apache.drill.exec.expr.holders.Decimal18Holder;
-import org.apache.drill.exec.expr.holders.Decimal28SparseHolder;
import org.apache.drill.exec.expr.holders.VarDecimalHolder;
import org.apache.drill.exec.expr.holders.NullableVarDecimalHolder;
-import org.apache.drill.exec.expr.holders.Decimal38SparseHolder;
-import org.apache.drill.exec.expr.holders.Decimal9Holder;
import org.apache.drill.exec.expr.holders.Float4Holder;
import org.apache.drill.exec.expr.holders.Float8Holder;
import org.apache.drill.exec.expr.holders.IntHolder;
import org.apache.drill.exec.expr.holders.NullableBigIntHolder;
-import org.apache.drill.exec.expr.holders.NullableDecimal18Holder;
-import org.apache.drill.exec.expr.holders.NullableDecimal28SparseHolder;
-import org.apache.drill.exec.expr.holders.NullableDecimal38SparseHolder;
-import org.apache.drill.exec.expr.holders.NullableDecimal9Holder;
import org.apache.drill.exec.expr.holders.NullableFloat4Holder;
import org.apache.drill.exec.expr.holders.NullableFloat8Holder;
import org.apache.drill.exec.expr.holders.NullableIntHolder;
@@ -45,6 +37,7 @@ import org.apache.drill.exec.expr.holders.NullableIntHolder;
* hash32 function definitions for numeric data types. These functions cast the input numeric value to a
* double before doing the hashing. See comments in {@link Hash64AsDouble} for the reason for doing this.
*/
+@SuppressWarnings("unused")
public class Hash32AsDouble {
@FunctionTemplate(name = "hash32AsDouble", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
@@ -134,7 +127,7 @@ public class Hash32AsDouble {
if (in.isSet == 0) {
out.value = 0;
} else {
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash32((long) in.value, 0);
+ out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash32(in.value, 0);
}
}
}
@@ -170,7 +163,7 @@ public class Hash32AsDouble {
}
public void eval() {
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash32((long)in.value, 0);
+ out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash32(in.value, 0);
}
}
@@ -190,78 +183,6 @@ public class Hash32AsDouble {
}
@FunctionTemplate(name = "hash32AsDouble", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class Decimal9Hash implements DrillSimpleFunc {
- @Param
- Decimal9Holder in;
- @Output
- IntHolder out;
-
- public void setup() {
- }
-
- public void eval() {
- java.math.BigDecimal input = new java.math.BigDecimal(java.math.BigInteger.valueOf(in.value), in.scale);
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash32(input.doubleValue(), 0);
- }
- }
-
- @FunctionTemplate(name = "hash32AsDouble", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class NullableDecimal9Hash implements DrillSimpleFunc {
- @Param
- NullableDecimal9Holder in;
- @Output
- IntHolder out;
-
- public void setup() {
- }
-
- public void eval() {
- if (in.isSet == 0) {
- out.value = 0;
- } else {
- java.math.BigDecimal input = new java.math.BigDecimal(java.math.BigInteger.valueOf(in.value), in.scale);
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash32(input.doubleValue(), 0);
- }
- }
- }
-
- @FunctionTemplate(name = "hash32AsDouble", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class Decimal18Hash implements DrillSimpleFunc {
- @Param
- Decimal18Holder in;
- @Output
- IntHolder out;
-
- public void setup() {
- }
-
- public void eval() {
- java.math.BigDecimal input = new java.math.BigDecimal(java.math.BigInteger.valueOf(in.value), in.scale);
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash32(input.doubleValue(), 0);
- }
- }
-
- @FunctionTemplate(name = "hash32AsDouble", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class NullableDecimal18Hash implements DrillSimpleFunc {
- @Param
- NullableDecimal18Holder in;
- @Output
- IntHolder out;
-
- public void setup() {
- }
-
- public void eval() {
- if (in.isSet == 0) {
- out.value = 0;
- } else {
- java.math.BigDecimal input = new java.math.BigDecimal(java.math.BigInteger.valueOf(in.value), in.scale);
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash32(input.doubleValue(), 0);
- }
- }
- }
-
- @FunctionTemplate(name = "hash32AsDouble", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
public static class VarDecimalHash implements DrillSimpleFunc {
@Param
VarDecimalHolder in;
@@ -298,80 +219,4 @@ public class Hash32AsDouble {
}
}
}
-
- @FunctionTemplate(name = "hash32AsDouble", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class Decimal28Hash implements DrillSimpleFunc {
- @Param
- Decimal28SparseHolder in;
- @Output
- IntHolder out;
-
- public void setup() {
- }
-
- public void eval() {
- java.math.BigDecimal input = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromSparse(in.buffer,
- in.start, in.nDecimalDigits, in.scale);
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash32(input.doubleValue(), 0);
- }
- }
-
- @FunctionTemplate(name = "hash32AsDouble", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class NullableDecimal28Hash implements DrillSimpleFunc {
- @Param
- NullableDecimal28SparseHolder in;
- @Output
- IntHolder out;
-
- public void setup() {
- }
-
- public void eval() {
- if (in.isSet == 0) {
- out.value = 0;
- } else {
- java.math.BigDecimal input = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromSparse(in.buffer,
- in.start, in.nDecimalDigits, in.scale);
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash32(input.doubleValue(), 0);
- }
- }
- }
-
- @FunctionTemplate(name = "hash32AsDouble", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class Decimal38Hash implements DrillSimpleFunc {
- @Param
- Decimal38SparseHolder in;
- @Output
- IntHolder out;
-
- public void setup() {
- }
-
- public void eval() {
- java.math.BigDecimal input = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromSparse(in.buffer,
- in.start, in.nDecimalDigits, in.scale);
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash32(input.doubleValue(), 0);
- }
- }
-
- @FunctionTemplate(name = "hash32AsDouble", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class NullableDecimal38Hash implements DrillSimpleFunc {
- @Param
- NullableDecimal38SparseHolder in;
- @Output
- IntHolder out;
-
- public void setup() {
- }
-
- public void eval() {
- if (in.isSet == 0) {
- out.value = 0;
- } else {
- java.math.BigDecimal input = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromSparse(in.buffer,
- in.start, in.nDecimalDigits, in.scale);
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash32(input.doubleValue(), 0);
- }
- }
- }
}
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/Hash32Functions.java b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/Hash32Functions.java
index a6d24f5a7..412674f13 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/Hash32Functions.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/Hash32Functions.java
@@ -25,22 +25,14 @@ import org.apache.drill.exec.expr.annotations.Param;
import org.apache.drill.exec.expr.holders.BigIntHolder;
import org.apache.drill.exec.expr.holders.BitHolder;
import org.apache.drill.exec.expr.holders.DateHolder;
-import org.apache.drill.exec.expr.holders.Decimal18Holder;
-import org.apache.drill.exec.expr.holders.Decimal28SparseHolder;
import org.apache.drill.exec.expr.holders.VarDecimalHolder;
import org.apache.drill.exec.expr.holders.NullableVarDecimalHolder;
-import org.apache.drill.exec.expr.holders.Decimal38SparseHolder;
-import org.apache.drill.exec.expr.holders.Decimal9Holder;
import org.apache.drill.exec.expr.holders.Float4Holder;
import org.apache.drill.exec.expr.holders.Float8Holder;
import org.apache.drill.exec.expr.holders.IntHolder;
import org.apache.drill.exec.expr.holders.NullableBigIntHolder;
import org.apache.drill.exec.expr.holders.NullableBitHolder;
import org.apache.drill.exec.expr.holders.NullableDateHolder;
-import org.apache.drill.exec.expr.holders.NullableDecimal18Holder;
-import org.apache.drill.exec.expr.holders.NullableDecimal28SparseHolder;
-import org.apache.drill.exec.expr.holders.NullableDecimal38SparseHolder;
-import org.apache.drill.exec.expr.holders.NullableDecimal9Holder;
import org.apache.drill.exec.expr.holders.NullableFloat4Holder;
import org.apache.drill.exec.expr.holders.NullableFloat8Holder;
import org.apache.drill.exec.expr.holders.NullableIntHolder;
@@ -55,8 +47,7 @@ import org.apache.drill.exec.expr.holders.Var16CharHolder;
import org.apache.drill.exec.expr.holders.VarBinaryHolder;
import org.apache.drill.exec.expr.holders.VarCharHolder;
-import java.math.BigDecimal;
-
+@SuppressWarnings("unused")
public class Hash32Functions {
@FunctionTemplate(names = {"hash", "hash32"}, scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL )
@@ -373,66 +364,6 @@ public class Hash32Functions {
}
@FunctionTemplate(names = {"hash", "hash32"}, scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class Decimal9Hash implements DrillSimpleFunc {
- @Param Decimal9Holder in;
- @Output IntHolder out;
-
- public void setup() {
- }
-
- public void eval() {
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash32(in.value, 0);
- }
- }
-
- @FunctionTemplate(names = {"hash", "hash32"}, scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class NullableDecimal9Hash implements DrillSimpleFunc {
- @Param NullableDecimal9Holder in;
- @Output IntHolder out;
-
- public void setup() {
- }
-
- public void eval() {
- if (in.isSet == 0) {
- out.value = 0;
- } else {
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash32(in.value, 0);
- }
- }
- }
-
- @FunctionTemplate(names = {"hash", "hash32"}, scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class Decimal18Hash implements DrillSimpleFunc {
- @Param Decimal18Holder in;
- @Output IntHolder out;
-
- public void setup() {
- }
-
- public void eval() {
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash32(in.value, 0);
- }
- }
-
- @FunctionTemplate(names = {"hash", "hash32"}, scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class NullableDecimal18Hash implements DrillSimpleFunc {
- @Param NullableDecimal18Holder in;
- @Output IntHolder out;
-
- public void setup() {
- }
-
- public void eval() {
- if (in.isSet == 0) {
- out.value = 0;
- } else {
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash32(in.value, 0);
- }
- }
- }
-
- @FunctionTemplate(names = {"hash", "hash32"}, scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
public static class VarDecimalHash implements DrillSimpleFunc {
@Param VarDecimalHolder in;
@Output IntHolder out;
@@ -441,28 +372,8 @@ public class Hash32Functions {
}
public void eval() {
- java.math.BigDecimal bd = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromDrillBuf(in.buffer,
- in.start, in.end - in.start, in.scale);
- out.value = hashBigDecimal(bd, 0);
- }
- }
-
- public static int hashBigDecimal(BigDecimal bd, int seed) {
- java.math.BigInteger bi = bd.unscaledValue();
- byte[] barr = bi.toByteArray();
- int shiftCount = 0;
- int xor = 0;
- for (int i = 0; i < barr.length; ++i) {
- byte b = barr[i];
- int ival = (int) b;
- ival <<= shiftCount;
- ++shiftCount;
- if (shiftCount > 3) {
- shiftCount = 0;
- }
- xor = xor ^ ival;
+ out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash32(in.start, in.end, in.buffer, 0);
}
- return org.apache.drill.exec.expr.fn.impl.HashHelper.hash32(xor, seed);
}
@FunctionTemplate(names = {"hash", "hash32"}, scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
@@ -477,87 +388,7 @@ public class Hash32Functions {
if (in.isSet == 0) {
out.value = 0;
} else {
- java.math.BigDecimal bd = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromDrillBuf(in.buffer,
- in.start, in.end - in.start, in.scale);
- out.value = hashBigDecimal(bd, 0);
- }
- }
- }
-
- @FunctionTemplate(names = {"hash", "hash32"}, scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class Decimal28Hash implements DrillSimpleFunc {
- @Param Decimal28SparseHolder in;
- @Output IntHolder out;
-
- public void setup() {
- }
-
- public void eval() {
-
- int xor = 0;
- for (int i = 0; i < in.nDecimalDigits; i++) {
- xor = xor ^ Decimal28SparseHolder.getInteger(i, in.start, in.buffer);
- }
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash32(xor, 0);
- }
- }
-
- @FunctionTemplate(names = {"hash", "hash32"}, scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class NullableDecimal28Hash implements DrillSimpleFunc {
- @Param NullableDecimal28SparseHolder in;
- @Output IntHolder out;
-
- public void setup() {
- }
-
- public void eval() {
- if (in.isSet == 0) {
- out.value = 0;
- } else {
- int xor = 0;
- for (int i = 0; i < in.nDecimalDigits; i++) {
- xor = xor ^ NullableDecimal28SparseHolder.getInteger(i, in.start, in.buffer);
- }
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash32(xor, 0);
- }
- }
- }
-
- @FunctionTemplate(names = {"hash", "hash32"}, scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class Decimal38Hash implements DrillSimpleFunc {
- @Param Decimal38SparseHolder in;
- @Output IntHolder out;
-
- public void setup() {
- }
-
- public void eval() {
-
- int xor = 0;
- for (int i = 0; i < in.nDecimalDigits; i++) {
- xor = xor ^ Decimal38SparseHolder.getInteger(i, in.start, in.buffer);
- }
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash32(xor, 0);
- }
- }
-
- @FunctionTemplate(names = {"hash", "hash32"}, scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class NullableDecimal38Hash implements DrillSimpleFunc {
- @Param NullableDecimal38SparseHolder in;
- @Output IntHolder out;
-
- public void setup() {
- }
-
- public void eval() {
- if (in.isSet == 0) {
- out.value = 0;
- } else {
- int xor = 0;
- for (int i = 0; i < in.nDecimalDigits; i++) {
- xor = xor ^ NullableDecimal38SparseHolder.getInteger(i, in.start, in.buffer);
- }
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash32(xor, 0);
+ out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash32(in.start, in.end, in.buffer, 0);
}
}
}
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/Hash32FunctionsWithSeed.java b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/Hash32FunctionsWithSeed.java
index cda47ff7c..1741eb8e0 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/Hash32FunctionsWithSeed.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/Hash32FunctionsWithSeed.java
@@ -25,22 +25,14 @@ import org.apache.drill.exec.expr.annotations.Param;
import org.apache.drill.exec.expr.holders.BigIntHolder;
import org.apache.drill.exec.expr.holders.BitHolder;
import org.apache.drill.exec.expr.holders.DateHolder;
-import org.apache.drill.exec.expr.holders.Decimal18Holder;
-import org.apache.drill.exec.expr.holders.Decimal28SparseHolder;
import org.apache.drill.exec.expr.holders.VarDecimalHolder;
import org.apache.drill.exec.expr.holders.NullableVarDecimalHolder;
-import org.apache.drill.exec.expr.holders.Decimal38SparseHolder;
-import org.apache.drill.exec.expr.holders.Decimal9Holder;
import org.apache.drill.exec.expr.holders.Float4Holder;
import org.apache.drill.exec.expr.holders.Float8Holder;
import org.apache.drill.exec.expr.holders.IntHolder;
import org.apache.drill.exec.expr.holders.NullableBigIntHolder;
import org.apache.drill.exec.expr.holders.NullableBitHolder;
import org.apache.drill.exec.expr.holders.NullableDateHolder;
-import org.apache.drill.exec.expr.holders.NullableDecimal18Holder;
-import org.apache.drill.exec.expr.holders.NullableDecimal28SparseHolder;
-import org.apache.drill.exec.expr.holders.NullableDecimal38SparseHolder;
-import org.apache.drill.exec.expr.holders.NullableDecimal9Holder;
import org.apache.drill.exec.expr.holders.NullableFloat4Holder;
import org.apache.drill.exec.expr.holders.NullableFloat8Holder;
import org.apache.drill.exec.expr.holders.NullableIntHolder;
@@ -58,6 +50,7 @@ import org.apache.drill.exec.expr.holders.VarCharHolder;
/*
* Class contains hash32 function definitions for different data types.
*/
+@SuppressWarnings("unused")
public class Hash32FunctionsWithSeed {
@FunctionTemplate(name = "hash32", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL )
public static class NullableFloatHash implements DrillSimpleFunc {
@@ -414,74 +407,6 @@ public class Hash32FunctionsWithSeed {
}
@FunctionTemplate(name = "hash32", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class Decimal9Hash implements DrillSimpleFunc {
- @Param Decimal9Holder in;
- @Param IntHolder seed;
- @Output IntHolder out;
-
-
- public void setup() {
- }
-
- public void eval() {
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash32(in.value, seed.value);
- }
- }
-
- @FunctionTemplate(name = "hash32", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class NullableDecimal9Hash implements DrillSimpleFunc {
- @Param NullableDecimal9Holder in;
- @Param IntHolder seed;
- @Output IntHolder out;
-
-
- public void setup() {
- }
-
- public void eval() {
- if (in.isSet == 0) {
- out.value = seed.value;
- } else {
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash32(in.value, seed.value);
- }
- }
- }
-
- @FunctionTemplate(name = "hash32", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class Decimal18Hash implements DrillSimpleFunc {
- @Param Decimal18Holder in;
- @Param IntHolder seed;
- @Output IntHolder out;
-
-
- public void setup() {
- }
-
- public void eval() {
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash32(in.value, seed.value);
- }
- }
-
- @FunctionTemplate(name = "hash32", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class NullableDecimal18Hash implements DrillSimpleFunc {
- @Param NullableDecimal18Holder in;
- @Param IntHolder seed;
- @Output IntHolder out;
-
-
- public void setup() {
- }
-
- public void eval() {
- if (in.isSet == 0) {
- out.value = seed.value;
- } else {
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash32(in.value, seed.value);
- }
- }
- }
-
- @FunctionTemplate(name = "hash32", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
public static class VarDecimalHash implements DrillSimpleFunc {
@Param VarDecimalHolder in;
@Param IntHolder seed;
@@ -491,9 +416,7 @@ public class Hash32FunctionsWithSeed {
}
public void eval() {
- java.math.BigDecimal bd = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromDrillBuf(in.buffer,
- in.start, in.end - in.start, in.scale);
- out.value = Hash32Functions.hashBigDecimal(bd, seed.value);
+ out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash32(in.start, in.end, in.buffer, seed.value);
}
}
@@ -510,77 +433,7 @@ public class Hash32FunctionsWithSeed {
if (in.isSet == 0) {
out.value = seed.value;
} else {
- java.math.BigDecimal bd = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromDrillBuf(in.buffer,
- in.start, in.end - in.start, in.scale);
- out.value = Hash32Functions.hashBigDecimal(bd, seed.value);
- }
- }
- }
-
- @FunctionTemplate(name = "hash32", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class Decimal28Hash implements DrillSimpleFunc {
- @Param Decimal28SparseHolder in;
- @Param IntHolder seed;
- @Output IntHolder out;
-
-
- public void setup() {
- }
-
- public void eval() {
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash32(in.start, in.start + Decimal28SparseHolder.WIDTH, in.buffer, seed.value);
- }
- }
-
- @FunctionTemplate(name = "hash32", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class NullableDecimal28Hash implements DrillSimpleFunc {
- @Param NullableDecimal28SparseHolder in;
- @Param IntHolder seed;
- @Output IntHolder out;
-
-
- public void setup() {
- }
-
- public void eval() {
- if (in.isSet == 0) {
- out.value = seed.value;
- } else {
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash32(in.start, in.start + NullableDecimal28SparseHolder.WIDTH, in.buffer, seed.value);
- }
- }
- }
-
- @FunctionTemplate(name = "hash32", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class Decimal38Hash implements DrillSimpleFunc {
- @Param Decimal38SparseHolder in;
- @Param IntHolder seed;
- @Output IntHolder out;
-
-
- public void setup() {
- }
-
- public void eval() {
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash32(in.start, in.start + Decimal38SparseHolder.WIDTH, in.buffer, seed.value);
- }
- }
-
- @FunctionTemplate(name = "hash32", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class NullableDecimal38Hash implements DrillSimpleFunc {
- @Param NullableDecimal38SparseHolder in;
- @Param IntHolder seed;
- @Output IntHolder out;
-
-
- public void setup() {
- }
-
- public void eval() {
- if (in.isSet == 0) {
- out.value = seed.value;
- } else {
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash32(in.start, in.start + NullableDecimal38SparseHolder.WIDTH, in.buffer, seed.value);
+ out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash32(in.start, in.end, in.buffer, seed.value);
}
}
}
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/Hash32WithSeedAsDouble.java b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/Hash32WithSeedAsDouble.java
index 140293517..67bbfa7ad 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/Hash32WithSeedAsDouble.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/Hash32WithSeedAsDouble.java
@@ -23,42 +23,21 @@ import org.apache.drill.exec.expr.annotations.FunctionTemplate.FunctionScope;
import org.apache.drill.exec.expr.annotations.Output;
import org.apache.drill.exec.expr.annotations.Param;
import org.apache.drill.exec.expr.holders.BigIntHolder;
-import org.apache.drill.exec.expr.holders.BitHolder;
-import org.apache.drill.exec.expr.holders.DateHolder;
-import org.apache.drill.exec.expr.holders.Decimal18Holder;
-import org.apache.drill.exec.expr.holders.Decimal28SparseHolder;
import org.apache.drill.exec.expr.holders.VarDecimalHolder;
import org.apache.drill.exec.expr.holders.NullableVarDecimalHolder;
-import org.apache.drill.exec.expr.holders.Decimal38SparseHolder;
-import org.apache.drill.exec.expr.holders.Decimal9Holder;
import org.apache.drill.exec.expr.holders.Float4Holder;
import org.apache.drill.exec.expr.holders.Float8Holder;
import org.apache.drill.exec.expr.holders.IntHolder;
import org.apache.drill.exec.expr.holders.NullableBigIntHolder;
-import org.apache.drill.exec.expr.holders.NullableBitHolder;
-import org.apache.drill.exec.expr.holders.NullableDateHolder;
-import org.apache.drill.exec.expr.holders.NullableDecimal18Holder;
-import org.apache.drill.exec.expr.holders.NullableDecimal28SparseHolder;
-import org.apache.drill.exec.expr.holders.NullableDecimal38SparseHolder;
-import org.apache.drill.exec.expr.holders.NullableDecimal9Holder;
import org.apache.drill.exec.expr.holders.NullableFloat4Holder;
import org.apache.drill.exec.expr.holders.NullableFloat8Holder;
import org.apache.drill.exec.expr.holders.NullableIntHolder;
-import org.apache.drill.exec.expr.holders.NullableTimeHolder;
-import org.apache.drill.exec.expr.holders.NullableTimeStampHolder;
-import org.apache.drill.exec.expr.holders.NullableVar16CharHolder;
-import org.apache.drill.exec.expr.holders.NullableVarBinaryHolder;
-import org.apache.drill.exec.expr.holders.NullableVarCharHolder;
-import org.apache.drill.exec.expr.holders.TimeHolder;
-import org.apache.drill.exec.expr.holders.TimeStampHolder;
-import org.apache.drill.exec.expr.holders.Var16CharHolder;
-import org.apache.drill.exec.expr.holders.VarBinaryHolder;
-import org.apache.drill.exec.expr.holders.VarCharHolder;
/**
* hash32 with seed function definitions for numeric data types. These functions cast the input numeric value to a
* double before doing the hashing. See comments in {@link Hash64AsDouble} for the reason for doing this.
*/
+@SuppressWarnings("unused")
public class Hash32WithSeedAsDouble {
@FunctionTemplate(name = "hash32AsDouble", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL )
public static class NullableFloatHash implements DrillSimpleFunc {
@@ -206,81 +185,8 @@ public class Hash32WithSeedAsDouble {
}
@FunctionTemplate(name = "hash32AsDouble", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class Decimal9Hash implements DrillSimpleFunc {
- @Param Decimal9Holder in;
- @Param IntHolder seed;
- @Output IntHolder out;
-
-
- public void setup() {
- }
-
- public void eval() {
- java.math.BigDecimal input = new java.math.BigDecimal(java.math.BigInteger.valueOf(in.value), in.scale);
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash32(input.doubleValue(), seed.value);
- }
- }
-
- @FunctionTemplate(name = "hash32AsDouble", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class NullableDecimal9Hash implements DrillSimpleFunc {
- @Param NullableDecimal9Holder in;
- @Param IntHolder seed;
- @Output IntHolder out;
-
-
- public void setup() {
- }
-
- public void eval() {
- if (in.isSet == 0) {
- out.value = seed.value;
- } else {
- java.math.BigDecimal input = new java.math.BigDecimal(java.math.BigInteger.valueOf(in.value), in.scale);
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash32(input.doubleValue(), seed.value);
- }
- }
- }
-
- @FunctionTemplate(name = "hash32AsDouble", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class Decimal18Hash implements DrillSimpleFunc {
- @Param Decimal18Holder in;
- @Param IntHolder seed;
- @Output IntHolder out;
-
-
- public void setup() {
- }
-
- public void eval() {
- java.math.BigDecimal input = new java.math.BigDecimal(java.math.BigInteger.valueOf(in.value), in.scale);
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash32(input.doubleValue(), seed.value);
- }
- }
-
- @FunctionTemplate(name = "hash32AsDouble", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class NullableDecimal18Hash implements DrillSimpleFunc {
- @Param NullableDecimal18Holder in;
- @Param IntHolder seed;
- @Output IntHolder out;
-
-
- public void setup() {
- }
-
- public void eval() {
- if (in.isSet == 0) {
- out.value = seed.value;
- } else {
- java.math.BigDecimal input = new java.math.BigDecimal(java.math.BigInteger.valueOf(in.value), in.scale);
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash32(input.doubleValue(), seed.value);
- }
- }
- }
-
- @FunctionTemplate(name = "hash32AsDouble", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
public static class VarDecimalHash implements DrillSimpleFunc {
- @Param
- VarDecimalHolder in;
+ @Param VarDecimalHolder in;
@Param IntHolder seed;
@Output IntHolder out;
@@ -290,7 +196,7 @@ public class Hash32WithSeedAsDouble {
public void eval() {
java.math.BigDecimal bd = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromDrillBuf(in.buffer,
in.start, in.end - in.start, in.scale);
- out.value = Hash32Functions.hashBigDecimal(bd, seed.value);
+ out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash32(bd.doubleValue(), seed.value);
}
}
@@ -309,83 +215,7 @@ public class Hash32WithSeedAsDouble {
} else {
java.math.BigDecimal bd = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromDrillBuf(in.buffer,
in.start, in.end - in.start, in.scale);
- out.value = Hash32Functions.hashBigDecimal(bd, seed.value);
- }
- }
- }
-
- @FunctionTemplate(name = "hash32AsDouble", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class Decimal28Hash implements DrillSimpleFunc {
- @Param Decimal28SparseHolder in;
- @Param IntHolder seed;
- @Output IntHolder out;
-
-
- public void setup() {
- }
-
- public void eval() {
- java.math.BigDecimal input = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromSparse(in.buffer,
- in.start, in.nDecimalDigits, in.scale);
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash32(input.doubleValue(), seed.value);
- }
- }
-
- @FunctionTemplate(name = "hash32AsDouble", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class NullableDecimal28Hash implements DrillSimpleFunc {
- @Param NullableDecimal28SparseHolder in;
- @Param IntHolder seed;
- @Output IntHolder out;
-
-
- public void setup() {
- }
-
- public void eval() {
- if (in.isSet == 0) {
- out.value = seed.value;
- } else {
- java.math.BigDecimal input = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromSparse(in.buffer,
- in.start, in.nDecimalDigits, in.scale);
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash32(input.doubleValue(), seed.value);
- }
- }
- }
-
- @FunctionTemplate(name = "hash32AsDouble", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class Decimal38Hash implements DrillSimpleFunc {
- @Param Decimal38SparseHolder in;
- @Param IntHolder seed;
- @Output IntHolder out;
-
-
- public void setup() {
- }
-
- public void eval() {
- java.math.BigDecimal input = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromSparse(in.buffer,
- in.start, in.nDecimalDigits, in.scale);
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash32(input.doubleValue(), seed.value);
- }
- }
-
- @FunctionTemplate(name = "hash32AsDouble", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class NullableDecimal38Hash implements DrillSimpleFunc {
- @Param NullableDecimal38SparseHolder in;
- @Param IntHolder seed;
- @Output IntHolder out;
-
-
- public void setup() {
- }
-
- public void eval() {
- if (in.isSet == 0) {
- out.value = seed.value;
- } else {
- java.math.BigDecimal input = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromSparse(in.buffer,
- in.start, in.nDecimalDigits, in.scale);
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash32(input.doubleValue(), seed.value);
+ out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash32(bd.doubleValue(), seed.value);
}
}
}
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/Hash64AsDouble.java b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/Hash64AsDouble.java
index cfda6c8e4..9161b5ec7 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/Hash64AsDouble.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/Hash64AsDouble.java
@@ -23,37 +23,15 @@ import org.apache.drill.exec.expr.annotations.Output;
import org.apache.drill.exec.expr.annotations.Param;
import org.apache.drill.exec.expr.annotations.FunctionTemplate.FunctionScope;
import org.apache.drill.exec.expr.holders.BigIntHolder;
-import org.apache.drill.exec.expr.holders.BitHolder;
-import org.apache.drill.exec.expr.holders.DateHolder;
-import org.apache.drill.exec.expr.holders.Decimal18Holder;
-import org.apache.drill.exec.expr.holders.Decimal28SparseHolder;
import org.apache.drill.exec.expr.holders.VarDecimalHolder;
import org.apache.drill.exec.expr.holders.NullableVarDecimalHolder;
-import org.apache.drill.exec.expr.holders.Decimal38SparseHolder;
-import org.apache.drill.exec.expr.holders.Decimal9Holder;
import org.apache.drill.exec.expr.holders.Float4Holder;
import org.apache.drill.exec.expr.holders.Float8Holder;
import org.apache.drill.exec.expr.holders.IntHolder;
import org.apache.drill.exec.expr.holders.NullableBigIntHolder;
-import org.apache.drill.exec.expr.holders.NullableBitHolder;
-import org.apache.drill.exec.expr.holders.NullableDateHolder;
-import org.apache.drill.exec.expr.holders.NullableDecimal18Holder;
-import org.apache.drill.exec.expr.holders.NullableDecimal28SparseHolder;
-import org.apache.drill.exec.expr.holders.NullableDecimal38SparseHolder;
-import org.apache.drill.exec.expr.holders.NullableDecimal9Holder;
import org.apache.drill.exec.expr.holders.NullableFloat4Holder;
import org.apache.drill.exec.expr.holders.NullableFloat8Holder;
import org.apache.drill.exec.expr.holders.NullableIntHolder;
-import org.apache.drill.exec.expr.holders.NullableTimeHolder;
-import org.apache.drill.exec.expr.holders.NullableTimeStampHolder;
-import org.apache.drill.exec.expr.holders.NullableVar16CharHolder;
-import org.apache.drill.exec.expr.holders.NullableVarBinaryHolder;
-import org.apache.drill.exec.expr.holders.NullableVarCharHolder;
-import org.apache.drill.exec.expr.holders.TimeHolder;
-import org.apache.drill.exec.expr.holders.TimeStampHolder;
-import org.apache.drill.exec.expr.holders.Var16CharHolder;
-import org.apache.drill.exec.expr.holders.VarBinaryHolder;
-import org.apache.drill.exec.expr.holders.VarCharHolder;
/*
* Class contains hash64 function definitions for different data types.
@@ -63,6 +41,7 @@ import org.apache.drill.exec.expr.holders.VarCharHolder;
* as expected we would need to hash the same value represented in different data types (int, bigint, float etc)
* to hash to the same node, this is why we cast all numeric values to double before performing the actual hash.
*/
+@SuppressWarnings("unused")
public class Hash64AsDouble {
@FunctionTemplate(name = "hash64AsDouble", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
public static class NullableFloatHash implements DrillSimpleFunc {
@@ -115,7 +94,7 @@ public class Hash64AsDouble {
if (in.isSet == 0) {
out.value = 0;
} else {
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash64((double) in.value, 0);
+ out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash64(in.value, 0);
}
}
}
@@ -208,83 +187,9 @@ public class Hash64AsDouble {
}
@FunctionTemplate(name = "hash64AsDouble", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class Decimal9Hash implements DrillSimpleFunc {
- @Param
- Decimal9Holder in;
- @Output
- BigIntHolder out;
-
- public void setup() {
- }
-
- public void eval() {
- java.math.BigDecimal input = new java.math.BigDecimal(java.math.BigInteger.valueOf(in.value), in.scale);
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash64(input.doubleValue(), 0);
- }
- }
-
- @FunctionTemplate(name = "hash64AsDouble", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class NullableDecimal9Hash implements DrillSimpleFunc {
- @Param
- NullableDecimal9Holder in;
- @Output
- BigIntHolder out;
-
- public void setup() {
- }
-
- public void eval() {
- if (in.isSet == 0) {
- out.value = 0;
- } else {
- java.math.BigDecimal input = new java.math.BigDecimal(java.math.BigInteger.valueOf(in.value), in.scale);
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash64(input.doubleValue(), 0);
- }
- }
- }
-
- @FunctionTemplate(name = "hash64AsDouble", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class Decimal18Hash implements DrillSimpleFunc {
- @Param
- Decimal18Holder in;
- @Output
- BigIntHolder out;
-
- public void setup() {
- }
-
- public void eval() {
- java.math.BigDecimal input = new java.math.BigDecimal(java.math.BigInteger.valueOf(in.value), in.scale);
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash64(input.doubleValue(), 0);
- }
- }
-
- @FunctionTemplate(name = "hash64AsDouble", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class NullableDecimal18Hash implements DrillSimpleFunc {
- @Param
- NullableDecimal18Holder in;
- @Output
- BigIntHolder out;
-
- public void setup() {
- }
-
- public void eval() {
- if (in.isSet == 0) {
- out.value = 0;
- } else {
- java.math.BigDecimal input = new java.math.BigDecimal(java.math.BigInteger.valueOf(in.value), in.scale);
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash64(input.doubleValue(), 0);
- }
- }
- }
-
- @FunctionTemplate(name = "hash64AsDouble", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
public static class VarDecimalHash implements DrillSimpleFunc {
- @Param
- VarDecimalHolder in;
- @Output
- BigIntHolder out;
+ @Param VarDecimalHolder in;
+ @Output BigIntHolder out;
public void setup() {
}
@@ -292,16 +197,14 @@ public class Hash64AsDouble {
public void eval() {
java.math.BigDecimal bd = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromDrillBuf(in.buffer,
in.start, in.end - in.start, in.scale);
- out.value = Hash32Functions.hashBigDecimal(bd, 0);
+ out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash64(bd.doubleValue(), 0);
}
}
@FunctionTemplate(name = "hash64AsDouble", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
public static class NullableVarDecimalHash implements DrillSimpleFunc {
- @Param
- NullableVarDecimalHolder in;
- @Output
- BigIntHolder out;
+ @Param NullableVarDecimalHolder in;
+ @Output BigIntHolder out;
public void setup() {
}
@@ -312,83 +215,7 @@ public class Hash64AsDouble {
} else {
java.math.BigDecimal bd = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromDrillBuf(in.buffer,
in.start, in.end - in.start, in.scale);
- out.value = Hash32Functions.hashBigDecimal(bd, 0);
- }
- }
- }
-
- @FunctionTemplate(name = "hash64AsDouble", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class Decimal28Hash implements DrillSimpleFunc {
- @Param
- Decimal28SparseHolder in;
- @Output
- BigIntHolder out;
-
- public void setup() {
- }
-
- public void eval() {
- java.math.BigDecimal input = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromSparse(in.buffer,
- in.start, in.nDecimalDigits, in.scale);
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash64(input.doubleValue(), 0);
- }
- }
-
- @FunctionTemplate(name = "hash64AsDouble", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class NullableDecimal28Hash implements DrillSimpleFunc {
- @Param
- NullableDecimal28SparseHolder in;
- @Output
- BigIntHolder out;
-
- public void setup() {
- }
-
- public void eval() {
- if (in.isSet == 0) {
- out.value = 0;
- } else {
- java.math.BigDecimal input = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromSparse(in.buffer,
- in.start, in.nDecimalDigits, in.scale);
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash64(input.doubleValue(), 0);
- }
- }
- }
-
- @FunctionTemplate(name = "hash64AsDouble", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class Decimal38Hash implements DrillSimpleFunc {
- @Param
- Decimal38SparseHolder in;
- @Output
- BigIntHolder out;
-
- public void setup() {
- }
-
- public void eval() {
- java.math.BigDecimal input = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromSparse(in.buffer,
- in.start, in.nDecimalDigits, in.scale);
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash64(input.doubleValue(), 0);
- }
- }
-
- @FunctionTemplate(name = "hash64AsDouble", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class NullableDecimal38Hash implements DrillSimpleFunc {
- @Param
- NullableDecimal38SparseHolder in;
- @Output
- BigIntHolder out;
-
- public void setup() {
- }
-
- public void eval() {
- if (in.isSet == 0) {
- out.value = 0;
- } else {
- java.math.BigDecimal input = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromSparse(in.buffer,
- in.start, in.nDecimalDigits, in.scale);
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash64(input.doubleValue(), 0);
+ out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash64(bd.doubleValue(), 0);
}
}
}
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/Hash64Functions.java b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/Hash64Functions.java
index e94b133a4..582fbb58e 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/Hash64Functions.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/Hash64Functions.java
@@ -25,22 +25,14 @@ import org.apache.drill.exec.expr.annotations.FunctionTemplate.FunctionScope;
import org.apache.drill.exec.expr.holders.BigIntHolder;
import org.apache.drill.exec.expr.holders.BitHolder;
import org.apache.drill.exec.expr.holders.DateHolder;
-import org.apache.drill.exec.expr.holders.Decimal18Holder;
-import org.apache.drill.exec.expr.holders.Decimal28SparseHolder;
import org.apache.drill.exec.expr.holders.VarDecimalHolder;
import org.apache.drill.exec.expr.holders.NullableVarDecimalHolder;
-import org.apache.drill.exec.expr.holders.Decimal38SparseHolder;
-import org.apache.drill.exec.expr.holders.Decimal9Holder;
import org.apache.drill.exec.expr.holders.Float4Holder;
import org.apache.drill.exec.expr.holders.Float8Holder;
import org.apache.drill.exec.expr.holders.IntHolder;
import org.apache.drill.exec.expr.holders.NullableBigIntHolder;
import org.apache.drill.exec.expr.holders.NullableBitHolder;
import org.apache.drill.exec.expr.holders.NullableDateHolder;
-import org.apache.drill.exec.expr.holders.NullableDecimal18Holder;
-import org.apache.drill.exec.expr.holders.NullableDecimal28SparseHolder;
-import org.apache.drill.exec.expr.holders.NullableDecimal38SparseHolder;
-import org.apache.drill.exec.expr.holders.NullableDecimal9Holder;
import org.apache.drill.exec.expr.holders.NullableFloat4Holder;
import org.apache.drill.exec.expr.holders.NullableFloat8Holder;
import org.apache.drill.exec.expr.holders.NullableIntHolder;
@@ -55,11 +47,10 @@ import org.apache.drill.exec.expr.holders.Var16CharHolder;
import org.apache.drill.exec.expr.holders.VarBinaryHolder;
import org.apache.drill.exec.expr.holders.VarCharHolder;
-import java.math.BigDecimal;
-
/*
* Class contains hash64 function definitions for different data types.
*/
+@SuppressWarnings("unused")
public class Hash64Functions {
@FunctionTemplate(name = "hash64", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
public static class NullableFloatHash implements DrillSimpleFunc {
@@ -415,79 +406,9 @@ public class Hash64Functions {
}
@FunctionTemplate(name = "hash64", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class Decimal9Hash implements DrillSimpleFunc {
- @Param
- Decimal9Holder in;
- @Output
- BigIntHolder out;
-
- public void setup() {
- }
-
- public void eval() {
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash64(in.value, 0);
- }
- }
-
- @FunctionTemplate(name = "hash64", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class NullableDecimal9Hash implements DrillSimpleFunc {
- @Param
- NullableDecimal9Holder in;
- @Output
- BigIntHolder out;
-
- public void setup() {
- }
-
- public void eval() {
- if (in.isSet == 0) {
- out.value = 0;
- } else {
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash64(in.value, 0);
- }
- }
- }
-
- @FunctionTemplate(name = "hash64", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class Decimal18Hash implements DrillSimpleFunc {
- @Param
- Decimal18Holder in;
- @Output
- BigIntHolder out;
-
- public void setup() {
- }
-
- public void eval() {
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash64(in.value, 0);
- }
- }
-
- @FunctionTemplate(name = "hash64", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class NullableDecimal18Hash implements DrillSimpleFunc {
- @Param
- NullableDecimal18Holder in;
- @Output
- BigIntHolder out;
-
- public void setup() {
- }
-
- public void eval() {
- if (in.isSet == 0) {
- out.value = 0;
- } else {
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash64(in.value, 0);
- }
- }
- }
-
- @FunctionTemplate(name = "hash64", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
public static class VarDecimalHash implements DrillSimpleFunc {
- @Param
- VarDecimalHolder in;
- @Output
- BigIntHolder out;
+ @Param VarDecimalHolder in;
+ @Output BigIntHolder out;
public void setup() {
}
@@ -499,10 +420,8 @@ public class Hash64Functions {
@FunctionTemplate(name = "hash64", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
public static class NullableVarDecimalHash implements DrillSimpleFunc {
- @Param
- NullableVarDecimalHolder in;
- @Output
- BigIntHolder out;
+ @Param NullableVarDecimalHolder in;
+ @Output BigIntHolder out;
public void setup() {
}
@@ -516,78 +435,6 @@ public class Hash64Functions {
}
}
- @FunctionTemplate(name = "hash64", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class Decimal28Hash implements DrillSimpleFunc {
- @Param
- Decimal28SparseHolder in;
- @Output
- BigIntHolder out;
-
- public void setup() {
- }
-
- public void eval() {
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash64(in.start, in.start + Decimal28SparseHolder.WIDTH,
- in.buffer, 0);
- }
- }
-
- @FunctionTemplate(name = "hash64", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class NullableDecimal28Hash implements DrillSimpleFunc {
- @Param
- NullableDecimal28SparseHolder in;
- @Output
- BigIntHolder out;
-
- public void setup() {
- }
-
- public void eval() {
- if (in.isSet == 0) {
- out.value = 0;
- } else {
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash64(in.start, in.start
- + NullableDecimal28SparseHolder.WIDTH, in.buffer, 0);
- }
- }
- }
-
- @FunctionTemplate(name = "hash64", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class Decimal38Hash implements DrillSimpleFunc {
- @Param
- Decimal38SparseHolder in;
- @Output
- BigIntHolder out;
-
- public void setup() {
- }
-
- public void eval() {
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash64(in.start, in.start + Decimal38SparseHolder.WIDTH,
- in.buffer, 0);
- }
- }
-
- @FunctionTemplate(name = "hash64", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class NullableDecimal38Hash implements DrillSimpleFunc {
- @Param
- NullableDecimal38SparseHolder in;
- @Output
- BigIntHolder out;
-
- public void setup() {
- }
-
- public void eval() {
- if (in.isSet == 0) {
- out.value = 0;
- } else {
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash64(in.start, in.start
- + NullableDecimal38SparseHolder.WIDTH, in.buffer, 0);
- }
- }
- }
-
@FunctionTemplate(names = {"hash64", "hash64AsDouble"}, scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
public static class NullableBitHash implements DrillSimpleFunc {
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/Hash64FunctionsWithSeed.java b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/Hash64FunctionsWithSeed.java
index 9568e9950..d77bf0d5d 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/Hash64FunctionsWithSeed.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/Hash64FunctionsWithSeed.java
@@ -59,6 +59,7 @@ import org.apache.drill.exec.expr.holders.VarCharHolder;
/*
* Class contains hash64 function definitions for different data types.
*/
+@SuppressWarnings("unused")
public class Hash64FunctionsWithSeed {
@FunctionTemplate(name = "hash64", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL )
public static class NullableFloatHash implements DrillSimpleFunc {
@@ -415,80 +416,11 @@ public class Hash64FunctionsWithSeed {
}
@FunctionTemplate(name = "hash64", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class Decimal9Hash implements DrillSimpleFunc {
- @Param Decimal9Holder in;
- @Param BigIntHolder seed;
- @Output BigIntHolder out;
-
-
- public void setup() {
- }
-
- public void eval() {
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash64(in.value, seed.value);
- }
- }
-
- @FunctionTemplate(name = "hash64", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class NullableDecimal9Hash implements DrillSimpleFunc {
- @Param NullableDecimal9Holder in;
- @Param BigIntHolder seed;
- @Output BigIntHolder out;
-
-
- public void setup() {
- }
-
- public void eval() {
- if (in.isSet == 0) {
- out.value = seed.value;
- } else {
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash64(in.value, seed.value);
- }
- }
- }
-
- @FunctionTemplate(name = "hash64", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class Decimal18Hash implements DrillSimpleFunc {
- @Param Decimal18Holder in;
- @Param BigIntHolder seed;
- @Output BigIntHolder out;
-
-
- public void setup() {
- }
-
- public void eval() {
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash64(in.value, seed.value);
- }
- }
-
- @FunctionTemplate(name = "hash64", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class NullableDecimal18Hash implements DrillSimpleFunc {
- @Param NullableDecimal18Holder in;
- @Param BigIntHolder seed;
- @Output BigIntHolder out;
-
-
- public void setup() {
- }
-
- public void eval() {
- if (in.isSet == 0) {
- out.value = seed.value;
- } else {
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash64(in.value, seed.value);
- }
- }
- }
-
- @FunctionTemplate(name = "hash64", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
public static class VarDecimalHash implements DrillSimpleFunc {
@Param VarDecimalHolder in;
@Param BigIntHolder seed;
@Output BigIntHolder out;
-
public void setup() {
}
@@ -503,41 +435,6 @@ public class Hash64FunctionsWithSeed {
@Param BigIntHolder seed;
@Output BigIntHolder out;
-
- public void setup() {
- }
-
- public void eval() {
- if (in.isSet == 0) {
- out.value = seed.value;
- } else {
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash64(in.start, in.start + NullableDecimal28SparseHolder.WIDTH, in.buffer, seed.value);
- }
- }
- }
-
- @FunctionTemplate(name = "hash64", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class Decimal28Hash implements DrillSimpleFunc {
- @Param Decimal28SparseHolder in;
- @Param BigIntHolder seed;
- @Output BigIntHolder out;
-
-
- public void setup() {
- }
-
- public void eval() {
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash64(in.start, in.start + Decimal28SparseHolder.WIDTH, in.buffer, seed.value);
- }
- }
-
- @FunctionTemplate(name = "hash64", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class NullableDecimal28Hash implements DrillSimpleFunc {
- @Param NullableDecimal28SparseHolder in;
- @Param BigIntHolder seed;
- @Output BigIntHolder out;
-
-
public void setup() {
}
@@ -550,40 +447,6 @@ public class Hash64FunctionsWithSeed {
}
}
- @FunctionTemplate(name = "hash64", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class Decimal38Hash implements DrillSimpleFunc {
- @Param Decimal38SparseHolder in;
- @Param BigIntHolder seed;
- @Output BigIntHolder out;
-
-
- public void setup() {
- }
-
- public void eval() {
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash64(in.start, in.start + Decimal38SparseHolder.WIDTH, in.buffer, seed.value);
- }
- }
-
- @FunctionTemplate(name = "hash64", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class NullableDecimal38Hash implements DrillSimpleFunc {
- @Param NullableDecimal38SparseHolder in;
- @Param BigIntHolder seed;
- @Output BigIntHolder out;
-
-
- public void setup() {
- }
-
- public void eval() {
- if (in.isSet == 0) {
- out.value = seed.value;
- } else {
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash64(in.start, in.start + NullableDecimal38SparseHolder.WIDTH, in.buffer, seed.value);
- }
- }
- }
-
@FunctionTemplate(names = {"hash64", "hash64AsDouble"}, scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL )
public static class NullableBitHash implements DrillSimpleFunc {
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/Hash64WithSeedAsDouble.java b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/Hash64WithSeedAsDouble.java
index 13edf33c3..2497e1199 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/Hash64WithSeedAsDouble.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/Hash64WithSeedAsDouble.java
@@ -23,20 +23,12 @@ import org.apache.drill.exec.expr.annotations.FunctionTemplate.FunctionScope;
import org.apache.drill.exec.expr.annotations.Output;
import org.apache.drill.exec.expr.annotations.Param;
import org.apache.drill.exec.expr.holders.BigIntHolder;
-import org.apache.drill.exec.expr.holders.Decimal18Holder;
-import org.apache.drill.exec.expr.holders.Decimal28SparseHolder;
import org.apache.drill.exec.expr.holders.VarDecimalHolder;
import org.apache.drill.exec.expr.holders.NullableVarDecimalHolder;
-import org.apache.drill.exec.expr.holders.Decimal38SparseHolder;
-import org.apache.drill.exec.expr.holders.Decimal9Holder;
import org.apache.drill.exec.expr.holders.Float4Holder;
import org.apache.drill.exec.expr.holders.Float8Holder;
import org.apache.drill.exec.expr.holders.IntHolder;
import org.apache.drill.exec.expr.holders.NullableBigIntHolder;
-import org.apache.drill.exec.expr.holders.NullableDecimal18Holder;
-import org.apache.drill.exec.expr.holders.NullableDecimal28SparseHolder;
-import org.apache.drill.exec.expr.holders.NullableDecimal38SparseHolder;
-import org.apache.drill.exec.expr.holders.NullableDecimal9Holder;
import org.apache.drill.exec.expr.holders.NullableFloat4Holder;
import org.apache.drill.exec.expr.holders.NullableFloat8Holder;
import org.apache.drill.exec.expr.holders.NullableIntHolder;
@@ -49,6 +41,7 @@ import org.apache.drill.exec.expr.holders.NullableIntHolder;
* as expected we would need to hash the same value represented in different data types (int, bigint, float etc)
* to hash to the same node, this is why we cast all numeric values to double before performing the actual hash.
*/
+@SuppressWarnings("unused")
public class Hash64WithSeedAsDouble {
@FunctionTemplate(name = "hash64AsDouble", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL )
public static class NullableFloatHash implements DrillSimpleFunc {
@@ -196,84 +189,11 @@ public class Hash64WithSeedAsDouble {
}
@FunctionTemplate(name = "hash64AsDouble", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class Decimal9Hash implements DrillSimpleFunc {
- @Param Decimal9Holder in;
- @Param BigIntHolder seed;
- @Output BigIntHolder out;
-
-
- public void setup() {
- }
-
- public void eval() {
- java.math.BigDecimal input = new java.math.BigDecimal(java.math.BigInteger.valueOf(in.value), in.scale);
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash64(input.doubleValue(), seed.value);
- }
- }
-
- @FunctionTemplate(name = "hash64AsDouble", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class NullableDecimal9Hash implements DrillSimpleFunc {
- @Param NullableDecimal9Holder in;
- @Param BigIntHolder seed;
- @Output BigIntHolder out;
-
-
- public void setup() {
- }
-
- public void eval() {
- if (in.isSet == 0) {
- out.value = seed.value;
- } else {
- java.math.BigDecimal input = new java.math.BigDecimal(java.math.BigInteger.valueOf(in.value), in.scale);
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash64(input.doubleValue(), seed.value);
- }
- }
- }
-
- @FunctionTemplate(name = "hash64AsDouble", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class Decimal18Hash implements DrillSimpleFunc {
- @Param Decimal18Holder in;
- @Param BigIntHolder seed;
- @Output BigIntHolder out;
-
-
- public void setup() {
- }
-
- public void eval() {
- java.math.BigDecimal input = new java.math.BigDecimal(java.math.BigInteger.valueOf(in.value), in.scale);
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash64(input.doubleValue(), seed.value);
- }
- }
-
- @FunctionTemplate(name = "hash64AsDouble", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class NullableDecimal18Hash implements DrillSimpleFunc {
- @Param NullableDecimal18Holder in;
- @Param BigIntHolder seed;
- @Output BigIntHolder out;
-
-
- public void setup() {
- }
-
- public void eval() {
- if (in.isSet == 0) {
- out.value = seed.value;
- } else {
- java.math.BigDecimal input = new java.math.BigDecimal(java.math.BigInteger.valueOf(in.value), in.scale);
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash64(input.doubleValue(), seed.value);
- }
- }
- }
-
- @FunctionTemplate(name = "hash64AsDouble", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
public static class VarDecimalHash implements DrillSimpleFunc {
@Param VarDecimalHolder in;
@Param BigIntHolder seed;
@Output BigIntHolder out;
-
public void setup() {
}
@@ -290,7 +210,6 @@ public class Hash64WithSeedAsDouble {
@Param BigIntHolder seed;
@Output BigIntHolder out;
-
public void setup() {
}
@@ -304,81 +223,5 @@ public class Hash64WithSeedAsDouble {
}
}
}
-
- @FunctionTemplate(name = "hash64AsDouble", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class Decimal28Hash implements DrillSimpleFunc {
- @Param Decimal28SparseHolder in;
- @Param BigIntHolder seed;
- @Output BigIntHolder out;
-
-
- public void setup() {
- }
-
- public void eval() {
- java.math.BigDecimal input = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromSparse(in.buffer,
- in.start, in.nDecimalDigits, in.scale);
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash64(input.doubleValue(), seed.value);
- }
- }
-
- @FunctionTemplate(name = "hash64AsDouble", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class NullableDecimal28Hash implements DrillSimpleFunc {
- @Param NullableDecimal28SparseHolder in;
- @Param BigIntHolder seed;
- @Output BigIntHolder out;
-
-
- public void setup() {
- }
-
- public void eval() {
- if (in.isSet == 0) {
- out.value = seed.value;
- } else {
- java.math.BigDecimal input = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromSparse(in.buffer,
- in.start, in.nDecimalDigits, in.scale);
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash64(input.doubleValue(), seed.value);
- }
- }
- }
-
- @FunctionTemplate(name = "hash64AsDouble", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class Decimal38Hash implements DrillSimpleFunc {
- @Param Decimal38SparseHolder in;
- @Param BigIntHolder seed;
- @Output BigIntHolder out;
-
-
- public void setup() {
- }
-
- public void eval() {
- java.math.BigDecimal input = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromSparse(in.buffer,
- in.start, in.nDecimalDigits, in.scale);
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash64(input.doubleValue(), seed.value);
- }
- }
-
- @FunctionTemplate(name = "hash64AsDouble", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL)
- public static class NullableDecimal38Hash implements DrillSimpleFunc {
- @Param NullableDecimal38SparseHolder in;
- @Param BigIntHolder seed;
- @Output BigIntHolder out;
-
-
- public void setup() {
- }
-
- public void eval() {
- if (in.isSet == 0) {
- out.value = seed.value;
- } else {
- java.math.BigDecimal input = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromSparse(in.buffer,
- in.start, in.nDecimalDigits, in.scale);
- out.value = org.apache.drill.exec.expr.fn.impl.HashHelper.hash64(input.doubleValue(), seed.value);
- }
- }
- }
}
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/interpreter/InterpreterEvaluator.java b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/interpreter/InterpreterEvaluator.java
index 4d837d838..9e8af1b5a 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/interpreter/InterpreterEvaluator.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/interpreter/InterpreterEvaluator.java
@@ -19,6 +19,7 @@ package org.apache.drill.exec.expr.fn.interpreter;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
+import java.util.Objects;
import javax.annotation.Nullable;
import javax.inject.Inject;
@@ -243,6 +244,12 @@ public class InterpreterEvaluator {
}
@Override
+ public ValueHolder visitVarDecimalConstant(final ValueExpressions.VarDecimalExpression decExpr, Integer value) throws RuntimeException {
+ return getConstantValueHolder(decExpr.getBigDecimal().toString(), decExpr.getMajorType().getMinorType(),
+ buffer -> ValueHolderHelper.getVarDecimalHolder(Objects.requireNonNull(buffer), decExpr.getBigDecimal().toString()));
+ }
+
+ @Override
public ValueHolder visitDateConstant(ValueExpressions.DateExpression dateExpr,Integer value) throws RuntimeException {
return ValueHolderHelper.getDateHolder(dateExpr.getDate());
}
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/output/DecimalReturnTypeInference.java b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/output/DecimalReturnTypeInference.java
index ab9c3185c..442514f79 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/output/DecimalReturnTypeInference.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/output/DecimalReturnTypeInference.java
@@ -21,10 +21,10 @@ import org.apache.drill.common.exceptions.DrillRuntimeException;
import org.apache.drill.common.expression.LogicalExpression;
import org.apache.drill.common.expression.ValueExpressions;
import org.apache.drill.common.types.TypeProtos;
-import org.apache.drill.common.util.DecimalScalePrecisionAddFunction;
-import org.apache.drill.common.util.DecimalScalePrecisionDivideFunction;
-import org.apache.drill.common.util.DecimalScalePrecisionModFunction;
-import org.apache.drill.common.util.DecimalScalePrecisionMulFunction;
+import org.apache.drill.exec.planner.types.decimal.DecimalScalePrecisionAddFunction;
+import org.apache.drill.exec.planner.types.decimal.DecimalScalePrecisionDivideFunction;
+import org.apache.drill.exec.planner.types.decimal.DecimalScalePrecisionModFunction;
+import org.apache.drill.exec.planner.types.decimal.DecimalScalePrecisionMulFunction;
import org.apache.drill.exec.expr.annotations.FunctionTemplate;
import org.apache.drill.exec.expr.fn.FunctionAttributes;
import org.apache.drill.exec.expr.fn.FunctionUtils;
@@ -32,6 +32,8 @@ import org.apache.drill.exec.util.DecimalUtility;
import java.util.List;
+import static org.apache.drill.exec.planner.types.DrillRelDataTypeSystem.DRILL_REL_DATATYPE_SYSTEM;
+
public class DecimalReturnTypeInference {
/**
@@ -56,13 +58,17 @@ public class DecimalReturnTypeInference {
assert logicalExpressions.size() == 2;
+ TypeProtos.MajorType leftMajorType = logicalExpressions.get(0).getMajorType();
+ TypeProtos.MajorType rightMajorType = logicalExpressions.get(1).getMajorType();
+
DecimalScalePrecisionAddFunction outputScalePrec =
- new DecimalScalePrecisionAddFunction(logicalExpressions.get(0).getMajorType().getPrecision(),
- logicalExpressions.get(0).getMajorType().getScale(),
- logicalExpressions.get(1).getMajorType().getPrecision(),
- logicalExpressions.get(1).getMajorType().getScale());
+ new DecimalScalePrecisionAddFunction(
+ DecimalUtility.getDefaultPrecision(leftMajorType.getMinorType(), leftMajorType.getPrecision()),
+ leftMajorType.getScale(),
+ DecimalUtility.getDefaultPrecision(rightMajorType.getMinorType(), rightMajorType.getPrecision()),
+ rightMajorType.getScale());
return TypeProtos.MajorType.newBuilder()
- .setMinorType(DecimalUtility.getDecimalDataType(outputScalePrec.getOutputPrecision()))
+ .setMinorType(TypeProtos.MinorType.VARDECIMAL)
.setScale(outputScalePrec.getOutputScale())
.setPrecision(outputScalePrec.getOutputPrecision())
.setMode(mode)
@@ -93,7 +99,7 @@ public class DecimalReturnTypeInference {
.setMinorType(attributes.getReturnValue().getType().getMinorType())
.setScale(scale)
.setPrecision(precision)
- .setMode(TypeProtos.DataMode.REQUIRED)
+ .setMode(TypeProtos.DataMode.OPTIONAL)
.build();
}
}
@@ -118,8 +124,8 @@ public class DecimalReturnTypeInference {
throw new DrillRuntimeException("Decimal cast function invoked with incorrect arguments" + err);
}
- int scale = (int) ((ValueExpressions.LongExpression)(logicalExpressions.get(logicalExpressions.size() - 1))).getLong();
- int precision = (int) ((ValueExpressions.LongExpression)(logicalExpressions.get(logicalExpressions.size() - 2))).getLong();
+ int scale = ((ValueExpressions.IntExpression) logicalExpressions.get(logicalExpressions.size() - 1)).getInt();
+ int precision = ((ValueExpressions.IntExpression) logicalExpressions.get(logicalExpressions.size() - 2)).getInt();
return TypeProtos.MajorType.newBuilder()
.setMinorType(attributes.getReturnValue().getType().getMinorType())
.setScale(scale)
@@ -151,13 +157,17 @@ public class DecimalReturnTypeInference {
assert logicalExpressions.size() == 2;
+ TypeProtos.MajorType leftMajorType = logicalExpressions.get(0).getMajorType();
+ TypeProtos.MajorType rightMajorType = logicalExpressions.get(1).getMajorType();
+
DecimalScalePrecisionDivideFunction outputScalePrec =
- new DecimalScalePrecisionDivideFunction(logicalExpressions.get(0).getMajorType().getPrecision(),
- logicalExpressions.get(0).getMajorType().getScale(),
- logicalExpressions.get(1).getMajorType().getPrecision(),
- logicalExpressions.get(1).getMajorType().getScale());
+ new DecimalScalePrecisionDivideFunction(
+ DecimalUtility.getDefaultPrecision(leftMajorType.getMinorType(), leftMajorType.getPrecision()),
+ leftMajorType.getScale(),
+ DecimalUtility.getDefaultPrecision(rightMajorType.getMinorType(), rightMajorType.getPrecision()),
+ rightMajorType.getScale());
return TypeProtos.MajorType.newBuilder()
- .setMinorType(DecimalUtility.getDecimalDataType(outputScalePrec.getOutputPrecision()))
+ .setMinorType(TypeProtos.MinorType.VARDECIMAL)
.setScale(outputScalePrec.getOutputScale())
.setPrecision(outputScalePrec.getOutputPrecision())
.setMode(mode)
@@ -216,13 +226,17 @@ public class DecimalReturnTypeInference {
assert logicalExpressions.size() == 2;
+ TypeProtos.MajorType leftMajorType = logicalExpressions.get(0).getMajorType();
+ TypeProtos.MajorType rightMajorType = logicalExpressions.get(1).getMajorType();
+
DecimalScalePrecisionModFunction outputScalePrec =
- new DecimalScalePrecisionModFunction(logicalExpressions.get(0).getMajorType().getPrecision(),
- logicalExpressions.get(0).getMajorType().getScale(),
- logicalExpressions.get(1).getMajorType().getPrecision(),
- logicalExpressions.get(1).getMajorType().getScale());
+ new DecimalScalePrecisionModFunction(
+ DecimalUtility.getDefaultPrecision(leftMajorType.getMinorType(), leftMajorType.getPrecision()),
+ leftMajorType.getScale(),
+ DecimalUtility.getDefaultPrecision(rightMajorType.getMinorType(), rightMajorType.getPrecision()),
+ rightMajorType.getScale());
return TypeProtos.MajorType.newBuilder()
- .setMinorType(DecimalUtility.getDecimalDataType(outputScalePrec.getOutputPrecision()))
+ .setMinorType(TypeProtos.MinorType.VARDECIMAL)
.setScale(outputScalePrec.getOutputScale())
.setPrecision(outputScalePrec.getOutputPrecision())
.setMode(mode)
@@ -281,20 +295,47 @@ public class DecimalReturnTypeInference {
@Override
public TypeProtos.MajorType getType(List<LogicalExpression> logicalExpressions, FunctionAttributes attributes) {
int scale = 0;
- int precision = 0;
// Get the max scale and precision from the inputs
for (LogicalExpression e : logicalExpressions) {
scale = Math.max(scale, e.getMajorType().getScale());
- precision = Math.max(precision, e.getMajorType().getPrecision());
}
- return (TypeProtos.MajorType.newBuilder()
- .setMinorType(attributes.getReturnValue().getType().getMinorType())
+ return TypeProtos.MajorType.newBuilder()
+ .setMinorType(TypeProtos.MinorType.VARDECIMAL)
.setScale(scale)
- .setPrecision(38)
- .setMode(TypeProtos.DataMode.REQUIRED)
- .build());
+ .setPrecision(DRILL_REL_DATATYPE_SYSTEM.getMaxNumericPrecision())
+ .setMode(TypeProtos.DataMode.OPTIONAL)
+ .build();
+ }
+ }
+
+ /**
+ * Return type calculation implementation for functions with return type set as
+ * {@link org.apache.drill.exec.expr.annotations.FunctionTemplate.ReturnType#DECIMAL_AVG_AGGREGATE}.
+ * Resulting scale is calculated as the max of 6 and the scale of input.
+ * Resulting precision is max allowed numeric precision.
+ */
+ public static class DecimalAvgAggReturnTypeInference implements ReturnTypeInference {
+
+ public static final DecimalAvgAggReturnTypeInference INSTANCE = new DecimalAvgAggReturnTypeInference();
+
+ @Override
+ public TypeProtos.MajorType getType(List<LogicalExpression> logicalExpressions, FunctionAttributes attributes) {
+ int scale = 0;
+
+ // Get the max scale and precision from the inputs
+ for (LogicalExpression e : logicalExpressions) {
+ scale = Math.max(scale, e.getMajorType().getScale());
+ }
+
+ return TypeProtos.MajorType.newBuilder()
+ .setMinorType(TypeProtos.MinorType.VARDECIMAL)
+ .setScale(Math.min(Math.max(6, scale),
+ DRILL_REL_DATATYPE_SYSTEM.getMaxNumericScale()))
+ .setPrecision(DRILL_REL_DATATYPE_SYSTEM.getMaxNumericPrecision())
+ .setMode(TypeProtos.DataMode.OPTIONAL)
+ .build();
}
}
@@ -313,13 +354,17 @@ public class DecimalReturnTypeInference {
assert logicalExpressions.size() == 2;
+ TypeProtos.MajorType leftMajorType = logicalExpressions.get(0).getMajorType();
+ TypeProtos.MajorType rightMajorType = logicalExpressions.get(1).getMajorType();
+
DecimalScalePrecisionMulFunction outputScalePrec =
- new DecimalScalePrecisionMulFunction(logicalExpressions.get(0).getMajorType().getPrecision(),
- logicalExpressions.get(0).getMajorType().getScale(),
- logicalExpressions.get(1).getMajorType().getPrecision(),
- logicalExpressions.get(1).getMajorType().getScale());
+ new DecimalScalePrecisionMulFunction(
+ DecimalUtility.getDefaultPrecision(leftMajorType.getMinorType(), leftMajorType.getPrecision()),
+ leftMajorType.getScale(),
+ DecimalUtility.getDefaultPrecision(rightMajorType.getMinorType(), rightMajorType.getPrecision()),
+ rightMajorType.getScale());
return TypeProtos.MajorType.newBuilder()
- .setMinorType(DecimalUtility.getDecimalDataType(outputScalePrec.getOutputPrecision()))
+ .setMinorType(TypeProtos.MinorType.VARDECIMAL)
.setScale(outputScalePrec.getOutputScale())
.setPrecision(outputScalePrec.getOutputPrecision())
.setMode(mode)
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/ScanBatch.java b/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/ScanBatch.java
index a937c7a70..ea943b2ec 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/ScanBatch.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/ScanBatch.java
@@ -409,7 +409,9 @@ public class ScanBatch implements CloseableRecordBatch {
// Check if the field exists.
ValueVector v = fieldVectorMap.get(field.getName());
- if (v == null || v.getClass() != clazz) {
+ // for the cases when fields have a different scale or precision,
+ // the new vector should be used to handle the value correctly
+ if (v == null || !v.getField().getType().equals(field.getType())) {
// Field does not exist--add it to the map and the output container.
v = TypeHelper.getNewVector(field, allocator, callBack);
if (!clazz.isAssignableFrom(v.getClass())) {
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/join/JoinUtils.java b/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/join/JoinUtils.java
index 036f3cdcd..b6604d272 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/join/JoinUtils.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/join/JoinUtils.java
@@ -36,6 +36,7 @@ import org.apache.drill.exec.expr.ExpressionTreeMaterializer;
import org.apache.drill.exec.ops.FragmentContext;
import org.apache.drill.exec.record.VectorAccessible;
import org.apache.drill.exec.resolver.TypeCastRules;
+import org.apache.drill.exec.util.DecimalUtility;
import java.util.LinkedList;
import java.util.List;
@@ -119,8 +120,11 @@ public class JoinUtils {
* @return true if implicit cast is allowed false otherwise
*/
private static boolean allowImplicitCast(TypeProtos.MinorType input1, TypeProtos.MinorType input2) {
- // allow implicit cast if both the input types are numeric
- if (TypeCastRules.isNumericType(input1) && TypeCastRules.isNumericType(input2)) {
+ // allow implicit cast if both the input types are numeric and any of them is non-decimal
+ // or both of them are decimal
+ if (TypeCastRules.isNumericType(input1) && TypeCastRules.isNumericType(input2)
+ && ((!DecimalUtility.isDecimalType(input1) && !DecimalUtility.isDecimalType(input2))
+ || DecimalUtility.isDecimalType(input1) && DecimalUtility.isDecimalType(input2))) {
return true;
}
@@ -166,8 +170,9 @@ public class JoinUtils {
// currently we only support implicit casts if the input types are numeric or varchar/varbinary
if (!allowImplicitCast(rightType, leftType)) {
- throw new DrillRuntimeException(String.format("Join only supports implicit casts between " +
- "1. Numeric data\n 2. Varchar, Varbinary data 3. Date, Timestamp data " +
+ throw new DrillRuntimeException(String.format("Join only supports implicit casts between\n" +
+ "1. Numeric data (none of types is decimal or both of them are decimal)\n" +
+ "2. Varchar, Varbinary data\n3. Date, Timestamp data\n" +
"Left type: %s, Right type: %s. Add explicit casts to avoid this error", leftType, rightType));
}
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/join/NestedLoopJoinBatch.java b/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/join/NestedLoopJoinBatch.java
index c8b676e48..03bf58b36 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/join/NestedLoopJoinBatch.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/join/NestedLoopJoinBatch.java
@@ -121,6 +121,11 @@ public class NestedLoopJoinBatch extends AbstractBinaryRecordBatch<NestedLoopJoi
"outgoing" /* write container */,
EMIT_LEFT_CONSTANT, EMIT_LEFT);
+ private static final MappingSet SETUP_LEFT_MAPPING = new MappingSet("leftIndex" /* read index */, "outIndex" /* write index */,
+ "leftBatch" /* read container */,
+ "outgoing" /* write container */,
+ ClassGenerator.DEFAULT_CONSTANT_MAP, ClassGenerator.DEFAULT_SCALAR_MAP);
+
protected NestedLoopJoinBatch(NestedLoopJoinPOP popConfig, FragmentContext context, RecordBatch left, RecordBatch right) throws OutOfMemoryException {
super(popConfig, context, left, right);
Preconditions.checkNotNull(left);
@@ -220,7 +225,7 @@ public class NestedLoopJoinBatch extends AbstractBinaryRecordBatch<NestedLoopJoi
*/
private NestedLoopJoin setupWorker() throws IOException, ClassTransformationException, SchemaChangeException {
final CodeGenerator<NestedLoopJoin> nLJCodeGenerator = CodeGenerator.get(
- NestedLoopJoin.TEMPLATE_DEFINITION, context.getOptions());
+ SETUP_LEFT_MAPPING, NestedLoopJoin.TEMPLATE_DEFINITION, context.getOptions());
nLJCodeGenerator.plainJavaCapable(true);
// Uncomment out this line to debug the generated code.
// nLJCodeGenerator.saveCodeForDebugging(true);
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/ParquetPartitionDescriptor.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/ParquetPartitionDescriptor.java
index cbc530b40..aaf41f7c3 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/ParquetPartitionDescriptor.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/ParquetPartitionDescriptor.java
@@ -17,6 +17,8 @@
*/
package org.apache.drill.exec.planner;
+import com.google.common.primitives.Ints;
+import com.google.common.primitives.Longs;
import org.apache.calcite.rel.core.TableScan;
import org.apache.calcite.util.BitSets;
import org.apache.drill.common.expression.SchemaPath;
@@ -30,11 +32,9 @@ import org.apache.drill.exec.store.dfs.FormatSelection;
import org.apache.drill.exec.store.dfs.MetadataContext;
import org.apache.drill.exec.store.parquet.AbstractParquetGroupScan;
import org.apache.drill.exec.store.parquet.ParquetReaderUtility;
-import org.apache.drill.exec.util.DecimalUtility;
import org.apache.drill.exec.vector.NullableBigIntVector;
import org.apache.drill.exec.vector.NullableBitVector;
import org.apache.drill.exec.vector.NullableDateVector;
-import org.apache.drill.exec.vector.NullableDecimal18Vector;
import org.apache.drill.exec.vector.NullableFloat4Vector;
import org.apache.drill.exec.vector.NullableFloat8Vector;
import org.apache.drill.exec.vector.NullableIntVector;
@@ -48,6 +48,7 @@ import org.apache.drill.exec.vector.NullableUInt2Vector;
import org.apache.drill.exec.vector.NullableUInt4Vector;
import org.apache.drill.exec.vector.NullableVarBinaryVector;
import org.apache.drill.exec.vector.NullableVarCharVector;
+import org.apache.drill.exec.vector.NullableVarDecimalVector;
import org.apache.drill.exec.vector.ValueVector;
import com.google.common.collect.Lists;
@@ -311,32 +312,21 @@ public class ParquetPartitionDescriptor extends AbstractPartitionDescriptor {
varBinaryVector.getMutator().setSafe(index, bytes, 0, bytes.length);
return;
}
- case DECIMAL18: {
- NullableDecimal18Vector decimalVector = (NullableDecimal18Vector) v;
+ case VARDECIMAL: {
+ NullableVarDecimalVector decimalVector = (NullableVarDecimalVector) v;
Object s = groupScan.getPartitionValue(path, column, Object.class);
byte[] bytes;
if (s == null) {
decimalVector.getMutator().setNull(index);
return;
} else if (s instanceof Integer) {
- long value = DecimalUtility.getBigDecimalFromPrimitiveTypes(
- (Integer) s,
- majorType.getScale(),
- majorType.getPrecision()).longValue();
- decimalVector.getMutator().setSafe(index, value);
- return;
+ bytes = Ints.toByteArray((int) s);
} else if (s instanceof Long) {
- long value = DecimalUtility.getBigDecimalFromPrimitiveTypes(
- (Long) s,
- majorType.getScale(),
- majorType.getPrecision()).longValue();
- decimalVector.getMutator().setSafe(index, value);
- return;
+ bytes = Longs.toByteArray((long) s);
} else {
bytes = getBytes(type, s);
}
- long value = DecimalUtility.getBigDecimalFromByteArray(bytes, 0, bytes.length, majorType.getScale()).longValue();
- decimalVector.getMutator().setSafe(index, value);
+ decimalVector.getMutator().setSafe(index, bytes, 0, bytes.length);
return;
}
case DATE: {
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/common/DrillValuesRelBase.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/common/DrillValuesRelBase.java
index 96702ebf2..7b82ff315 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/common/DrillValuesRelBase.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/common/DrillValuesRelBase.java
@@ -47,7 +47,6 @@ import static org.apache.drill.exec.planner.logical.DrillOptiq.isLiteralNull;
*/
public abstract class DrillValuesRelBase extends Values implements DrillRelNode {
- private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(DrillValuesRelBase.class);
private static final ObjectMapper MAPPER = new ObjectMapper();
protected final JSONOptions content;
@@ -169,12 +168,13 @@ public abstract class DrillValuesRelBase extends Values implements DrillRelNode
return;
case DECIMAL:
+ // Converting exact decimal into double since values in the list may have different scales
+ // so the resulting scale wouldn't be calculated correctly
if (isLiteralNull(literal)) {
out.writeDoubleNull();
} else {
out.writeDouble(((BigDecimal) literal.getValue()).doubleValue());
}
- logger.warn("Converting exact decimal into approximate decimal. Should be fixed once full decimal support is implemented.");
return;
case VARCHAR:
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillAggregateRel.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillAggregateRel.java
index 21a4c90b3..55cd7bfc2 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillAggregateRel.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillAggregateRel.java
@@ -23,6 +23,8 @@ import org.apache.calcite.linq4j.Ord;
import org.apache.calcite.plan.RelOptCost;
import org.apache.calcite.plan.RelOptPlanner;
import org.apache.calcite.rel.metadata.RelMetadataQuery;
+import org.apache.calcite.sql.SqlKind;
+import org.apache.calcite.sql.type.SqlTypeName;
import org.apache.calcite.util.BitSets;
import org.apache.calcite.util.ImmutableBitSet;
import org.apache.drill.common.expression.ExpressionPosition;
@@ -91,8 +93,13 @@ public class DrillAggregateRel extends DrillAggregateRelBase implements DrillRel
// For avg, stddev_pop, stddev_samp, var_pop and var_samp, the ReduceAggregatesRule is supposed
// to convert them to use sum and count. Here, we make the cost of the original functions high
// enough such that the planner does not choose them and instead chooses the rewritten functions.
- if (name.equals("AVG") || name.equals("STDDEV_POP") || name.equals("STDDEV_SAMP")
- || name.equals("VAR_POP") || name.equals("VAR_SAMP")) {
+ // Except when AVG, STDDEV_POP, STDDEV_SAMP, VAR_POP and VAR_SAMP are used with DECIMAL type.
+ if ((name.equals(SqlKind.AVG.name())
+ || name.equals(SqlKind.STDDEV_POP.name())
+ || name.equals(SqlKind.STDDEV_SAMP.name())
+ || name.equals(SqlKind.VAR_POP.name())
+ || name.equals(SqlKind.VAR_SAMP.name()))
+ && aggCall.getType().getSqlTypeName() != SqlTypeName.DECIMAL) {
return planner.getCostFactory().makeHugeCost();
}
}
@@ -108,14 +115,13 @@ public class DrillAggregateRel extends DrillAggregateRelBase implements DrillRel
// for count(1).
if (args.isEmpty()) {
- args.add(new ValueExpressions.LongExpression(1l));
+ args.add(new ValueExpressions.LongExpression(1L));
}
- LogicalExpression expr = FunctionCallFactory.createExpression(call.getAggregation().getName().toLowerCase(), ExpressionPosition.UNKNOWN, args);
- return expr;
+ return FunctionCallFactory.createExpression(call.getAggregation().getName().toLowerCase(), ExpressionPosition.UNKNOWN, args);
}
- public static DrillAggregateRel convert(GroupingAggregate groupBy, ConversionContext value)
- throws InvalidRelException {
+ @SuppressWarnings("unused")
+ public static DrillAggregateRel convert(GroupingAggregate groupBy, ConversionContext value) {
throw new UnsupportedOperationException();
}
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillConstExecutor.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillConstExecutor.java
index 40382a738..ab27c7a83 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillConstExecutor.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillConstExecutor.java
@@ -62,6 +62,7 @@ import org.apache.drill.exec.expr.holders.NullableIntervalYearHolder;
import org.apache.drill.exec.expr.holders.NullableTimeHolder;
import org.apache.drill.exec.expr.holders.NullableTimeStampHolder;
import org.apache.drill.exec.expr.holders.NullableVarCharHolder;
+import org.apache.drill.exec.expr.holders.NullableVarDecimalHolder;
import org.apache.drill.exec.expr.holders.TimeHolder;
import org.apache.drill.exec.expr.holders.TimeStampHolder;
import org.apache.drill.exec.expr.holders.ValueHolder;
@@ -245,15 +246,30 @@ public class DrillConstExecutor implements RexExecutor {
false);
}
case VARDECIMAL: {
- VarDecimalHolder varDecimalOut = (VarDecimalHolder)output;
+ DrillBuf buffer;
+ int start;
+ int end;
+ int scale;
+ int precision;
+ if (materializedExpr.getMajorType().getMode() == TypeProtos.DataMode.OPTIONAL) {
+ NullableVarDecimalHolder varDecimalHolder = (NullableVarDecimalHolder) output;
+ buffer = varDecimalHolder.buffer;
+ start = varDecimalHolder.start;
+ end = varDecimalHolder.end;
+ scale = varDecimalHolder.scale;
+ precision = varDecimalHolder.precision;
+ } else {
+ VarDecimalHolder varDecimalHolder = (VarDecimalHolder) output;
+ buffer = varDecimalHolder.buffer;
+ start = varDecimalHolder.start;
+ end = varDecimalHolder.end;
+ scale = varDecimalHolder.scale;
+ precision = varDecimalHolder.precision;
+ }
return rexBuilder.makeLiteral(
- org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromDrillBuf(
- varDecimalOut.buffer,
- varDecimalOut.start,
- varDecimalOut.end - varDecimalOut.start,
- varDecimalOut.scale),
- TypeInferenceUtils.createCalciteTypeWithNullability(typeFactory, SqlTypeName.DECIMAL, newCall.getType().isNullable()),
- false);
+ org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromDrillBuf(buffer, start, end - start, scale),
+ typeFactory.createSqlType(SqlTypeName.DECIMAL, precision, scale),
+ false);
}
case DECIMAL28SPARSE: {
DrillBuf buffer;
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillOptiq.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillOptiq.java
index d1c22388d..fd791dd7f 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillOptiq.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillOptiq.java
@@ -61,6 +61,8 @@ import com.google.common.collect.Lists;
import org.apache.drill.exec.planner.physical.PlannerSettings;
import org.apache.drill.exec.work.ExecErrorConstants;
+import static org.apache.drill.exec.planner.physical.PlannerSettings.ENABLE_DECIMAL_DATA_TYPE;
+
/**
* Utilities for Drill's planner.
*/
@@ -314,20 +316,13 @@ public class DrillOptiq {
int precision = call.getType().getPrecision();
int scale = call.getType().getScale();
- // TODO: this may eventually need changes for VARDECIMAL
-
- if (precision <= 9) {
- castType = TypeProtos.MajorType.newBuilder().setMinorType(MinorType.DECIMAL9).setPrecision(precision).setScale(scale).build();
- } else if (precision <= 18) {
- castType = TypeProtos.MajorType.newBuilder().setMinorType(MinorType.DECIMAL18).setPrecision(precision).setScale(scale).build();
- } else if (precision <= 28) {
- // Inject a cast to SPARSE before casting to the dense type.
- castType = TypeProtos.MajorType.newBuilder().setMinorType(MinorType.DECIMAL28SPARSE).setPrecision(precision).setScale(scale).build();
- } else if (precision <= 38) {
- castType = TypeProtos.MajorType.newBuilder().setMinorType(MinorType.DECIMAL38SPARSE).setPrecision(precision).setScale(scale).build();
- } else {
- throw new UnsupportedOperationException("Only Decimal types with precision range 0 - 38 is supported");
- }
+ castType =
+ TypeProtos.MajorType
+ .newBuilder()
+ .setMinorType(MinorType.VARDECIMAL)
+ .setPrecision(precision)
+ .setScale(scale)
+ .build();
break;
case "INTERVAL_YEAR":
@@ -545,24 +540,21 @@ public class DrillOptiq {
return ValueExpressions.getInt(a);
case DECIMAL:
- /* TODO: Enable using Decimal literals once we have more functions implemented for Decimal
- * For now continue using Double instead of decimals
-
- int precision = ((BigDecimal) literal.getValue()).precision();
- if (precision <= 9) {
- return ValueExpressions.getDecimal9((BigDecimal)literal.getValue());
- } else if (precision <= 18) {
- return ValueExpressions.getDecimal18((BigDecimal)literal.getValue());
- } else if (precision <= 28) {
- return ValueExpressions.getDecimal28((BigDecimal)literal.getValue());
- } else if (precision <= 38) {
- return ValueExpressions.getDecimal38((BigDecimal)literal.getValue());
- } */
- if (isLiteralNull(literal)) {
- return createNullExpr(MinorType.FLOAT8);
+ if (context.getPlannerSettings().getOptions()
+ .getBoolean(ENABLE_DECIMAL_DATA_TYPE.getOptionName())) {
+ if (isLiteralNull(literal)) {
+ return new TypedNullConstant(
+ Types.withScaleAndPrecision(
+ MinorType.VARDECIMAL,
+ TypeProtos.DataMode.OPTIONAL,
+ literal.getType().getScale(),
+ literal.getType().getPrecision()));
+ }
+ return ValueExpressions.getVarDecimal((BigDecimal) literal.getValue());
}
double dbl = ((BigDecimal) literal.getValue()).doubleValue();
- logger.warn("Converting exact decimal into approximate decimal. Should be fixed once decimal is implemented.");
+ logger.warn("Converting exact decimal into approximate decimal.\n" +
+ "Please enable decimal data types using `planner.enable_decimal_data_type`.");
return ValueExpressions.getFloat8(dbl);
case VARCHAR:
if (isLiteralNull(literal)) {
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillReduceAggregatesRule.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillReduceAggregatesRule.java
index 496ac1a97..6b0576cb4 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillReduceAggregatesRule.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/logical/DrillReduceAggregatesRule.java
@@ -238,6 +238,20 @@ public class DrillReduceAggregatesRule extends RelOptRule {
return reduceSum(oldAggRel, oldCall, newCalls, aggCallMapping);
}
if (sqlAggFunction instanceof SqlAvgAggFunction) {
+ // for DECIMAL data types does not produce rewriting of complex calls,
+ // since SUM returns value with 38 precision and further handling of the value
+ // causes the loss of the scale
+ if (oldCall.getType().getSqlTypeName() == SqlTypeName.DECIMAL) {
+ return oldAggRel.getCluster().getRexBuilder().addAggCall(
+ oldCall,
+ oldAggRel.getGroupCount(),
+ oldAggRel.indicator,
+ newCalls,
+ aggCallMapping,
+ ImmutableList.of(getFieldType(
+ oldAggRel.getInput(),
+ oldCall.getArgList().get(0))));
+ }
final SqlKind subtype = sqlAggFunction.getKind();
switch (subtype) {
case AVG:
@@ -253,7 +267,7 @@ public class DrillReduceAggregatesRule extends RelOptRule {
oldAggRel, oldCall, true, true, newCalls, aggCallMapping,
inputExprs);
case STDDEV_SAMP:
- // replace original STDDEV_POP(x) with
+ // replace original STDDEV_SAMP(x) with
// SQRT(
// (SUM(x * x) - SUM(x) * SUM(x) / COUNT(x))
// / CASE COUNT(x) WHEN 1 THEN NULL ELSE COUNT(x) - 1 END)
@@ -268,7 +282,7 @@ public class DrillReduceAggregatesRule extends RelOptRule {
oldAggRel, oldCall, true, false, newCalls, aggCallMapping,
inputExprs);
case VAR_SAMP:
- // replace original VAR_POP(x) with
+ // replace original VAR_SAMP(x) with
// (SUM(x * x) - SUM(x) * SUM(x) / COUNT(x))
// / CASE COUNT(x) WHEN 1 THEN NULL ELSE COUNT(x) - 1 END
return reduceStddev(
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/SqlConverter.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/SqlConverter.java
index 69362d939..2366b8ad3 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/SqlConverter.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/SqlConverter.java
@@ -17,6 +17,7 @@
*/
package org.apache.drill.exec.planner.sql;
+import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
@@ -559,6 +560,19 @@ public class SqlConverter {
if (matchNullability) {
return makeAbstractCast(type, exp);
}
+ // for the case when BigDecimal literal has a scale or precision
+ // that differs from the value from specified RelDataType, cast cannot be removed
+ // TODO: remove this code when CALCITE-1468 is fixed
+ if (type.getSqlTypeName() == SqlTypeName.DECIMAL && exp instanceof RexLiteral) {
+ RexLiteral literal = (RexLiteral) exp;
+ Comparable value = literal.getValueAs(Comparable.class);
+ if (value instanceof BigDecimal) {
+ BigDecimal bigDecimal = (BigDecimal) value;
+ if (bigDecimal.scale() != type.getScale() || bigDecimal.precision() != type.getPrecision()) {
+ return makeAbstractCast(type, exp);
+ }
+ }
+ }
return super.makeCast(type, exp, false);
}
}
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/TypeInferenceUtils.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/TypeInferenceUtils.java
index c6c93209a..529546f54 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/TypeInferenceUtils.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/TypeInferenceUtils.java
@@ -18,6 +18,7 @@
package org.apache.drill.exec.planner.sql;
import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import org.apache.calcite.avatica.util.TimeUnit;
@@ -45,12 +46,16 @@ import org.apache.drill.common.expression.MajorTypeInLogicalExpression;
import org.apache.drill.common.exceptions.UserException;
import org.apache.drill.common.types.TypeProtos;
import org.apache.drill.common.types.Types;
+import org.apache.drill.common.util.CoreDecimalUtility;
+import org.apache.drill.exec.expr.annotations.FunctionTemplate;
import org.apache.drill.exec.expr.fn.DrillFuncHolder;
+import org.apache.drill.exec.planner.types.DrillRelDataTypeSystem;
import org.apache.drill.exec.resolver.FunctionResolver;
import org.apache.drill.exec.resolver.FunctionResolverFactory;
import org.apache.drill.exec.resolver.TypeCastRules;
import java.util.List;
+import java.util.Set;
public class TypeInferenceUtils {
private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(TypeInferenceUtils.class);
@@ -111,6 +116,7 @@ public class TypeInferenceUtils {
.put(SqlTypeName.INTERVAL_MINUTE, TypeProtos.MinorType.INTERVALDAY)
.put(SqlTypeName.INTERVAL_MINUTE_SECOND, TypeProtos.MinorType.INTERVALDAY)
.put(SqlTypeName.INTERVAL_SECOND, TypeProtos.MinorType.INTERVALDAY)
+ .put(SqlTypeName.DECIMAL, TypeProtos.MinorType.VARDECIMAL)
// SqlTypeName.CHAR is the type for Literals in Calcite, Drill treats Literals as VARCHAR also
.put(SqlTypeName.CHAR, TypeProtos.MinorType.VARCHAR)
@@ -154,10 +160,10 @@ public class TypeInferenceUtils {
.put("CONVERT_FROM", DrillDeferToExecSqlReturnTypeInference.INSTANCE)
// Functions that return the same type
- .put("LOWER", DrillSameSqlReturnTypeInference.INSTANCE)
- .put("UPPER", DrillSameSqlReturnTypeInference.INSTANCE)
- .put("INITCAP", DrillSameSqlReturnTypeInference.INSTANCE)
- .put("REVERSE", DrillSameSqlReturnTypeInference.INSTANCE)
+ .put("LOWER", DrillSameSqlReturnTypeInference.THE_SAME_RETURN_TYPE)
+ .put("UPPER", DrillSameSqlReturnTypeInference.THE_SAME_RETURN_TYPE)
+ .put("INITCAP", DrillSameSqlReturnTypeInference.THE_SAME_RETURN_TYPE)
+ .put("REVERSE", DrillSameSqlReturnTypeInference.THE_SAME_RETURN_TYPE)
// Window Functions
// RANKING
@@ -175,8 +181,8 @@ public class TypeInferenceUtils {
.put(SqlKind.LAG.name(), DrillLeadLagSqlReturnTypeInference.INSTANCE)
// FIRST_VALUE, LAST_VALUE
- .put(SqlKind.FIRST_VALUE.name(), DrillSameSqlReturnTypeInference.INSTANCE)
- .put(SqlKind.LAST_VALUE.name(), DrillSameSqlReturnTypeInference.INSTANCE)
+ .put(SqlKind.FIRST_VALUE.name(), DrillSameSqlReturnTypeInference.THE_SAME_RETURN_TYPE)
+ .put(SqlKind.LAST_VALUE.name(), DrillSameSqlReturnTypeInference.THE_SAME_RETURN_TYPE)
// Functions rely on DrillReduceAggregatesRule for expression simplification as opposed to getting evaluated directly
.put(SqlKind.AVG.name(), DrillAvgAggSqlReturnTypeInference.INSTANCE)
@@ -184,6 +190,18 @@ public class TypeInferenceUtils {
.put(SqlKind.STDDEV_SAMP.name(), DrillAvgAggSqlReturnTypeInference.INSTANCE)
.put(SqlKind.VAR_POP.name(), DrillAvgAggSqlReturnTypeInference.INSTANCE)
.put(SqlKind.VAR_SAMP.name(), DrillAvgAggSqlReturnTypeInference.INSTANCE)
+ .put(SqlKind.MIN.name(), DrillSameSqlReturnTypeInference.ALL_NULLABLE)
+ .put(SqlKind.MAX.name(), DrillSameSqlReturnTypeInference.ALL_NULLABLE)
+ .build();
+
+ /**
+ * Set of the decimal functions which return type cannot be determined exactly for some reasons at the current stage.
+ * For example functions which takes as an parameter scale or precision of return type.
+ */
+ private static final Set<String> SET_SCALE_DECIMAL_FUNCTIONS = ImmutableSet.<String> builder()
+ .add("ROUND")
+ .add("TRUNC")
+ .add("TRUNCATE")
.build();
/**
@@ -281,17 +299,27 @@ public class TypeInferenceUtils {
factory.createSqlType(SqlTypeName.ANY),
true);
}
+ } else if (SET_SCALE_DECIMAL_FUNCTIONS.contains(opBinding.getOperator().getName())
+ && getDrillTypeFromCalciteType(type) == TypeProtos.MinorType.VARDECIMAL) {
+ return factory.createTypeWithNullability(
+ factory.createSqlType(SqlTypeName.ANY),
+ true);
}
}
- final DrillFuncHolder func = resolveDrillFuncHolder(opBinding, functions);
- final RelDataType returnType = getReturnType(opBinding, func);
+ final FunctionCall functionCall = convertSqlOperatorBindingToFunctionCall(opBinding);
+ final DrillFuncHolder func = resolveDrillFuncHolder(opBinding, functions, functionCall);
+
+ final RelDataType returnType = getReturnType(opBinding,
+ func.getReturnType(functionCall.args), func.getNullHandling());
+
return returnType.getSqlTypeName() == SqlTypeName.VARBINARY
? createCalciteTypeWithNullability(factory, SqlTypeName.ANY, returnType.isNullable())
: returnType;
}
- private static RelDataType getReturnType(final SqlOperatorBinding opBinding, final DrillFuncHolder func) {
+ private static RelDataType getReturnType(final SqlOperatorBinding opBinding,
+ final TypeProtos.MajorType returnType, FunctionTemplate.NullHandling nullHandling) {
final RelDataTypeFactory factory = opBinding.getTypeFactory();
// least restrictive type (nullable ANY type)
@@ -299,7 +327,6 @@ public class TypeInferenceUtils {
factory.createSqlType(SqlTypeName.ANY),
true);
- final TypeProtos.MajorType returnType = func.getReturnType();
if (UNKNOWN_TYPE.equals(returnType)) {
return nullableAnyType;
}
@@ -318,7 +345,7 @@ public class TypeInferenceUtils {
break;
case REQUIRED:
- switch (func.getNullHandling()) {
+ switch (nullHandling) {
case INTERNAL:
isNullable = false;
break;
@@ -343,10 +370,7 @@ public class TypeInferenceUtils {
throw new UnsupportedOperationException();
}
- return createCalciteTypeWithNullability(
- factory,
- sqlTypeName,
- isNullable);
+ return convertToCalciteType(factory, returnType, isNullable);
}
}
@@ -381,15 +405,36 @@ public class TypeInferenceUtils {
isNullable);
}
+ // Determines SqlTypeName of the result.
+ // For the case when input may be implicitly casted to BIGINT, the type of result is BIGINT.
+ // Else for the case when input may be implicitly casted to FLOAT4, the type of result is DOUBLE.
+ // Else for the case when input may be implicitly casted to VARDECIMAL, the type of result is DECIMAL
+ // with the same scale as input and max allowed numeric precision.
+ // Else for the case when input may be implicitly casted to FLOAT8, the type of result is DOUBLE.
+ // When none of these conditions is satisfied, error is thrown.
+ // This order of checks is caused by the order of types in ResolverTypePrecedence.precedenceMap
final RelDataType operandType = opBinding.getOperandType(0);
final TypeProtos.MinorType inputMinorType = getDrillTypeFromCalciteType(operandType);
- if(TypeCastRules.getLeastRestrictiveType(Lists.newArrayList(inputMinorType, TypeProtos.MinorType.BIGINT))
+ if (TypeCastRules.getLeastRestrictiveType(Lists.newArrayList(inputMinorType, TypeProtos.MinorType.BIGINT))
== TypeProtos.MinorType.BIGINT) {
return createCalciteTypeWithNullability(
factory,
SqlTypeName.BIGINT,
isNullable);
- } else if(TypeCastRules.getLeastRestrictiveType(Lists.newArrayList(inputMinorType, TypeProtos.MinorType.FLOAT8))
+ } else if (TypeCastRules.getLeastRestrictiveType(Lists.newArrayList(inputMinorType, TypeProtos.MinorType.FLOAT4))
+ == TypeProtos.MinorType.FLOAT4) {
+ return createCalciteTypeWithNullability(
+ factory,
+ SqlTypeName.DOUBLE,
+ isNullable);
+ } else if (TypeCastRules.getLeastRestrictiveType(Lists.newArrayList(inputMinorType, TypeProtos.MinorType.VARDECIMAL))
+ == TypeProtos.MinorType.VARDECIMAL) {
+ RelDataType sqlType = factory.createSqlType(SqlTypeName.DECIMAL,
+ DrillRelDataTypeSystem.DRILL_REL_DATATYPE_SYSTEM.getMaxNumericPrecision(),
+ Math.min(operandType.getScale(),
+ DrillRelDataTypeSystem.DRILL_REL_DATATYPE_SYSTEM.getMaxNumericScale()));
+ return factory.createTypeWithNullability(sqlType, isNullable);
+ } else if (TypeCastRules.getLeastRestrictiveType(Lists.newArrayList(inputMinorType, TypeProtos.MinorType.FLOAT8))
== TypeProtos.MinorType.FLOAT8) {
return createCalciteTypeWithNullability(
factory,
@@ -669,10 +714,21 @@ public class TypeInferenceUtils {
}
private static class DrillSameSqlReturnTypeInference implements SqlReturnTypeInference {
- private static final DrillSameSqlReturnTypeInference INSTANCE = new DrillSameSqlReturnTypeInference();
+ private static final DrillSameSqlReturnTypeInference THE_SAME_RETURN_TYPE = new DrillSameSqlReturnTypeInference(true);
+ private static final DrillSameSqlReturnTypeInference ALL_NULLABLE = new DrillSameSqlReturnTypeInference(false);
+
+ private final boolean preserveNullability;
+
+ public DrillSameSqlReturnTypeInference(boolean preserveNullability) {
+ this.preserveNullability = preserveNullability;
+ }
+
@Override
public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
- return opBinding.getOperandType(0);
+ if (preserveNullability) {
+ return opBinding.getOperandType(0);
+ }
+ return opBinding.getTypeFactory().createTypeWithNullability(opBinding.getOperandType(0), true);
}
}
@@ -680,27 +736,72 @@ public class TypeInferenceUtils {
private static final DrillAvgAggSqlReturnTypeInference INSTANCE = new DrillAvgAggSqlReturnTypeInference();
@Override
public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
- final boolean isNullable = opBinding.getGroupCount() == 0 || opBinding.hasFilter() || opBinding.getOperandType(0).isNullable();
- return createCalciteTypeWithNullability(
- opBinding.getTypeFactory(),
- SqlTypeName.DOUBLE,
- isNullable);
+ final RelDataTypeFactory factory = opBinding.getTypeFactory();
+ // If there is group-by and the imput type is Non-nullable,
+ // the output is Non-nullable;
+ // Otherwise, the output is nullable.
+ final boolean isNullable = opBinding.getGroupCount() == 0
+ || opBinding.getOperandType(0).isNullable();
+
+ if (getDrillTypeFromCalciteType(opBinding.getOperandType(0)) == TypeProtos.MinorType.LATE) {
+ return createCalciteTypeWithNullability(
+ factory,
+ SqlTypeName.ANY,
+ isNullable);
+ }
+
+ // Determines SqlTypeName of the result.
+ // For the case when input may be implicitly casted to FLOAT4, the type of result is DOUBLE.
+ // Else for the case when input may be implicitly casted to VARDECIMAL, the type of result is DECIMAL
+ // with scale max(6, input) and max allowed numeric precision.
+ // Else for the case when input may be implicitly casted to FLOAT8, the type of result is DOUBLE.
+ // When none of these conditions is satisfied, error is thrown.
+ // This order of checks is caused by the order of types in ResolverTypePrecedence.precedenceMap
+ final RelDataType operandType = opBinding.getOperandType(0);
+ final TypeProtos.MinorType inputMinorType = getDrillTypeFromCalciteType(operandType);
+ if (TypeCastRules.getLeastRestrictiveType(Lists.newArrayList(inputMinorType, TypeProtos.MinorType.FLOAT4))
+ == TypeProtos.MinorType.FLOAT4) {
+ return createCalciteTypeWithNullability(
+ factory,
+ SqlTypeName.DOUBLE,
+ isNullable);
+ } else if (TypeCastRules.getLeastRestrictiveType(Lists.newArrayList(inputMinorType, TypeProtos.MinorType.VARDECIMAL))
+ == TypeProtos.MinorType.VARDECIMAL) {
+ RelDataType sqlType = factory.createSqlType(SqlTypeName.DECIMAL,
+ DrillRelDataTypeSystem.DRILL_REL_DATATYPE_SYSTEM.getMaxNumericPrecision(),
+ Math.min(Math.max(6, operandType.getScale()),
+ DrillRelDataTypeSystem.DRILL_REL_DATATYPE_SYSTEM.getMaxNumericScale()));
+ return factory.createTypeWithNullability(sqlType, isNullable);
+ } else if (TypeCastRules.getLeastRestrictiveType(Lists.newArrayList(inputMinorType, TypeProtos.MinorType.FLOAT8))
+ == TypeProtos.MinorType.FLOAT8) {
+ return createCalciteTypeWithNullability(
+ factory,
+ SqlTypeName.DOUBLE,
+ isNullable);
+ } else {
+ throw UserException
+ .functionError()
+ .message(String.format("%s does not support operand types (%s)",
+ opBinding.getOperator().getName(),
+ opBinding.getOperandType(0).getSqlTypeName()))
+ .build(logger);
+ }
}
}
- private static DrillFuncHolder resolveDrillFuncHolder(final SqlOperatorBinding opBinding, final List<DrillFuncHolder> functions) {
- final FunctionCall functionCall = convertSqlOperatorBindingToFunctionCall(opBinding);
+ private static DrillFuncHolder resolveDrillFuncHolder(final SqlOperatorBinding opBinding,
+ final List<DrillFuncHolder> functions, FunctionCall functionCall) {
final FunctionResolver functionResolver = FunctionResolverFactory.getResolver(functionCall);
final DrillFuncHolder func = functionResolver.getBestMatch(functions, functionCall);
// Throw an exception
// if no DrillFuncHolder matched for the given list of operand types
- if(func == null) {
- String operandTypes = "";
- for(int i = 0; i < opBinding.getOperandCount(); ++i) {
- operandTypes += opBinding.getOperandType(i).getSqlTypeName();
- if(i < opBinding.getOperandCount() - 1) {
- operandTypes += ",";
+ if (func == null) {
+ StringBuilder operandTypes = new StringBuilder();
+ for (int i = 0; i < opBinding.getOperandCount(); ++i) {
+ operandTypes.append(opBinding.getOperandType(i).getSqlTypeName());
+ if (i < opBinding.getOperandCount() - 1) {
+ operandTypes.append(",");
}
}
@@ -708,7 +809,7 @@ public class TypeInferenceUtils {
.functionError()
.message(String.format("%s does not support operand types (%s)",
opBinding.getOperator().getName(),
- operandTypes))
+ operandTypes.toString()))
.build(logger);
}
return func;
@@ -768,6 +869,25 @@ public class TypeInferenceUtils {
}
/**
+ * Creates a RelDataType using specified RelDataTypeFactory which corresponds to specified TypeProtos.MajorType.
+ *
+ * @param typeFactory RelDataTypeFactory used to create the RelDataType
+ * @param drillType the given TypeProtos.MajorType
+ * @param isNullable nullability of the resulting type
+ * @return RelDataType which corresponds to specified TypeProtos.MajorType
+ */
+ public static RelDataType convertToCalciteType(RelDataTypeFactory typeFactory,
+ TypeProtos.MajorType drillType, boolean isNullable) {
+ SqlTypeName sqlTypeName = getCalciteTypeFromDrillType(drillType.getMinorType());
+ if (sqlTypeName == SqlTypeName.DECIMAL) {
+ return typeFactory.createTypeWithNullability(
+ typeFactory.createSqlType(sqlTypeName, drillType.getPrecision(),
+ drillType.getScale()), isNullable);
+ }
+ return createCalciteTypeWithNullability(typeFactory, sqlTypeName, isNullable);
+ }
+
+ /**
* Given a SqlOperatorBinding, convert it to FunctionCall
* @param opBinding the given SqlOperatorBinding
* @return FunctionCall the converted FunctionCall
@@ -778,22 +898,28 @@ public class TypeInferenceUtils {
for (int i = 0; i < opBinding.getOperandCount(); ++i) {
final RelDataType type = opBinding.getOperandType(i);
final TypeProtos.MinorType minorType = getDrillTypeFromCalciteType(type);
- final TypeProtos.MajorType majorType;
- if (type.isNullable()) {
- majorType = Types.optional(minorType);
- } else {
- majorType = Types.required(minorType);
+ TypeProtos.DataMode dataMode =
+ type.isNullable() ? TypeProtos.DataMode.OPTIONAL : TypeProtos.DataMode.REQUIRED;
+
+ TypeProtos.MajorType.Builder builder =
+ TypeProtos.MajorType.newBuilder()
+ .setMode(dataMode)
+ .setMinorType(minorType);
+
+ if (CoreDecimalUtility.isDecimalType(minorType)) {
+ builder
+ .setScale(type.getScale())
+ .setPrecision(type.getPrecision());
}
- args.add(new MajorTypeInLogicalExpression(majorType));
+ args.add(new MajorTypeInLogicalExpression(builder.build()));
}
final String drillFuncName = FunctionCallFactory.replaceOpWithFuncName(opBinding.getOperator().getName());
- final FunctionCall functionCall = new FunctionCall(
+ return new FunctionCall(
drillFuncName,
args,
ExpressionPosition.UNKNOWN);
- return functionCall;
}
/**
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/handlers/FindLimit0Visitor.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/handlers/FindLimit0Visitor.java
index 03d5f75f0..8031609b8 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/handlers/FindLimit0Visitor.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/handlers/FindLimit0Visitor.java
@@ -30,9 +30,6 @@ import org.apache.calcite.rel.logical.LogicalMinus;
import org.apache.calcite.rel.logical.LogicalSort;
import org.apache.calcite.rel.logical.LogicalUnion;
import org.apache.calcite.rel.type.RelDataTypeField;
-import org.apache.calcite.rex.RexLiteral;
-import org.apache.calcite.rex.RexNode;
-import org.apache.calcite.sql.SqlKind;
import org.apache.calcite.sql.type.SqlTypeName;
import org.apache.drill.common.exceptions.ExecutionSetupException;
import org.apache.drill.common.types.TypeProtos;
@@ -62,7 +59,6 @@ public class FindLimit0Visitor extends RelShuttleImpl {
// private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(FindLimit0Visitor.class);
// Some types are excluded in this set:
- // + DECIMAL type is not fully supported in general.
// + VARBINARY is not fully tested.
// + MAP, ARRAY are currently not exposed to the planner.
// + TINYINT, SMALLINT are defined in the Drill type system but have been turned off for now.
@@ -77,7 +73,7 @@ public class FindLimit0Visitor extends RelShuttleImpl {
SqlTypeName.INTERVAL_MONTH, SqlTypeName.INTERVAL_DAY, SqlTypeName.INTERVAL_DAY_HOUR,
SqlTypeName.INTERVAL_DAY_MINUTE, SqlTypeName.INTERVAL_DAY_SECOND, SqlTypeName.INTERVAL_HOUR,
SqlTypeName.INTERVAL_HOUR_MINUTE, SqlTypeName.INTERVAL_HOUR_SECOND, SqlTypeName.INTERVAL_MINUTE,
- SqlTypeName.INTERVAL_MINUTE_SECOND, SqlTypeName.INTERVAL_SECOND, SqlTypeName.CHAR)
+ SqlTypeName.INTERVAL_MINUTE_SECOND, SqlTypeName.INTERVAL_SECOND, SqlTypeName.CHAR, SqlTypeName.DECIMAL)
.build();
/**
@@ -101,7 +97,10 @@ public class FindLimit0Visitor extends RelShuttleImpl {
.setMode(field.getType().isNullable() ? TypeProtos.DataMode.OPTIONAL : TypeProtos.DataMode.REQUIRED)
.setMinorType(TypeInferenceUtils.getDrillTypeFromCalciteType(sqlTypeName));
- if (TypeInferenceUtils.isScalarStringType(sqlTypeName)) {
+ if (sqlTypeName == SqlTypeName.DECIMAL) {
+ builder.setScale(field.getType().getScale());
+ builder.setPrecision(field.getType().getPrecision());
+ } else if (TypeInferenceUtils.isScalarStringType(sqlTypeName)) {
builder.setPrecision(field.getType().getPrecision());
}
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/types/DrillRelDataTypeSystem.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/types/DrillRelDataTypeSystem.java
index 7f3db6671..c32a28dba 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/types/DrillRelDataTypeSystem.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/types/DrillRelDataTypeSystem.java
@@ -19,7 +19,6 @@ package org.apache.drill.exec.planner.types;
import org.apache.calcite.rel.type.RelDataTypeSystem;
import org.apache.calcite.rel.type.RelDataTypeSystemImpl;
-import org.apache.calcite.sql.type.SqlTypeName;
public class DrillRelDataTypeSystem extends RelDataTypeSystemImpl {
diff --git a/common/src/main/java/org/apache/drill/common/util/DecimalScalePrecisionAddFunction.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/types/decimal/DecimalScalePrecisionAddFunction.java
index 77a2e7d94..138f97f63 100644
--- a/common/src/main/java/org/apache/drill/common/util/DecimalScalePrecisionAddFunction.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/types/decimal/DecimalScalePrecisionAddFunction.java
@@ -15,7 +15,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.drill.common.util;
+package org.apache.drill.exec.planner.types.decimal;
public class DecimalScalePrecisionAddFunction extends DrillBaseComputeScalePrecision {
@@ -31,10 +31,6 @@ public class DecimalScalePrecisionAddFunction extends DrillBaseComputeScalePreci
outputPrecision = (outputScale + maxResultIntegerDigits);
- // If we are beyond the maximum precision range, cut down the fractional part
- if (outputPrecision > 38) {
- outputPrecision = 38;
- outputScale = (outputPrecision - maxResultIntegerDigits >= 0) ? (outputPrecision - maxResultIntegerDigits) : 0;
- }
+ checkPrecisionRange();
}
}
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/types/decimal/DecimalScalePrecisionDivideFunction.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/types/decimal/DecimalScalePrecisionDivideFunction.java
new file mode 100644
index 000000000..eb79d44ae
--- /dev/null
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/types/decimal/DecimalScalePrecisionDivideFunction.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.drill.exec.planner.types.decimal;
+
+import static org.apache.drill.exec.planner.types.DrillRelDataTypeSystem.DRILL_REL_DATATYPE_SYSTEM;
+
+public class DecimalScalePrecisionDivideFunction extends DrillBaseComputeScalePrecision {
+
+ public DecimalScalePrecisionDivideFunction(int leftPrecision, int leftScale, int rightPrecision, int rightScale) {
+ super(leftPrecision, leftScale, rightPrecision, rightScale);
+ }
+
+ @Override
+ public void computeScalePrecision(int leftPrecision, int leftScale, int rightPrecision, int rightScale) {
+
+ // compute the output scale and precision here
+ int maxResultIntegerDigits = Math.min(leftPrecision - leftScale + rightScale, MAX_NUMERIC_PRECISION);
+ outputScale = Math.max(6, leftScale + rightPrecision + 1);
+ outputScale = Math.min(outputScale, MAX_NUMERIC_PRECISION - maxResultIntegerDigits);
+ outputScale = Math.min(outputScale, DRILL_REL_DATATYPE_SYSTEM.getMaxNumericScale());
+ outputPrecision = maxResultIntegerDigits + outputScale;
+ }
+}
diff --git a/common/src/main/java/org/apache/drill/common/util/DecimalScalePrecisionModFunction.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/types/decimal/DecimalScalePrecisionModFunction.java
index 075a50bd2..6901580eb 100644
--- a/common/src/main/java/org/apache/drill/common/util/DecimalScalePrecisionModFunction.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/types/decimal/DecimalScalePrecisionModFunction.java
@@ -15,8 +15,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.drill.common.util;
+package org.apache.drill.exec.planner.types.decimal;
+import static org.apache.drill.exec.planner.types.DrillRelDataTypeSystem.DRILL_REL_DATATYPE_SYSTEM;
public class DecimalScalePrecisionModFunction extends DrillBaseComputeScalePrecision {
@@ -31,7 +32,7 @@ public class DecimalScalePrecisionModFunction extends DrillBaseComputeScalePreci
outputScale = Math.max(leftScale, rightScale);
int leftIntegerDigits = leftPrecision - leftScale;
- outputPrecision = CoreDecimalUtility.getPrecisionRange(outputScale + leftIntegerDigits);
+ outputPrecision = DRILL_REL_DATATYPE_SYSTEM.getMaxNumericPrecision();
if (outputScale + leftIntegerDigits > outputPrecision) {
outputScale = outputPrecision - leftIntegerDigits;
diff --git a/common/src/main/java/org/apache/drill/common/util/DecimalScalePrecisionMulFunction.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/types/decimal/DecimalScalePrecisionMulFunction.java
index 3caed6a45..2a8b22b9d 100644
--- a/common/src/main/java/org/apache/drill/common/util/DecimalScalePrecisionMulFunction.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/types/decimal/DecimalScalePrecisionMulFunction.java
@@ -15,7 +15,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.drill.common.util;
+package org.apache.drill.exec.planner.types.decimal;
/*
* Here we compute the output scale and precision of the multiply function.
@@ -32,15 +32,10 @@ public class DecimalScalePrecisionMulFunction extends DrillBaseComputeScalePreci
public void computeScalePrecision(int leftPrecision, int leftScale, int rightPrecision, int rightScale) {
// compute the output scale and precision here
outputScale = leftScale + rightScale;
- int integerDigits = (leftPrecision - leftScale) + (rightPrecision - rightScale);
- outputPrecision = integerDigits + outputScale;
+ outputPrecision = leftPrecision + rightPrecision;
- // If we are beyond the maximum precision range, cut down the fractional part
- if (outputPrecision > 38) {
- outputPrecision = 38;
- outputScale = (outputPrecision - integerDigits >= 0) ? (outputPrecision - integerDigits) : 0;
- }
+ checkPrecisionRange();
}
}
diff --git a/common/src/main/java/org/apache/drill/common/util/DrillBaseComputeScalePrecision.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/types/decimal/DrillBaseComputeScalePrecision.java
index 4f1135178..1c3c18667 100644
--- a/common/src/main/java/org/apache/drill/common/util/DrillBaseComputeScalePrecision.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/types/decimal/DrillBaseComputeScalePrecision.java
@@ -15,9 +15,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.drill.common.util;
+package org.apache.drill.exec.planner.types.decimal;
+
+import static org.apache.drill.exec.planner.types.DrillRelDataTypeSystem.DRILL_REL_DATATYPE_SYSTEM;
public abstract class DrillBaseComputeScalePrecision {
+ protected final static int MAX_NUMERIC_PRECISION = DRILL_REL_DATATYPE_SYSTEM.getMaxNumericPrecision();
+
protected int outputScale = 0;
protected int outputPrecision = 0;
@@ -34,4 +38,15 @@ public abstract class DrillBaseComputeScalePrecision {
public int getOutputPrecision() {
return outputPrecision;
}
+
+ /**
+ * Cuts down the fractional part if the current precision
+ * exceeds the maximum precision range.
+ */
+ protected void checkPrecisionRange() {
+ if (outputPrecision > MAX_NUMERIC_PRECISION) {
+ outputScale = outputScale - (outputPrecision - MAX_NUMERIC_PRECISION);
+ outputPrecision = MAX_NUMERIC_PRECISION;
+ }
+ }
}
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/record/VectorContainer.java b/exec/java-exec/src/main/java/org/apache/drill/exec/record/VectorContainer.java
index c46efaff2..03e9249cc 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/record/VectorContainer.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/record/VectorContainer.java
@@ -136,10 +136,9 @@ public class VectorContainer implements VectorAccessible {
public <T extends ValueVector> T addOrGet(final MaterializedField field, final SchemaChangeCallBack callBack) {
final TypedFieldId id = getValueVectorId(SchemaPath.getSimplePath(field.getName()));
final ValueVector vector;
- final Class<?> clazz = TypeHelper.getValueVectorClass(field.getType().getMinorType(), field.getType().getMode());
if (id != null) {
vector = getValueAccessorById(id.getFieldIds()).getValueVector();
- if (id.getFieldIds().length == 1 && clazz != null && !clazz.isAssignableFrom(vector.getClass())) {
+ if (id.getFieldIds().length == 1 && !vector.getField().getType().equals(field.getType())) {
final ValueVector newVector = TypeHelper.getNewVector(field, this.getAllocator(), callBack);
replace(vector, newVector);
return (T) newVector;
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/resolver/ExactFunctionResolver.java b/exec/java-exec/src/main/java/org/apache/drill/exec/resolver/ExactFunctionResolver.java
index 73776b1fa..ddbd8039c 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/resolver/ExactFunctionResolver.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/resolver/ExactFunctionResolver.java
@@ -27,7 +27,6 @@ import java.util.List;
public class ExactFunctionResolver implements FunctionResolver {
-
/*
* This function resolves the input call to a func holder only if all
* the input argument types match exactly with the func holder arguments. This is used when we
@@ -37,17 +36,17 @@ public class ExactFunctionResolver implements FunctionResolver {
@Override
public DrillFuncHolder getBestMatch(List<DrillFuncHolder> methods, FunctionCall call) {
- int currcost;
+ int currCost;
- for (DrillFuncHolder h : methods) {
- final List<TypeProtos.MajorType> argumentTypes = Lists.newArrayList();
- for (LogicalExpression expression : call.args) {
- argumentTypes.add(expression.getMajorType());
- }
- currcost = TypeCastRules.getCost(argumentTypes, h);
+ final List<TypeProtos.MajorType> argumentTypes = Lists.newArrayList();
+ for (LogicalExpression expression : call.args) {
+ argumentTypes.add(expression.getMajorType());
+ }
+ for (DrillFuncHolder h : methods) {
+ currCost = TypeCastRules.getCost(argumentTypes, h);
// Return if we found a function that has an exact match with the input arguments
- if (currcost == 0){
+ if (currCost == 0) {
return h;
}
}
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/resolver/ResolverTypePrecedence.java b/exec/java-exec/src/main/java/org/apache/drill/exec/resolver/ResolverTypePrecedence.java
index f3df7b647..247594f68 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/resolver/ResolverTypePrecedence.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/resolver/ResolverTypePrecedence.java
@@ -42,7 +42,7 @@ public class ResolverTypePrecedence {
* tinyint could be promoted into int; but int could NOT be promoted into tinyint (due to possible precision loss).
*/
int i = 0;
- precedenceMap = new HashMap<MinorType, Integer>();
+ precedenceMap = new HashMap<>();
precedenceMap.put(MinorType.NULL, i += 2); // NULL is legal to implicitly be promoted to any other type
precedenceMap.put(MinorType.FIXEDBINARY, i += 2); // Fixed-length is promoted to var length
precedenceMap.put(MinorType.VARBINARY, i += 2);
@@ -107,12 +107,6 @@ public class ResolverTypePrecedence {
rule.add(MinorType.UINT2);
rule.add(MinorType.UINT4);
rule.add(MinorType.UINT8);
- rule.add(MinorType.DECIMAL9);
- rule.add(MinorType.DECIMAL18);
- rule.add(MinorType.DECIMAL28SPARSE);
- rule.add(MinorType.DECIMAL28DENSE);
- rule.add(MinorType.DECIMAL38SPARSE);
- rule.add(MinorType.DECIMAL38DENSE);
rule.add(MinorType.VARDECIMAL);
rule.add(MinorType.MONEY);
rule.add(MinorType.FLOAT4);
@@ -140,6 +134,34 @@ public class ResolverTypePrecedence {
rule.add(MinorType.VARCHAR);
secondaryImplicitCastRules.put(MinorType.VARBINARY, rule);
- }
+ rule = new HashSet<>();
+
+ // Be able to implicitly cast to VARDECIMAL
+ rule.add(MinorType.FLOAT8);
+ secondaryImplicitCastRules.put(MinorType.VARDECIMAL, rule);
+
+ rule = new HashSet<>();
+
+ // Be able to implicitly cast to DECIMAL9
+ rule.add(MinorType.VARDECIMAL);
+ secondaryImplicitCastRules.put(MinorType.DECIMAL9, rule);
+
+ rule = new HashSet<>();
+ // Be able to implicitly cast to DECIMAL18
+ rule.add(MinorType.VARDECIMAL);
+ secondaryImplicitCastRules.put(MinorType.DECIMAL18, rule);
+
+ rule = new HashSet<>();
+
+ // Be able to implicitly cast to DECIMAL28SPARSE
+ rule.add(MinorType.VARDECIMAL);
+ secondaryImplicitCastRules.put(MinorType.DECIMAL28SPARSE, rule);
+
+ rule = new HashSet<>();
+
+ // Be able to implicitly cast to DECIMAL38SPARSE
+ rule.add(MinorType.VARDECIMAL);
+ secondaryImplicitCastRules.put(MinorType.DECIMAL38SPARSE, rule);
+ }
}
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/resolver/TypeCastRules.java b/exec/java-exec/src/main/java/org/apache/drill/exec/resolver/TypeCastRules.java
index d90c16c32..93bcf58df 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/resolver/TypeCastRules.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/resolver/TypeCastRules.java
@@ -30,11 +30,12 @@ import org.apache.drill.common.types.TypeProtos.MajorType;
import org.apache.drill.common.types.TypeProtos.MinorType;
import org.apache.drill.exec.expr.annotations.FunctionTemplate.NullHandling;
import org.apache.drill.exec.expr.fn.DrillFuncHolder;
-import org.apache.drill.exec.util.DecimalUtility;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
+import static org.apache.drill.exec.planner.types.DrillRelDataTypeSystem.DRILL_REL_DATATYPE_SYSTEM;
+
public class TypeCastRules {
private static Map<MinorType, Set<MinorType>> rules;
@@ -183,6 +184,7 @@ public class TypeCastRules {
rule.add(MinorType.DECIMAL28DENSE);
rule.add(MinorType.DECIMAL38SPARSE);
rule.add(MinorType.DECIMAL38DENSE);
+ rule.add(MinorType.VARDECIMAL);
rule.add(MinorType.MONEY);
rule.add(MinorType.FLOAT4);
rule.add(MinorType.FLOAT8);
@@ -226,122 +228,31 @@ public class TypeCastRules {
/** DECIMAL9 cast able from **/
rule = new HashSet<>();
- rule.add(MinorType.TINYINT);
- rule.add(MinorType.SMALLINT);
- rule.add(MinorType.INT);
- rule.add(MinorType.BIGINT);
- rule.add(MinorType.UINT1);
- rule.add(MinorType.UINT2);
- rule.add(MinorType.UINT4);
- rule.add(MinorType.UINT8);
rule.add(MinorType.DECIMAL9);
- rule.add(MinorType.DECIMAL18);
- rule.add(MinorType.DECIMAL28SPARSE);
- rule.add(MinorType.DECIMAL28DENSE);
- rule.add(MinorType.DECIMAL38SPARSE);
- rule.add(MinorType.DECIMAL38DENSE);
rule.add(MinorType.VARDECIMAL);
- rule.add(MinorType.MONEY);
- rule.add(MinorType.FLOAT4);
- rule.add(MinorType.FLOAT8);
- rule.add(MinorType.BIT);
- rule.add(MinorType.FIXEDCHAR);
- rule.add(MinorType.FIXED16CHAR);
- rule.add(MinorType.FIXEDBINARY);
- rule.add(MinorType.VARCHAR);
- rule.add(MinorType.VAR16CHAR);
- rule.add(MinorType.VARBINARY);
rules.put(MinorType.DECIMAL9, rule);
/** DECIMAL18 cast able from **/
rule = new HashSet<>();
- rule.add(MinorType.TINYINT);
- rule.add(MinorType.SMALLINT);
- rule.add(MinorType.INT);
- rule.add(MinorType.BIGINT);
- rule.add(MinorType.UINT1);
- rule.add(MinorType.UINT2);
- rule.add(MinorType.UINT4);
- rule.add(MinorType.UINT8);
- rule.add(MinorType.DECIMAL9);
rule.add(MinorType.DECIMAL18);
- rule.add(MinorType.DECIMAL28SPARSE);
- rule.add(MinorType.DECIMAL28DENSE);
- rule.add(MinorType.DECIMAL38SPARSE);
- rule.add(MinorType.DECIMAL38DENSE);
- rule.add(MinorType.VARDECIMAL); // TODO: implement conversion between VARDECIMAL and other types??
- rule.add(MinorType.MONEY);
- rule.add(MinorType.FLOAT4);
- rule.add(MinorType.FLOAT8);
- rule.add(MinorType.BIT);
- rule.add(MinorType.FIXEDCHAR);
- rule.add(MinorType.FIXED16CHAR);
- rule.add(MinorType.FIXEDBINARY);
- rule.add(MinorType.VARCHAR);
- rule.add(MinorType.VAR16CHAR);
- rule.add(MinorType.VARBINARY);
+ rule.add(MinorType.VARDECIMAL);
rules.put(MinorType.DECIMAL18, rule);
/** DECIMAL28Dense cast able from **/
rule = new HashSet<>();
- rule.add(MinorType.TINYINT);
- rule.add(MinorType.SMALLINT);
- rule.add(MinorType.INT);
- rule.add(MinorType.BIGINT);
- rule.add(MinorType.UINT1);
- rule.add(MinorType.UINT2);
- rule.add(MinorType.UINT4);
- rule.add(MinorType.UINT8);
- rule.add(MinorType.DECIMAL9);
- rule.add(MinorType.DECIMAL18);
- rule.add(MinorType.DECIMAL28SPARSE);
rule.add(MinorType.DECIMAL28DENSE);
- rule.add(MinorType.DECIMAL38SPARSE);
- rule.add(MinorType.DECIMAL38DENSE);
- rule.add(MinorType.VARDECIMAL); // TODO: implement conversion between VARDECIMAL and other types??
- rule.add(MinorType.MONEY);
- rule.add(MinorType.FLOAT4);
- rule.add(MinorType.FLOAT8);
- rule.add(MinorType.BIT);
- rule.add(MinorType.FIXEDCHAR);
- rule.add(MinorType.FIXED16CHAR);
- rule.add(MinorType.FIXEDBINARY);
- rule.add(MinorType.VARCHAR);
- rule.add(MinorType.VAR16CHAR);
- rule.add(MinorType.VARBINARY);
+ rule.add(MinorType.VARDECIMAL);
rules.put(MinorType.DECIMAL28DENSE, rule);
/** DECIMAL28Sparse cast able from **/
+
rule = new HashSet<>();
- rule.add(MinorType.TINYINT);
- rule.add(MinorType.SMALLINT);
- rule.add(MinorType.INT);
- rule.add(MinorType.BIGINT);
- rule.add(MinorType.UINT1);
- rule.add(MinorType.UINT2);
- rule.add(MinorType.UINT4);
- rule.add(MinorType.UINT8);
- rule.add(MinorType.DECIMAL9);
- rule.add(MinorType.DECIMAL18);
rule.add(MinorType.DECIMAL28SPARSE);
- rule.add(MinorType.DECIMAL28DENSE);
- rule.add(MinorType.DECIMAL38SPARSE);
- rule.add(MinorType.DECIMAL38DENSE);
- rule.add(MinorType.VARDECIMAL); // TODO: implement conversion between VARDECIMAL and other types??
- rule.add(MinorType.MONEY);
- rule.add(MinorType.FLOAT4);
- rule.add(MinorType.FLOAT8);
- rule.add(MinorType.BIT);
- rule.add(MinorType.FIXEDCHAR);
- rule.add(MinorType.FIXED16CHAR);
- rule.add(MinorType.FIXEDBINARY);
- rule.add(MinorType.VARCHAR);
- rule.add(MinorType.VAR16CHAR);
- rule.add(MinorType.VARBINARY);
+ rule.add(MinorType.VARDECIMAL);
rules.put(MinorType.DECIMAL28SPARSE, rule);
- /** VARDECIMAL cast able from **/
- rule = new HashSet<MinorType>();
+ /* VARDECIMAL cast able from **/
+ rule = new HashSet<>();
rule.add(MinorType.TINYINT);
rule.add(MinorType.SMALLINT);
rule.add(MinorType.INT);
@@ -350,82 +261,20 @@ public class TypeCastRules {
rule.add(MinorType.UINT2);
rule.add(MinorType.UINT4);
rule.add(MinorType.UINT8);
- rule.add(MinorType.DECIMAL9); // TODO: implement conversion between VARDECIMAL and other types??
- rule.add(MinorType.DECIMAL18); // TODO: implement conversion between VARDECIMAL and other types??
- rule.add(MinorType.DECIMAL28SPARSE); // TODO: implement conversion between VARDECIMAL and other types??
- rule.add(MinorType.DECIMAL28DENSE); // TODO: implement conversion between VARDECIMAL and other types??
- rule.add(MinorType.DECIMAL38SPARSE); // TODO: implement conversion between VARDECIMAL and other types??
- rule.add(MinorType.DECIMAL38DENSE); // TODO: implement conversion between VARDECIMAL and other types??
rule.add(MinorType.VARDECIMAL);
- rule.add(MinorType.MONEY);
- rule.add(MinorType.FLOAT4);
- rule.add(MinorType.FLOAT8);
- rule.add(MinorType.BIT);
- rule.add(MinorType.FIXEDCHAR);
- rule.add(MinorType.FIXED16CHAR);
- rule.add(MinorType.FIXEDBINARY);
- rule.add(MinorType.VARCHAR);
- rule.add(MinorType.VAR16CHAR);
- rule.add(MinorType.VARBINARY);
rules.put(MinorType.VARDECIMAL, rule);
/** DECIMAL38Dense cast able from **/
rule = new HashSet<>();
- rule.add(MinorType.TINYINT);
- rule.add(MinorType.SMALLINT);
- rule.add(MinorType.INT);
- rule.add(MinorType.BIGINT);
- rule.add(MinorType.UINT1);
- rule.add(MinorType.UINT2);
- rule.add(MinorType.UINT4);
- rule.add(MinorType.UINT8);
- rule.add(MinorType.DECIMAL9);
- rule.add(MinorType.DECIMAL18);
- rule.add(MinorType.DECIMAL28SPARSE);
- rule.add(MinorType.DECIMAL28DENSE);
- rule.add(MinorType.DECIMAL38SPARSE);
rule.add(MinorType.DECIMAL38DENSE);
- rule.add(MinorType.VARDECIMAL); // TODO: implement conversion between VARDECIMAL and other types??
- rule.add(MinorType.MONEY);
- rule.add(MinorType.FLOAT4);
- rule.add(MinorType.FLOAT8);
- rule.add(MinorType.BIT);
- rule.add(MinorType.FIXEDCHAR);
- rule.add(MinorType.FIXED16CHAR);
- rule.add(MinorType.FIXEDBINARY);
- rule.add(MinorType.VARCHAR);
- rule.add(MinorType.VAR16CHAR);
- rule.add(MinorType.VARBINARY);
+ rule.add(MinorType.VARDECIMAL);
rules.put(MinorType.DECIMAL38DENSE, rule);
/** DECIMAL38Sparse cast able from **/
rule = new HashSet<>();
- rule.add(MinorType.TINYINT);
- rule.add(MinorType.SMALLINT);
- rule.add(MinorType.INT);
- rule.add(MinorType.BIGINT);
- rule.add(MinorType.UINT1);
- rule.add(MinorType.UINT2);
- rule.add(MinorType.UINT4);
- rule.add(MinorType.UINT8);
- rule.add(MinorType.DECIMAL9);
- rule.add(MinorType.DECIMAL18);
- rule.add(MinorType.DECIMAL28SPARSE);
- rule.add(MinorType.DECIMAL28DENSE);
rule.add(MinorType.DECIMAL38SPARSE);
- rule.add(MinorType.DECIMAL38DENSE);
- rule.add(MinorType.VARDECIMAL); // TODO: implement conversion between VARDECIMAL and other types??
- rule.add(MinorType.MONEY);
- rule.add(MinorType.FLOAT4);
- rule.add(MinorType.FLOAT8);
- rule.add(MinorType.BIT);
- rule.add(MinorType.FIXEDCHAR);
- rule.add(MinorType.FIXED16CHAR);
- rule.add(MinorType.FIXEDBINARY);
- rule.add(MinorType.VARCHAR);
- rule.add(MinorType.VAR16CHAR);
- rule.add(MinorType.VARBINARY);
+ rule.add(MinorType.VARDECIMAL);
rules.put(MinorType.DECIMAL38SPARSE, rule);
/** MONEY cast able from **/
@@ -635,7 +484,6 @@ public class TypeCastRules {
rule.add(MinorType.INT);
rule.add(MinorType.BIGINT);
rule.add(MinorType.MONEY);
- rule.add(MinorType.TIMESTAMPTZ);
rule.add(MinorType.UINT1);
rule.add(MinorType.UINT2);
rule.add(MinorType.UINT4);
@@ -647,7 +495,6 @@ public class TypeCastRules {
rule.add(MinorType.DECIMAL38SPARSE);
rule.add(MinorType.DECIMAL38DENSE);
rule.add(MinorType.VARDECIMAL);
- rule.add(MinorType.TIMESTAMP);
rule.add(MinorType.FLOAT4);
rule.add(MinorType.FLOAT8);
rule.add(MinorType.BIT);
@@ -684,7 +531,6 @@ public class TypeCastRules {
rule.add(MinorType.DECIMAL38DENSE);
rule.add(MinorType.VARDECIMAL);
rule.add(MinorType.MONEY);
- rule.add(MinorType.TIMESTAMPTZ);
rule.add(MinorType.FLOAT4);
rule.add(MinorType.FLOAT8);
rule.add(MinorType.BIT);
@@ -721,7 +567,6 @@ public class TypeCastRules {
rule.add(MinorType.DECIMAL38DENSE);
rule.add(MinorType.VARDECIMAL);
rule.add(MinorType.MONEY);
- rule.add(MinorType.TIMESTAMPTZ);
rule.add(MinorType.FLOAT4);
rule.add(MinorType.FLOAT8);
rule.add(MinorType.BIT);
@@ -849,7 +694,7 @@ public class TypeCastRules {
public static boolean isCastable(MinorType from, MinorType to) {
return from.equals(MinorType.NULL) || //null could be casted to any other type.
- (rules.get(to) == null ? false : rules.get(to).contains(from));
+ (rules.get(to) != null && rules.get(to).contains(from));
}
public static DataMode getLeastRestrictiveDataMode(List<DataMode> dataModes) {
@@ -932,14 +777,14 @@ public class TypeCastRules {
* If we are determining function holder for decimal data type, we need to make sure the output type of
* the function can fit the precision that we need based on the input types.
*/
- if (holder.checkPrecisionRange() == true) {
+ if (holder.checkPrecisionRange()) {
List<LogicalExpression> logicalExpressions = Lists.newArrayList();
for(MajorType majorType : argumentTypes) {
logicalExpressions.add(
new MajorTypeInLogicalExpression(majorType));
}
- if (DecimalUtility.getMaxPrecision(holder.getReturnType().getMinorType()) <
+ if (DRILL_REL_DATATYPE_SYSTEM.getMaxNumericPrecision() <
holder.getReturnType(logicalExpressions).getPrecision()) {
return -1;
}
@@ -988,8 +833,8 @@ public class TypeCastRules {
* if the seconday rules allow us to cast
*/
Set<MinorType> rules;
- if ((rules = (ResolverTypePrecedence.secondaryImplicitCastRules.get(parmType.getMinorType()))) != null &&
- rules.contains(argType.getMinorType()) != false) {
+ if ((rules = (ResolverTypePrecedence.secondaryImplicitCastRules.get(parmType.getMinorType()))) != null
+ && rules.contains(argType.getMinorType())) {
secondaryCast = true;
} else {
return -1;
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/server/options/SystemOptionManager.java b/exec/java-exec/src/main/java/org/apache/drill/exec/server/options/SystemOptionManager.java
index 63f1dc2e9..a9ef7376a 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/server/options/SystemOptionManager.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/server/options/SystemOptionManager.java
@@ -130,6 +130,8 @@ public class SystemOptionManager extends BaseOptionManager implements AutoClosea
new OptionDefinition(ExecConstants.PARQUET_DICT_PAGE_SIZE_VALIDATOR),
new OptionDefinition(ExecConstants.PARQUET_WRITER_COMPRESSION_TYPE_VALIDATOR),
new OptionDefinition(ExecConstants.PARQUET_WRITER_ENABLE_DICTIONARY_ENCODING_VALIDATOR),
+ new OptionDefinition(ExecConstants.PARQUET_WRITER_USE_PRIMITIVE_TYPES_FOR_DECIMALS_VALIDATOR),
+ new OptionDefinition(ExecConstants.PARQUET_WRITER_LOGICAL_TYPE_FOR_DECIMALS_VALIDATOR),
new OptionDefinition(ExecConstants.PARQUET_VECTOR_FILL_THRESHOLD_VALIDATOR),
new OptionDefinition(ExecConstants.PARQUET_VECTOR_FILL_CHECK_THRESHOLD_VALIDATOR),
new OptionDefinition(ExecConstants.PARQUET_RECORD_READER_IMPLEMENTATION_VALIDATOR),
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/store/avro/AvroDrillTable.java b/exec/java-exec/src/main/java/org/apache/drill/exec/store/avro/AvroDrillTable.java
index d89079b85..d3f90ee1c 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/store/avro/AvroDrillTable.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/store/avro/AvroDrillTable.java
@@ -20,6 +20,7 @@ package org.apache.drill.exec.store.avro;
import java.io.IOException;
import java.util.List;
+import org.apache.avro.LogicalType;
import org.apache.avro.Schema;
import org.apache.avro.Schema.Field;
import org.apache.avro.file.DataFileReader;
@@ -95,6 +96,8 @@ public class AvroDrillTable extends DrillTable {
private RelDataType getNullableRelDataTypeFromAvroType(
RelDataTypeFactory typeFactory, Schema fieldSchema) {
+ LogicalType logicalType = fieldSchema.getLogicalType();
+ String logicalTypeName = logicalType != null ? logicalType.getName() : "";
RelDataType relDataType = null;
switch (fieldSchema.getType()) {
case ARRAY:
@@ -105,22 +108,57 @@ public class AvroDrillTable extends DrillTable {
relDataType = typeFactory.createSqlType(SqlTypeName.BOOLEAN);
break;
case BYTES:
- relDataType = typeFactory.createSqlType(SqlTypeName.BINARY);
+ switch (logicalTypeName) {
+ case "decimal":
+ relDataType = typeFactory.createSqlType(SqlTypeName.DECIMAL);
+ break;
+ default:
+ relDataType = typeFactory.createSqlType(SqlTypeName.BINARY);
+ }
break;
case DOUBLE:
relDataType = typeFactory.createSqlType(SqlTypeName.DOUBLE);
break;
case FIXED:
- logger.error("{} type not supported", fieldSchema.getType());
- throw UserException.unsupportedError().message("FIXED type not supported yet").build(logger);
+ switch (logicalTypeName) {
+ case "decimal":
+ relDataType = typeFactory.createSqlType(SqlTypeName.DECIMAL);
+ break;
+ default:
+ logger.error("{} type not supported", fieldSchema.getType());
+ throw UserException.unsupportedError().message("FIXED type not supported yet").build(logger);
+ }
+ break;
case FLOAT:
relDataType = typeFactory.createSqlType(SqlTypeName.FLOAT);
break;
case INT:
- relDataType = typeFactory.createSqlType(SqlTypeName.INTEGER);
+ switch (logicalTypeName) {
+ case "date":
+ relDataType = typeFactory.createSqlType(SqlTypeName.DATE);
+ break;
+ case "time-millis":
+ relDataType = typeFactory.createSqlType(SqlTypeName.TIME);
+ break;
+ default:
+ relDataType = typeFactory.createSqlType(SqlTypeName.INTEGER);
+ }
break;
case LONG:
- relDataType = typeFactory.createSqlType(SqlTypeName.BIGINT);
+ switch (logicalTypeName) {
+ case "date":
+ relDataType = typeFactory.createSqlType(SqlTypeName.DATE);
+ break;
+ case "time-micros":
+ relDataType = typeFactory.createSqlType(SqlTypeName.TIME);
+ break;
+ case "timestamp-millis":
+ case "timestamp-micros":
+ relDataType = typeFactory.createSqlType(SqlTypeName.TIMESTAMP);
+ break;
+ default:
+ relDataType = typeFactory.createSqlType(SqlTypeName.BIGINT);
+ }
break;
case MAP:
RelDataType valueType = getNullableRelDataTypeFromAvroType(typeFactory, fieldSchema.getValueType());
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/store/avro/AvroRecordReader.java b/exec/java-exec/src/main/java/org/apache/drill/exec/store/avro/AvroRecordReader.java
index c7d2aed27..09ee5af6c 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/store/avro/AvroRecordReader.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/store/avro/AvroRecordReader.java
@@ -19,6 +19,8 @@ package org.apache.drill.exec.store.avro;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
+import java.math.BigDecimal;
+import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.security.PrivilegedExceptionAction;
import java.util.HashMap;
@@ -26,24 +28,28 @@ import java.util.List;
import java.util.Map.Entry;
import java.util.concurrent.TimeUnit;
+import org.apache.avro.LogicalType;
+import org.apache.avro.LogicalTypes;
import org.apache.avro.Schema;
import org.apache.avro.Schema.Type;
import org.apache.avro.file.DataFileReader;
import org.apache.avro.generic.GenericArray;
import org.apache.avro.generic.GenericContainer;
import org.apache.avro.generic.GenericDatumReader;
+import org.apache.avro.generic.GenericFixed;
import org.apache.avro.generic.GenericRecord;
import org.apache.avro.mapred.FsInput;
import org.apache.avro.util.Utf8;
import org.apache.drill.common.exceptions.DrillRuntimeException;
import org.apache.drill.common.exceptions.ExecutionSetupException;
-import org.apache.drill.common.expression.PathSegment;
import org.apache.drill.common.expression.SchemaPath;
import org.apache.drill.exec.ops.FragmentContext;
import org.apache.drill.exec.ops.OperatorContext;
import org.apache.drill.exec.physical.impl.OutputMutator;
+import org.apache.drill.exec.server.options.OptionManager;
import org.apache.drill.exec.store.AbstractRecordReader;
import org.apache.drill.exec.store.RecordReader;
+import org.apache.drill.exec.store.parquet.ParquetReaderUtility;
import org.apache.drill.exec.util.ImpersonationUtil;
import org.apache.drill.exec.vector.complex.fn.FieldSelection;
import org.apache.drill.exec.vector.complex.impl.MapOrListWriterImpl;
@@ -56,6 +62,7 @@ import com.google.common.base.Charsets;
import com.google.common.base.Stopwatch;
import io.netty.buffer.DrillBuf;
+import org.joda.time.DateTimeConstants;
/**
* A RecordReader implementation for Avro data files.
@@ -64,12 +71,13 @@ import io.netty.buffer.DrillBuf;
*/
public class AvroRecordReader extends AbstractRecordReader {
- static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(AvroRecordReader.class);
+ private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(AvroRecordReader.class);
private final Path hadoop;
private final long start;
private final long end;
private final FieldSelection fieldSelection;
+ private final OptionManager optionManager;
private DrillBuf buffer;
private VectorContainerWriter writer;
@@ -98,6 +106,7 @@ public class AvroRecordReader extends AbstractRecordReader {
this.queryUserName = fragmentContext.getQueryUserName();
setColumns(projectedColumns);
this.fieldSelection = FieldSelection.getFieldSelection(projectedColumns);
+ optionManager = fragmentContext.getOptions();
}
private DataFileReader<GenericContainer> getReader(final Path hadoop, final FileSystem fs) throws ExecutionSetupException {
@@ -233,7 +242,6 @@ public class AvroRecordReader extends AbstractRecordReader {
writer.end();
break;
case FIXED:
- throw new UnsupportedOperationException("Unimplemented type: " + type.toString());
case ENUM: // Enum symbols are strings
case NULL: // Treat null type as a primitive
default:
@@ -245,21 +253,24 @@ public class AvroRecordReader extends AbstractRecordReader {
}
}
- processPrimitive(value, schema.getType(), fieldName, writer);
+ processPrimitive(value, schema, fieldName, writer);
break;
}
}
- private void processPrimitive(final Object value, final Schema.Type type, final String fieldName,
+ private void processPrimitive(final Object value, final Schema schema, final String fieldName,
final MapOrListWriterImpl writer) {
+ LogicalType logicalType = schema.getLogicalType();
+ String logicalTypeName = logicalType != null ? logicalType.getName() : "";
+
if (value == null) {
return;
}
- switch (type) {
+ switch (schema.getType()) {
case STRING:
- byte[] binary = null;
+ byte[] binary;
final int length;
if (value instanceof Utf8) {
binary = ((Utf8) value).getBytes();
@@ -273,10 +284,34 @@ public class AvroRecordReader extends AbstractRecordReader {
writer.varChar(fieldName).writeVarChar(0, length, buffer);
break;
case INT:
- writer.integer(fieldName).writeInt((Integer) value);
+ switch (logicalTypeName) {
+ case "date":
+ writer.date(fieldName).writeDate((int) value * (long) DateTimeConstants.MILLIS_PER_DAY);
+ break;
+ case "time-millis":
+ writer.time(fieldName).writeTime((Integer) value);
+ break;
+ default:
+ writer.integer(fieldName).writeInt((Integer) value);
+ }
break;
case LONG:
- writer.bigInt(fieldName).writeBigInt((Long) value);
+ switch (logicalTypeName) {
+ case "date":
+ writer.date(fieldName).writeDate((Long) value);
+ break;
+ case "time-micros":
+ writer.time(fieldName).writeTime((int) ((long) value / 1000));
+ break;
+ case "timestamp-millis":
+ writer.timeStamp(fieldName).writeTimeStamp((Long) value);
+ break;
+ case "timestamp-micros":
+ writer.timeStamp(fieldName).writeTimeStamp((long) value / 1000);
+ break;
+ default:
+ writer.bigInt(fieldName).writeBigInt((Long) value);
+ }
break;
case FLOAT:
writer.float4(fieldName).writeFloat4((Float) value);
@@ -292,7 +327,16 @@ public class AvroRecordReader extends AbstractRecordReader {
length = buf.remaining();
ensure(length);
buffer.setBytes(0, buf);
- writer.binary(fieldName).writeVarBinary(0, length, buffer);
+ switch (logicalTypeName) {
+ case "decimal":
+ ParquetReaderUtility.checkDecimalTypeEnabled(optionManager);
+ LogicalTypes.Decimal decimalType = (LogicalTypes.Decimal) logicalType;
+ writer.varDecimal(fieldName, decimalType.getScale(), decimalType.getPrecision())
+ .writeVarDecimal(0, length, buffer, decimalType.getScale(), decimalType.getPrecision());
+ break;
+ default:
+ writer.binary(fieldName).writeVarBinary(0, length, buffer);
+ }
break;
case NULL:
// Nothing to do for null type
@@ -301,17 +345,29 @@ public class AvroRecordReader extends AbstractRecordReader {
final String symbol = value.toString();
final byte[] b;
try {
- b = symbol.getBytes("UTF-8");
+ b = symbol.getBytes(Charsets.UTF_8.name());
} catch (UnsupportedEncodingException e) {
throw new DrillRuntimeException("Unable to read enum value for field: " + fieldName, e);
}
ensure(b.length);
buffer.setBytes(0, b);
writer.varChar(fieldName).writeVarChar(0, b.length, buffer);
-
+ break;
+ case FIXED:
+ GenericFixed genericFixed = (GenericFixed) value;
+ switch (logicalTypeName) {
+ case "decimal":
+ ParquetReaderUtility.checkDecimalTypeEnabled(optionManager);
+ LogicalTypes.Decimal decimalType = (LogicalTypes.Decimal) logicalType;
+ writer.varDecimal(fieldName, decimalType.getScale(), decimalType.getPrecision())
+ .writeVarDecimal(new BigDecimal(new BigInteger(genericFixed.bytes()), decimalType.getScale()));
+ break;
+ default:
+ throw new UnsupportedOperationException("Unimplemented type: " + schema.getType().toString());
+ }
break;
default:
- throw new DrillRuntimeException("Unhandled Avro type: " + type.toString());
+ throw new DrillRuntimeException("Unhandled Avro type: " + schema.getType().toString());
}
}
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/store/mock/ColumnDef.java b/exec/java-exec/src/main/java/org/apache/drill/exec/store/mock/ColumnDef.java
index c1137bdfa..1a7dc3031 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/store/mock/ColumnDef.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/store/mock/ColumnDef.java
@@ -96,6 +96,8 @@ public class ColumnDef {
break;
case DECIMAL38SPARSE:
break;
+ case VARDECIMAL:
+ break;
case DECIMAL9:
break;
case FIXED16CHAR:
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/ParquetFilterBuilder.java b/exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/ParquetFilterBuilder.java
index 9804e2496..52c47230e 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/ParquetFilterBuilder.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/ParquetFilterBuilder.java
@@ -39,10 +39,12 @@ import org.apache.drill.exec.expr.holders.IntHolder;
import org.apache.drill.exec.expr.holders.TimeHolder;
import org.apache.drill.exec.expr.holders.TimeStampHolder;
import org.apache.drill.exec.expr.holders.ValueHolder;
+import org.apache.drill.exec.expr.holders.VarDecimalHolder;
import org.apache.drill.exec.expr.stat.ParquetBooleanPredicates;
import org.apache.drill.exec.expr.stat.ParquetComparisonPredicates;
import org.apache.drill.exec.expr.stat.ParquetIsPredicates;
import org.apache.drill.exec.ops.UdfUtilities;
+import org.apache.drill.exec.util.DecimalUtility;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -110,6 +112,12 @@ public class ParquetFilterBuilder extends AbstractExprVisitor<LogicalExpression,
}
@Override
+ public LogicalExpression visitVarDecimalConstant(ValueExpressions.VarDecimalExpression decExpr, Set<LogicalExpression> value)
+ throws RuntimeException {
+ return decExpr;
+ }
+
+ @Override
public LogicalExpression visitDateConstant(ValueExpressions.DateExpression dateExpr, Set<LogicalExpression> value) throws RuntimeException {
return dateExpr;
}
@@ -169,6 +177,11 @@ public class ParquetFilterBuilder extends AbstractExprVisitor<LogicalExpression,
return ValueExpressions.getFloat4(((Float4Holder) holder).value);
case FLOAT8:
return ValueExpressions.getFloat8(((Float8Holder) holder).value);
+ case VARDECIMAL:
+ VarDecimalHolder decimalHolder = (VarDecimalHolder) holder;
+ return ValueExpressions.getVarDecimal(
+ DecimalUtility.getBigDecimalFromDrillBuf(decimalHolder.buffer,
+ decimalHolder.start, decimalHolder.end - decimalHolder.start, decimalHolder.scale));
case DATE:
return ValueExpressions.getDate(((DateHolder) holder).value);
case TIMESTAMP:
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/ParquetFormatPlugin.java b/exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/ParquetFormatPlugin.java
index f66cf303b..94760da6f 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/ParquetFormatPlugin.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/ParquetFormatPlugin.java
@@ -153,6 +153,12 @@ public class ParquetFormatPlugin implements FormatPlugin{
options.put(ExecConstants.PARQUET_WRITER_ENABLE_DICTIONARY_ENCODING,
context.getOptions().getOption(ExecConstants.PARQUET_WRITER_ENABLE_DICTIONARY_ENCODING).bool_val.toString());
+ options.put(ExecConstants.PARQUET_WRITER_LOGICAL_TYPE_FOR_DECIMALS,
+ context.getOptions().getOption(ExecConstants.PARQUET_WRITER_LOGICAL_TYPE_FOR_DECIMALS).string_val);
+
+ options.put(ExecConstants.PARQUET_WRITER_USE_PRIMITIVE_TYPES_FOR_DECIMALS,
+ context.getOptions().getOption(ExecConstants.PARQUET_WRITER_USE_PRIMITIVE_TYPES_FOR_DECIMALS).bool_val.toString());
+
RecordWriter recordWriter = new ParquetRecordWriter(context, writer);
recordWriter.init(options);
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/ParquetReaderUtility.java b/exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/ParquetReaderUtility.java
index 915759069..377dfbe0e 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/ParquetReaderUtility.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/ParquetReaderUtility.java
@@ -486,7 +486,7 @@ public class ParquetReaderUtility {
if (originalType != null) {
switch (originalType) {
case DECIMAL:
- return Types.withScaleAndPrecision(TypeProtos.MinorType.DECIMAL18, TypeProtos.DataMode.OPTIONAL, scale, precision);
+ return Types.withScaleAndPrecision(TypeProtos.MinorType.VARDECIMAL, TypeProtos.DataMode.OPTIONAL, scale, precision);
case DATE:
return Types.optional(TypeProtos.MinorType.DATE);
case TIME_MILLIS:
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/ParquetRecordWriter.java b/exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/ParquetRecordWriter.java
index 9b84e810a..ec7861974 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/ParquetRecordWriter.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/ParquetRecordWriter.java
@@ -45,6 +45,7 @@ import org.apache.drill.exec.record.VectorWrapper;
import org.apache.drill.exec.store.EventBasedRecordWriter;
import org.apache.drill.exec.store.EventBasedRecordWriter.FieldConverter;
import org.apache.drill.exec.store.ParquetOutputRecordWriter;
+import org.apache.drill.exec.util.DecimalUtility;
import org.apache.drill.exec.vector.BitVector;
import org.apache.drill.exec.vector.complex.reader.FieldReader;
import org.apache.hadoop.conf.Configuration;
@@ -114,9 +115,10 @@ public class ParquetRecordWriter extends ParquetOutputRecordWriter {
private OperatorContext oContext;
private List<String> partitionColumns;
private boolean hasPartitions;
+ private PrimitiveTypeName logicalTypeForDecimals;
+ private boolean usePrimitiveTypesForDecimals;
- public ParquetRecordWriter(FragmentContext context, ParquetWriter writer) throws OutOfMemoryException{
- super();
+ public ParquetRecordWriter(FragmentContext context, ParquetWriter writer) throws OutOfMemoryException {
this.oContext = context.newOperatorContext(writer);
this.codecFactory = CodecFactory.createDirectCodecFactory(writer.getFormatPlugin().getFsConf(),
new ParquetDirectByteBufferAllocator(oContext.getAllocator()), pageSize);
@@ -158,8 +160,24 @@ public class ParquetRecordWriter extends ParquetOutputRecordWriter {
throw new UnsupportedOperationException(String.format("Unknown compression type: %s", codecName));
}
+ String logicalTypeNameForDecimals = writerOptions.get(ExecConstants.PARQUET_WRITER_LOGICAL_TYPE_FOR_DECIMALS).toLowerCase();
+ switch (logicalTypeNameForDecimals) {
+ case "fixed_len_byte_array":
+ logicalTypeForDecimals = PrimitiveTypeName.FIXED_LEN_BYTE_ARRAY;
+ break;
+ case "binary":
+ logicalTypeForDecimals = PrimitiveTypeName.BINARY;
+ break;
+ default:
+ throw new UnsupportedOperationException(
+ String.format(
+ "Unsupported logical type for decimals: %s\n" +
+ "Supported types: ['fixed_len_byte_array', 'binary']", codecName));
+ }
+
enableDictionary = Boolean.parseBoolean(writerOptions.get(ExecConstants.PARQUET_WRITER_ENABLE_DICTIONARY_ENCODING));
useSingleFSBlock = Boolean.parseBoolean(writerOptions.get(ExecConstants.PARQUET_WRITER_USE_SINGLE_FS_BLOCK));
+ usePrimitiveTypesForDecimals = Boolean.parseBoolean(writerOptions.get(ExecConstants.PARQUET_WRITER_USE_PRIMITIVE_TYPES_FOR_DECIMALS));
if (useSingleFSBlock) {
// Round up blockSize to multiple of 64K.
@@ -228,14 +246,27 @@ public class ParquetRecordWriter extends ParquetOutputRecordWriter {
setUp(schema, consumer);
}
- private PrimitiveType getPrimitiveType(MaterializedField field) {
+ protected PrimitiveType getPrimitiveType(MaterializedField field) {
MinorType minorType = field.getType().getMinorType();
String name = field.getName();
+ int length = ParquetTypeHelper.getLengthForMinorType(minorType);
PrimitiveTypeName primitiveTypeName = ParquetTypeHelper.getPrimitiveTypeNameForMinorType(minorType);
+ if (DecimalUtility.isDecimalType(minorType)) {
+ primitiveTypeName = logicalTypeForDecimals;
+ if (usePrimitiveTypesForDecimals) {
+ if (field.getPrecision() <= ParquetTypeHelper.getMaxPrecisionForPrimitiveType(PrimitiveTypeName.INT32)) {
+ primitiveTypeName = PrimitiveTypeName.INT32;
+ } else if (field.getPrecision() <= ParquetTypeHelper.getMaxPrecisionForPrimitiveType(PrimitiveTypeName.INT64)) {
+ primitiveTypeName = PrimitiveTypeName.INT64;
+ }
+ }
+
+ length = DecimalUtility.getMaxBytesSizeForPrecision(field.getPrecision());
+ }
+
Repetition repetition = ParquetTypeHelper.getRepetitionForDataMode(field.getDataMode());
OriginalType originalType = ParquetTypeHelper.getOriginalTypeForMinorType(minorType);
DecimalMetadata decimalMetadata = ParquetTypeHelper.getDecimalMetadataForField(field);
- int length = ParquetTypeHelper.getLengthForMinorType(minorType);
return new PrimitiveType(repetition, primitiveTypeName, length, name, originalType, decimalMetadata, null);
}
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/columnreaders/ColumnReaderFactory.java b/exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/columnreaders/ColumnReaderFactory.java
index 5fbd20f41..cf297fa72 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/columnreaders/ColumnReaderFactory.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/columnreaders/ColumnReaderFactory.java
@@ -25,10 +25,6 @@ import org.apache.drill.exec.vector.NullableVarDecimalVector;
import org.apache.drill.exec.vector.BigIntVector;
import org.apache.drill.exec.vector.BitVector;
import org.apache.drill.exec.vector.DateVector;
-import org.apache.drill.exec.vector.Decimal18Vector;
-import org.apache.drill.exec.vector.Decimal28SparseVector;
-import org.apache.drill.exec.vector.Decimal38SparseVector;
-import org.apache.drill.exec.vector.Decimal9Vector;
import org.apache.drill.exec.vector.Float4Vector;
import org.apache.drill.exec.vector.Float8Vector;
import org.apache.drill.exec.vector.IntVector;
@@ -36,10 +32,6 @@ import org.apache.drill.exec.vector.IntervalVector;
import org.apache.drill.exec.vector.NullableBigIntVector;
import org.apache.drill.exec.vector.NullableBitVector;
import org.apache.drill.exec.vector.NullableDateVector;
-import org.apache.drill.exec.vector.NullableDecimal18Vector;
-import org.apache.drill.exec.vector.NullableDecimal28SparseVector;
-import org.apache.drill.exec.vector.NullableDecimal38SparseVector;
-import org.apache.drill.exec.vector.NullableDecimal9Vector;
import org.apache.drill.exec.vector.NullableFloat4Vector;
import org.apache.drill.exec.vector.NullableFloat8Vector;
import org.apache.drill.exec.vector.NullableIntVector;
@@ -80,25 +72,23 @@ public class ColumnReaderFactory {
ConvertedType convertedType = schemaElement.getConverted_type();
// if the column is required, or repeated (in which case we just want to use this to generate our appropriate
// ColumnReader for actually transferring data into the data vector inside of our repeated vector
- if (descriptor.getMaxDefinitionLevel() == 0 || descriptor.getMaxRepetitionLevel() > 0){
+ if (descriptor.getMaxDefinitionLevel() == 0 || descriptor.getMaxRepetitionLevel() > 0) {
if (columnChunkMetaData.getType() == PrimitiveType.PrimitiveTypeName.BOOLEAN){
return new BitReader(recordReader, allocateSize, descriptor, columnChunkMetaData,
fixedLength, (BitVector) v, schemaElement);
} else if (!columnChunkMetaData.getEncodings().contains(Encoding.PLAIN_DICTIONARY) && (
columnChunkMetaData.getType() == PrimitiveType.PrimitiveTypeName.FIXED_LEN_BYTE_ARRAY
|| columnChunkMetaData.getType() == PrimitiveType.PrimitiveTypeName.INT96)) {
- if (convertedType == ConvertedType.DECIMAL){
- int length = schemaElement.type_length;
- if (length <= 12) {
- return new FixedByteAlignedReader.Decimal28Reader(recordReader, allocateSize, descriptor, columnChunkMetaData, fixedLength, (Decimal28SparseVector) v, schemaElement);
- } else if (length <= 16) {
- return new FixedByteAlignedReader.Decimal38Reader(recordReader, allocateSize, descriptor, columnChunkMetaData, fixedLength, (Decimal38SparseVector) v, schemaElement);
- }
- } else if (convertedType == ConvertedType.INTERVAL) {
- return new FixedByteAlignedReader.IntervalReader(recordReader, allocateSize, descriptor, columnChunkMetaData, fixedLength, (IntervalVector) v, schemaElement);
- }
- else {
- return new FixedByteAlignedReader.FixedBinaryReader(recordReader, allocateSize, descriptor, columnChunkMetaData, (VariableWidthVector) v, schemaElement);
+ switch (convertedType) {
+ case DECIMAL:
+ return new FixedByteAlignedReader.VarDecimalReader(recordReader, allocateSize, descriptor,
+ columnChunkMetaData, fixedLength, (VarDecimalVector) v, schemaElement);
+ case INTERVAL:
+ return new FixedByteAlignedReader.IntervalReader(recordReader, allocateSize, descriptor,
+ columnChunkMetaData, fixedLength, (IntervalVector) v, schemaElement);
+ default:
+ return new FixedByteAlignedReader.FixedBinaryReader(recordReader, allocateSize, descriptor,
+ columnChunkMetaData, (VariableWidthVector) v, schemaElement);
}
} else if (columnChunkMetaData.getType() == PrimitiveType.PrimitiveTypeName.INT32 && convertedType == ConvertedType.DATE){
switch(recordReader.getDateCorruptionStatus()) {
@@ -114,7 +104,7 @@ public class ColumnReaderFactory {
"unrecognized date corruption status %s. See DRILL-4203 for more info.",
recordReader.getDateCorruptionStatus()));
}
- } else{
+ } else {
if (columnChunkMetaData.getEncodings().contains(Encoding.PLAIN_DICTIONARY)) {
switch (columnChunkMetaData.getType()) {
case INT32:
@@ -123,7 +113,8 @@ public class ColumnReaderFactory {
}
switch (convertedType) {
case DECIMAL:
- return new ParquetFixedWidthDictionaryReaders.DictionaryDecimal9Reader(recordReader, allocateSize, descriptor, columnChunkMetaData, fixedLength, (Decimal9Vector) v, schemaElement);
+ return new ParquetFixedWidthDictionaryReaders.DictionaryVarDecimalReader(recordReader, allocateSize,
+ descriptor, columnChunkMetaData, fixedLength, (VarDecimalVector) v, schemaElement);
case TIME_MILLIS:
return new ParquetFixedWidthDictionaryReaders.DictionaryTimeReader(recordReader, allocateSize, descriptor, columnChunkMetaData, fixedLength, (TimeVector) v, schemaElement);
case INT_8:
@@ -147,7 +138,8 @@ public class ColumnReaderFactory {
case UINT_64:
return new ParquetFixedWidthDictionaryReaders.DictionaryUInt8Reader(recordReader, allocateSize, descriptor, columnChunkMetaData, fixedLength, (UInt8Vector) v, schemaElement);
case DECIMAL:
- return new ParquetFixedWidthDictionaryReaders.DictionaryDecimal18Reader(recordReader, allocateSize, descriptor, columnChunkMetaData, fixedLength, (Decimal18Vector) v, schemaElement);
+ return new ParquetFixedWidthDictionaryReaders.DictionaryVarDecimalReader(recordReader, allocateSize,
+ descriptor, columnChunkMetaData, fixedLength, (VarDecimalVector) v, schemaElement);
case TIMESTAMP_MILLIS:
return new ParquetFixedWidthDictionaryReaders.DictionaryTimeStampReader(recordReader, allocateSize, descriptor, columnChunkMetaData, fixedLength, (TimeStampVector) v, schemaElement);
default:
@@ -169,17 +161,19 @@ public class ColumnReaderFactory {
throw new ExecutionSetupException("Unsupported dictionary column type " + descriptor.getType().name() );
}
+ } else if (convertedType == ConvertedType.DECIMAL) {
+ return new FixedByteAlignedReader.VarDecimalReader(recordReader, allocateSize,
+ descriptor, columnChunkMetaData, fixedLength, (VarDecimalVector) v, schemaElement);
} else {
return new FixedByteAlignedReader<>(recordReader, allocateSize, descriptor, columnChunkMetaData,
fixedLength, v, schemaElement);
}
}
- }
- else { // if the column is nullable
- if (columnChunkMetaData.getType() == PrimitiveType.PrimitiveTypeName.BOOLEAN){
+ } else { // if the column is nullable
+ if (columnChunkMetaData.getType() == PrimitiveType.PrimitiveTypeName.BOOLEAN) {
return new NullableBitReader(recordReader, allocateSize, descriptor, columnChunkMetaData,
fixedLength, (NullableBitVector) v, schemaElement);
- } else if (columnChunkMetaData.getType() == PrimitiveType.PrimitiveTypeName.INT32 && convertedType == ConvertedType.DATE){
+ } else if (columnChunkMetaData.getType() == PrimitiveType.PrimitiveTypeName.INT32 && convertedType == ConvertedType.DATE) {
switch(recordReader.getDateCorruptionStatus()) {
case META_SHOWS_CORRUPTION:
return new NullableFixedByteAlignedReaders.NullableCorruptDateReader(recordReader, allocateSize, descriptor, columnChunkMetaData, fixedLength, (NullableDateVector)v, schemaElement);
@@ -195,12 +189,8 @@ public class ColumnReaderFactory {
}
} else if (columnChunkMetaData.getType() == PrimitiveType.PrimitiveTypeName.FIXED_LEN_BYTE_ARRAY) {
if (convertedType == ConvertedType.DECIMAL) {
- int length = schemaElement.type_length;
- if (length <= 12) {
- return new NullableFixedByteAlignedReaders.NullableDecimal28Reader(recordReader, allocateSize, descriptor, columnChunkMetaData, fixedLength, (NullableDecimal28SparseVector) v, schemaElement);
- } else if (length <= 16) {
- return new NullableFixedByteAlignedReaders.NullableDecimal38Reader(recordReader, allocateSize, descriptor, columnChunkMetaData, fixedLength, (NullableDecimal38SparseVector) v, schemaElement);
- }
+ return new NullableFixedByteAlignedReaders.NullableVarDecimalReader(recordReader, allocateSize,
+ descriptor, columnChunkMetaData, fixedLength, (NullableVarDecimalVector) v, schemaElement);
} else if (convertedType == ConvertedType.INTERVAL) {
return new NullableFixedByteAlignedReaders.NullableIntervalReader(recordReader, allocateSize, descriptor,
columnChunkMetaData, fixedLength, (NullableIntervalVector) v, schemaElement);
@@ -230,10 +220,6 @@ public class ColumnReaderFactory {
case DECIMAL:
if (v instanceof VarDecimalVector) {
return new VarLengthColumnReaders.VarDecimalColumn(parentReader, allocateSize, descriptor, columnChunkMetaData, fixedLength, (VarDecimalVector) v, schemaElement);
- } else if (v instanceof Decimal28SparseVector) {
- return new VarLengthColumnReaders.Decimal28Column(parentReader, allocateSize, descriptor, columnChunkMetaData, fixedLength, (Decimal28SparseVector) v, schemaElement);
- } else if (v instanceof Decimal38SparseVector) {
- return new VarLengthColumnReaders.Decimal38Column(parentReader, allocateSize, descriptor, columnChunkMetaData, fixedLength, (Decimal38SparseVector) v, schemaElement);
}
default:
return new VarLengthColumnReaders.VarBinaryColumn(parentReader, allocateSize, descriptor, columnChunkMetaData, fixedLength, (VarBinaryVector) v, schemaElement);
@@ -250,10 +236,6 @@ public class ColumnReaderFactory {
case DECIMAL:
if (v instanceof NullableVarDecimalVector) {
return new VarLengthColumnReaders.NullableVarDecimalColumn(parentReader, allocateSize, descriptor, columnChunkMetaData, fixedLength, (NullableVarDecimalVector) v, schemaElement);
- } else if (v instanceof NullableDecimal28SparseVector) {
- return new VarLengthColumnReaders.NullableDecimal28Column(parentReader, allocateSize, descriptor, columnChunkMetaData, fixedLength, (NullableDecimal28SparseVector) v, schemaElement);
- } else if (v instanceof NullableDecimal38SparseVector) {
- return new VarLengthColumnReaders.NullableDecimal38Column(parentReader, allocateSize, descriptor, columnChunkMetaData, fixedLength, (NullableDecimal38SparseVector) v, schemaElement);
}
default:
return new VarLengthColumnReaders.NullableVarBinaryColumn(parentReader, allocateSize, descriptor, columnChunkMetaData, fixedLength, (NullableVarBinaryVector) v, schemaElement);
@@ -277,7 +259,13 @@ public class ColumnReaderFactory {
} else {
return new NullableFixedByteAlignedReaders.NullableFixedBinaryReader(parentReader, allocateSize, columnDescriptor, columnChunkMetaData, true, (NullableVarBinaryVector) valueVec, schemaElement);
}
- }else{
+ } else if (convertedType == ConvertedType.DECIMAL) {
+ // NullableVarDecimalVector allows storing of values with different width,
+ // so every time when the value is added, offset vector should be updated.
+ // Therefore NullableVarDecimalReader is used here instead of NullableFixedByteAlignedReader.
+ return new NullableFixedByteAlignedReaders.NullableVarDecimalReader(parentReader, allocateSize,
+ columnDescriptor, columnChunkMetaData, fixedLength, (NullableVarDecimalVector) valueVec, schemaElement);
+ } else {
return new NullableFixedByteAlignedReaders.NullableFixedByteAlignedReader<>(parentReader, allocateSize, columnDescriptor, columnChunkMetaData, fixedLength, valueVec, schemaElement);
}
} else {
@@ -288,7 +276,8 @@ public class ColumnReaderFactory {
}
switch (convertedType) {
case DECIMAL:
- return new NullableFixedByteAlignedReaders.NullableDictionaryDecimal9Reader(parentReader, allocateSize, columnDescriptor, columnChunkMetaData, fixedLength, (NullableDecimal9Vector) valueVec, schemaElement);
+ return new NullableFixedByteAlignedReaders.NullableDictionaryVarDecimalReader(parentReader, allocateSize,
+ columnDescriptor, columnChunkMetaData, fixedLength, (NullableVarDecimalVector) valueVec, schemaElement);
case TIME_MILLIS:
return new NullableFixedByteAlignedReaders.NullableDictionaryTimeReader(parentReader, allocateSize, columnDescriptor, columnChunkMetaData, fixedLength, (NullableTimeVector)valueVec, schemaElement);
default:
@@ -300,7 +289,8 @@ public class ColumnReaderFactory {
}
switch (convertedType) {
case DECIMAL:
- return new NullableFixedByteAlignedReaders.NullableDictionaryDecimal18Reader(parentReader, allocateSize, columnDescriptor, columnChunkMetaData, fixedLength, (NullableDecimal18Vector)valueVec, schemaElement);
+ return new NullableFixedByteAlignedReaders.NullableDictionaryVarDecimalReader(parentReader, allocateSize,
+ columnDescriptor, columnChunkMetaData, fixedLength, (NullableVarDecimalVector) valueVec, schemaElement);
case TIMESTAMP_MILLIS:
return new NullableFixedByteAlignedReaders.NullableDictionaryTimeStampReader(parentReader, allocateSize, columnDescriptor, columnChunkMetaData, fixedLength, (NullableTimeStampVector)valueVec, schemaElement);
default:
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/columnreaders/FixedByteAlignedReader.java b/exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/columnreaders/FixedByteAlignedReader.java
index e6708ec0b..385b117c1 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/columnreaders/FixedByteAlignedReader.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/columnreaders/FixedByteAlignedReader.java
@@ -17,18 +17,14 @@
*/
package org.apache.drill.exec.store.parquet.columnreaders;
-import java.math.BigDecimal;
-
+import com.google.common.primitives.Ints;
+import com.google.common.primitives.Longs;
import org.apache.drill.common.exceptions.ExecutionSetupException;
-import org.apache.drill.exec.expr.holders.Decimal28SparseHolder;
-import org.apache.drill.exec.expr.holders.Decimal38SparseHolder;
import org.apache.drill.exec.store.parquet.ParquetReaderUtility;
-import org.apache.drill.exec.util.DecimalUtility;
import org.apache.drill.exec.vector.DateVector;
-import org.apache.drill.exec.vector.Decimal28SparseVector;
-import org.apache.drill.exec.vector.Decimal38SparseVector;
import org.apache.drill.exec.vector.IntervalVector;
import org.apache.drill.exec.vector.ValueVector;
+import org.apache.drill.exec.vector.VarDecimalVector;
import org.apache.drill.exec.vector.VariableWidthVector;
import org.apache.parquet.column.ColumnDescriptor;
import org.apache.parquet.format.SchemaElement;
@@ -199,37 +195,27 @@ class FixedByteAlignedReader<V extends ValueVector> extends ColumnReader<V> {
}
- public static class Decimal28Reader extends ConvertedReader<Decimal28SparseVector> {
+ public static class VarDecimalReader extends ConvertedReader<VarDecimalVector> {
- Decimal28Reader(ParquetRecordReader parentReader, int allocateSize, ColumnDescriptor descriptor, ColumnChunkMetaData columnChunkMetaData,
- boolean fixedLength, Decimal28SparseVector v, SchemaElement schemaElement) throws ExecutionSetupException {
+ VarDecimalReader(ParquetRecordReader parentReader, int allocateSize, ColumnDescriptor descriptor, ColumnChunkMetaData columnChunkMetaData,
+ boolean fixedLength, VarDecimalVector v, SchemaElement schemaElement) throws ExecutionSetupException {
super(parentReader, allocateSize, descriptor, columnChunkMetaData, fixedLength, v, schemaElement);
}
@Override
void addNext(int start, int index) {
- int width = Decimal28SparseHolder.WIDTH;
- BigDecimal intermediate = DecimalUtility.getBigDecimalFromDrillBuf(bytebuf, start, dataTypeLengthInBytes,
- schemaElement.getScale());
- DecimalUtility.getSparseFromBigDecimal(intermediate, valueVec.getBuffer(), index * width, schemaElement.getScale(),
- schemaElement.getPrecision(), Decimal28SparseHolder.nDecimalDigits);
- }
- }
-
- public static class Decimal38Reader extends ConvertedReader<Decimal38SparseVector> {
-
- Decimal38Reader(ParquetRecordReader parentReader, int allocateSize, ColumnDescriptor descriptor, ColumnChunkMetaData columnChunkMetaData,
- boolean fixedLength, Decimal38SparseVector v, SchemaElement schemaElement) throws ExecutionSetupException {
- super(parentReader, allocateSize, descriptor, columnChunkMetaData, fixedLength, v, schemaElement);
- }
-
- @Override
- void addNext(int start, int index) {
- int width = Decimal38SparseHolder.WIDTH;
- BigDecimal intermediate = DecimalUtility.getBigDecimalFromDrillBuf(bytebuf, start, dataTypeLengthInBytes,
- schemaElement.getScale());
- DecimalUtility.getSparseFromBigDecimal(intermediate, valueVec.getBuffer(), index * width, schemaElement.getScale(),
- schemaElement.getPrecision(), Decimal38SparseHolder.nDecimalDigits);
+ switch (columnChunkMetaData.getType()) {
+ case INT32:
+ valueVec.getMutator().setSafe(index, Ints.toByteArray(bytebuf.getInt(start)), 0, dataTypeLengthInBytes);
+ break;
+ case INT64:
+ valueVec.getMutator().setSafe(index, Longs.toByteArray(bytebuf.getLong(start)), 0, dataTypeLengthInBytes);
+ break;
+ case FIXED_LEN_BYTE_ARRAY:
+ case BINARY:
+ valueVec.getMutator().setSafe(index, start, start + dataTypeLengthInBytes, bytebuf);
+ break;
+ }
}
}
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/columnreaders/NullableFixedByteAlignedReaders.java b/exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/columnreaders/NullableFixedByteAlignedReaders.java
index 86cba6e66..9e66b1f1b 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/columnreaders/NullableFixedByteAlignedReaders.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/columnreaders/NullableFixedByteAlignedReaders.java
@@ -17,21 +17,15 @@
*/
package org.apache.drill.exec.store.parquet.columnreaders;
-import java.math.BigDecimal;
import java.nio.ByteBuffer;
+import com.google.common.primitives.Ints;
+import com.google.common.primitives.Longs;
import org.apache.drill.common.exceptions.ExecutionSetupException;
-import org.apache.drill.exec.expr.holders.NullableDecimal28SparseHolder;
-import org.apache.drill.exec.expr.holders.NullableDecimal38SparseHolder;
import org.apache.drill.exec.expr.holders.NullableTimeStampHolder;
import org.apache.drill.exec.store.parquet.ParquetReaderUtility;
-import org.apache.drill.exec.util.DecimalUtility;
import org.apache.drill.exec.vector.NullableBigIntVector;
import org.apache.drill.exec.vector.NullableDateVector;
-import org.apache.drill.exec.vector.NullableDecimal18Vector;
-import org.apache.drill.exec.vector.NullableDecimal28SparseVector;
-import org.apache.drill.exec.vector.NullableDecimal38SparseVector;
-import org.apache.drill.exec.vector.NullableDecimal9Vector;
import org.apache.drill.exec.vector.NullableFloat4Vector;
import org.apache.drill.exec.vector.NullableFloat8Vector;
import org.apache.drill.exec.vector.NullableIntVector;
@@ -39,6 +33,7 @@ import org.apache.drill.exec.vector.NullableIntervalVector;
import org.apache.drill.exec.vector.NullableTimeStampVector;
import org.apache.drill.exec.vector.NullableTimeVector;
import org.apache.drill.exec.vector.NullableVarBinaryVector;
+import org.apache.drill.exec.vector.NullableVarDecimalVector;
import org.apache.drill.exec.vector.ValueVector;
import org.apache.parquet.column.ColumnDescriptor;
import org.apache.parquet.format.SchemaElement;
@@ -164,29 +159,6 @@ public class NullableFixedByteAlignedReaders {
}
}
- static class NullableDictionaryDecimal9Reader extends NullableColumnReader<NullableDecimal9Vector> {
-
- NullableDictionaryDecimal9Reader(ParquetRecordReader parentReader, int allocateSize, ColumnDescriptor descriptor,
- ColumnChunkMetaData columnChunkMetaData, boolean fixedLength, NullableDecimal9Vector v,
- SchemaElement schemaElement) throws ExecutionSetupException {
- super(parentReader, allocateSize, descriptor, columnChunkMetaData, fixedLength, v, schemaElement);
- }
-
- // this method is called by its superclass during a read loop
- @Override
- protected void readField(long recordsToReadInThisPass) {
- if (usingDictionary) {
- for (int i = 0; i < recordsToReadInThisPass; i++){
- valueVec.getMutator().setSafe(valuesReadInCurrentPass + i, pageReader.dictionaryValueReader.readInteger());
- }
- } else {
- for (int i = 0; i < recordsToReadInThisPass; i++){
- valueVec.getMutator().setSafe(valuesReadInCurrentPass + i, pageReader.valueReader.readInteger());
- }
- }
- }
- }
-
static class NullableDictionaryTimeReader extends NullableColumnReader<NullableTimeVector> {
NullableDictionaryTimeReader(ParquetRecordReader parentReader, int allocateSize, ColumnDescriptor descriptor,
@@ -255,28 +227,53 @@ public class NullableFixedByteAlignedReaders {
}
}
}
- static class NullableDictionaryDecimal18Reader extends NullableColumnReader<NullableDecimal18Vector> {
- NullableDictionaryDecimal18Reader(ParquetRecordReader parentReader, int allocateSize, ColumnDescriptor descriptor,
- ColumnChunkMetaData columnChunkMetaData, boolean fixedLength, NullableDecimal18Vector v,
- SchemaElement schemaElement) throws ExecutionSetupException {
+ static class NullableDictionaryVarDecimalReader extends NullableColumnReader<NullableVarDecimalVector> {
+
+ NullableDictionaryVarDecimalReader(ParquetRecordReader parentReader, int allocateSize, ColumnDescriptor descriptor,
+ ColumnChunkMetaData columnChunkMetaData, boolean fixedLength, NullableVarDecimalVector v,
+ SchemaElement schemaElement) throws ExecutionSetupException {
super(parentReader, allocateSize, descriptor, columnChunkMetaData, fixedLength, v, schemaElement);
}
// this method is called by its superclass during a read loop
@Override
protected void readField(long recordsToReadInThisPass) {
- if (usingDictionary) {
- for (int i = 0; i < recordsToReadInThisPass; i++){
- valueVec.getMutator().setSafe(valuesReadInCurrentPass + i, pageReader.dictionaryValueReader.readLong());
- }
- } else {
- for (int i = 0; i < recordsToReadInThisPass; i++){
- valueVec.getMutator().setSafe(valuesReadInCurrentPass + i, pageReader.valueReader.readLong());
- }
+ switch (columnDescriptor.getType()) {
+ case INT32:
+ if (usingDictionary) {
+ for (int i = 0; i < recordsToReadInThisPass; i++) {
+ byte[] bytes = Ints.toByteArray(pageReader.dictionaryValueReader.readInteger());
+ setValueBytes(i, bytes);
+ }
+ } else {
+ for (int i = 0; i < recordsToReadInThisPass; i++) {
+ byte[] bytes = Ints.toByteArray(pageReader.valueReader.readInteger());
+ setValueBytes(i, bytes);
+ }
+ }
+ break;
+ case INT64:
+ if (usingDictionary) {
+ for (int i = 0; i < recordsToReadInThisPass; i++) {
+ byte[] bytes = Longs.toByteArray(pageReader.dictionaryValueReader.readLong());
+ setValueBytes(i, bytes);
+ }
+ } else {
+ for (int i = 0; i < recordsToReadInThisPass; i++) {
+ byte[] bytes = Longs.toByteArray(pageReader.valueReader.readLong());
+ setValueBytes(i, bytes);
+ }
+ }
+ break;
}
}
+
+ private void setValueBytes(int i, byte[] bytes) {
+ valueVec.getMutator().setSafe(valuesReadInCurrentPass + i, bytes, 0, bytes.length);
+ }
}
+
static class NullableDictionaryFloat4Reader extends NullableColumnReader<NullableFloat4Vector> {
NullableDictionaryFloat4Reader(ParquetRecordReader parentReader, int allocateSize, ColumnDescriptor descriptor,
@@ -398,14 +395,11 @@ public class NullableFixedByteAlignedReaders {
*/
public static class CorruptionDetectingNullableDateReader extends NullableConvertedReader<NullableDateVector> {
- NullableDateVector dateVector;
-
CorruptionDetectingNullableDateReader(ParquetRecordReader parentReader, int allocateSize,
ColumnDescriptor descriptor, ColumnChunkMetaData columnChunkMetaData,
boolean fixedLength, NullableDateVector v, SchemaElement schemaElement)
throws ExecutionSetupException {
super(parentReader, allocateSize, descriptor, columnChunkMetaData, fixedLength, v, schemaElement);
- dateVector = (NullableDateVector) v;
}
@Override
@@ -418,43 +412,35 @@ public class NullableFixedByteAlignedReaders {
}
if (intValue > ParquetReaderUtility.DATE_CORRUPTION_THRESHOLD) {
- dateVector.getMutator().set(index, (intValue - ParquetReaderUtility.CORRECT_CORRUPT_DATE_SHIFT) * DateTimeConstants.MILLIS_PER_DAY);
+ valueVec.getMutator().set(index, (intValue - ParquetReaderUtility.CORRECT_CORRUPT_DATE_SHIFT) * DateTimeConstants.MILLIS_PER_DAY);
} else {
- dateVector.getMutator().set(index, intValue * (long) DateTimeConstants.MILLIS_PER_DAY);
+ valueVec.getMutator().set(index, intValue * (long) DateTimeConstants.MILLIS_PER_DAY);
}
}
}
- public static class NullableDecimal28Reader extends NullableConvertedReader<NullableDecimal28SparseVector> {
-
- NullableDecimal28Reader(ParquetRecordReader parentReader, int allocateSize, ColumnDescriptor descriptor, ColumnChunkMetaData columnChunkMetaData,
- boolean fixedLength, NullableDecimal28SparseVector v, SchemaElement schemaElement) throws ExecutionSetupException {
+ public static class NullableVarDecimalReader extends NullableConvertedReader<NullableVarDecimalVector> {
+ NullableVarDecimalReader(ParquetRecordReader parentReader, int allocateSize, ColumnDescriptor descriptor, ColumnChunkMetaData columnChunkMetaData,
+ boolean fixedLength, NullableVarDecimalVector v, SchemaElement schemaElement) throws ExecutionSetupException {
super(parentReader, allocateSize, descriptor, columnChunkMetaData, fixedLength, v, schemaElement);
}
+ // TODO: allow reading page instead of reading every record separately
@Override
void addNext(int start, int index) {
- int width = NullableDecimal28SparseHolder.WIDTH;
- BigDecimal intermediate = DecimalUtility.getBigDecimalFromDrillBuf(bytebuf, start, dataTypeLengthInBytes,
- schemaElement.getScale());
- DecimalUtility.getSparseFromBigDecimal(intermediate, valueVec.getBuffer(), index * width, schemaElement.getScale(),
- schemaElement.getPrecision(), NullableDecimal28SparseHolder.nDecimalDigits);
- }
- }
-
- public static class NullableDecimal38Reader extends NullableConvertedReader<NullableDecimal38SparseVector> {
- NullableDecimal38Reader(ParquetRecordReader parentReader, int allocateSize, ColumnDescriptor descriptor, ColumnChunkMetaData columnChunkMetaData,
- boolean fixedLength, NullableDecimal38SparseVector v, SchemaElement schemaElement) throws ExecutionSetupException {
- super(parentReader, allocateSize, descriptor, columnChunkMetaData, fixedLength, v, schemaElement);
- }
+ switch (columnChunkMetaData.getType()) {
+ case INT32:
+ valueVec.getMutator().setSafe(index, Ints.toByteArray(bytebuf.getInt(start)), 0, dataTypeLengthInBytes);
+ break;
+ case INT64:
+ valueVec.getMutator().setSafe(index, Longs.toByteArray(bytebuf.getLong(start)), 0, dataTypeLengthInBytes);
+ break;
+ case FIXED_LEN_BYTE_ARRAY:
+ case BINARY:
+ valueVec.getMutator().setSafe(index, 1, start, start + dataTypeLengthInBytes, bytebuf);
+ break;
+ }
- @Override
- void addNext(int start, int index) {
- int width = NullableDecimal38SparseHolder.WIDTH;
- BigDecimal intermediate = DecimalUtility.getBigDecimalFromDrillBuf(bytebuf, start, dataTypeLengthInBytes,
- schemaElement.getScale());
- DecimalUtility.getSparseFromBigDecimal(intermediate, valueVec.getBuffer(), index * width, schemaElement.getScale(),
- schemaElement.getPrecision(), NullableDecimal38SparseHolder.nDecimalDigits);
}
}
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/columnreaders/ParquetFixedWidthDictionaryReaders.java b/exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/columnreaders/ParquetFixedWidthDictionaryReaders.java
index 5bc9ea11b..38ab70037 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/columnreaders/ParquetFixedWidthDictionaryReaders.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/columnreaders/ParquetFixedWidthDictionaryReaders.java
@@ -17,10 +17,10 @@
*/
package org.apache.drill.exec.store.parquet.columnreaders;
+import com.google.common.primitives.Ints;
+import com.google.common.primitives.Longs;
import org.apache.drill.common.exceptions.ExecutionSetupException;
import org.apache.drill.exec.vector.BigIntVector;
-import org.apache.drill.exec.vector.Decimal18Vector;
-import org.apache.drill.exec.vector.Decimal9Vector;
import org.apache.drill.exec.vector.Float4Vector;
import org.apache.drill.exec.vector.Float8Vector;
import org.apache.drill.exec.vector.IntVector;
@@ -29,6 +29,7 @@ import org.apache.drill.exec.vector.TimeVector;
import org.apache.drill.exec.vector.UInt4Vector;
import org.apache.drill.exec.vector.UInt8Vector;
import org.apache.drill.exec.vector.VarBinaryVector;
+import org.apache.drill.exec.vector.VarDecimalVector;
import org.apache.parquet.column.ColumnDescriptor;
import org.apache.parquet.format.SchemaElement;
import org.apache.parquet.hadoop.metadata.ColumnChunkMetaData;
@@ -38,6 +39,8 @@ import static org.apache.drill.exec.store.parquet.ParquetReaderUtility.NanoTimeU
public class ParquetFixedWidthDictionaryReaders {
+ private static final double BITS_COUNT_IN_BYTE_DOUBLE_VALUE = 8.0;
+
static class DictionaryIntReader extends FixedByteAlignedReader<IntVector> {
DictionaryIntReader(ParquetRecordReader parentReader, int allocateSize, ColumnDescriptor descriptor,
ColumnChunkMetaData columnChunkMetaData, boolean fixedLength, IntVector v,
@@ -86,7 +89,7 @@ public class ParquetFixedWidthDictionaryReaders {
// and we will go into the else condition below. The readField method of the parent class requires the
// writer index to be set correctly.
readLengthInBits = recordsReadInThisIteration * dataTypeLengthInBits;
- readLength = (int) Math.ceil(readLengthInBits / 8.0);
+ readLength = (int) Math.ceil(readLengthInBits / BITS_COUNT_IN_BYTE_DOUBLE_VALUE);
int writerIndex = valueVec.getBuffer().writerIndex();
valueVec.getBuffer().setIndex(0, writerIndex + (int) readLength);
} else {
@@ -109,7 +112,7 @@ public class ParquetFixedWidthDictionaryReaders {
recordsReadInThisIteration = Math.min(pageReader.currentPageCount
- pageReader.valuesRead, recordsToReadInThisPass - valuesReadInCurrentPass);
readLengthInBits = recordsReadInThisIteration * dataTypeLengthInBits;
- readLength = (int) Math.ceil(readLengthInBits / 8.0);
+ readLength = (int) Math.ceil(readLengthInBits / BITS_COUNT_IN_BYTE_DOUBLE_VALUE);
if (usingDictionary) {
VarBinaryVector.Mutator mutator = valueVec.getMutator();
@@ -137,28 +140,6 @@ public class ParquetFixedWidthDictionaryReaders {
}
}
- static class DictionaryDecimal9Reader extends FixedByteAlignedReader<Decimal9Vector> {
- DictionaryDecimal9Reader(ParquetRecordReader parentReader, int allocateSize, ColumnDescriptor descriptor,
- ColumnChunkMetaData columnChunkMetaData, boolean fixedLength, Decimal9Vector v,
- SchemaElement schemaElement) throws ExecutionSetupException {
- super(parentReader, allocateSize, descriptor, columnChunkMetaData, fixedLength, v, schemaElement);
- }
-
- // this method is called by its superclass during a read loop
- @Override
- protected void readField(long recordsToReadInThisPass) {
-
- recordsReadInThisIteration = Math.min(pageReader.currentPageCount
- - pageReader.valuesRead, recordsToReadInThisPass - valuesReadInCurrentPass);
-
- if (usingDictionary) {
- for (int i = 0; i < recordsReadInThisIteration; i++){
- valueVec.getMutator().setSafe(valuesReadInCurrentPass + i, pageReader.dictionaryValueReader.readInteger());
- }
- }
- }
- }
-
static class DictionaryTimeReader extends FixedByteAlignedReader<TimeVector> {
DictionaryTimeReader(ParquetRecordReader parentReader, int allocateSize, ColumnDescriptor descriptor,
ColumnChunkMetaData columnChunkMetaData, boolean fixedLength, TimeVector v,
@@ -204,7 +185,7 @@ public class ParquetFixedWidthDictionaryReaders {
// and we will go into the else condition below. The readField method of the parent class requires the
// writer index to be set correctly.
readLengthInBits = recordsReadInThisIteration * dataTypeLengthInBits;
- readLength = (int) Math.ceil(readLengthInBits / 8.0);
+ readLength = (int) Math.ceil(readLengthInBits / BITS_COUNT_IN_BYTE_DOUBLE_VALUE);
int writerIndex = valueVec.getBuffer().writerIndex();
valueVec.getBuffer().setIndex(0, writerIndex + (int)readLength);
} else {
@@ -239,7 +220,7 @@ public class ParquetFixedWidthDictionaryReaders {
// and we will go into the else condition below. The readField method of the parent class requires the
// writer index to be set correctly.
readLengthInBits = recordsReadInThisIteration * dataTypeLengthInBits;
- readLength = (int) Math.ceil(readLengthInBits / 8.0);
+ readLength = (int) Math.ceil(readLengthInBits / BITS_COUNT_IN_BYTE_DOUBLE_VALUE);
int writerIndex = valueVec.getBuffer().writerIndex();
valueVec.getBuffer().setIndex(0, writerIndex + (int) readLength);
} else {
@@ -248,27 +229,61 @@ public class ParquetFixedWidthDictionaryReaders {
}
}
- static class DictionaryDecimal18Reader extends FixedByteAlignedReader<Decimal18Vector> {
- DictionaryDecimal18Reader(ParquetRecordReader parentReader, int allocateSize, ColumnDescriptor descriptor,
- ColumnChunkMetaData columnChunkMetaData, boolean fixedLength, Decimal18Vector v,
- SchemaElement schemaElement) throws ExecutionSetupException {
+ static class DictionaryVarDecimalReader extends FixedByteAlignedReader<VarDecimalVector> {
+
+ DictionaryVarDecimalReader(ParquetRecordReader parentReader, int allocateSize, ColumnDescriptor descriptor,
+ ColumnChunkMetaData columnChunkMetaData, boolean fixedLength, VarDecimalVector v,
+ SchemaElement schemaElement) throws ExecutionSetupException {
super(parentReader, allocateSize, descriptor, columnChunkMetaData, fixedLength, v, schemaElement);
}
// this method is called by its superclass during a read loop
@Override
protected void readField(long recordsToReadInThisPass) {
+ recordsReadInThisIteration =
+ Math.min(pageReader.currentPageCount - pageReader.valuesRead,
+ recordsToReadInThisPass - valuesReadInCurrentPass);
+
+ switch (columnDescriptor.getType()) {
+ case INT32:
+ if (usingDictionary) {
+ for (int i = 0; i < recordsReadInThisIteration; i++) {
+ byte[] bytes = Ints.toByteArray(pageReader.dictionaryValueReader.readInteger());
+ setValueBytes(i, bytes);
+ }
+ setWriteIndex();
+ } else {
+ super.readField(recordsToReadInThisPass);
+ }
+ break;
+ case INT64:
+ if (usingDictionary) {
+ for (int i = 0; i < recordsReadInThisIteration; i++) {
+ byte[] bytes = Longs.toByteArray(pageReader.dictionaryValueReader.readLong());
+ setValueBytes(i, bytes);
+ }
+ setWriteIndex();
+ } else {
+ super.readField(recordsToReadInThisPass);
+ }
+ break;
+ }
+ }
- recordsReadInThisIteration = Math.min(pageReader.currentPageCount
- - pageReader.valuesRead, recordsToReadInThisPass - valuesReadInCurrentPass);
+ /**
+ * Set the write Index. The next page that gets read might be a page that does not use dictionary encoding
+ * and we will go into the else condition below. The readField method of the parent class requires the
+ * writer index to be set correctly.
+ */
+ private void setWriteIndex() {
+ readLengthInBits = recordsReadInThisIteration * dataTypeLengthInBits;
+ readLength = (int) Math.ceil(readLengthInBits / BITS_COUNT_IN_BYTE_DOUBLE_VALUE);
+ int writerIndex = valueVec.getBuffer().writerIndex();
+ valueVec.getBuffer().setIndex(0, writerIndex + (int) readLength);
+ }
- for (int i = 0; i < recordsReadInThisIteration; i++){
- try {
- valueVec.getMutator().setSafe(valuesReadInCurrentPass + i, pageReader.dictionaryValueReader.readLong());
- } catch ( Exception ex) {
- throw ex;
- }
- }
+ private void setValueBytes(int i, byte[] bytes) {
+ valueVec.getMutator().setSafe(valuesReadInCurrentPass + i, bytes, 0, bytes.length);
}
}
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/columnreaders/ParquetToDrillTypeConverter.java b/exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/columnreaders/ParquetToDrillTypeConverter.java
index d6cf5dbf2..309ed89bf 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/columnreaders/ParquetToDrillTypeConverter.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/columnreaders/ParquetToDrillTypeConverter.java
@@ -29,20 +29,11 @@ import org.apache.parquet.format.SchemaElement;
import org.apache.parquet.schema.PrimitiveType;
import static com.google.common.base.Preconditions.checkArgument;
-import static org.apache.parquet.format.Type.BYTE_ARRAY;
public class ParquetToDrillTypeConverter {
- private static TypeProtos.MinorType getDecimalType(SchemaElement schemaElement) {
- if (schemaElement.getType() == BYTE_ARRAY) {
- return TypeProtos.MinorType.VARDECIMAL; // variable width decimal uses new VARDECIMAL type
- }
- return schemaElement.getPrecision() <= 28 ? TypeProtos.MinorType.DECIMAL28SPARSE : MinorType.DECIMAL38SPARSE;
- }
-
private static TypeProtos.MinorType getMinorType(PrimitiveType.PrimitiveTypeName primitiveTypeName, int length,
- ConvertedType convertedType, SchemaElement schemaElement,
- OptionManager options) {
+ ConvertedType convertedType, OptionManager options) {
switch (primitiveTypeName) {
case BINARY:
if (convertedType == null) {
@@ -54,7 +45,7 @@ public class ParquetToDrillTypeConverter {
return (TypeProtos.MinorType.VARCHAR);
case DECIMAL:
ParquetReaderUtility.checkDecimalTypeEnabled(options);
- return (getDecimalType(schemaElement));
+ return TypeProtos.MinorType.VARDECIMAL;
default:
return (TypeProtos.MinorType.VARBINARY);
}
@@ -69,7 +60,7 @@ public class ParquetToDrillTypeConverter {
return TypeProtos.MinorType.UINT8;
case DECIMAL:
ParquetReaderUtility.checkDecimalTypeEnabled(options);
- return TypeProtos.MinorType.DECIMAL18;
+ return TypeProtos.MinorType.VARDECIMAL;
// TODO - add this back if it is decided to be added upstream, was removed form our pull request July 2014
// case TIME_MICROS:
// throw new UnsupportedOperationException();
@@ -93,7 +84,7 @@ public class ParquetToDrillTypeConverter {
return TypeProtos.MinorType.INT;
case DECIMAL:
ParquetReaderUtility.checkDecimalTypeEnabled(options);
- return TypeProtos.MinorType.DECIMAL9;
+ return TypeProtos.MinorType.VARDECIMAL;
case DATE:
return TypeProtos.MinorType.DATE;
case TIME_MILLIS:
@@ -121,7 +112,7 @@ public class ParquetToDrillTypeConverter {
return TypeProtos.MinorType.VARBINARY;
} else if (convertedType == ConvertedType.DECIMAL) {
ParquetReaderUtility.checkDecimalTypeEnabled(options);
- return getDecimalType(schemaElement);
+ return TypeProtos.MinorType.VARDECIMAL;
} else if (convertedType == ConvertedType.INTERVAL) {
return TypeProtos.MinorType.INTERVAL;
}
@@ -134,7 +125,7 @@ public class ParquetToDrillTypeConverter {
TypeProtos.DataMode mode, SchemaElement schemaElement,
OptionManager options) {
ConvertedType convertedType = schemaElement.getConverted_type();
- MinorType minorType = getMinorType(primitiveTypeName, length, convertedType, schemaElement, options);
+ MinorType minorType = getMinorType(primitiveTypeName, length, convertedType, options);
TypeProtos.MajorType.Builder typeBuilder = TypeProtos.MajorType.newBuilder().setMinorType(minorType).setMode(mode);
if (CoreDecimalUtility.isDecimalType(minorType)) {
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/columnreaders/VarLengthColumnReaders.java b/exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/columnreaders/VarLengthColumnReaders.java
index 2d8b4747a..dd61abda2 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/columnreaders/VarLengthColumnReaders.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/columnreaders/VarLengthColumnReaders.java
@@ -19,19 +19,11 @@ package org.apache.drill.exec.store.parquet.columnreaders;
import io.netty.buffer.DrillBuf;
-import java.math.BigDecimal;
import java.nio.ByteBuffer;
import org.apache.drill.common.exceptions.ExecutionSetupException;
-import org.apache.drill.exec.expr.holders.Decimal28SparseHolder;
-import org.apache.drill.exec.expr.holders.Decimal38SparseHolder;
-import org.apache.drill.exec.util.DecimalUtility;
import org.apache.drill.exec.vector.VarDecimalVector;
import org.apache.drill.exec.vector.NullableVarDecimalVector;
-import org.apache.drill.exec.vector.Decimal28SparseVector;
-import org.apache.drill.exec.vector.Decimal38SparseVector;
-import org.apache.drill.exec.vector.NullableDecimal28SparseVector;
-import org.apache.drill.exec.vector.NullableDecimal38SparseVector;
import org.apache.drill.exec.vector.NullableVarBinaryVector;
import org.apache.drill.exec.vector.NullableVarCharVector;
import org.apache.drill.exec.vector.VarBinaryVector;
@@ -45,9 +37,6 @@ import org.apache.parquet.hadoop.metadata.ColumnChunkMetaData;
public class VarLengthColumnReaders {
static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(VarLengthColumnReaders.class);
- /* DAO 7/28/2016 replace fixed width decimal columns for variable width parquet column, and instead use variable
- * width decimal column (new code, VarDecimal*)
- */
public static class VarDecimalColumn extends VarLengthValuesColumn<VarDecimalVector> {
protected VarDecimalVector varDecimalVector;
@@ -114,131 +103,6 @@ public class VarLengthColumnReaders {
return nullableVarDecimalVector.getBuffer().capacity();
}
}
- /* end DAO VarDecimal changes */
-
- public static class Decimal28Column extends VarLengthValuesColumn<Decimal28SparseVector> {
-
- protected Decimal28SparseVector decimal28Vector;
-
- Decimal28Column(ParquetRecordReader parentReader, int allocateSize, ColumnDescriptor descriptor,
- ColumnChunkMetaData columnChunkMetaData, boolean fixedLength, Decimal28SparseVector v,
- SchemaElement schemaElement) throws ExecutionSetupException {
- super(parentReader, allocateSize, descriptor, columnChunkMetaData, fixedLength, v, schemaElement);
- this.decimal28Vector = v;
- }
-
- @Override
- public boolean setSafe(int index, DrillBuf bytebuf, int start, int length) {
- int width = Decimal28SparseHolder.WIDTH;
- BigDecimal intermediate = DecimalUtility.getBigDecimalFromDrillBuf(bytebuf, start, length,
- schemaElement.getScale());
- if (index >= decimal28Vector.getValueCapacity()) {
- return false;
- }
- DecimalUtility.getSparseFromBigDecimal(intermediate, decimal28Vector.getBuffer(), index * width, schemaElement.getScale(),
- schemaElement.getPrecision(), Decimal28SparseHolder.nDecimalDigits);
- return true;
- }
-
- @Override
- public int capacity() {
- return decimal28Vector.getBuffer().capacity();
- }
- }
-
- public static class NullableDecimal28Column extends NullableVarLengthValuesColumn<NullableDecimal28SparseVector> {
-
- protected NullableDecimal28SparseVector nullableDecimal28Vector;
-
- NullableDecimal28Column(ParquetRecordReader parentReader, int allocateSize, ColumnDescriptor descriptor,
- ColumnChunkMetaData columnChunkMetaData, boolean fixedLength, NullableDecimal28SparseVector v,
- SchemaElement schemaElement) throws ExecutionSetupException {
- super(parentReader, allocateSize, descriptor, columnChunkMetaData, fixedLength, v, schemaElement);
- nullableDecimal28Vector = v;
- }
-
- @Override
- public boolean setSafe(int index, DrillBuf bytebuf, int start, int length) {
- int width = Decimal28SparseHolder.WIDTH;
- BigDecimal intermediate = DecimalUtility.getBigDecimalFromDrillBuf(bytebuf, start, length,
- schemaElement.getScale());
- if (index >= nullableDecimal28Vector.getValueCapacity()) {
- return false;
- }
- DecimalUtility.getSparseFromBigDecimal(intermediate, nullableDecimal28Vector.getBuffer(), index * width, schemaElement.getScale(),
- schemaElement.getPrecision(), Decimal28SparseHolder.nDecimalDigits);
- nullableDecimal28Vector.getMutator().setIndexDefined(index);
- return true;
- }
-
- @Override
- public int capacity() {
- return nullableDecimal28Vector.getBuffer().capacity();
- }
- }
-
- public static class Decimal38Column extends VarLengthValuesColumn<Decimal38SparseVector> {
-
- protected Decimal38SparseVector decimal28Vector;
-
- Decimal38Column(ParquetRecordReader parentReader, int allocateSize, ColumnDescriptor descriptor,
- ColumnChunkMetaData columnChunkMetaData, boolean fixedLength, Decimal38SparseVector v,
- SchemaElement schemaElement) throws ExecutionSetupException {
- super(parentReader, allocateSize, descriptor, columnChunkMetaData, fixedLength, v, schemaElement);
- decimal28Vector = v;
- }
-
- @Override
- public boolean setSafe(int index, DrillBuf bytebuf, int start, int length) {
- int width = Decimal38SparseHolder.WIDTH;
- BigDecimal intermediate = DecimalUtility.getBigDecimalFromDrillBuf(bytebuf, start, length,
- schemaElement.getScale());
- if (index >= decimal28Vector.getValueCapacity()) {
- return false;
- }
- DecimalUtility.getSparseFromBigDecimal(intermediate, decimal28Vector.getBuffer(), index * width, schemaElement.getScale(),
- schemaElement.getPrecision(), Decimal38SparseHolder.nDecimalDigits);
- return true;
- }
-
- @Override
- public int capacity() {
- return decimal28Vector.getBuffer().capacity();
- }
- }
-
- public static class NullableDecimal38Column extends NullableVarLengthValuesColumn<NullableDecimal38SparseVector> {
-
- private final NullableDecimal38SparseVector nullableDecimal38Vector;
-
- NullableDecimal38Column(ParquetRecordReader parentReader, int allocateSize, ColumnDescriptor descriptor,
- ColumnChunkMetaData columnChunkMetaData, boolean fixedLength, NullableDecimal38SparseVector v,
- SchemaElement schemaElement) throws ExecutionSetupException {
- super(parentReader, allocateSize, descriptor, columnChunkMetaData, fixedLength, v, schemaElement);
- nullableDecimal38Vector = v;
- }
-
- @Override
- public boolean setSafe(int index, DrillBuf bytebuf, int start, int length) {
- int width = Decimal38SparseHolder.WIDTH;
- BigDecimal intermediate = DecimalUtility.getBigDecimalFromDrillBuf(bytebuf, start, length,
- schemaElement.getScale());
- if (index >= nullableDecimal38Vector.getValueCapacity()) {
- return false;
- }
-
- DecimalUtility.getSparseFromBigDecimal(intermediate, nullableDecimal38Vector.getBuffer(), index * width, schemaElement.getScale(),
- schemaElement.getPrecision(), Decimal38SparseHolder.nDecimalDigits);
- nullableDecimal38Vector.getMutator().setIndexDefined(index);
- return true;
- }
-
- @Override
- public int capacity() {
- return nullableDecimal38Vector.getBuffer().capacity();
- }
- }
- /* DAO */
public static class VarCharColumn extends VarLengthValuesColumn<VarCharVector> {
@@ -278,8 +142,6 @@ public class VarLengthColumnReaders {
public static class NullableVarCharColumn extends NullableVarLengthValuesColumn<NullableVarCharVector> {
- int nullsRead;
- boolean currentValNull = false;
// store a hard reference to the vector (which is also stored in the superclass) to prevent repetitive casting
protected final NullableVarCharVector.Mutator mutator;
private final NullableVarCharVector vector;
@@ -351,8 +213,6 @@ public class VarLengthColumnReaders {
public static class NullableVarBinaryColumn extends NullableVarLengthValuesColumn<NullableVarBinaryVector> {
- int nullsRead;
- boolean currentValNull = false;
// store a hard reference to the vector (which is also stored in the superclass) to prevent repetitive casting
private final NullableVarBinaryVector nullableVarBinaryVector;
private final NullableVarBinaryVector.Mutator mutator;
@@ -365,7 +225,6 @@ public class VarLengthColumnReaders {
mutator = v.getMutator();
}
-
@Override
public boolean setSafe(int index, DrillBuf value, int start, int length) {
if (index >= nullableVarBinaryVector.getValueCapacity()) {
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/decimal/BinaryDecimalParquetValueWriter.java b/exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/decimal/BinaryDecimalParquetValueWriter.java
new file mode 100644
index 000000000..85d9f80ff
--- /dev/null
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/decimal/BinaryDecimalParquetValueWriter.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.drill.exec.store.parquet.decimal;
+
+import io.netty.buffer.DrillBuf;
+import org.apache.parquet.io.api.Binary;
+import org.apache.parquet.io.api.RecordConsumer;
+
+/**
+ * Parquet value writer for passing decimal values
+ * into {@code RecordConsumer} to be stored as BINARY type.
+ */
+public class BinaryDecimalParquetValueWriter extends DecimalValueWriter {
+
+ @Override
+ public void writeValue(RecordConsumer consumer, DrillBuf buffer, int start, int end, int precision) {
+ consumer.addBinary(Binary.fromReusedByteBuffer(buffer.nioBuffer(start, end - start)));
+ }
+}
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/decimal/DecimalValueWriter.java b/exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/decimal/DecimalValueWriter.java
new file mode 100644
index 000000000..ed70a4175
--- /dev/null
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/decimal/DecimalValueWriter.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.drill.exec.store.parquet.decimal;
+
+import io.netty.buffer.DrillBuf;
+import org.apache.parquet.io.api.RecordConsumer;
+import org.apache.parquet.schema.PrimitiveType;
+
+public abstract class DecimalValueWriter {
+
+ /**
+ * Takes value from specified {@code DrillBuf buffer}, converts it into required format
+ * if needed and passes the value into specified {@code RecordConsumer consumer}.
+ *
+ * @param consumer abstraction for writing records
+ * @param buffer the source of data that should be written
+ * @param start start position of data in buffer
+ * @param end end position of data in buffer
+ * @param precision precision of the value that should be stored
+ */
+ public abstract void writeValue(RecordConsumer consumer, DrillBuf buffer,
+ int start, int end, int precision);
+
+ /**
+ * Creates and returns writer suitable for specified {@code PrimitiveType.PrimitiveTypeName type}.
+ *
+ * @param type the type of the value in output file.
+ * @return writer for decimal values.
+ */
+ public static DecimalValueWriter getDecimalValueWriterForType(
+ PrimitiveType.PrimitiveTypeName type) {
+ switch (type) {
+ case INT32:
+ return new Int32DecimalParquetValueWriter();
+ case INT64:
+ return new Int64DecimalParquetValueWriter();
+ case FIXED_LEN_BYTE_ARRAY:
+ return new FixedLenDecimalParquetValueWriter();
+ case BINARY:
+ return new BinaryDecimalParquetValueWriter();
+ default:
+ throw new UnsupportedOperationException(
+ String.format("Specified PrimitiveTypeName %s cannot be used to store decimal values", type));
+ }
+ }
+}
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/decimal/FixedLenDecimalParquetValueWriter.java b/exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/decimal/FixedLenDecimalParquetValueWriter.java
new file mode 100644
index 000000000..893d9dcd3
--- /dev/null
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/decimal/FixedLenDecimalParquetValueWriter.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.drill.exec.store.parquet.decimal;
+
+import io.netty.buffer.DrillBuf;
+import org.apache.drill.exec.util.DecimalUtility;
+import org.apache.parquet.io.api.Binary;
+import org.apache.parquet.io.api.RecordConsumer;
+
+import java.util.Arrays;
+
+/**
+ * Parquet value writer for passing decimal values
+ * into {@code RecordConsumer} to be stored as FIXED_LEN_BYTE_ARRAY type.
+ */
+public class FixedLenDecimalParquetValueWriter extends DecimalValueWriter {
+
+ @Override
+ public void writeValue(RecordConsumer consumer, DrillBuf buffer, int start, int end, int precision) {
+ int typeLength = DecimalUtility.getMaxBytesSizeForPrecision(precision);
+ int length = end - start;
+ int startPos = typeLength - length;
+ byte[] output = new byte[typeLength];
+ if (startPos >= 0) {
+ buffer.getBytes(start, output, startPos, length);
+ if (output[startPos] < 0) {
+ Arrays.fill(output, 0, output.length - length, (byte) -1);
+ }
+ } else {
+ // in this case value from FIXED_LEN_BYTE_ARRAY or BINARY field with greater length was taken, ignore leading bytes
+ buffer.getBytes(start - startPos, output, 0, length + startPos);
+ }
+ consumer.addBinary(Binary.fromReusedByteArray(output));
+ }
+}
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/decimal/Int32DecimalParquetValueWriter.java b/exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/decimal/Int32DecimalParquetValueWriter.java
new file mode 100644
index 000000000..1dc90a09b
--- /dev/null
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/decimal/Int32DecimalParquetValueWriter.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.drill.exec.store.parquet.decimal;
+
+import com.google.common.primitives.Ints;
+import io.netty.buffer.DrillBuf;
+import org.apache.parquet.io.api.RecordConsumer;
+
+import java.util.Arrays;
+
+/**
+ * Parquet value writer for passing decimal values
+ * into {@code RecordConsumer} to be stored as INT32 type.
+ */
+public class Int32DecimalParquetValueWriter extends DecimalValueWriter {
+
+ @Override
+ public void writeValue(RecordConsumer consumer, DrillBuf buffer, int start, int end, int precision) {
+ byte[] output;
+ int startPos;
+ int length = end - start;
+ startPos = Ints.BYTES - length;
+ output = new byte[Ints.BYTES];
+ if (startPos >= 0) {
+ buffer.getBytes(start, output, startPos, length);
+ } else {
+ // in this case value from FIXED_LEN_BYTE_ARRAY or BINARY field was taken, ignore leading bytes
+ buffer.getBytes(start - startPos, output, 0, length + startPos);
+ startPos = 0;
+ }
+ if (output[startPos] < 0) {
+ Arrays.fill(output, 0, output.length - length, (byte) -1);
+ }
+ consumer.addInteger(Ints.fromByteArray(output));
+ }
+}
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/decimal/Int64DecimalParquetValueWriter.java b/exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/decimal/Int64DecimalParquetValueWriter.java
new file mode 100644
index 000000000..f6b83970e
--- /dev/null
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet/decimal/Int64DecimalParquetValueWriter.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.drill.exec.store.parquet.decimal;
+
+import com.google.common.primitives.Longs;
+import io.netty.buffer.DrillBuf;
+import org.apache.parquet.io.api.RecordConsumer;
+
+import java.util.Arrays;
+
+/**
+ * Parquet value writer for passing decimal values
+ * into {@code RecordConsumer} to be stored as INT32 type.
+ */
+public class Int64DecimalParquetValueWriter extends DecimalValueWriter {
+
+ @Override
+ public void writeValue(RecordConsumer consumer, DrillBuf buffer, int start, int end, int precision) {
+ byte[] output;
+ int startPos;
+ int length = end - start;
+ startPos = Longs.BYTES - length;
+ output = new byte[Longs.BYTES];
+ if (startPos > 0) {
+ buffer.getBytes(start, output, startPos, length);
+ if (output[startPos] < 0) {
+ Arrays.fill(output, 0, output.length - length, (byte) -1);
+ }
+ } else {
+ // in this case value from FIXED_LEN_BYTE_ARRAY or BINARY field was taken, ignore leading bytes
+ buffer.getBytes(start - startPos, output, 0, length + startPos);
+ }
+ consumer.addLong(Longs.fromByteArray(output));
+ }
+}
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet2/DrillParquetGroupConverter.java b/exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet2/DrillParquetGroupConverter.java
index f451ee28b..59302d067 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet2/DrillParquetGroupConverter.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/store/parquet2/DrillParquetGroupConverter.java
@@ -19,12 +19,13 @@ package org.apache.drill.exec.store.parquet2;
import static org.apache.drill.exec.store.parquet.ParquetReaderUtility.NanoTimeUtils.getDateTimeValueFromBinary;
-import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
+import com.google.common.primitives.Ints;
+import com.google.common.primitives.Longs;
import org.apache.drill.common.exceptions.DrillRuntimeException;
import org.apache.drill.common.expression.PathSegment;
import org.apache.drill.common.expression.SchemaPath;
@@ -32,10 +33,6 @@ import org.apache.drill.exec.ExecConstants;
import org.apache.drill.exec.expr.holders.BigIntHolder;
import org.apache.drill.exec.expr.holders.BitHolder;
import org.apache.drill.exec.expr.holders.DateHolder;
-import org.apache.drill.exec.expr.holders.Decimal18Holder;
-import org.apache.drill.exec.expr.holders.Decimal28SparseHolder;
-import org.apache.drill.exec.expr.holders.Decimal38SparseHolder;
-import org.apache.drill.exec.expr.holders.Decimal9Holder;
import org.apache.drill.exec.expr.holders.Float4Holder;
import org.apache.drill.exec.expr.holders.Float8Holder;
import org.apache.drill.exec.expr.holders.IntHolder;
@@ -49,16 +46,11 @@ import org.apache.drill.exec.physical.impl.OutputMutator;
import org.apache.drill.exec.server.options.OptionManager;
import org.apache.drill.exec.store.parquet.ParquetReaderUtility;
import org.apache.drill.exec.store.parquet.columnreaders.ParquetColumnMetadata;
-import org.apache.drill.exec.util.DecimalUtility;
import org.apache.drill.exec.vector.complex.impl.ComplexWriterImpl;
import org.apache.drill.exec.vector.complex.writer.BaseWriter.MapWriter;
import org.apache.drill.exec.vector.complex.writer.BigIntWriter;
import org.apache.drill.exec.vector.complex.writer.BitWriter;
import org.apache.drill.exec.vector.complex.writer.DateWriter;
-import org.apache.drill.exec.vector.complex.writer.Decimal18Writer;
-import org.apache.drill.exec.vector.complex.writer.Decimal28SparseWriter;
-import org.apache.drill.exec.vector.complex.writer.Decimal38SparseWriter;
-import org.apache.drill.exec.vector.complex.writer.Decimal9Writer;
import org.apache.drill.exec.vector.complex.writer.Float4Writer;
import org.apache.drill.exec.vector.complex.writer.Float8Writer;
import org.apache.drill.exec.vector.complex.writer.IntWriter;
@@ -75,7 +67,6 @@ import org.apache.parquet.io.api.PrimitiveConverter;
import org.apache.parquet.schema.DecimalMetadata;
import org.apache.parquet.schema.GroupType;
import org.apache.parquet.schema.MessageType;
-import org.apache.parquet.schema.OriginalType;
import org.apache.parquet.schema.PrimitiveType;
import org.apache.parquet.schema.Type;
import org.apache.parquet.schema.Type.Repetition;
@@ -191,10 +182,11 @@ public class DrillParquetGroupConverter extends GroupConverter {
}
case DECIMAL: {
ParquetReaderUtility.checkDecimalTypeEnabled(options);
- Decimal9Writer writer = type.getRepetition() == Repetition.REPEATED
- ? mapWriter.list(name).decimal9()
- : mapWriter.decimal9(name, type.getDecimalMetadata().getScale(), type.getDecimalMetadata().getPrecision());
- return new DrillDecimal9Converter(writer, type.getDecimalMetadata().getPrecision(), type.getDecimalMetadata().getScale());
+ VarDecimalWriter writer = type.getRepetition() == Repetition.REPEATED
+ ? mapWriter.list(name).varDecimal(type.getDecimalMetadata().getScale(), type.getDecimalMetadata().getPrecision())
+ : mapWriter.varDecimal(name, type.getDecimalMetadata().getScale(), type.getDecimalMetadata().getPrecision());
+ return new DrillVarDecimalConverter(writer, type.getDecimalMetadata().getPrecision(),
+ type.getDecimalMetadata().getScale(), mutator.getManagedBuffer());
}
case DATE: {
DateWriter writer = type.getRepetition() == Repetition.REPEATED ? mapWriter.list(name).date() : mapWriter.date(name);
@@ -234,10 +226,11 @@ public class DrillParquetGroupConverter extends GroupConverter {
}
case DECIMAL: {
ParquetReaderUtility.checkDecimalTypeEnabled(options);
- Decimal18Writer writer = type.getRepetition() == Repetition.REPEATED
- ? mapWriter.list(name).decimal18()
- : mapWriter.decimal18(name, type.getDecimalMetadata().getScale(), type.getDecimalMetadata().getPrecision());
- return new DrillDecimal18Converter(writer, type.getDecimalMetadata().getPrecision(), type.getDecimalMetadata().getScale());
+ VarDecimalWriter writer = type.getRepetition() == Repetition.REPEATED
+ ? mapWriter.list(name).varDecimal(type.getDecimalMetadata().getScale(), type.getDecimalMetadata().getPrecision())
+ : mapWriter.varDecimal(name, type.getDecimalMetadata().getScale(), type.getDecimalMetadata().getPrecision());
+ return new DrillVarDecimalConverter(writer, type.getDecimalMetadata().getPrecision(),
+ type.getDecimalMetadata().getScale(), mutator.getManagedBuffer());
}
case TIMESTAMP_MILLIS: {
TimeStampWriter writer = type.getRepetition() == Repetition.REPEATED ? mapWriter.list(name).timeStamp() : mapWriter.timeStamp(name);
@@ -287,22 +280,15 @@ public class DrillParquetGroupConverter extends GroupConverter {
VarCharWriter writer = type.getRepetition() == Repetition.REPEATED ? mapWriter.list(name).varChar() : mapWriter.varChar(name);
return new DrillVarCharConverter(writer, mutator.getManagedBuffer());
}
- // TODO not sure if BINARY/DECIMAL is actually supported.
// See DRILL-4184 and DRILL-4834. Support for this is added using new VarDecimal type.
case DECIMAL: {
ParquetReaderUtility.checkDecimalTypeEnabled(options);
DecimalMetadata metadata = type.getDecimalMetadata();
- VarDecimalWriter writer = type.getRepetition() == Repetition.REPEATED ? mapWriter.list(name).varDecimal() : mapWriter.varDecimal(name);
- return new DrillBinaryToVarDecimalConverter(writer, metadata.getPrecision(), metadata.getScale(), mutator.getManagedBuffer());
- /* DAO 7/28/2016 this has previously used the following logic for fixed-width decimal vectors
- if (metadata.getPrecision() <= 28) {
- Decimal28SparseWriter writer = type.getRepetition() == Repetition.REPEATED ? mapWriter.list(name).decimal28Sparse() : mapWriter.decimal28Sparse(name, metadata.getScale(), metadata.getPrecision());
- return new DrillBinaryToDecimal28Converter(writer, metadata.getPrecision(), metadata.getScale(), mutator.getManagedBuffer());
- } else {
- Decimal38SparseWriter writer = type.getRepetition() == Repetition.REPEATED ? mapWriter.list(name).decimal38Sparse() : mapWriter.decimal38Sparse(name, metadata.getScale(), metadata.getPrecision());
- return new DrillBinaryToDecimal38Converter(writer, metadata.getPrecision(), metadata.getScale(), mutator.getManagedBuffer());
- }
- */
+ VarDecimalWriter writer =
+ type.getRepetition() == Repetition.REPEATED
+ ? mapWriter.list(name).varDecimal(metadata.getScale(), metadata.getPrecision())
+ : mapWriter.varDecimal(name, metadata.getScale(), metadata.getPrecision());
+ return new DrillVarDecimalConverter(writer, metadata.getPrecision(), metadata.getScale(), mutator.getManagedBuffer());
}
default: {
throw new UnsupportedOperationException("Unsupported type " + type.getOriginalType());
@@ -310,28 +296,28 @@ public class DrillParquetGroupConverter extends GroupConverter {
}
}
case FIXED_LEN_BYTE_ARRAY:
- if (type.getOriginalType() == OriginalType.DECIMAL) {
- ParquetReaderUtility.checkDecimalTypeEnabled(options);
- DecimalMetadata metadata = type.getDecimalMetadata();
- if (metadata.getPrecision() <= 28) {
- Decimal28SparseWriter writer = type.getRepetition() == Repetition.REPEATED
- ? mapWriter.list(name).decimal28Sparse()
- : mapWriter.decimal28Sparse(name, metadata.getScale(), metadata.getPrecision());
- return new DrillBinaryToDecimal28Converter(writer, metadata.getPrecision(), metadata.getScale(), mutator.getManagedBuffer());
- } else {
- Decimal38SparseWriter writer = type.getRepetition() == Repetition.REPEATED
- ? mapWriter.list(name).decimal38Sparse()
- : mapWriter.decimal38Sparse(name, metadata.getScale(), metadata.getPrecision());
- return new DrillBinaryToDecimal38Converter(writer, metadata.getPrecision(), metadata.getScale(), mutator.getManagedBuffer());
+ switch (type.getOriginalType()) {
+ case DECIMAL: {
+ ParquetReaderUtility.checkDecimalTypeEnabled(options);
+ DecimalMetadata metadata = type.getDecimalMetadata();
+ VarDecimalWriter writer = type.getRepetition() == Repetition.REPEATED
+ ? mapWriter.list(name).varDecimal(metadata.getScale(), metadata.getPrecision())
+ : mapWriter.varDecimal(name, metadata.getScale(), metadata.getPrecision());
+ return new DrillVarDecimalConverter(writer, metadata.getPrecision(), metadata.getScale(), mutator.getManagedBuffer());
}
- } else if (type.getOriginalType() == OriginalType.INTERVAL) {
- IntervalWriter writer = type.getRepetition() == Repetition.REPEATED ? mapWriter.list(name).interval()
- : mapWriter.interval(name);
- return new DrillFixedLengthByteArrayToInterval(writer);
+ case INTERVAL: {
+ IntervalWriter writer = type.getRepetition() == Repetition.REPEATED
+ ? mapWriter.list(name).interval()
+ : mapWriter.interval(name);
+ return new DrillFixedLengthByteArrayToInterval(writer);
- } else {
- VarBinaryWriter writer = type.getRepetition() == Repetition.REPEATED ? mapWriter.list(name).varBinary() : mapWriter.varBinary(name);
- return new DrillFixedBinaryToVarbinaryConverter(writer, type.getTypeLength(), mutator.getManagedBuffer());
+ }
+ default: {
+ VarBinaryWriter writer = type.getRepetition() == Repetition.REPEATED
+ ? mapWriter.list(name).varBinary()
+ : mapWriter.varBinary(name);
+ return new DrillFixedBinaryToVarbinaryConverter(writer, type.getTypeLength(), mutator.getManagedBuffer());
+ }
}
default:
throw new UnsupportedOperationException("Unsupported type: " + type.getPrimitiveTypeName());
@@ -369,25 +355,6 @@ public class DrillParquetGroupConverter extends GroupConverter {
}
}
- public static class DrillDecimal9Converter extends PrimitiveConverter {
- private Decimal9Writer writer;
- private Decimal9Holder holder = new Decimal9Holder();
- int precision;
- int scale;
-
- public DrillDecimal9Converter(Decimal9Writer writer, int precision, int scale) {
- this.writer = writer;
- this.scale = scale;
- this.precision = precision;
- }
-
- @Override
- public void addInt(int value) {
- holder.value = value;
- writer.write(holder);
- }
- }
-
public static class CorruptionDetectingDateConverter extends PrimitiveConverter {
private DateWriter writer;
private DateHolder holder = new DateHolder();
@@ -482,23 +449,6 @@ public class DrillParquetGroupConverter extends GroupConverter {
}
}
- public static class DrillDecimal18Converter extends PrimitiveConverter {
- private Decimal18Writer writer;
- private Decimal18Holder holder = new Decimal18Holder();
-
- public DrillDecimal18Converter(Decimal18Writer writer, int precision, int scale) {
- this.writer = writer;
- holder.precision = precision;
- holder.scale = scale;
- }
-
- @Override
- public void addLong(long value) {
- holder.value = value;
- writer.write(holder);
- }
- }
-
public static class DrillFloat4Converter extends PrimitiveConverter {
private Float4Writer writer;
private Float4Holder holder = new Float4Holder();
@@ -584,70 +534,44 @@ public class DrillParquetGroupConverter extends GroupConverter {
}
}
- public static class DrillBinaryToVarDecimalConverter extends PrimitiveConverter {
+ public static class DrillVarDecimalConverter extends PrimitiveConverter {
private VarDecimalWriter writer;
private VarDecimalHolder holder = new VarDecimalHolder();
private DrillBuf buf;
- public DrillBinaryToVarDecimalConverter(VarDecimalWriter writer, int precision, int scale, DrillBuf buf) {
+ public DrillVarDecimalConverter(VarDecimalWriter writer, int precision, int scale, DrillBuf buf) {
this.writer = writer;
holder.scale = scale;
+ holder.precision = precision;
+ this.buf = buf;
}
@Override
public void addBinary(Binary value) {
- // NOTE: the following commented out line can be used later to produce a BigDecimal number from the binary value,
- // with the scale information added from holder.scale. For variable width decimal vectors, unlike for fixed width ones,
- // we don't need to convert to a "sparse" representation (line after next, commented out) as the binary array is already
- // "sparse" in the sense that it should only use a number of bytes needed to encode this particular numerical value.
- //BigDecimal bigDecimal = DecimalUtility.getBigDecimalFromByteArray(value.getBytes(), 0, value.length(), holder.scale);
- //DecimalUtility.getSparseFromBigDecimal(bigDecimal, buf, 0, holder.scale, holder.precision, Decimal28SparseHolder.nDecimalDigits);
- holder.buffer = buf = buf.reallocIfNeeded(value.length());
- buf.setBytes(0, value.toByteBuffer());
+ holder.buffer = buf.reallocIfNeeded(value.length());
+ holder.buffer.setBytes(0, value.toByteBuffer());
holder.start = 0;
holder.end = value.length();
writer.write(holder);
}
- }
-
- public static class DrillBinaryToDecimal28Converter extends PrimitiveConverter {
- private Decimal28SparseWriter writer;
- private Decimal28SparseHolder holder = new Decimal28SparseHolder();
- private DrillBuf buf;
-
- public DrillBinaryToDecimal28Converter(Decimal28SparseWriter writer, int precision, int scale, DrillBuf buf) {
- this.writer = writer;
- this.buf = buf.reallocIfNeeded(28);
- holder.precision = precision;
- holder.scale = scale;
- }
@Override
- public void addBinary(Binary value) {
- BigDecimal bigDecimal = DecimalUtility.getBigDecimalFromByteArray(value.getBytes(), 0, value.length(), holder.scale);
- DecimalUtility.getSparseFromBigDecimal(bigDecimal, buf, 0, holder.scale, holder.precision, Decimal28SparseHolder.nDecimalDigits);
- holder.buffer = buf;
+ public void addInt(int value) {
+ byte[] bytes = Ints.toByteArray(value);
+ holder.buffer = buf.reallocIfNeeded(bytes.length);
+ holder.buffer.setBytes(0, bytes);
+ holder.start = 0;
+ holder.end = bytes.length;
writer.write(holder);
}
- }
-
- public static class DrillBinaryToDecimal38Converter extends PrimitiveConverter {
- private Decimal38SparseWriter writer;
- private Decimal38SparseHolder holder = new Decimal38SparseHolder();
- private DrillBuf buf;
-
- public DrillBinaryToDecimal38Converter(Decimal38SparseWriter writer, int precision, int scale, DrillBuf buf) {
- this.writer = writer;
- this.buf = buf.reallocIfNeeded(38);
- holder.precision = precision;
- holder.scale = scale;
- }
@Override
- public void addBinary(Binary value) {
- BigDecimal bigDecimal = DecimalUtility.getBigDecimalFromByteArray(value.getBytes(), 0, value.length(), holder.scale);
- DecimalUtility.getSparseFromBigDecimal(bigDecimal, buf, 0, holder.scale, holder.precision, Decimal38SparseHolder.nDecimalDigits);
- holder.buffer = buf;
+ public void addLong(long value) {
+ byte[] bytes = Longs.toByteArray(value);
+ holder.buffer = buf.reallocIfNeeded(bytes.length);
+ holder.buffer.setBytes(0, bytes);
+ holder.start = 0;
+ holder.end = bytes.length;
writer.write(holder);
}
}
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/store/pojo/PojoDataType.java b/exec/java-exec/src/main/java/org/apache/drill/exec/store/pojo/PojoDataType.java
index cb68efcb9..7d8a8e492 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/store/pojo/PojoDataType.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/store/pojo/PojoDataType.java
@@ -19,11 +19,10 @@ package org.apache.drill.exec.store.pojo;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
+import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.List;
-import org.apache.calcite.rel.type.RelDataType;
-import org.apache.calcite.rel.type.RelDataTypeFactory;
import org.apache.calcite.sql.type.SqlTypeName;
import com.google.common.collect.Lists;
@@ -57,6 +56,8 @@ public class PojoDataType extends RecordDataType {
types.add(SqlTypeName.BIGINT);
} else if(type == double.class || type == Double.class) {
types.add(SqlTypeName.DOUBLE);
+ } else if(type == BigDecimal.class) {
+ types.add(SqlTypeName.DECIMAL);
} else if(type == String.class) {
types.add(SqlTypeName.VARCHAR);
} else if(type.isEnum()) {
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/store/pojo/PojoWriters.java b/exec/java-exec/src/main/java/org/apache/drill/exec/store/pojo/PojoWriters.java
index 090f32f6f..19c236585 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/store/pojo/PojoWriters.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/store/pojo/PojoWriters.java
@@ -19,6 +19,7 @@ package org.apache.drill.exec.store.pojo;
import io.netty.buffer.DrillBuf;
+import java.math.BigDecimal;
import java.sql.Timestamp;
import org.apache.drill.common.exceptions.ExecutionSetupException;
@@ -37,6 +38,7 @@ import org.apache.drill.exec.vector.NullableTimeStampVector;
import org.apache.drill.exec.vector.NullableVarCharVector;
import com.google.common.base.Charsets;
+import org.apache.drill.exec.vector.VarDecimalVector;
public class PojoWriters {
@@ -63,6 +65,8 @@ public class PojoWriters {
return new EnumWriter(fieldName, buffer);
} else if (type == String.class) {
return new StringWriter(fieldName, buffer);
+ } else if (type == BigDecimal.class) {
+ return new DecimalWriter(fieldName);
} else if (type == Timestamp.class) {
return new NTimeStampWriter(fieldName);
// primitives
@@ -143,6 +147,24 @@ public class PojoWriters {
}
/**
+ * Pojo writer for decimal. If null is encountered does not write it.
+ */
+ public static class DecimalWriter extends AbstractPojoWriter<VarDecimalVector> {
+
+ public DecimalWriter(String fieldName) {
+ super(fieldName, Types.optional(MinorType.VARDECIMAL));
+ }
+
+ @Override
+ public void writeField(Object value, int outboundIndex) {
+ if (value != null) {
+ vector.getMutator().setSafe(outboundIndex, (BigDecimal) value);
+ }
+ }
+
+ }
+
+ /**
* Parent class for String and Enum writers. Writes data using nullable varchar holder.
*/
private abstract static class AbstractStringWriter extends AbstractPojoWriter<NullableVarCharVector> {
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/vector/complex/MapUtility.java b/exec/java-exec/src/main/java/org/apache/drill/exec/vector/complex/MapUtility.java
index 9a35b234a..543a6db98 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/vector/complex/MapUtility.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/vector/complex/MapUtility.java
@@ -132,9 +132,12 @@ public class MapUtility {
break;
case VARDECIMAL:
if (repeated) {
- fieldReader.copyAsValue(mapWriter.list(MappifyUtility.fieldValue).varDecimal());
+ fieldReader.copyAsValue(
+ mapWriter.list(MappifyUtility.fieldValue)
+ .varDecimal(valueMajorType.getScale(), valueMajorType.getPrecision()));
} else {
- fieldReader.copyAsValue(mapWriter.varDecimal(MappifyUtility.fieldValue));
+ fieldReader.copyAsValue(
+ mapWriter.varDecimal(MappifyUtility.fieldValue, valueMajorType.getScale(), valueMajorType.getPrecision()));
}
break;
case DATE:
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/work/ExecErrorConstants.java b/exec/java-exec/src/main/java/org/apache/drill/exec/work/ExecErrorConstants.java
index 9c7b9b90a..f1ebffbb2 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/work/ExecErrorConstants.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/work/ExecErrorConstants.java
@@ -22,7 +22,6 @@ import org.apache.drill.exec.planner.physical.PlannerSettings;
public interface ExecErrorConstants {
// Error message when decimal data type is disabled
- public static final String DECIMAL_DISABLE_ERR_MSG = String.format("Decimal data type is disabled. \n" +
- "As of this release decimal data type is a beta level feature and should not be used in production \n" +
+ String DECIMAL_DISABLE_ERR_MSG = String.format("Decimal data type is disabled. \n" +
"Use option '%s' to enable decimal data type", PlannerSettings.ENABLE_DECIMAL_DATA_TYPE_KEY);
}
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/work/prepare/PreparedStatementProvider.java b/exec/java-exec/src/main/java/org/apache/drill/exec/work/prepare/PreparedStatementProvider.java
index b748cdb59..4c757ef21 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/work/prepare/PreparedStatementProvider.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/work/prepare/PreparedStatementProvider.java
@@ -91,6 +91,7 @@ public class PreparedStatementProvider {
.put(MinorType.DECIMAL18, BigDecimal.class.getName())
.put(MinorType.DECIMAL28SPARSE, BigDecimal.class.getName())
.put(MinorType.DECIMAL38SPARSE, BigDecimal.class.getName())
+ .put(MinorType.VARDECIMAL, BigDecimal.class.getName())
.put(MinorType.TIME, Time.class.getName())
.put(MinorType.TIMESTAMP, Timestamp.class.getName())
.put(MinorType.VARBINARY, byte[].class.getName())
diff --git a/exec/java-exec/src/main/resources/drill-module.conf b/exec/java-exec/src/main/resources/drill-module.conf
index 60fd63928..8874f9204 100644
--- a/exec/java-exec/src/main/resources/drill-module.conf
+++ b/exec/java-exec/src/main/resources/drill-module.conf
@@ -466,7 +466,7 @@ drill.exec.options: {
planner.disable_exchanges: false,
planner.enable_broadcast_join: true,
planner.enable_constant_folding: true,
- planner.enable_decimal_data_type: false,
+ planner.enable_decimal_data_type: true,
planner.enable_demux_exchange: false,
planner.enable_hash_single_key: true,
planner.enable_hashagg: true,
@@ -548,6 +548,8 @@ drill.exec.options: {
store.parquet.use_new_reader: false,
store.parquet.vector_fill_check_threshold: 10,
store.parquet.vector_fill_threshold: 85,
+ store.parquet.writer.use_primitive_types_for_decimals: true,
+ store.parquet.writer.logical_type_for_decimals: "fixed_len_byte_array",
store.parquet.writer.use_single_fs_block: false,
store.partition.hash_distribute: false,
store.text.estimated_row_size_bytes: 100.0,
diff --git a/exec/java-exec/src/test/java/org/apache/drill/PlanningBase.java b/exec/java-exec/src/test/java/org/apache/drill/PlanningBase.java
index 0dc62c637..18fc4e137 100644
--- a/exec/java-exec/src/test/java/org/apache/drill/PlanningBase.java
+++ b/exec/java-exec/src/test/java/org/apache/drill/PlanningBase.java
@@ -20,12 +20,17 @@ package org.apache.drill;
import java.io.IOException;
import java.net.URL;
+import com.google.common.base.Function;
+import io.netty.buffer.DrillBuf;
import org.apache.calcite.jdbc.CalciteSchema;
import org.apache.calcite.schema.SchemaPlus;
import org.apache.drill.common.config.DrillConfig;
import org.apache.drill.common.config.LogicalPlanPersistence;
import org.apache.drill.common.scanner.ClassPathScanner;
import org.apache.drill.common.scanner.persistence.ScanResult;
+import org.apache.drill.common.types.TypeProtos;
+import org.apache.drill.exec.expr.holders.ValueHolder;
+import org.apache.drill.exec.vector.ValueHolderHelper;
import org.apache.drill.test.TestTools;
import org.apache.drill.exec.ExecTest;
import org.apache.drill.exec.expr.fn.FunctionImplementationRegistry;
@@ -54,7 +59,9 @@ import com.codahale.metrics.MetricRegistry;
import com.google.common.base.Charsets;
import com.google.common.collect.ImmutableList;
import com.google.common.io.Resources;
+import org.mockito.Matchers;
+import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -116,6 +123,18 @@ public class PlanningBase extends ExecTest {
when(context.getAllocator()).thenReturn(allocator);
when(context.getExecutionControls()).thenReturn(executionControls);
when(context.getLpPersistence()).thenReturn(logicalPlanPersistence);
+ // mocks for org.apache.drill.TestTpchPlanning#tpch06 test.
+ // With changes for decimal types, subtract udf for decimals is used.
+ when(context.getManagedBuffer()).thenReturn(allocator.buffer(4));
+ when(context.getConstantValueHolder(eq("0.03"),
+ eq(TypeProtos.MinorType.VARDECIMAL),
+ Matchers.<Function<DrillBuf, ValueHolder>>any()))
+ .thenReturn(ValueHolderHelper.getVarDecimalHolder(allocator.buffer(4), "0.03"));
+ when(context.getConstantValueHolder(eq("0.01"),
+ eq(TypeProtos.MinorType.VARDECIMAL),
+ Matchers.<Function<DrillBuf, ValueHolder>>any()))
+ .thenReturn(ValueHolderHelper.getVarDecimalHolder(allocator.buffer(4), "0.01"));
+
for (final String sql : sqlStrings) {
if (sql.trim().isEmpty()) {
diff --git a/exec/java-exec/src/test/java/org/apache/drill/TestDisabledFunctionality.java b/exec/java-exec/src/test/java/org/apache/drill/TestDisabledFunctionality.java
index bfbc17410..781fce31b 100644
--- a/exec/java-exec/src/test/java/org/apache/drill/TestDisabledFunctionality.java
+++ b/exec/java-exec/src/test/java/org/apache/drill/TestDisabledFunctionality.java
@@ -18,6 +18,7 @@
package org.apache.drill;
import org.apache.drill.categories.UnlikelyTest;
import org.apache.drill.common.exceptions.UserException;
+import org.apache.drill.exec.planner.physical.PlannerSettings;
import org.apache.drill.exec.work.ExecErrorConstants;
import org.apache.drill.exec.work.foreman.SqlUnsupportedException;
import org.apache.drill.exec.work.foreman.UnsupportedDataTypeException;
@@ -307,14 +308,24 @@ public class TestDisabledFunctionality extends BaseTestQuery {
@Test // DRILL-2848
public void testDisableDecimalCasts() throws Exception {
- final String query = "select cast('1.2' as decimal(9, 2)) from cp.`employee.json` limit 1";
- errorMsgTestHelper(query, ExecErrorConstants.DECIMAL_DISABLE_ERR_MSG);
+ try {
+ alterSession(PlannerSettings.ENABLE_DECIMAL_DATA_TYPE_KEY, false);
+ final String query = "select cast('1.2' as decimal(9, 2)) from cp.`employee.json` limit 1";
+ errorMsgTestHelper(query, ExecErrorConstants.DECIMAL_DISABLE_ERR_MSG);
+ } finally {
+ resetSessionOption(PlannerSettings.ENABLE_DECIMAL_DATA_TYPE_KEY);
+ }
}
@Test // DRILL-2848
public void testDisableDecimalFromParquet() throws Exception {
- final String query = "select * from cp.`parquet/decimal_dictionary.parquet`";
- errorMsgTestHelper(query, ExecErrorConstants.DECIMAL_DISABLE_ERR_MSG);
+ try {
+ alterSession(PlannerSettings.ENABLE_DECIMAL_DATA_TYPE_KEY, false);
+ final String query = "select * from cp.`parquet/decimal_dictionary.parquet`";
+ errorMsgTestHelper(query, ExecErrorConstants.DECIMAL_DISABLE_ERR_MSG);
+ } finally {
+ resetSessionOption(PlannerSettings.ENABLE_DECIMAL_DATA_TYPE_KEY);
+ }
}
@Test (expected = UnsupportedFunctionException.class) //DRILL-3802
diff --git a/exec/java-exec/src/test/java/org/apache/drill/TestFrameworkTest.java b/exec/java-exec/src/test/java/org/apache/drill/TestFrameworkTest.java
index 419e639e4..5c36ca8db 100644
--- a/exec/java-exec/src/test/java/org/apache/drill/TestFrameworkTest.java
+++ b/exec/java-exec/src/test/java/org/apache/drill/TestFrameworkTest.java
@@ -144,7 +144,7 @@ public class TestFrameworkTest extends BaseTestQuery {
.sqlQuery("select cast(dec_col as decimal(38,2)) dec_col from cp.`testframework/decimal_test.json`")
.unOrdered()
.csvBaselineFile("testframework/decimal_test.tsv")
- .baselineTypes(Types.withScaleAndPrecision(TypeProtos.MinorType.DECIMAL38SPARSE, TypeProtos.DataMode.REQUIRED, 2, 38))
+ .baselineTypes(Types.withScaleAndPrecision(TypeProtos.MinorType.VARDECIMAL, TypeProtos.DataMode.REQUIRED, 2, 38))
.baselineColumns("dec_col")
.build().run();
diff --git a/exec/java-exec/src/test/java/org/apache/drill/TestFunctionsQuery.java b/exec/java-exec/src/test/java/org/apache/drill/TestFunctionsQuery.java
index 5ae0c380d..9986579c1 100644
--- a/exec/java-exec/src/test/java/org/apache/drill/TestFunctionsQuery.java
+++ b/exec/java-exec/src/test/java/org/apache/drill/TestFunctionsQuery.java
@@ -42,8 +42,8 @@ public class TestFunctionsQuery extends BaseTestQuery {
}
@AfterClass
- public static void disableDecimalDataType() throws Exception {
- test(String.format("alter session set `%s` = false", PlannerSettings.ENABLE_DECIMAL_DATA_TYPE_KEY));
+ public static void disableDecimalDataType() {
+ resetSessionOption(PlannerSettings.ENABLE_DECIMAL_DATA_TYPE_KEY);
}
@Test
@@ -402,7 +402,7 @@ public class TestFunctionsQuery extends BaseTestQuery {
.sqlQuery(query)
.unOrdered()
.baselineColumns("DEC38_1", "DEC38_2", "DEC38_3")
- .baselineValues(new BigDecimal("1000000000000000000000000000.00000"), new BigDecimal("1000000000000000000"), new BigDecimal("1000000000.000000000000000000"))
+ .baselineValues(new BigDecimal("1000000000000000000000000000.00000"), new BigDecimal("1.0000000000000000E+18"), new BigDecimal("1000000000.000000000000000000"))
.go();
}
@@ -429,7 +429,7 @@ public class TestFunctionsQuery extends BaseTestQuery {
String query = "select cast((cast('12345.6789' as decimal(18, 4))) as decimal(9, 4)) as DEC18_DEC9_1, " +
"cast((cast('12345.6789' as decimal(18, 4))) as decimal(9, 2)) as DEC18_DEC9_2, " +
"cast((cast('-12345.6789' as decimal(18, 4))) as decimal(9, 0)) as DEC18_DEC9_3, " +
- "cast((cast('999999999.6789' as decimal(38, 4))) as decimal(9, 0)) as DEC38_DEC19_1, " +
+ "cast((cast('99999999.6789' as decimal(38, 4))) as decimal(9, 0)) as DEC38_DEC19_1, " +
"cast((cast('-999999999999999.6789' as decimal(38, 4))) as decimal(18, 2)) as DEC38_DEC18_1, " +
"cast((cast('-999999999999999.6789' as decimal(38, 4))) as decimal(18, 0)) as DEC38_DEC18_2, " +
"cast((cast('100000000999999999.6789' as decimal(38, 4))) as decimal(28, 0)) as DEC38_DEC28_1 " +
@@ -438,24 +438,25 @@ public class TestFunctionsQuery extends BaseTestQuery {
.sqlQuery(query)
.unOrdered()
.baselineColumns("DEC18_DEC9_1", "DEC18_DEC9_2", "DEC18_DEC9_3", "DEC38_DEC19_1", "DEC38_DEC18_1", "DEC38_DEC18_2", "DEC38_DEC28_1")
- .baselineValues(new BigDecimal("12345.6789"), new BigDecimal("12345.68"), new BigDecimal("-12346"), new BigDecimal("1000000000"),
+ .baselineValues(new BigDecimal("12345.6789"), new BigDecimal("12345.68"), new BigDecimal("-12346"), new BigDecimal("100000000"),
new BigDecimal("-999999999999999.68"), new BigDecimal("-1000000000000000"), new BigDecimal("100000001000000000"))
.go();
}
@Test
public void testTruncateWithParamFunction() throws Exception {
- String query = "SELECT " +
- "trunc(1234.4567, 2) as T_1, " +
- "trunc(-1234.4567, 2) as T_2, " +
- "trunc(1234.4567, -2) as T_3, " +
- "trunc(-1234.4567, -2) as T_4, " +
- "trunc(1234, 4) as T_5, " +
- "trunc(-1234, 4) as T_6, " +
- "trunc(1234, -4) as T_7, " +
- "trunc(-1234, -4) as T_8, " +
- "trunc(8124674407369523212, 0) as T_9, " +
- "trunc(81246744073695.395, 1) as T_10 " +
+ String query =
+ "SELECT\n" +
+ "trunc(cast('1234.4567' as double), 2) as T_1,\n" +
+ "trunc(cast('-1234.4567' as double), 2) as T_2,\n" +
+ "trunc(cast('1234.4567' as double), -2) as T_3,\n" +
+ "trunc(cast('-1234.4567' as double), -2) as T_4,\n" +
+ "trunc(cast('1234' as double), 4) as T_5,\n" +
+ "trunc(cast('-1234' as double), 4) as T_6,\n" +
+ "trunc(cast('1234' as double), -4) as T_7,\n" +
+ "trunc(cast('-1234' as double), -4) as T_8,\n" +
+ "trunc(cast('8124674407369523212' as double), 0) as T_9,\n" +
+ "trunc(cast('81246744073695.395' as double), 1) as T_10\n" +
"FROM cp.`tpch/region.parquet` limit 1";
testBuilder()
@@ -469,17 +470,18 @@ public class TestFunctionsQuery extends BaseTestQuery {
@Test
public void testRoundWithParamFunction() throws Exception {
- String query = "SELECT " +
- "round(1234.4567, 2) as T_1, " +
- "round(-1234.4567, 2) as T_2, " +
- "round(1234.4567, -2) as T_3, " +
- "round(-1234.4567, -2) as T_4, " +
- "round(1234, 4) as T_5, " +
- "round(-1234, 4) as T_6, " +
- "round(1234, -4) as T_7, " +
- "round(-1234, -4) as T_8, " +
- "round(8124674407369523212, -4) as T_9, " +
- "round(81246744073695.395, 1) as T_10 " +
+ String query =
+ "SELECT\n" +
+ "round(cast('1234.4567' as double), 2) as T_1,\n" +
+ "round(cast('-1234.4567' as double), 2) as T_2,\n" +
+ "round(cast('1234.4567' as double), -2) as T_3,\n" +
+ "round(cast('-1234.4567' as double), -2) as T_4,\n" +
+ "round(cast('1234' as double), 4) as T_5,\n" +
+ "round(cast('-1234' as double), 4) as T_6,\n" +
+ "round(cast('1234' as double), -4) as T_7,\n" +
+ "round(cast('-1234' as double), -4) as T_8,\n" +
+ "round(cast('8124674407369523212' as double), -4) as T_9,\n" +
+ "round(cast('81246744073695.395' as double), 1) as T_10\n" +
"FROM cp.`tpch/region.parquet` limit 1";
testBuilder()
@@ -494,19 +496,20 @@ public class TestFunctionsQuery extends BaseTestQuery {
@Test
public void testRoundWithOneParam() throws Exception {
- String query = "select " +
- "round(8124674407369523212) round_bigint," +
- "round(9999999) round_int, " +
- "round(cast('23.45' as float)) round_float_1, " +
- "round(cast('23.55' as float)) round_float_2, " +
- "round(8124674407369.2345) round_double_1, " +
- "round(8124674407369.589) round_double_2 " +
- " from cp.`tpch/region.parquet` limit 1";
+ String query =
+ "select\n" +
+ "round(8124674407369523212) round_bigint,\n" +
+ "round(9999999) round_int,\n" +
+ "round(cast('23.45' as float)) round_float_1,\n" +
+ "round(cast('23.55' as float)) round_float_2,\n" +
+ "round(cast('8124674407369.2345' as double)) round_double_1,\n" +
+ "round(cast('8124674407369.589' as double)) round_double_2\n" +
+ "from cp.`tpch/region.parquet` limit 1";
testBuilder()
.sqlQuery(query)
.unOrdered()
.baselineColumns("round_bigint", "round_int", "round_float_1", "round_float_2", "round_double_1", "round_double_2")
- .baselineValues(8124674407369523212l, 9999999, 23.0f, 24.0f, 8124674407369.0d, 8124674407370.0d)
+ .baselineValues(8124674407369523212L, 9999999, 23.0f, 24.0f, 8124674407369.0d, 8124674407370.0d)
.go();
}
@@ -729,14 +732,14 @@ public class TestFunctionsQuery extends BaseTestQuery {
@Test
public void testNegative() throws Exception {
- String query = "select negative(cast(2 as bigint)) as NEG " +
+ String query = "select negative(cast(2 as bigint)) as NEG\n" +
"from cp.`employee.json` where employee_id = 1";
testBuilder()
.sqlQuery(query)
.unOrdered()
.baselineColumns("NEG")
- .baselineValues(-2l)
+ .baselineValues(-2L)
.go();
}
@@ -755,11 +758,11 @@ public class TestFunctionsQuery extends BaseTestQuery {
@Test
public void testToTimeStamp() throws Exception {
- String query = "select to_timestamp(cast('800120400.12312' as decimal(38, 5))) as DEC38_TS, to_timestamp(200120400) as INT_TS " +
+ String query = "select to_timestamp(cast('800120400.12312' as decimal(38, 5))) as DEC38_TS, to_timestamp(200120400) as INT_TS\n" +
"from cp.`employee.json` where employee_id < 2";
- DateTime result1 = new DateTime(800120400123l);
- DateTime result2 = new DateTime(200120400000l);
+ DateTime result1 = new DateTime(800120400123L);
+ DateTime result2 = new DateTime(200120400000L);
testBuilder()
.sqlQuery(query)
@@ -883,7 +886,7 @@ public class TestFunctionsQuery extends BaseTestQuery {
.sqlQuery("select `integer` i, `float` f from cp.`jsoninput/input1.json` where `float` = '1.2'")
.unOrdered()
.baselineColumns("i", "f")
- .baselineValues(2001l, 1.2d)
+ .baselineValues(2001L, 1.2d)
.go();
}
diff --git a/exec/java-exec/src/test/java/org/apache/drill/exec/TestEmptyInputSql.java b/exec/java-exec/src/test/java/org/apache/drill/exec/TestEmptyInputSql.java
index e79d75de4..84da7a6e8 100644
--- a/exec/java-exec/src/test/java/org/apache/drill/exec/TestEmptyInputSql.java
+++ b/exec/java-exec/src/test/java/org/apache/drill/exec/TestEmptyInputSql.java
@@ -19,6 +19,7 @@ package org.apache.drill.exec;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.tuple.Pair;
+import org.apache.drill.exec.planner.physical.PlannerSettings;
import org.apache.drill.test.BaseTestQuery;
import org.apache.drill.test.rowSet.schema.SchemaBuilder;
import org.apache.drill.categories.UnlikelyTest;
@@ -128,26 +129,53 @@ public class TestEmptyInputSql extends BaseTestQuery {
/**
* Test with query against an empty file. Select clause has three expressions.
- * 1.0 + 100.0 as constant expression, is resolved to required FLOAT8
+ * 1.0 + 100.0 as constant expression, is resolved to required FLOAT8/VARDECIMAL
* cast(100 as varchar(100) is resolved to required varchar(100)
* cast(columns as varchar(100)) is resolved to nullable varchar(100).
*/
@Test
public void testQueryConstExprEmptyJson() throws Exception {
- final BatchSchema expectedSchema = new SchemaBuilder()
- .add("key", TypeProtos.MinorType.FLOAT8)
- .add("name", TypeProtos.MinorType.VARCHAR, 100)
- .addNullable("name2", TypeProtos.MinorType.VARCHAR, 100)
- .build();
-
- testBuilder()
- .sqlQuery("select 1.0 + 100.0 as key, "
- + " cast(100 as varchar(100)) as name, "
- + " cast(columns as varchar(100)) as name2 "
- + " from cp.`%s` ", SINGLE_EMPTY_JSON)
- .schemaBaseLine(expectedSchema)
- .build()
- .run();
+ try {
+ alterSession(PlannerSettings.ENABLE_DECIMAL_DATA_TYPE_KEY, false);
+ BatchSchema expectedSchema = new SchemaBuilder()
+ .add("key", TypeProtos.MinorType.FLOAT8)
+ .add("name", TypeProtos.MinorType.VARCHAR, 100)
+ .addNullable("name2", TypeProtos.MinorType.VARCHAR, 100)
+ .build();
+
+ testBuilder()
+ .sqlQuery("select 1.0 + 100.0 as key, "
+ + " cast(100 as varchar(100)) as name, "
+ + " cast(columns as varchar(100)) as name2 "
+ + " from cp.`%s` ", SINGLE_EMPTY_JSON)
+ .schemaBaseLine(expectedSchema)
+ .build()
+ .run();
+
+ alterSession(PlannerSettings.ENABLE_DECIMAL_DATA_TYPE_KEY, true);
+ expectedSchema = new SchemaBuilder()
+ .add("key",
+ TypeProtos.MajorType.newBuilder()
+ .setMinorType(TypeProtos.MinorType.VARDECIMAL)
+ .setMode(TypeProtos.DataMode.REQUIRED)
+ .setPrecision(5)
+ .setScale(1)
+ .build())
+ .add("name", TypeProtos.MinorType.VARCHAR, 100)
+ .addNullable("name2", TypeProtos.MinorType.VARCHAR, 100)
+ .build();
+
+ testBuilder()
+ .sqlQuery("select 1.0 + 100.0 as key, "
+ + " cast(100 as varchar(100)) as name, "
+ + " cast(columns as varchar(100)) as name2 "
+ + " from cp.`%s` ", SINGLE_EMPTY_JSON)
+ .schemaBaseLine(expectedSchema)
+ .build()
+ .run();
+ } finally {
+ resetSessionOption(PlannerSettings.ENABLE_DECIMAL_DATA_TYPE_KEY);
+ }
}
/**
diff --git a/exec/java-exec/src/test/java/org/apache/drill/exec/TestWindowFunctions.java b/exec/java-exec/src/test/java/org/apache/drill/exec/TestWindowFunctions.java
index e2aec04ac..fc2f63957 100644
--- a/exec/java-exec/src/test/java/org/apache/drill/exec/TestWindowFunctions.java
+++ b/exec/java-exec/src/test/java/org/apache/drill/exec/TestWindowFunctions.java
@@ -575,13 +575,15 @@ public class TestWindowFunctions extends BaseTestQuery {
.sqlQuery(query)
.ordered()
.baselineColumns("cnt")
- .baselineValues(26l)
+ .baselineValues(26L)
.build().run();
}
@Test // DRILL-3292
public void testWindowConstants() throws Exception {
- String query = "select rank() over w fn, sum(2) over w sumINTEGER, sum(employee_id) over w sumEmpId, sum(0.5) over w sumFLOAT \n" +
+ String query =
+ "select rank() over w fn, sum(2) over w sumINTEGER, sum(employee_id) over w sumEmpId,\n" +
+ "sum(cast(0.5 as double)) over w sumFLOAT \n" +
"from cp.`employee.json` \n" +
"where position_id = 2 \n" +
"window w as(partition by position_id order by employee_id)";
@@ -596,12 +598,12 @@ public class TestWindowFunctions extends BaseTestQuery {
.sqlQuery(query)
.ordered()
.baselineColumns("fn", "sumINTEGER", "sumEmpId", "sumFLOAT")
- .baselineValues(1l, 2l, 2l, 0.5)
- .baselineValues(2l, 4l, 6l, 1.0)
- .baselineValues(3l, 6l, 11l, 1.5)
- .baselineValues(4l, 8l, 31l, 2.0)
- .baselineValues(5l, 10l, 52l, 2.5)
- .baselineValues(6l, 12l, 74l, 3.0)
+ .baselineValues(1L, 2L, 2L, 0.5)
+ .baselineValues(2L, 4L, 6L, 1.0)
+ .baselineValues(3L, 6L, 11L, 1.5)
+ .baselineValues(4L, 8L, 31L, 2.0)
+ .baselineValues(5L, 10L, 52L, 2.5)
+ .baselineValues(6L, 12L, 74L, 3.0)
.build()
.run();
}
diff --git a/exec/java-exec/src/test/java/org/apache/drill/exec/cache/TestBatchSerialization.java b/exec/java-exec/src/test/java/org/apache/drill/exec/cache/TestBatchSerialization.java
index 684c79a3b..6a4ec52db 100644
--- a/exec/java-exec/src/test/java/org/apache/drill/exec/cache/TestBatchSerialization.java
+++ b/exec/java-exec/src/test/java/org/apache/drill/exec/cache/TestBatchSerialization.java
@@ -169,6 +169,7 @@ public class TestBatchSerialization extends DrillTest {
testType(MinorType.DECIMAL18);
testType(MinorType.DECIMAL28SPARSE);
testType(MinorType.DECIMAL38SPARSE);
+ testType(MinorType.VARDECIMAL);
// testType(MinorType.DECIMAL28DENSE); No writer
// testType(MinorType.DECIMAL38DENSE); No writer
testType(MinorType.DATE);
diff --git a/exec/java-exec/src/test/java/org/apache/drill/exec/fn/impl/TestAggregateFunctions.java b/exec/java-exec/src/test/java/org/apache/drill/exec/fn/impl/TestAggregateFunctions.java
index 120f1e63d..0a5b7cd6e 100644
--- a/exec/java-exec/src/test/java/org/apache/drill/exec/fn/impl/TestAggregateFunctions.java
+++ b/exec/java-exec/src/test/java/org/apache/drill/exec/fn/impl/TestAggregateFunctions.java
@@ -17,10 +17,14 @@
*/
package org.apache.drill.exec.fn.impl;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.drill.common.exceptions.UserRemoteException;
+import org.apache.drill.common.types.Types;
+import org.apache.drill.exec.ExecConstants;
+import org.apache.drill.exec.planner.physical.PlannerSettings;
import org.apache.drill.test.BaseTestQuery;
import org.apache.drill.categories.OperatorTest;
import org.apache.drill.PlanTestBase;
@@ -39,6 +43,7 @@ import org.junit.experimental.categories.Category;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
+import java.math.BigDecimal;
import java.nio.file.Paths;
import java.util.List;
import java.util.Map;
@@ -65,8 +70,8 @@ public class TestAggregateFunctions extends BaseTestQuery {
.sqlQuery("select count(t.x.y) as cnt1, count(`integer`) as cnt2 from cp.`jsoninput/input2.json` t")
.ordered()
.baselineColumns("cnt1", "cnt2")
- .baselineValues(3l, 4l)
- .build().run();
+ .baselineValues(3L, 4L)
+ .go();
}
@Test
@@ -75,18 +80,23 @@ public class TestAggregateFunctions extends BaseTestQuery {
.sqlQuery("select count(distinct `bool_val`) as cnt from `sys`.`options`")
.ordered()
.baselineColumns("cnt")
- .baselineValues(2l)
- .build().run();
+ .baselineValues(2L)
+ .go();
}
@Test
public void testMaxWithZeroInput() throws Exception {
- testBuilder()
- .sqlQuery("select max(employee_id * 0.0) as max_val from cp.`employee.json`")
- .unOrdered()
- .baselineColumns("max_val")
- .baselineValues(0.0d)
- .go();
+ try {
+ alterSession(PlannerSettings.ENABLE_DECIMAL_DATA_TYPE_KEY, false);
+ testBuilder()
+ .sqlQuery("select max(employee_id * 0.0) as max_val from cp.`employee.json`")
+ .unOrdered()
+ .baselineColumns("max_val")
+ .baselineValues(0.0)
+ .go();
+ } finally {
+ resetSessionOption(PlannerSettings.ENABLE_DECIMAL_DATA_TYPE_KEY);
+ }
}
@Ignore
@@ -142,8 +152,8 @@ public class TestAggregateFunctions extends BaseTestQuery {
.ordered()
.optionSettingQueriesForTestQuery("alter system set `planner.slice_target` = 1000")
.baselineColumns("cnt")
- .baselineValues(100l)
- .build().run();
+ .baselineValues(100L)
+ .go();
}
@Test // DRILL-2168
@@ -209,14 +219,14 @@ public class TestAggregateFunctions extends BaseTestQuery {
.sqlQuery("select count(a) col1, avg(b) col2 from cp.`jsoninput/nullable3.json`")
.unOrdered()
.baselineColumns("col1", "col2")
- .baselineValues(2l, 3.0d)
+ .baselineValues(2L, 3.0d)
.go();
testBuilder()
.sqlQuery("select count(a) col1, avg(a) col2 from cp.`jsoninput/nullable3.json`")
.unOrdered()
.baselineColumns("col1", "col2")
- .baselineValues(2l, 1.0d)
+ .baselineValues(2L, 1.0d)
.go();
}
@@ -241,6 +251,211 @@ public class TestAggregateFunctions extends BaseTestQuery {
}
@Test
+ public void testVarSampDecimal() throws Exception {
+ try {
+ alterSession(PlannerSettings.ENABLE_DECIMAL_DATA_TYPE_KEY, true);
+ testBuilder()
+ .sqlQuery("select var_samp(cast(employee_id as decimal(28, 20))) as dec20,\n" +
+ "var_samp(cast(employee_id as decimal(28, 0))) as dec6,\n" +
+ "var_samp(cast(employee_id as integer)) as d\n" +
+ "from cp.`employee.json`")
+ .unOrdered()
+ .baselineColumns("dec20", "dec6", "d")
+ .baselineValues(new BigDecimal("111266.99999699895713760532"),
+ new BigDecimal("111266.999997"),
+ 111266.99999699896)
+ .go();
+ } finally {
+ resetSessionOption(PlannerSettings.ENABLE_DECIMAL_DATA_TYPE_KEY);
+ }
+ }
+
+ @Test
+ public void testVarPopDecimal() throws Exception {
+ try {
+ alterSession(PlannerSettings.ENABLE_DECIMAL_DATA_TYPE_KEY, true);
+ testBuilder()
+ .sqlQuery("select var_pop(cast(employee_id as decimal(28, 20))) as dec20,\n" +
+ "var_pop(cast(employee_id as decimal(28, 0))) as dec6,\n" +
+ "var_pop(cast(employee_id as integer)) as d\n" +
+ "from cp.`employee.json`")
+ .unOrdered()
+ .baselineColumns("dec20", "dec6", "d")
+ .baselineValues(new BigDecimal("111170.66493206649050804895"),
+ new BigDecimal("111170.664932"),
+ 111170.66493206649)
+ .go();
+ } finally {
+ resetSessionOption(PlannerSettings.ENABLE_DECIMAL_DATA_TYPE_KEY);
+ }
+ }
+
+ @Test
+ public void testStddevSampDecimal() throws Exception {
+ try {
+ alterSession(PlannerSettings.ENABLE_DECIMAL_DATA_TYPE_KEY, true);
+ testBuilder()
+ .sqlQuery("select stddev_samp(cast(employee_id as decimal(28, 20))) as dec20,\n" +
+ "stddev_samp(cast(employee_id as decimal(28, 0))) as dec6,\n" +
+ "stddev_samp(cast(employee_id as integer)) as d\n" +
+ "from cp.`employee.json`")
+ .unOrdered()
+ .baselineColumns("dec20", "dec6", "d")
+ .baselineValues(new BigDecimal("333.56708470261114349632"),
+ new BigDecimal("333.567085"),
+ 333.56708470261117) // last number differs because of double precision.
+ // Was taken sqrt of 111266.99999699895713760531784795216338 and decimal result is correct
+ .go();
+ } finally {
+ resetSessionOption(PlannerSettings.ENABLE_DECIMAL_DATA_TYPE_KEY);
+ }
+ }
+
+ @Test
+ public void testStddevPopDecimal() throws Exception {
+ try {
+ alterSession(PlannerSettings.ENABLE_DECIMAL_DATA_TYPE_KEY, true);
+ testBuilder()
+ .sqlQuery("select stddev_pop(cast(employee_id as decimal(28, 20))) as dec20,\n" +
+ "stddev_pop(cast(employee_id as decimal(28, 0))) as dec6,\n" +
+ "stddev_pop(cast(employee_id as integer)) as d\n" +
+ "from cp.`employee.json`")
+ .unOrdered()
+ .baselineColumns("dec20", "dec6", "d")
+ .baselineValues(new BigDecimal("333.42265209800381903633"),
+ new BigDecimal("333.422652"),
+ 333.4226520980038)
+ .go();
+ } finally {
+ resetSessionOption(PlannerSettings.ENABLE_DECIMAL_DATA_TYPE_KEY);
+ }
+ }
+
+ @Test
+ public void testSumDecimal() throws Exception {
+ try {
+ alterSession(PlannerSettings.ENABLE_DECIMAL_DATA_TYPE_KEY, true);
+ testBuilder()
+ .sqlQuery("select sum(cast(employee_id as decimal(9, 0))) as colDecS0,\n" +
+ "sum(cast(employee_id as decimal(12, 3))) as colDecS3,\n" +
+ "sum(cast(employee_id as integer)) as colInt\n" +
+ "from cp.`employee.json`")
+ .unOrdered()
+ .baselineColumns("colDecS0", "colDecS3", "colInt")
+ .baselineValues(BigDecimal.valueOf(668743), new BigDecimal("668743.000"), 668743L)
+ .go();
+ } finally {
+ resetSessionOption(PlannerSettings.ENABLE_DECIMAL_DATA_TYPE_KEY);
+ }
+ }
+
+ @Test
+ public void testAvgDecimal() throws Exception {
+ try {
+ alterSession(PlannerSettings.ENABLE_DECIMAL_DATA_TYPE_KEY, true);
+ testBuilder()
+ .sqlQuery("select avg(cast(employee_id as decimal(28, 20))) as colDec20,\n" +
+ "avg(cast(employee_id as decimal(28, 0))) as colDec6,\n" +
+ "avg(cast(employee_id as integer)) as colInt\n" +
+ "from cp.`employee.json`")
+ .unOrdered()
+ .baselineColumns("colDec20", "colDec6", "colInt")
+ .baselineValues(new BigDecimal("578.99826839826839826840"),
+ new BigDecimal("578.998268"),
+ 578.9982683982684)
+ .go();
+ } finally {
+ resetSessionOption(PlannerSettings.ENABLE_DECIMAL_DATA_TYPE_KEY);
+ }
+ }
+
+ @Test
+ public void testSumAvgDecimalLimit0() throws Exception {
+ final List<Pair<SchemaPath, TypeProtos.MajorType>> expectedSchema =
+ ImmutableList.of(
+ Pair.of(SchemaPath.getSimplePath("sum_col"),
+ Types.withScaleAndPrecision(TypeProtos.MinorType.VARDECIMAL, TypeProtos.DataMode.OPTIONAL, 3, 38)),
+ Pair.of(SchemaPath.getSimplePath("avg_col"),
+ Types.withScaleAndPrecision(TypeProtos.MinorType.VARDECIMAL, TypeProtos.DataMode.OPTIONAL, 6, 38)),
+ Pair.of(SchemaPath.getSimplePath("stddev_pop_col"),
+ Types.withScaleAndPrecision(TypeProtos.MinorType.VARDECIMAL, TypeProtos.DataMode.OPTIONAL, 6, 38)),
+ Pair.of(SchemaPath.getSimplePath("stddev_samp_col"),
+ Types.withScaleAndPrecision(TypeProtos.MinorType.VARDECIMAL, TypeProtos.DataMode.OPTIONAL, 6, 38)),
+ Pair.of(SchemaPath.getSimplePath("var_pop_col"),
+ Types.withScaleAndPrecision(TypeProtos.MinorType.VARDECIMAL, TypeProtos.DataMode.OPTIONAL, 6, 38)),
+ Pair.of(SchemaPath.getSimplePath("var_samp_col"),
+ Types.withScaleAndPrecision(TypeProtos.MinorType.VARDECIMAL, TypeProtos.DataMode.OPTIONAL, 6, 38)),
+ Pair.of(SchemaPath.getSimplePath("max_col"),
+ Types.withScaleAndPrecision(TypeProtos.MinorType.VARDECIMAL, TypeProtos.DataMode.OPTIONAL, 3, 9)),
+ Pair.of(SchemaPath.getSimplePath("min_col"),
+ Types.withScaleAndPrecision(TypeProtos.MinorType.VARDECIMAL, TypeProtos.DataMode.OPTIONAL, 3, 9)));
+
+ String query =
+ "select\n" +
+ "sum(cast(employee_id as decimal(9, 3))) sum_col,\n" +
+ "avg(cast(employee_id as decimal(9, 3))) avg_col,\n" +
+ "stddev_pop(cast(employee_id as decimal(9, 3))) stddev_pop_col,\n" +
+ "stddev_samp(cast(employee_id as decimal(9, 3))) stddev_samp_col,\n" +
+ "var_pop(cast(employee_id as decimal(9, 3))) var_pop_col,\n" +
+ "var_samp(cast(employee_id as decimal(9, 3))) var_samp_col,\n" +
+ "max(cast(employee_id as decimal(9, 3))) max_col,\n" +
+ "min(cast(employee_id as decimal(9, 3))) min_col\n" +
+ "from cp.`employee.json` limit 0";
+ try {
+ alterSession(PlannerSettings.ENABLE_DECIMAL_DATA_TYPE_KEY, true);
+ alterSession(ExecConstants.EARLY_LIMIT0_OPT_KEY, true);
+
+ testBuilder()
+ .sqlQuery(query)
+ .schemaBaseLine(expectedSchema)
+ .go();
+
+ alterSession(ExecConstants.EARLY_LIMIT0_OPT_KEY, false);
+
+ testBuilder()
+ .sqlQuery(query)
+ .schemaBaseLine(expectedSchema)
+ .go();
+
+ } finally {
+ resetSessionOption(PlannerSettings.ENABLE_DECIMAL_DATA_TYPE_KEY);
+ resetSessionOption(ExecConstants.EARLY_LIMIT0_OPT_KEY);
+ }
+ }
+
+ @Test // DRILL-6221
+ public void testAggGroupByWithNullDecimal() throws Exception {
+ String fileName = "table.json";
+ try (BufferedWriter writer = new BufferedWriter(new FileWriter(new File(dirTestWatcher.getRootDir(), fileName)))) {
+ writer.write("{\"a\": 1, \"b\": 0}");
+ writer.write("{\"b\": 2}");
+ }
+
+ try {
+ alterSession(PlannerSettings.ENABLE_DECIMAL_DATA_TYPE_KEY, true);
+ testBuilder()
+ .sqlQuery("select sum(cast(a as decimal(9,0))) as s,\n" +
+ "avg(cast(a as decimal(9,0))) as a,\n" +
+ "var_samp(cast(a as decimal(9,0))) as varSamp,\n" +
+ "var_pop(cast(a as decimal(9,0))) as varPop,\n" +
+ "stddev_pop(cast(a as decimal(9,0))) as stddevPop,\n" +
+ "stddev_samp(cast(a as decimal(9,0))) as stddevSamp," +
+ "max(cast(a as decimal(9,0))) as mx," +
+ "min(cast(a as decimal(9,0))) as mn from dfs.`%s` t group by a", fileName)
+ .unOrdered()
+ .baselineColumns("s", "a", "varSamp", "varPop", "stddevPop", "stddevSamp", "mx", "mn")
+ .baselineValues(BigDecimal.valueOf(1), new BigDecimal("1.000000"), new BigDecimal("0.000000"),
+ new BigDecimal("0.000000"), new BigDecimal("0.000000"), new BigDecimal("0.000000"),
+ BigDecimal.valueOf(1), BigDecimal.valueOf(1))
+ .baselineValues(null, null, null, null, null, null, null, null)
+ .go();
+
+ } finally {
+ resetSessionOption(PlannerSettings.ENABLE_DECIMAL_DATA_TYPE_KEY);
+ }
+ }
+
+ @Test
// test aggregates when input is empty and data type is optional
public void countEmptyNullableInput() throws Exception {
String query = "select " +
@@ -251,7 +466,7 @@ public class TestAggregateFunctions extends BaseTestQuery {
.sqlQuery(query)
.unOrdered()
.baselineColumns("col1", "col2", "col3")
- .baselineValues(0l, null, null)
+ .baselineValues(0L, null, null)
.go();
}
diff --git a/exec/java-exec/src/test/java/org/apache/drill/exec/fn/impl/TestCastFunctions.java b/exec/java-exec/src/test/java/org/apache/drill/exec/fn/impl/TestCastFunctions.java
index 14a49b520..4eb3917f9 100644
--- a/exec/java-exec/src/test/java/org/apache/drill/exec/fn/impl/TestCastFunctions.java
+++ b/exec/java-exec/src/test/java/org/apache/drill/exec/fn/impl/TestCastFunctions.java
@@ -20,6 +20,7 @@ package org.apache.drill.exec.fn.impl;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import mockit.integration.junit4.JMockit;
+import org.apache.drill.exec.planner.physical.PlannerSettings;
import org.apache.drill.test.BaseTestQuery;
import org.apache.drill.categories.SqlFunctionTest;
import org.apache.drill.categories.UnlikelyTest;
@@ -28,6 +29,8 @@ import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.runner.RunWith;
import java.math.BigDecimal;
+import java.math.MathContext;
+import java.math.RoundingMode;
import java.util.List;
import java.util.Map;
@@ -41,8 +44,8 @@ public class TestCastFunctions extends BaseTestQuery {
.sqlQuery("select count(*) as cnt from cp.`employee.json` where (cast(convert_to(birth_date, 'utf8') as date)) = date '1961-08-26'")
.unOrdered()
.baselineColumns("cnt")
- .baselineValues(1l)
- .build().run();
+ .baselineValues(1L)
+ .go();
}
@Test // DRILL-2827
@@ -66,9 +69,8 @@ public class TestCastFunctions extends BaseTestQuery {
.sqlQuery(query)
.ordered()
.baselineColumns("col1", "col2")
- .baselineValues(1155l, 1155l)
- .build()
- .run();
+ .baselineValues(1155L, 1155L)
+ .go();
}
@Test // DRILL-3769
@@ -116,8 +118,7 @@ public class TestCastFunctions extends BaseTestQuery {
.unOrdered()
.baselineColumns("col1")
.baselineValues(values.get(value))
- .build()
- .run();
+ .go();
} finally {
test("drop table if exists dfs.tmp.table_with_float");
}
@@ -148,8 +149,7 @@ public class TestCastFunctions extends BaseTestQuery {
.unOrdered()
.baselineColumns("col1", "col2")
.baselineValues((float) value, (double) value)
- .build()
- .run();
+ .go();
} finally {
test("drop table if exists dfs.tmp.table_with_int");
}
@@ -185,8 +185,7 @@ public class TestCastFunctions extends BaseTestQuery {
.unOrdered()
.baselineColumns("col1")
.baselineValues(values.get(value))
- .build()
- .run();
+ .go();
} finally {
test("drop table if exists dfs.tmp.table_with_float");
}
@@ -219,8 +218,7 @@ public class TestCastFunctions extends BaseTestQuery {
.unOrdered()
.baselineColumns("col1", "col2")
.baselineValues((float) value, (double) value)
- .build()
- .run();
+ .go();
} finally {
test("drop table if exists dfs.tmp.table_with_bigint");
}
@@ -256,8 +254,7 @@ public class TestCastFunctions extends BaseTestQuery {
.unOrdered()
.baselineColumns("col1")
.baselineValues(values.get(value))
- .build()
- .run();
+ .go();
} finally {
test("drop table if exists dfs.tmp.table_with_double");
}
@@ -293,8 +290,7 @@ public class TestCastFunctions extends BaseTestQuery {
.unOrdered()
.baselineColumns("col1")
.baselineValues(values.get(value))
- .build()
- .run();
+ .go();
} finally {
test("drop table if exists dfs.tmp.table_with_double");
}
@@ -324,8 +320,7 @@ public class TestCastFunctions extends BaseTestQuery {
.unOrdered()
.baselineColumns("col1", "col2")
.baselineValues((long) value, value)
- .build()
- .run();
+ .go();
} finally {
test("drop table if exists dfs.tmp.table_with_int");
}
@@ -362,8 +357,7 @@ public class TestCastFunctions extends BaseTestQuery {
.unOrdered()
.baselineColumns("col1", "col2")
.baselineValues((double) ((float) (value)), (float) value)
- .build()
- .run();
+ .go();
} finally {
test("drop table if exists dfs.tmp.table_with_float");
}
@@ -383,22 +377,29 @@ public class TestCastFunctions extends BaseTestQuery {
.baselineValues(new BigDecimal(1), new BigDecimal(1), new BigDecimal(1), new BigDecimal(1))
.baselineValues(new BigDecimal(-1), new BigDecimal(-1), new BigDecimal(-1), new BigDecimal(-1))
- .baselineValues(new BigDecimal(Integer.MAX_VALUE),
+ .baselineValues(new BigDecimal(Integer.MAX_VALUE)
+ .round(new MathContext(9, RoundingMode.HALF_UP))
+ .setScale(0, RoundingMode.HALF_UP),
new BigDecimal(Integer.MAX_VALUE),
- new BigDecimal((int) Long.MAX_VALUE),
+ new BigDecimal(Long.MAX_VALUE)
+ .round(new MathContext(9, RoundingMode.HALF_UP))
+ .setScale(0, RoundingMode.HALF_UP),
new BigDecimal(Long.MAX_VALUE))
- .baselineValues(new BigDecimal(Integer.MIN_VALUE),
+ .baselineValues(new BigDecimal(Integer.MIN_VALUE)
+ .round(new MathContext(9, RoundingMode.HALF_UP))
+ .setScale(0, RoundingMode.HALF_UP),
new BigDecimal(Integer.MIN_VALUE),
- new BigDecimal((int) Long.MIN_VALUE),
+ new BigDecimal(Long.MIN_VALUE)
+ .round(new MathContext(9, RoundingMode.HALF_UP))
+ .setScale(0, RoundingMode.HALF_UP),
new BigDecimal(Long.MIN_VALUE))
.baselineValues(new BigDecimal(123456789),
new BigDecimal(123456789),
new BigDecimal(123456789),
new BigDecimal(123456789))
- .build()
- .run();
+ .go();
} finally {
test("drop table if exists dfs.tmp.table_with_int");
test("alter session reset planner.enable_decimal_data_type");
@@ -417,11 +418,24 @@ public class TestCastFunctions extends BaseTestQuery {
.baselineValues(0, 0, 0L, 0L)
.baselineValues(1, 1, 1L, 1L)
.baselineValues(-1, -1, -1L, -1L)
- .baselineValues(Integer.MAX_VALUE, (int) Long.MAX_VALUE, (long) Integer.MAX_VALUE, Long.MAX_VALUE)
- .baselineValues(Integer.MIN_VALUE, (int) Long.MIN_VALUE, (long) Integer.MIN_VALUE, Long.MIN_VALUE)
+ .baselineValues(new BigDecimal(Integer.MAX_VALUE)
+ .round(new MathContext(9, RoundingMode.HALF_UP))
+ .setScale(0, RoundingMode.HALF_UP).intValue(),
+ (int) Long.MAX_VALUE,
+ new BigDecimal(Integer.MAX_VALUE)
+ .round(new MathContext(9, RoundingMode.HALF_UP))
+ .setScale(0, RoundingMode.HALF_UP).longValue(),
+ Long.MAX_VALUE)
+ .baselineValues(new BigDecimal(Integer.MIN_VALUE)
+ .round(new MathContext(9, RoundingMode.HALF_UP))
+ .setScale(0, RoundingMode.HALF_UP).intValue(),
+ (int) Long.MIN_VALUE,
+ new BigDecimal(Integer.MIN_VALUE)
+ .round(new MathContext(9, RoundingMode.HALF_UP))
+ .setScale(0, RoundingMode.HALF_UP).longValue(),
+ Long.MIN_VALUE)
.baselineValues(123456789, 123456789, 123456789L, 123456789L)
- .build()
- .run();
+ .go();
} finally {
test("drop table if exists dfs.tmp.table_with_int");
test("alter session reset planner.enable_decimal_data_type");
@@ -443,14 +457,73 @@ public class TestCastFunctions extends BaseTestQuery {
.baselineValues(-0.12f, -0.1004f, -0.12, -0.1004)
.baselineValues(-123.1234f, -987654321.1234567891f, -123.1234, -987654321.1235)
.baselineValues(-1.0001f, -2.0301f, -1.0001, -2.0301)
- .build()
- .run();
+ .go();
} finally {
test("drop table if exists dfs.tmp.table_with_int");
test("alter session reset planner.enable_decimal_data_type");
}
}
+ @Test
+ public void testCastDecimalToVarDecimal() throws Exception {
+ try {
+ setSessionOption(PlannerSettings.ENABLE_DECIMAL_DATA_TYPE_KEY, true);
+
+ testBuilder()
+ .physicalPlanFromFile("decimal/cast_decimal_vardecimal.json")
+ .unOrdered()
+ .baselineColumns("DEC28_COL", "DEC38_COL", "DEC9_COL", "DEC18_COL")
+ .baselineValues(new BigDecimal("-100000000001.0000000000000000"), new BigDecimal("1123.3000000000000000"),
+ new BigDecimal("1123"), new BigDecimal("-100000000001"))
+ .baselineValues(new BigDecimal("11.1234567890123456"), new BigDecimal("0.3000000000000000"),
+ new BigDecimal("0"), new BigDecimal("11"))
+ .baselineValues(new BigDecimal("0.1000000000010000"), new BigDecimal("123456789.0000000000000000"),
+ new BigDecimal("123456789"), new BigDecimal("0"))
+ .baselineValues(new BigDecimal("-0.1200000000000000"), new BigDecimal("0.0000020000000000"),
+ new BigDecimal("0"), new BigDecimal("0"))
+ .baselineValues(new BigDecimal("100000000001.1234567890010000"), new BigDecimal("111.3000000000000000"),
+ new BigDecimal("111"), new BigDecimal("100000000001"))
+ .baselineValues(new BigDecimal("-100000000001.0000000000000000"), new BigDecimal("121.0930000000000000"),
+ new BigDecimal("121"), new BigDecimal("-100000000001"))
+ .baselineValues(new BigDecimal("123456789123456789.0000000000000000"), new BigDecimal("12.3000000000000000"),
+ new BigDecimal("12"), new BigDecimal("123456789123456789"))
+ .go();
+ } finally {
+ test("drop table if exists dfs.tmp.table_with_int");
+ resetSessionOption(PlannerSettings.ENABLE_DECIMAL_DATA_TYPE_KEY);
+ }
+ }
+
+ @Test
+ public void testCastVarDecimalToDecimal() throws Exception {
+ try {
+ setSessionOption(PlannerSettings.ENABLE_DECIMAL_DATA_TYPE_KEY, true);
+
+ testBuilder()
+ .physicalPlanFromFile("decimal/cast_vardecimal_decimal.json")
+ .unOrdered()
+ .baselineColumns("DEC28_COL", "DEC38_COL", "DEC9_COL", "DEC18_COL")
+ .baselineValues(new BigDecimal("-100000000001.0000000000000000"), new BigDecimal("1123.3000000000000000"),
+ new BigDecimal("1123"), new BigDecimal("-100000000001"))
+ .baselineValues(new BigDecimal("11.1234567890123456"), new BigDecimal("0.3000000000000000"),
+ new BigDecimal("0"), new BigDecimal("11"))
+ .baselineValues(new BigDecimal("0.1000000000010000"), new BigDecimal("123456789.0000000000000000"),
+ new BigDecimal("123456789"), new BigDecimal("0"))
+ .baselineValues(new BigDecimal("-0.1200000000000000"), new BigDecimal("0.0000020000000000"),
+ new BigDecimal("0"), new BigDecimal("0"))
+ .baselineValues(new BigDecimal("100000000001.1234567890010000"), new BigDecimal("111.3000000000000000"),
+ new BigDecimal("111"), new BigDecimal("100000000001"))
+ .baselineValues(new BigDecimal("-100000000001.0000000000000000"), new BigDecimal("121.0930000000000000"),
+ new BigDecimal("121"), new BigDecimal("-100000000001"))
+ .baselineValues(new BigDecimal("123456789123456789.0000000000000000"), new BigDecimal("12.3000000000000000"),
+ new BigDecimal("12"), new BigDecimal("123456789123456789"))
+ .go();
+ } finally {
+ test("drop table if exists dfs.tmp.table_with_int");
+ resetSessionOption(PlannerSettings.ENABLE_DECIMAL_DATA_TYPE_KEY);
+ }
+ }
+
@Test // DRILL-4970
public void testCastNegativeFloatToInt() throws Exception {
try {
@@ -477,8 +550,7 @@ public class TestCastFunctions extends BaseTestQuery {
.unOrdered()
.baselineColumns("c")
.baselineValues(1L)
- .build()
- .run();
+ .go();
}
}
} finally {
@@ -509,12 +581,24 @@ public class TestCastFunctions extends BaseTestQuery {
.unOrdered()
.baselineColumns("c")
.baselineValues(1L)
- .build()
- .run();
+ .go();
}
} finally {
test("drop table if exists dfs.tmp.table_with_decimal");
test("alter session reset planner.enable_decimal_data_type");
}
}
+
+ @Test
+ public void testCastDecimalLiteral() throws Exception {
+ String query =
+ "select case when true then cast(100.0 as decimal(38,2)) else cast('123.0' as decimal(38,2)) end as c1";
+
+ testBuilder()
+ .sqlQuery(query)
+ .ordered()
+ .baselineColumns("c1")
+ .baselineValues(new BigDecimal("100.00"))
+ .go();
+ }
} \ No newline at end of file
diff --git a/exec/java-exec/src/test/java/org/apache/drill/exec/fn/impl/TestVarDecimalFunctions.java b/exec/java-exec/src/test/java/org/apache/drill/exec/fn/impl/TestVarDecimalFunctions.java
new file mode 100644
index 000000000..b74a86070
--- /dev/null
+++ b/exec/java-exec/src/test/java/org/apache/drill/exec/fn/impl/TestVarDecimalFunctions.java
@@ -0,0 +1,743 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.drill.exec.fn.impl;
+
+import org.apache.drill.categories.SqlFunctionTest;
+import org.apache.drill.exec.planner.physical.PlannerSettings;
+import org.apache.drill.test.BaseTestQuery;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import java.math.BigDecimal;
+import java.math.MathContext;
+import java.math.RoundingMode;
+
+@Category(SqlFunctionTest.class)
+public class TestVarDecimalFunctions extends BaseTestQuery {
+
+ @BeforeClass
+ public static void enableDecimalDataType() {
+ setSessionOption(PlannerSettings.ENABLE_DECIMAL_DATA_TYPE_KEY, true);
+ }
+
+ @AfterClass
+ public static void disableDecimalDataType() {
+ resetSessionOption(PlannerSettings.ENABLE_DECIMAL_DATA_TYPE_KEY);
+ }
+
+ // Tests for math functions
+
+ @Test
+ public void testDecimalAdd() throws Exception {
+ String query =
+ "select\n" +
+ // checks trimming of scale
+ "cast('999999999999999999999999999.92345678912' as DECIMAL(38, 11))\n" +
+ "+ cast('0.32345678912345678912345678912345678912' as DECIMAL(38, 38)) as s1,\n" +
+ // sanitary checks
+ "cast('1234567891234567891234567891234567.89' as DECIMAL(36, 2))\n" +
+ "+ cast('123456789123456789123456789123456.789' as DECIMAL(36, 3)) as s2,\n" +
+ "cast('1234567891234567891234567891234567.89' as DECIMAL(36, 2))\n" +
+ "+ cast('0' as DECIMAL(36, 3)) as s3,\n" +
+ "cast('15.02' as DECIMAL(4, 2)) - cast('12.93' as DECIMAL(4, 2)) as s4,\n" +
+ "cast('11.02' as DECIMAL(4, 2)) - cast('12.93' as DECIMAL(4, 2)) as s5,\n" +
+ "cast('0' as DECIMAL(36, 2)) - cast('12.93' as DECIMAL(36, 2)) as s6,\n" +
+ // check trimming (negative scale)
+ "cast('99999999999999999999999999992345678912' as DECIMAL(38, 0))\n" +
+ "+ cast('32345678912345678912345678912345678912' as DECIMAL(38, 0)) as s7";
+ testBuilder()
+ .sqlQuery(query)
+ .ordered()
+ .baselineColumns("s1", "s2", "s3", "s4", "s5", "s6", "s7")
+ .baselineValues(
+ new BigDecimal("999999999999999999999999999.92345678912")
+ .add(new BigDecimal("0.32345678912345678912345678912345678912"))
+ .round(new MathContext(38, RoundingMode.HALF_UP)),
+ new BigDecimal("1358024680358024680358024680358024.679"),
+ new BigDecimal("1234567891234567891234567891234567.890"),
+ new BigDecimal("2.09"), new BigDecimal("-1.91"), new BigDecimal("-12.93"),
+ new BigDecimal("1.3234567891234567891234567890469135782E+38"))
+ .go();
+ }
+
+ @Test
+ public void testDecimalMultiply() throws Exception {
+ String query =
+ "select\n" +
+ // checks trimming of scale
+ "cast('999999999999999999999999999.92345678912' as DECIMAL(38, 11))\n" +
+ "* cast('0.32345678912345678912345678912345678912' as DECIMAL(38, 38)) as s1,\n" +
+ // sanitary checks
+ "cast('1234567.89' as DECIMAL(9, 2))\n" +
+ "* cast('-1.789' as DECIMAL(4, 3)) as s2,\n" +
+ "cast('15.02' as DECIMAL(4, 2)) * cast('0' as DECIMAL(4, 2)) as s3,\n" +
+ "cast('12.93123456789' as DECIMAL(13, 11)) * cast('1' as DECIMAL(1, 0)) as s4";
+ testBuilder()
+ .sqlQuery(query)
+ .ordered()
+ .baselineColumns("s1", "s2", "s3", "s4")
+ .baselineValues(new BigDecimal("999999999999999999999999999.92345678912")
+ .multiply(new BigDecimal("0.32345678912345678912345678912345678912"))
+ .round(new MathContext(38, RoundingMode.HALF_UP)),
+ new BigDecimal("-2208641.95521"),
+ new BigDecimal("0.0000"), new BigDecimal("12.93123456789"))
+ .go();
+ }
+
+ @Test
+ public void testDecimalDivide() throws Exception {
+ String query =
+ "select\n" +
+ // checks trimming of scale
+ "cast('1.9999999999999999999999999999234567891' as DECIMAL(38, 37))\n" +
+ "/ cast('0.00000000000000000000000000000000000001' as DECIMAL(38, 38)) as s1,\n" +
+ // sanitary checks
+ "cast('1234567.89' as DECIMAL(9, 2))\n" +
+ "/ cast('-1.789' as DECIMAL(4, 3)) as s2,\n" +
+ "cast('15.02' as DECIMAL(4, 2)) / cast('15.02' as DECIMAL(4, 2)) as s3,\n" +
+ "cast('12.93123456789' as DECIMAL(13, 11)) / cast('1' as DECIMAL(1, 0)) as s4,\n" +
+ "cast('0' as DECIMAL(0, 0)) / cast('15.02' as DECIMAL(4, 2)) as s5";
+ testBuilder()
+ .sqlQuery(query)
+ .ordered()
+ .baselineColumns("s1", "s2", "s3", "s4", "s5")
+ .baselineValues(new BigDecimal("199999999999999999999999999992345678910"),
+ new BigDecimal("-690088.2560089"),
+ new BigDecimal("1.0000000"), new BigDecimal("12.9312345678900"), new BigDecimal("0.000000"))
+ .go();
+ }
+
+ @Test
+ public void testDecimalMod() throws Exception {
+ String query =
+ "select\n" +
+ "mod(cast('1111' as DECIMAL(4, 0)), cast('12' as DECIMAL(2, 0))) as s1,\n" +
+ "mod(cast('1234567' as DECIMAL(7, 0)),\n" +
+ "cast('-9' as DECIMAL(1, 0))) as s2,\n" +
+ "mod(cast('-1502' as DECIMAL(4, 0)), cast('15' as DECIMAL(2, 0))) as s3,\n" +
+ "mod(cast('-987654' as DECIMAL(6, 0)), cast('-31' as DECIMAL(2, 0))) as s4";
+ testBuilder()
+ .sqlQuery(query)
+ .ordered()
+ .baselineColumns("s1", "s2", "s3", "s4")
+ .baselineValues(new BigDecimal("7"), new BigDecimal("1"),
+ new BigDecimal("-2"), new BigDecimal("-25"))
+ .go();
+ }
+
+ @Test
+ public void testDecimalAbs() throws Exception {
+ String query =
+ "select\n" +
+ "abs(cast('1111' as DECIMAL(4, 0))) as s1,\n" +
+ "abs(cast('-1234567.123456' as DECIMAL(13, 6))) as s2,\n" +
+ "abs(cast('-1502' as DECIMAL(4, 0))) as s3,\n" +
+ "abs(cast('0' as DECIMAL(4, 0))) as s4,\n" +
+ "abs(cast('-987654' as DECIMAL(6, 0))) as s5";
+ testBuilder()
+ .sqlQuery(query)
+ .ordered()
+ .baselineColumns("s1", "s2", "s3", "s4", "s5")
+ .baselineValues(new BigDecimal("1111"), new BigDecimal("1234567.123456"),
+ new BigDecimal("1502"), new BigDecimal("0"), new BigDecimal("987654"))
+ .go();
+ }
+
+ @Test
+ public void testDecimalCeil() throws Exception {
+ String query =
+ "select\n" +
+ "ceil(cast('1111.35' as DECIMAL(6, 2))) as s1,\n" +
+ "ceiling(cast('1234567.123456' as DECIMAL(13, 6))) as s2,\n" +
+ "ceil(cast('-1502.5' as DECIMAL(5, 1))) as s3,\n" +
+ "ceiling(cast('987654.5' as DECIMAL(7, 1))) as s4,\n" +
+ "ceil(cast('987654.00' as DECIMAL(8, 2))) as s5";
+ testBuilder()
+ .sqlQuery(query)
+ .ordered()
+ .baselineColumns("s1", "s2", "s3", "s4", "s5")
+ .baselineValues(new BigDecimal("1112"), new BigDecimal("1234568"),
+ new BigDecimal("-1502"), new BigDecimal("987655"), new BigDecimal("987654"))
+ .go();
+ }
+
+ @Test
+ public void testDecimalFloor() throws Exception {
+ String query =
+ "select\n" +
+ "floor(cast('1111.35' as DECIMAL(6, 2))) as s1,\n" +
+ "floor(cast('1234567.123456' as DECIMAL(13, 6))) as s2,\n" +
+ "floor(cast('-1502.5' as DECIMAL(5, 1))) as s3,\n" +
+ "floor(cast('987654.5' as DECIMAL(7, 1))) as s4,\n" +
+ "floor(cast('987654.00' as DECIMAL(8, 2))) as s5";
+ testBuilder()
+ .sqlQuery(query)
+ .ordered()
+ .baselineColumns("s1", "s2", "s3", "s4", "s5")
+ .baselineValues(new BigDecimal("1111"), new BigDecimal("1234567"),
+ new BigDecimal("-1503"), new BigDecimal("987654"), new BigDecimal("987654"))
+ .go();
+ }
+
+ @Test
+ public void testDecimalTrunc() throws Exception {
+ String query =
+ "select\n" +
+ "trunc(cast('1111.35' as DECIMAL(6, 2))) as s1,\n" +
+ "truncate(cast('1234567.123456' as DECIMAL(13, 6))) as s2,\n" +
+ "trunc(cast('-1502.5' as DECIMAL(5, 1))) as s3,\n" +
+ "truncate(cast('987654.5' as DECIMAL(7, 1))) as s4,\n" +
+ "trunc(cast('987654.00' as DECIMAL(8, 2))) as s5";
+ testBuilder()
+ .sqlQuery(query)
+ .ordered()
+ .baselineColumns("s1", "s2", "s3", "s4", "s5")
+ .baselineValues(new BigDecimal("1111"), new BigDecimal("1234567"),
+ new BigDecimal("-1502"), new BigDecimal("987654"), new BigDecimal("987654"))
+ .go();
+ }
+
+ @Test
+ public void testDecimalRound() throws Exception {
+ String query =
+ "select\n" +
+ "round(cast('1111.45' as DECIMAL(6, 2))) as s1,\n" +
+ "round(cast('1234567.523456' as DECIMAL(13, 6))) as s2,\n" +
+ "round(cast('-1502.5' as DECIMAL(5, 1))) as s3,\n" +
+ "round(cast('-987654.4' as DECIMAL(7, 1))) as s4,\n" +
+ "round(cast('987654.00' as DECIMAL(8, 2))) as s5";
+ testBuilder()
+ .sqlQuery(query)
+ .ordered()
+ .baselineColumns("s1", "s2", "s3", "s4", "s5")
+ .baselineValues(new BigDecimal("1111"), new BigDecimal("1234568"),
+ new BigDecimal("-1503"), new BigDecimal("-987654"), new BigDecimal("987654"))
+ .go();
+ }
+
+ @Test
+ public void testDecimalSign() throws Exception {
+ String query =
+ "select\n" +
+ "sign(cast('+1111.45' as DECIMAL(6, 2))) as s1,\n" +
+ "sign(cast('-1234567.523456' as DECIMAL(13, 6))) as s2,\n" +
+ "sign(cast('-1502.5' as DECIMAL(5, 1))) as s3,\n" +
+ "sign(cast('987654.4' as DECIMAL(7, 1))) as s4,\n" +
+ "sign(cast('0' as DECIMAL(8, 2))) as s5";
+ testBuilder()
+ .sqlQuery(query)
+ .ordered()
+ .baselineColumns("s1", "s2", "s3", "s4", "s5")
+ .baselineValues(1, -1, -1, 1, 0)
+ .go();
+ }
+
+ @Test
+ public void testDecimalRoundWithScale() throws Exception {
+ String query =
+ "select\n" +
+ "round(cast('1111.45' as DECIMAL(6, 2)), 1) as s1,\n" +
+ "round(cast('1234567.523456' as DECIMAL(13, 6)), 5) as s2,\n" +
+ "round(cast('-1502.5' as DECIMAL(5, 1)), 0) as s3,\n" +
+ "round(cast('-987654.4' as DECIMAL(7, 1)), 1) as s4,\n" +
+ "round(cast('987654.00' as DECIMAL(8, 2)), 2) as s5";
+ testBuilder()
+ .sqlQuery(query)
+ .ordered()
+ .baselineColumns("s1", "s2", "s3", "s4", "s5")
+ .baselineValues(new BigDecimal("1111.5"), new BigDecimal("1234567.52346"),
+ new BigDecimal("-1503"), new BigDecimal("-987654.4"), new BigDecimal("987654.00"))
+ .go();
+ }
+
+ @Test
+ public void testDecimalTruncWithScale() throws Exception {
+ String query =
+ "select\n" +
+ "trunc(cast('1111.45' as DECIMAL(6, 2)), 1) as s1,\n" +
+ "truncate(cast('1234567.523456' as DECIMAL(13, 6)), 5) as s2,\n" +
+ "trunc(cast('-1502.5' as DECIMAL(5, 1)), 0) as s3,\n" +
+ "truncate(cast('-987654.4' as DECIMAL(7, 1)), 1) as s4,\n" +
+ "trunc(cast('987654.00' as DECIMAL(8, 2)), 2) as s5";
+ testBuilder()
+ .sqlQuery(query)
+ .ordered()
+ .baselineColumns("s1", "s2", "s3", "s4", "s5")
+ .baselineValues(new BigDecimal("1111.4"), new BigDecimal("1234567.52345"),
+ new BigDecimal("-1502"), new BigDecimal("-987654.4"), new BigDecimal("987654.00"))
+ .go();
+ }
+
+ // Tests for comparison functions
+
+ @Test
+ public void testDecimalEquals() throws Exception {
+ String query =
+ "select\n" +
+ "cast('1.9999999999999999999999999999234567891' as DECIMAL(38, 37))\n" +
+ "= cast('1.9999999999999999999999999999234567891' as DECIMAL(38, 37)) as s1,\n" +
+ "cast('1.9999999999999999999999999999234567891' as DECIMAL(38, 37))\n" +
+ "<> cast('1.9999999999999999999999999999234567891' as DECIMAL(38, 37)) as s2,\n" +
+ // the same value but different scale and precision
+ "cast('1234567.89' as DECIMAL(9, 2)) = cast('1234567.890' as DECIMAL(10, 3)) as s3,\n" +
+ "cast('0' as DECIMAL(4, 2)) = cast('0' as DECIMAL(0, 0)) as s4,\n" +
+ "cast('0' as DECIMAL(4, 2)) <> cast('0' as DECIMAL(0, 0)) as s5,\n" +
+ "cast('12.93123456789' as DECIMAL(13, 11)) = cast('12.93123456788' as DECIMAL(13, 11)) as s6";
+ testBuilder()
+ .sqlQuery(query)
+ .ordered()
+ .baselineColumns("s1", "s2", "s3", "s4", "s5", "s6")
+ .baselineValues(true, false, true, true, false, false)
+ .go();
+ }
+
+ @Test
+ public void testDecimalLessThan() throws Exception {
+ String query =
+ "select\n" +
+ "cast('1.9999999999999999999999999999234567891' as DECIMAL(38, 37))\n" +
+ "< cast('1.9999999999999999999999999999234567891' as DECIMAL(38, 37)) as s1,\n" +
+ "cast('1.9999999999999999999999999999234567891' as DECIMAL(38, 37))\n" +
+ "< cast('1.9999999999999999999999999999234567892' as DECIMAL(38, 37)) as s2,\n" +
+ // the same value but different scale and precision
+ "cast('1234567.89' as DECIMAL(9, 2)) < cast('1234567.890' as DECIMAL(10, 3)) as s3,\n" +
+ "cast('0' as DECIMAL(4, 2)) < cast('0' as DECIMAL(0, 0)) as s4,\n" +
+ "cast('12.93123456789' as DECIMAL(13, 11)) < cast('12.93123456788' as DECIMAL(13, 11)) as s5";
+ testBuilder()
+ .sqlQuery(query)
+ .ordered()
+ .baselineColumns("s1", "s2", "s3", "s4", "s5")
+ .baselineValues(false, true, false, false, false)
+ .go();
+ }
+
+ @Test
+ public void testDecimalLessThanEquals() throws Exception {
+ String query =
+ "select\n" +
+ "cast('1.9999999999999999999999999999234567891' as DECIMAL(38, 37))\n" +
+ "<= cast('1.9999999999999999999999999999234567891' as DECIMAL(38, 37)) as s1,\n" +
+ "cast('1.9999999999999999999999999999234567891' as DECIMAL(38, 37))\n" +
+ "<= cast('1.9999999999999999999999999999234567892' as DECIMAL(38, 37)) as s2,\n" +
+ // the same value but different scale and precision
+ "cast('1234567.89' as DECIMAL(9, 2)) <= cast('1234567.890' as DECIMAL(10, 3)) as s3,\n" +
+ "cast('0' as DECIMAL(4, 2)) <= cast('0' as DECIMAL(0, 0)) as s4,\n" +
+ "cast('12.93123456789' as DECIMAL(13, 11)) <= cast('12.93123456788' as DECIMAL(13, 11)) as s5";
+ testBuilder()
+ .sqlQuery(query)
+ .ordered()
+ .baselineColumns("s1", "s2", "s3", "s4", "s5")
+ .baselineValues(true, true, true, true, false)
+ .go();
+ }
+
+ @Test
+ public void testDecimalGreaterThan() throws Exception {
+ String query =
+ "select\n" +
+ "cast('1.9999999999999999999999999999234567891' as DECIMAL(38, 37))\n" +
+ "> cast('1.9999999999999999999999999999234567891' as DECIMAL(38, 37)) as s1,\n" +
+ "cast('1.9999999999999999999999999999234567891' as DECIMAL(38, 37))\n" +
+ "> cast('1.9999999999999999999999999999234567892' as DECIMAL(38, 37)) as s2,\n" +
+ // the same value but different scale and precision
+ "cast('1234567.89' as DECIMAL(9, 2)) > cast('1234567.890' as DECIMAL(10, 3)) as s3,\n" +
+ "cast('0' as DECIMAL(4, 2)) > cast('0' as DECIMAL(0, 0)) as s4,\n" +
+ "cast('12.93123456789' as DECIMAL(13, 11)) > cast('12.93123456788' as DECIMAL(13, 11)) as s5";
+ testBuilder()
+ .sqlQuery(query)
+ .ordered()
+ .baselineColumns("s1", "s2", "s3", "s4", "s5")
+ .baselineValues(false, false, false, false, true)
+ .go();
+ }
+
+ @Test
+ public void testDecimalGreaterThanEquals() throws Exception {
+ String query =
+ "select\n" +
+ "cast('1.9999999999999999999999999999234567891' as DECIMAL(38, 37))\n" +
+ ">= cast('1.9999999999999999999999999999234567891' as DECIMAL(38, 37)) as s1,\n" +
+ "cast('1.9999999999999999999999999999234567891' as DECIMAL(38, 37))\n" +
+ ">= cast('1.9999999999999999999999999999234567892' as DECIMAL(38, 37)) as s2,\n" +
+ // the same value but different scale and precision
+ "cast('1234567.89' as DECIMAL(9, 2)) >= cast('1234567.890' as DECIMAL(10, 3)) as s3,\n" +
+ "cast('0' as DECIMAL(4, 2)) >= cast('0' as DECIMAL(0, 0)) as s4,\n" +
+ "cast('12.93123456789' as DECIMAL(13, 11)) >= cast('12.93123456788' as DECIMAL(13, 11)) as s5";
+ testBuilder()
+ .sqlQuery(query)
+ .ordered()
+ .baselineColumns("s1", "s2", "s3", "s4", "s5")
+ .baselineValues(true, false, true, true, true)
+ .go();
+ }
+
+ @Test
+ public void testDecimalCompareToNullsHigh() throws Exception {
+ String query =
+ "select\n" +
+ "compare_to_nulls_high(cast('1.9999999999999999999999999999234567891' as DECIMAL(38, 37)),\n" +
+ "cast('1.9999999999999999999999999999234567891' as DECIMAL(38, 37))) as s1,\n" +
+ "compare_to_nulls_high(cast('1.9999999999999999999999999999234567891' as DECIMAL(38, 37)),\n" +
+ "cast('1.9999999999999999999999999999234567892' as DECIMAL(38, 37))) as s2,\n" +
+ // the same value but different scale and precision
+ "compare_to_nulls_high(cast('1234567.89' as DECIMAL(9, 2)), cast('1234567.890' as DECIMAL(10, 3))) as s3,\n" +
+ "compare_to_nulls_high(cast('0' as DECIMAL(4, 2)), cast('0' as DECIMAL(0, 0))) as s4,\n" +
+ "compare_to_nulls_high(cast('0' as DECIMAL(4, 2)), cast(null as DECIMAL(0, 0))) as s5,\n" +
+ "compare_to_nulls_high(cast('12.93123456789' as DECIMAL(13, 11)), " +
+ "cast('12.93123456788' as DECIMAL(13, 11))) as s6";
+ testBuilder()
+ .sqlQuery(query)
+ .ordered()
+ .baselineColumns("s1", "s2", "s3", "s4", "s5", "s6")
+ .baselineValues(0, -1, 0, 0, -1, 1)
+ .go();
+ }
+
+ @Test
+ public void testDecimalCompareToNullsLow() throws Exception {
+ String query =
+ "select\n" +
+ "compare_to_nulls_low(cast('1.9999999999999999999999999999234567891' as DECIMAL(38, 37)),\n" +
+ "cast('1.9999999999999999999999999999234567891' as DECIMAL(38, 37))) as s1,\n" +
+ "compare_to_nulls_low(cast('1.9999999999999999999999999999234567891' as DECIMAL(38, 37)),\n" +
+ "cast('1.9999999999999999999999999999234567892' as DECIMAL(38, 37))) as s2,\n" +
+ // the same value but different scale and precision
+ "compare_to_nulls_low(cast('1234567.89' as DECIMAL(9, 2)), cast('1234567.890' as DECIMAL(10, 3))) as s3,\n" +
+ "compare_to_nulls_low(cast('0' as DECIMAL(4, 2)), cast('0' as DECIMAL(0, 0))) as s4,\n" +
+ "compare_to_nulls_low(cast('0' as DECIMAL(4, 2)), cast(null as DECIMAL(0, 0))) as s5,\n" +
+ "compare_to_nulls_low(cast('12.93123456789' as DECIMAL(13, 11)), " +
+ "cast('12.93123456788' as DECIMAL(13, 11))) as s6";
+ testBuilder()
+ .sqlQuery(query)
+ .ordered()
+ .baselineColumns("s1", "s2", "s3", "s4", "s5", "s6")
+ .baselineValues(0, -1, 0, 0, 1, 1)
+ .go();
+ }
+
+ // Tests for cast functions
+
+ @Test
+ public void testCastIntDecimal() throws Exception {
+ String query =
+ "select\n" +
+ "cast(i1 as DECIMAL(4, 0)) as s1,\n" +
+ "cast(i2 as DECIMAL(7, 0)) as s2,\n" +
+ "cast(i3 as DECIMAL(8, 0)) as s3,\n" +
+ "cast(i4 as DECIMAL(6, 0)) as s4,\n" +
+ "cast(i5 as DECIMAL(6, 0)) as s5,\n" +
+ "cast(i6 as DECIMAL(10, 0)) as s6,\n" +
+ "cast(i7 as DECIMAL(10, 0)) as s7\n" +
+ "from (" +
+ "select\n" +
+ "cast(0 as int) as i1,\n" +
+ "cast(1234567 as int) as i2,\n" +
+ "cast(-15022222 as int) as i3,\n" +
+ "cast(-987654 as int) as i4,\n" +
+ "cast(987654 as int) as i5,\n" +
+ "cast(%s as int) as i6,\n" +
+ "cast(%s as int) as i7)";
+ testBuilder()
+ .sqlQuery(query, Integer.MAX_VALUE, Integer.MIN_VALUE)
+ .ordered()
+ .baselineColumns("s1", "s2", "s3", "s4", "s5", "s6", "s7")
+ .baselineValues(BigDecimal.valueOf(0), BigDecimal.valueOf(1234567),
+ BigDecimal.valueOf(-15022222), BigDecimal.valueOf(-987654),BigDecimal.valueOf(987654),
+ BigDecimal.valueOf(Integer.MAX_VALUE), BigDecimal.valueOf(Integer.MIN_VALUE))
+ .go();
+ }
+
+ @Test
+ public void testCastDecimalInt() throws Exception {
+ String query =
+ "select\n" +
+ "cast(i1 as int) as s1,\n" +
+ "cast(i2 as int) as s2,\n" +
+ "cast(i3 as int) as s3,\n" +
+ "cast(i4 as int) as s4,\n" +
+ "cast(i5 as int) as s5,\n" +
+ "cast(i6 as int) as s6,\n" +
+ "cast(i7 as int) as s7\n" +
+ "from (" +
+ "select\n" +
+ "cast('999999999999999999999999999.92345678912' as DECIMAL(38, 11)) as i1,\n" +
+ "cast('0.32345678912345678912345678912345678912' as DECIMAL(38, 38)) as i2,\n" +
+ "cast('-1234567891234567891234567891234567.89' as DECIMAL(36, 2)) as i3,\n" +
+ "cast('0' as DECIMAL(36, 3)) as i4,\n" +
+ "cast('15.02' as DECIMAL(4, 2)) as i5,\n" +
+ "cast('-15.02' as DECIMAL(4, 2)) as i6,\n" +
+ "cast('0.7877' as DECIMAL(4, 4)) as i7)";
+ testBuilder()
+ .sqlQuery(query)
+ .ordered()
+ .baselineColumns("s1", "s2", "s3", "s4", "s5", "s6", "s7")
+ .baselineValues(
+ new BigDecimal("999999999999999999999999999.92345678912")
+ .setScale(0, BigDecimal.ROUND_HALF_UP).intValue(),
+ 0,
+ new BigDecimal("-1234567891234567891234567891234567.89")
+ .setScale(0, BigDecimal.ROUND_HALF_UP).intValue(),
+ 0, 15, -15, 1)
+ .go();
+ }
+
+ @Test
+ public void testCastBigIntDecimal() throws Exception {
+ String query =
+ "select\n" +
+ "cast(i1 as DECIMAL(4, 0)) as s1,\n" +
+ "cast(i2 as DECIMAL(7, 0)) as s2,\n" +
+ "cast(i3 as DECIMAL(8, 0)) as s3,\n" +
+ "cast(i4 as DECIMAL(6, 0)) as s4,\n" +
+ "cast(i5 as DECIMAL(6, 0)) as s5,\n" +
+ "cast(i6 as DECIMAL(19, 0)) as s6,\n" +
+ "cast(i7 as DECIMAL(19, 0)) as s7\n" +
+ "from (" +
+ "select " +
+ "cast(0 as bigint) as i1,\n" +
+ "cast(1234567 as bigint) as i2,\n" +
+ "cast(-15022222 as bigint) as i3,\n" +
+ "cast(-987654 as bigint) as i4,\n" +
+ "cast(987654 as bigint) as i5,\n" +
+ "cast(%s as bigint) as i6,\n" +
+ "cast(%s as bigint) as i7)";
+ testBuilder()
+ .sqlQuery(query, Long.MAX_VALUE, Long.MIN_VALUE)
+ .ordered()
+ .baselineColumns("s1", "s2", "s3", "s4", "s5", "s6", "s7")
+ .baselineValues(new BigDecimal("0"), new BigDecimal("1234567"),
+ new BigDecimal("-15022222"), new BigDecimal("-987654"), new BigDecimal("987654"),
+ BigDecimal.valueOf(Long.MAX_VALUE), BigDecimal.valueOf(Long.MIN_VALUE))
+ .go();
+ }
+
+ @Test
+ public void testCastDecimalBigInt() throws Exception {
+ String query =
+ "select\n" +
+ "cast(i1 as bigint) as s1,\n" +
+ "cast(i2 as bigint) as s2,\n" +
+ "cast(i3 as bigint) as s3,\n" +
+ "cast(i4 as bigint) as s4,\n" +
+ "cast(i5 as bigint) as s5,\n" +
+ "cast(i6 as bigint) as s6,\n" +
+ "cast(i7 as bigint) as s7\n" +
+ "from (" +
+ "select\n" +
+ "cast('999999999999999999999999999.92345678912' as DECIMAL(38, 11)) as i1,\n" +
+ "cast('0.32345678912345678912345678912345678912' as DECIMAL(38, 38)) as i2,\n" +
+ "cast('-1234567891234567891234567891234567.89' as DECIMAL(36, 2)) as i3,\n" +
+ "cast('0' as DECIMAL(36, 3)) as i4,\n" +
+ "cast('15.02' as DECIMAL(4, 2)) as i5,\n" +
+ "cast('-15.02' as DECIMAL(4, 2)) as i6,\n" +
+ "cast('0.7877' as DECIMAL(4, 4)) as i7)";
+ testBuilder()
+ .sqlQuery(query)
+ .ordered()
+ .baselineColumns("s1", "s2", "s3", "s4", "s5", "s6", "s7")
+ .baselineValues(
+ new BigDecimal("999999999999999999999999999.92345678912")
+ .setScale(0, BigDecimal.ROUND_HALF_UP).longValue(),
+ 0L,
+ new BigDecimal("-1234567891234567891234567891234567.89")
+ .setScale(0, BigDecimal.ROUND_HALF_UP).longValue(),
+ 0L, 15L, -15L, 1L)
+ .go();
+ }
+
+ @Test
+ public void testCastFloatDecimal() throws Exception {
+ String query =
+ "select\n" +
+ "cast(i1 as DECIMAL(4, 0)) as s1,\n" +
+ "cast(i2 as DECIMAL(7, 6)) as s2,\n" +
+ "cast(i3 as DECIMAL(8, 7)) as s3,\n" +
+ "cast(i4 as DECIMAL(6, 6)) as s4,\n" +
+ "cast(i5 as DECIMAL(7, 0)) as s5,\n" +
+ "cast(i6 as DECIMAL(7, 46)) as s6,\n" +
+ "cast(i7 as DECIMAL(17, 0)) as s7\n" +
+ "from (" +
+ "select\n" +
+ "cast(0 as float) as i1,\n" +
+ "cast(1.234567 as float) as i2,\n" +
+ "cast(-1.5022222 as float) as i3,\n" +
+ "cast(-0.987654 as float) as i4,\n" +
+ "cast(9999999 as float) as i5,\n" +
+ "cast('%s' as float) as i6,\n" +
+ "cast('%s' as float) as i7)";
+
+ testBuilder()
+ .sqlQuery(query, Float.MIN_VALUE, Float.MAX_VALUE)
+ .ordered()
+ .baselineColumns("s1", "s2", "s3", "s4", "s5", "s6", "s7")
+ .baselineValues(BigDecimal.valueOf(0), new BigDecimal("1.234567"),
+ new BigDecimal("-1.5022222"), new BigDecimal("-0.987654"), BigDecimal.valueOf(9999999),
+ new BigDecimal(String.format("%s", Float.MIN_VALUE)),
+ new BigDecimal("340282350000000000000000000000000000000")) // Float.MAX_VALUE in non-scientific format
+ .go();
+ }
+
+ @Test
+ public void testCastDecimalFloat() throws Exception {
+ String query =
+ "select\n" +
+ "cast(i1 as float) as s1,\n" +
+ "cast(i2 as float) as s2,\n" +
+ "cast(i3 as float) as s3,\n" +
+ "cast(i4 as float) as s4,\n" +
+ "cast(i5 as float) as s5,\n" +
+ "cast(i6 as float) as s6,\n" +
+ "cast(i7 as float) as s7\n" +
+ "from (" +
+ "select\n" +
+ "cast('999999999999999999999999999.92345678912' as DECIMAL(38, 11)) as i1,\n" +
+ "cast('0.32345678912345678912345678912345678912' as DECIMAL(38, 38)) as i2,\n" +
+ "cast('-1234567891234567891234567891234567.89' as DECIMAL(36, 2)) as i3,\n" +
+ "cast('0' as DECIMAL(36, 3)) as i4,\n" +
+ "cast('15.02' as DECIMAL(4, 2)) as i5,\n" +
+ "cast('%s' as DECIMAL(2, 46)) as i6,\n" +
+ "cast('%s' as DECIMAL(8, 0)) as i7)";
+
+ testBuilder()
+ .sqlQuery(query, Float.MIN_VALUE, Float.MAX_VALUE)
+ .ordered()
+ .baselineColumns("s1", "s2", "s3", "s4", "s5", "s6", "s7")
+ .baselineValues(new BigDecimal("999999999999999999999999999.92345678912").floatValue(),
+ new BigDecimal("0.32345678912345678912345678912345678912").floatValue(),
+ new BigDecimal("-1234567891234567891234567891234567.89").floatValue(),
+ 0f, 15.02f, Float.MIN_VALUE, Float.MAX_VALUE)
+ .go();
+ }
+
+ @Test
+ public void testCastDoubleDecimal() throws Exception {
+ String query =
+ "select\n" +
+ "cast(i1 as DECIMAL(4, 0)) as s1,\n" +
+ "cast(i2 as DECIMAL(7, 6)) as s2,\n" +
+ "cast(i3 as DECIMAL(8, 7)) as s3,\n" +
+ "cast(i4 as DECIMAL(6, 6)) as s4,\n" +
+ "cast(i5 as DECIMAL(7, 0)) as s5,\n" +
+ "cast(i6 as DECIMAL(17, 325)) as s6,\n" +
+ "cast(i7 as DECIMAL(17, 0)) as s7\n" +
+ "from (" +
+ "select\n" +
+ "cast(0 as double) as i1,\n" +
+ "cast(1.234567 as double) as i2,\n" +
+ "cast(-1.5022222 as double) as i3,\n" +
+ "cast(-0.987654 as double) as i4,\n" +
+ "cast(9999999 as double) as i5,\n" +
+ "cast('%e' as double) as i6,\n" +
+ "cast('%f' as double) as i7)";
+
+ testBuilder()
+ .sqlQuery(query, Double.MIN_VALUE, Double.MAX_VALUE)
+ .ordered()
+ .baselineColumns("s1", "s2", "s3", "s4", "s5", "s6", "s7")
+ .baselineValues(BigDecimal.valueOf(0), new BigDecimal("1.234567"),
+ new BigDecimal("-1.5022222"), new BigDecimal("-0.987654"), BigDecimal.valueOf(9999999),
+ new BigDecimal(String.valueOf(Double.MIN_VALUE)),
+ new BigDecimal(String.format("%1.0f", Double.MAX_VALUE))) // non-scientific format
+ .go();
+ }
+
+ @Test
+ public void testCastDecimalDouble() throws Exception {
+ String query =
+ "select\n" +
+ "cast(i1 as double) as s1,\n" +
+ "cast(i2 as double) as s2,\n" +
+ "cast(i3 as double) as s3,\n" +
+ "cast(i4 as double) as s4,\n" +
+ "cast(i5 as double) as s5,\n" +
+ "cast(i6 as double) as s6,\n" +
+ "cast(i7 as double) as s7\n" +
+ "from (" +
+ "select\n" +
+ "cast('999999999999999999999999999.92345678912' as DECIMAL(38, 11)) as i1,\n" +
+ "cast('0.32345678912345678912345678912345678912' as DECIMAL(38, 38)) as i2,\n" +
+ "cast('-1234567891234567891234567891234567.89' as DECIMAL(36, 2)) as i3,\n" +
+ "cast('0' as DECIMAL(36, 3)) as i4,\n" +
+ "cast('15.02' as DECIMAL(4, 2)) as i5,\n" +
+ "cast('%e' as DECIMAL(17, 325)) as i6,\n" +
+ "cast('%f' as DECIMAL(17, 0)) as i7)";
+
+ testBuilder()
+ .sqlQuery(query, Double.MIN_VALUE, Double.MAX_VALUE)
+ .ordered()
+ .baselineColumns("s1", "s2", "s3", "s4", "s5", "s6", "s7")
+ .baselineValues(new BigDecimal("999999999999999999999999999.92345678912").doubleValue(),
+ new BigDecimal("0.32345678912345678912345678912345678912").doubleValue(),
+ new BigDecimal("-1234567891234567891234567891234567.89").doubleValue(),
+ 0d, 15.02, Double.MIN_VALUE, Double.MAX_VALUE)
+ .go();
+ }
+
+ @Test
+ public void testCastDecimalVarchar() throws Exception {
+ String query =
+ "select\n" +
+ "cast(i1 as varchar) as s1,\n" +
+ "cast(i2 as varchar) as s2,\n" +
+ "cast(i3 as varchar) as s3,\n" +
+ "cast(i4 as varchar) as s4,\n" +
+ "cast(i5 as varchar) as s5\n" +
+ "from (" +
+ "select\n" +
+ "cast('999999999999999999999999999.92345678912' as DECIMAL(38, 11)) as i1,\n" +
+ "cast('0.32345678912345678912345678912345678912' as DECIMAL(38, 38)) as i2,\n" +
+ "cast('-1234567891234567891234567891234567.89' as DECIMAL(36, 2)) as i3,\n" +
+ "cast('0' as DECIMAL(36, 3)) as i4,\n" +
+ "cast('15.02' as DECIMAL(4, 2)) as i5)";
+ testBuilder()
+ .sqlQuery(query)
+ .ordered()
+ .baselineColumns("s1", "s2", "s3", "s4", "s5")
+ .baselineValues("999999999999999999999999999.92345678912",
+ "0.32345678912345678912345678912345678912",
+ "-1234567891234567891234567891234567.89", "0.000", "15.02")
+ .go();
+ }
+
+ @Test
+ public void testDecimalToChar() throws Exception {
+ String query =
+ "select\n" +
+ "to_char(i1, '#.#') as s1,\n" +
+ "to_char(i2, '#.#') as s2,\n" +
+ "to_char(i3, '#.#') as s3,\n" +
+ "to_char(i4, '#.#') as s4,\n" +
+ "to_char(i5, '#.#') as s5\n" +
+ "from (" +
+ "select\n" +
+ "cast('999999999999999999999999999.92345678912' as DECIMAL(38, 11)) as i1,\n" +
+ "cast('0.32345678912345678912345678912345678912' as DECIMAL(38, 38)) as i2,\n" +
+ "cast('-1234567891234567891234567891234567.89' as DECIMAL(36, 2)) as i3,\n" +
+ "cast('0' as DECIMAL(36, 3)) as i4,\n" +
+ "cast('15.02' as DECIMAL(4, 2)) as i5)";
+ testBuilder()
+ .sqlQuery(query)
+ .ordered()
+ .baselineColumns("s1", "s2", "s3", "s4", "s5")
+ .baselineValues("999999999999999999999999999.9", "0.3",
+ "-1234567891234567891234567891234567.9", "0", "15")
+ .go();
+ }
+}
diff --git a/exec/java-exec/src/test/java/org/apache/drill/exec/physical/impl/TestDecimal.java b/exec/java-exec/src/test/java/org/apache/drill/exec/physical/impl/TestDecimal.java
index 1bdcda5c3..ff1edb932 100644
--- a/exec/java-exec/src/test/java/org/apache/drill/exec/physical/impl/TestDecimal.java
+++ b/exec/java-exec/src/test/java/org/apache/drill/exec/physical/impl/TestDecimal.java
@@ -20,10 +20,10 @@ package org.apache.drill.exec.physical.impl;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+import java.math.BigInteger;
import java.util.Iterator;
import java.util.List;
-import org.apache.drill.common.config.DrillConfig;
import org.apache.drill.common.util.DrillFileUtils;
import org.apache.drill.exec.client.DrillClient;
import org.apache.drill.exec.pop.PopUnitTestBase;
@@ -32,6 +32,7 @@ import org.apache.drill.exec.record.VectorWrapper;
import org.apache.drill.exec.rpc.user.QueryDataBatch;
import org.apache.drill.exec.server.Drillbit;
import org.apache.drill.exec.server.RemoteServiceSet;
+import org.apache.drill.exec.util.DecimalUtility;
import org.apache.drill.exec.vector.ValueVector;
import org.apache.drill.categories.SlowTest;
import org.junit.Test;
@@ -41,8 +42,7 @@ import com.google.common.io.Files;
import org.junit.experimental.categories.Category;
@Category({SlowTest.class})
-public class TestDecimal extends PopUnitTestBase{
- DrillConfig c = DrillConfig.create();
+public class TestDecimal extends PopUnitTestBase {
@Test
public void testSimpleDecimal() throws Exception {
@@ -314,4 +314,24 @@ public class TestDecimal extends PopUnitTestBase{
}
}
+ @Test
+ public void testGetMaxBytesSizeForPrecision() {
+ for (int i = 0; i < 10_000; i++) {
+ assertEquals(String.format("Bytes size does not match for precision %s", i),
+ getMaxBytesSizeForPrecisionFromBigInteger(i),
+ DecimalUtility.getMaxBytesSizeForPrecision(i));
+ }
+ }
+
+ private static int getMaxBytesSizeForPrecisionFromBigInteger(int precision) {
+ if (precision == 0) {
+ return 0;
+ }
+
+ StringBuilder sb = new StringBuilder("-");
+ for (int i = 0; i < precision; i++) {
+ sb.append(9);
+ }
+ return new BigInteger(sb.toString()).toByteArray().length;
+ }
}
diff --git a/exec/java-exec/src/test/java/org/apache/drill/exec/physical/impl/join/TestNestedLoopJoin.java b/exec/java-exec/src/test/java/org/apache/drill/exec/physical/impl/join/TestNestedLoopJoin.java
index 78f76d363..fb41df5e1 100644
--- a/exec/java-exec/src/test/java/org/apache/drill/exec/physical/impl/join/TestNestedLoopJoin.java
+++ b/exec/java-exec/src/test/java/org/apache/drill/exec/physical/impl/join/TestNestedLoopJoin.java
@@ -409,4 +409,30 @@ public class TestNestedLoopJoin extends JoinTestBase {
setSessionOption(ExecConstants.SLICE_TARGET, 100000);
}
}
+
+ @Test
+ public void testNlJoinWithStringsInCondition() throws Exception {
+ try {
+ test(DISABLE_NLJ_SCALAR);
+ test(DISABLE_JOIN_OPTIMIZATION);
+
+ final String query =
+ "select v.employee_id\n" +
+ "from cp.`employee.json` v\n" +
+ "left outer join cp.`employee.json` s\n" +
+ "on v.employee_id <> s.employee_id\n" +
+ "and (v.position_id <= '-1' or s.department_id > '5000')\n" +
+ "order by v.employee_id limit 1";
+
+ testBuilder()
+ .sqlQuery(query)
+ .unOrdered()
+ .baselineColumns("employee_id")
+ .baselineValues(1L)
+ .go();
+ } finally {
+ resetJoinOptions();
+ test(RESET_JOIN_OPTIMIZATION);
+ }
+ }
}
diff --git a/exec/java-exec/src/test/java/org/apache/drill/exec/physical/impl/writer/TestParquetWriter.java b/exec/java-exec/src/test/java/org/apache/drill/exec/physical/impl/writer/TestParquetWriter.java
index c359e69b6..c1dc643e8 100644
--- a/exec/java-exec/src/test/java/org/apache/drill/exec/physical/impl/writer/TestParquetWriter.java
+++ b/exec/java-exec/src/test/java/org/apache/drill/exec/physical/impl/writer/TestParquetWriter.java
@@ -19,11 +19,17 @@ package org.apache.drill.exec.physical.impl.writer;
import static org.apache.drill.exec.store.parquet.ParquetRecordWriter.DRILL_VERSION_PROPERTY;
import static org.apache.drill.test.TestBuilder.convertToLocalTimestamp;
+import static org.apache.parquet.format.converter.ParquetMetadataConverter.NO_FILTER;
import static org.apache.parquet.format.converter.ParquetMetadataConverter.SKIP_ROW_GROUPS;
+import static org.apache.parquet.schema.PrimitiveType.PrimitiveTypeName.BINARY;
+import static org.apache.parquet.schema.PrimitiveType.PrimitiveTypeName.FIXED_LEN_BYTE_ARRAY;
+import static org.apache.parquet.schema.PrimitiveType.PrimitiveTypeName.INT32;
+import static org.apache.parquet.schema.PrimitiveType.PrimitiveTypeName.INT64;
import static org.junit.Assert.assertEquals;
import java.io.File;
import java.io.FileWriter;
+import java.io.IOException;
import java.math.BigDecimal;
import java.nio.file.Paths;
import java.sql.Date;
@@ -35,6 +41,9 @@ import java.util.List;
import java.util.Map;
import com.google.common.base.Joiner;
+import com.google.common.collect.ImmutableList;
+import org.apache.calcite.util.Pair;
+import org.apache.drill.exec.util.JsonStringArrayList;
import org.apache.drill.test.BaseTestQuery;
import org.apache.drill.categories.ParquetTest;
import org.apache.drill.categories.SlowTest;
@@ -49,6 +58,9 @@ import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.parquet.hadoop.ParquetFileReader;
import org.apache.parquet.hadoop.metadata.ParquetMetadata;
+import org.apache.parquet.schema.MessageType;
+import org.apache.parquet.schema.OriginalType;
+import org.apache.parquet.schema.PrimitiveType;
import org.joda.time.DateTime;
import org.joda.time.Period;
import org.junit.AfterClass;
@@ -72,7 +84,7 @@ public class TestParquetWriter extends BaseTestQuery {
dirTestWatcher.copyResourceToRoot(Paths.get("parquet", "int96_dict_change"));
}
- static FileSystem fs;
+ private static FileSystem fs;
// Map storing a convenient name as well as the cast type necessary
// to produce it casting from a varchar
@@ -85,11 +97,11 @@ public class TestParquetWriter extends BaseTestQuery {
static {
allTypes.put("int", "int");
allTypes.put("bigint", "bigint");
- // TODO(DRILL-3367)
-// allTypes.put("decimal(9, 4)", "decimal9");
-// allTypes.put("decimal(18,9)", "decimal18");
-// allTypes.put("decimal(28, 14)", "decimal28sparse");
-// allTypes.put("decimal(38, 19)", "decimal38sparse");
+ allTypes.put("decimal(9, 4)", "decimal9");
+ allTypes.put("decimal(18,9)", "decimal18");
+ allTypes.put("decimal(28, 14)", "decimal28sparse");
+ allTypes.put("decimal(38, 19)", "decimal38sparse");
+ allTypes.put("decimal(38, 15)", "vardecimal");
allTypes.put("date", "date");
allTypes.put("timestamp", "timestamp");
allTypes.put("float", "float4");
@@ -126,8 +138,8 @@ public class TestParquetWriter extends BaseTestQuery {
}
@AfterClass
- public static void disableDecimalDataType() throws Exception {
- alterSession(PlannerSettings.ENABLE_DECIMAL_DATA_TYPE_KEY, false);
+ public static void disableDecimalDataType() {
+ resetSessionOption(PlannerSettings.ENABLE_DECIMAL_DATA_TYPE_KEY);
}
@Test
@@ -146,7 +158,7 @@ public class TestParquetWriter extends BaseTestQuery {
@Test
public void testLargeFooter() throws Exception {
- StringBuffer sb = new StringBuffer();
+ StringBuilder sb = new StringBuilder();
// create a JSON document with a lot of columns
sb.append("{");
final int numCols = 1000;
@@ -155,13 +167,13 @@ public class TestParquetWriter extends BaseTestQuery {
for (int i = 0 ; i < numCols - 1; i++) {
sb.append(String.format("\"col_%d\" : 100,", i));
colNames[i] = "col_" + i;
- values[i] = 100l;
+ values[i] = 100L;
}
// add one column without a comma after it
sb.append(String.format("\"col_%d\" : 100", numCols - 1));
sb.append("}");
colNames[numCols - 1] = "col_" + (numCols - 1);
- values[numCols - 1] = 100l;
+ values[numCols - 1] = 100L;
String path = "test";
File pathDir = dirTestWatcher.makeRootSubDir(Paths.get(path));
@@ -1002,5 +1014,295 @@ public class TestParquetWriter extends BaseTestQuery {
resetSessionOption(ExecConstants.PARQUET_READER_INT96_AS_TIMESTAMP);
}
}
-}
+ @Test
+ public void testWriteDecimalIntBigIntFixedLen() throws Exception {
+ String tableName = "decimalIntBigIntFixedLen";
+ try {
+ alterSession(ExecConstants.PARQUET_WRITER_LOGICAL_TYPE_FOR_DECIMALS, FIXED_LEN_BYTE_ARRAY.name());
+ test(
+ "create table dfs.tmp.%s as\n" +
+ "select cast('123456.789' as decimal(9, 3)) as decInt,\n" +
+ "cast('123456.789123456789' as decimal(18, 12)) as decBigInt,\n" +
+ "cast('123456.789123456789' as decimal(19, 12)) as fixedLen", tableName);
+ checkTableTypes(tableName,
+ ImmutableList.of(
+ Pair.of("decInt", INT32),
+ Pair.of("decBigInt", INT64),
+ Pair.of("fixedLen", FIXED_LEN_BYTE_ARRAY)),
+ true);
+ testBuilder()
+ .sqlQuery("select * from dfs.tmp.%s", tableName)
+ .unOrdered()
+ .baselineColumns("decInt", "decBigInt", "fixedLen")
+ .baselineValues(new BigDecimal("123456.789"),
+ new BigDecimal("123456.789123456789"),
+ new BigDecimal("123456.789123456789"))
+ .go();
+ } finally {
+ resetSessionOption(ExecConstants.PARQUET_WRITER_USE_PRIMITIVE_TYPES_FOR_DECIMALS);
+ resetSessionOption(ExecConstants.PARQUET_WRITER_LOGICAL_TYPE_FOR_DECIMALS);
+ test("drop table if exists dfs.tmp.%s", tableName);
+ }
+ }
+
+ @Test
+ public void testWriteDecimalIntBigIntBinary() throws Exception {
+ String tableName = "decimalIntBigIntBinary";
+ try {
+ alterSession(ExecConstants.PARQUET_WRITER_USE_PRIMITIVE_TYPES_FOR_DECIMALS, true);
+ alterSession(ExecConstants.PARQUET_WRITER_LOGICAL_TYPE_FOR_DECIMALS, BINARY.name());
+ test(
+ "create table dfs.tmp.%s as\n" +
+ "select cast('123456.789' as decimal(9, 3)) as decInt,\n" +
+ "cast('123456.789123456789' as decimal(18, 12)) as decBigInt,\n" +
+ "cast('123456.789123456789' as decimal(19, 12)) as binCol", tableName);
+ checkTableTypes(tableName,
+ ImmutableList.of(
+ Pair.of("decInt", INT32),
+ Pair.of("decBigInt", INT64),
+ Pair.of("binCol", BINARY)),
+ true);
+ testBuilder()
+ .sqlQuery("select * from dfs.tmp.%s", tableName)
+ .unOrdered()
+ .baselineColumns("decInt", "decBigInt", "binCol")
+ .baselineValues(new BigDecimal("123456.789"),
+ new BigDecimal("123456.789123456789"),
+ new BigDecimal("123456.789123456789"))
+ .go();
+ } finally {
+ resetSessionOption(ExecConstants.PARQUET_WRITER_USE_PRIMITIVE_TYPES_FOR_DECIMALS);
+ resetSessionOption(ExecConstants.PARQUET_WRITER_LOGICAL_TYPE_FOR_DECIMALS);
+ test("drop table if exists dfs.tmp.%s", tableName);
+ }
+ }
+
+ @Test
+ public void testWriteDecimalFixedLenOnly() throws Exception {
+ String tableName = "decimalFixedLenOnly";
+ try {
+ alterSession(ExecConstants.PARQUET_WRITER_USE_PRIMITIVE_TYPES_FOR_DECIMALS, false);
+ alterSession(ExecConstants.PARQUET_WRITER_LOGICAL_TYPE_FOR_DECIMALS, FIXED_LEN_BYTE_ARRAY.name());
+ test(
+ "create table dfs.tmp.%s as\n" +
+ "select cast('123456.789' as decimal(9, 3)) as decInt,\n" +
+ "cast('123456.789123456789' as decimal(18, 12)) as decBigInt,\n" +
+ "cast('123456.789123456789' as decimal(19, 12)) as fixedLen", tableName);
+ checkTableTypes(tableName,
+ ImmutableList.of(
+ Pair.of("decInt", FIXED_LEN_BYTE_ARRAY),
+ Pair.of("decBigInt", FIXED_LEN_BYTE_ARRAY),
+ Pair.of("fixedLen", FIXED_LEN_BYTE_ARRAY)),
+ true);
+ testBuilder()
+ .sqlQuery("select * from dfs.tmp.%s", tableName)
+ .unOrdered()
+ .baselineColumns("decInt", "decBigInt", "fixedLen")
+ .baselineValues(new BigDecimal("123456.789"),
+ new BigDecimal("123456.789123456789"),
+ new BigDecimal("123456.789123456789"))
+ .go();
+ } finally {
+ resetSessionOption(ExecConstants.PARQUET_WRITER_USE_PRIMITIVE_TYPES_FOR_DECIMALS);
+ resetSessionOption(ExecConstants.PARQUET_WRITER_LOGICAL_TYPE_FOR_DECIMALS);
+ test("drop table if exists dfs.tmp.%s", tableName);
+ }
+ }
+
+ @Test
+ public void testWriteDecimalBinaryOnly() throws Exception {
+ String tableName = "decimalBinaryOnly";
+ try {
+ alterSession(ExecConstants.PARQUET_WRITER_USE_PRIMITIVE_TYPES_FOR_DECIMALS, false);
+ alterSession(ExecConstants.PARQUET_WRITER_LOGICAL_TYPE_FOR_DECIMALS, BINARY.name());
+ test(
+ "create table dfs.tmp.%s as\n" +
+ "select cast('123456.789' as decimal(9, 3)) as decInt,\n" +
+ "cast('123456.789123456789' as decimal(18, 12)) as decBigInt,\n" +
+ "cast('123456.789123456789' as decimal(19, 12)) as binCol", tableName);
+ checkTableTypes(tableName,
+ ImmutableList.of(
+ Pair.of("decInt", BINARY),
+ Pair.of("decBigInt", BINARY),
+ Pair.of("binCol", BINARY)),
+ true);
+ testBuilder()
+ .sqlQuery("select * from dfs.tmp.%s", tableName)
+ .unOrdered()
+ .baselineColumns("decInt", "decBigInt", "binCol")
+ .baselineValues(new BigDecimal("123456.789"),
+ new BigDecimal("123456.789123456789"),
+ new BigDecimal("123456.789123456789"))
+ .go();
+ } finally {
+ resetSessionOption(ExecConstants.PARQUET_WRITER_USE_PRIMITIVE_TYPES_FOR_DECIMALS);
+ resetSessionOption(ExecConstants.PARQUET_WRITER_LOGICAL_TYPE_FOR_DECIMALS);
+ test("drop table if exists dfs.tmp.%s", tableName);
+ }
+ }
+
+ @Test
+ public void testWriteDecimalIntBigIntRepeated() throws Exception {
+ String tableName = "decimalIntBigIntRepeated";
+
+ JsonStringArrayList<BigDecimal> ints = new JsonStringArrayList<>();
+ ints.add(new BigDecimal("999999.999"));
+ ints.add(new BigDecimal("-999999.999"));
+ ints.add(new BigDecimal("0.000"));
+
+ JsonStringArrayList<BigDecimal> longs = new JsonStringArrayList<>();
+ longs.add(new BigDecimal("999999999.999999999"));
+ longs.add(new BigDecimal("-999999999.999999999"));
+ longs.add(new BigDecimal("0.000000000"));
+
+ JsonStringArrayList<BigDecimal> fixedLen = new JsonStringArrayList<>();
+ fixedLen.add(new BigDecimal("999999999999.999999"));
+ fixedLen.add(new BigDecimal("-999999999999.999999"));
+ fixedLen.add(new BigDecimal("0.000000"));
+
+ try {
+ alterSession(ExecConstants.PARQUET_WRITER_USE_PRIMITIVE_TYPES_FOR_DECIMALS, true);
+ alterSession(ExecConstants.PARQUET_WRITER_LOGICAL_TYPE_FOR_DECIMALS, FIXED_LEN_BYTE_ARRAY.name());
+ test(
+ "create table dfs.tmp.%s as\n" +
+ "select * from cp.`parquet/repeatedIntLondFixedLenBinaryDecimal.parquet`", tableName);
+ checkTableTypes(tableName,
+ ImmutableList.of(
+ Pair.of("decimal_int32", INT32),
+ Pair.of("decimal_int64", INT64),
+ Pair.of("decimal_fixedLen", INT64),
+ Pair.of("decimal_binary", INT64)),
+ true);
+ testBuilder()
+ .sqlQuery("select * from dfs.tmp.%s", tableName)
+ .unOrdered()
+ .baselineColumns("decimal_int32", "decimal_int64", "decimal_fixedLen", "decimal_binary")
+ .baselineValues(ints, longs, fixedLen, fixedLen)
+ .go();
+ } finally {
+ resetSessionOption(ExecConstants.PARQUET_WRITER_USE_PRIMITIVE_TYPES_FOR_DECIMALS);
+ resetSessionOption(ExecConstants.PARQUET_WRITER_LOGICAL_TYPE_FOR_DECIMALS);
+ test("drop table if exists dfs.tmp.%s", tableName);
+ }
+ }
+
+ @Test
+ public void testWriteDecimalFixedLenRepeated() throws Exception {
+ String tableName = "decimalFixedLenRepeated";
+
+ JsonStringArrayList<BigDecimal> ints = new JsonStringArrayList<>();
+ ints.add(new BigDecimal("999999.999"));
+ ints.add(new BigDecimal("-999999.999"));
+ ints.add(new BigDecimal("0.000"));
+
+ JsonStringArrayList<BigDecimal> longs = new JsonStringArrayList<>();
+ longs.add(new BigDecimal("999999999.999999999"));
+ longs.add(new BigDecimal("-999999999.999999999"));
+ longs.add(new BigDecimal("0.000000000"));
+
+ JsonStringArrayList<BigDecimal> fixedLen = new JsonStringArrayList<>();
+ fixedLen.add(new BigDecimal("999999999999.999999"));
+ fixedLen.add(new BigDecimal("-999999999999.999999"));
+ fixedLen.add(new BigDecimal("0.000000"));
+
+ try {
+ alterSession(ExecConstants.PARQUET_WRITER_USE_PRIMITIVE_TYPES_FOR_DECIMALS, false);
+ alterSession(ExecConstants.PARQUET_WRITER_LOGICAL_TYPE_FOR_DECIMALS, FIXED_LEN_BYTE_ARRAY.name());
+ test(
+ "create table dfs.tmp.%s as\n" +
+ "select * from cp.`parquet/repeatedIntLondFixedLenBinaryDecimal.parquet`", tableName);
+ checkTableTypes(tableName,
+ ImmutableList.of(
+ Pair.of("decimal_int32", FIXED_LEN_BYTE_ARRAY),
+ Pair.of("decimal_int64", FIXED_LEN_BYTE_ARRAY),
+ Pair.of("decimal_fixedLen", FIXED_LEN_BYTE_ARRAY),
+ Pair.of("decimal_binary", FIXED_LEN_BYTE_ARRAY)),
+ true);
+ testBuilder()
+ .sqlQuery("select * from dfs.tmp.%s", tableName)
+ .unOrdered()
+ .baselineColumns("decimal_int32", "decimal_int64", "decimal_fixedLen", "decimal_binary")
+ .baselineValues(ints, longs, fixedLen, fixedLen)
+ .go();
+ } finally {
+ resetSessionOption(ExecConstants.PARQUET_WRITER_USE_PRIMITIVE_TYPES_FOR_DECIMALS);
+ resetSessionOption(ExecConstants.PARQUET_WRITER_LOGICAL_TYPE_FOR_DECIMALS);
+ test("drop table if exists dfs.tmp.%s", tableName);
+ }
+ }
+
+ @Test
+ public void testWriteDecimalBinaryRepeated() throws Exception {
+ String tableName = "decimalBinaryRepeated";
+
+ JsonStringArrayList<BigDecimal> ints = new JsonStringArrayList<>();
+ ints.add(new BigDecimal("999999.999"));
+ ints.add(new BigDecimal("-999999.999"));
+ ints.add(new BigDecimal("0.000"));
+
+ JsonStringArrayList<BigDecimal> longs = new JsonStringArrayList<>();
+ longs.add(new BigDecimal("999999999.999999999"));
+ longs.add(new BigDecimal("-999999999.999999999"));
+ longs.add(new BigDecimal("0.000000000"));
+
+ JsonStringArrayList<BigDecimal> fixedLen = new JsonStringArrayList<>();
+ fixedLen.add(new BigDecimal("999999999999.999999"));
+ fixedLen.add(new BigDecimal("-999999999999.999999"));
+ fixedLen.add(new BigDecimal("0.000000"));
+ try {
+ alterSession(ExecConstants.PARQUET_WRITER_USE_PRIMITIVE_TYPES_FOR_DECIMALS, false);
+ alterSession(ExecConstants.PARQUET_WRITER_LOGICAL_TYPE_FOR_DECIMALS, BINARY.name());
+ test(
+ "create table dfs.tmp.%s as\n" +
+ "select * from cp.`parquet/repeatedIntLondFixedLenBinaryDecimal.parquet`", tableName);
+ checkTableTypes(tableName,
+ ImmutableList.of(
+ Pair.of("decimal_int32", BINARY),
+ Pair.of("decimal_int64", BINARY),
+ Pair.of("decimal_fixedLen", BINARY),
+ Pair.of("decimal_binary", BINARY)),
+ true);
+ testBuilder()
+ .sqlQuery("select * from dfs.tmp.%s", tableName)
+ .unOrdered()
+ .baselineColumns("decimal_int32", "decimal_int64", "decimal_fixedLen", "decimal_binary")
+ .baselineValues(ints, longs, fixedLen, fixedLen)
+ .go();
+ } finally {
+ resetSessionOption(ExecConstants.PARQUET_WRITER_USE_PRIMITIVE_TYPES_FOR_DECIMALS);
+ resetSessionOption(ExecConstants.PARQUET_WRITER_LOGICAL_TYPE_FOR_DECIMALS);
+ test("drop table if exists dfs.tmp.%s", tableName);
+ }
+ }
+
+ /**
+ * Checks that specified parquet table contains specified columns with specified types.
+ *
+ * @param tableName name of the table that should be checked.
+ * @param columnsToCheck pair of column name and column type that should be checked in the table.
+ * @param isDecimalType is should be specified columns annotated ad DECIMAL.
+ * @throws IOException If table file was not found.
+ */
+ private void checkTableTypes(String tableName,
+ List<Pair<String, PrimitiveType.PrimitiveTypeName>> columnsToCheck,
+ boolean isDecimalType) throws IOException {
+ MessageType schema = ParquetFileReader.readFooter(
+ new Configuration(),
+ new Path(Paths.get(dirTestWatcher.getDfsTestTmpDir().getPath(), tableName, "0_0_0.parquet").toUri().getPath()),
+ NO_FILTER).getFileMetaData().getSchema();
+
+ for (Pair<String, PrimitiveType.PrimitiveTypeName> nameType : columnsToCheck) {
+ assertEquals(
+ String.format("Table %s does not contain column %s with type %s",
+ tableName, nameType.getKey(), nameType.getValue()),
+ nameType.getValue(),
+ schema.getType(nameType.getKey()).asPrimitiveType().getPrimitiveTypeName());
+
+ assertEquals(
+ String.format("Table %s %s column %s with DECIMAL type", tableName,
+ isDecimalType ? "does not contain" : "contains unexpected", nameType.getKey()),
+ isDecimalType, schema.getType(nameType.getKey()).getOriginalType() == OriginalType.DECIMAL);
+ }
+ }
+}
diff --git a/exec/java-exec/src/test/java/org/apache/drill/exec/physical/impl/xsort/managed/TestCopier.java b/exec/java-exec/src/test/java/org/apache/drill/exec/physical/impl/xsort/managed/TestCopier.java
index 6de16bfd1..3138eede5 100644
--- a/exec/java-exec/src/test/java/org/apache/drill/exec/physical/impl/xsort/managed/TestCopier.java
+++ b/exec/java-exec/src/test/java/org/apache/drill/exec/physical/impl/xsort/managed/TestCopier.java
@@ -55,7 +55,7 @@ import org.junit.experimental.categories.Category;
public class TestCopier extends SubOperatorTest {
@Test
- public void testEmptyInput() throws Exception {
+ public void testEmptyInput() {
BatchSchema schema = SortTestUtilities.nonNullSchema();
List<BatchGroup> batches = new ArrayList<>();
Sort popConfig = SortTestUtilities.makeCopierConfig(Ordering.ORDER_ASC, Ordering.NULLS_UNSPECIFIED);
@@ -323,8 +323,7 @@ public class TestCopier extends SubOperatorTest {
runTypeTest(fixture, MinorType.BIGINT);
runTypeTest(fixture, MinorType.FLOAT4);
runTypeTest(fixture, MinorType.FLOAT8);
- runTypeTest(fixture, MinorType.DECIMAL9);
- runTypeTest(fixture, MinorType.DECIMAL18);
+ runTypeTest(fixture, MinorType.VARDECIMAL);
runTypeTest(fixture, MinorType.VARCHAR);
runTypeTest(fixture, MinorType.VARBINARY);
runTypeTest(fixture, MinorType.DATE);
diff --git a/exec/java-exec/src/test/java/org/apache/drill/exec/physical/impl/xsort/managed/TestSorter.java b/exec/java-exec/src/test/java/org/apache/drill/exec/physical/impl/xsort/managed/TestSorter.java
index 49667ab81..88a7b9909 100644
--- a/exec/java-exec/src/test/java/org/apache/drill/exec/physical/impl/xsort/managed/TestSorter.java
+++ b/exec/java-exec/src/test/java/org/apache/drill/exec/physical/impl/xsort/managed/TestSorter.java
@@ -493,10 +493,11 @@ public class TestSorter extends DrillTest {
// tester1.test(MinorType.UINT4); DRILL-5329
tester.test(MinorType.BIGINT);
// tester1.test(MinorType.UINT8); DRILL-5329
- tester.test(MinorType.FLOAT4);
- tester.test(MinorType.FLOAT8);
- tester.test(MinorType.DECIMAL9);
- tester.test(MinorType.DECIMAL18);
+ tester.test(MinorType.FLOAT4);
+ tester.test(MinorType.FLOAT8);
+ tester.test(MinorType.VARDECIMAL);
+// tester1.test(MinorType.DECIMAL9);
+// tester1.test(MinorType.DECIMAL18);
// tester1.test(MinorType.DECIMAL28SPARSE); DRILL-5329
// tester1.test(MinorType.DECIMAL38SPARSE); DRILL-5329
// tester1.test(MinorType.DECIMAL28DENSE); No writer
diff --git a/exec/java-exec/src/test/java/org/apache/drill/exec/planner/logical/TestCaseNullableTypes.java b/exec/java-exec/src/test/java/org/apache/drill/exec/planner/logical/TestCaseNullableTypes.java
index f18821bd0..b8c727558 100644
--- a/exec/java-exec/src/test/java/org/apache/drill/exec/planner/logical/TestCaseNullableTypes.java
+++ b/exec/java-exec/src/test/java/org/apache/drill/exec/planner/logical/TestCaseNullableTypes.java
@@ -17,6 +17,7 @@
*/
package org.apache.drill.exec.planner.logical;
+import org.apache.drill.exec.planner.physical.PlannerSettings;
import org.apache.drill.test.BaseTestQuery;
import org.apache.drill.categories.SqlTest;
import org.joda.time.DateTime;
@@ -24,6 +25,8 @@ import org.joda.time.format.DateTimeFormat;
import org.junit.Test;
import org.junit.experimental.categories.Category;
+import java.math.BigDecimal;
+
/**
* DRILL-4906
* Tests for handling nullable types in CASE function
@@ -143,4 +146,19 @@ public class TestCaseNullableTypes extends BaseTestQuery {
.baselineValues(date)
.go();
}
+
+ @Test
+ public void testCaseNullableTypesDecimal() throws Exception {
+ try {
+ alterSession(PlannerSettings.ENABLE_DECIMAL_DATA_TYPE_KEY, true);
+ testBuilder()
+ .sqlQuery("select (case when (false) then null else cast(0.1 as decimal(2, 1)) end) res1")
+ .ordered()
+ .baselineColumns("res1")
+ .baselineValues(new BigDecimal("0.1"))
+ .go();
+ } finally {
+ resetSessionOption(PlannerSettings.ENABLE_DECIMAL_DATA_TYPE_KEY);
+ }
+ }
}
diff --git a/exec/java-exec/src/test/java/org/apache/drill/exec/store/avro/AvroFormatTest.java b/exec/java-exec/src/test/java/org/apache/drill/exec/store/avro/AvroFormatTest.java
index 930c41b10..466a3f123 100644
--- a/exec/java-exec/src/test/java/org/apache/drill/exec/store/avro/AvroFormatTest.java
+++ b/exec/java-exec/src/test/java/org/apache/drill/exec/store/avro/AvroFormatTest.java
@@ -18,17 +18,28 @@
package org.apache.drill.exec.store.avro;
import com.google.common.collect.Lists;
+import mockit.integration.junit4.JMockit;
+import org.apache.avro.specific.TestRecordWithLogicalTypes;
import org.apache.commons.io.FileUtils;
import org.apache.drill.exec.ExecConstants;
+import org.apache.drill.exec.ExecTest;
+import org.apache.drill.exec.expr.fn.impl.DateUtility;
+import org.apache.drill.exec.planner.physical.PlannerSettings;
+import org.apache.drill.exec.work.ExecErrorConstants;
import org.apache.drill.test.BaseTestQuery;
import org.apache.drill.test.TestBuilder;
import org.apache.drill.common.exceptions.UserException;
import org.apache.drill.common.exceptions.UserRemoteException;
import org.apache.drill.exec.util.JsonStringHashMap;
+import org.joda.time.DateTime;
+import org.joda.time.LocalDate;
+import org.joda.time.LocalTime;
import org.junit.Assert;
import org.junit.Test;
+import org.junit.runner.RunWith;
import java.io.File;
+import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
@@ -46,11 +57,13 @@ import static org.apache.drill.exec.store.avro.AvroTestUtil.generateUnionNestedA
import static org.apache.drill.exec.store.avro.AvroTestUtil.generateUnionNestedSchema_withNullValues;
import static org.apache.drill.exec.store.avro.AvroTestUtil.generateUnionSchema_WithNonNullValues;
import static org.apache.drill.exec.store.avro.AvroTestUtil.generateUnionSchema_WithNullValues;
+import static org.apache.drill.exec.store.avro.AvroTestUtil.write;
import static org.apache.drill.test.TestBuilder.listOf;
/**
* Unit tests for Avro record reader.
*/
+@RunWith(JMockit.class)
public class AvroFormatTest extends BaseTestQuery {
// XXX
@@ -294,6 +307,65 @@ public class AvroFormatTest extends BaseTestQuery {
}
@Test
+ public void testAvroTableWithLogicalTypesDecimal() throws Exception {
+ ExecTest.mockUtcDateTimeZone();
+ DateTime date = DateUtility.getDateTimeFormatter().parseDateTime("2018-02-03");
+ DateTime time = DateUtility.getTimeFormatter().parseDateTime("19:25:03");
+ DateTime timestamp = DateUtility.getDateTimeFormatter().parseDateTime("2018-02-03 19:25:03");
+ BigDecimal bigDecimal = new BigDecimal("123.45");
+
+ TestRecordWithLogicalTypes record = new TestRecordWithLogicalTypes(
+ true,
+ 34,
+ 35L,
+ 3.14F,
+ 3019.34,
+ "abc",
+ timestamp.toLocalDate(),
+ timestamp.toLocalTime(),
+ timestamp,
+ bigDecimal
+ );
+
+ File data = write(TestRecordWithLogicalTypes.getClassSchema(), record);
+
+ final String query = "select * from dfs.`%s`";
+
+ testBuilder()
+ .sqlQuery(query, data.getName())
+ .unOrdered()
+ .baselineColumns("b", "i32", "i64", "f32", "f64", "s", "d", "t", "ts", "dec")
+ .baselineValues(true, 34, 35L, 3.14F, 3019.34, "abc", date, time, timestamp, bigDecimal)
+ .go();
+ }
+
+ @Test
+ public void testAvroWithDisabledDecimalType() throws Exception {
+ TestRecordWithLogicalTypes record = new TestRecordWithLogicalTypes(
+ true,
+ 34,
+ 35L,
+ 3.14F,
+ 3019.34,
+ "abc",
+ LocalDate.now(),
+ LocalTime.now(),
+ DateTime.now(),
+ new BigDecimal("123.45")
+ );
+
+ File data = write(TestRecordWithLogicalTypes.getClassSchema(), record);
+ final String query = String.format("select * from dfs.`%s`", data.getName());
+
+ try {
+ alterSession(PlannerSettings.ENABLE_DECIMAL_DATA_TYPE_KEY, false);
+ errorMsgTestHelper(query, ExecErrorConstants.DECIMAL_DISABLE_ERR_MSG);
+ } finally {
+ resetSessionOption(PlannerSettings.ENABLE_DECIMAL_DATA_TYPE_KEY);
+ }
+ }
+
+ @Test
public void testSimpleArraySchema_NoNullValues() throws Exception {
final String file = generateSimpleArraySchema_NoNullValues().getFileName();
final String sql = "select a_string, c_string_array[0], e_float_array[2] from dfs.`%s`";
diff --git a/exec/java-exec/src/test/java/org/apache/drill/exec/store/avro/AvroTestUtil.java b/exec/java-exec/src/test/java/org/apache/drill/exec/store/avro/AvroTestUtil.java
index 11b3d3902..c85cdf678 100644
--- a/exec/java-exec/src/test/java/org/apache/drill/exec/store/avro/AvroTestUtil.java
+++ b/exec/java-exec/src/test/java/org/apache/drill/exec/store/avro/AvroTestUtil.java
@@ -38,6 +38,9 @@ import org.apache.avro.generic.GenericData;
import org.apache.avro.generic.GenericDatumWriter;
import org.apache.avro.generic.GenericRecord;
+import org.apache.avro.io.DatumWriter;
+import org.apache.avro.specific.SpecificData;
+import org.apache.avro.specific.SpecificRecord;
import org.apache.drill.exec.util.JsonStringArrayList;
import org.apache.drill.exec.util.JsonStringHashMap;
import org.apache.drill.exec.util.Text;
@@ -716,4 +719,27 @@ public class AvroTestUtil {
return record;
}
+
+ /**
+ * Creates Avro table with specified schema and specified data
+ * @param schema table schema
+ * @param data table data
+ * @param <D> record type
+ * @return file with newly created Avro table.
+ * @throws IOException if an error is appeared during creation or filling the file.
+ */
+ public static <D extends SpecificRecord> File write(Schema schema, D... data) throws IOException {
+ File file = File.createTempFile("avro-primitive-test", ".avro", BaseTestQuery.dirTestWatcher.getRootDir());
+
+ DatumWriter writer = SpecificData.get().createDatumWriter(schema);
+
+ try (DataFileWriter<D> fileWriter = new DataFileWriter<>(writer)) {
+ fileWriter.create(schema, file);
+ for (D datum : data) {
+ fileWriter.append(datum);
+ }
+ }
+
+ return file;
+ }
}
diff --git a/exec/java-exec/src/test/java/org/apache/drill/exec/store/parquet/TestFixedlenDecimal.java b/exec/java-exec/src/test/java/org/apache/drill/exec/store/parquet/TestFixedlenDecimal.java
index e6d7c10ef..678930c7d 100644
--- a/exec/java-exec/src/test/java/org/apache/drill/exec/store/parquet/TestFixedlenDecimal.java
+++ b/exec/java-exec/src/test/java/org/apache/drill/exec/store/parquet/TestFixedlenDecimal.java
@@ -20,16 +20,23 @@ package org.apache.drill.exec.store.parquet;
import org.apache.drill.categories.UnlikelyTest;
import org.apache.drill.test.BaseTestQuery;
import org.apache.drill.exec.planner.physical.PlannerSettings;
+import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.experimental.categories.Category;
@Category({UnlikelyTest.class})
public class TestFixedlenDecimal extends BaseTestQuery {
- // enable decimal data type
+
+
@BeforeClass
- public static void enableDecimalDataType() throws Exception {
- test(String.format("alter session set `%s` = true", PlannerSettings.ENABLE_DECIMAL_DATA_TYPE_KEY));
+ public static void enableDecimalDataType() {
+ setSessionOption(PlannerSettings.ENABLE_DECIMAL_DATA_TYPE_KEY, true);
+ }
+
+ @AfterClass
+ public static void disableDecimalDataType() {
+ resetSessionOption(PlannerSettings.ENABLE_DECIMAL_DATA_TYPE_KEY);
}
private static final String DATAFILE = "cp.`parquet/fixedlenDecimal.parquet`";
@@ -41,8 +48,7 @@ public class TestFixedlenDecimal extends BaseTestQuery {
.unOrdered()
.baselineColumns("c")
.baselineValues(1L)
- .build()
- .run();
+ .go();
}
@Test
@@ -52,8 +58,7 @@ public class TestFixedlenDecimal extends BaseTestQuery {
.unOrdered()
.baselineColumns("c")
.baselineValues(106L)
- .build()
- .run();
+ .go();
}
@Test
@@ -63,8 +68,7 @@ public class TestFixedlenDecimal extends BaseTestQuery {
.unOrdered()
.baselineColumns("c")
.baselineValues(80L)
- .build()
- .run();
+ .go();
}
@Test
@@ -74,7 +78,6 @@ public class TestFixedlenDecimal extends BaseTestQuery {
.unOrdered()
.baselineColumns("c")
.baselineValues(80L)
- .build()
- .run();
+ .go();
}
}
diff --git a/exec/java-exec/src/test/java/org/apache/drill/exec/store/parquet/TestParquetComplex.java b/exec/java-exec/src/test/java/org/apache/drill/exec/store/parquet/TestParquetComplex.java
index 8252834d2..a7653b841 100644
--- a/exec/java-exec/src/test/java/org/apache/drill/exec/store/parquet/TestParquetComplex.java
+++ b/exec/java-exec/src/test/java/org/apache/drill/exec/store/parquet/TestParquetComplex.java
@@ -17,12 +17,14 @@
*/
package org.apache.drill.exec.store.parquet;
+import org.apache.drill.exec.util.JsonStringArrayList;
import org.apache.drill.test.BaseTestQuery;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.Period;
import org.junit.Test;
+import java.math.BigDecimal;
import java.util.Arrays;
import static org.apache.drill.test.TestBuilder.mapOf;
@@ -202,10 +204,10 @@ public class TestParquetComplex extends BaseTestQuery {
@Test //DRILL-5971
public void testComplexLogicalIntTypes() throws Exception {
- String query = String.format("select t.complextype as complextype, " +
+ String query = "select t.complextype as complextype, " +
"t.uint_64 as uint_64, t.uint_32 as uint_32, t.uint_16 as uint_16, t.uint_8 as uint_8, " +
"t.int_64 as int_64, t.int_32 as int_32, t.int_16 as int_16, t.int_8 as int_8 " +
- "from cp.`store/parquet/complex/logical_int_complex.parquet` t" );
+ "from cp.`store/parquet/complex/logical_int_complex.parquet` t";
String[] columns = {"complextype", "uint_64", "uint_32", "uint_16", "uint_8", "int_64", "int_32", "int_16", "int_8" };
testBuilder()
.sqlQuery(query)
@@ -225,7 +227,7 @@ public class TestParquetComplex extends BaseTestQuery {
byte[] bytesOnes = new byte[12];
byte[] bytesZeros = new byte[12];
Arrays.fill(bytesOnes, (byte) 1);
- String query = String.format(
+ String query =
" select " +
" t.rowKey as rowKey, " +
" t.StringTypes._UTF8 as _UTF8, " +
@@ -247,8 +249,7 @@ public class TestParquetComplex extends BaseTestQuery {
" t.NumericTypes.Int96._INT96_RAW as _INT96_RAW " +
" from " +
" cp.`store/parquet/complex/parquet_logical_types_complex.parquet` t " +
- " order by t.rowKey "
- );
+ " order by t.rowKey ";
String[] columns = {
"rowKey " ,
"_UTF8" ,
@@ -300,7 +301,7 @@ public class TestParquetComplex extends BaseTestQuery {
byte[] bytesOnes = new byte[12];
byte[] bytesZeros = new byte[12];
Arrays.fill(bytesOnes, (byte) 1);
- String query = String.format(
+ String query =
" select " +
" t.rowKey as rowKey, " +
" t.StringTypes._UTF8 as _UTF8, " +
@@ -322,8 +323,7 @@ public class TestParquetComplex extends BaseTestQuery {
" t.NumericTypes.Int96._INT96_RAW as _INT96_RAW " +
" from " +
" cp.`store/parquet/complex/parquet_logical_types_complex_nullable.parquet` t " +
- " order by t.rowKey "
- );
+ " order by t.rowKey ";
String[] columns = {
"rowKey " ,
"_UTF8" ,
@@ -370,4 +370,29 @@ public class TestParquetComplex extends BaseTestQuery {
.build().run();
}
+ @Test
+ public void testReadRepeatedDecimals() throws Exception {
+
+ JsonStringArrayList<BigDecimal> ints = new JsonStringArrayList<>();
+ ints.add(new BigDecimal("999999.999"));
+ ints.add(new BigDecimal("-999999.999"));
+ ints.add(new BigDecimal("0.000"));
+
+ JsonStringArrayList<BigDecimal> longs = new JsonStringArrayList<>();
+ longs.add(new BigDecimal("999999999.999999999"));
+ longs.add(new BigDecimal("-999999999.999999999"));
+ longs.add(new BigDecimal("0.000000000"));
+
+ JsonStringArrayList<BigDecimal> fixedLen = new JsonStringArrayList<>();
+ fixedLen.add(new BigDecimal("999999999999.999999"));
+ fixedLen.add(new BigDecimal("-999999999999.999999"));
+ fixedLen.add(new BigDecimal("0.000000"));
+
+ testBuilder()
+ .sqlQuery("select * from cp.`parquet/repeatedIntLondFixedLenBinaryDecimal.parquet`")
+ .unOrdered()
+ .baselineColumns("decimal_int32", "decimal_int64", "decimal_fixedLen", "decimal_binary")
+ .baselineValues(ints, longs, fixedLen, fixedLen)
+ .go();
+ }
}
diff --git a/exec/java-exec/src/test/java/org/apache/drill/exec/store/parquet/TestVarlenDecimal.java b/exec/java-exec/src/test/java/org/apache/drill/exec/store/parquet/TestVarlenDecimal.java
index 4eda21a7e..eb5c900c3 100644
--- a/exec/java-exec/src/test/java/org/apache/drill/exec/store/parquet/TestVarlenDecimal.java
+++ b/exec/java-exec/src/test/java/org/apache/drill/exec/store/parquet/TestVarlenDecimal.java
@@ -1,4 +1,4 @@
-/**
+/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
@@ -17,61 +17,126 @@
*/
package org.apache.drill.exec.store.parquet;
+import org.apache.commons.io.FileUtils;
+import org.apache.drill.exec.ExecConstants;
import org.apache.drill.test.BaseTestQuery;
import org.apache.drill.exec.planner.physical.PlannerSettings;
-import org.apache.drill.exec.proto.UserBitShared;
+import org.hamcrest.CoreMatchers;
+import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.AfterClass;
import org.junit.Test;
+import java.math.BigDecimal;
+import java.nio.file.Paths;
+
public class TestVarlenDecimal extends BaseTestQuery {
- // enable decimal data type
+
@BeforeClass
- public static void enableDecimalDataType() throws Exception {
- test(String.format("alter session set `%s` = true", PlannerSettings.ENABLE_DECIMAL_DATA_TYPE_KEY));
+ public static void enableDecimalDataType() {
+ setSessionOption(PlannerSettings.ENABLE_DECIMAL_DATA_TYPE_KEY, true);
}
- // disable decimal data type
@AfterClass
- public static void disableDecimalDataType() throws Exception {
- test(String.format("alter session set `%s` = false", PlannerSettings.ENABLE_DECIMAL_DATA_TYPE_KEY));
+ public static void disableDecimalDataType() {
+ resetSessionOption(PlannerSettings.ENABLE_DECIMAL_DATA_TYPE_KEY);
}
private static final String DATAFILE = "cp.`parquet/varlenDecimal.parquet`";
@Test
public void testNullCount() throws Exception {
- String query = String.format("select count(*) as c from %s where department_id is null", DATAFILE);
+ String query = "select count(*) as c from %s where department_id is null";
testBuilder()
- .sqlQuery(query)
+ .sqlQuery(query, DATAFILE)
.unOrdered()
.baselineColumns("c")
.baselineValues(1L)
- .build()
- .run();
+ .go();
}
@Test
public void testNotNullCount() throws Exception {
- String query = String.format("select count(*) as c from %s where department_id is not null", DATAFILE);
+ String query = "select count(*) as c from %s where department_id is not null";
testBuilder()
- .sqlQuery(query)
+ .sqlQuery(query, DATAFILE)
.unOrdered()
.baselineColumns("c")
.baselineValues(106L)
- .build()
- .run();
+ .go();
}
@Test
public void testSimpleQuery() throws Exception {
- String query = String.format("select cast(department_id as bigint) as c from %s where cast(employee_id as decimal) = 170", DATAFILE);
+ String query = "select cast(department_id as bigint) as c from %s where cast(employee_id as decimal) = 170";
+
testBuilder()
- .sqlQuery(query)
+ .sqlQuery(query, DATAFILE)
.unOrdered()
.baselineColumns("c")
.baselineValues(80L)
- .build()
- .run();
+ .go();
+ }
+
+ @Test
+ public void testWriteReadJson() throws Exception {
+ // Drill stores decimal values in JSON files correctly, but it can read only double values, but not big decimal.
+ // See JsonToken class.
+
+ String tableName = "jsonWithDecimals";
+ try {
+ alterSession(ExecConstants.OUTPUT_FORMAT_OPTION, "json");
+
+ String bigDecimalValue = "987654321987654321987654321.987654321";
+
+ test(
+ "create table dfs.tmp.%s as\n" +
+ "select cast('%s' as decimal(36, 9)) dec36", tableName, bigDecimalValue);
+
+ String json = FileUtils.readFileToString(
+ Paths.get(dirTestWatcher.getDfsTestTmpDir().getPath(), tableName, "0_0_0.json").toFile());
+
+ Assert.assertThat(json, CoreMatchers.containsString(bigDecimalValue));
+
+ // checks that decimal value may be read as a double value
+ testBuilder()
+ .sqlQuery("select dec36 from dfs.tmp.%s", tableName)
+ .unOrdered()
+ .baselineColumns("dec36")
+ .baselineValues(new BigDecimal(bigDecimalValue).doubleValue())
+ .go();
+ } finally {
+ resetSessionOption(ExecConstants.OUTPUT_FORMAT_OPTION);
+ test("drop table if exists dfs.tmp.%s", tableName);
+ }
+ }
+
+ @Test
+ public void testWriteReadCsv() throws Exception {
+ String tableName = "csvWithDecimals";
+ try {
+ alterSession(ExecConstants.OUTPUT_FORMAT_OPTION, "csvh");
+
+ String bigDecimalValue = "987654321987654321987654321.987654321";
+
+ test(
+ "create table dfs.tmp.%s as\n" +
+ "select cast('%s' as decimal(36, 9)) dec36", tableName, bigDecimalValue);
+
+ String csv = FileUtils.readFileToString(
+ Paths.get(dirTestWatcher.getDfsTestTmpDir().getPath(), tableName, "0_0_0.csvh").toFile());
+
+ Assert.assertThat(csv, CoreMatchers.containsString(bigDecimalValue));
+
+ testBuilder()
+ .sqlQuery("select cast(dec36 as decimal(36, 9)) as dec36 from dfs.tmp.%s", tableName)
+ .ordered()
+ .baselineColumns("dec36")
+ .baselineValues(new BigDecimal(bigDecimalValue))
+ .go();
+ } finally {
+ resetSessionOption(ExecConstants.OUTPUT_FORMAT_OPTION);
+ test("drop table if exists dfs.tmp.%s", tableName);
+ }
}
}
diff --git a/exec/java-exec/src/test/java/org/apache/drill/exec/store/parquet/columnreaders/TestColumnReaderFactory.java b/exec/java-exec/src/test/java/org/apache/drill/exec/store/parquet/columnreaders/TestColumnReaderFactory.java
index 87adc2654..a6a3bed96 100644
--- a/exec/java-exec/src/test/java/org/apache/drill/exec/store/parquet/columnreaders/TestColumnReaderFactory.java
+++ b/exec/java-exec/src/test/java/org/apache/drill/exec/store/parquet/columnreaders/TestColumnReaderFactory.java
@@ -24,15 +24,15 @@ import org.junit.BeforeClass;
import org.junit.Test;
public class TestColumnReaderFactory extends BaseTestQuery {
- // enable decimal data type
+
@BeforeClass
- public static void enableDecimalDataType() throws Exception {
- test(String.format("alter session set `%s` = true", PlannerSettings.ENABLE_DECIMAL_DATA_TYPE_KEY));
+ public static void enableDecimalDataType() {
+ alterSession(PlannerSettings.ENABLE_DECIMAL_DATA_TYPE_KEY, true);
}
@AfterClass
- public static void disableDecimalDataType() throws Exception {
- test(String.format("alter session set `%s` = false", PlannerSettings.ENABLE_DECIMAL_DATA_TYPE_KEY));
+ public static void disableDecimalDataType() {
+ resetSessionOption(PlannerSettings.ENABLE_DECIMAL_DATA_TYPE_KEY);
}
/**
diff --git a/exec/java-exec/src/test/java/org/apache/drill/test/rowSet/test/TestFillEmpties.java b/exec/java-exec/src/test/java/org/apache/drill/test/rowSet/test/TestFillEmpties.java
index f4c00ca1f..63a98b322 100644
--- a/exec/java-exec/src/test/java/org/apache/drill/test/rowSet/test/TestFillEmpties.java
+++ b/exec/java-exec/src/test/java/org/apache/drill/test/rowSet/test/TestFillEmpties.java
@@ -114,6 +114,7 @@ public class TestFillEmpties extends SubOperatorTest {
case DECIMAL28SPARSE:
case DECIMAL9:
case DECIMAL38SPARSE:
+ case VARDECIMAL:
doFillEmptiesTest(type, mode, 9, 2);
break;
default:
diff --git a/exec/java-exec/src/test/resources/decimal/cast_decimal_float.json b/exec/java-exec/src/test/resources/decimal/cast_decimal_float.json
index 3fc94a0d2..af155045b 100644
--- a/exec/java-exec/src/test/resources/decimal/cast_decimal_float.json
+++ b/exec/java-exec/src/test/resources/decimal/cast_decimal_float.json
@@ -19,8 +19,8 @@
"pop" : "project",
"@id" : 2,
"exprs" : [
- { "ref" : "DEC9_COL", "expr": "(cast(DEC9 as decimal9(9, 4)))" },
- { "ref" : "DEC38_COL", "expr": "(cast(DEC18 as decimal38sparse(38, 4)))" }
+ { "ref" : "DEC9_COL", "expr": "(cast(DEC9 as vardecimal(9, 4)))" },
+ { "ref" : "DEC38_COL", "expr": "(cast(DEC18 as vardecimal(38, 4)))" }
],
"child" : 1
diff --git a/exec/java-exec/src/test/resources/decimal/cast_decimal_int.json b/exec/java-exec/src/test/resources/decimal/cast_decimal_int.json
index 2cca86541..27df35aea 100644
--- a/exec/java-exec/src/test/resources/decimal/cast_decimal_int.json
+++ b/exec/java-exec/src/test/resources/decimal/cast_decimal_int.json
@@ -19,8 +19,8 @@
"pop" : "project",
"@id" : 2,
"exprs" : [
- { "ref" : "DEC9_COL", "expr": "(cast(cast(INT_COL as int) as decimal9(9, 0)))" },
- { "ref" : "DEC38_COL", "expr": "(cast(BIGINT_COL as decimal38sparse(38, 0)))" }
+ { "ref" : "DEC9_COL", "expr": "(cast(cast(INT_COL as int) as vardecimal(9, 0)))" },
+ { "ref" : "DEC38_COL", "expr": "(cast(BIGINT_COL as vardecimal(38, 0)))" }
],
"child" : 1
diff --git a/exec/java-exec/src/test/resources/decimal/cast_decimal_vardecimal.json b/exec/java-exec/src/test/resources/decimal/cast_decimal_vardecimal.json
new file mode 100644
index 000000000..92c8237b4
--- /dev/null
+++ b/exec/java-exec/src/test/resources/decimal/cast_decimal_vardecimal.json
@@ -0,0 +1,56 @@
+{
+ "head" : {
+ "version" : 1,
+ "generator" : {
+ "type" : "org.apache.drill.exec.planner.logical.DrillImplementor",
+ "info" : ""
+ },
+ "type" : "APACHE_DRILL_PHYSICAL",
+ "resultMode" : "EXEC"
+ },
+ "graph":[
+ {
+ "pop" : "fs-scan",
+ "@id" : 4,
+ "format": {"type": "json"},
+ "storage":{"type": "file", "connection": "classpath:///"},
+ "files":["/input_complex_decimal.json"]
+ }, {
+ "pop" : "project",
+ "@id" : 3,
+ "exprs" : [
+ { "ref" : "DEC28", "expr": "(cast(B as vardecimal(38, 20)))" },
+ { "ref" : "DEC38", "expr": "(cast(A as vardecimal(28, 16)))" },
+ { "ref" : "DEC18", "expr": "(cast(B as vardecimal(18, 9)))" },
+ { "ref" : "DEC9", "expr": "(cast(A as vardecimal(9, 0)))" }
+ ],
+
+ "child" : 4
+ }, {
+ "pop" : "project",
+ "@id" : 2,
+ "exprs" : [
+ {"ref": "DEC28_COL", "expr" : "cast(DEC28 as decimal38sparse(38, 20))"},
+ {"ref": "DEC38_COL", "expr" : "cast(DEC38 as decimal28sparse(28, 16))"},
+ {"ref": "DEC18_COL", "expr" : "cast(DEC18 as decimal18(18, 0))"},
+ {"ref": "DEC9_COL", "expr" : "cast(DEC9 as decimal9(9, 0))"}
+ ],
+
+ "child" : 3
+ }, {
+ "pop" : "project",
+ "@id" : 1,
+ "exprs" : [
+ {"ref": "DEC28_COL", "expr" : "cast(DEC28_COL as decimal38sparse(38, 16))"},
+ {"ref": "DEC38_COL", "expr" : "cast(DEC38_COL as decimal28sparse(28, 16))"},
+ {"ref": "DEC18_COL", "expr" : "cast(DEC18_COL as decimal18(18, 0))"},
+ {"ref": "DEC9_COL", "expr" : "cast(DEC9_COL as decimal9(9, 0))"}
+ ],
+
+ "child" : 2
+ }, {
+ "pop" : "screen",
+ "@id" : 0,
+ "child" : 1
+ } ]
+}
diff --git a/exec/java-exec/src/test/resources/decimal/cast_float_decimal.json b/exec/java-exec/src/test/resources/decimal/cast_float_decimal.json
index b9e05d36c..e8f318a24 100644
--- a/exec/java-exec/src/test/resources/decimal/cast_float_decimal.json
+++ b/exec/java-exec/src/test/resources/decimal/cast_float_decimal.json
@@ -32,9 +32,9 @@
"@id" : 4,
"exprs" : [ {
"ref" : "DECIMAL_9",
- "expr" : " cast(F4 as decimal9(9, 4)) "
+ "expr" : " cast(F4 as vardecimal(9, 4)) "
},
- {"ref": "DECIMAL38", "expr" : "cast(F8 as decimal38sparse(38, 4))"}
+ {"ref": "DECIMAL38", "expr" : "cast(F8 as vardecimal(38, 4))"}
],
"child" : 2
diff --git a/exec/java-exec/src/test/resources/decimal/cast_int_decimal.json b/exec/java-exec/src/test/resources/decimal/cast_int_decimal.json
index 885ff534b..2f0999289 100644
--- a/exec/java-exec/src/test/resources/decimal/cast_int_decimal.json
+++ b/exec/java-exec/src/test/resources/decimal/cast_int_decimal.json
@@ -29,10 +29,10 @@
"pop" : "project",
"@id" : 4,
"exprs" : [
- {"ref": "DEC9_INT", "expr" : "cast(INT_COL as decimal9(9, 0))"},
- {"ref": "DEC38_INT", "expr" : "cast(INT_COL as decimal38sparse(38, 0))"},
- {"ref": "DEC9_BIGINT", "expr" : "cast(BIGINT_COL as decimal9(9, 0))"},
- {"ref": "DEC38_BIGINT", "expr" : "cast(BIGINT_COL as decimal38sparse(38, 0))"}
+ {"ref": "DEC9_INT", "expr" : "cast(INT_COL as vardecimal(9, 0))"},
+ {"ref": "DEC38_INT", "expr" : "cast(INT_COL as vardecimal(38, 0))"},
+ {"ref": "DEC9_BIGINT", "expr" : "cast(BIGINT_COL as vardecimal(9, 0))"},
+ {"ref": "DEC38_BIGINT", "expr" : "cast(BIGINT_COL as vardecimal(38, 0))"}
],
"child" : 2
diff --git a/exec/java-exec/src/test/resources/decimal/cast_simple_decimal.json b/exec/java-exec/src/test/resources/decimal/cast_simple_decimal.json
index 029172465..53ff360c8 100644
--- a/exec/java-exec/src/test/resources/decimal/cast_simple_decimal.json
+++ b/exec/java-exec/src/test/resources/decimal/cast_simple_decimal.json
@@ -20,9 +20,9 @@
"@id" : 2,
"exprs" : [ {
"ref" : "DECIMAL_9",
- "expr" : " (cast(DEC9 as decimal9(9, 4))) "
+ "expr" : " (cast(DEC9 as vardecimal(9, 4))) "
},
- { "ref" : "DECIMAL_18", "expr": "(cast(DEC18 as decimal18(18, 9)))" }
+ { "ref" : "DECIMAL_18", "expr": "(cast(DEC18 as vardecimal(18, 9)))" }
],
"child" : 1
diff --git a/exec/java-exec/src/test/resources/decimal/cast_vardecimal_decimal.json b/exec/java-exec/src/test/resources/decimal/cast_vardecimal_decimal.json
new file mode 100644
index 000000000..4a4c5c90f
--- /dev/null
+++ b/exec/java-exec/src/test/resources/decimal/cast_vardecimal_decimal.json
@@ -0,0 +1,47 @@
+{
+ "head" : {
+ "version" : 1,
+ "generator" : {
+ "type" : "org.apache.drill.exec.planner.logical.DrillImplementor",
+ "info" : ""
+ },
+ "type" : "APACHE_DRILL_PHYSICAL",
+ "resultMode" : "EXEC"
+ },
+ graph:[
+ {
+ @id:1,
+ pop:"fs-scan",
+ format: {type: "json"},
+ storage:{type: "file", connection: "classpath:///"},
+ files:["/input_complex_decimal.json"]
+ }, {
+ "pop" : "project",
+ "@id" : 2,
+ "exprs" : [
+ { "ref" : "DEC28", "expr": "(cast(B as vardecimal(38, 16)))" },
+ { "ref" : "DEC38", "expr": "(cast(A as vardecimal(28, 16)))" },
+ { "ref" : "DEC18", "expr": "(cast(B as vardecimal(18, 9)))" },
+ { "ref" : "DEC9", "expr": "(cast(A as vardecimal(9, 0)))" }
+ ],
+
+ "child" : 1
+ },
+ {
+ "pop" : "project",
+ "@id" : 4,
+ "exprs" : [
+ {"ref": "DEC28_COL", "expr" : "cast(DEC28 as decimal38sparse(38, 16))"},
+ {"ref": "DEC38_COL", "expr" : "cast(DEC38 as decimal28sparse(28, 16))"},
+ {"ref": "DEC18_COL", "expr" : "cast(DEC18 as decimal18(18, 0))"},
+ {"ref": "DEC9_COL", "expr" : "cast(DEC9 as decimal9(9, 0))"}
+ ],
+
+ "child" : 2
+ },
+ {
+ "pop" : "screen",
+ "@id" : 5,
+ "child" : 4
+ } ]
+}
diff --git a/exec/java-exec/src/test/resources/decimal/simple_decimal_arithmetic.json b/exec/java-exec/src/test/resources/decimal/simple_decimal_arithmetic.json
index ca31d8865..c774230f8 100644
--- a/exec/java-exec/src/test/resources/decimal/simple_decimal_arithmetic.json
+++ b/exec/java-exec/src/test/resources/decimal/simple_decimal_arithmetic.json
@@ -19,8 +19,8 @@
"pop" : "project",
"@id" : 2,
"exprs" : [
- { "ref" : "DECIMAL18_1", "expr": "(cast(DEC18 as decimal18(18, 1)))" },
- { "ref" : "DECIMAL18_2", "expr": "(cast(DEC9 as decimal18(18, 1)))" }
+ { "ref" : "DECIMAL18_1", "expr": "(cast(DEC18 as vardecimal(18, 1)))" },
+ { "ref" : "DECIMAL18_2", "expr": "(cast(DEC9 as vardecimal(18, 1)))" }
],
"child" : 1
diff --git a/exec/java-exec/src/test/resources/decimal/simple_decimal_math.json b/exec/java-exec/src/test/resources/decimal/simple_decimal_math.json
index 42fd78eaf..f7eb7f2c5 100644
--- a/exec/java-exec/src/test/resources/decimal/simple_decimal_math.json
+++ b/exec/java-exec/src/test/resources/decimal/simple_decimal_math.json
@@ -19,7 +19,7 @@
"pop" : "project",
"@id" : 2,
"exprs" : [
- { "ref" : "DECIMAL_18", "expr": "log((cast(DEC18 as decimal18(18, 9))))" }
+ { "ref" : "DECIMAL_18", "expr": "log((cast(DEC18 as vardecimal(18, 9))))" }
],
"child" : 1
diff --git a/exec/java-exec/src/test/resources/decimal/test_decimal_complex.json b/exec/java-exec/src/test/resources/decimal/test_decimal_complex.json
index b909411ab..f341421b2 100644
--- a/exec/java-exec/src/test/resources/decimal/test_decimal_complex.json
+++ b/exec/java-exec/src/test/resources/decimal/test_decimal_complex.json
@@ -20,9 +20,9 @@
"@id" : 2,
"exprs" : [ {
"ref" : "DE",
- "expr" : " (cast(B as decimal38sparse(28, 9))) "
+ "expr" : " (cast(B as vardecimal(28, 9))) "
},
- {"ref" : "DE1", "expr": " cast(A as decimal18(15, 6))" }
+ {"ref" : "DE1", "expr": " cast(A as vardecimal(15, 6))" }
],
"child" : 1
diff --git a/exec/java-exec/src/test/resources/decimal/test_decimal_sort_complex.json b/exec/java-exec/src/test/resources/decimal/test_decimal_sort_complex.json
index 70a7a1004..8ff0253f2 100644
--- a/exec/java-exec/src/test/resources/decimal/test_decimal_sort_complex.json
+++ b/exec/java-exec/src/test/resources/decimal/test_decimal_sort_complex.json
@@ -20,7 +20,7 @@
"@id" : 2,
"exprs" : [ {
"ref" : "DEC",
- "expr" : " (cast(B as decimal38sparse(38, 12)))"
+ "expr" : " (cast(B as vardecimal(38, 12)))"
}
],
"child" : 1
diff --git a/exec/java-exec/src/test/resources/parquet/repeatedIntLondFixedLenBinaryDecimal.parquet b/exec/java-exec/src/test/resources/parquet/repeatedIntLondFixedLenBinaryDecimal.parquet
new file mode 100644
index 000000000..62795b292
--- /dev/null
+++ b/exec/java-exec/src/test/resources/parquet/repeatedIntLondFixedLenBinaryDecimal.parquet
Binary files differ
diff --git a/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillMetaImpl.java b/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillMetaImpl.java
index b08c0f564..f3d1e3869 100644
--- a/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillMetaImpl.java
+++ b/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/DrillMetaImpl.java
@@ -19,6 +19,7 @@ package org.apache.drill.jdbc.impl;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
+import java.math.BigDecimal;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import java.sql.Time;
@@ -132,6 +133,7 @@ class DrillMetaImpl extends MetaImpl {
.put(Double.TYPE, of(Types.DOUBLE, "DOUBLE"))
.put(Double.class, of(Types.DOUBLE, "DOUBLE"))
.put(String.class, of(Types.VARCHAR, "CHARACTER VARYING"))
+ .put(BigDecimal.class, of(Types.DECIMAL, "DECIMAL"))
.put(java.sql.Date.class, of(Types.DATE, "DATE"))
.put(Time.class, of(Types.TIME, "TIME"))
.put(Timestamp.class, of(Types.TIMESTAMP, "TIMESTAMP"))
diff --git a/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/TypeConvertingSqlAccessor.java b/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/TypeConvertingSqlAccessor.java
index f8ac6bfef..f3d24fc9f 100644
--- a/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/TypeConvertingSqlAccessor.java
+++ b/exec/jdbc/src/main/java/org/apache/drill/jdbc/impl/TypeConvertingSqlAccessor.java
@@ -301,6 +301,11 @@ class TypeConvertingSqlAccessor implements SqlAccessor {
result = getByteValueOrThrow( innerAccessor.getDouble( rowOffset ),
"Java double / SQL DOUBLE PRECISION" );
break;
+ case VARDECIMAL:
+ result = getByteValueOrThrow(
+ innerAccessor.getBigDecimal(rowOffset).byteValue(),
+ "Java BigDecimal / SQL DECIMAL PRECISION");
+ break;
// 3. Not-yet-converted and unconvertible types:
default:
@@ -365,6 +370,11 @@ class TypeConvertingSqlAccessor implements SqlAccessor {
result = getShortValueOrThrow( innerAccessor.getDouble( rowOffset ),
"Java double / SQL DOUBLE PRECISION" );
break;
+ case VARDECIMAL:
+ result = getShortValueOrThrow(
+ innerAccessor.getBigDecimal(rowOffset).shortValue(),
+ "Java BigDecimal / SQL DECIMAL PRECISION");
+ break;
// 3. Not-yet-converted and unconvertible types:
default:
@@ -428,6 +438,11 @@ class TypeConvertingSqlAccessor implements SqlAccessor {
result = getIntValueOrThrow( innerAccessor.getDouble( rowOffset ),
"Java double / SQL DOUBLE PRECISION" );
break;
+ case VARDECIMAL:
+ result = getIntValueOrThrow(
+ innerAccessor.getBigDecimal(rowOffset).intValue(),
+ "Java BigDecimal / SQL DECIMAL PRECISION");
+ break;
// 3. Not-yet-converted and unconvertible types:
default:
@@ -481,6 +496,11 @@ class TypeConvertingSqlAccessor implements SqlAccessor {
result = getLongValueOrThrow( innerAccessor.getDouble( rowOffset ),
"Java double / SQL DOUBLE PRECISION" );
break;
+ case VARDECIMAL:
+ result = getLongValueOrThrow(
+ innerAccessor.getBigDecimal(rowOffset).longValue(),
+ "Java BigDecimal / SQL DECIMAL PRECISION");
+ break;
// 3. Not-yet-converted and unconvertible types:
default:
@@ -490,6 +510,14 @@ class TypeConvertingSqlAccessor implements SqlAccessor {
return result;
}
+ private static float getFloatValueOrThrow(double value, String typeLabel)
+ throws SQLConversionOverflowException {
+ if (Float.MIN_VALUE <= value && value <= Float.MAX_VALUE) {
+ return (float) value;
+ } else {
+ throw newOverflowException("getFloat(...)", typeLabel, value);
+ }
+ }
////////////////////////////////////////
// - getFloat:
@@ -516,14 +544,13 @@ class TypeConvertingSqlAccessor implements SqlAccessor {
result = innerAccessor.getLong( rowOffset );
break;
case FLOAT8:
- final double value = innerAccessor.getDouble( rowOffset );
- if ( Float.MIN_VALUE <= value && value <= Float.MAX_VALUE ) {
- result = (float) value;
- } else {
- throw newOverflowException( "getFloat(...)",
- "Java double / SQL DOUBLE PRECISION",
- value );
- }
+ result = getFloatValueOrThrow(innerAccessor.getDouble(rowOffset),
+ "Java double / SQL DOUBLE PRECISION");
+ break;
+ case VARDECIMAL:
+ result = getFloatValueOrThrow(
+ innerAccessor.getBigDecimal(rowOffset).floatValue(),
+ "Java BigDecimal / SQL DECIMAL PRECISION");
break;
// 3. Not-yet-converted and unconvertible types:
@@ -561,6 +588,9 @@ class TypeConvertingSqlAccessor implements SqlAccessor {
case FLOAT4:
result = innerAccessor.getFloat( rowOffset );
break;
+ case VARDECIMAL:
+ result = innerAccessor.getBigDecimal(rowOffset).doubleValue();
+ break;
// 3. Not-yet-converted and unconvertible types:
default:
diff --git a/exec/jdbc/src/test/java/org/apache/drill/jdbc/ResultSetGetMethodConversionsTest.java b/exec/jdbc/src/test/java/org/apache/drill/jdbc/ResultSetGetMethodConversionsTest.java
index 0af4c2577..e47c82656 100644
--- a/exec/jdbc/src/test/java/org/apache/drill/jdbc/ResultSetGetMethodConversionsTest.java
+++ b/exec/jdbc/src/test/java/org/apache/drill/jdbc/ResultSetGetMethodConversionsTest.java
@@ -92,8 +92,8 @@ public class ResultSetGetMethodConversionsTest extends JdbcTestBase {
//+ "\n CAST( 5.5 AS REAL ) AS `C_REAL_5.5`, "
+ "\n CAST( 6.6 AS DOUBLE PRECISION ) AS `C_DOUBLE_PREC._6.6`, "
+ "\n CAST( 7.7 AS FLOAT ) AS `C_FLOAT_7.7`, "
- + "\n CAST( 10.10 AS DECIMAL ) AS `C_DECIMAL_10.10`, "
- + "\n CAST( 10.5 AS DECIMAL ) AS `C_DECIMAL_10.5`, "
+ + "\n CAST( 10.10 AS DECIMAL(4,2) ) AS `C_DECIMAL_10.10`, "
+ + "\n CAST( 10.5 AS DECIMAL (3,1) ) AS `C_DECIMAL_10.5`, "
+ "\n CAST( 11.11 AS DECIMAL(9,2) ) AS `C_DECIMAL(9,2)_11.11`, "
+ "\n CAST( 12.12 AS DECIMAL(18,2) ) AS `C_DECIMAL(18,2)_12.12`, "
+ "\n CAST( 13.13 AS DECIMAL(28,2) ) AS `C_DECIMAL(28,2)_13.13`, "
@@ -494,7 +494,6 @@ public class ResultSetGetMethodConversionsTest extends JdbcTestBase {
assertThat( testDataRow.getBigDecimal( "C_DECIMAL_10.5" ), equalTo( new BigDecimal( "10.5") ) );
}
- @Ignore( "TODO(DRILL-3367): unignore when DECIMAL is no longer DOUBLE" )
@Test
public void test_getBigDecimal_handles_DECIMAL_2() throws SQLException {
assertThat( testDataRow.getBigDecimal( "C_DECIMAL_10.10" ), equalTo( new BigDecimal( "10.10") ) );
@@ -566,7 +565,7 @@ public class ResultSetGetMethodConversionsTest extends JdbcTestBase {
@Test
public void test_getString_handles_DECIMAL() throws SQLException {
- assertThat( testDataRow.getString( "C_DECIMAL_10.10" ), equalTo( "10.1" ) );
+ assertThat( testDataRow.getString( "C_DECIMAL_10.10" ), equalTo( "10.10" ) );
assertThat( testDataRowWithNulls.getString( "C_DECIMAL_10.10" ), equalTo( null ) );
}
@@ -724,14 +723,12 @@ public class ResultSetGetMethodConversionsTest extends JdbcTestBase {
assertThat( testDataRow.getObject( "C_FLOAT_7.7" ), equalTo( (Object) 7.7f ) );
}
- @Ignore( "TODO(DRILL-3367): unignore when DECIMAL is no longer DOUBLE" )
@Test
public void test_getObject_handles_DECIMAL_1() throws SQLException {
assertThat( testDataRow.getObject( "C_DECIMAL_10.5" ),
equalTo( (Object) new BigDecimal( "10.5" ) ) );
}
- @Ignore( "TODO(DRILL-3367): unignore when DECIMAL is no longer DOUBLE" )
@Test
public void test_getObject_handles_DECIMAL_2() throws SQLException {
assertThat( testDataRow.getObject( "C_DECIMAL_10.10" ),
diff --git a/exec/vector/src/main/codegen/data/ValueVectorTypes.tdd b/exec/vector/src/main/codegen/data/ValueVectorTypes.tdd
index ca4653d3e..f6e1f1d09 100644
--- a/exec/vector/src/main/codegen/data/ValueVectorTypes.tdd
+++ b/exec/vector/src/main/codegen/data/ValueVectorTypes.tdd
@@ -183,7 +183,9 @@
javaType: "int",
boxedType: "DrillBuf",
minor: [
- { class: "VarDecimal", friendlyType: "BigDecimal", fields: [{name: "start", type: "int"}, {name: "end", type: "int"}, {name: "buffer", type: "DrillBuf"}, {name: "scale", type: "int", include: false}] }
+ { class: "VarDecimal", friendlyType: "BigDecimal", fields: [{name: "start", type: "int"},
+ {name: "end", type: "int"}, {name: "buffer", type: "DrillBuf"},
+ {name: "scale", type: "int", include: false}, {name: "precision", type: "int", include: false}] }
]
},
{
diff --git a/exec/vector/src/main/codegen/templates/AbstractFieldReader.java b/exec/vector/src/main/codegen/templates/AbstractFieldReader.java
index f2e1eb0dd..2ed5a3b6d 100644
--- a/exec/vector/src/main/codegen/templates/AbstractFieldReader.java
+++ b/exec/vector/src/main/codegen/templates/AbstractFieldReader.java
@@ -29,10 +29,9 @@ package org.apache.drill.exec.vector.complex.impl;
* This class is generated using freemarker and the ${.template_name} template.
*/
@SuppressWarnings("unused")
-abstract class AbstractFieldReader extends AbstractBaseReader implements FieldReader{
+abstract class AbstractFieldReader extends AbstractBaseReader implements FieldReader {
- AbstractFieldReader(){
- super();
+ AbstractFieldReader() {
}
/**
@@ -49,78 +48,77 @@ abstract class AbstractFieldReader extends AbstractBaseReader implements FieldRe
<#assign safeType=friendlyType />
<#if safeType=="byte[]"><#assign safeType="ByteArray" /></#if>
- public ${friendlyType} read${safeType}(int arrayIndex){
+ public ${friendlyType} read${safeType}(int arrayIndex) {
fail("read${safeType}(int arrayIndex)");
return null;
}
- public ${friendlyType} read${safeType}(){
+ public ${friendlyType} read${safeType}() {
fail("read${safeType}()");
return null;
}
</#list>
- public void copyAsValue(MapWriter writer){
+ public void copyAsValue(MapWriter writer) {
fail("CopyAsValue MapWriter");
}
- public void copyAsField(String name, MapWriter writer){
+ public void copyAsField(String name, MapWriter writer) {
fail("CopyAsField MapWriter");
}
- public void copyAsField(String name, ListWriter writer){
+ public void copyAsField(String name, ListWriter writer) {
fail("CopyAsFieldList");
}
<#list vv.types as type><#list type.minor as minor><#assign name = minor.class?cap_first />
<#assign boxedType = (minor.boxedType!type.boxedType) />
- public void read(${name}Holder holder){
+ public void read(${name}Holder holder) {
fail("${name}");
}
- public void read(Nullable${name}Holder holder){
+ public void read(Nullable${name}Holder holder) {
fail("${name}");
}
- public void read(int arrayIndex, ${name}Holder holder){
+ public void read(int arrayIndex, ${name}Holder holder) {
fail("Repeated${name}");
}
- public void read(int arrayIndex, Nullable${name}Holder holder){
+ public void read(int arrayIndex, Nullable${name}Holder holder) {
fail("Repeated${name}");
}
- public void copyAsValue(${name}Writer writer){
+ public void copyAsValue(${name}Writer writer) {
fail("CopyAsValue${name}");
}
- public void copyAsField(String name, ${name}Writer writer){
+
+ <#if minor.class == "VarDecimal">
+ public void copyAsField(String name, ${name}Writer writer, int scale, int precision) {
+ <#else>
+ public void copyAsField(String name, ${name}Writer writer) {
+ </#if>
fail("CopyAsField${name}");
}
</#list></#list>
- public FieldReader reader(String name){
+ public FieldReader reader(String name) {
fail("reader(String name)");
return null;
}
- public FieldReader reader(){
+ public FieldReader reader() {
fail("reader()");
return null;
-
}
- public int size(){
+ public int size() {
fail("size()");
return -1;
}
- private void fail(String name){
+ private void fail(String name) {
throw new IllegalArgumentException(String.format("You tried to read a [%s] type when you are using a field reader of type [%s].", name, this.getClass().getSimpleName()));
}
-
-
}
-
-
-
diff --git a/exec/vector/src/main/codegen/templates/AbstractFieldWriter.java b/exec/vector/src/main/codegen/templates/AbstractFieldWriter.java
index 608420cce..dcf99d34b 100644
--- a/exec/vector/src/main/codegen/templates/AbstractFieldWriter.java
+++ b/exec/vector/src/main/codegen/templates/AbstractFieldWriter.java
@@ -65,6 +65,12 @@ abstract class AbstractFieldWriter extends AbstractBaseWriter implements FieldWr
fail("${name}");
}
+ <#if minor.class?contains("Decimal") >
+ public void write${minor.class}(BigDecimal value) {
+ fail("${name}");
+ }
+ </#if>
+
</#list></#list>
public void writeNull() {
@@ -111,11 +117,18 @@ abstract class AbstractFieldWriter extends AbstractBaseWriter implements FieldWr
<#if lowerName == "int" ><#assign lowerName = "integer" /></#if>
<#assign upperName = minor.class?upper_case />
<#assign capName = minor.class?cap_first />
- <#if minor.class?starts_with("Decimal") >
+ <#if minor.class?contains("Decimal") >
+ @Override
public ${capName}Writer ${lowerName}(String name, int scale, int precision) {
fail("${capName}");
return null;
}
+
+ @Override
+ public ${capName}Writer ${lowerName}(int scale, int precision) {
+ fail("${capName}");
+ return null;
+ }
</#if>
@Override
diff --git a/exec/vector/src/main/codegen/templates/AbstractPromotableFieldWriter.java b/exec/vector/src/main/codegen/templates/AbstractPromotableFieldWriter.java
index df7be39bd..96b45d329 100644
--- a/exec/vector/src/main/codegen/templates/AbstractPromotableFieldWriter.java
+++ b/exec/vector/src/main/codegen/templates/AbstractPromotableFieldWriter.java
@@ -75,12 +75,20 @@ abstract class AbstractPromotableFieldWriter extends AbstractFieldWriter {
<#list vv.types as type><#list type.minor as minor><#assign name = minor.class?cap_first />
<#assign fields = minor.fields!type.fields />
- <#if !minor.class?starts_with("Decimal") >
+ <#if minor.class?contains("VarDecimal")>
+ @Override
+ public void write${minor.class}(BigDecimal value) {
+ getWriter(MinorType.${name?upper_case}).write${minor.class}(value);
+ }
+ </#if>
+
@Override
public void write(${name}Holder holder) {
getWriter(MinorType.${name?upper_case}).write(holder);
}
+ <#-- This condition was added to cover previous decimal functionality for new VarDecimal type -->
+ <#if !minor.class?contains("Decimal") || minor.class?contains("VarDecimal")>
public void write${minor.class}(<#list fields as field>${field.type} ${field.name}<#if field_has_next>, </#if></#list>) {
getWriter(MinorType.${name?upper_case}).write${minor.class}(<#list fields as field>${field.name}<#if field_has_next>, </#if></#list>);
}
@@ -116,7 +124,19 @@ abstract class AbstractPromotableFieldWriter extends AbstractFieldWriter {
<#if lowerName == "int" ><#assign lowerName = "integer" /></#if>
<#assign upperName = minor.class?upper_case />
<#assign capName = minor.class?cap_first />
- <#if !minor.class?starts_with("Decimal") >
+ <#if minor.class?contains("Decimal")>
+
+ @Override
+ public ${capName}Writer ${lowerName}(String name, int scale, int precision) {
+ return getWriter(MinorType.MAP).${lowerName}(name, scale, precision);
+ }
+
+ @Override
+ public ${capName}Writer ${lowerName}(int scale, int precision) {
+ return getWriter(MinorType.LIST).${lowerName}(scale, precision);
+ }
+
+ <#else>
@Override
public ${capName}Writer ${lowerName}(String name) {
diff --git a/exec/vector/src/main/codegen/templates/BaseWriter.java b/exec/vector/src/main/codegen/templates/BaseWriter.java
index ad9c44e1f..e65060976 100644
--- a/exec/vector/src/main/codegen/templates/BaseWriter.java
+++ b/exec/vector/src/main/codegen/templates/BaseWriter.java
@@ -53,7 +53,7 @@ package org.apache.drill.exec.vector.complex.writer;
<#if lowerName == "int" ><#assign lowerName = "integer" /></#if>
<#assign upperName = minor.class?upper_case />
<#assign capName = minor.class?cap_first />
- <#if minor.class?starts_with("Decimal") >
+ <#if minor.class?contains("Decimal") >
${capName}Writer ${lowerName}(String name, int scale, int precision);
</#if>
${capName}Writer ${lowerName}(String name);
@@ -78,6 +78,9 @@ package org.apache.drill.exec.vector.complex.writer;
<#if lowerName == "int" ><#assign lowerName = "integer" /></#if>
<#assign upperName = minor.class?upper_case />
<#assign capName = minor.class?cap_first />
+ <#if minor.class?contains("Decimal") >
+ ${capName}Writer ${lowerName}(int scale, int precision);
+ </#if>
${capName}Writer ${lowerName}();
</#list></#list>
}
@@ -112,6 +115,7 @@ package org.apache.drill.exec.vector.complex.writer;
VarCharWriter varChar(String name);
Var16CharWriter var16Char(String name);
VarDecimalWriter varDecimal(String name);
+ VarDecimalWriter varDecimal(String name, int scale, int precision);
TinyIntWriter tinyInt(String name);
SmallIntWriter smallInt(String name);
IntWriter integer(String name);
diff --git a/exec/vector/src/main/codegen/templates/BasicTypeHelper.java b/exec/vector/src/main/codegen/templates/BasicTypeHelper.java
index 8160dd59a..f818c236f 100644
--- a/exec/vector/src/main/codegen/templates/BasicTypeHelper.java
+++ b/exec/vector/src/main/codegen/templates/BasicTypeHelper.java
@@ -395,7 +395,9 @@ public class BasicTypeHelper {
MajorType type1 = v1.getField().getType();
MajorType type2 = v2.getField().getType();
- if (type1.getMinorType() != type2.getMinorType()) {
+ if (type1.getMinorType() != type2.getMinorType()
+ || type1.getScale() != type1.getScale()
+ || type1.getPrecision() != type1.getPrecision()) {
return false;
}
@@ -539,11 +541,19 @@ public class BasicTypeHelper {
}
<#list vv.types as type>
<#list type.minor as minor>
+ <#if minor.class.contains("Decimal")>
+ else if (holder instanceof ${minor.class}Holder) {
+ return getType((${minor.class}Holder) holder);
+ } else if (holder instanceof Nullable${minor.class}Holder) {
+ return getType((Nullable${minor.class}Holder) holder);
+ }
+ <#else>
else if (holder instanceof ${minor.class}Holder) {
return ((${minor.class}Holder) holder).TYPE;
} else if (holder instanceof Nullable${minor.class}Holder) {
return ((Nullable${minor.class}Holder) holder).TYPE;
}
+ </#if>
</#list>
</#list>
else if (holder instanceof UntypedNullHolder) {
@@ -553,4 +563,31 @@ public class BasicTypeHelper {
}
+ <#list vv.types as type>
+ <#list type.minor as minor>
+ <#if minor.class.contains("Decimal")>
+ <#list ["Nullable", "", "Repeated"] as dataMode>
+ public static MajorType getType(${dataMode}${minor.class}Holder holder) {
+ return MajorType.newBuilder()
+ .setMinorType(MinorType.${minor.class?upper_case})
+ <#if dataMode == "Nullable">
+ .setMode(DataMode.OPTIONAL)
+ .setScale(holder.scale)
+ .setPrecision(holder.precision)
+ <#elseif dataMode == "Repeated">
+ .setMode(DataMode.REPEATED)
+ .setScale(holder.vector.getField().getScale())
+ .setPrecision(holder.vector.getField().getPrecision())
+ <#else>
+ .setMode(DataMode.REQUIRED)
+ .setScale(holder.scale)
+ .setPrecision(holder.precision)
+ </#if>
+ .build();
+ }
+ </#list>
+ </#if>
+ </#list>
+ </#list>
+
}
diff --git a/exec/vector/src/main/codegen/templates/ColumnAccessors.java b/exec/vector/src/main/codegen/templates/ColumnAccessors.java
index 6068afa22..accf1b28d 100644
--- a/exec/vector/src/main/codegen/templates/ColumnAccessors.java
+++ b/exec/vector/src/main/codegen/templates/ColumnAccessors.java
@@ -28,6 +28,8 @@
return ValueType.INTEGER;
<#elseif drillType == "VarChar" || drillType == "Var16Char">
return ValueType.STRING;
+ <#elseif drillType == "VarDecimal">
+ return ValueType.DECIMAL;
<#else>
return ValueType.${label?upper_case};
</#if>
@@ -65,6 +67,7 @@
package org.apache.drill.exec.vector.accessor;
import java.math.BigDecimal;
+import java.math.BigInteger;
import org.apache.drill.common.types.TypeProtos.MajorType;
import org.apache.drill.exec.vector.DateUtilities;
@@ -141,12 +144,10 @@ public class ColumnAccessors {
private static final int VALUE_WIDTH = ${drillType}Vector.VALUE_WIDTH;
- <#if decimal>
- private MajorType type;
-
- </#if>
</#if>
<#if decimal>
+ private MajorType type;
+
@Override
public void bindVector(ColumnMetadata schema, VectorAccessor va) {
super.bindVector(schema, va);
@@ -234,6 +235,14 @@ public class ColumnAccessors {
public String getString() {
return new String(getBytes(${indexVar}), Charsets.UTF_16);
}
+ <#elseif drillType == "VarDecimal">
+
+ @Override
+ public BigDecimal getDecimal() {
+ byte[] bytes = getBytes();
+ BigInteger unscaledValue = bytes.length == 0 ? BigInteger.ZERO : new BigInteger(bytes);
+ return new BigDecimal(unscaledValue, type.getScale());
+ }
</#if>
}
@@ -269,20 +278,10 @@ public class ColumnAccessors {
</#if>
<@getType drillType label />
<#if ! varWidth>
-
</#if>
- @Override
- <#if drillType = "VarDecimal">
- public final void setDecimal(final BigDecimal bd) {
- byte[] barr = bd.unscaledValue().toByteArray();
- int len = barr.length;
- setBytes(barr, len);
- }
- public final void setBytes(final byte[] value, int len) {
- <#else>
+ @Override
public final void set${label}(final ${accessorType} value${putArgs}) {
- </#if>
<#-- Must compute the write offset first; can't be inline because the
writeOffset() function has a side effect of possibly changing the buffer
address (bufAddr). -->
@@ -347,6 +346,15 @@ public class ColumnAccessors {
final byte bytes[] = value.getBytes(Charsets.UTF_16);
setBytes(bytes, bytes.length);
}
+
+ <#elseif drillType = "VarDecimal">
+
+ @Override
+ public final void setDecimal(final BigDecimal bd) {
+ byte[] barr = bd.unscaledValue().toByteArray();
+ int len = barr.length;
+ setBytes(barr, len);
+ }
</#if>
}
diff --git a/exec/vector/src/main/codegen/templates/ComplexCopier.java b/exec/vector/src/main/codegen/templates/ComplexCopier.java
index 91e3ff645..6d7c7e607 100644
--- a/exec/vector/src/main/codegen/templates/ComplexCopier.java
+++ b/exec/vector/src/main/codegen/templates/ComplexCopier.java
@@ -97,9 +97,12 @@ public class ComplexCopier {
<#list vv.types as type><#list type.minor as minor><#assign name = minor.class?cap_first />
<#assign fields = minor.fields!type.fields />
<#assign uncappedName = name?uncap_first/>
- <#if !minor.class?starts_with("Decimal")>
+ <#if !minor.class?contains("Decimal")>
case ${name?upper_case}:
return (FieldWriter) writer.<#if name == "Int">integer<#else>${uncappedName}</#if>(name);
+ <#elseif minor.class?contains("VarDecimal")>
+ case ${name?upper_case}:
+ return (FieldWriter) writer.${uncappedName}(name, reader.getType().getScale(), reader.getType().getPrecision());
</#if>
</#list></#list>
case MAP:
@@ -116,9 +119,12 @@ public class ComplexCopier {
<#list vv.types as type><#list type.minor as minor><#assign name = minor.class?cap_first />
<#assign fields = minor.fields!type.fields />
<#assign uncappedName = name?uncap_first/>
- <#if !minor.class?starts_with("Decimal")>
+ <#if !minor.class?contains("Decimal")>
+ case ${name?upper_case}:
+ return (FieldWriter) writer.<#if name == "Int">integer<#else>${uncappedName}</#if>();
+ <#elseif minor.class?contains("VarDecimal")>
case ${name?upper_case}:
- return (FieldWriter) writer.<#if name == "Int">integer<#else>${uncappedName}</#if>();
+ return (FieldWriter) writer.${uncappedName}(reader.getType().getScale(), reader.getType().getPrecision());
</#if>
</#list></#list>
case MAP:
diff --git a/exec/vector/src/main/codegen/templates/ComplexReaders.java b/exec/vector/src/main/codegen/templates/ComplexReaders.java
index 1f0b92b02..d72c7c696 100644
--- a/exec/vector/src/main/codegen/templates/ComplexReaders.java
+++ b/exec/vector/src/main/codegen/templates/ComplexReaders.java
@@ -53,20 +53,20 @@ public class ${nullMode}${name}ReaderImpl extends AbstractFieldReader {
private final ${nullMode}${name}Vector vector;
- public ${nullMode}${name}ReaderImpl(${nullMode}${name}Vector vector){
+ public ${nullMode}${name}ReaderImpl(${nullMode}${name}Vector vector) {
super();
this.vector = vector;
}
- public MajorType getType(){
+ public MajorType getType() {
return vector.getField().getType();
}
- public MaterializedField getField(){
+ public MaterializedField getField() {
return vector.getField();
}
- public boolean isSet(){
+ public boolean isSet() {
<#if nullMode == "Nullable">
return !vector.getAccessor().isNull(idx());
<#else>
@@ -74,76 +74,85 @@ public class ${nullMode}${name}ReaderImpl extends AbstractFieldReader {
</#if>
}
-
-
-
<#if mode == "Repeated">
- public void copyAsValue(${minor.class?cap_first}Writer writer){
+ public void copyAsValue(${minor.class?cap_first}Writer writer) {
Repeated${minor.class?cap_first}WriterImpl impl = (Repeated${minor.class?cap_first}WriterImpl) writer;
impl.vector.copyFromSafe(idx(), impl.idx(), vector);
}
-
- public void copyAsField(String name, MapWriter writer){
- Repeated${minor.class?cap_first}WriterImpl impl = (Repeated${minor.class?cap_first}WriterImpl) writer.list(name).${lowerName}();
+
+ <#if minor.class == "VarDecimal">
+ public void copyAsField(String name, MapWriter writer, int scale, int precision) {
+ Repeated${minor.class?cap_first}WriterImpl impl
+ = (Repeated${minor.class?cap_first}WriterImpl) writer.list(name).${lowerName}(scale, precision);
+ <#else>
+ public void copyAsField(String name, MapWriter writer) {
+ Repeated${minor.class?cap_first}WriterImpl impl = (Repeated${minor.class?cap_first}WriterImpl) writer.list(name).${lowerName}();
+ </#if>
impl.vector.copyFromSafe(idx(), impl.idx(), vector);
}
- public int size(){
+ public int size() {
return vector.getAccessor().getInnerValueCountAt(idx());
}
- public void read(int arrayIndex, ${minor.class?cap_first}Holder h){
+ public void read(int arrayIndex, ${minor.class?cap_first}Holder h) {
vector.getAccessor().get(idx(), arrayIndex, h);
}
- public void read(int arrayIndex, Nullable${minor.class?cap_first}Holder h){
+
+ public void read(int arrayIndex, Nullable${minor.class?cap_first}Holder h) {
vector.getAccessor().get(idx(), arrayIndex, h);
}
- public ${friendlyType} read${safeType}(int arrayIndex){
+ public ${friendlyType} read${safeType}(int arrayIndex) {
return vector.getAccessor().getSingleObject(idx(), arrayIndex);
}
- public List<Object> readObject(){
+ public List<Object> readObject() {
return (List<Object>) (Object) vector.getAccessor().getObject(idx());
}
<#else>
- public void copyAsValue(${minor.class?cap_first}Writer writer){
+ public void copyAsValue(${minor.class?cap_first}Writer writer) {
${nullMode}${minor.class?cap_first}WriterImpl impl = (${nullMode}${minor.class?cap_first}WriterImpl) writer;
impl.vector.copyFromSafe(idx(), impl.idx(), vector);
}
-
- public void copyAsField(String name, MapWriter writer){
+
+ <#if minor.class == "VarDecimal">
+ public void copyAsField(String name, MapWriter writer, int scale, int precision) {
+ ${nullMode}${minor.class?cap_first}WriterImpl impl
+ = (${nullMode}${minor.class?cap_first}WriterImpl) writer.${lowerName}(name, scale, precision);
+<#else>
+ public void copyAsField(String name, MapWriter writer) {
${nullMode}${minor.class?cap_first}WriterImpl impl = (${nullMode}${minor.class?cap_first}WriterImpl) writer.${lowerName}(name);
+ </#if>
impl.vector.copyFromSafe(idx(), impl.idx(), vector);
}
<#if nullMode != "Nullable">
- public void read(${minor.class?cap_first}Holder h){
+ public void read(${minor.class?cap_first}Holder h) {
vector.getAccessor().get(idx(), h);
}
</#if>
- public void read(Nullable${minor.class?cap_first}Holder h){
+ public void read(Nullable${minor.class?cap_first}Holder h) {
vector.getAccessor().get(idx(), h);
}
- public ${friendlyType} read${safeType}(){
+ public ${friendlyType} read${safeType}() {
return vector.getAccessor().getObject(idx());
}
- public void copyValue(FieldWriter w){
+ public void copyValue(FieldWriter w) {
}
- public Object readObject(){
+ public Object readObject() {
return vector.getAccessor().getObject(idx());
}
-
</#if>
}
</#if>
@@ -155,7 +164,7 @@ package org.apache.drill.exec.vector.complex.reader;
<#include "/@includes/vv_imports.ftl" />
@SuppressWarnings("unused")
-public interface ${name}Reader extends BaseReader{
+public interface ${name}Reader extends BaseReader {
<#if mode == "Repeated">
public int size();
@@ -171,8 +180,11 @@ public interface ${name}Reader extends BaseReader{
</#if>
public boolean isSet();
public void copyAsValue(${minor.class}Writer writer);
+ <#if minor.class == "VarDecimal">
+ public void copyAsField(String name, ${minor.class}Writer writer, int scale, int precision);
+ <#else>
public void copyAsField(String name, ${minor.class}Writer writer);
-
+ </#if>
}
diff --git a/exec/vector/src/main/codegen/templates/ComplexWriters.java b/exec/vector/src/main/codegen/templates/ComplexWriters.java
index 6e1d8f3e2..f46b7958d 100644
--- a/exec/vector/src/main/codegen/templates/ComplexWriters.java
+++ b/exec/vector/src/main/codegen/templates/ComplexWriters.java
@@ -96,14 +96,10 @@ public class ${eName}WriterImpl extends AbstractFieldWriter {
vector.getMutator().setValueCount(idx()+1);
}
- <#if !(minor.class == "Decimal9" || minor.class == "Decimal18" || minor.class == "Decimal28Sparse" || minor.class == "Decimal38Sparse" || minor.class == "Decimal28Dense" || minor.class == "Decimal38Dense")>
+ <#if !minor.class?contains("Decimal") || minor.class?contains("VarDecimal")>
public void write${minor.class}(<#list fields as field>${field.type} ${field.name}<#if field_has_next>, </#if></#list>) {
- <#if minor.class == "VarDecimal">
- mutator.addSafe(idx(), <#list fields as field><#if field.name == "scale"><#break></#if>${field.name}<#if field_has_next && fields[field_index+1].name != "scale" >, </#if></#list>);
- <#else>
- mutator.addSafe(idx(), <#list fields as field>${field.name}<#if field_has_next>, </#if></#list>);
- </#if>
- vector.getMutator().setValueCount(idx()+1);
+ mutator.addSafe(idx()<#list fields as field><#if field.include!true>, ${field.name}</#if></#list>);
+ vector.getMutator().setValueCount(idx() + 1);
}
</#if>
@@ -125,21 +121,23 @@ public class ${eName}WriterImpl extends AbstractFieldWriter {
vector.getMutator().setValueCount(idx()+1);
}
- <#if !(minor.class == "Decimal9" || minor.class == "Decimal18" || minor.class == "Decimal28Sparse" || minor.class == "Decimal38Sparse" || minor.class == "Decimal28Dense" || minor.class == "Decimal38Dense")>
- public void write${minor.class}(<#list fields as field>${field.type} ${field.name}<#if field_has_next>, </#if></#list>) {
- <#if minor.class == "VarDecimal">
- mutator.setSafe(idx(), <#if mode == "Nullable">1, </#if><#list fields as field><#if field.name == "scale"><#break></#if>${field.name}<#if field_has_next && fields[field_index+1].name != "scale" >, </#if></#list>);
- <#else>
- mutator.setSafe(idx(), <#if mode == "Nullable">1, </#if><#list fields as field>${field.name}<#if field_has_next>, </#if></#list>);
- </#if>
- vector.getMutator().setValueCount(idx()+1);
- }
-
<#if mode == "Nullable">
-
public void writeNull() {
mutator.setNull(idx());
- vector.getMutator().setValueCount(idx()+1);
+ vector.getMutator().setValueCount(idx() + 1);
+ }
+ </#if>
+
+ <#if !(minor.class == "Decimal9" || minor.class == "Decimal18")>
+ public void write${minor.class}(<#list fields as field>${field.type} ${field.name}<#if field_has_next>, </#if></#list>) {
+ mutator.setSafe(idx()<#if mode == "Nullable">, 1</#if><#list fields as field><#if field.include!true>, ${field.name}</#if></#list>);
+ vector.getMutator().setValueCount(idx() + 1);
+ }
+
+ <#if minor.class?contains("VarDecimal")>
+ public void write${minor.class}(BigDecimal value) {
+ mutator.setSafe(idx(), value);
+ vector.getMutator().setValueCount(idx() + 1);
}
</#if>
</#if>
@@ -156,9 +154,13 @@ package org.apache.drill.exec.vector.complex.writer;
public interface ${eName}Writer extends BaseWriter {
public void write(${minor.class}Holder h);
- <#if !(minor.class == "Decimal9" || minor.class == "Decimal18" || minor.class == "Decimal28Sparse" || minor.class == "Decimal38Sparse" || minor.class == "Decimal28Dense" || minor.class == "Decimal38Dense")>
+ <#if !(minor.class == "Decimal9" || minor.class == "Decimal18")>
public void write${minor.class}(<#list fields as field>${field.type} ${field.name}<#if field_has_next>, </#if></#list>);
</#if>
+
+ <#if minor.class?contains("VarDecimal")>
+ public void write${minor.class}(BigDecimal value);
+ </#if>
}
</#list>
diff --git a/exec/vector/src/main/codegen/templates/HolderReaderImpl.java b/exec/vector/src/main/codegen/templates/HolderReaderImpl.java
index e46989ba5..4b7be4fd7 100644
--- a/exec/vector/src/main/codegen/templates/HolderReaderImpl.java
+++ b/exec/vector/src/main/codegen/templates/HolderReaderImpl.java
@@ -42,6 +42,7 @@ import java.math.BigDecimal;
import java.math.BigInteger;
import org.apache.drill.exec.expr.holders.*;
+import org.apache.drill.exec.expr.BasicTypeHelper;
import org.joda.time.Period;
// Source code generated using FreeMarker template ${.template_name}
@@ -96,10 +97,14 @@ public class ${holderMode}${name}HolderReaderImpl extends AbstractFieldReader {
@Override
public MajorType getType() {
-<#if holderMode == "Repeated">
- return this.repeatedHolder.TYPE;
+<#if name?contains("Decimal")>
+ return BasicTypeHelper.getType(holder);
<#else>
+ <#if holderMode == "Repeated">
+ return this.repeatedHolder.TYPE;
+ <#else>
return this.holder.TYPE;
+ </#if>
</#if>
}
@@ -161,7 +166,7 @@ public class ${holderMode}${name}HolderReaderImpl extends AbstractFieldReader {
<#if minor.class == "VarBinary">
return value;
<#elseif minor.class == "VarDecimal">
- return org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromDrillBuf(holder.buffer, holder.start, holder.end-holder.start, holder.scale);
+ return org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromDrillBuf(holder.buffer, holder.start, holder.end - holder.start, holder.scale);
<#elseif minor.class == "Var16Char">
return new String(value);
<#elseif minor.class == "VarChar">
@@ -236,7 +241,7 @@ public class ${holderMode}${name}HolderReaderImpl extends AbstractFieldReader {
<#if minor.class == "VarBinary">
return value;
<#elseif minor.class == "VarDecimal">
- return org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromDrillBuf(holder.buffer, holder.start, holder.end-holder.start, holder.scale);
+ return org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromDrillBuf(holder.buffer, holder.start, holder.end - holder.start, holder.scale);
<#elseif minor.class == "Var16Char">
return new String(value);
<#elseif minor.class == "VarChar">
diff --git a/exec/vector/src/main/codegen/templates/ListWriters.java b/exec/vector/src/main/codegen/templates/ListWriters.java
index d7a66f75d..cab8772a7 100644
--- a/exec/vector/src/main/codegen/templates/ListWriters.java
+++ b/exec/vector/src/main/codegen/templates/ListWriters.java
@@ -156,10 +156,24 @@ public class ${mode}ListWriter extends AbstractFieldWriter {
<#assign upperName = minor.class?upper_case />
<#assign capName = minor.class?cap_first />
<#if lowerName == "int" ><#assign lowerName = "integer" /></#if>
+
+ <#if minor.class?contains("Decimal") >
+ @Override
+ public ${capName}Writer ${lowerName}() {
+ // returns existing writer
+ assert mode == Mode.IN_${upperName};
+ return writer;
+ }
+
+ @Override
+ public ${capName}Writer ${lowerName}(int scale, int precision) {
+ final MajorType ${upperName}_TYPE = Types.withScaleAndPrecision(MinorType.${upperName}, DataMode.REPEATED, scale, precision);
+ <#else>
private static final MajorType ${upperName}_TYPE = Types.repeated(MinorType.${upperName});
@Override
public ${capName}Writer ${lowerName}() {
+ </#if>
switch (mode) {
case INIT:
final int vectorCount = container.size();
@@ -181,14 +195,14 @@ public class ${mode}ListWriter extends AbstractFieldWriter {
.build(logger);
}
}
-
+
</#list></#list>
@Override
public MaterializedField getField() {
return container.getField();
}
<#if mode == "Repeated">
-
+
@Override
public void startList() {
final RepeatedListVector list = (RepeatedListVector) container;
diff --git a/exec/vector/src/main/codegen/templates/MapWriters.java b/exec/vector/src/main/codegen/templates/MapWriters.java
index 0f0552817..9074293d7 100644
--- a/exec/vector/src/main/codegen/templates/MapWriters.java
+++ b/exec/vector/src/main/codegen/templates/MapWriters.java
@@ -197,7 +197,8 @@ public class ${mode}MapWriter extends AbstractFieldWriter {
<#assign vectName = capName />
<#assign vectName = "Nullable${capName}" />
- <#if minor.class?starts_with("Decimal") >
+ <#if minor.class?contains("Decimal") >
+ @Override
public ${minor.class}Writer ${lowerName}(String name) {
// returns existing writer
final FieldWriter writer = fields.get(name.toLowerCase());
@@ -205,6 +206,7 @@ public class ${mode}MapWriter extends AbstractFieldWriter {
return writer;
}
+ @Override
public ${minor.class}Writer ${lowerName}(String name, int scale, int precision) {
final MajorType ${upperName}_TYPE = Types.withScaleAndPrecision(MinorType.${upperName}, DataMode.OPTIONAL, scale, precision);
<#else>
diff --git a/exec/vector/src/main/codegen/templates/NullReader.java b/exec/vector/src/main/codegen/templates/NullReader.java
index 32ee9b9b9..4d867baa4 100644
--- a/exec/vector/src/main/codegen/templates/NullReader.java
+++ b/exec/vector/src/main/codegen/templates/NullReader.java
@@ -31,20 +31,18 @@ import org.apache.drill.common.types.TypeProtos;
* This class is generated using freemarker and the ${.template_name} template.
*/
@SuppressWarnings("unused")
-public class NullReader extends AbstractBaseReader implements FieldReader{
+public class NullReader extends AbstractBaseReader implements FieldReader {
public static final NullReader INSTANCE = new NullReader();
public static final NullReader EMPTY_LIST_INSTANCE = new NullReader(Types.repeated(TypeProtos.MinorType.NULL));
public static final NullReader EMPTY_MAP_INSTANCE = new NullReader(Types.required(TypeProtos.MinorType.MAP));
private MajorType type;
- private NullReader(){
- super();
+ private NullReader() {
type = Types.NULL;
}
- private NullReader(MajorType type){
- super();
+ private NullReader(MajorType type) {
this.type = type;
}
@@ -60,63 +58,67 @@ public class NullReader extends AbstractBaseReader implements FieldReader{
public void copyAsValue(UnionWriter writer) {}
<#list vv.types as type><#list type.minor as minor><#assign name = minor.class?cap_first />
- public void read(${name}Holder holder){
+ public void read(${name}Holder holder) {
throw new UnsupportedOperationException("NullReader cannot write into non-nullable holder");
}
- public void read(Nullable${name}Holder holder){
+ public void read(Nullable${name}Holder holder) {
holder.isSet = 0;
}
- public void read(int arrayIndex, ${name}Holder holder){
+ public void read(int arrayIndex, ${name}Holder holder) {
throw new ArrayIndexOutOfBoundsException();
}
- public void copyAsValue(${minor.class}Writer writer){}
- public void copyAsField(String name, ${minor.class}Writer writer){}
+ public void copyAsValue(${minor.class}Writer writer) {}
+ <#if minor.class == "VarDecimal">
+ public void copyAsField(String name, ${minor.class}Writer writer, int scale, int precision) {}
+ <#else>
+ public void copyAsField(String name, ${minor.class}Writer writer) {}
+ </#if>
- public void read(int arrayIndex, Nullable${name}Holder holder){
+ public void read(int arrayIndex, Nullable${name}Holder holder) {
throw new ArrayIndexOutOfBoundsException();
}
</#list></#list>
- public int size(){
+ public int size() {
return 0;
}
- public boolean isSet(){
+ public boolean isSet() {
return false;
}
- public boolean next(){
+ public boolean next() {
return false;
}
- public RepeatedMapReader map(){
+ public RepeatedMapReader map() {
return this;
}
- public RepeatedListReader list(){
+ public RepeatedListReader list() {
return this;
}
- public MapReader map(String name){
+ public MapReader map(String name) {
return this;
}
- public ListReader list(String name){
+ public ListReader list(String name) {
return this;
}
- public FieldReader reader(String name){
+ public FieldReader reader(String name) {
return this;
}
- public FieldReader reader(){
+ public FieldReader reader() {
return this;
}
- private void fail(String name){
+ private void fail(String name) {
throw new IllegalArgumentException(String.format("You tried to read a %s type when you are using a ValueReader of type %s.", name, this.getClass().getSimpleName()));
}
@@ -126,11 +128,11 @@ public class NullReader extends AbstractBaseReader implements FieldReader{
<#assign safeType=friendlyType />
<#if safeType=="byte[]"><#assign safeType="ByteArray" /></#if>
- public ${friendlyType} read${safeType}(int arrayIndex){
+ public ${friendlyType} read${safeType}(int arrayIndex) {
return null;
}
- public ${friendlyType} read${safeType}(){
+ public ${friendlyType} read${safeType}() {
return null;
}
</#list>
diff --git a/exec/vector/src/main/codegen/templates/NullableValueVectors.java b/exec/vector/src/main/codegen/templates/NullableValueVectors.java
index 8be5c8b86..c9c098743 100644
--- a/exec/vector/src/main/codegen/templates/NullableValueVectors.java
+++ b/exec/vector/src/main/codegen/templates/NullableValueVectors.java
@@ -482,7 +482,7 @@ public final class ${className} extends BaseDataValueVector implements <#if type
vAccessor.get(index, holder);
holder.isSet = bAccessor.get(index);
- <#if minor.class.startsWith("Decimal")>
+ <#if minor.class.contains("Decimal")>
holder.scale = getField().getScale();
holder.precision = getField().getPrecision();
</#if>
@@ -694,17 +694,29 @@ public final class ${className} extends BaseDataValueVector implements <#if type
}
</#if>
- <#if minor.class == "Decimal28Sparse" || minor.class == "Decimal38Sparse">
+ <#if minor.class == "Decimal28Sparse" || minor.class == "Decimal38Sparse" || minor.class == "VarDecimal">
public void set(int index, BigDecimal value) {
+ <#if type.major == "VarLen">
+ if (index > lastSet + 1) {
+ fillEmpties(index);
+ }
+ </#if>
bits.getMutator().set(index, 1);
values.getMutator().set(index, value);
setCount++;
+ <#if type.major == "VarLen">lastSet = index;</#if>
}
public void setSafe(int index, BigDecimal value) {
+ <#if type.major == "VarLen">
+ if (index > lastSet + 1) {
+ fillEmpties(index);
+ }
+ </#if>
bits.getMutator().setSafe(index, 1);
values.getMutator().setSafe(index, value);
setCount++;
+ <#if type.major == "VarLen">lastSet = index;</#if>
}
</#if>
diff --git a/exec/vector/src/main/codegen/templates/RepeatedValueVectors.java b/exec/vector/src/main/codegen/templates/RepeatedValueVectors.java
index 2b2b6bd9a..e9884208f 100644
--- a/exec/vector/src/main/codegen/templates/RepeatedValueVectors.java
+++ b/exec/vector/src/main/codegen/templates/RepeatedValueVectors.java
@@ -404,20 +404,14 @@ public final class Repeated${minor.class}Vector extends BaseRepeatedValueVector
}
}
- <#if (fields?size > 1) && !(minor.class == "Decimal9" || minor.class == "Decimal18" || minor.class == "Decimal28Sparse" || minor.class == "Decimal38Sparse" || minor.class == "Decimal28Dense" || minor.class == "Decimal38Dense")>
- <#if minor.class == "VarDecimal">
- public void addSafe(int arrayIndex, <#list fields as field><#if field.name == "scale"><#break></#if>${field.type} ${field.name}<#if field_has_next && fields[field_index+1].name != "scale" >, </#if></#list>) {
- int nextOffset = offsets.getAccessor().get(arrayIndex+1);
- values.getMutator().setSafe(nextOffset, <#list fields as field><#if field.name == "scale"><#break></#if>${field.name}<#if field_has_next && fields[field_index+1].name != "scale">, </#if></#list>);
- offsets.getMutator().setSafe(arrayIndex+1, nextOffset+1);
- }
- <#else>
- public void addSafe(int rowIndex, <#list fields as field>${field.type} ${field.name}<#if field_has_next>, </#if></#list>) {
+ <#if (fields?size > 1) && !(minor.class == "Decimal9" || minor.class == "Decimal18"
+ || minor.class == "Decimal28Sparse" || minor.class == "Decimal38Sparse" || minor.class == "Decimal28Dense"
+ || minor.class == "Decimal38Dense") || minor.class == "VarDecimal">
+ public void addSafe(int rowIndex<#list fields as field><#if field.include!true>, ${field.type} ${field.name}</#if></#list>) {
final int nextOffset = offsets.getAccessor().get(rowIndex+1);
- values.getMutator().setSafe(nextOffset, <#list fields as field>${field.name}<#if field_has_next>, </#if></#list>);
- offsets.getMutator().setSafe(rowIndex+1, nextOffset+1);
+ values.getMutator().setSafe(nextOffset<#list fields as field><#if field.include!true>, ${field.name}</#if></#list>);
+ offsets.getMutator().setSafe(rowIndex + 1, nextOffset + 1);
}
- </#if>
</#if>
<#if minor.class == "Decimal28Sparse" || minor.class == "Decimal38Sparse">
diff --git a/exec/vector/src/main/codegen/templates/UnionListWriter.java b/exec/vector/src/main/codegen/templates/UnionListWriter.java
index a0d26a020..4ea907d1b 100644
--- a/exec/vector/src/main/codegen/templates/UnionListWriter.java
+++ b/exec/vector/src/main/codegen/templates/UnionListWriter.java
@@ -81,6 +81,17 @@ public class UnionListWriter extends AbstractFieldWriter {
return this;
}
+ <#if minor.class == "VarDecimal">
+ @Override
+ public ${name}Writer <#if uncappedName == "int">integer<#else>${uncappedName}</#if>(String name, int scale, int precision) {
+ assert inMap;
+ final int nextOffset = offsets.getAccessor().get(idx() + 1);
+ vector.getMutator().setNotNull(idx());
+ writer.setPosition(nextOffset);
+ ${name}Writer ${uncappedName}Writer = writer.${uncappedName}(name, scale, precision);
+ return ${uncappedName}Writer;
+ }
+ <#else>
@Override
public ${name}Writer <#if uncappedName == "int">integer<#else>${uncappedName}</#if>(String name) {
assert inMap;
@@ -91,6 +102,7 @@ public class UnionListWriter extends AbstractFieldWriter {
return ${uncappedName}Writer;
}
</#if>
+ </#if>
</#list></#list>
@Override
diff --git a/exec/vector/src/main/codegen/templates/UnionWriter.java b/exec/vector/src/main/codegen/templates/UnionWriter.java
index 961810e3a..13c093acf 100644
--- a/exec/vector/src/main/codegen/templates/UnionWriter.java
+++ b/exec/vector/src/main/codegen/templates/UnionWriter.java
@@ -181,7 +181,21 @@ public class UnionWriter extends AbstractFieldWriter implements FieldWriter {
<#if lowerName == "int" ><#assign lowerName = "integer" /></#if>
<#assign upperName = minor.class?upper_case />
<#assign capName = minor.class?cap_first />
- <#if !minor.class?starts_with("Decimal")>
+ <#if minor.class == "VarDecimal">
+ @Override
+ public ${capName}Writer ${lowerName}(String name, int scale, int precision) {
+ data.getMutator().setType(idx(), MinorType.MAP);
+ getMapWriter().setPosition(idx());
+ return getMapWriter().${lowerName}(name, scale, precision);
+ }
+
+ @Override
+ public ${capName}Writer ${lowerName}(int scale, int precision) {
+ data.getMutator().setType(idx(), MinorType.LIST);
+ getListWriter().setPosition(idx());
+ return getListWriter().${lowerName}(scale, precision);
+ }
+ <#else>
@Override
public ${capName}Writer ${lowerName}(String name) {
data.getMutator().setType(idx(), MinorType.MAP);
diff --git a/exec/vector/src/main/codegen/templates/ValueHolders.java b/exec/vector/src/main/codegen/templates/ValueHolders.java
index d5b4342df..7635895be 100644
--- a/exec/vector/src/main/codegen/templates/ValueHolders.java
+++ b/exec/vector/src/main/codegen/templates/ValueHolders.java
@@ -32,99 +32,90 @@ package org.apache.drill.exec.expr.holders;
/*
* This class is generated using freemarker and the ${.template_name} template.
*/
-public final class ${className} implements ValueHolder{
-
+<#if minor.class.contains("Decimal") && !minor.class.contains("VarDecimal")>
+/**
+ * Old decimal types are deprecated. Please use {@link VarDecimalHolder} holder instead.
+ */
+@Deprecated
+</#if>
+public final class ${className} implements ValueHolder {
+
+ <#if minor.class.contains("Decimal")>
+ @Deprecated
+ </#if>
public static final MajorType TYPE = Types.${mode.name?lower_case}(MinorType.${minor.class?upper_case});
- <#if mode.name == "Repeated">
+ <#if mode.name == "Repeated">
- /** The first index (inclusive) into the Vector. **/
- public int start;
+ /** The first index (inclusive) into the Vector. **/
+ public int start;
- /** The last index (exclusive) into the Vector. **/
- public int end;
+ /** The last index (exclusive) into the Vector. **/
+ public int end;
- /** The Vector holding the actual values. **/
- public ${minor.class}Vector vector;
+ /** The Vector holding the actual values. **/
+ public ${minor.class}Vector vector;
- <#else>
- public static final int WIDTH = ${type.width};
+ <#else>
+ public static final int WIDTH = ${type.width};
- <#if mode.name == "Optional">public int isSet;</#if>
- <#assign fields = minor.fields!type.fields />
- <#list fields as field>
- public ${field.type} ${field.name};
- </#list>
+ <#if mode.name == "Optional">public int isSet;</#if>
+ <#assign fields = minor.fields!type.fields />
+ <#list fields as field>
+ public ${field.type} ${field.name};
+ </#list>
- <#if minor.class.startsWith("Decimal")>
- public static final int maxPrecision = ${minor.maxPrecisionDigits};
- <#if minor.class.startsWith("Decimal28") || minor.class.startsWith("Decimal38")>
- public static final int nDecimalDigits = ${minor.nDecimalDigits};
+ <#if minor.class.startsWith("Decimal")>
+ public static final int maxPrecision = ${minor.maxPrecisionDigits};
+ <#if minor.class.startsWith("Decimal28") || minor.class.startsWith("Decimal38")>
+ public static final int nDecimalDigits = ${minor.nDecimalDigits};
- public static int getInteger(int index, int start, DrillBuf buffer) {
- int value = buffer.getInt(start + (index * 4));
+ public static int getInteger(int index, int start, DrillBuf buffer) {
+ int value = buffer.getInt(start + (index * 4));
- if (index == 0) {
- /* the first byte contains sign bit, return value without it */
- <#if minor.class.endsWith("Sparse")>
- value = (value & 0x7FFFFFFF);
- <#elseif minor.class.endsWith("Dense")>
- value = (value & 0x0000007F);
- </#if>
- }
- return value;
+ if (index == 0) {
+ /* the first byte contains sign bit, return value without it */
+ <#if minor.class.endsWith("Sparse")>
+ value = (value & 0x7FFFFFFF);
+ <#elseif minor.class.endsWith("Dense")>
+ value = (value & 0x0000007F);
+ </#if>
}
+ return value;
+ }
- public static void setInteger(int index, int value, int start, DrillBuf buffer) {
- buffer.setInt(start + (index * 4), value);
- }
+ public static void setInteger(int index, int value, int start, DrillBuf buffer) {
+ buffer.setInt(start + (index * 4), value);
+ }
- public static void setSign(boolean sign, int start, DrillBuf buffer) {
- // Set MSB to 1 if sign is negative
- if (sign == true) {
- int value = getInteger(0, start, buffer);
- setInteger(0, (value | 0x80000000), start, buffer);
- }
+ public static void setSign(boolean sign, int start, DrillBuf buffer) {
+ // Set MSB to 1 if sign is negative
+ if (sign == true) {
+ int value = getInteger(0, start, buffer);
+ setInteger(0, (value | 0x80000000), start, buffer);
}
+ }
- public static boolean getSign(int start, DrillBuf buffer) {
- return ((buffer.getInt(start) & 0x80000000) != 0);
- }
-
- public java.math.BigDecimal getBigDecimal() {
- java.math.BigDecimal currentValue = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromSparse(buffer, start, nDecimalDigits, scale);
- return currentValue;
- }
- </#if></#if>
-
- <#if minor.class.startsWith("VarDecimal")>
- public java.math.BigDecimal getBigDecimal() {
- //System.out.println("valueHolder start " + start + " end " + " end " + " scale " + scale);
- java.math.BigDecimal currentValue = org.apache.drill.exec.util.DecimalUtility.getBigDecimalFromDrillBuf(buffer, start, end-start, scale);
- return currentValue;
- }
- </#if>
+ public static boolean getSign(int start, DrillBuf buffer) {
+ return ((buffer.getInt(start) & 0x80000000) != 0);
+ }
- @Deprecated
- public int hashCode(){
- throw new UnsupportedOperationException();
- }
+ </#if></#if>
+ @Deprecated
+ public int hashCode() {
+ throw new UnsupportedOperationException();
+ }
- /*
- * Reason for deprecation is that ValueHolders are potential scalar replacements
- * and hence we don't want any methods to be invoked on them.
- */
- @Deprecated
- public String toString(){
- throw new UnsupportedOperationException();
- }
- </#if>
-
-
-
-
+ /*
+ * Reason for deprecation is that ValueHolders are potential scalar replacements
+ * and hence we don't want any methods to be invoked on them.
+ */
+ @Deprecated
+ public String toString() {
+ throw new UnsupportedOperationException();
+ }
+ </#if>
}
-
</#list>
</#list>
</#list>
diff --git a/exec/vector/src/main/codegen/templates/VariableLengthVectors.java b/exec/vector/src/main/codegen/templates/VariableLengthVectors.java
index 8ab4c3a48..6a67772ce 100644
--- a/exec/vector/src/main/codegen/templates/VariableLengthVectors.java
+++ b/exec/vector/src/main/codegen/templates/VariableLengthVectors.java
@@ -464,6 +464,10 @@ public final class ${minor.class}Vector extends BaseDataValueVector implements V
holder.start = oAccessor.get(index);
holder.end = oAccessor.get(index + 1);
holder.buffer = data;
+ <#if minor.class.contains("Decimal")>
+ holder.scale = field.getScale();
+ holder.precision = field.getPrecision();
+ </#if>
}
public void get(int index, Nullable${minor.class}Holder holder){
@@ -471,6 +475,10 @@ public final class ${minor.class}Vector extends BaseDataValueVector implements V
holder.start = oAccessor.get(index);
holder.end = oAccessor.get(index + 1);
holder.buffer = data;
+ <#if minor.class.contains("Decimal")>
+ holder.scale = field.getScale();
+ holder.precision = field.getPrecision();
+ </#if>
}
<#switch minor.class>
@@ -478,7 +486,7 @@ public final class ${minor.class}Vector extends BaseDataValueVector implements V
@Override
public ${friendlyType} getObject(int index) {
byte[] b = get(index);
- BigInteger bi = b.length == 0 ? new BigInteger("0") : new BigInteger(b);
+ BigInteger bi = b.length == 0 ? BigInteger.ZERO : new BigInteger(b);
BigDecimal bd = new BigDecimal(bi, getField().getScale());
return bd;
}
@@ -672,6 +680,18 @@ public final class ${minor.class}Vector extends BaseDataValueVector implements V
offsetVector.getMutator().setSafe(index + 1, outputStart + len);
}
+ <#if minor.class == "VarDecimal">
+ public void set(int index, BigDecimal value) {
+ byte[] bytes = value.unscaledValue().toByteArray();
+ set(index, bytes, 0, bytes.length);
+ }
+
+ public void setSafe(int index, BigDecimal value) {
+ byte[] bytes = value.unscaledValue().toByteArray();
+ setSafe(index, bytes, 0, bytes.length);
+ }
+ </#if>
+
public void setSafe(int index, ${minor.class}Holder holder) {
final int start = holder.start;
final int end = holder.end;
diff --git a/exec/vector/src/main/java/org/apache/drill/exec/util/DecimalUtility.java b/exec/vector/src/main/java/org/apache/drill/exec/util/DecimalUtility.java
index 82809547d..a451b974f 100644
--- a/exec/vector/src/main/java/org/apache/drill/exec/util/DecimalUtility.java
+++ b/exec/vector/src/main/java/org/apache/drill/exec/util/DecimalUtility.java
@@ -17,20 +17,23 @@
*/
package org.apache.drill.exec.util;
+import com.google.common.math.BigIntegerMath;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.DrillBuf;
import io.netty.buffer.UnpooledByteBufAllocator;
import java.math.BigDecimal;
import java.math.BigInteger;
+import java.math.RoundingMode;
import java.nio.ByteBuffer;
import java.util.Arrays;
+import org.apache.drill.common.types.TypeProtos;
import org.apache.drill.common.util.CoreDecimalUtility;
import org.apache.drill.exec.expr.fn.impl.ByteFunctionHelpers;
import org.apache.drill.exec.expr.holders.Decimal38SparseHolder;
-public class DecimalUtility extends CoreDecimalUtility{
+public class DecimalUtility extends CoreDecimalUtility {
public final static int MAX_DIGITS = 9;
public final static int MAX_DIGITS_INT = 10;
@@ -152,18 +155,18 @@ public class DecimalUtility extends CoreDecimalUtility{
return getBigDecimalFromDrillBuf(data, startIndex, nDecimalDigits, scale, false);
}
- public static BigDecimal getBigDecimalFromSparse(DrillBuf data, int startIndex, int nDecimalDigits, int scale) {
+ public static BigDecimal getBigDecimalFromSparse(DrillBuf data, int startIndex, int nDecimalDigits, int scale) {
- // In the sparse representation we pad the scale with zeroes for ease of arithmetic, need to truncate
- return getBigDecimalFromDrillBuf(data, startIndex, nDecimalDigits, scale, true);
- }
+ // In the sparse representation we pad the scale with zeroes for ease of arithmetic, need to truncate
+ return getBigDecimalFromDrillBuf(data, startIndex, nDecimalDigits, scale, true);
+ }
- public static BigDecimal getBigDecimalFromDrillBuf(DrillBuf bytebuf, int start, int length, int scale) {
- byte[] value = new byte[length];
- bytebuf.getBytes(start, value, 0, length);
- BigInteger unscaledValue = new BigInteger(value);
- return new BigDecimal(unscaledValue, scale);
- }
+ public static BigDecimal getBigDecimalFromDrillBuf(DrillBuf bytebuf, int start, int length, int scale) {
+ byte[] value = new byte[length];
+ bytebuf.getBytes(start, value, 0, length);
+ BigInteger unscaledValue = new BigInteger(value);
+ return new BigDecimal(unscaledValue, scale);
+ }
public static BigDecimal getBigDecimalFromByteBuffer(ByteBuffer bytebuf, int start, int length, int scale) {
byte[] value = new byte[length];
@@ -355,29 +358,27 @@ public class DecimalUtility extends CoreDecimalUtility{
scale -= MAX_DIGITS;
}
- // Set the negative sign
- if (sign == true) {
- data.setInt(startIndex, data.getInt(startIndex) | 0x80000000);
- }
-
+ // Set the negative sign
+ if (sign) {
+ data.setInt(startIndex, data.getInt(startIndex) | 0x80000000);
}
+ }
- /**
- * Converts from an input BigDecimal into varying width "VarDecimal" representation.
- * The object that manages the "data" is assumed to already have the proper scale set,
- * matching that of input.scale().
- * @param input input decimal number to be stored
- * @param data destination buffer to store the byte array representation of input
- * @param startIndex starting index in data to hold the bytes
- * @return startIndex + length of bytes stored (i.e., the next startIndex in the data buffer)
- */
- public static int getVarDecimalFromBigDecimal(BigDecimal input, ByteBuf data, int startIndex) {
- byte[] bytes = input.unscaledValue().toByteArray();
- int len = bytes.length;
- data.setBytes(startIndex, bytes);
- //System.out.println("getVarDecimal start " + startIndex + " len " + len + " value " + input);
- return startIndex + len;
- }
+ /**
+ * Converts from an input BigDecimal into varying width "VarDecimal" representation.
+ * The object that manages the "data" is assumed to already have the proper scale set,
+ * matching that of input.scale().
+ * @param input input decimal number to be stored
+ * @param data destination buffer to store the byte array representation of input
+ * @param startIndex starting index in data to hold the bytes
+ * @return startIndex + length of bytes stored (i.e., the next startIndex in the data buffer)
+ */
+ public static int getVarDecimalFromBigDecimal(BigDecimal input, ByteBuf data, int startIndex) {
+ byte[] bytes = input.unscaledValue().toByteArray();
+ int len = bytes.length;
+ data.setBytes(startIndex, bytes);
+ return startIndex + len;
+ }
public static long getDecimal18FromBigDecimal(BigDecimal input, int scale, int precision) {
// Truncate or pad to set the input to the correct scale
@@ -451,31 +452,52 @@ public class DecimalUtility extends CoreDecimalUtility{
buffer.setInt(start + (index * 4), value);
}
- /**
- * Compares two VarDecimal values, still stored in their respective Drill buffers
- * @param left left value Drill buffer
- * @param leftStart start offset of left value
- * @param leftEnd end offset of left value
- * @param leftScale scale of left value
- * @param right right value Drill buffer
- * @param rightStart start offset of right value
- * @param rightEnd end offset of right value
- * @param rightScale scale of right value
- * @param absCompare comparison of absolute values is done iff this is true
- * @return 1 if left > right, 0 if left = right, -1 if left < right. two values that are numerically equal, but with different
- * scales (e.g., 2.00 and 2), are considered equal.
- */
- public static int compareVarLenBytes(DrillBuf left, int leftStart, int leftEnd, int leftScale, DrillBuf right, int rightStart, int rightEnd, int rightScale, boolean absCompare) {
- java.math.BigDecimal bdLeft = getBigDecimalFromDrillBuf(left, leftStart, leftEnd - leftStart, leftScale);
- java.math.BigDecimal bdRight = getBigDecimalFromDrillBuf(right, rightStart, rightEnd - rightStart, rightScale);
- if (absCompare) {
- bdLeft = bdLeft.abs();
- bdRight = bdRight.abs();
- }
- return bdLeft.compareTo(bdRight);
- }
+ /**
+ * Compares two VarDecimal values, still stored in their respective Drill buffers
+ *
+ * @param left left value Drill buffer
+ * @param leftStart start offset of left value
+ * @param leftEnd end offset of left value
+ * @param leftScale scale of left value
+ * @param right right value Drill buffer
+ * @param rightStart start offset of right value
+ * @param rightEnd end offset of right value
+ * @param rightScale scale of right value
+ * @param absCompare comparison of absolute values is done iff this is true
+ * @return 1 if left > right, 0 if left = right, -1 if left < right. two values that are numerically equal, but with different
+ * scales (e.g., 2.00 and 2), are considered equal.
+ */
+ public static int compareVarLenBytes(DrillBuf left, int leftStart, int leftEnd, int leftScale, DrillBuf right, int rightStart, int rightEnd, int rightScale, boolean absCompare) {
+ byte[] rightBytes = new byte[rightEnd - rightStart];
+ right.getBytes(rightStart, rightBytes, 0, rightEnd - rightStart);
+
+ return compareVarLenBytes(left, leftStart, leftEnd, leftScale, rightBytes, rightScale, absCompare);
+ }
+
+ /**
+ * Compares two VarDecimal values, still stored in Drill buffer and byte array
+ *
+ * @param left left value Drill buffer
+ * @param leftStart start offset of left value
+ * @param leftEnd end offset of left value
+ * @param leftScale scale of left value
+ * @param right right value byte array
+ * @param rightScale scale of right value
+ * @param absCompare comparison of absolute values is done iff this is true
+ * @return 1 if left > right, 0 if left = right, -1 if left < right. two values that are numerically equal, but with different
+ * scales (e.g., 2.00 and 2), are considered equal.
+ */
+ public static int compareVarLenBytes(DrillBuf left, int leftStart, int leftEnd, int leftScale, byte right[], int rightScale, boolean absCompare) {
+ java.math.BigDecimal bdLeft = getBigDecimalFromDrillBuf(left, leftStart, leftEnd - leftStart, leftScale);
+ java.math.BigDecimal bdRight = new BigDecimal(new BigInteger(right), rightScale);
+ if (absCompare) {
+ bdLeft = bdLeft.abs();
+ bdRight = bdRight.abs();
+ }
+ return bdLeft.compareTo(bdRight);
+ }
- public static int compareSparseBytes(DrillBuf left, int leftStart, boolean leftSign, int leftScale, int leftPrecision, DrillBuf right, int rightStart, boolean rightSign, int rightPrecision, int rightScale, int width, int nDecimalDigits, boolean absCompare) {
+ public static int compareSparseBytes(DrillBuf left, int leftStart, boolean leftSign, int leftScale, int leftPrecision, DrillBuf right, int rightStart, boolean rightSign, int rightPrecision, int rightScale, int width, int nDecimalDigits, boolean absCompare) {
int invert = 1;
@@ -782,5 +804,73 @@ public class DecimalUtility extends CoreDecimalUtility{
}
return cmp * invert;
}
-}
+ /**
+ * Returns max length of byte array, required to store value with specified precision.
+ *
+ * @param precision the precision of value
+ *
+ * @return max length of byte array
+ */
+ public static int getMaxBytesSizeForPrecision(int precision) {
+ if (precision == 0) {
+ return 0;
+ }
+ if (precision < 300) { // normal case, use exact heuristic formula
+ return (int) Math.ceil((Math.log(Math.pow(10, precision) - 1) / Math.log(2) + 1) / Byte.SIZE);
+ } else {
+ // for values greater than 304 Math.pow(10, precision) returns Infinity, therefore 1 is neglected in Math.log()
+ return (int) Math.ceil((precision * Math.log(10) / Math.log(2) + 1) / Byte.SIZE);
+ }
+ }
+
+ /**
+ * Calculates and returns square root for specified BigDecimal
+ * with specified number of digits alter decimal point.
+ *
+ * @param in BigDecimal which square root should be calculated
+ * @param scale number of digits alter decimal point in the result value.
+ * @return square root for specified BigDecimal
+ */
+ public static BigDecimal sqrt(BigDecimal in, int scale) {
+ // unscaled BigInteger value from specified BigDecimal with doubled number of digits after decimal point
+ // was used to calculate sqrt using Guava's BigIntegerMath.
+ BigInteger valueWithDoubleMaxPrecision =
+ in.multiply(BigDecimal.TEN.pow(scale * 2)).setScale(0, RoundingMode.HALF_UP).unscaledValue();
+ return new BigDecimal(
+ BigIntegerMath.sqrt(valueWithDoubleMaxPrecision, RoundingMode.HALF_UP), scale);
+ }
+
+ /**
+ * Checks that specified decimal minorType is obsolete.
+ *
+ * @param minorType type to check
+ * @return true if specified decimal minorType is obsolete.
+ */
+ public static boolean isObsoleteDecimalType(TypeProtos.MinorType minorType) {
+ return minorType == TypeProtos.MinorType.DECIMAL9 ||
+ minorType == TypeProtos.MinorType.DECIMAL18 ||
+ minorType == TypeProtos.MinorType.DECIMAL28SPARSE ||
+ minorType == TypeProtos.MinorType.DECIMAL38SPARSE;
+ }
+
+ /**
+ * Returns default precision for specified {@link TypeProtos.MinorType}
+ * or returns specified defaultPrecision if {@link TypeProtos.MinorType} isn't
+ * {@link TypeProtos.MinorType#INT} or {@link TypeProtos.MinorType#BIGINT}.
+ *
+ * @param minorType type wich precision should be received
+ * @param defaultPrecision default value for precision
+ * @return default precision for specified {@link TypeProtos.MinorType}
+ */
+ public static int getDefaultPrecision(TypeProtos.MinorType minorType, int defaultPrecision) {
+ switch (minorType) {
+ case INT:
+ return MAX_DIGITS_INT;
+ case BIGINT:
+ return MAX_DIGITS_BIGINT;
+ default:
+ return defaultPrecision;
+ }
+ }
+}
diff --git a/exec/vector/src/main/java/org/apache/drill/exec/vector/ValueHolderHelper.java b/exec/vector/src/main/java/org/apache/drill/exec/vector/ValueHolderHelper.java
index 73b2b551e..d1cc3b4a1 100644
--- a/exec/vector/src/main/java/org/apache/drill/exec/vector/ValueHolderHelper.java
+++ b/exec/vector/src/main/java/org/apache/drill/exec/vector/ValueHolderHelper.java
@@ -37,6 +37,7 @@ import org.apache.drill.exec.expr.holders.NullableBitHolder;
import org.apache.drill.exec.expr.holders.TimeHolder;
import org.apache.drill.exec.expr.holders.TimeStampHolder;
import org.apache.drill.exec.expr.holders.VarCharHolder;
+import org.apache.drill.exec.expr.holders.VarDecimalHolder;
import org.apache.drill.exec.memory.BufferAllocator;
import org.apache.drill.exec.util.DecimalUtility;
@@ -200,4 +201,22 @@ public class ValueHolderHelper {
return dch;
}
+
+ public static VarDecimalHolder getVarDecimalHolder(DrillBuf buf, String decimal) {
+ VarDecimalHolder dch = new VarDecimalHolder();
+
+ BigDecimal bigDecimal = new BigDecimal(decimal);
+
+ byte[] bytes = bigDecimal.unscaledValue().toByteArray();
+ int length = bytes.length;
+
+ dch.scale = bigDecimal.scale();
+ dch.precision = bigDecimal.precision();
+ dch.start = 0;
+ dch.end = length;
+ dch.buffer = buf.reallocIfNeeded(length);
+ dch.buffer.setBytes(0, bytes);
+
+ return dch;
+ }
}
diff --git a/exec/vector/src/main/java/org/apache/drill/exec/vector/complex/impl/MapOrListWriterImpl.java b/exec/vector/src/main/java/org/apache/drill/exec/vector/complex/impl/MapOrListWriterImpl.java
index 1fa785748..937df8603 100644
--- a/exec/vector/src/main/java/org/apache/drill/exec/vector/complex/impl/MapOrListWriterImpl.java
+++ b/exec/vector/src/main/java/org/apache/drill/exec/vector/complex/impl/MapOrListWriterImpl.java
@@ -229,6 +229,11 @@ public class MapOrListWriterImpl implements MapOrListWriter {
}
@Override
+ public VarDecimalWriter varDecimal(String name, int scale, int precision) {
+ return (map != null) ? map.varDecimal(name, scale, precision) : list.varDecimal(scale, precision);
+ }
+
+ @Override
public Decimal38SparseWriter decimal38Sparse(String name) {
return (map != null) ? map.decimal38Sparse(name) : list.decimal38Sparse();
}
diff --git a/logical/src/main/antlr3/org/apache/drill/common/expression/parser/ExprLexer.g b/logical/src/main/antlr3/org/apache/drill/common/expression/parser/ExprLexer.g
index 02979da26..2b497a195 100644
--- a/logical/src/main/antlr3/org/apache/drill/common/expression/parser/ExprLexer.g
+++ b/logical/src/main/antlr3/org/apache/drill/common/expression/parser/ExprLexer.g
@@ -62,7 +62,7 @@ DECIMAL28DENSE : 'decimal28dense' | 'DECIMAL28DENSE';
DECIMAL28SPARSE : 'decimal28sparse' | 'DECIMAL28SPARSE';
DECIMAL38DENSE : 'decimal38dense' | 'DECIMAL38DENSE';
DECIMAL38SPARSE : 'decimal38sparse' | 'DECIMAL38SPARSE';
-VARDECIMAL : 'varDecimal' | 'VARDECIMAL';
+VARDECIMAL : 'vardecimal' | 'VARDECIMAL';
Or : 'or' | 'OR' | 'Or';
And : 'and' | 'AND' ;
Equals : '==' | '=';
diff --git a/logical/src/main/java/org/apache/drill/common/expression/ExpressionStringBuilder.java b/logical/src/main/java/org/apache/drill/common/expression/ExpressionStringBuilder.java
index e5aec87ea..f09f88741 100644
--- a/logical/src/main/java/org/apache/drill/common/expression/ExpressionStringBuilder.java
+++ b/logical/src/main/java/org/apache/drill/common/expression/ExpressionStringBuilder.java
@@ -35,6 +35,7 @@ import org.apache.drill.common.expression.ValueExpressions.LongExpression;
import org.apache.drill.common.expression.ValueExpressions.QuotedString;
import org.apache.drill.common.expression.ValueExpressions.TimeExpression;
import org.apache.drill.common.expression.ValueExpressions.TimeStampExpression;
+import org.apache.drill.common.expression.ValueExpressions.VarDecimalExpression;
import org.apache.drill.common.expression.visitors.AbstractExprVisitor;
import org.apache.drill.common.types.TypeProtos.MajorType;
import org.joda.time.Period;
@@ -217,6 +218,12 @@ public class ExpressionStringBuilder extends AbstractExprVisitor<Void, StringBui
}
@Override
+ public Void visitVarDecimalConstant(VarDecimalExpression decExpr, StringBuilder sb) throws RuntimeException {
+ sb.append(decExpr.getBigDecimal().toString());
+ return null;
+ }
+
+ @Override
public Void visitDoubleConstant(DoubleExpression dExpr, StringBuilder sb) throws RuntimeException {
sb.append(dExpr.getDouble());
return null;
@@ -292,7 +299,7 @@ public class ExpressionStringBuilder extends AbstractExprVisitor<Void, StringBui
case DECIMAL28SPARSE:
case DECIMAL38DENSE:
case DECIMAL38SPARSE:
- case VARDECIMAL: // TODO: precision might not be appropriate for VARDECIMAL, as it is "one-size-fits-all"
+ case VARDECIMAL:
// add scale and precision
sb.append("(");
sb.append(mt.getPrecision());
diff --git a/logical/src/main/java/org/apache/drill/common/expression/ValueExpressions.java b/logical/src/main/java/org/apache/drill/common/expression/ValueExpressions.java
index ef12d2f45..29e9c0519 100644
--- a/logical/src/main/java/org/apache/drill/common/expression/ValueExpressions.java
+++ b/logical/src/main/java/org/apache/drill/common/expression/ValueExpressions.java
@@ -18,6 +18,7 @@
package org.apache.drill.common.expression;
import java.math.BigDecimal;
+import java.util.Collections;
import java.util.GregorianCalendar;
import java.util.Iterator;
@@ -109,6 +110,10 @@ public class ValueExpressions {
return new Decimal38Expression(i, ExpressionPosition.UNKNOWN);
}
+ public static LogicalExpression getVarDecimal(BigDecimal i) {
+ return new VarDecimalExpression(i, ExpressionPosition.UNKNOWN);
+ }
+
public static LogicalExpression getNumericExpression(String sign, String s, ExpressionPosition ep) {
String numStr = (sign == null) ? s : sign+s;
try {
@@ -366,8 +371,6 @@ public class ValueExpressions {
}
- // TODO: is a class also needed for VARDECIMAL?
-
public static class Decimal38Expression extends LogicalExpressionBase {
private BigDecimal bigDecimal;
@@ -393,11 +396,45 @@ public class ValueExpressions {
@Override
public Iterator<LogicalExpression> iterator() {
- return Iterators.emptyIterator();
+ return Collections.emptyIterator();
}
}
+ public static class VarDecimalExpression extends LogicalExpressionBase {
+
+ private BigDecimal bigDecimal;
+
+ public VarDecimalExpression(BigDecimal input, ExpressionPosition pos) {
+ super(pos);
+ this.bigDecimal = input;
+ }
+
+ public BigDecimal getBigDecimal() {
+ return bigDecimal;
+ }
+
+ @Override
+ public MajorType getMajorType() {
+ return MajorType
+ .newBuilder()
+ .setMinorType(MinorType.VARDECIMAL)
+ .setScale(bigDecimal.scale())
+ .setPrecision(bigDecimal.precision())
+ .setMode(DataMode.REQUIRED)
+ .build();
+ }
+
+ @Override
+ public <T, V, E extends Exception> T accept(ExprVisitor<T, V, E> visitor, V value) throws E {
+ return visitor.visitVarDecimalConstant(this, value);
+ }
+
+ @Override
+ public Iterator<LogicalExpression> iterator() {
+ return Collections.emptyIterator();
+ }
+ }
public static class DoubleExpression extends LogicalExpressionBase {
private double d;
diff --git a/logical/src/main/java/org/apache/drill/common/expression/visitors/AbstractExprVisitor.java b/logical/src/main/java/org/apache/drill/common/expression/visitors/AbstractExprVisitor.java
index 5356813eb..845896849 100644
--- a/logical/src/main/java/org/apache/drill/common/expression/visitors/AbstractExprVisitor.java
+++ b/logical/src/main/java/org/apache/drill/common/expression/visitors/AbstractExprVisitor.java
@@ -44,6 +44,7 @@ import org.apache.drill.common.expression.ValueExpressions.ParameterExpression;
import org.apache.drill.common.expression.ValueExpressions.QuotedString;
import org.apache.drill.common.expression.ValueExpressions.TimeExpression;
import org.apache.drill.common.expression.ValueExpressions.TimeStampExpression;
+import org.apache.drill.common.expression.ValueExpressions.VarDecimalExpression;
public abstract class AbstractExprVisitor<T, VAL, EXCEP extends Exception> implements ExprVisitor<T, VAL, EXCEP> {
@@ -109,6 +110,11 @@ public abstract class AbstractExprVisitor<T, VAL, EXCEP extends Exception> imple
}
@Override
+ public T visitVarDecimalConstant(VarDecimalExpression decExpr, VAL value) throws EXCEP {
+ return visitUnknown(decExpr, value);
+ }
+
+ @Override
public T visitDateConstant(DateExpression intExpr, VAL value) throws EXCEP {
return visitUnknown(intExpr, value);
}
diff --git a/logical/src/main/java/org/apache/drill/common/expression/visitors/AggregateChecker.java b/logical/src/main/java/org/apache/drill/common/expression/visitors/AggregateChecker.java
index f6fe89dac..2e6b60b5e 100644
--- a/logical/src/main/java/org/apache/drill/common/expression/visitors/AggregateChecker.java
+++ b/logical/src/main/java/org/apache/drill/common/expression/visitors/AggregateChecker.java
@@ -46,6 +46,7 @@ import org.apache.drill.common.expression.ValueExpressions.LongExpression;
import org.apache.drill.common.expression.ValueExpressions.QuotedString;
import org.apache.drill.common.expression.ValueExpressions.TimeExpression;
import org.apache.drill.common.expression.ValueExpressions.TimeStampExpression;
+import org.apache.drill.common.expression.ValueExpressions.VarDecimalExpression;
public final class AggregateChecker implements ExprVisitor<Boolean, ErrorCollector, RuntimeException>{
@@ -151,6 +152,11 @@ public final class AggregateChecker implements ExprVisitor<Boolean, ErrorCollect
}
@Override
+ public Boolean visitVarDecimalConstant(VarDecimalExpression decExpr, ErrorCollector errors) {
+ return false;
+ }
+
+ @Override
public Boolean visitQuotedStringConstant(QuotedString e, ErrorCollector errors) {
return false;
}
diff --git a/logical/src/main/java/org/apache/drill/common/expression/visitors/ConstantChecker.java b/logical/src/main/java/org/apache/drill/common/expression/visitors/ConstantChecker.java
index 0468bc219..fbe7d721b 100644
--- a/logical/src/main/java/org/apache/drill/common/expression/visitors/ConstantChecker.java
+++ b/logical/src/main/java/org/apache/drill/common/expression/visitors/ConstantChecker.java
@@ -98,10 +98,7 @@ final class ConstantChecker implements ExprVisitor<Boolean, ErrorCollector, Runt
return false;
}
- if (!ifExpr.elseExpression.accept(this, errors)) {
- return false;
- }
- return true;
+ return ifExpr.elseExpression.accept(this, errors);
}
@Override
@@ -170,6 +167,11 @@ final class ConstantChecker implements ExprVisitor<Boolean, ErrorCollector, Runt
}
@Override
+ public Boolean visitVarDecimalConstant(ValueExpressions.VarDecimalExpression decExpr, ErrorCollector errors) {
+ return true;
+ }
+
+ @Override
public Boolean visitDoubleConstant(DoubleExpression dExpr, ErrorCollector errors) {
return true;
}
diff --git a/logical/src/main/java/org/apache/drill/common/expression/visitors/ExprVisitor.java b/logical/src/main/java/org/apache/drill/common/expression/visitors/ExprVisitor.java
index e6198ae6b..c065bc883 100644
--- a/logical/src/main/java/org/apache/drill/common/expression/visitors/ExprVisitor.java
+++ b/logical/src/main/java/org/apache/drill/common/expression/visitors/ExprVisitor.java
@@ -44,6 +44,7 @@ import org.apache.drill.common.expression.ValueExpressions.ParameterExpression;
import org.apache.drill.common.expression.ValueExpressions.QuotedString;
import org.apache.drill.common.expression.ValueExpressions.TimeExpression;
import org.apache.drill.common.expression.ValueExpressions.TimeStampExpression;
+import org.apache.drill.common.expression.ValueExpressions.VarDecimalExpression;
public interface ExprVisitor<T, VAL, EXCEP extends Exception> {
T visitFunctionCall(FunctionCall call, VAL value) throws EXCEP;
@@ -63,6 +64,7 @@ public interface ExprVisitor<T, VAL, EXCEP extends Exception> {
T visitDecimal18Constant(Decimal18Expression decExpr, VAL value) throws EXCEP;
T visitDecimal28Constant(Decimal28Expression decExpr, VAL value) throws EXCEP;
T visitDecimal38Constant(Decimal38Expression decExpr, VAL value) throws EXCEP;
+ T visitVarDecimalConstant(VarDecimalExpression decExpr, VAL value) throws EXCEP;
T visitDoubleConstant(DoubleExpression dExpr, VAL value) throws EXCEP;
T visitBooleanConstant(BooleanExpression e, VAL value) throws EXCEP;
T visitQuotedStringConstant(QuotedString e, VAL value) throws EXCEP;
diff --git a/logical/src/main/java/org/apache/drill/common/expression/visitors/ExpressionValidator.java b/logical/src/main/java/org/apache/drill/common/expression/visitors/ExpressionValidator.java
index c32825abb..b3074fcb1 100644
--- a/logical/src/main/java/org/apache/drill/common/expression/visitors/ExpressionValidator.java
+++ b/logical/src/main/java/org/apache/drill/common/expression/visitors/ExpressionValidator.java
@@ -44,6 +44,7 @@ import org.apache.drill.common.expression.ValueExpressions.LongExpression;
import org.apache.drill.common.expression.ValueExpressions.QuotedString;
import org.apache.drill.common.expression.ValueExpressions.TimeExpression;
import org.apache.drill.common.expression.ValueExpressions.TimeStampExpression;
+import org.apache.drill.common.expression.ValueExpressions.VarDecimalExpression;
import org.apache.drill.common.types.TypeProtos.DataMode;
import org.apache.drill.common.types.TypeProtos.MajorType;
import org.apache.drill.common.types.TypeProtos.MinorType;
@@ -167,6 +168,11 @@ public class ExpressionValidator implements ExprVisitor<Void, ErrorCollector, Ru
}
@Override
+ public Void visitVarDecimalConstant(VarDecimalExpression decExpr, ErrorCollector errors) throws RuntimeException {
+ return null;
+ }
+
+ @Override
public Void visitDateConstant(DateExpression intExpr, ErrorCollector errors) throws RuntimeException {
return null;
}
diff --git a/logical/src/main/java/org/apache/drill/common/expression/visitors/SimpleExprVisitor.java b/logical/src/main/java/org/apache/drill/common/expression/visitors/SimpleExprVisitor.java
index 6655986f1..c025dc87e 100644
--- a/logical/src/main/java/org/apache/drill/common/expression/visitors/SimpleExprVisitor.java
+++ b/logical/src/main/java/org/apache/drill/common/expression/visitors/SimpleExprVisitor.java
@@ -36,6 +36,7 @@ import org.apache.drill.common.expression.ValueExpressions.LongExpression;
import org.apache.drill.common.expression.ValueExpressions.QuotedString;
import org.apache.drill.common.expression.ValueExpressions.TimeExpression;
import org.apache.drill.common.expression.ValueExpressions.TimeStampExpression;
+import org.apache.drill.common.expression.ValueExpressions.VarDecimalExpression;
public abstract class SimpleExprVisitor<T> implements ExprVisitor<T, Void, RuntimeException>{
@@ -121,6 +122,11 @@ public abstract class SimpleExprVisitor<T> implements ExprVisitor<T, Void, Runti
}
@Override
+ public T visitVarDecimalConstant(VarDecimalExpression decExpr, Void value) throws RuntimeException {
+ return visitVarDecimalConstant(decExpr);
+ }
+
+ @Override
public T visitDoubleConstant(DoubleExpression dExpr, Void value) throws RuntimeException {
return visitDoubleConstant(dExpr);
}
@@ -152,6 +158,7 @@ public abstract class SimpleExprVisitor<T> implements ExprVisitor<T, Void, Runti
public abstract T visitDecimal18Constant(Decimal18Expression intExpr);
public abstract T visitDecimal28Constant(Decimal28Expression intExpr);
public abstract T visitDecimal38Constant(Decimal38Expression intExpr);
+ public abstract T visitVarDecimalConstant(VarDecimalExpression intExpr);
public abstract T visitDoubleConstant(DoubleExpression dExpr);
public abstract T visitBooleanConstant(BooleanExpression e);
public abstract T visitQuotedStringConstant(QuotedString e);
diff --git a/pom.xml b/pom.xml
index 8233d1c18..42729781b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -72,6 +72,7 @@
<javassist.version>3.22.0-GA</javassist.version>
<msgpack.version>0.6.6</msgpack.version>
<reflections.version>0.9.10</reflections.version>
+ <avro.version>1.8.2</avro.version>
<metrics.version>4.0.2</metrics.version>
<excludedGroups/>
<memoryMb>4096</memoryMb>
@@ -966,6 +967,44 @@
</exclusions>
</dependency>
<dependency>
+ <groupId>org.apache.avro</groupId>
+ <artifactId>avro</artifactId>
+ <version>${avro.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.xerial.snappy</groupId>
+ <artifactId>snappy-java</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>io.netty</groupId>
+ <artifactId>netty</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>io.netty</groupId>
+ <artifactId>netty-all</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.avro</groupId>
+ <artifactId>avro-mapred</artifactId>
+ <version>${avro.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>servlet-api</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>io.netty</groupId>
+ <artifactId>netty</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>io.netty</groupId>
+ <artifactId>netty-all</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
<groupId>org.apache.hive</groupId>
<artifactId>hive-exec</artifactId>
<version>${hive.version}</version>
diff --git a/protocol/src/main/java/org/apache/drill/common/types/MinorType.java b/protocol/src/main/java/org/apache/drill/common/types/MinorType.java
index dffc912e0..b26cb087d 100644
--- a/protocol/src/main/java/org/apache/drill/common/types/MinorType.java
+++ b/protocol/src/main/java/org/apache/drill/common/types/MinorType.java
@@ -59,7 +59,8 @@ public enum MinorType implements com.dyuproject.protostuff.EnumLite<MinorType>
INTERVALDAY(39),
LIST(40),
GENERIC_OBJECT(41),
- UNION(42);
+ UNION(42),
+ VARDECIMAL(43);
public final int number;
@@ -115,6 +116,7 @@ public enum MinorType implements com.dyuproject.protostuff.EnumLite<MinorType>
case 40: return LIST;
case 41: return GENERIC_OBJECT;
case 42: return UNION;
+ case 43: return VARDECIMAL;
default: return null;
}
}