diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result
index 078584b25d0be0dff75fc608df4fbd2f1138592f..846e54f12efb9e7588892a54c064355745be8d2d 100644
--- a/mysql-test/r/subselect.result
+++ b/mysql-test/r/subselect.result
@@ -810,7 +810,7 @@ a	t1.a in (select t2.a from t2)
 explain SELECT t1.a, t1.a in (select t2.a from t2) FROM t1;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	t1	index	NULL	PRIMARY	4	NULL	4	Using index
-2	DEPENDENT SUBQUERY	t2	index	NULL	a	5	NULL	3	Using where; Using index
+2	DEPENDENT SUBQUERY	t2	index	a	a	5	NULL	3	Using where; Using index
 drop table t1,t2;
 create table t1 (a float);
 select 10.5 IN (SELECT * from t1 LIMIT 1);
@@ -1062,7 +1062,7 @@ SELECT 0 IN (SELECT 1 FROM t1 a);
 EXPLAIN SELECT 0 IN (SELECT 1 FROM t1 a);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
-2	DEPENDENT SUBQUERY	NULL	NULL	NULL	NULL	NULL	NULL	NULL	Impossible WHERE
+2	DEPENDENT SUBQUERY	NULL	NULL	NULL	NULL	NULL	NULL	NULL	Impossible WHERE noticed after reading const tables
 INSERT INTO t1 (pseudo) VALUES ('test1');
 SELECT 0 IN (SELECT 1 FROM t1 a);
 0 IN (SELECT 1 FROM t1 a)
@@ -1070,7 +1070,7 @@ SELECT 0 IN (SELECT 1 FROM t1 a);
 EXPLAIN SELECT 0 IN (SELECT 1 FROM t1 a);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
-2	DEPENDENT SUBQUERY	NULL	NULL	NULL	NULL	NULL	NULL	NULL	Impossible WHERE
+2	DEPENDENT SUBQUERY	NULL	NULL	NULL	NULL	NULL	NULL	NULL	Impossible WHERE noticed after reading const tables
 drop table t1;
 CREATE TABLE `t1` (
 `i` int(11) NOT NULL default '0',
@@ -1099,3 +1099,9 @@ id	name
 2	lenka
 1	lenka
 drop table t1,t2;
+create table t1 (a int, unique index indexa (a));
+insert into t1 values (-1), (-4), (-2), (NULL);
+select -10 IN (select a from t1 FORCE INDEX (indexa));
+-10 IN (select a from t1 FORCE INDEX (indexa))
+NULL
+drop table t1;
diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test
index e6ae86aa83952fb14117ebb5d377849636001a68..97c3b0523b42079e4e6f1db63136b9e0e11ec6c1 100644
--- a/mysql-test/t/subselect.test
+++ b/mysql-test/t/subselect.test
@@ -690,3 +690,11 @@ INSERT INTO t2 VALUES (4,'vita'), (1,'vita'), (2,'vita'), (1,'vita');
 update t1, t2 set t2.name='lenka' where t2.id in (select id from t1);
 select * from t2;
 drop table t1,t2;
+
+#
+# correct NULL in <CONSTANT> IN (SELECT ...)
+#
+create table t1 (a int, unique index indexa (a)); 
+insert into t1 values (-1), (-4), (-2), (NULL); 
+select -10 IN (select a from t1 FORCE INDEX (indexa)); 
+drop table t1;
diff --git a/sql/item.h b/sql/item.h
index 6a7ebd506ac5c31eccb3163393f91091771c0dee..4862ad21fbede0d34db8c9cf010b953dd0bfa408 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -603,6 +603,7 @@ class Item_asterisk_remover :public Item_ref_null_helper
     item(it) 
   {}
   bool fix_fields(THD *, struct st_table_list *, Item ** ref);
+  Item **storage() {return &item;}
 };
 
 /*
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index ac2d0b4f84743204c46c6c03f9e1701e8b3e443a..0f21cf5a77467579d3829e6aad49382b5667733c 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -1781,6 +1781,43 @@ longlong Item_func_isnull::val_int()
   return args[0]->is_null() ? 1: 0;
 }
 
+longlong Item_is_not_null_test::val_int()
+{
+  DBUG_ENTER("Item_is_not_null_test::val_int");
+  if (!used_tables_cache)
+  {
+    owner->was_null|= (!cached_value);
+    DBUG_PRINT("info", ("cached :%d", cached_value));
+    DBUG_RETURN(cached_value);
+  }
+  if (args[0]->is_null())
+  {
+    DBUG_PRINT("info", ("null"))
+    owner->was_null|= 1;
+    DBUG_RETURN(0);
+  }
+  else
+    DBUG_RETURN(1);
+}
+
+/* Optimize case of not_null_column IS NULL */
+void Item_is_not_null_test::update_used_tables()
+{
+  if (!args[0]->maybe_null)
+  {
+    used_tables_cache= 0;			/* is always true */
+    cached_value= (longlong) 1;
+  }
+  else
+  {
+    args[0]->update_used_tables();
+    if (!(used_tables_cache=args[0]->used_tables()))
+    {
+      /* Remember if the value is always NULL or never NULL */
+      cached_value= (longlong) !args[0]->is_null();
+    }
+  }
+}
 
 longlong Item_func_isnotnull::val_int()
 {
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index e7670755396e03ec1df9eeb5d3505a60e7d9a413..5e246e3e2854dc52f2b1da73a7b20c960c0026e0 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -648,6 +648,7 @@ class Item_func_in :public Item_int_func
 
 class Item_func_isnull :public Item_bool_func
 {
+protected:
   longlong cached_value;
 public:
   Item_func_isnull(Item *a) :Item_bool_func(a) {}
@@ -656,11 +657,11 @@ class Item_func_isnull :public Item_bool_func
   void fix_length_and_dec()
   {
     decimals=0; max_length=1; maybe_null=0;
-    Item_func_isnull::update_used_tables();
+    update_used_tables();
   }
   const char *func_name() const { return "isnull"; }
   /* Optimize case of not_null_column IS NULL */
-  void update_used_tables()
+  virtual void update_used_tables()
   {
     if (!args[0]->maybe_null)
     {
@@ -680,6 +681,22 @@ class Item_func_isnull :public Item_bool_func
   optimize_type select_optimize() const { return OPTIMIZE_NULL; }
 };
 
+/* Functions used by HAVING for rewriting IN subquery */
+
+class Item_in_subselect;
+class Item_is_not_null_test :public Item_func_isnull
+{
+  Item_in_subselect* owner;
+public:
+  Item_is_not_null_test(Item_in_subselect* ow, Item *a)
+    :Item_func_isnull(a), owner(ow)
+  {}
+  longlong val_int();
+  const char *func_name() const { return "is_not_null_test"; }
+  void update_used_tables();
+};
+
+
 class Item_func_isnotnull :public Item_bool_func
 {
 public:
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 76451680b5991442fc17cce1b9997410c64b96ba..6c0b799b4de05b0169230db13d85ceb448260fab 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -508,9 +508,31 @@ void Item_in_subselect::single_value_transformer(THD *thd,
       sl->item_list.push_back(new Item_int("Not_used", (longlong) 1, 21));
       if (sl->table_list.elements)
       {
-	item= (*func)(expr, new Item_asterisk_remover(this, item,
-						      (char *)"<no matter>",
-						      (char*)"<result>"));
+	Item *having= item, *isnull= item;
+	if (item->type() == Item::FIELD_ITEM &&
+	    ((Item_field*) item)->field_name[0] == '*')
+	{
+	  Item_asterisk_remover *remover;
+	  item= remover= new Item_asterisk_remover(this, item,
+						   (char*)"<no matter>",
+						   (char*)"<result>");
+	  having= 
+	    new Item_is_not_null_test(this,
+				      new Item_ref(remover->storage(),
+						   (char*)"<no matter>",
+						   (char*)"<null test>"));
+	  isnull=
+	    new Item_is_not_null_test(this,
+				      new Item_ref(remover->storage(),
+						   (char*)"<no matter>",
+						   (char*)"<null test>"));
+	}
+	having= new Item_is_not_null_test(this, having);
+	sl->having= (sl->having ?
+		     new Item_cond_and(having, sl->having) :
+		     having);
+	item= new Item_cond_or((*func)(expr, item),
+			       new Item_func_isnull(isnull));
 	sl->where= and_items(sl->where, item);
       }
       else
diff --git a/sql/item_subselect.h b/sql/item_subselect.h
index 351c4af7f3333f182cc348dbba9e2ffab03649bf..fc4dad5a6b30d26e2550b05aa3a4f13b6f34963b 100644
--- a/sql/item_subselect.h
+++ b/sql/item_subselect.h
@@ -183,6 +183,7 @@ class Item_in_subselect :public Item_exists_subselect
 
   friend class Item_asterisk_remover;
   friend class Item_ref_null_helper;
+  friend class Item_is_not_null_test;
 };
 
 /* ALL/ANY/SOME subselect */
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 3fdff4e96a45b388d71aeba85ca3a907dc27f74b..f2dc2b2afd649cb581357b9c740f46b4aa7cd66f 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -299,7 +299,7 @@ JOIN::prepare(Item ***rref_pointer_array,
     DBUG_RETURN(-1);				/* purecov: inspected */
 
   ref_pointer_array= *rref_pointer_array;
-
+  
   if (having)
   {
     thd->where="having clause";
@@ -313,6 +313,7 @@ JOIN::prepare(Item ***rref_pointer_array,
     if (having->with_sum_func)
       having->split_sum_func(ref_pointer_array, all_fields);
   }
+  
   if (setup_ftfuncs(select_lex)) /* should be after having->fix_fields */
     DBUG_RETURN(-1);
   /*
@@ -426,7 +427,7 @@ JOIN::optimize()
 
 #ifdef HAVE_REF_TO_FIELDS			// Not done yet
   /* Add HAVING to WHERE if possible */
-  if (having && !group_list && ! sum_func_count)
+  if (having && !group_list && !sum_func_count)
   {
     if (!conds)
     {