 mysql-test/r/cache_temporal_4265.result   |  1 -
 mysql-test/r/derived_cond_pushdown.result |  8 +--
 mysql-test/r/range.result                 |  2 -
 mysql-test/r/range_mrr_icp.result         |  2 -
 mysql-test/r/type_date.result             |  4 +-
 mysql-test/t/a.test                       |  1 +
 sql/field.h                               |  6 ++-
 sql/item.cc                               | 48 ++++++------------
 sql/item.h                                | 13 ++---
 sql/item_cmpfunc.cc                       | 83 +++++++++----------------------
 sql/item_cmpfunc.h                        | 20 ++------
 11 files changed, 57 insertions(+), 131 deletions(-)

diff --git a/mysql-test/r/cache_temporal_4265.result b/mysql-test/r/cache_temporal_4265.result
index 980bb957e19..7f215de43fb 100644
--- a/mysql-test/r/cache_temporal_4265.result
+++ b/mysql-test/r/cache_temporal_4265.result
@@ -7,7 +7,6 @@ a
 2002-03-04
 Warnings:
 Note	1003	2000-01-01
-Note	1003	2000-01-06
 set debug_dbug='';
 drop table t1;
 create table t1 (id int not null, ut timestamp(6) not null);
diff --git a/mysql-test/r/derived_cond_pushdown.result b/mysql-test/r/derived_cond_pushdown.result
index 0be577a9f64..5c9c57904e8 100644
--- a/mysql-test/r/derived_cond_pushdown.result
+++ b/mysql-test/r/derived_cond_pushdown.result
@@ -8019,7 +8019,7 @@ EXPLAIN
       "access_type": "ALL",
       "rows": 3,
       "filtered": 100,
-      "attached_condition": "sq.i = 2007-05-28 00:00:00",
+      "attached_condition": "sq.i = '2007-05-28 00:00:00'",
       "materialized": {
         "query_block": {
           "select_id": 2,
@@ -8071,7 +8071,7 @@ EXPLAIN
       "access_type": "ALL",
       "rows": 3,
       "filtered": 100,
-      "attached_condition": "sq.i = 2007-05-28",
+      "attached_condition": "sq.i = '2007-05-28'",
       "materialized": {
         "query_block": {
           "select_id": 2,
@@ -8080,7 +8080,7 @@ EXPLAIN
             "access_type": "ALL",
             "rows": 3,
             "filtered": 100,
-            "attached_condition": "t1.i = TIMESTAMP'2007-05-28 00:00:00'"
+            "attached_condition": "t1.i = DATE'2007-05-28'"
           }
         }
       }
@@ -8123,7 +8123,7 @@ EXPLAIN
       "access_type": "ALL",
       "rows": 3,
       "filtered": 100,
-      "attached_condition": "sq.i = 10:00:02",
+      "attached_condition": "sq.i = '10:00:02'",
       "materialized": {
         "query_block": {
           "select_id": 2,
diff --git a/mysql-test/r/range.result b/mysql-test/r/range.result
index 5027fffe047..cfaf28fb4b1 100644
--- a/mysql-test/r/range.result
+++ b/mysql-test/r/range.result
@@ -1595,8 +1595,6 @@ NULL
 Warnings:
 Warning	1411	Incorrect datetime value: '2007-20-00' for function str_to_date
 Warning	1411	Incorrect datetime value: '2007-20-00' for function str_to_date
-Warning	1411	Incorrect datetime value: '2007-20-00' for function str_to_date
-Warning	1411	Incorrect datetime value: '2007-20-00' for function str_to_date
 SELECT str_to_date('2007-10-00', '%Y-%m-%d') BETWEEN '' AND '2007/10/20';
 str_to_date('2007-10-00', '%Y-%m-%d') BETWEEN '' AND '2007/10/20'
 1
diff --git a/mysql-test/r/range_mrr_icp.result b/mysql-test/r/range_mrr_icp.result
index 7d009070150..e1ff8769cd7 100644
--- a/mysql-test/r/range_mrr_icp.result
+++ b/mysql-test/r/range_mrr_icp.result
@@ -1597,8 +1597,6 @@ NULL
 Warnings:
 Warning	1411	Incorrect datetime value: '2007-20-00' for function str_to_date
 Warning	1411	Incorrect datetime value: '2007-20-00' for function str_to_date
-Warning	1411	Incorrect datetime value: '2007-20-00' for function str_to_date
-Warning	1411	Incorrect datetime value: '2007-20-00' for function str_to_date
 SELECT str_to_date('2007-10-00', '%Y-%m-%d') BETWEEN '' AND '2007/10/20';
 str_to_date('2007-10-00', '%Y-%m-%d') BETWEEN '' AND '2007/10/20'
 1
diff --git a/mysql-test/r/type_date.result b/mysql-test/r/type_date.result
index b28cf54f53a..aa010b2c258 100644
--- a/mysql-test/r/type_date.result
+++ b/mysql-test/r/type_date.result
@@ -434,9 +434,7 @@ insert into t1 values ('2012-01-01'),('2012-02-02');
 explain
 select 1 from t1 as t1_0 inner join t1 as t2 on (t1_0.a <=> now()) join t1 on 1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	SIMPLE	t1_0	ref	a	a	4	const	0	Using where; Using index
-1	SIMPLE	t2	index	NULL	a	4	NULL	2	Using index; Using join buffer (flat, BNL join)
-1	SIMPLE	t1	index	NULL	a	4	NULL	2	Using index; Using join buffer (incremental, BNL join)
+1	SIMPLE	NULL	NULL	NULL	NULL	NULL	NULL	NULL	Impossible WHERE noticed after reading const tables
 select 1 from t1 as t1_0 inner join t1 as t2 on (t1_0.a <=> now()) join t1 on 1;
 1
 drop table t1;
diff --git a/mysql-test/t/a.test b/mysql-test/t/a.test
new file mode 100644
index 00000000000..e9a0aaf651b
--- /dev/null
+++ b/mysql-test/t/a.test
@@ -0,0 +1 @@
+SELECT TIME'00:00:00'> CAST(0xFFFFFFFF00000000 AS UNSIGNED);
diff --git a/sql/field.h b/sql/field.h
index 1142915235a..52c49ee4b40 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -586,11 +586,15 @@ static inline const char *vcol_type_name(enum_vcol_info_type type)
   Flags for Virtual_column_info. If none is set, the expression must be
   a constant with no side-effects, so it's calculated at CREATE TABLE time,
   stored in table->record[2], and not recalculated for every statement.
+
+  Also, VCOL_SESSION_FUNC means that vcol expression has session-dependent
+  (a.k.a. THD-dependend) data and it needs fix_fields() to be run
+  for every statement (in case THD has changed).
 */
 #define VCOL_FIELD_REF         1
 #define VCOL_NON_DETERMINISTIC 2
 #define VCOL_SESSION_FUNC      4  /* uses session data, e.g. USER or DAYNAME */
-#define VCOL_TIME_FUNC         8
+#define VCOL_TIME_FUNC         8  /* NOW() etc */
 #define VCOL_IMPOSSIBLE       16
 
 #define VCOL_NOT_STRICTLY_DETERMINISTIC                       \
diff --git a/sql/item.cc b/sql/item.cc
index 753dd5035b1..ebc657dac78 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -9139,14 +9139,16 @@ void resolve_const_item(THD *thd, Item **ref, Item *comp_item)
   switch (res_type) {
   case TIME_RESULT:
   {
-    bool is_null;
-    Item **ref_copy= ref;
-    /* the following call creates a constant and puts it in new_item */
     enum_field_types type= item->field_type_for_temporal_comparison(comp_item);
-    get_datetime_value(thd, &ref_copy, &new_item, type, &is_null);
-    if (is_null)
+    longlong value= item->val_temporal_packed(type);
+    if (item->null_value)
       new_item= new (mem_root) Item_null(thd, name);
-    break;
+    else
+    {
+      Item_datetime *dt= new (mem_root) Item_datetime(thd);
+      dt->set(value);
+      new_item= dt;
+    }
   }
   case STRING_RESULT:
   {
@@ -9551,20 +9553,19 @@ double Item_cache_temporal::val_real()
 }
 
 
-bool  Item_cache_temporal::cache_value()
+bool Item_cache_temporal::cache_value()
 {
   if (!example)
     return false;
 
-  value_cached= true;
- 
   MYSQL_TIME ltime;
-  if (example->get_date_result(&ltime, 0))
-    value=0;
-  else
-    value= pack_time(&ltime);
+  uint fuzzydate= TIME_FUZZY_DATES | TIME_INVALID_DATES;
+  if (Item_cache_temporal::field_type() == MYSQL_TYPE_TIME)
+    fuzzydate|= TIME_TIME_ONLY;
+
+  value= example->get_date_result(&ltime, fuzzydate) ? 0 : pack_time(&ltime);
   null_value= example->null_value;
-  return true;
+  return value_cached= true;
 }
 
 
@@ -9601,25 +9602,6 @@ int Item_cache_temporal::save_in_field(Field *field, bool no_conversions)
 }
 
 
-void Item_cache_temporal::store_packed(longlong val_arg, Item *example_arg)
-{
-  /* An explicit values is given, save it. */
-  store(example_arg);
-  value_cached= true;
-  value= val_arg;
-  null_value= false;
-}
-
-
-Item *Item_cache_temporal::clone_item(THD *thd)
-{
-  Item_cache_temporal *item= new (thd->mem_root)
-    Item_cache_temporal(thd, Item_cache_temporal::field_type());
-  item->store_packed(value, example);
-  return item;
-}
-
-
 Item *Item_cache_temporal::convert_to_basic_const_item(THD *thd)
 {
   Item *new_item;
diff --git a/sql/item.h b/sql/item.h
index a9eaeb073c3..a4e707ef4b0 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -1345,7 +1345,7 @@ class Item: public Value_source,
   /*
     Get time with automatic DATE/DATETIME to TIME conversion.
 
-    Performce a reserve operation to get_date_with_conversion().
+    Performes a reverse operation to get_date_with_conversion().
     Suppose:
     - we have a set of items (typically with the native MYSQL_TYPE_TIME type)
       whose item->get_date() return TIME1 value, and
@@ -3718,7 +3718,7 @@ class Item_date_literal_for_invalid_dates: public Item_date_literal
 
     Item_date_literal_for_invalid_dates::get_date()
     (unlike the regular Item_date_literal::get_date())
-    does not check the result for NO_ZERO_IN_DATE and NO_ZER_DATE,
+    does not check the result for NO_ZERO_IN_DATE and NO_ZERO_DATE,
     always returns success (false), and does not produce error/warning messages.
 
     We need these _for_invalid_dates classes to be able to rewrite:
@@ -5396,7 +5396,7 @@ class Item_cache: public Item_basic_constant,
   virtual void store(Item *item);
   virtual bool cache_value()= 0;
   bool basic_const_item() const
-  { return MY_TEST(example && example->basic_const_item()); }
+  { return example && example->basic_const_item(); }
   virtual void clear() { null_value= TRUE; value_cached= FALSE; }
   bool is_null() { return !has_value(); }
   virtual bool is_expensive()
@@ -5474,13 +5474,6 @@ class Item_cache_temporal: public Item_cache_int
   bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate);
   int save_in_field(Field *field, bool no_conversions);
   Item_result cmp_type() const { return TIME_RESULT; }
-  void store_packed(longlong val_arg, Item *example);
-  /*
-    Having a clone_item method tells optimizer that this object
-    is a constant and need not be optimized further.
-    Important when storing packed datetime values.
-  */
-  Item *clone_item(THD *thd);
   Item *convert_to_basic_const_item(THD *thd);
   Item *get_copy(THD *thd, MEM_ROOT *mem_root)
   { return get_item_copy<Item_cache_temporal>(thd, mem_root, this); }
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 2856cea0697..508954b9d1e 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -610,7 +610,7 @@ int Arg_comparator::set_compare_func(Item_func_or_sum *item, Item_result type)
 int Arg_comparator::set_cmp_func(Item_func_or_sum *owner_arg,
                                  Item **a1, Item **a2)
 {
-  thd= current_thd;
+  THD *thd= current_thd;
   owner= owner_arg;
   set_null= set_null && owner_arg;
   a= a1;
@@ -642,7 +642,6 @@ int Arg_comparator::set_cmp_func(Item_func_or_sum *owner_arg,
       func= is_owner_equal_func() ? &Arg_comparator::compare_e_datetime :
                                     &Arg_comparator::compare_datetime;
     }
-    return 0;
   }
 
   if (m_compare_type == INT_RESULT &&
@@ -654,6 +653,7 @@ int Arg_comparator::set_cmp_func(Item_func_or_sum *owner_arg,
                                   &Arg_comparator::compare_datetime;
   }
 
+#error Item_cache_temporal constructor needs to know f_type not m_compare_type
   a= cache_converted_constant(thd, a, &a_cache, m_compare_type);
   b= cache_converted_constant(thd, b, &b_cache, m_compare_type);
   return set_compare_func(owner_arg, m_compare_type);
@@ -677,21 +677,16 @@ int Arg_comparator::set_cmp_func(Item_func_or_sum *owner_arg,
   @return cache item or original value.
 */
 
-Item** Arg_comparator::cache_converted_constant(THD *thd_arg, Item **value,
+Item** Arg_comparator::cache_converted_constant(THD *thd, Item **value,
                                                 Item **cache_item,
                                                 Item_result type)
 {
-  /*
-    Don't need cache if doing context analysis only.
-    Also, get_datetime_value creates Item_cache internally.
-    Unless fixed, we should not do it here.
-  */
-  if (!thd_arg->lex->is_ps_or_view_context_analysis() &&
-      (*value)->const_item() && type != (*value)->result_type() &&
-      type != TIME_RESULT)
+  /* Don't need cache if doing context analysis only.  */
+  if (!thd->lex->is_ps_or_view_context_analysis() &&
+      (*value)->const_item() && type != (*value)->result_type())
   {
-    Item_cache *cache= Item_cache::get_cache(thd_arg, *value, type);
-    cache->setup(thd_arg, *value);
+    Item_cache *cache= Item_cache::get_cache(thd, *value, type);
+    cache->setup(thd, *value);
     *cache_item= cache;
     return cache_item;
   }
@@ -730,28 +725,11 @@ Item** Arg_comparator::cache_converted_constant(THD *thd_arg, Item **value,
     MYSQL_TIME value, packed in a longlong, suitable for comparison.
 */
 
-longlong
-get_datetime_value(THD *thd, Item ***item_arg, Item **cache_arg,
-                   enum_field_types f_type, bool *is_null)
+longlong get_datetime_value(Item *item, enum_field_types f_type, bool *is_null)
 {
-  longlong UNINIT_VAR(value);
-  Item *item= **item_arg;
-  value= item->val_temporal_packed(f_type);
+  longlong value= item->val_temporal_packed(f_type);
   if ((*is_null= item->null_value))
     return ~(ulonglong) 0;
-  if (cache_arg && item->const_item() &&
-      !(item->type() == Item::CACHE_ITEM && item->cmp_type() == TIME_RESULT))
-  {
-    Query_arena backup;
-    Query_arena *save_arena= thd->switch_to_arena_for_cached_items(&backup);
-    Item_cache_temporal *cache= new (thd->mem_root) Item_cache_temporal(thd, f_type);
-    if (save_arena)
-      thd->set_query_arena(save_arena);
-
-    cache->store_packed(value, item);
-    *cache_arg= cache;
-    *item_arg= cache_arg;
-  }
   return value;
 }
 
@@ -782,12 +760,12 @@ int Arg_comparator::compare_temporal(enum_field_types type)
     owner->null_value= 1;
 
   /* Get DATE/DATETIME/TIME value of the 'a' item. */
-  a_value= get_datetime_value(thd, &a, &a_cache, type, &a_is_null);
+  a_value= get_datetime_value(*a, type, &a_is_null);
   if (a_is_null)
     return -1;
 
   /* Get DATE/DATETIME/TIME value of the 'b' item. */
-  b_value= get_datetime_value(thd, &b, &b_cache, type, &b_is_null);
+  b_value= get_datetime_value(*b, type, &b_is_null);
   if (b_is_null)
     return -1;
 
@@ -805,10 +783,10 @@ int Arg_comparator::compare_e_temporal(enum_field_types type)
   longlong a_value, b_value;
 
   /* Get DATE/DATETIME/TIME value of the 'a' item. */
-  a_value= get_datetime_value(thd, &a, &a_cache, type, &a_is_null);
+  a_value= get_datetime_value(*a, type, &a_is_null);
 
   /* Get DATE/DATETIME/TIME value of the 'b' item. */
-  b_value= get_datetime_value(thd, &b, &b_cache, type, &b_is_null);
+  b_value= get_datetime_value(*b, type, &b_is_null);
   return a_is_null || b_is_null ? a_is_null == b_is_null
                                 : a_value == b_value;
 }
@@ -2071,7 +2049,7 @@ void Item_func_between::fix_length_and_dec()
   if (m_compare_type ==  TIME_RESULT)
     compare_as_dates= find_date_time_item(args, 3, 0);
 
-  /* See the comment about the similar block in Item_bool_func2 */
+  /* See the comment for Item_func::convert_const_compared_to_int_field */
   if (args[0]->real_item()->type() == FIELD_ITEM &&
       !thd->lex->is_ps_or_view_context_analysis())
   {
@@ -2095,29 +2073,18 @@ longlong Item_func_between::val_int()
   switch (m_compare_type) {
   case TIME_RESULT:
   {
-    THD *thd= current_thd;
     longlong value, a, b;
-    Item *cache, **ptr;
     bool value_is_null, a_is_null, b_is_null;
 
-    ptr= &args[0];
     enum_field_types f_type= field_type_for_temporal_comparison(compare_as_dates);
-    value= get_datetime_value(thd, &ptr, &cache, f_type, &value_is_null);
-    if (ptr != &args[0])
-      thd->change_item_tree(&args[0], *ptr);
+    value= get_datetime_value(args[0], f_type, &value_is_null);
 
     if ((null_value= value_is_null))
       return 0;
 
-    ptr= &args[1];
-    a= get_datetime_value(thd, &ptr, &cache, f_type, &a_is_null);
-    if (ptr != &args[1])
-      thd->change_item_tree(&args[1], *ptr);
+    a= get_datetime_value(args[1], f_type, &a_is_null);
 
-    ptr= &args[2];
-    b= get_datetime_value(thd, &ptr, &cache, f_type, &b_is_null);
-    if (ptr != &args[2])
-      thd->change_item_tree(&args[2], *ptr);
+    b= get_datetime_value(args[2], f_type, &b_is_null);
 
     if (!a_is_null && !b_is_null)
       return (longlong) ((value >= a && value <= b) != negated);
@@ -3739,10 +3706,8 @@ void in_datetime::set(uint pos,Item *item)
 uchar *in_datetime::get_value(Item *item)
 {
   bool is_null;
-  Item **tmp_item= lval_cache ? &lval_cache : &item;
-  enum_field_types f_type=
-    tmp_item[0]->field_type_for_temporal_comparison(warn_item);
-  tmp.val= get_datetime_value(thd, &tmp_item, &lval_cache, f_type, &is_null);
+  enum_field_types f_type= item->field_type_for_temporal_comparison(warn_item);
+  tmp.val= get_datetime_value(item, f_type, &is_null);
   if (item->null_value)
     return 0;
   tmp.unsigned_flag= 1L;
@@ -4004,10 +3969,8 @@ cmp_item* cmp_item_decimal::make_same()
 void cmp_item_datetime::store_value(Item *item)
 {
   bool is_null;
-  Item **tmp_item= lval_cache ? &lval_cache : &item;
-  enum_field_types f_type=
-    tmp_item[0]->field_type_for_temporal_comparison(warn_item);
-  value= get_datetime_value(thd, &tmp_item, &lval_cache, f_type, &is_null);
+  enum_field_types f_type= item->field_type_for_temporal_comparison(warn_item);
+  value= get_datetime_value(item, f_type, &is_null);
   m_null_value= item->null_value;
 }
 
@@ -4234,7 +4197,7 @@ void Item_func_in::fix_length_and_dec()
       values on the right can be compared as integers and adjust the 
       comparison type accordingly.
 
-      See the comment about the similar block in Item_bool_func2
+      And see the comment for Item_func::convert_const_compared_to_int_field
     */  
     if (args[0]->real_item()->type() == FIELD_ITEM &&
         !thd->lex->is_view_context_analysis() && m_compare_type != INT_RESULT)
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 7774663bd57..95f9d6a73be 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -55,7 +55,6 @@ class Arg_comparator: public Sql_alloc
   Arg_comparator *comparators;   // used only for compare_row()
   double precision;
   /* Fields used in DATE/DATETIME comparison. */
-  THD *thd;
   Item *a_cache, *b_cache;         // Cached values of a and b items
                                    //   when one of arguments is NULL.
   int set_compare_func(Item_func_or_sum *owner, Item_result type);
@@ -70,12 +69,12 @@ class Arg_comparator: public Sql_alloc
 
   Arg_comparator(): m_compare_type(STRING_RESULT),
     m_compare_collation(&my_charset_bin),
-    set_null(TRUE), comparators(0), thd(0),
+    set_null(TRUE), comparators(0),
     a_cache(0), b_cache(0) {};
   Arg_comparator(Item **a1, Item **a2): a(a1), b(a2),
     m_compare_type(STRING_RESULT),
     m_compare_collation(&my_charset_bin),
-    set_null(TRUE), comparators(0), thd(0),
+    set_null(TRUE), comparators(0),
     a_cache(0), b_cache(0) {};
 
 public:
@@ -1262,21 +1261,15 @@ class in_longlong :public in_vector
 /*
   Class to represent a vector of constant DATE/DATETIME values.
   Values are obtained with help of the get_datetime_value() function.
-  If the left item is a constant one then its value is cached in the
-  lval_cache variable.
 */
 class in_datetime :public in_longlong
 {
 public:
-  THD *thd;
   /* An item used to issue warnings. */
   Item *warn_item;
-  /* Cache for the left item. */
-  Item *lval_cache;
 
   in_datetime(THD *thd, Item *warn_item_arg, uint elements)
-    :in_longlong(thd, elements), thd(current_thd), warn_item(warn_item_arg),
-     lval_cache(0) {};
+    : in_longlong(thd, elements), warn_item(warn_item_arg) {};
   void set(uint pos,Item *item);
   uchar *get_value(Item *item);
   Item *create_item(THD *thd);
@@ -1445,14 +1438,11 @@ class cmp_item_datetime : public cmp_item_scalar
 {
   longlong value;
 public:
-  THD *thd;
   /* Item used for issuing warnings. */
   Item *warn_item;
-  /* Cache for the left item. */
-  Item *lval_cache;
 
   cmp_item_datetime(Item *warn_item_arg)
-    :thd(current_thd), warn_item(warn_item_arg), lval_cache(0) {}
+    : warn_item(warn_item_arg) {}
   void store_value(Item *item);
   int cmp(Item *arg);
   int compare(cmp_item *ci);
@@ -2609,7 +2599,7 @@ inline bool is_cond_or(Item *item)
 
 Item *and_expressions(Item *a, Item *b, Item **org_item);
 
-longlong get_datetime_value(THD *thd, Item ***item_arg, Item **cache_arg,
+longlong get_datetime_value(Item ***item_arg, Item **cache_arg,
                             enum_field_types f_type, bool *is_null);
 
 
