#At file:///home/kgeorge/mysql/bzr/merge-6.0-bugteam/
2858 Georgi Kodinov 2008-10-08 [merge]
merged 6.0-5.1.29-rc -> 6.0-bugteam
modified:
mysql-test/r/lock_multi.result
mysql-test/suite/parts/inc/partition_auto_increment.inc
mysql-test/suite/parts/r/partition_auto_increment_archive.result
mysql-test/suite/parts/r/partition_auto_increment_blackhole.result
mysql-test/t/lock_multi.test
sql/item.cc
sql/sp_head.cc
sql/sql_base.cc
sql/sql_lex.cc
sql/sql_lex.h
sql/sql_update.cc
sql/table.cc
sql/table.h
=== modified file 'mysql-test/r/lock_multi.result'
--- a/mysql-test/r/lock_multi.result 2008-02-19 14:09:52 +0000
+++ b/mysql-test/r/lock_multi.result 2008-10-07 22:05:23 +0000
@@ -97,6 +97,22 @@ alter table t1 auto_increment=0;
alter table t1 auto_increment=0;
unlock tables;
drop table t1;
+CREATE TABLE t1 (
+a int(11) unsigned default NULL,
+b varchar(255) default NULL,
+UNIQUE KEY a (a),
+KEY b (b)
+);
+INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3);
+CREATE TABLE t2 SELECT * FROM t1;
+CREATE TABLE t3 SELECT * FROM t1;
+# test altering of columns that multiupdate doesn't use
+# normal mode
+# PS mode
+# test altering of columns that multiupdate uses
+# normal mode
+# PS mode
+DROP TABLE t1, t2, t3;
End of 5.0 tests
create table t1 (i int);
lock table t1 read;
=== modified file 'mysql-test/suite/parts/inc/partition_auto_increment.inc'
--- a/mysql-test/suite/parts/inc/partition_auto_increment.inc 2008-10-03 12:35:01 +0000
+++ b/mysql-test/suite/parts/inc/partition_auto_increment.inc 2008-10-08 08:59:25 +0000
@@ -33,11 +33,11 @@ if (!$mysql_errno)
}
INSERT INTO t1 VALUES (17);
INSERT INTO t1 VALUES (19), (NULL);
--- error 0, ER_DUP_KEY
+-- error 0, ER_DUP_ENTRY, ER_DUP_KEY
INSERT INTO t1 VALUES (NULL), (10), (NULL);
if ($mysql_errno)
{
- echo # ERROR (only OK if Archive) mysql_errno: $mysql_errno;
+ echo # ERROR (only OK if Archive);
}
INSERT INTO t1 VALUES (NULL);
SET INSERT_ID = 30;
@@ -118,11 +118,11 @@ if (!$mysql_errno)
INSERT INTO t1 VALUES (1, NULL);
let $old_sql_mode = `select @@session.sql_mode`;
SET @@session.sql_mode = 'NO_AUTO_VALUE_ON_ZERO';
--- error 0, ER_DUP_KEY
+-- error 0, ER_DUP_ENTRY, ER_DUP_KEY
INSERT INTO t1 VALUES (1, 0);
if ($mysql_errno)
{
- echo # ERROR (only OK if Archive) mysql_errno: $mysql_errno;
+ echo # ERROR (only OK if Archive);
}
SELECT * FROM t1 ORDER BY c1, c2;
DROP TABLE t1;
@@ -133,11 +133,11 @@ eval CREATE TABLE t1 (
ENGINE=$engine
PARTITION BY HASH(c2)
PARTITIONS 2;
--- error 0, ER_DUP_KEY
+-- error 0, ER_DUP_ENTRY, ER_DUP_KEY
INSERT INTO t1 VALUES (1, 0);
if ($mysql_errno)
{
- echo # ERROR (only OK if Archive) mysql_errno: $mysql_errno;
+ echo # ERROR (only OK if Archive);
}
INSERT INTO t1 VALUES (1, 1), (1, NULL);
INSERT INTO t1 VALUES (2, NULL), (4, 7);
@@ -164,23 +164,23 @@ if (!$mysql_errno)
echo # mysql_errno: $mysql_errno;
}
INSERT INTO t1 VALUES (17), (19), (NULL);
--- error 0, ER_DUP_KEY
+-- error 0, ER_DUP_ENTRY, ER_DUP_KEY
INSERT INTO t1 VALUES (NULL), (10), (NULL);
if ($mysql_errno)
{
- echo # ERROR (only OK if Archive) mysql_errno: $mysql_errno;
+ echo # ERROR (only OK if Archive);
}
--- error 0, ER_DUP_KEY
+-- error 0, ER_DUP_ENTRY, ER_DUP_KEY
INSERT INTO t1 VALUES (NULL), (9);
if ($mysql_errno)
{
- echo # ERROR (only OK if Archive) mysql_errno: $mysql_errno;
+ echo # ERROR (only OK if Archive);
}
--- error 0, ER_DUP_KEY
+-- error 0, ER_DUP_ENTRY, ER_DUP_KEY
INSERT INTO t1 VALUES (59), (55);
if ($mysql_errno)
{
- echo # ERROR (only OK if Archive) mysql_errno: $mysql_errno;
+ echo # ERROR (only OK if Archive);
}
INSERT INTO t1 VALUES (NULL), (90);
INSERT INTO t1 VALUES (NULL);
@@ -266,22 +266,22 @@ SELECT AUTO_INCREMENT FROM INFORMATION_S
AND TABLE_NAME='t1';
SELECT AUTO_INCREMENT FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='test'
AND TABLE_NAME='t1';
--- error 0, ER_DUP_KEY
+-- error 0, ER_DUP_ENTRY, ER_DUP_KEY
INSERT INTO t1 VALUES (10);
if ($mysql_errno)
{
- echo # ERROR (only OK if Archive) mysql_errno: $mysql_errno;
+ echo # ERROR (only OK if Archive);
}
SELECT * FROM t1 ORDER BY c1;
INSERT INTO t1 VALUES (NULL);
SELECT AUTO_INCREMENT FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='test'
AND TABLE_NAME='t1';
INSERT INTO t1 VALUES (NULL);
--- error 0, ER_DUP_KEY
+-- error 0, ER_DUP_ENTRY, ER_DUP_KEY
INSERT INTO t1 VALUES (15);
if ($mysql_errno)
{
- echo # ERROR (only OK if Archive) mysql_errno: $mysql_errno;
+ echo # ERROR (only OK if Archive);
}
INSERT INTO t1 VALUES (NULL);
SELECT * FROM t1 ORDER BY c1;
@@ -327,11 +327,11 @@ connection con1;
INSERT INTO t1 (c1) VALUES (NULL);
connection default;
-- echo # con default
--- error 0, ER_DUP_KEY
+-- error 0, ER_DUP_ENTRY, ER_DUP_KEY
INSERT INTO t1 (c1) VALUES (16);
if ($mysql_errno)
{
- echo # ERROR (only OK if Archive) mysql_errno: $mysql_errno;
+ echo # ERROR (only OK if Archive);
}
-- echo # con1
connection con1;
@@ -368,11 +368,11 @@ connection con1;
INSERT INTO t1 (c1) VALUES (NULL);
connection default;
-- echo # con default
--- error 0, ER_DUP_KEY
+-- error 0, ER_DUP_KEY, ER_DUP_KEY
INSERT INTO t1 (c1) VALUES (16);
if ($mysql_errno)
{
- echo # ERROR (only OK if Archive) mysql_errno: $mysql_errno;
+ echo # ERROR (only OK if Archive);
}
-- echo # con1
connection con1;
@@ -413,11 +413,11 @@ connection con1;
INSERT INTO t1 (c1) VALUES (NULL);
connection default;
-- echo # con default
--- error 0, ER_DUP_KEY
+-- error 0, ER_DUP_ENTRY, ER_DUP_KEY
INSERT INTO t1 (c1) VALUES (16);
if ($mysql_errno)
{
- echo # ERROR (only OK if Archive) mysql_errno: $mysql_errno;
+ echo # ERROR (only OK if Archive);
}
-- echo # con1
connection con1;
@@ -522,11 +522,11 @@ INSERT INTO t1 VALUES (1, NULL);
INSERT INTO t1 VALUES (2, NULL);
INSERT INTO t1 VALUES (3, NULL);
INSERT INTO t1 VALUES (3, NULL), (2, 0), (2, NULL);
--- error 0, ER_DUP_ENTRY
+-- error 0, ER_DUP_ENTRY, ER_DUP_KEY
INSERT INTO t1 VALUES (2, 2);
if (!$mysql_errno)
{
- echo # ERROR (only OK if Blackhole/NDB) should give ER_DUP_ENTRY;
+ echo # ERROR (only OK if Blackhole/NDB) should give ER_DUP_KEY or ER_DUP_ENTRY;
echo # mysql_errno: $mysql_errno;
}
INSERT INTO t1 VALUES (2, 22), (2, NULL);
@@ -541,11 +541,11 @@ eval CREATE TABLE t1 (c1 INT NOT NULL AU
PARTITION BY HASH(c1)
PARTITIONS 2;
SHOW CREATE TABLE t1;
--- error 0, ER_DUP_KEY
+-- error 0, ER_DUP_ENTRY, ER_DUP_KEY
INSERT INTO t1 (c1) VALUES (4);
if ($mysql_errno)
{
- echo # ERROR (only OK if Archive) mysql_errno: $mysql_errno;
+ echo # ERROR (only OK if Archive);
}
SHOW CREATE TABLE t1;
INSERT INTO t1 (c1) VALUES (0);
@@ -559,11 +559,11 @@ let $old_sql_mode = `select @@session.sq
SET @@session.sql_mode = 'NO_AUTO_VALUE_ON_ZERO';
INSERT INTO t1 (c1) VALUES (300);
SHOW CREATE TABLE t1;
--- error 0, ER_DUP_KEY
+-- error 0, ER_DUP_ENTRY, ER_DUP_KEY
INSERT INTO t1 (c1) VALUES (0);
if ($mysql_errno)
{
- echo # ERROR (only OK if Archive) mysql_errno: $mysql_errno;
+ echo # ERROR (only OK if Archive);
}
SHOW CREATE TABLE t1;
INSERT INTO t1 (c1) VALUES (NULL);
=== modified file 'mysql-test/suite/parts/r/partition_auto_increment_archive.result'
--- a/mysql-test/suite/parts/r/partition_auto_increment_archive.result 2008-09-08 13:30:01 +0000
+++ b/mysql-test/suite/parts/r/partition_auto_increment_archive.result 2008-10-08 08:59:25 +0000
@@ -30,7 +30,7 @@ INSERT INTO t1 VALUES (5), (16);
INSERT INTO t1 VALUES (17);
INSERT INTO t1 VALUES (19), (NULL);
INSERT INTO t1 VALUES (NULL), (10), (NULL);
-# ERROR (only OK if Archive) mysql_errno: 1022
+# ERROR (only OK if Archive)
INSERT INTO t1 VALUES (NULL);
SET INSERT_ID = 30;
INSERT INTO t1 VALUES (NULL);
@@ -137,7 +137,7 @@ INSERT INTO t1 VALUES (1, 1), (99, 99);
INSERT INTO t1 VALUES (1, NULL);
SET @@session.sql_mode = 'NO_AUTO_VALUE_ON_ZERO';
INSERT INTO t1 VALUES (1, 0);
-# ERROR (only OK if Archive) mysql_errno: 1022
+# ERROR (only OK if Archive)
SELECT * FROM t1 ORDER BY c1, c2;
c1 c2
1 1
@@ -151,7 +151,7 @@ ENGINE='Archive'
PARTITION BY HASH(c2)
PARTITIONS 2;
INSERT INTO t1 VALUES (1, 0);
-# ERROR (only OK if Archive) mysql_errno: 1022
+# ERROR (only OK if Archive)
INSERT INTO t1 VALUES (1, 1), (1, NULL);
INSERT INTO t1 VALUES (2, NULL), (4, 7);
INSERT INTO t1 VALUES (1, NULL);
@@ -176,11 +176,11 @@ INSERT INTO t1 VALUES (0);
INSERT INTO t1 VALUES (5), (16);
INSERT INTO t1 VALUES (17), (19), (NULL);
INSERT INTO t1 VALUES (NULL), (10), (NULL);
-# ERROR (only OK if Archive) mysql_errno: 1022
+# ERROR (only OK if Archive)
INSERT INTO t1 VALUES (NULL), (9);
-# ERROR (only OK if Archive) mysql_errno: 1022
+# ERROR (only OK if Archive)
INSERT INTO t1 VALUES (59), (55);
-# ERROR (only OK if Archive) mysql_errno: 1022
+# ERROR (only OK if Archive)
INSERT INTO t1 VALUES (NULL), (90);
INSERT INTO t1 VALUES (NULL);
SELECT * FROM t1 ORDER BY c1;
@@ -283,7 +283,7 @@ AND TABLE_NAME='t1';
AUTO_INCREMENT
22
INSERT INTO t1 VALUES (10);
-# ERROR (only OK if Archive) mysql_errno: 1022
+# ERROR (only OK if Archive)
SELECT * FROM t1 ORDER BY c1;
c1
2
@@ -301,7 +301,7 @@ AUTO_INCREMENT
23
INSERT INTO t1 VALUES (NULL);
INSERT INTO t1 VALUES (15);
-# ERROR (only OK if Archive) mysql_errno: 1022
+# ERROR (only OK if Archive)
INSERT INTO t1 VALUES (NULL);
SELECT * FROM t1 ORDER BY c1;
c1
@@ -383,7 +383,7 @@ INSERT INTO t1 (c1) VALUES (21);
INSERT INTO t1 (c1) VALUES (NULL);
# con default
INSERT INTO t1 (c1) VALUES (16);
-# ERROR (only OK if Archive) mysql_errno: 1022
+# ERROR (only OK if Archive)
# con1
INSERT INTO t1 (c1) VALUES (NULL);
# con default
@@ -422,7 +422,7 @@ INSERT INTO t1 (c1) VALUES (21);
INSERT INTO t1 (c1) VALUES (NULL);
# con default
INSERT INTO t1 (c1) VALUES (16);
-# ERROR (only OK if Archive) mysql_errno: 1022
+# ERROR (only OK if Archive)
# con1
INSERT INTO t1 (c1) VALUES (NULL);
SELECT * FROM t1 ORDER BY c1;
@@ -499,7 +499,7 @@ INSERT INTO t1 (c1) VALUES (21);
INSERT INTO t1 (c1) VALUES (NULL);
# con default
INSERT INTO t1 (c1) VALUES (16);
-# ERROR (only OK if Archive) mysql_errno: 1022
+# ERROR (only OK if Archive)
# con1
INSERT INTO t1 (c1) VALUES (NULL);
SELECT * FROM t1 ORDER BY c1;
@@ -607,7 +607,7 @@ t1 CREATE TABLE `t1` (
PRIMARY KEY (`c1`)
) ENGINE=ARCHIVE AUTO_INCREMENT=15 DEFAULT CHARSET=latin1 /*!50100 PARTITION BY HASH (c1) PARTITIONS 2 */
INSERT INTO t1 (c1) VALUES (4);
-# ERROR (only OK if Archive) mysql_errno: 1022
+# ERROR (only OK if Archive)
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
@@ -642,7 +642,7 @@ t1 CREATE TABLE `t1` (
PRIMARY KEY (`c1`)
) ENGINE=ARCHIVE AUTO_INCREMENT=301 DEFAULT CHARSET=latin1 /*!50100 PARTITION BY HASH (c1) PARTITIONS 2 */
INSERT INTO t1 (c1) VALUES (0);
-# ERROR (only OK if Archive) mysql_errno: 1022
+# ERROR (only OK if Archive)
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
=== modified file 'mysql-test/suite/parts/r/partition_auto_increment_blackhole.result'
--- a/mysql-test/suite/parts/r/partition_auto_increment_blackhole.result 2008-10-03 12:35:01 +0000
+++ b/mysql-test/suite/parts/r/partition_auto_increment_blackhole.result 2008-10-08 08:59:25 +0000
@@ -433,7 +433,7 @@ INSERT INTO t1 VALUES (2, NULL);
INSERT INTO t1 VALUES (3, NULL);
INSERT INTO t1 VALUES (3, NULL), (2, 0), (2, NULL);
INSERT INTO t1 VALUES (2, 2);
-# ERROR (only OK if Blackhole/NDB) should give ER_DUP_ENTRY
+# ERROR (only OK if Blackhole/NDB) should give ER_DUP_KEY or ER_DUP_ENTRY
# mysql_errno: 0
INSERT INTO t1 VALUES (2, 22), (2, NULL);
SELECT * FROM t1 ORDER BY c1,c2;
=== modified file 'mysql-test/t/lock_multi.test'
--- a/mysql-test/t/lock_multi.test 2008-05-23 13:54:03 +0000
+++ b/mysql-test/t/lock_multi.test 2008-10-07 22:05:23 +0000
@@ -292,6 +292,126 @@ connection reader;
reap;
connection locker;
drop table t1;
+
+#
+# Bug #38691: segfault/abort in ``UPDATE ...JOIN'' while
+# ``FLUSH TABLES WITH READ LOCK''
+#
+
+--connection default
+CREATE TABLE t1 (
+ a int(11) unsigned default NULL,
+ b varchar(255) default NULL,
+ UNIQUE KEY a (a),
+ KEY b (b)
+);
+
+INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3);
+CREATE TABLE t2 SELECT * FROM t1;
+CREATE TABLE t3 SELECT * FROM t1;
+
+--echo # test altering of columns that multiupdate doesn't use
+
+--echo # normal mode
+
+--disable_query_log
+let $i = 100;
+while ($i) {
+--dec $i
+
+--connection writer
+ send UPDATE t2 INNER JOIN (t1 JOIN t3 USING(a)) USING(a)
+ SET a = NULL WHERE t1.b <> t2.b;
+
+--connection locker
+ ALTER TABLE t2 ADD COLUMN (c INT);
+ ALTER TABLE t2 DROP COLUMN c;
+
+--connection writer
+--reap
+}
+
+--echo # PS mode
+
+--connection writer
+PREPARE stmt FROM 'UPDATE t2 INNER JOIN (t1 JOIN t3 USING(a)) USING(a)
+ SET a = NULL WHERE t1.b <> t2.b';
+
+let $i = 100;
+while ($i) {
+--dec $i
+
+--connection writer
+--send EXECUTE stmt
+
+--connection locker
+ ALTER TABLE t2 ADD COLUMN (c INT);
+ ALTER TABLE t2 DROP COLUMN c;
+
+--connection writer
+--reap
+}
+--enable_query_log
+
+
+--echo # test altering of columns that multiupdate uses
+
+--echo # normal mode
+
+--connection default
+
+--disable_query_log
+let $i = 100;
+while ($i) {
+ dec $i;
+
+--connection locker
+--error 0,1060
+ ALTER TABLE t2 ADD COLUMN a int(11) unsigned default NULL;
+ UPDATE t2 SET a=b;
+
+--connection writer
+--send UPDATE t2 INNER JOIN (t1 JOIN t3 USING(a)) USING(a) SET a = NULL WHERE t1.b <> t2.b
+
+--connection locker
+--error 0,1091
+ ALTER TABLE t2 DROP COLUMN a;
+
+--connection writer
+--error 0,1054
+--reap
+}
+--enable_query_log
+
+--echo # PS mode
+
+--disable_query_log
+let $i = 100;
+while ($i) {
+ dec $i;
+
+--connection locker
+--error 0,1060
+ ALTER TABLE t2 ADD COLUMN a int(11) unsigned default NULL;
+ UPDATE t2 SET a=b;
+
+--connection writer
+ PREPARE stmt FROM 'UPDATE t2 INNER JOIN (t1 JOIN t3 USING(a)) USING(a) SET a = NULL WHERE t1.b <> t2.b';
+--send EXECUTE stmt
+
+--connection locker
+--error 0,1091
+ ALTER TABLE t2 DROP COLUMN a;
+
+--connection writer
+--error 0,1054
+--reap
+
+}
+--enable_query_log
+--connection default
+DROP TABLE t1, t2, t3;
+
#
--echo End of 5.0 tests
=== modified file 'sql/item.cc'
--- a/sql/item.cc 2008-10-03 09:55:06 +0000
+++ b/sql/item.cc 2008-10-07 22:05:23 +0000
@@ -1801,14 +1801,16 @@ Item_field::Item_field(THD *thd, Name_re
We need to copy db_name, table_name and field_name because they must
be allocated in the statement memory, not in table memory (the table
structure can go away and pop up again between subsequent executions
- of a prepared statement).
+ of a prepared statement or after the close_tables_for_reopen() call
+ in mysql_multi_update_prepare()).
*/
- if (thd->stmt_arena->is_stmt_prepare_or_first_sp_execute())
{
if (db_name)
orig_db_name= thd->strdup(db_name);
- orig_table_name= thd->strdup(table_name);
- orig_field_name= thd->strdup(field_name);
+ if (table_name)
+ orig_table_name= thd->strdup(table_name);
+ if (field_name)
+ orig_field_name= thd->strdup(field_name);
/*
We don't restore 'name' in cleanup because it's not changed
during execution. Still we need it to point to persistent
=== modified file 'sql/sp_head.cc'
--- a/sql/sp_head.cc 2008-10-07 15:40:12 +0000
+++ b/sql/sp_head.cc 2008-10-08 09:23:13 +0000
@@ -1944,8 +1944,7 @@ sp_head::execute_procedure(THD *thd, Lis
thd->rollback_item_tree_changes();
}
- DBUG_PRINT("info",(" %.*s: eval args done",
- (int) m_name.length, m_name.str));
+ DBUG_PRINT("info",(" %.*s: eval args done", m_name.length, m_name.str));
}
if (!(m_flags & LOG_SLOW_STATEMENTS) && thd->enable_slow_log)
{
=== modified file 'sql/sql_base.cc'
--- a/sql/sql_base.cc 2008-10-03 12:44:52 +0000
+++ b/sql/sql_base.cc 2008-10-08 09:23:13 +0000
@@ -4947,8 +4947,21 @@ find_field_in_natural_join(THD *thd, TAB
{
/* This is a base table. */
DBUG_ASSERT(nj_col->view_field == NULL);
- DBUG_ASSERT(nj_col->table_ref->table == nj_col->table_field->table);
- found_field= nj_col->table_field;
+ /*
+ This fix_fields is not necessary (initially this item is fixed by
+ the Item_field constructor; after reopen_tables the Item_func_eq
+ calls fix_fields on that item), it's just a check during table
+ reopening for columns that was dropped by the concurrent connection.
+ */
+ if (!nj_col->table_field->fixed &&
+ nj_col->table_field->fix_fields(thd, (Item **)&nj_col->table_field))
+ {
+ DBUG_PRINT("info", ("column '%s' was dropped by the concurrent connection",
+ nj_col->table_field->name));
+ DBUG_RETURN(NULL);
+ }
+ DBUG_ASSERT(nj_col->table_ref->table == nj_col->table_field->field->table);
+ found_field= nj_col->table_field->field;
update_field_dependencies(thd, found_field, nj_col->table_ref->table);
}
@@ -5873,7 +5886,7 @@ mark_common_columns(THD *thd, TABLE_LIST
const char *field_name_1;
/* true if field_name_1 is a member of using_fields */
bool is_using_column_1;
- if (!(nj_col_1= it_1.get_or_create_column_ref(leaf_1)))
+ if (!(nj_col_1= it_1.get_or_create_column_ref(thd, leaf_1)))
goto err;
field_name_1= nj_col_1->name();
is_using_column_1= using_fields &&
@@ -5894,7 +5907,7 @@ mark_common_columns(THD *thd, TABLE_LIST
{
Natural_join_column *cur_nj_col_2;
const char *cur_field_name_2;
- if (!(cur_nj_col_2= it_2.get_or_create_column_ref(leaf_2)))
+ if (!(cur_nj_col_2= it_2.get_or_create_column_ref(thd, leaf_2)))
goto err;
cur_field_name_2= cur_nj_col_2->name();
DBUG_PRINT ("info", ("cur_field_name_2=%s.%s",
@@ -6384,15 +6397,24 @@ static bool setup_natural_join_row_types
TABLE_LIST *left_neighbor;
/* Table reference to the right of the current. */
TABLE_LIST *right_neighbor= NULL;
+ bool save_first_natural_join_processing=
+ context->select_lex->first_natural_join_processing;
+
+ context->select_lex->first_natural_join_processing= FALSE;
/* Note that tables in the list are in reversed order */
for (left_neighbor= table_ref_it++; left_neighbor ; )
{
table_ref= left_neighbor;
left_neighbor= table_ref_it++;
- /* For stored procedures do not redo work if already done. */
- if (context->select_lex->first_execution)
+ /*
+ Do not redo work if already done:
+ 1) for stored procedures,
+ 2) for multitable update after lock failure and table reopening.
+ */
+ if (save_first_natural_join_processing)
{
+ context->select_lex->first_natural_join_processing= FALSE;
if (store_top_level_join_columns(thd, table_ref,
left_neighbor, right_neighbor))
return TRUE;
=== modified file 'sql/sql_lex.cc'
--- a/sql/sql_lex.cc 2008-10-01 12:02:28 +0000
+++ b/sql/sql_lex.cc 2008-10-07 22:05:23 +0000
@@ -1618,6 +1618,7 @@ void st_select_lex::init_query()
subquery_in_having= explicit_limit= 0;
is_item_list_lookup= 0;
first_execution= 1;
+ first_natural_join_processing= 1;
first_cond_optimization= 1;
parsing_place= NO_MATTER;
exclude_from_table_unique_test= no_wrap_view_item= FALSE;
=== modified file 'sql/sql_lex.h'
--- a/sql/sql_lex.h 2008-10-01 12:02:28 +0000
+++ b/sql/sql_lex.h 2008-10-07 22:05:23 +0000
@@ -678,6 +678,7 @@ public:
case of an error during prepare the PS is not created.
*/
bool first_execution;
+ bool first_natural_join_processing;
bool first_cond_optimization;
/* do not wrap view fields with Item_ref */
bool no_wrap_view_item;
=== modified file 'sql/sql_update.cc'
--- a/sql/sql_update.cc 2008-09-29 18:20:59 +0000
+++ b/sql/sql_update.cc 2008-10-07 22:05:23 +0000
@@ -1083,11 +1083,14 @@ reopen_tables:
}
/* now lock and fill tables */
- if (lock_tables(thd, table_list, table_count, 0, &need_reopen))
+ if (!thd->stmt_arena->is_stmt_prepare() &&
+ lock_tables(thd, table_list, table_count, 0, &need_reopen))
{
if (!need_reopen)
DBUG_RETURN(TRUE);
+ DBUG_PRINT("info", ("lock_tables failed, reopening"));
+
/*
We have to reopen tables since some of them were altered or dropped
during lock_tables() or something was done with their triggers.
@@ -1103,6 +1106,14 @@ reopen_tables:
for (TABLE_LIST *tbl= table_list; tbl; tbl= tbl->next_global)
tbl->cleanup_items();
+ /*
+ Also we need to cleanup Natural_join_column::table_field items.
+ To not to traverse a join tree we will cleanup whole
+ thd->free_list (in PS execution mode that list may not contain
+ items from 'fields' list, so the cleanup above is necessary to.
+ */
+ cleanup_items(thd->free_list);
+
close_tables_for_reopen(thd, &table_list, FALSE);
goto reopen_tables;
}
=== modified file 'sql/table.cc'
--- a/sql/table.cc 2008-10-01 12:02:28 +0000
+++ b/sql/table.cc 2008-10-07 22:05:23 +0000
@@ -3528,7 +3528,7 @@ TABLE_LIST *TABLE_LIST::find_underlying_
}
/*
- cleunup items belonged to view fields translation table
+ cleanup items belonged to view fields translation table
SYNOPSIS
TABLE_LIST::cleanup_items()
@@ -3974,10 +3974,10 @@ Natural_join_column::Natural_join_column
}
-Natural_join_column::Natural_join_column(Field *field_param,
+Natural_join_column::Natural_join_column(Item_field *field_param,
TABLE_LIST *tab)
{
- DBUG_ASSERT(tab->table == field_param->table);
+ DBUG_ASSERT(tab->table == field_param->field->table);
table_field= field_param;
view_field= NULL;
table_ref= tab;
@@ -4005,7 +4005,7 @@ Item *Natural_join_column::create_item(T
return create_view_field(thd, table_ref, &view_field->item,
view_field->name);
}
- return new Item_field(thd, &thd->lex->current_select->context, table_field);
+ return table_field;
}
@@ -4016,7 +4016,7 @@ Field *Natural_join_column::field()
DBUG_ASSERT(table_field == NULL);
return NULL;
}
- return table_field;
+ return table_field->field;
}
@@ -4148,7 +4148,7 @@ void Field_iterator_natural_join::next()
cur_column_ref= column_ref_it++;
DBUG_ASSERT(!cur_column_ref || ! cur_column_ref->table_field ||
cur_column_ref->table_ref->table ==
- cur_column_ref->table_field->table);
+ cur_column_ref->table_field->field->table);
}
@@ -4312,7 +4312,7 @@ GRANT_INFO *Field_iterator_table_ref::gr
*/
Natural_join_column *
-Field_iterator_table_ref::get_or_create_column_ref(TABLE_LIST *parent_table_ref)
+Field_iterator_table_ref::get_or_create_column_ref(THD *thd, TABLE_LIST *parent_table_ref)
{
Natural_join_column *nj_col;
bool is_created= TRUE;
@@ -4325,7 +4325,11 @@ Field_iterator_table_ref::get_or_create_
{
/* The field belongs to a stored table. */
Field *tmp_field= table_field_it.field();
- nj_col= new Natural_join_column(tmp_field, table_ref);
+ Item_field *tmp_item=
+ new Item_field(thd, &thd->lex->current_select->context, tmp_field);
+ if (!tmp_item)
+ return NULL;
+ nj_col= new Natural_join_column(tmp_item, table_ref);
field_count= table_ref->table->s->fields;
}
else if (field_it == &view_field_it)
@@ -4349,7 +4353,7 @@ Field_iterator_table_ref::get_or_create_
DBUG_ASSERT(nj_col);
}
DBUG_ASSERT(!nj_col->table_field ||
- nj_col->table_ref->table == nj_col->table_field->table);
+ nj_col->table_ref->table == nj_col->table_field->field->table);
/*
If the natural join column was just created add it to the list of
@@ -4414,7 +4418,7 @@ Field_iterator_table_ref::get_natural_co
nj_col= natural_join_it.column_ref();
DBUG_ASSERT(nj_col &&
(!nj_col->table_field ||
- nj_col->table_ref->table == nj_col->table_field->table));
+ nj_col->table_ref->table == nj_col->table_field->field->table));
return nj_col;
}
=== modified file 'sql/table.h'
--- a/sql/table.h 2008-10-01 14:47:29 +0000
+++ b/sql/table.h 2008-10-07 22:05:23 +0000
@@ -20,6 +20,7 @@
class Item; /* Needed by ORDER */
class Item_subselect;
+class Item_field;
class GRANT_TABLE;
class st_select_lex_unit;
class st_select_lex;
@@ -981,7 +982,7 @@ class Natural_join_column: public Sql_al
{
public:
Field_translator *view_field; /* Column reference of merge view. */
- Field *table_field; /* Column reference of table or temp view. */
+ Item_field *table_field; /* Column reference of table or temp view. */
TABLE_LIST *table_ref; /* Original base table/view reference. */
/*
True if a common join column of two NATURAL/USING join operands. Notice
@@ -993,7 +994,7 @@ public:
bool is_common;
public:
Natural_join_column(Field_translator *field_param, TABLE_LIST *tab);
- Natural_join_column(Field *field_param, TABLE_LIST *tab);
+ Natural_join_column(Item_field *field_param, TABLE_LIST *tab);
const char *name();
Item *create_item(THD *thd);
Field *field();
@@ -1620,7 +1621,7 @@ public:
GRANT_INFO *grant();
Item *create_item(THD *thd) { return field_it->create_item(thd); }
Field *field() { return field_it->field(); }
- Natural_join_column *get_or_create_column_ref(TABLE_LIST *parent_table_ref);
+ Natural_join_column *get_or_create_column_ref(THD *thd, TABLE_LIST *parent_table_ref);
Natural_join_column *get_natural_column_ref();
};
| Thread |
|---|
| • bzr commit into mysql-6.0 branch (kgeorge:2858) | Georgi Kodinov | 8 Oct |