Index: mysql-test/r/subselect.result
===================================================================
--- mysql-test/r/subselect.result.orig
+++ mysql-test/r/subselect.result
@@ -4397,3 +4397,20 @@ Warnings:
 Note	1003	select 1 AS `1` from `test`.`t1` where <in_optimizer>(1,<exists>(select 1 AS `1` from `test`.`t1` where (`test`.`t1`.`a` > 3) group by `test`.`t1`.`a` having (<cache>(1) = <ref_null_helper>(1))))
 DROP TABLE t1;
 End of 5.0 tests.
+#
+# Bug #52711: Segfault when doing EXPLAIN SELECT with
+#  union...order by (select... where...)
+#
+CREATE TABLE t1 (a VARCHAR(10), FULLTEXT KEY a (a));
+INSERT INTO t1 VALUES (1),(2);
+CREATE TABLE t2 (b INT);
+INSERT INTO t2 VALUES (1),(2);
+# Should not crash
+EXPLAIN
+SELECT * FROM t2 UNION SELECT * FROM t2
+ORDER BY (SELECT * FROM t1 WHERE MATCH(a) AGAINST ('+abc' IN BOOLEAN MODE));
+# Should not crash
+SELECT * FROM t2 UNION SELECT * FROM t2
+ORDER BY (SELECT * FROM t1 WHERE MATCH(a) AGAINST ('+abc' IN BOOLEAN MODE));
+DROP TABLE t1,t2;
+End of 5.1 tests
Index: mysql-test/t/subselect.test
===================================================================
--- mysql-test/t/subselect.test.orig
+++ mysql-test/t/subselect.test
@@ -3297,3 +3297,26 @@ DROP TABLE t1;
 
 --echo End of 5.0 tests.
 
+--echo #
+--echo # Bug #52711: Segfault when doing EXPLAIN SELECT with
+--echo #  union...order by (select... where...)
+--echo #
+
+CREATE TABLE t1 (a VARCHAR(10), FULLTEXT KEY a (a));
+INSERT INTO t1 VALUES (1),(2);
+CREATE TABLE t2 (b INT);
+INSERT INTO t2 VALUES (1),(2);
+
+--echo # Should not crash
+--disable_result_log
+EXPLAIN
+SELECT * FROM t2 UNION SELECT * FROM t2
+  ORDER BY (SELECT * FROM t1 WHERE MATCH(a) AGAINST ('+abc' IN BOOLEAN MODE));
+
+--echo # Should not crash
+SELECT * FROM t2 UNION SELECT * FROM t2
+  ORDER BY (SELECT * FROM t1 WHERE MATCH(a) AGAINST ('+abc' IN BOOLEAN MODE));
+DROP TABLE t1,t2;
+--enable_result_log
+
+--echo End of 5.1 tests
Index: sql/item_subselect.cc
===================================================================
--- sql/item_subselect.cc.orig
+++ sql/item_subselect.cc
@@ -367,7 +367,6 @@ Item_singlerow_subselect::select_transfo
     return RES_OK;
 
   SELECT_LEX *select_lex= join->select_lex;
-  Query_arena *arena= thd->stmt_arena;
  
   if (!select_lex->master_unit()->first_select()->next_select() &&
       !select_lex->table_list.elements &&
@@ -388,7 +387,7 @@ Item_singlerow_subselect::select_transfo
         because we do not rollback this changes
         TODO: make rollback for it, or special name resolving mode in 5.0.
       */
-      !arena->is_stmt_prepare_or_first_sp_execute()
+      !thd->stmt_arena->is_stmt_prepare_or_first_sp_execute()
       )
   {
 
@@ -415,6 +414,7 @@ Item_singlerow_subselect::select_transfo
 
 void Item_singlerow_subselect::store(uint i, Item *item)
 {
+  DBUG_ASSERT(i < max_columns);
   row[i]->store(item);
 }
 
Index: sql/sql_select.cc
===================================================================
--- sql/sql_select.cc.orig
+++ sql/sql_select.cc
@@ -6687,7 +6687,8 @@ remove_const(JOIN *join,ORDER *first_ord
       *simple_order=0;				// Must do a temp table to sort
     else if (!(order_tables & not_const_tables))
     {
-      if (order->item[0]->with_subselect)
+      if ((order->item[0]->with_subselect) &&
+          !(join->select_lex->options & SELECT_DESCRIBE))
         order->item[0]->val_str(&order->item[0]->str_value);
       DBUG_PRINT("info",("removing: %s", order->item[0]->full_name()));
       continue;					// skip const item
Index: libmysqld/sql_select.cc
===================================================================
--- libmysqld/sql_select.cc.orig
+++ libmysqld/sql_select.cc
@@ -6687,7 +6687,8 @@ remove_const(JOIN *join,ORDER *first_ord
       *simple_order=0;				// Must do a temp table to sort
     else if (!(order_tables & not_const_tables))
     {
-      if (order->item[0]->with_subselect)
+      if ((order->item[0]->with_subselect)) &&
+          !(join->select_lex->options & SELECT_DESCRIBE))
         order->item[0]->val_str(&order->item[0]->str_value);
       DBUG_PRINT("info",("removing: %s", order->item[0]->full_name()));
       continue;					// skip const item
