From 6266493fc33cfcfd3f878c6955b53576277f52ba Mon Sep 17 00:00:00 2001
From: Jimmy Yang <jimmy.yang@oracle.com>
Date: Wed, 20 Sep 2017 01:38:26 +0200
Subject: [PATCH] Bug #25729649 LOCK0LOCK.CC:NNN:ADD_POSITION != __NULL

Reviewed-by: Sunny Bains <sunny.bains@oracle.com>
---
 .../innodb/r/high_prio_trx_predicate.result   | 30 +++++++++
 .../innodb/t/high_prio_trx_predicate.test     | 61 +++++++++++++++++++
 storage/innobase/lock/lock0lock.cc            |  7 ++-
 3 files changed, 96 insertions(+), 2 deletions(-)
 create mode 100644 mysql-test/suite/innodb/r/high_prio_trx_predicate.result
 create mode 100644 mysql-test/suite/innodb/t/high_prio_trx_predicate.test

diff --git a/mysql-test/suite/innodb/r/high_prio_trx_predicate.result b/mysql-test/suite/innodb/r/high_prio_trx_predicate.result
new file mode 100644
index 00000000000..965e1e0f6ad
--- /dev/null
+++ b/mysql-test/suite/innodb/r/high_prio_trx_predicate.result
@@ -0,0 +1,30 @@
+CREATE TABLE tab(c1 int NOT NULL PRIMARY KEY,c2 POINT NOT NULL);
+CREATE SPATIAL INDEX idx1 on tab(c2);
+INSERT INTO tab(c1,c2) VALUES(1,ST_GeomFromText('POINT(10 10)'));
+
+# On connection 1
+set transaction isolation level serializable ;
+START TRANSACTION;
+SELECT ST_AsText(c2) FROM tab WHERE MBRWithin(c2, ST_GeomFromText('POLYGON((5 5, 15 5, 15 15, 5 15, 5 5))'));
+ST_AsText(c2)
+POINT(10 10)
+
+# On connection 2
+start transaction;
+INSERT INTO tab(c1,c2) VALUES(7, ST_GeomFromText('POINT(11 11)'));;
+
+# On connection 3
+include/start_transaction_high_prio.inc
+START TRANSACTION /* HIGH PRIORITY */;
+INSERT INTO tab(c1,c2) VALUES(8, ST_GeomFromText('POINT(10 10)'));
+COMMIT;
+
+# On connection 1
+COMMIT;
+ERROR HY000: Got error 149 during COMMIT
+include/assert.inc ['There is a 8 in tab']
+SELECT c1 FROM tab;
+c1
+1
+8
+DROP TABLE tab;
diff --git a/mysql-test/suite/innodb/t/high_prio_trx_predicate.test b/mysql-test/suite/innodb/t/high_prio_trx_predicate.test
new file mode 100644
index 00000000000..6503e90653b
--- /dev/null
+++ b/mysql-test/suite/innodb/t/high_prio_trx_predicate.test
@@ -0,0 +1,61 @@
+# Scenario:
+#  T1=({R(B)})
+#  T2=({W(B)})
+#  T3=({W(B), C}, HIGH_PRIORITY).
+#
+# Outcome: T1 must abort, T2 must commit.
+
+--source include/count_sessions.inc
+
+CREATE TABLE tab(c1 int NOT NULL PRIMARY KEY,c2 POINT NOT NULL);
+CREATE SPATIAL INDEX idx1 on tab(c2);
+INSERT INTO tab(c1,c2) VALUES(1,ST_GeomFromText('POINT(10 10)'));
+
+--connect(con1,localhost,root,,test)
+--connect(con2,localhost,root,,test)
+--connect(con3,localhost,root,,test)
+
+--echo
+--echo # On connection 1
+--connection con1
+set transaction isolation level serializable ;
+START TRANSACTION;
+SELECT ST_AsText(c2) FROM tab WHERE MBRWithin(c2, ST_GeomFromText('POLYGON((5 5, 15 5, 15 15, 5 15, 5 5))'));
+
+
+--echo
+--echo # On connection 2
+--connection con2
+start transaction;
+--send INSERT INTO tab(c1,c2) VALUES(7, ST_GeomFromText('POINT(11 11)'));
+
+--echo
+--echo # On connection 3
+--connection con3
+--source include/start_transaction_high_prio.inc
+INSERT INTO tab(c1,c2) VALUES(8, ST_GeomFromText('POINT(10 10)'));
+COMMIT;
+--disconnect con3
+
+--echo
+--echo # On connection 1
+--connection con1
+--error ER_ERROR_DURING_COMMIT
+COMMIT;
+--disconnect con1
+
+--connection default
+--let $assert_text= 'There is a 8 in tab'
+--let $assert_cond= [SELECT COUNT(*) AS count FROM tab WHERE tab.c1 = 8, count, 1] = 1
+--source include/assert.inc
+
+--connection con2
+--reap;
+--disconnect con2
+
+--connection default
+SELECT c1 FROM tab;
+
+DROP TABLE tab;
+
+--source include/wait_until_count_sessions.inc
diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc
index f25ac596d5f..cde267aa638 100644
--- a/storage/innobase/lock/lock0lock.cc
+++ b/storage/innobase/lock/lock0lock.cc
@@ -1,6 +1,6 @@
 /*****************************************************************************
 
-Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved.
 Copyright (c) 2014, 2017, MariaDB Corporation.
 
 This program is free software; you can redistribute it and/or modify it under
@@ -2728,7 +2728,10 @@ RecLock::lock_add_priority(
 	lock_t*	grant_position = NULL;
 	lock_t*	add_position = NULL;
 
-	HASH_SEARCH(hash, lock_sys->rec_hash, m_rec_id.fold(), lock_t*,
+	/* Different lock (such as predicate lock) are on different hash */
+	hash_table_t*	lock_hash = lock_hash_get(m_mode);
+
+	HASH_SEARCH(hash, lock_hash, m_rec_id.fold(), lock_t*,
 		    lock_head, ut_ad(lock_head->is_record_lock()), true);
 
 	ut_ad(lock_head);