diff --git a/mysql-test/r/join_cache.result b/mysql-test/r/join_cache.result
index db869ba434a0725f91772b8056443bb74e1ed395..11114a032f93754256df8a1099982e985923164c 100644
--- a/mysql-test/r/join_cache.result
+++ b/mysql-test/r/join_cache.result
@@ -5486,4 +5486,52 @@ i
 set join_cache_level = default;
 set optimizer_switch=@tmp_optimizer_switch;
 DROP TABLE t1,t2,t3;
+#
+# Bug #12546542: missing row with semijoin=off + join cache
+# (LP bug #922971)
+#
+CREATE TABLE t1 (a varchar(1024));
+INSERT INTO t1 VALUES ('v'), ('we');
+CREATE TABLE t2 (
+a varchar(1024) CHARACTER SET utf8 DEFAULT NULL, b int, c int
+);
+INSERT INTO t2 VALUES ('we',4,NULL), ('v',1305673728,6);
+CREATE TABLE t3 (b int, c int);
+INSERT INTO t3 VALUES (4,4);
+set @tmp_optimizer_switch=@@optimizer_switch;
+set optimizer_switch='semijoin=off';
+set optimizer_switch='materialization=off';
+set join_cache_level=0;
+EXPLAIN
+SELECT * FROM t1
+WHERE a IN (SELECT t2.a FROM t2 LEFT JOIN t3 ON t2.b = t3.b 
+WHERE t2.c < 10 OR t3.c > 1);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	PRIMARY	t1	ALL	NULL	NULL	NULL	NULL	2	Using where
+2	DEPENDENT SUBQUERY	t2	ALL	NULL	NULL	NULL	NULL	2	Using where
+2	DEPENDENT SUBQUERY	t3	ALL	NULL	NULL	NULL	NULL	1	Using where
+SELECT * FROM t1
+WHERE a IN (SELECT t2.a FROM t2 LEFT JOIN t3 ON t2.b = t3.b 
+WHERE t2.c < 10 OR t3.c > 1);
+a
+v
+we
+set join_cache_level=2;
+EXPLAIN
+SELECT * FROM t1
+WHERE a IN (SELECT t2.a FROM t2 LEFT JOIN t3 ON t2.b = t3.b
+WHERE t2.c < 10 OR t3.c > 1);
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	PRIMARY	t1	ALL	NULL	NULL	NULL	NULL	2	Using where
+2	DEPENDENT SUBQUERY	t2	ALL	NULL	NULL	NULL	NULL	2	Using where
+2	DEPENDENT SUBQUERY	t3	ALL	NULL	NULL	NULL	NULL	1	Using where; Using join buffer (flat, BNL join)
+SELECT * FROM t1
+WHERE a IN (SELECT t2.a FROM t2 LEFT JOIN t3 ON t2.b = t3.b
+WHERE t2.c < 10 OR t3.c > 1);
+a
+v
+we
+set join_cache_level = default;
+set optimizer_switch=@tmp_optimizer_switch;
+DROP TABLE t1,t2,t3;
 set @@optimizer_switch=@save_optimizer_switch;
diff --git a/mysql-test/t/join_cache.test b/mysql-test/t/join_cache.test
index cc1941e16b925fe6b7b9ca0542595d40d61ab6fc..8a61c00b7d432369ab99c5909106b83a79ceaf50 100644
--- a/mysql-test/t/join_cache.test
+++ b/mysql-test/t/join_cache.test
@@ -3505,5 +3505,47 @@ set optimizer_switch=@tmp_optimizer_switch;
 
 DROP TABLE t1,t2,t3;
 
+--echo #
+--echo # Bug #12546542: missing row with semijoin=off + join cache
+--echo # (LP bug #922971)
+--echo #
+
+CREATE TABLE t1 (a varchar(1024));
+INSERT INTO t1 VALUES ('v'), ('we');
+CREATE TABLE t2 (
+  a varchar(1024) CHARACTER SET utf8 DEFAULT NULL, b int, c int
+);
+INSERT INTO t2 VALUES ('we',4,NULL), ('v',1305673728,6);
+CREATE TABLE t3 (b int, c int);
+INSERT INTO t3 VALUES (4,4);
+
+set @tmp_optimizer_switch=@@optimizer_switch;
+set optimizer_switch='semijoin=off';
+set optimizer_switch='materialization=off';
+
+set join_cache_level=0;
+EXPLAIN
+SELECT * FROM t1
+  WHERE a IN (SELECT t2.a FROM t2 LEFT JOIN t3 ON t2.b = t3.b 
+                WHERE t2.c < 10 OR t3.c > 1);
+
+SELECT * FROM t1
+  WHERE a IN (SELECT t2.a FROM t2 LEFT JOIN t3 ON t2.b = t3.b 
+                WHERE t2.c < 10 OR t3.c > 1);
+
+set join_cache_level=2;
+EXPLAIN
+SELECT * FROM t1
+  WHERE a IN (SELECT t2.a FROM t2 LEFT JOIN t3 ON t2.b = t3.b
+                WHERE t2.c < 10 OR t3.c > 1);
+SELECT * FROM t1
+  WHERE a IN (SELECT t2.a FROM t2 LEFT JOIN t3 ON t2.b = t3.b
+                WHERE t2.c < 10 OR t3.c > 1);
+
+set join_cache_level = default;
+set optimizer_switch=@tmp_optimizer_switch;
+
+DROP TABLE t1,t2,t3;
+
 # this must be the last command in the file
 set @@optimizer_switch=@save_optimizer_switch;
diff --git a/sql/sql_join_cache.cc b/sql/sql_join_cache.cc
index af4b157ba90fa27dab72a6cdf38ddc875ec076f2..2a8db8b4fd1bce12064c052c78d79d08b343ab99 100644
--- a/sql/sql_join_cache.cc
+++ b/sql/sql_join_cache.cc
@@ -2109,16 +2109,6 @@ enum_nested_loop_state JOIN_CACHE::join_records(bool skip_last)
     if (rc != NESTED_LOOP_OK && rc != NESTED_LOOP_NO_MORE_ROWS)
       goto finish;
   }
-  if (outer_join_first_inner)
-  {
-    /* 
-      All null complemented rows have been already generated for all
-      outer records from join buffer. Restore the state of the
-      first_unmatched values to 0 to avoid another null complementing.
-    */
-    for (tab= join_tab->first_inner; tab <= join_tab->last_inner; tab++)
-      tab->first_unmatched= 0;
-  } 
  
   if (skip_last)
   {
@@ -2131,6 +2121,16 @@ enum_nested_loop_state JOIN_CACHE::join_records(bool skip_last)
   }
 
 finish:
+  if (outer_join_first_inner)
+  {
+    /* 
+      All null complemented rows have been already generated for all
+      outer records from join buffer. Restore the state of the
+      first_unmatched values to 0 to avoid another null complementing.
+    */
+    for (tab= join_tab->first_inner; tab <= join_tab->last_inner; tab++)
+      tab->first_unmatched= 0;
+  } 
   restore_last_record();
   reset(TRUE);
   DBUG_PRINT("exit", ("rc: %d", rc));