You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@drill.apache.org by me...@apache.org on 2015/04/03 22:04:00 UTC

drill git commit: DRILL-2244: Hash all numeric types as double

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 <me...@gmail.com>
Authored: Thu Apr 2 11:54:39 2015 -0700
Committer: Mehant Baid <me...@gmail.com>
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();
+  }
 }