Repository: drill Updated Branches: refs/heads/master 30ad950e5 -> f215c4629
DRILL-2244: Hash all numeric types as double Project: http://git-wip-us.apache.org/repos/asf/drill/repo Commit: http://git-wip-us.apache.org/repos/asf/drill/commit/f215c462 Tree: http://git-wip-us.apache.org/repos/asf/drill/tree/f215c462 Diff: http://git-wip-us.apache.org/repos/asf/drill/diff/f215c462 Branch: refs/heads/master Commit: f215c4629536df9e3990606b595b21c26cb6c86a Parents: 30ad950 Author: Mehant Baid <[email protected]> Authored: Thu Apr 2 11:54:39 2015 -0700 Committer: Mehant Baid <[email protected]> Committed: Fri Apr 3 11:12:29 2015 -0700 ---------------------------------------------------------------------- .../drill/exec/expr/fn/impl/Hash64AsDouble.java | 341 ++++++++++++++++++ .../exec/expr/fn/impl/Hash64Functions.java | 31 +- .../expr/fn/impl/Hash64FunctionsWithSeed.java | 31 +- .../expr/fn/impl/Hash64WithSeedAsDouble.java | 344 +++++++++++++++++++ .../physical/impl/common/ChainedHashTable.java | 31 +- .../drill/exec/planner/physical/PrelUtil.java | 13 +- .../drill/exec/resolver/TypeCastRules.java | 25 ++ .../org/apache/drill/TestFunctionsQuery.java | 25 ++ 8 files changed, 808 insertions(+), 33 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/drill/blob/f215c462/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/Hash64AsDouble.java ---------------------------------------------------------------------- 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 new file mode 100644 index 0000000..b3e4cc1 --- /dev/null +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/Hash64AsDouble.java @@ -0,0 +1,341 @@ +/** + * 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.expr.fn.impl; + +import org.apache.drill.exec.expr.DrillSimpleFunc; +import org.apache.drill.exec.expr.annotations.FunctionTemplate; +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.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; + +/* + * Class contains hash64 function definitions for different data types. + * + * NOTE: These functions are used internally by Drill to perform hash distribution and in hash join. For + * numeric data types we would like to apply implicit casts in the join method however for this to work + * 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. + */ +public class Hash64AsDouble { + @FunctionTemplate(name = "hash64AsDouble", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL) + public static class NullableFloatHash implements DrillSimpleFunc { + + @Param + NullableFloat4Holder 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.XXHash.hash64((double) in.value, 0); + } + } + } + + @FunctionTemplate(name = "hash64AsDouble", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL) + public static class FloatHash implements DrillSimpleFunc { + + @Param + Float4Holder in; + @Output + BigIntHolder out; + + public void setup() { + } + + public void eval() { + out.value = org.apache.drill.exec.expr.fn.impl.XXHash.hash64((double) in.value, 0); + } + } + + @FunctionTemplate(name = "hash64AsDouble", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL) + public static class NullableDoubleHash implements DrillSimpleFunc { + + @Param + NullableFloat8Holder 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.XXHash.hash64((double) in.value, 0); + } + } + } + + @FunctionTemplate(name = "hash64AsDouble", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL) + public static class DoubleHash implements DrillSimpleFunc { + + @Param + Float8Holder in; + @Output + BigIntHolder out; + + public void setup() { + } + + public void eval() { + out.value = org.apache.drill.exec.expr.fn.impl.XXHash.hash64(in.value, 0); + } + } + + @FunctionTemplate(name = "hash64AsDouble", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL) + public static class NullableBigIntHash implements DrillSimpleFunc { + + @Param + NullableBigIntHolder 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.XXHash.hash64((double) in.value, 0); + } + } + } + + @FunctionTemplate(name = "hash64AsDouble", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL) + public static class NullableIntHash implements DrillSimpleFunc { + @Param + NullableIntHolder 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.XXHash.hash64((double) in.value, 0); + } + } + } + + @FunctionTemplate(name = "hash64AsDouble", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL) + public static class HashBigInt implements DrillSimpleFunc { + + @Param + BigIntHolder in; + @Output + BigIntHolder out; + + public void setup() { + } + + public void eval() { + out.value = org.apache.drill.exec.expr.fn.impl.XXHash.hash64((double) in.value, 0); + } + } + + @FunctionTemplate(name = "hash64AsDouble", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL) + public static class IntHash implements DrillSimpleFunc { + @Param + IntHolder in; + @Output + BigIntHolder out; + + public void setup() { + } + + public void eval() { + // TODO: implement hash function for other types + out.value = org.apache.drill.exec.expr.fn.impl.XXHash.hash64((double) in.value, 0); + } + } + + @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.XXHash.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.XXHash.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.XXHash.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.XXHash.hash64(input.doubleValue(), 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.XXHash.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.XXHash.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.XXHash.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.XXHash.hash64(input.doubleValue(), 0); + } + } + } +} http://git-wip-us.apache.org/repos/asf/drill/blob/f215c462/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/Hash64Functions.java ---------------------------------------------------------------------- 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 57154ed..3e390a4 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 @@ -53,6 +53,9 @@ 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. + */ public class Hash64Functions { @FunctionTemplate(name = "hash64", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL) public static class NullableFloatHash implements DrillSimpleFunc { @@ -126,7 +129,7 @@ public class Hash64Functions { } } - @FunctionTemplate(name = "hash64", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL) + @FunctionTemplate(names = {"hash64", "hash64AsDouble"}, scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL) public static class NullableVarBinaryHash implements DrillSimpleFunc { @Param @@ -146,7 +149,7 @@ public class Hash64Functions { } } - @FunctionTemplate(name = "hash64", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL) + @FunctionTemplate(names = {"hash64", "hash64AsDouble"}, scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL) public static class NullableVarCharHash implements DrillSimpleFunc { @Param @@ -166,7 +169,7 @@ public class Hash64Functions { } } - @FunctionTemplate(name = "hash64", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL) + @FunctionTemplate(names = {"hash64", "hash64AsDouble"}, scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL) public static class NullableVar16CharHash implements DrillSimpleFunc { @Param @@ -225,7 +228,7 @@ public class Hash64Functions { } } - @FunctionTemplate(name = "hash64", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL) + @FunctionTemplate(names = {"hash64", "hash64AsDouble"}, scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL) public static class VarBinaryHash implements DrillSimpleFunc { @Param @@ -241,7 +244,7 @@ public class Hash64Functions { } } - @FunctionTemplate(name = "hash64", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL) + @FunctionTemplate(names = {"hash64", "hash64AsDouble"}, scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL) public static class VarCharHash implements DrillSimpleFunc { @Param @@ -257,7 +260,7 @@ public class Hash64Functions { } } - @FunctionTemplate(name = "hash64", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL) + @FunctionTemplate(names = {"hash64", "hash64AsDouble"}, scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL) public static class Var16CharHash implements DrillSimpleFunc { @Param @@ -305,7 +308,7 @@ public class Hash64Functions { } } - @FunctionTemplate(name = "hash64", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL) + @FunctionTemplate(names = {"hash64", "hash64AsDouble"}, scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL) public static class DateHash implements DrillSimpleFunc { @Param DateHolder in; @@ -320,7 +323,7 @@ public class Hash64Functions { } } - @FunctionTemplate(name = "hash64", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL) + @FunctionTemplate(names = {"hash64", "hash64AsDouble"}, scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL) public static class NullableDateHash implements DrillSimpleFunc { @Param NullableDateHolder in; @@ -339,7 +342,7 @@ public class Hash64Functions { } } - @FunctionTemplate(name = "hash64", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL) + @FunctionTemplate(names = {"hash64", "hash64AsDouble"}, scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL) public static class TimeStampHash implements DrillSimpleFunc { @Param TimeStampHolder in; @@ -354,7 +357,7 @@ public class Hash64Functions { } } - @FunctionTemplate(name = "hash64", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL) + @FunctionTemplate(names = {"hash64", "hash64AsDouble"}, scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL) public static class NullableTimeStampHash implements DrillSimpleFunc { @Param NullableTimeStampHolder in; @@ -373,7 +376,7 @@ public class Hash64Functions { } } - @FunctionTemplate(name = "hash64", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL) + @FunctionTemplate(names = {"hash64", "hash64AsDouble"}, scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL) public static class TimeHash implements DrillSimpleFunc { @Param TimeHolder in; @@ -388,7 +391,7 @@ public class Hash64Functions { } } - @FunctionTemplate(name = "hash64", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL) + @FunctionTemplate(names = {"hash64", "hash64AsDouble"}, scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL) public static class NullableTimeHash implements DrillSimpleFunc { @Param NullableTimeHolder in; @@ -547,7 +550,7 @@ public class Hash64Functions { } } - @FunctionTemplate(name = "hash64", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL) + @FunctionTemplate(names = {"hash64", "hash64AsDouble"}, scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL) public static class NullableBitHash implements DrillSimpleFunc { @Param @@ -567,7 +570,7 @@ public class Hash64Functions { } } - @FunctionTemplate(name = "hash64", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL) + @FunctionTemplate(names = {"hash64", "hash64AsDouble"}, scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL) public static class BitHash implements DrillSimpleFunc { @Param http://git-wip-us.apache.org/repos/asf/drill/blob/f215c462/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/Hash64FunctionsWithSeed.java ---------------------------------------------------------------------- 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 b9ec956..3a1edd3 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 @@ -53,6 +53,9 @@ 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. + */ public class Hash64FunctionsWithSeed { @FunctionTemplate(name = "hash64", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL ) public static class NullableFloatHash implements DrillSimpleFunc { @@ -126,7 +129,7 @@ public class Hash64FunctionsWithSeed { } } - @FunctionTemplate(name = "hash64", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL ) + @FunctionTemplate(names = {"hash64", "hash64AsDouble"}, scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL ) public static class NullableVarBinaryHash implements DrillSimpleFunc { @Param NullableVarBinaryHolder in; @@ -146,7 +149,7 @@ public class Hash64FunctionsWithSeed { } } - @FunctionTemplate(name = "hash64", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL ) + @FunctionTemplate(names = {"hash64", "hash64AsDouble"}, scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL ) public static class NullableVarCharHash implements DrillSimpleFunc { @Param NullableVarCharHolder in; @@ -166,7 +169,7 @@ public class Hash64FunctionsWithSeed { } } - @FunctionTemplate(name = "hash64", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL ) + @FunctionTemplate(names = {"hash64", "hash64AsDouble"}, scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL ) public static class NullableVar16CharHash implements DrillSimpleFunc { @Param NullableVar16CharHolder in; @@ -227,7 +230,7 @@ public class Hash64FunctionsWithSeed { } } - @FunctionTemplate(name = "hash64", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL) + @FunctionTemplate(names = {"hash64", "hash64AsDouble"}, scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL) public static class VarBinaryHash implements DrillSimpleFunc { @Param VarBinaryHolder in; @@ -243,7 +246,7 @@ public class Hash64FunctionsWithSeed { } } - @FunctionTemplate(name = "hash64", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL) + @FunctionTemplate(names = {"hash64", "hash64AsDouble"}, scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL) public static class VarCharHash implements DrillSimpleFunc { @Param VarCharHolder in; @@ -259,7 +262,7 @@ public class Hash64FunctionsWithSeed { } } - @FunctionTemplate(name = "hash64", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL) + @FunctionTemplate(names = {"hash64", "hash64AsDouble"}, scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL) public static class Var16CharHash implements DrillSimpleFunc { @Param Var16CharHolder in; @@ -306,7 +309,7 @@ public class Hash64FunctionsWithSeed { out.value = org.apache.drill.exec.expr.fn.impl.XXHash.hash64(in.value, seed.value); } } - @FunctionTemplate(name = "hash64", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL) + @FunctionTemplate(names = {"hash64", "hash64AsDouble"}, scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL) public static class DateHash implements DrillSimpleFunc { @Param DateHolder in; @Param BigIntHolder seed; @@ -321,7 +324,7 @@ public class Hash64FunctionsWithSeed { } } - @FunctionTemplate(name = "hash64", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL) + @FunctionTemplate(names = {"hash64", "hash64AsDouble"}, scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL) public static class NullableDateHash implements DrillSimpleFunc { @Param NullableDateHolder in; @Param BigIntHolder seed; @@ -340,7 +343,7 @@ public class Hash64FunctionsWithSeed { } } - @FunctionTemplate(name = "hash64", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL) + @FunctionTemplate(names = {"hash64", "hash64AsDouble"}, scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL) public static class TimeStampHash implements DrillSimpleFunc { @Param TimeStampHolder in; @Param BigIntHolder seed; @@ -355,7 +358,7 @@ public class Hash64FunctionsWithSeed { } } - @FunctionTemplate(name = "hash64", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL) + @FunctionTemplate(names = {"hash64", "hash64AsDouble"}, scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL) public static class NullableTimeStampHash implements DrillSimpleFunc { @Param NullableTimeStampHolder in; @Param BigIntHolder seed; @@ -374,7 +377,7 @@ public class Hash64FunctionsWithSeed { } } - @FunctionTemplate(name = "hash64", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL) + @FunctionTemplate(names = {"hash64", "hash64AsDouble"}, scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL) public static class TimeHash implements DrillSimpleFunc { @Param TimeHolder in; @Param BigIntHolder seed; @@ -389,7 +392,7 @@ public class Hash64FunctionsWithSeed { } } - @FunctionTemplate(name = "hash64", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL) + @FunctionTemplate(names = {"hash64", "hash64AsDouble"}, scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL) public static class NullableTimeHash implements DrillSimpleFunc { @Param NullableTimeHolder in; @Param BigIntHolder seed; @@ -544,7 +547,7 @@ public class Hash64FunctionsWithSeed { } } - @FunctionTemplate(name = "hash64", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL ) + @FunctionTemplate(names = {"hash64", "hash64AsDouble"}, scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL ) public static class NullableBitHash implements DrillSimpleFunc { @Param NullableBitHolder in; @@ -564,7 +567,7 @@ public class Hash64FunctionsWithSeed { } } - @FunctionTemplate(name = "hash64", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL ) + @FunctionTemplate(names = {"hash64", "hash64AsDouble"}, scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL ) public static class BitHash implements DrillSimpleFunc { @Param BitHolder in; http://git-wip-us.apache.org/repos/asf/drill/blob/f215c462/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/Hash64WithSeedAsDouble.java ---------------------------------------------------------------------- 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 new file mode 100644 index 0000000..0cbac1b --- /dev/null +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/expr/fn/impl/Hash64WithSeedAsDouble.java @@ -0,0 +1,344 @@ +/** + * 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.expr.fn.impl; + +import org.apache.drill.exec.expr.DrillSimpleFunc; +import org.apache.drill.exec.expr.annotations.FunctionTemplate; +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.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; + +/* + * Class contains hash64 function definitions for different data types. + * + * NOTE: These functions are used internally by Drill to perform hash distribution and in hash join. For + * numeric data types we would like to apply implicit casts in the join method however for this to work + * 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. + */ +public class Hash64WithSeedAsDouble { + @FunctionTemplate(name = "hash64AsDouble", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL ) + public static class NullableFloatHash implements DrillSimpleFunc { + + @Param NullableFloat4Holder in; + @Param BigIntHolder seed; + @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.XXHash.hash64((double) in.value, seed.value); + } + } + } + + @FunctionTemplate(name = "hash64AsDouble", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL ) + public static class FloatHash implements DrillSimpleFunc { + + @Param Float4Holder in; + @Param BigIntHolder seed; + @Output BigIntHolder out; + + + public void setup() { + } + + public void eval() { + out.value = org.apache.drill.exec.expr.fn.impl.XXHash.hash64((double) in.value, seed.value); + } + } + + @FunctionTemplate(name = "hash64AsDouble", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL ) + public static class NullableDoubleHash implements DrillSimpleFunc { + + @Param NullableFloat8Holder in; + @Param BigIntHolder seed; + @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.XXHash.hash64(in.value, seed.value); + } + } + } + + @FunctionTemplate(name = "hash64AsDouble", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL ) + public static class DoubleHash implements DrillSimpleFunc { + + @Param Float8Holder in; + @Param BigIntHolder seed; + @Output BigIntHolder out; + + + public void setup() { + } + + public void eval() { + out.value = org.apache.drill.exec.expr.fn.impl.XXHash.hash64(in.value, seed.value); + } + } + + @FunctionTemplate(name = "hash64AsDouble", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL) + public static class NullableBigIntHash implements DrillSimpleFunc { + + @Param NullableBigIntHolder in; + @Param BigIntHolder seed; + @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.XXHash.hash64((double) in.value, seed.value); + } + } + } + + @FunctionTemplate(name = "hash64AsDouble", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL) + public static class NullableIntHash implements DrillSimpleFunc { + @Param NullableIntHolder in; + @Param BigIntHolder seed; + @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.XXHash.hash64((double) in.value, seed.value); + } + } + } + + @FunctionTemplate(name = "hash64AsDouble", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL) + public static class HashBigInt implements DrillSimpleFunc { + + @Param BigIntHolder in; + @Param BigIntHolder seed; + @Output BigIntHolder out; + + + public void setup() { + } + + public void eval() { + out.value = org.apache.drill.exec.expr.fn.impl.XXHash.hash64((double) in.value, seed.value); + } + } + + @FunctionTemplate(name = "hash64AsDouble", scope = FunctionScope.SIMPLE, nulls = FunctionTemplate.NullHandling.INTERNAL) + public static class IntHash implements DrillSimpleFunc { + @Param IntHolder in; + @Param BigIntHolder seed; + @Output BigIntHolder out; + + + public void setup() { + } + + public void eval() { + // TODO: implement hash function for other types + out.value = org.apache.drill.exec.expr.fn.impl.XXHash.hash64((double) in.value, seed.value); + } + } + + @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.XXHash.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 = 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.XXHash.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.XXHash.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 = 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.XXHash.hash64(input.doubleValue(), seed.value); + } + } + } + + @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.XXHash.hash64(input.doubleValue(), 0); + } + } + + @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 = 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.XXHash.hash64(input.doubleValue(), 0); + } + } + } + + @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.XXHash.hash64(input.doubleValue(), 0); + } + } + + @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 = 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.XXHash.hash64(input.doubleValue(), 0); + } + } + } +} + http://git-wip-us.apache.org/repos/asf/drill/blob/f215c462/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/common/ChainedHashTable.java ---------------------------------------------------------------------- diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/common/ChainedHashTable.java b/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/common/ChainedHashTable.java index 84a2956..9df67d8 100644 --- a/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/common/ChainedHashTable.java +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/physical/impl/common/ChainedHashTable.java @@ -309,6 +309,14 @@ public class ChainedHashTable { MinorType probeType = probeExpr.getMajorType().getMinorType(); if (buildType != probeType) { + + // currently we only support implicit casts if the input types are numeric or varchar/varbinary + if (!allowImplicitCast(buildType, probeType)) { + throw new DrillRuntimeException(String.format("Hash join only supports implicit casts between " + + "1. Numeric data\n 2. Varchar, Varbinary data " + + "Build type: %s, Probe type: %s. Add explicit casts to avoid this error", buildType, probeType)); + } + // We need to add a cast to one of the expressions List<MinorType> types = new LinkedList<>(); types.add(buildType); @@ -349,11 +357,32 @@ public class ChainedHashTable { return; } - LogicalExpression hashExpression = PrelUtil.getHashExpression(Arrays.asList(keyExprs)); + /* + * We use the same logic to generate run time code for the hash function both for hash join and hash + * aggregate. For join we need to hash everything as double (both for distribution and for comparison) but + * for aggregation we can avoid the penalty of casting to double + */ + LogicalExpression hashExpression = PrelUtil.getHashExpression(Arrays.asList(keyExprs), + incomingProbe != null ? true : false); final LogicalExpression materializedExpr = ExpressionTreeMaterializer.materializeAndCheckErrors(hashExpression, batch, context.getFunctionRegistry()); HoldingContainer hash = cg.addExpr(materializedExpr); cg.getEvalBlock()._return(hash.getValue()); } + + private boolean allowImplicitCast(MinorType input1, MinorType input2) { + // allow implicit cast if both the input types are numeric + if (TypeCastRules.isNumericType(input1) && TypeCastRules.isNumericType(input2)) { + return true; + } + + // allow implicit cast if both the input types are varbinary/ varchar + if ((input1 == MinorType.VARCHAR || input1 == MinorType.VARBINARY) && + (input2 == MinorType.VARCHAR || input2 == MinorType.VARBINARY)) { + return true; + } + + return false; + } } http://git-wip-us.apache.org/repos/asf/drill/blob/f215c462/exec/java-exec/src/main/java/org/apache/drill/exec/planner/physical/PrelUtil.java ---------------------------------------------------------------------- diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/physical/PrelUtil.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/physical/PrelUtil.java index f7c144f..44afd68 100644 --- a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/physical/PrelUtil.java +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/physical/PrelUtil.java @@ -68,6 +68,8 @@ import com.google.common.collect.Sets; public class PrelUtil { public static final String HASH_EXPR_NAME = "E_X_P_R_H_A_S_H_F_I_E_L_D"; + private static final String HASH64_FUNCTION_NAME = "hash64"; + private static final String HASH64_DOUBLE_FUNCTION_NAME = "hash64AsDouble"; public static List<Ordering> getOrdering(RelCollation collation, RelDataType rowType) { List<Ordering> orderExpr = Lists.newArrayList(); @@ -85,12 +87,13 @@ public class PrelUtil { /* * Return a hash expression : (int) hash(field1, hash(field2, hash(field3, 0))); */ - public static LogicalExpression getHashExpression(List<LogicalExpression> fields){ + public static LogicalExpression getHashExpression(List<LogicalExpression> fields, boolean hashAsDouble){ assert fields.size() > 0; - FunctionCall func = new FunctionCall("hash64", ImmutableList.of(fields.get(0)), ExpressionPosition.UNKNOWN); + String functionName = hashAsDouble ? HASH64_DOUBLE_FUNCTION_NAME : HASH64_FUNCTION_NAME; + FunctionCall func = new FunctionCall(functionName, ImmutableList.of(fields.get(0)), ExpressionPosition.UNKNOWN); for (int i = 1; i<fields.size(); i++) { - func = new FunctionCall("hash64", ImmutableList.of(fields.get(i), func), ExpressionPosition.UNKNOWN); + func = new FunctionCall(functionName, ImmutableList.of(fields.get(i), func), ExpressionPosition.UNKNOWN); } return new CastExpression(func, Types.required(MinorType.INT), ExpressionPosition.UNKNOWN); @@ -111,7 +114,9 @@ public class PrelUtil { for(int i =0; i < fields.size(); i++){ expressions.add(new FieldReference(childFields.get(fields.get(i).getFieldId()), ExpressionPosition.UNKNOWN)); } - return getHashExpression(expressions); + + // for distribution always hash as double + return getHashExpression(expressions, true); } public static Iterator<Prel> iter(RelNode... nodes) { http://git-wip-us.apache.org/repos/asf/drill/blob/f215c462/exec/java-exec/src/main/java/org/apache/drill/exec/resolver/TypeCastRules.java ---------------------------------------------------------------------- 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 d8652f2..92302e0 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 @@ -938,4 +938,29 @@ public class TypeCastRules { return cost; } + /* + * Simple helper function to determine if input type is numeric + */ + public static boolean isNumericType(MinorType inputType) { + switch (inputType) { + case TINYINT: + case SMALLINT: + case INT: + case BIGINT: + case UINT1: + case UINT2: + case UINT4: + case UINT8: + case DECIMAL9: + case DECIMAL18: + case DECIMAL28SPARSE: + case DECIMAL38SPARSE: + case FLOAT4: + case FLOAT8: + return true; + default: + return false; + } + } + } http://git-wip-us.apache.org/repos/asf/drill/blob/f215c462/exec/java-exec/src/test/java/org/apache/drill/TestFunctionsQuery.java ---------------------------------------------------------------------- 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 f1005ab..476370d 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 @@ -709,4 +709,29 @@ public class TestFunctionsQuery extends BaseTestQuery { .baselineValues(new BigDecimal("1.00000")) .go(); } + + /* + * We may apply implicit casts in Hash Join while dealing with different numeric data types + * For this to work we need to distribute the data based on a common key, below method + * makes sure the hash value for different numeric types is the same for the same key + */ + @Test + public void testHash64() throws Exception { + String query = "select " + + "hash64AsDouble(cast(employee_id as int)) = hash64AsDouble(cast(employee_id as bigint)) col1, " + + "hash64AsDouble(cast(employee_id as bigint)) = hash64AsDouble(cast(employee_id as float)) col2, " + + "hash64AsDouble(cast(employee_id as float)) = hash64AsDouble(cast(employee_id as double)) col3, " + + "hash64AsDouble(cast(employee_id as double)) = hash64AsDouble(cast(employee_id as decimal(9, 0))) col4, " + + "hash64AsDouble(cast(employee_id as decimal(9, 0))) = hash64AsDouble(cast(employee_id as decimal(18, 0))) col5, " + + "hash64AsDouble(cast(employee_id as decimal(18, 0))) = hash64AsDouble(cast(employee_id as decimal(28, 0))) col6, " + + "hash64AsDouble(cast(employee_id as decimal(28, 0))) = hash64AsDouble(cast(employee_id as decimal(38, 0))) col7 " + + "from cp.`employee.json` where employee_id = 1"; + + testBuilder() + .sqlQuery(query) + .unOrdered() + .baselineColumns("col1", "col2", "col3", "col4", "col5", "col6", "col7") + .baselineValues(true, true, true, true, true, true, true) + .go(); + } }
