Commit 702ae189 authored by Georgi Kodinov's avatar Georgi Kodinov
Browse files

merged 5.0-main -> 5.0-bugteam

parents 27f4c34b 0b38c93d
Loading
Loading
Loading
Loading
+34 −0
Original line number Diff line number Diff line
@@ -99,3 +99,37 @@ kill query
ERROR 70100: Query execution was interrupted
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;
CREATE TABLE t1( a INT, b INT );
INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3), (4, 4);
# 1. test regular tables
# 1.1. test altering of columns that multiupdate doesn't use
# 1.1.1. normal mode
# 1.1.2. PS mode
# 1.2. test altering of columns that multiupdate uses
# 1.2.1. normal mode
# 1.2.2. PS mode
ALTER TABLE t1 ADD COLUMN a INT;
# 2. test UNIONs
# 2.1. test altering of columns that multiupdate doesn't use
# 2.1.1. normal mode
# 2.1.2. PS mode
# 2.2. test altering of columns that multiupdate uses
# 2.2.1. normal mode
# 2.2.2. PS mode
DROP TABLE t1;
+321 −0
Original line number Diff line number Diff line
@@ -281,4 +281,325 @@ unlock tables;
connection default;
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;

#
# Bug#38499: flush tables and multitable table update with derived table cause 
#            crash
#

CREATE TABLE t1( a INT, b INT );
INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3), (4, 4);

--echo # 1. test regular tables
--echo # 1.1. test altering of columns that multiupdate doesn't use
--echo # 1.1.1. normal mode

--disable_query_log
let $i = 100;
while ($i) {
--dec $i

--connection writer
  send UPDATE t1, (SELECT 1 FROM t1 t1i) d SET a = 0 WHERE 1=0;

--connection locker
  ALTER TABLE t1 ADD COLUMN (c INT);
  ALTER TABLE t1 DROP COLUMN c;

--connection writer
--reap
}

--echo # 1.1.2. PS mode

--connection writer
PREPARE stmt FROM 'UPDATE t1, (SELECT 1 FROM t1 t1i) d SET a = 0 WHERE 1=0';

let $i = 100;
while ($i) {
--dec $i

--connection writer
--send EXECUTE stmt

--connection locker
  ALTER TABLE t1 ADD COLUMN (c INT);
  ALTER TABLE t1 DROP COLUMN c;

--connection writer
--reap
}
--enable_query_log

--echo # 1.2. test altering of columns that multiupdate uses
--echo # 1.2.1. normal mode

--connection default

--disable_query_log
let $i = 100;
while ($i) {
  dec $i;

--connection locker
--error 0,1060
  ALTER TABLE t1 ADD COLUMN a int(11) unsigned default NULL;
  UPDATE t1 SET a=b;

--connection writer
--send UPDATE t1, (SELECT 1 FROM t1 t1i) d SET a = 0 WHERE 1=0;

--connection locker
--error 0,1091
  ALTER TABLE t1 DROP COLUMN a;

--connection writer
--error 0,1054 # unknown column error
--reap
}
--enable_query_log

--echo # 1.2.2. PS mode

--disable_query_log
let $i = 100;
while ($i) {
  dec $i;

--connection locker
--error 0,1060
  ALTER TABLE t1 ADD COLUMN a INT;
  UPDATE t1 SET a=b;

--connection writer
  PREPARE stmt FROM 'UPDATE t1, (SELECT 1 FROM t1 t1i) d SET a = 0 WHERE 1=0';
--send EXECUTE stmt

--connection locker
--error 0,1091
  ALTER TABLE t1 DROP COLUMN a;

--connection writer
--error 0,1054 # Unknown column 'a' in 'field list'
--reap
}
--enable_query_log
--connection default
ALTER TABLE t1 ADD COLUMN a INT;

--echo # 2. test UNIONs
--echo # 2.1. test altering of columns that multiupdate doesn't use
--echo # 2.1.1. normal mode

--disable_query_log
let $i = 100;
while ($i) {
--dec $i

--connection writer
  send UPDATE t1, ((SELECT 1 FROM t1 t1i) UNION (SELECT 2 FROM t1 t1ii)) e SET a = 0 WHERE 1=0;

--connection locker
  ALTER TABLE t1 ADD COLUMN (c INT);
  ALTER TABLE t1 DROP COLUMN c;

--connection writer
--reap
}

--echo # 2.1.2. PS mode

--connection writer
PREPARE stmt FROM 'UPDATE t1, ((SELECT 1 FROM t1 t1i) UNION (SELECT 2 FROM t1 t1ii)) e SET a = 0 WHERE 1=0';

let $i = 100;
while ($i) {
--dec $i

--connection writer
--send EXECUTE stmt

--connection locker
  ALTER TABLE t1 ADD COLUMN (c INT);
  ALTER TABLE t1 DROP COLUMN c;

--connection writer
--reap
}
--enable_query_log

--echo # 2.2. test altering of columns that multiupdate uses
--echo # 2.2.1. normal mode

--connection default

--disable_query_log
let $i = 100;
while ($i) {
  dec $i;

--connection locker
--error 0,1060
  ALTER TABLE t1 ADD COLUMN a int(11) unsigned default NULL;
  UPDATE t1 SET a=b;

--connection writer
--send UPDATE t1, ((SELECT 1 FROM t1 t1i) UNION (SELECT 2 FROM t1 t1ii)) e SET a = 0 WHERE 1=0;

--connection locker
--error 0,1091
  ALTER TABLE t1 DROP COLUMN a;

--connection writer
--error 0,1054 # Unknown column 'a' in 'field list'
--reap
}
--enable_query_log

--echo # 2.2.2. PS mode

--disable_query_log
let $i = 100;
while ($i) {
  dec $i;

--connection locker
--error 0,1060
  ALTER TABLE t1 ADD COLUMN a INT;
  UPDATE t1 SET a=b;

--connection writer
  PREPARE stmt FROM 'UPDATE t1, ((SELECT 1 FROM t1 t1i) UNION (SELECT 2 FROM t1 t1ii)) e SET a = 0 WHERE 1=0';
--send EXECUTE stmt

--connection locker
--error 0,1091
  ALTER TABLE t1 DROP COLUMN a;

--connection writer
--error 0,1054 # Unknown column 'a' in 'field list'
--reap
}
--enable_query_log
--connection default
DROP TABLE t1;

# End of 5.0 tests
+6 −4
Original line number Diff line number Diff line
@@ -1758,13 +1758,15 @@ Item_field::Item_field(THD *thd, Name_resolution_context *context_arg,
    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);
    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
+28 −6
Original line number Diff line number Diff line
@@ -3617,8 +3617,21 @@ find_field_in_natural_join(THD *thd, TABLE_LIST *table_ref, const char *name,
  {
    /* 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);
  }

@@ -4450,7 +4463,7 @@ mark_common_columns(THD *thd, TABLE_LIST *table_ref_1, TABLE_LIST *table_ref_2,
    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 && 
@@ -4471,7 +4484,7 @@ mark_common_columns(THD *thd, TABLE_LIST *table_ref_1, TABLE_LIST *table_ref_2,
    {
      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", 
@@ -4957,15 +4970,24 @@ static bool setup_natural_join_row_types(THD *thd,
  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;
+1 −0
Original line number Diff line number Diff line
@@ -1205,6 +1205,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;
Loading