You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hive.apache.org by kg...@apache.org on 2020/10/02 13:02:21 UTC

[hive] branch master updated: HIVE-24157: Strict mode to fail on CAST timestamp <-> numeric (#1497) (Zoltan Haindrich reviewed by Jesus Camacho Rodriguez)

This is an automated email from the ASF dual-hosted git repository.

kgyrtkirk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hive.git


The following commit(s) were added to refs/heads/master by this push:
     new f002c10  HIVE-24157: Strict mode to fail on CAST timestamp <-> numeric (#1497) (Zoltan Haindrich reviewed by Jesus Camacho Rodriguez)
f002c10 is described below

commit f002c103da25ea9826abff90aa84c0a1967c4a50
Author: Zoltan Haindrich <ki...@rxd.hu>
AuthorDate: Fri Oct 2 15:02:11 2020 +0200

    HIVE-24157: Strict mode to fail on CAST timestamp <-> numeric (#1497) (Zoltan Haindrich reviewed by Jesus Camacho Rodriguez)
---
 .../java/org/apache/hadoop/hive/conf/HiveConf.java |  2 +
 data/conf/hive-site.xml                            |  6 ++
 data/conf/llap/hive-site.xml                       |  5 ++
 .../ql/udf/TimestampCastRestrictorResolver.java    | 71 ++++++++++++++++++++++
 .../apache/hadoop/hive/ql/udf/UDFToBoolean.java    |  6 ++
 .../org/apache/hadoop/hive/ql/udf/UDFToByte.java   |  6 ++
 .../org/apache/hadoop/hive/ql/udf/UDFToDouble.java |  6 ++
 .../org/apache/hadoop/hive/ql/udf/UDFToFloat.java  |  5 ++
 .../apache/hadoop/hive/ql/udf/UDFToInteger.java    |  6 ++
 .../org/apache/hadoop/hive/ql/udf/UDFToLong.java   |  5 ++
 .../org/apache/hadoop/hive/ql/udf/UDFToShort.java  |  6 ++
 .../hive/ql/udf/generic/GenericUDFBaseCompare.java | 33 ++++++++++
 .../hive/ql/udf/generic/GenericUDFTimestamp.java   | 15 ++++-
 .../clientnegative/strict_numeric_to_timestamp.q   |  2 +
 .../clientnegative/strict_numeric_to_timestamp2.q  |  3 +
 .../clientnegative/strict_timestamp_to_numeric.q   |  2 +
 .../clientnegative/strict_timestamp_to_numeric2.q  |  3 +
 .../clientnegative/strict_timestamp_to_numeric3.q  |  3 +
 .../clientnegative/strict_timestamp_to_numeric4.q  |  3 +
 .../strict_numeric_to_timestamp.q.out              |  1 +
 .../strict_numeric_to_timestamp2.q.out             |  9 +++
 .../strict_timestamp_to_numeric.q.out              |  1 +
 .../strict_timestamp_to_numeric2.q.out             |  9 +++
 .../strict_timestamp_to_numeric3.q.out             |  9 +++
 .../strict_timestamp_to_numeric4.q.out             |  9 +++
 25 files changed, 223 insertions(+), 3 deletions(-)

diff --git a/common/src/java/org/apache/hadoop/hive/conf/HiveConf.java b/common/src/java/org/apache/hadoop/hive/conf/HiveConf.java
index 1e6e5ca..b0488db 100644
--- a/common/src/java/org/apache/hadoop/hive/conf/HiveConf.java
+++ b/common/src/java/org/apache/hadoop/hive/conf/HiveConf.java
@@ -1774,6 +1774,8 @@ public class HiveConf extends Configuration {
     HIVE_STRICT_CHECKS_BUCKETING("hive.strict.checks.bucketing", true,
         "Enabling strict bucketing checks disallows the following:\n" +
         "  Load into bucketed tables."),
+    HIVE_STRICT_TIMESTAMP_CONVERSION("hive.strict.timestamp.conversion", true,
+        "Restricts unsafe numeric to timestamp conversions"),
     HIVE_LOAD_DATA_OWNER("hive.load.data.owner", "",
         "Set the owner of files loaded using load data in managed tables."),
 
diff --git a/data/conf/hive-site.xml b/data/conf/hive-site.xml
index 53a38c8..f0f71f6 100644
--- a/data/conf/hive-site.xml
+++ b/data/conf/hive-site.xml
@@ -381,4 +381,10 @@
   <name>hive.scheduled.queries.executor.enabled</name>
   <value>false</value>
 </property>
+
+<property>
+  <name>hive.strict.timestamp.conversion</name>
+  <value>false</value>
+</property>
+
 </configuration>
diff --git a/data/conf/llap/hive-site.xml b/data/conf/llap/hive-site.xml
index fe4337b..7bc3791 100644
--- a/data/conf/llap/hive-site.xml
+++ b/data/conf/llap/hive-site.xml
@@ -402,4 +402,9 @@
   <description>Using property defined in HiveConf.ConfVars to test System property overriding</description>
 </property>
 
+<property>
+  <name>hive.strict.timestamp.conversion</name>
+  <value>false</value>
+</property>
+
 </configuration>
diff --git a/ql/src/java/org/apache/hadoop/hive/ql/udf/TimestampCastRestrictorResolver.java b/ql/src/java/org/apache/hadoop/hive/ql/udf/TimestampCastRestrictorResolver.java
new file mode 100644
index 0000000..edb0736
--- /dev/null
+++ b/ql/src/java/org/apache/hadoop/hive/ql/udf/TimestampCastRestrictorResolver.java
@@ -0,0 +1,71 @@
+/*
+ * 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.hadoop.hive.ql.udf;
+
+import java.lang.reflect.Method;
+import java.util.List;
+
+import org.apache.hadoop.hive.conf.HiveConf.ConfVars;
+import org.apache.hadoop.hive.ql.exec.UDF;
+import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
+import org.apache.hadoop.hive.ql.exec.UDFMethodResolver;
+import org.apache.hadoop.hive.ql.session.SessionState;
+import org.apache.hadoop.hive.serde2.objectinspector.PrimitiveObjectInspector.PrimitiveCategory;
+import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorUtils;
+import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorUtils.PrimitiveGrouping;
+import org.apache.hadoop.hive.serde2.typeinfo.PrimitiveTypeInfo;
+import org.apache.hadoop.hive.serde2.typeinfo.TypeInfo;
+
+/**
+ * Restricts casting timestamp/date types to numeric values.
+ *
+ * This Resolver is used in {@link UDF} implementations to enforce strict conversion rules.
+ */
+public class TimestampCastRestrictorResolver implements UDFMethodResolver {
+
+  private UDFMethodResolver parentResolver;
+  private boolean strictTsConversion;
+
+  public TimestampCastRestrictorResolver(UDFMethodResolver parentResolver) {
+    this.parentResolver = parentResolver;
+    SessionState ss = SessionState.get();
+    if (ss != null && ss.getConf().getBoolVar(ConfVars.HIVE_STRICT_TIMESTAMP_CONVERSION)) {
+      strictTsConversion = true;
+    }
+  }
+
+  @Override
+  public Method getEvalMethod(List<TypeInfo> argClasses) throws UDFArgumentException {
+    if (strictTsConversion) {
+      TypeInfo arg = argClasses.get(0);
+      if (arg instanceof PrimitiveTypeInfo) {
+        PrimitiveTypeInfo primitiveTypeInfo = (PrimitiveTypeInfo) arg;
+        PrimitiveCategory category = primitiveTypeInfo.getPrimitiveCategory();
+        PrimitiveGrouping group = PrimitiveObjectInspectorUtils.getPrimitiveGrouping(category);
+        if (group == PrimitiveGrouping.DATE_GROUP) {
+          throw new UDFArgumentException(
+              "Casting DATE/TIMESTAMP types to NUMERIC is prohibited (" + ConfVars.HIVE_STRICT_TIMESTAMP_CONVERSION
+                  + ")");
+        }
+      }
+    }
+    return parentResolver.getEvalMethod(argClasses);
+  }
+
+}
diff --git a/ql/src/java/org/apache/hadoop/hive/ql/udf/UDFToBoolean.java b/ql/src/java/org/apache/hadoop/hive/ql/udf/UDFToBoolean.java
index 0957fe0..a2c1e07 100755
--- a/ql/src/java/org/apache/hadoop/hive/ql/udf/UDFToBoolean.java
+++ b/ql/src/java/org/apache/hadoop/hive/ql/udf/UDFToBoolean.java
@@ -22,6 +22,7 @@ package org.apache.hadoop.hive.ql.udf;
 import org.apache.hadoop.hive.common.type.HiveDecimal;
 import org.apache.hadoop.hive.ql.exec.Description;
 import org.apache.hadoop.hive.ql.exec.UDF;
+import org.apache.hadoop.hive.ql.exec.UDFMethodResolver;
 import org.apache.hadoop.hive.ql.exec.vector.VectorizedExpressions;
 import org.apache.hadoop.hive.ql.exec.vector.expressions.CastDecimalToBoolean;
 import org.apache.hadoop.hive.ql.exec.vector.expressions.CastStringToBoolean;
@@ -75,6 +76,11 @@ public class UDFToBoolean extends UDF {
   public UDFToBoolean() {
   }
 
+  @Override
+  public UDFMethodResolver getResolver() {
+    return new TimestampCastRestrictorResolver(super.getResolver());
+  }
+
   /**
    * Convert a void to boolean. This is called for CAST(... AS BOOLEAN)
    *
diff --git a/ql/src/java/org/apache/hadoop/hive/ql/udf/UDFToByte.java b/ql/src/java/org/apache/hadoop/hive/ql/udf/UDFToByte.java
index b335293..ee71590 100755
--- a/ql/src/java/org/apache/hadoop/hive/ql/udf/UDFToByte.java
+++ b/ql/src/java/org/apache/hadoop/hive/ql/udf/UDFToByte.java
@@ -20,6 +20,7 @@ package org.apache.hadoop.hive.ql.udf;
 
 import org.apache.hadoop.hive.ql.exec.Description;
 import org.apache.hadoop.hive.ql.exec.UDF;
+import org.apache.hadoop.hive.ql.exec.UDFMethodResolver;
 import org.apache.hadoop.hive.ql.exec.vector.VectorizedExpressions;
 import org.apache.hadoop.hive.ql.exec.vector.expressions.CastDecimalToLong;
 import org.apache.hadoop.hive.ql.exec.vector.expressions.CastStringToLong;
@@ -68,6 +69,11 @@ public class UDFToByte extends UDF {
   public UDFToByte() {
   }
 
+  @Override
+  public UDFMethodResolver getResolver() {
+    return new TimestampCastRestrictorResolver(super.getResolver());
+  }
+
   /**
    * Convert from void to a byte. This is called for CAST(... AS TINYINT)
    *
diff --git a/ql/src/java/org/apache/hadoop/hive/ql/udf/UDFToDouble.java b/ql/src/java/org/apache/hadoop/hive/ql/udf/UDFToDouble.java
index 6f820c6..2320e4a 100755
--- a/ql/src/java/org/apache/hadoop/hive/ql/udf/UDFToDouble.java
+++ b/ql/src/java/org/apache/hadoop/hive/ql/udf/UDFToDouble.java
@@ -20,6 +20,7 @@ package org.apache.hadoop.hive.ql.udf;
 
 import org.apache.hadoop.hive.ql.exec.Description;
 import org.apache.hadoop.hive.ql.exec.UDF;
+import org.apache.hadoop.hive.ql.exec.UDFMethodResolver;
 import org.apache.hadoop.hive.ql.exec.vector.VectorizedExpressions;
 import org.apache.hadoop.hive.ql.exec.vector.expressions.CastDecimalToDouble;
 import org.apache.hadoop.hive.ql.exec.vector.expressions.CastStringToDouble;
@@ -66,6 +67,11 @@ public class UDFToDouble extends UDF {
   public UDFToDouble() {
   }
 
+  @Override
+  public UDFMethodResolver getResolver() {
+    return new TimestampCastRestrictorResolver(super.getResolver());
+  }
+
   /**
    * Convert from void to a double. This is called for CAST(... AS DOUBLE)
    *
diff --git a/ql/src/java/org/apache/hadoop/hive/ql/udf/UDFToFloat.java b/ql/src/java/org/apache/hadoop/hive/ql/udf/UDFToFloat.java
index c7cabb2..e5df0b8 100755
--- a/ql/src/java/org/apache/hadoop/hive/ql/udf/UDFToFloat.java
+++ b/ql/src/java/org/apache/hadoop/hive/ql/udf/UDFToFloat.java
@@ -20,6 +20,7 @@ package org.apache.hadoop.hive.ql.udf;
 
 import org.apache.hadoop.hive.ql.exec.Description;
 import org.apache.hadoop.hive.ql.exec.UDF;
+import org.apache.hadoop.hive.ql.exec.UDFMethodResolver;
 import org.apache.hadoop.hive.ql.exec.vector.VectorizedExpressions;
 import org.apache.hadoop.hive.ql.exec.vector.expressions.CastDecimalToFloat;
 import org.apache.hadoop.hive.ql.exec.vector.expressions.CastStringToFloat;
@@ -67,6 +68,10 @@ public class UDFToFloat extends UDF {
   public UDFToFloat() {
   }
 
+  @Override
+  public UDFMethodResolver getResolver() {
+    return new TimestampCastRestrictorResolver(super.getResolver());
+  }
   /**
    * Convert from void to a float. This is called for CAST(... AS FLOAT)
    *
diff --git a/ql/src/java/org/apache/hadoop/hive/ql/udf/UDFToInteger.java b/ql/src/java/org/apache/hadoop/hive/ql/udf/UDFToInteger.java
index 936f77d..af86db0 100755
--- a/ql/src/java/org/apache/hadoop/hive/ql/udf/UDFToInteger.java
+++ b/ql/src/java/org/apache/hadoop/hive/ql/udf/UDFToInteger.java
@@ -20,6 +20,7 @@ package org.apache.hadoop.hive.ql.udf;
 
 import org.apache.hadoop.hive.ql.exec.Description;
 import org.apache.hadoop.hive.ql.exec.UDF;
+import org.apache.hadoop.hive.ql.exec.UDFMethodResolver;
 import org.apache.hadoop.hive.ql.exec.vector.VectorizedExpressions;
 import org.apache.hadoop.hive.ql.exec.vector.expressions.CastDecimalToLong;
 import org.apache.hadoop.hive.ql.exec.vector.expressions.gen.CastDoubleToLong;
@@ -70,6 +71,11 @@ public class UDFToInteger extends UDF {
   public UDFToInteger() {
   }
 
+  @Override
+  public UDFMethodResolver getResolver() {
+    return new TimestampCastRestrictorResolver(super.getResolver());
+  }
+
   /**
    * Convert from void to an integer. This is called for CAST(... AS INT)
    *
diff --git a/ql/src/java/org/apache/hadoop/hive/ql/udf/UDFToLong.java b/ql/src/java/org/apache/hadoop/hive/ql/udf/UDFToLong.java
index 36d1c4d..eb465d9 100755
--- a/ql/src/java/org/apache/hadoop/hive/ql/udf/UDFToLong.java
+++ b/ql/src/java/org/apache/hadoop/hive/ql/udf/UDFToLong.java
@@ -20,6 +20,7 @@ package org.apache.hadoop.hive.ql.udf;
 
 import org.apache.hadoop.hive.ql.exec.Description;
 import org.apache.hadoop.hive.ql.exec.UDF;
+import org.apache.hadoop.hive.ql.exec.UDFMethodResolver;
 import org.apache.hadoop.hive.ql.exec.vector.VectorizedExpressions;
 import org.apache.hadoop.hive.ql.exec.vector.expressions.CastDecimalToLong;
 import org.apache.hadoop.hive.ql.exec.vector.expressions.CastStringToLong;
@@ -68,6 +69,10 @@ public class UDFToLong extends UDF {
   public UDFToLong() {
   }
 
+  @Override
+  public UDFMethodResolver getResolver() {
+    return new TimestampCastRestrictorResolver(super.getResolver());
+  }
   /**
    * Convert from void to a long. This is called for CAST(... AS BIGINT)
    *
diff --git a/ql/src/java/org/apache/hadoop/hive/ql/udf/UDFToShort.java b/ql/src/java/org/apache/hadoop/hive/ql/udf/UDFToShort.java
index 583b626..2ba2e01 100644
--- a/ql/src/java/org/apache/hadoop/hive/ql/udf/UDFToShort.java
+++ b/ql/src/java/org/apache/hadoop/hive/ql/udf/UDFToShort.java
@@ -20,6 +20,7 @@ package org.apache.hadoop.hive.ql.udf;
 
 import org.apache.hadoop.hive.ql.exec.Description;
 import org.apache.hadoop.hive.ql.exec.UDF;
+import org.apache.hadoop.hive.ql.exec.UDFMethodResolver;
 import org.apache.hadoop.hive.ql.exec.vector.VectorizedExpressions;
 import org.apache.hadoop.hive.ql.exec.vector.expressions.CastDecimalToLong;
 import org.apache.hadoop.hive.ql.exec.vector.expressions.CastStringToLong;
@@ -68,6 +69,11 @@ public class UDFToShort extends UDF {
   public UDFToShort() {
   }
 
+  @Override
+  public UDFMethodResolver getResolver() {
+    return new TimestampCastRestrictorResolver(super.getResolver());
+  }
+
   /**
    * Convert from void to a short. This is called for CAST(... AS SMALLINT)
    *
diff --git a/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFBaseCompare.java b/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFBaseCompare.java
index 97f4d1e..f8713ac 100644
--- a/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFBaseCompare.java
+++ b/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFBaseCompare.java
@@ -18,22 +18,28 @@
 
 package org.apache.hadoop.hive.ql.udf.generic;
 
+import org.apache.hadoop.hive.conf.HiveConf.ConfVars;
 import org.apache.hadoop.hive.ql.exec.Description;
 import org.apache.hadoop.hive.ql.exec.FunctionRegistry;
 import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
 import org.apache.hadoop.hive.ql.exec.UDFArgumentTypeException;
 import org.apache.hadoop.hive.ql.metadata.HiveException;
+import org.apache.hadoop.hive.ql.session.SessionState;
 import org.apache.hadoop.hive.ql.udf.generic.GenericUDFUtils.ReturnObjectInspectorResolver;
 import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
 import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector.Category;
 import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorConverters;
 import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorConverters.Converter;
 import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorUtils;
+import org.apache.hadoop.hive.serde2.objectinspector.PrimitiveObjectInspector;
+import org.apache.hadoop.hive.serde2.objectinspector.PrimitiveObjectInspector.PrimitiveCategory;
 import org.apache.hadoop.hive.serde2.objectinspector.primitive.BooleanObjectInspector;
 import org.apache.hadoop.hive.serde2.objectinspector.primitive.ByteObjectInspector;
 import org.apache.hadoop.hive.serde2.objectinspector.primitive.IntObjectInspector;
 import org.apache.hadoop.hive.serde2.objectinspector.primitive.LongObjectInspector;
 import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;
+import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorUtils;
+import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorUtils.PrimitiveGrouping;
 import org.apache.hadoop.hive.serde2.objectinspector.primitive.StringObjectInspector;
 import org.apache.hadoop.hive.serde2.typeinfo.TypeInfo;
 import org.apache.hadoop.hive.serde2.typeinfo.TypeInfoFactory;
@@ -145,12 +151,39 @@ public abstract class GenericUDFBaseCompare extends GenericUDFBaseBinary {
 
         converter0 = ObjectInspectorConverters.getConverter(arguments[0], compareOI);
         converter1 = ObjectInspectorConverters.getConverter(arguments[1], compareOI);
+
+        checkConversionAllowed(arguments[0], compareOI);
+        checkConversionAllowed(arguments[1], compareOI);
       }
     }
     return PrimitiveObjectInspectorFactory.writableBooleanObjectInspector;
 
   }
 
+  protected void checkConversionAllowed(ObjectInspector argOI, ObjectInspector compareOI)
+      throws UDFArgumentException {
+    if (primitiveGroupOf(argOI) != PrimitiveGrouping.DATE_GROUP) {
+      return;
+    }
+    SessionState ss = SessionState.get();
+    if (ss != null && ss.getConf().getBoolVar(ConfVars.HIVE_STRICT_TIMESTAMP_CONVERSION)) {
+      if (primitiveGroupOf(compareOI) == PrimitiveGrouping.NUMERIC_GROUP) {
+        throw new UDFArgumentException(
+            "Casting DATE/TIMESTAMP to NUMERIC is prohibited (" + ConfVars.HIVE_STRICT_TIMESTAMP_CONVERSION + ")");
+      }
+    }
+  }
+
+  protected PrimitiveGrouping primitiveGroupOf(ObjectInspector oi) {
+    if (oi instanceof PrimitiveObjectInspector) {
+      PrimitiveCategory category = ((PrimitiveObjectInspector) oi).getPrimitiveCategory();
+      PrimitiveGrouping group = PrimitiveObjectInspectorUtils.getPrimitiveGrouping(category);
+      return group;
+    } else {
+      return null;
+    }
+  }
+
   public Integer compare(DeferredObject[] arguments) throws HiveException {
     Object o0,o1;
     o0 = arguments[0].get();
diff --git a/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFTimestamp.java b/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFTimestamp.java
index 70f57b7..ba4afde 100644
--- a/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFTimestamp.java
+++ b/ql/src/java/org/apache/hadoop/hive/ql/udf/generic/GenericUDFTimestamp.java
@@ -17,8 +17,6 @@
  */
 package org.apache.hadoop.hive.ql.udf.generic;
 
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 import org.apache.hadoop.hive.conf.HiveConf.ConfVars;
 import org.apache.hadoop.hive.ql.exec.Description;
 import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
@@ -31,11 +29,13 @@ import org.apache.hadoop.hive.ql.exec.vector.expressions.CastLongToTimestamp;
 import org.apache.hadoop.hive.ql.exec.vector.expressions.CastStringToTimestamp;
 import org.apache.hadoop.hive.ql.metadata.HiveException;
 import org.apache.hadoop.hive.ql.session.SessionState;
-import org.apache.hadoop.hive.ql.session.SessionState.LogHelper;
 import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
 import org.apache.hadoop.hive.serde2.objectinspector.PrimitiveObjectInspector;
+import org.apache.hadoop.hive.serde2.objectinspector.PrimitiveObjectInspector.PrimitiveCategory;
 import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorConverter.TimestampConverter;
 import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;
+import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorUtils;
+import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorUtils.PrimitiveGrouping;
 
 /**
  *
@@ -84,6 +84,15 @@ public class GenericUDFTimestamp extends GenericUDF {
           "The function TIMESTAMP takes only primitive types");
     }
 
+    if (ss != null && ss.getConf().getBoolVar(ConfVars.HIVE_STRICT_TIMESTAMP_CONVERSION)) {
+      PrimitiveCategory category = argumentOI.getPrimitiveCategory();
+      PrimitiveGrouping group = PrimitiveObjectInspectorUtils.getPrimitiveGrouping(category);
+      if (group == PrimitiveGrouping.NUMERIC_GROUP) {
+        throw new UDFArgumentException(
+            "Casting NUMERIC types to TIMESTAMP is prohibited (" + ConfVars.HIVE_STRICT_TIMESTAMP_CONVERSION + ")");
+      }
+    }
+
     tc = new TimestampConverter(argumentOI,
         PrimitiveObjectInspectorFactory.writableTimestampObjectInspector);
     tc.setIntToTimestampInSeconds(intToTimestampInSeconds);
diff --git a/ql/src/test/queries/clientnegative/strict_numeric_to_timestamp.q b/ql/src/test/queries/clientnegative/strict_numeric_to_timestamp.q
new file mode 100644
index 0000000..da8ba71
--- /dev/null
+++ b/ql/src/test/queries/clientnegative/strict_numeric_to_timestamp.q
@@ -0,0 +1,2 @@
+set hive.strict.timestamp.conversion=true;
+select cast(123 as timestamp);
diff --git a/ql/src/test/queries/clientnegative/strict_numeric_to_timestamp2.q b/ql/src/test/queries/clientnegative/strict_numeric_to_timestamp2.q
new file mode 100644
index 0000000..002412f
--- /dev/null
+++ b/ql/src/test/queries/clientnegative/strict_numeric_to_timestamp2.q
@@ -0,0 +1,3 @@
+set hive.strict.timestamp.conversion=true;
+create table t (a integer);
+select cast(a as timestamp) from t;
diff --git a/ql/src/test/queries/clientnegative/strict_timestamp_to_numeric.q b/ql/src/test/queries/clientnegative/strict_timestamp_to_numeric.q
new file mode 100644
index 0000000..23d4420
--- /dev/null
+++ b/ql/src/test/queries/clientnegative/strict_timestamp_to_numeric.q
@@ -0,0 +1,2 @@
+set hive.strict.timestamp.conversion=true;
+select cast(cast('2011-11-11' as timestamp) as integer);
diff --git a/ql/src/test/queries/clientnegative/strict_timestamp_to_numeric2.q b/ql/src/test/queries/clientnegative/strict_timestamp_to_numeric2.q
new file mode 100644
index 0000000..a4566ff
--- /dev/null
+++ b/ql/src/test/queries/clientnegative/strict_timestamp_to_numeric2.q
@@ -0,0 +1,3 @@
+set hive.strict.timestamp.conversion=true;
+create table t(a timestamp);
+select cast(a as integer) from t;
diff --git a/ql/src/test/queries/clientnegative/strict_timestamp_to_numeric3.q b/ql/src/test/queries/clientnegative/strict_timestamp_to_numeric3.q
new file mode 100644
index 0000000..4638135
--- /dev/null
+++ b/ql/src/test/queries/clientnegative/strict_timestamp_to_numeric3.q
@@ -0,0 +1,3 @@
+set hive.strict.timestamp.conversion=true;
+create table t(a struct<t:timestamp>);
+select cast(a.t as integer) from t;
diff --git a/ql/src/test/queries/clientnegative/strict_timestamp_to_numeric4.q b/ql/src/test/queries/clientnegative/strict_timestamp_to_numeric4.q
new file mode 100644
index 0000000..dacdd8a
--- /dev/null
+++ b/ql/src/test/queries/clientnegative/strict_timestamp_to_numeric4.q
@@ -0,0 +1,3 @@
+set hive.strict.timestamp.conversion=true;
+create table t(a timestamp);
+select 1 from t where a=1000;
diff --git a/ql/src/test/results/clientnegative/strict_numeric_to_timestamp.q.out b/ql/src/test/results/clientnegative/strict_numeric_to_timestamp.q.out
new file mode 100644
index 0000000..a4c04bf
--- /dev/null
+++ b/ql/src/test/results/clientnegative/strict_numeric_to_timestamp.q.out
@@ -0,0 +1 @@
+FAILED: SemanticException Line 0:-1 Wrong arguments '123': Casting NUMERIC types to TIMESTAMP is prohibited (hive.strict.timestamp.conversion)
diff --git a/ql/src/test/results/clientnegative/strict_numeric_to_timestamp2.q.out b/ql/src/test/results/clientnegative/strict_numeric_to_timestamp2.q.out
new file mode 100644
index 0000000..199764c
--- /dev/null
+++ b/ql/src/test/results/clientnegative/strict_numeric_to_timestamp2.q.out
@@ -0,0 +1,9 @@
+PREHOOK: query: create table t (a integer)
+PREHOOK: type: CREATETABLE
+PREHOOK: Output: database:default
+PREHOOK: Output: default@t
+POSTHOOK: query: create table t (a integer)
+POSTHOOK: type: CREATETABLE
+POSTHOOK: Output: database:default
+POSTHOOK: Output: default@t
+FAILED: SemanticException Line 0:-1 Wrong arguments 'a': Casting NUMERIC types to TIMESTAMP is prohibited (hive.strict.timestamp.conversion)
diff --git a/ql/src/test/results/clientnegative/strict_timestamp_to_numeric.q.out b/ql/src/test/results/clientnegative/strict_timestamp_to_numeric.q.out
new file mode 100644
index 0000000..fc7191a
--- /dev/null
+++ b/ql/src/test/results/clientnegative/strict_timestamp_to_numeric.q.out
@@ -0,0 +1 @@
+FAILED: SemanticException Line 0:-1 Wrong arguments ''2011-11-11'': Casting DATE/TIMESTAMP types to NUMERIC is prohibited (hive.strict.timestamp.conversion)
diff --git a/ql/src/test/results/clientnegative/strict_timestamp_to_numeric2.q.out b/ql/src/test/results/clientnegative/strict_timestamp_to_numeric2.q.out
new file mode 100644
index 0000000..0f8b46f
--- /dev/null
+++ b/ql/src/test/results/clientnegative/strict_timestamp_to_numeric2.q.out
@@ -0,0 +1,9 @@
+PREHOOK: query: create table t(a timestamp)
+PREHOOK: type: CREATETABLE
+PREHOOK: Output: database:default
+PREHOOK: Output: default@t
+POSTHOOK: query: create table t(a timestamp)
+POSTHOOK: type: CREATETABLE
+POSTHOOK: Output: database:default
+POSTHOOK: Output: default@t
+FAILED: SemanticException Line 0:-1 Wrong arguments 'a': Casting DATE/TIMESTAMP types to NUMERIC is prohibited (hive.strict.timestamp.conversion)
diff --git a/ql/src/test/results/clientnegative/strict_timestamp_to_numeric3.q.out b/ql/src/test/results/clientnegative/strict_timestamp_to_numeric3.q.out
new file mode 100644
index 0000000..e8d0852
--- /dev/null
+++ b/ql/src/test/results/clientnegative/strict_timestamp_to_numeric3.q.out
@@ -0,0 +1,9 @@
+PREHOOK: query: create table t(a struct<t:timestamp>)
+PREHOOK: type: CREATETABLE
+PREHOOK: Output: database:default
+PREHOOK: Output: default@t
+POSTHOOK: query: create table t(a struct<t:timestamp>)
+POSTHOOK: type: CREATETABLE
+POSTHOOK: Output: database:default
+POSTHOOK: Output: default@t
+FAILED: SemanticException Line 0:-1 Wrong arguments 't': Casting DATE/TIMESTAMP types to NUMERIC is prohibited (hive.strict.timestamp.conversion)
diff --git a/ql/src/test/results/clientnegative/strict_timestamp_to_numeric4.q.out b/ql/src/test/results/clientnegative/strict_timestamp_to_numeric4.q.out
new file mode 100644
index 0000000..5ca64e6
--- /dev/null
+++ b/ql/src/test/results/clientnegative/strict_timestamp_to_numeric4.q.out
@@ -0,0 +1,9 @@
+PREHOOK: query: create table t(a timestamp)
+PREHOOK: type: CREATETABLE
+PREHOOK: Output: database:default
+PREHOOK: Output: default@t
+POSTHOOK: query: create table t(a timestamp)
+POSTHOOK: type: CREATETABLE
+POSTHOOK: Output: database:default
+POSTHOOK: Output: default@t
+FAILED: SemanticException [Error 10014]: Line 2:22 Wrong arguments '1000': Casting DATE/TIMESTAMP to NUMERIC is prohibited (hive.strict.timestamp.conversion)