summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/view.result14
-rw-r--r--mysql-test/t/view.test19
-rw-r--r--sql/sql_base.cc34
3 files changed, 63 insertions, 4 deletions
diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result
index ef40a408932..684c4950acd 100644
--- a/mysql-test/r/view.result
+++ b/mysql-test/r/view.result
@@ -1977,3 +1977,17 @@ A
B
DROP VIEW v1;
DROP TABLE t1;
+CREATE TABLE t1 ( bug_table_seq INTEGER NOT NULL);
+CREATE OR REPLACE VIEW v1 AS SELECT * from t1;
+DROP PROCEDURE IF EXISTS p1;
+Warnings:
+Note 1305 PROCEDURE p1 does not exist
+CREATE PROCEDURE p1 ( )
+BEGIN
+DO (SELECT @next := IFNULL(max(bug_table_seq),0) + 1 FROM v1);
+INSERT INTO t1 VALUES (1);
+END //
+CALL p1();
+DROP PROCEDURE p1;
+DROP VIEW v1;
+DROP TABLE t1;
diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test
index d296d5ebee5..8eeac41efcd 100644
--- a/mysql-test/t/view.test
+++ b/mysql-test/t/view.test
@@ -1804,7 +1804,6 @@ drop table t1;
#
# Test for bug #11771: wrong query_id in SELECT * FROM <view>
#
-
CREATE TABLE t1 (f1 char) ENGINE = innodb;
INSERT INTO t1 VALUES ('A');
CREATE VIEW v1 AS SELECT * FROM t1;
@@ -1815,3 +1814,21 @@ SELECT * FROM t1;
DROP VIEW v1;
DROP TABLE t1;
+
+#
+# opening table in correct locking mode (BUG#9597)
+#
+CREATE TABLE t1 ( bug_table_seq INTEGER NOT NULL);
+CREATE OR REPLACE VIEW v1 AS SELECT * from t1;
+DROP PROCEDURE IF EXISTS p1;
+delimiter //;
+CREATE PROCEDURE p1 ( )
+BEGIN
+ DO (SELECT @next := IFNULL(max(bug_table_seq),0) + 1 FROM v1);
+ INSERT INTO t1 VALUES (1);
+END //
+delimiter ;//
+CALL p1();
+DROP PROCEDURE p1;
+DROP VIEW v1;
+DROP TABLE t1;
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 2ee1c8c24cc..7021f61a052 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -1041,6 +1041,8 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
if (thd->locked_tables || thd->prelocked_mode)
{ // Using table locks
+ TABLE *best_table= 0;
+ int best_distance= INT_MIN, distance;
for (table=thd->open_tables; table ; table=table->next)
{
if (table->s->key_length == key_length &&
@@ -1049,11 +1051,37 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
table->query_id != thd->query_id && /* skip tables already used by this query */
!(thd->prelocked_mode && table->query_id))
{
- table->query_id= thd->query_id;
- DBUG_PRINT("info",("Using locked table"));
- goto reset;
+ distance= ((int) table->reginfo.lock_type -
+ (int) table_list->lock_type);
+ /*
+ Find a table that either has the exact lock type requested,
+ or has the best suitable lock. In case there is no locked
+ table that has an equal or higher lock than requested,
+ we still maitain the best_table to produce an error message
+ about wrong lock mode on the table. The best_table is changed
+ if bd < 0 <= d or bd < d < 0 or 0 <= d < bd.
+
+ distance < 0 - we have not enough high lock mode
+ distance > 0 - we have lock mode higher then we require
+ distance == 0 - we have lock mode exactly which we need
+ */
+ if (best_distance < 0 && distance > best_distance ||
+ distance >= 0 && distance < best_distance)
+ {
+ best_distance= distance;
+ best_table= table;
+ if (best_distance == 0)
+ break;
+ }
}
}
+ if (best_table)
+ {
+ table= best_table;
+ table->query_id= thd->query_id;
+ DBUG_PRINT("info",("Using locked table"));
+ goto reset;
+ }
/*
is it view?
(it is work around to allow to open view with locked tables,