diff --git a/mysql-test/r/gis-rtree.result b/mysql-test/r/gis-rtree.result
index c400ebb39ef7ccd5ac16de976292622a6c3f492c..345914c9e51155ec30665083058f237aab0db960 100644
--- a/mysql-test/r/gis-rtree.result
+++ b/mysql-test/r/gis-rtree.result
@@ -1596,3 +1596,27 @@ SELECT COUNT(*) FROM t1 FORCE INDEX(l) WHERE MBRWithin(GEOMFROMTEXT('POINT(0 0)'
 COUNT(*)
 1
 DROP TABLE t1;
+#
+# Start of 10.1 tests
+#
+#
+# MDEV-8239 Reverse spatial operations OP(const, field) do not get optimized
+#
+CREATE TABLE t1 (a GEOMETRY NOT NULL, SPATIAL KEY(a)) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (Point(1,2)),(Point(1,3));
+EXPLAIN SELECT * FROM t1 WHERE MBRINTERSECTS(a,Point(1,2));
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	range	a	a	34	NULL	1	Using where
+EXPLAIN SELECT * FROM t1 WHERE ST_INTERSECTS(a,Point(1,2));
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	range	a	a	34	NULL	1	Using where
+EXPLAIN SELECT * FROM t1 WHERE MBRINTERSECTS(Point(1,2),a);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	range	a	a	34	NULL	1	Using where
+EXPLAIN SELECT * FROM t1 WHERE ST_INTERSECTS(Point(1,2),a);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t1	range	a	a	34	NULL	1	Using where
+DROP TABLE t1;
+#
+# End of 10.1 tests
+#
diff --git a/mysql-test/t/gis-rtree.test b/mysql-test/t/gis-rtree.test
index 404f0447f568f897efb23f822d64f1034ef58cdf..9c8dce5012781145d7ef805a07e30fccab7dc2e0 100644
--- a/mysql-test/t/gis-rtree.test
+++ b/mysql-test/t/gis-rtree.test
@@ -976,3 +976,23 @@ SELECT COUNT(*) FROM t1 FORCE INDEX(l) WHERE MBRContains(l, GEOMFROMTEXT('POINT(
 SELECT COUNT(*) FROM t1 FORCE INDEX(l) WHERE MBRWithin(GEOMFROMTEXT('POINT(0 0)'), l);
 
 DROP TABLE t1;
+
+
+--echo #
+--echo # Start of 10.1 tests
+--echo #
+
+--echo #
+--echo # MDEV-8239 Reverse spatial operations OP(const, field) do not get optimized
+--echo #
+CREATE TABLE t1 (a GEOMETRY NOT NULL, SPATIAL KEY(a)) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (Point(1,2)),(Point(1,3));
+EXPLAIN SELECT * FROM t1 WHERE MBRINTERSECTS(a,Point(1,2));
+EXPLAIN SELECT * FROM t1 WHERE ST_INTERSECTS(a,Point(1,2));
+EXPLAIN SELECT * FROM t1 WHERE MBRINTERSECTS(Point(1,2),a);
+EXPLAIN SELECT * FROM t1 WHERE ST_INTERSECTS(Point(1,2),a);
+DROP TABLE t1;
+
+--echo #
+--echo # End of 10.1 tests
+--echo #
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index c19341c3ee13bdd9ab320519f214431233117f1f..35310219c457b05750490ede84a9fbda750af9e9 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -297,11 +297,6 @@ public:
   virtual enum Functype rev_functype() const { return UNKNOWN_FUNC; }
   bool have_rev_func() const { return rev_functype() != UNKNOWN_FUNC; }
 
-  virtual inline void print(String *str, enum_query_type query_type)
-  {
-    Item_func::print_op(str, query_type);
-  }
-
   bool is_null() { return MY_TEST(args[0]->is_null() || args[1]->is_null()); }
   COND *remove_eq_conds(THD *thd, Item::cond_result *cond_value,
                         bool top_level);
@@ -318,6 +313,10 @@ public:
   {
     allowed_arg_cols= 0;  // Fetch this value from first argument
   }
+  void print(String *str, enum_query_type query_type)
+  {
+    Item_func::print_op(str, query_type);
+  }
   Item *neg_transformer(THD *thd);
   virtual Item *negated_item();
   bool subst_argument_checker(uchar **arg)
@@ -1505,6 +1504,10 @@ public:
      escape_used_in_parsing(escape_used), use_sampling(0) {}
   longlong val_int();
   enum Functype functype() const { return LIKE_FUNC; }
+  void print(String *str, enum_query_type query_type)
+  {
+    Item_func::print_op(str, query_type);
+  }
   optimize_type select_optimize() const;
   CHARSET_INFO *compare_collation() const
   { return cmp_collation.collation; }
diff --git a/sql/item_geofunc.h b/sql/item_geofunc.h
index 72dddee1fbaf74f9eec65dfc7fb1e4d4d8f8d5c7..4ae3be73da10cde4eeecc68cf1ef6a0f8211f7b2 100644
--- a/sql/item_geofunc.h
+++ b/sql/item_geofunc.h
@@ -272,19 +272,18 @@ public:
   Spatial relations
 */
 
-class Item_func_spatial_rel: public Item_bool_func
+class Item_func_spatial_rel: public Item_bool_func2
 {
 protected:
   enum Functype spatial_rel;
   String tmp_value1, tmp_value2;
 public:
   Item_func_spatial_rel(Item *a, Item *b, enum Functype sp_rel)
-   :Item_bool_func(a, b), spatial_rel(sp_rel)
+   :Item_bool_func2(a, b), spatial_rel(sp_rel)
   { }
   enum Functype functype() const { return spatial_rel; }
   enum Functype rev_functype() const { return spatial_rel; }
   bool is_null() { (void) val_int(); return null_value; }
-  optimize_type select_optimize() const { return OPTIMIZE_OP; }
   void add_key_fields(JOIN *join, KEY_FIELD **key_fields,
                       uint *and_level, table_map usable_tables,
                       SARGABLE_PARAM **sargables)