diff --git a/mysql-test/r/order_by.result b/mysql-test/r/order_by.result
index 4033996b239f4e2f9c4d6cf46193c7d4a547d22a..006b507d409eac29aa5e52c76481a74c7de7b892 100644
--- a/mysql-test/r/order_by.result
+++ b/mysql-test/r/order_by.result
@@ -611,3 +611,35 @@ a	b
 5	2
 6	2
 drop table t1;
+create table t1 (a int not null auto_increment, b int not null, c int not null, d int not null,
+key(a,b,d), key(c,b,a));
+create table t2 like t1;
+insert into t1 values (NULL, 1, 2, 0), (NULL, 2, 1, 1), (NULL, 3, 4, 2), (NULL, 4, 3, 3);
+insert into t2 select null, b, c, d from t1;
+insert into t1 select null, b, c, d from t2;
+insert into t2 select null, b, c, d from t1;
+insert into t1 select null, b, c, d from t2;
+insert into t2 select null, b, c, d from t1;
+insert into t1 select null, b, c, d from t2;
+insert into t2 select null, b, c, d from t1;
+insert into t1 select null, b, c, d from t2;
+insert into t2 select null, b, c, d from t1;
+insert into t1 select null, b, c, d from t2;
+optimize table t1;
+Table	Op	Msg_type	Msg_text
+test.t1	optimize	status	OK
+set @row=10;
+insert into t1 select 1, b, c + (@row:=@row - 1) * 10, d - @row from t2 limit 10;
+select * from t1 where a=1 and b in (1) order by c, b, a;
+a	b	c	d
+1	1	2	0
+1	1	12	-1
+1	1	52	-5
+1	1	92	-9
+select * from t1 where a=1 and b in (1);
+a	b	c	d
+1	1	92	-9
+1	1	52	-5
+1	1	12	-1
+1	1	2	0
+drop table t1, t2;
diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result
index 1bfd74f01edf94e79bdf4167958a2d9066dd4c96..9650b7bb591689d6fbe2a37d1df70b0c8b817b45 100644
--- a/mysql-test/r/subselect.result
+++ b/mysql-test/r/subselect.result
@@ -1624,6 +1624,14 @@ select 2 in (select * from t1);
 1
 SET SQL_SELECT_LIMIT=default;
 drop table t1;
+CREATE TABLE t1 (a int, b int, INDEX (a));
+INSERT INTO t1 VALUES (1, 1), (1, 2), (1, 3);
+SELECT * FROM t1 WHERE a = (SELECT MAX(a) FROM t1 WHERE a = 1) ORDER BY b;
+a	b
+1	1
+1	2
+1	3
+DROP TABLE t1;
 create table t1(val varchar(10));
 insert into t1 values ('aaa'), ('bbb'),('eee'),('mmm'),('ppp');
 select count(*) from t1 as w1 where w1.val in (select w2.val from t1 as w2 where w2.val like 'm%') and w1.val in (select w3.val from t1 as w3 where w3.val like 'e%');
diff --git a/mysql-test/t/order_by.test b/mysql-test/t/order_by.test
index bbb0046b47ff6650302ba0e7aa0bfeb59a815cb3..2cd8dbbb95aad35df5bdc9e0105d2b44ad9b526d 100644
--- a/mysql-test/t/order_by.test
+++ b/mysql-test/t/order_by.test
@@ -393,3 +393,28 @@ select * from t1 where b=1 or b is null order by a;
 explain select * from t1 where b=2 or b is null order by a;
 select * from t1 where b=2 or b is null order by a;
 drop table t1;
+
+#
+# Bug #3155
+#
+
+create table t1 (a int not null auto_increment, b int not null, c int not null, d int not null,
+key(a,b,d), key(c,b,a));
+create table t2 like t1;
+insert into t1 values (NULL, 1, 2, 0), (NULL, 2, 1, 1), (NULL, 3, 4, 2), (NULL, 4, 3, 3);
+insert into t2 select null, b, c, d from t1;
+insert into t1 select null, b, c, d from t2;
+insert into t2 select null, b, c, d from t1;
+insert into t1 select null, b, c, d from t2;
+insert into t2 select null, b, c, d from t1;
+insert into t1 select null, b, c, d from t2;
+insert into t2 select null, b, c, d from t1;
+insert into t1 select null, b, c, d from t2;
+insert into t2 select null, b, c, d from t1;
+insert into t1 select null, b, c, d from t2;
+optimize table t1;
+set @row=10;
+insert into t1 select 1, b, c + (@row:=@row - 1) * 10, d - @row from t2 limit 10;
+select * from t1 where a=1 and b in (1) order by c, b, a;
+select * from t1 where a=1 and b in (1);
+drop table t1, t2;
diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test
index 6d766f8f8f8feb48b71ef351be92cdae745ecf1b..8da67f84c8686d2e844bf9afac3ecdcaa82611af 100644
--- a/mysql-test/t/subselect.test
+++ b/mysql-test/t/subselect.test
@@ -1067,6 +1067,14 @@ SET SQL_SELECT_LIMIT=default;
 drop table t1;
 
 #
+# Bug #3118: subselect + order by
+#
+
+CREATE TABLE t1 (a int, b int, INDEX (a));
+INSERT INTO t1 VALUES (1, 1), (1, 2), (1, 3);
+SELECT * FROM t1 WHERE a = (SELECT MAX(a) FROM t1 WHERE a = 1) ORDER BY b;
+DROP TABLE t1;
+
 # Item_cond fix field
 #
 create table t1(val varchar(10));
diff --git a/sql/item.h b/sql/item.h
index 832fc77501657efe3cd028b3e7e16d0e3a56dfd0..984c4d0c7f52b929b9499f7baaa4dc739f01a1f2 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -422,18 +422,14 @@ class Item_uint :public Item_int
 {
 public:
   Item_uint(const char *str_arg, uint length) :
-    Item_int(str_arg, (longlong) strtoull(str_arg,(char**) 0,10), length) {}
-  Item_uint(uint32 i) :Item_int((longlong) i, 10) {}
+    Item_int(str_arg, (longlong) strtoull(str_arg,(char**) 0,10), length) 
+    { unsigned_flag= 1; }
+  Item_uint(uint32 i) :Item_int((longlong) i, 10) 
+    { unsigned_flag= 1; }
   double val() { return ulonglong2double((ulonglong)value); }
   String *val_str(String*);
   Item *new_item() { return new Item_uint(name,max_length); }
   int save_in_field(Field *field, bool no_conversions);
-  bool fix_fields(THD *thd, struct st_table_list *list, Item **item)
-  {
-    bool res= Item::fix_fields(thd, list, item);
-    unsigned_flag= 1;
-    return res;
-  }
   void print(String *str);
 };
 
diff --git a/sql/item_func.cc b/sql/item_func.cc
index e365398127aa4182c87fb8ef68517a6afe96b9c4..2d98a7b8391d337392c26b5850e9e7eabb0b1b32 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -215,7 +215,8 @@ Item_func::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
     {
       Item *item;
       /* We can't yet set item to *arg as fix_fields may change *arg */
-      if ((*arg)->fix_fields(thd, tables, arg) ||
+      /* We shouldn't call fix_fields() twice, so check 'fixed' field first */
+      if ((!(*arg)->fixed && (*arg)->fix_fields(thd, tables, arg)) ||
 	  (*arg)->check_cols(allowed_arg_cols))
 	return 1;				/* purecov: inspected */
       item= *arg;
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index e49aff6d82ccc090898aa8064622fd1bbbf7a3d5..13efad05eb91de964a3452bf32ee847c75792deb 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -3451,6 +3451,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
 	tab->type=JT_ALL;
 	use_quick_range=1;
 	tab->use_quick=1;
+        tab->ref.key= -1;
 	tab->ref.key_parts=0;		// Don't use ref key.
 	join->best_positions[i].records_read= rows2double(tab->quick->records);
       }
@@ -7023,7 +7024,7 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
 
   ref_key= -1;
   /* Test if constant range in WHERE */
-  if (tab->ref.key >= 0)
+  if (tab->ref.key >= 0 && tab->ref.key_parts)
   {
     ref_key=	   tab->ref.key;
     ref_key_parts= tab->ref.key_parts;