From 77c4a2ca606500fdd80c0938650a8b4b2f31b99b Mon Sep 17 00:00:00 2001 From: "mats@mysql.com" <> Date: Wed, 3 May 2006 15:00:38 +0200 Subject: [PATCH 01/27] WL#3259 (RBR with more columns on slave than on master): Extended replication to allow extra columns added last on slave as compared with table on master. --- .../extra/rpl_tests/rpl_row_tabledefs.test | 79 +++-- mysql-test/r/rpl_row_tabledefs.result | 142 ++++---- mysql-test/t/rpl_row_tabledefs.test | 8 + sql/Makefile.am | 4 +- sql/field.cc | 8 + sql/field.h | 2 + sql/log_event.cc | 327 +++++++++++------- sql/log_event.h | 35 +- sql/mysql_priv.h | 5 + sql/rpl_utility.cc | 156 +++++++++ sql/rpl_utility.h | 60 ++++ 11 files changed, 591 insertions(+), 235 deletions(-) create mode 100644 mysql-test/t/rpl_row_tabledefs.test create mode 100644 sql/rpl_utility.cc create mode 100644 sql/rpl_utility.h diff --git a/mysql-test/extra/rpl_tests/rpl_row_tabledefs.test b/mysql-test/extra/rpl_tests/rpl_row_tabledefs.test index 94a3af87ecd..0aabd633394 100644 --- a/mysql-test/extra/rpl_tests/rpl_row_tabledefs.test +++ b/mysql-test/extra/rpl_tests/rpl_row_tabledefs.test @@ -3,11 +3,16 @@ # Consider making these part of the basic RBR tests. --- source include/have_binlog_format_row.inc --- source include/master-slave.inc +connection slave; +STOP SLAVE; +SET GLOBAL SQL_MODE='STRICT_ALL_TABLES'; +START SLAVE; connection master; -eval CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=$engine_type; +eval CREATE TABLE t1_int (a INT PRIMARY KEY, b INT) ENGINE=$engine_type; +eval CREATE TABLE t1_bit (a INT PRIMARY KEY, b INT) ENGINE=$engine_type; +eval CREATE TABLE t1_char (a INT PRIMARY KEY, b INT) ENGINE=$engine_type; +eval CREATE TABLE t1_nodef (a INT PRIMARY KEY, b INT) ENGINE=$engine_type; eval CREATE TABLE t2 (a INT PRIMARY KEY, b INT) ENGINE=$engine_type; eval CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=$engine_type; eval CREATE TABLE t4 (a INT) ENGINE=$engine_type; @@ -15,15 +20,21 @@ eval CREATE TABLE t5 (a INT, b INT, c INT) ENGINE=$engine_type; eval CREATE TABLE t6 (a INT, b INT, c INT) ENGINE=$engine_type; # Table used to detect that slave is running -eval CREATE TABLE t9 (a INT PRIMARY KEY) ENGINE=$engine_type; +eval CREATE TABLE t9 (a INT) ENGINE=$engine_type; sync_slave_with_master; -# On the slave, we add one column last in table 't1', -ALTER TABLE t1 ADD x INT DEFAULT 42; -# ... add one column in the middle of table 't2', and -ALTER TABLE t2 ADD x INT DEFAULT 42 AFTER a; -# ... add one column first in table 't3'. -ALTER TABLE t3 ADD x INT DEFAULT 42 FIRST; + +# On the slave, we add one INT column last in table 't1_int', +ALTER TABLE t1_int ADD x INT DEFAULT 42; +# ... and add one BIT column last in table 't1_bit', +ALTER TABLE t1_bit ADD x BIT(3) DEFAULT b'011'; +# ... and add one CHAR column last in table 't1_char', +ALTER TABLE t1_char ADD x CHAR(20) DEFAULT 'Just a test'; +# ... and add one non-nullable INT column last in table 't1_text' +# with no default, +ALTER TABLE t1_nodef ADD x INT NOT NULL; +# ... and remove the last column in t2 +ALTER TABLE t2 DROP b; # ... change the type of the single column in table 't4' ALTER TABLE t4 MODIFY a FLOAT; # ... change the type of the middle column of table 't5' @@ -31,13 +42,37 @@ ALTER TABLE t5 MODIFY b FLOAT; # ... change the type of the last column of table 't6' ALTER TABLE t6 MODIFY c FLOAT; -# Each of these should generate an error and stop the slave +# Insert some values for tables on slave side. These should not be +# modified when the row from the master is applied. +INSERT INTO t1_int VALUES (2,4,4711); +INSERT INTO t1_char VALUES (2,4,'Foo is a bar'); +INSERT INTO t1_bit VALUES (2,4,b'101'); + +--echo **** On Master **** connection master; -INSERT INTO t9 VALUES (1); +INSERT INTO t1_int VALUES (1,2); +INSERT INTO t1_int VALUES (2,5); +INSERT INTO t1_bit VALUES (1,2); +INSERT INTO t1_bit VALUES (2,5); +INSERT INTO t1_char VALUES (1,2); +INSERT INTO t1_char VALUES (2,5); +SELECT * FROM t1_int; +SELECT * FROM t1_bit; +SELECT * FROM t1_char; +--echo **** On Slave **** +sync_slave_with_master; +SELECT a,b,x FROM t1_int; +SELECT a,b,HEX(x) FROM t1_bit; +SELECT a,b,x FROM t1_char; + +# Each of these should generate an error and stop the slave + +connection master; +INSERT INTO t9 VALUES (2); sync_slave_with_master; # Now slave is guaranteed to be running connection master; -INSERT INTO t1 VALUES (1,2); +INSERT INTO t1_nodef VALUES (1,2); connection slave; wait_for_slave_to_stop; --replace_result $MASTER_MYPORT MASTER_PORT @@ -62,21 +97,6 @@ SHOW SLAVE STATUS; SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; START SLAVE; -connection master; -INSERT INTO t9 VALUES (3); -sync_slave_with_master; -# Now slave is guaranteed to be running -connection master; -INSERT INTO t3 VALUES (3,6); -connection slave; -wait_for_slave_to_stop; ---replace_result $MASTER_MYPORT MASTER_PORT ---replace_column 1 # 8 # 9 # 23 # 33 # ---vertical_results -SHOW SLAVE STATUS; -SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; -START SLAVE; - connection master; INSERT INTO t9 VALUES (4); sync_slave_with_master; @@ -124,6 +144,7 @@ START SLAVE; connection master; --disable_warnings -DROP TABLE IF EXISTS t1,t2,t3,t4,t5,t6,t9; +DROP TABLE IF EXISTS t1_int,t1_bit,t1_char,t1_nodef; +DROP TABLE IF EXISTS t2,t3,t4,t5,t6,t9; --enable_warnings sync_slave_with_master; diff --git a/mysql-test/r/rpl_row_tabledefs.result b/mysql-test/r/rpl_row_tabledefs.result index 715ffcc7578..31a7330041f 100644 --- a/mysql-test/r/rpl_row_tabledefs.result +++ b/mysql-test/r/rpl_row_tabledefs.result @@ -4,21 +4,64 @@ reset master; reset slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; -CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=myisam; -CREATE TABLE t2 (a INT PRIMARY KEY, b INT) ENGINE=myisam; -CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE=myisam; -CREATE TABLE t4 (a INT) ENGINE=myisam; -CREATE TABLE t5 (a INT, b INT, c INT) ENGINE=myisam; -CREATE TABLE t6 (a INT, b INT, c INT) ENGINE=myisam; -CREATE TABLE t9 (a INT PRIMARY KEY) ENGINE=myisam; -ALTER TABLE t1 ADD x INT DEFAULT 42; -ALTER TABLE t2 ADD x INT DEFAULT 42 AFTER a; -ALTER TABLE t3 ADD x INT DEFAULT 42 FIRST; +STOP SLAVE; +SET GLOBAL SQL_MODE='STRICT_ALL_TABLES'; +START SLAVE; +CREATE TABLE t1_int (a INT PRIMARY KEY, b INT) ENGINE='MyISAM'; +CREATE TABLE t1_bit (a INT PRIMARY KEY, b INT) ENGINE='MyISAM'; +CREATE TABLE t1_char (a INT PRIMARY KEY, b INT) ENGINE='MyISAM'; +CREATE TABLE t1_nodef (a INT PRIMARY KEY, b INT) ENGINE='MyISAM'; +CREATE TABLE t2 (a INT PRIMARY KEY, b INT) ENGINE='MyISAM'; +CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE='MyISAM'; +CREATE TABLE t4 (a INT) ENGINE='MyISAM'; +CREATE TABLE t5 (a INT, b INT, c INT) ENGINE='MyISAM'; +CREATE TABLE t6 (a INT, b INT, c INT) ENGINE='MyISAM'; +CREATE TABLE t9 (a INT) ENGINE='MyISAM'; +ALTER TABLE t1_int ADD x INT DEFAULT 42; +ALTER TABLE t1_bit ADD x BIT(3) DEFAULT b'011'; +ALTER TABLE t1_char ADD x CHAR(20) DEFAULT 'Just a test'; +ALTER TABLE t1_nodef ADD x INT NOT NULL; +ALTER TABLE t2 DROP b; ALTER TABLE t4 MODIFY a FLOAT; ALTER TABLE t5 MODIFY b FLOAT; ALTER TABLE t6 MODIFY c FLOAT; -INSERT INTO t9 VALUES (1); -INSERT INTO t1 VALUES (1,2); +INSERT INTO t1_int VALUES (2,4,4711); +INSERT INTO t1_char VALUES (2,4,'Foo is a bar'); +INSERT INTO t1_bit VALUES (2,4,b'101'); +**** On Master **** +INSERT INTO t1_int VALUES (1,2); +INSERT INTO t1_int VALUES (2,5); +INSERT INTO t1_bit VALUES (1,2); +INSERT INTO t1_bit VALUES (2,5); +INSERT INTO t1_char VALUES (1,2); +INSERT INTO t1_char VALUES (2,5); +SELECT * FROM t1_int; +a b +1 2 +2 5 +SELECT * FROM t1_bit; +a b +1 2 +2 5 +SELECT * FROM t1_char; +a b +1 2 +2 5 +**** On Slave **** +SELECT a,b,x FROM t1_int; +a b x +2 5 4711 +1 2 42 +SELECT a,b,HEX(x) FROM t1_bit; +a b HEX(x) +2 5 5 +1 2 3 +SELECT a,b,x FROM t1_char; +a b x +2 5 Foo is a bar +1 2 Just a test +INSERT INTO t9 VALUES (2); +INSERT INTO t1_nodef VALUES (1,2); SHOW SLAVE STATUS; Slave_IO_State # Master_Host 127.0.0.1 @@ -26,7 +69,7 @@ Master_User root Master_Port MASTER_PORT Connect_Retry 1 Master_Log_File master-bin.000001 -Read_Master_Log_Pos 1042 +Read_Master_Log_Pos 1934 Relay_Log_File # Relay_Log_Pos # Relay_Master_Log_File master-bin.000001 @@ -38,10 +81,10 @@ Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table -Last_Errno 1454 -Last_Error Table width mismatch - received 2 columns, test.t1 has 3 columns +Last_Errno 1364 +Last_Error Error in Write_rows event: error during transaction execution on table test.t1_nodef Skip_Counter 0 -Exec_Master_Log_Pos 968 +Exec_Master_Log_Pos 1850 Relay_Log_Space # Until_Condition None Until_Log_File @@ -64,7 +107,7 @@ Master_User root Master_Port MASTER_PORT Connect_Retry 1 Master_Log_File master-bin.000001 -Read_Master_Log_Pos 1185 +Read_Master_Log_Pos 2085 Relay_Log_File # Relay_Log_Pos # Relay_Master_Log_File master-bin.000001 @@ -76,48 +119,10 @@ Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table -Last_Errno 1454 -Last_Error Table width mismatch - received 2 columns, test.t2 has 3 columns +Last_Errno 1514 +Last_Error Table width mismatch - received 2 columns, test.t2 has 1 columns Skip_Counter 0 -Exec_Master_Log_Pos 1111 -Relay_Log_Space # -Until_Condition None -Until_Log_File -Until_Log_Pos 0 -Master_SSL_Allowed No -Master_SSL_CA_File -Master_SSL_CA_Path -Master_SSL_Cert -Master_SSL_Cipher -Master_SSL_Key -Seconds_Behind_Master # -SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; -START SLAVE; -INSERT INTO t9 VALUES (3); -INSERT INTO t3 VALUES (3,6); -SHOW SLAVE STATUS; -Slave_IO_State # -Master_Host 127.0.0.1 -Master_User root -Master_Port MASTER_PORT -Connect_Retry 1 -Master_Log_File master-bin.000001 -Read_Master_Log_Pos 1328 -Relay_Log_File # -Relay_Log_Pos # -Relay_Master_Log_File master-bin.000001 -Slave_IO_Running Yes -Slave_SQL_Running No -Replicate_Do_DB -Replicate_Ignore_DB -Replicate_Do_Table -Replicate_Ignore_Table -Replicate_Wild_Do_Table -Replicate_Wild_Ignore_Table -Last_Errno 1454 -Last_Error Table width mismatch - received 2 columns, test.t3 has 3 columns -Skip_Counter 0 -Exec_Master_Log_Pos 1254 +Exec_Master_Log_Pos 2007 Relay_Log_Space # Until_Condition None Until_Log_File @@ -140,7 +145,7 @@ Master_User root Master_Port MASTER_PORT Connect_Retry 1 Master_Log_File master-bin.000001 -Read_Master_Log_Pos 1466 +Read_Master_Log_Pos 2231 Relay_Log_File # Relay_Log_Pos # Relay_Master_Log_File master-bin.000001 @@ -152,10 +157,10 @@ Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table -Last_Errno 1454 +Last_Errno 1514 Last_Error Column 0 type mismatch - received type 3, test.t4 has type 4 Skip_Counter 0 -Exec_Master_Log_Pos 1397 +Exec_Master_Log_Pos 2158 Relay_Log_Space # Until_Condition None Until_Log_File @@ -178,7 +183,7 @@ Master_User root Master_Port MASTER_PORT Connect_Retry 1 Master_Log_File master-bin.000001 -Read_Master_Log_Pos 1614 +Read_Master_Log_Pos 2387 Relay_Log_File # Relay_Log_Pos # Relay_Master_Log_File master-bin.000001 @@ -190,10 +195,10 @@ Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table -Last_Errno 1454 +Last_Errno 1514 Last_Error Column 1 type mismatch - received type 3, test.t5 has type 4 Skip_Counter 0 -Exec_Master_Log_Pos 1535 +Exec_Master_Log_Pos 2304 Relay_Log_Space # Until_Condition None Until_Log_File @@ -216,7 +221,7 @@ Master_User root Master_Port MASTER_PORT Connect_Retry 1 Master_Log_File master-bin.000001 -Read_Master_Log_Pos 1762 +Read_Master_Log_Pos 2543 Relay_Log_File # Relay_Log_Pos # Relay_Master_Log_File master-bin.000001 @@ -228,10 +233,10 @@ Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table -Last_Errno 1454 +Last_Errno 1514 Last_Error Column 2 type mismatch - received type 3, test.t6 has type 4 Skip_Counter 0 -Exec_Master_Log_Pos 1683 +Exec_Master_Log_Pos 2460 Relay_Log_Space # Until_Condition None Until_Log_File @@ -245,4 +250,5 @@ Master_SSL_Key Seconds_Behind_Master # SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; START SLAVE; -DROP TABLE IF EXISTS t1,t2,t3,t4,t5,t6,t9; +DROP TABLE IF EXISTS t1_int,t1_bit,t1_char,t1_nodef; +DROP TABLE IF EXISTS t2,t3,t4,t5,t6,t9; diff --git a/mysql-test/t/rpl_row_tabledefs.test b/mysql-test/t/rpl_row_tabledefs.test new file mode 100644 index 00000000000..ab4914e15fa --- /dev/null +++ b/mysql-test/t/rpl_row_tabledefs.test @@ -0,0 +1,8 @@ + +-- source include/have_binlog_format_row.inc +-- source include/master-slave.inc + +let $engine_type = 'MyISAM'; +-- source extra/rpl_tests/rpl_row_tabledefs.test + + diff --git a/sql/Makefile.am b/sql/Makefile.am index 60e7891931f..71c91cdf7fa 100644 --- a/sql/Makefile.am +++ b/sql/Makefile.am @@ -53,7 +53,7 @@ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \ sql_manager.h sql_map.h sql_string.h unireg.h \ sql_error.h field.h handler.h mysqld_suffix.h \ ha_heap.h ha_myisam.h ha_myisammrg.h ha_partition.h \ - opt_range.h protocol.h rpl_tblmap.h \ + opt_range.h protocol.h rpl_tblmap.h rpl_utility.h \ log.h sql_show.h rpl_rli.h \ sql_select.h structs.h table.h sql_udf.h hash_filo.h\ lex.h lex_symbol.h sql_acl.h sql_crypt.h \ @@ -91,7 +91,7 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc sql_partition.cc \ sql_load.cc mf_iocache.cc field_conv.cc sql_show.cc \ sql_udf.cc sql_analyse.cc sql_analyse.h sql_cache.cc \ slave.cc sql_repl.cc rpl_filter.cc rpl_tblmap.cc \ - rpl_injector.cc \ + rpl_utility.cc rpl_injector.cc \ sql_union.cc sql_derived.cc \ client.c sql_client.cc mini_client_errors.c pack.c\ stacktrace.c repl_failsafe.h repl_failsafe.cc \ diff --git a/sql/field.cc b/sql/field.cc index 1176257359f..32e63597c30 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -8259,6 +8259,14 @@ const char *Field_bit::unpack(char *to, const char *from) } +void Field_bit::set_default() +{ + my_ptrdiff_t const offset= table->s->default_values - table->record[0]; + uchar bits= get_rec_bits(bit_ptr + offset, bit_ofs, bit_len); + set_rec_bits(bits, bit_ptr, bit_ofs, bit_len); + Field::set_default(); +} + /* Bit field support for non-MyISAM tables. */ diff --git a/sql/field.h b/sql/field.h index b473100eaab..d8dcb85fd5a 100644 --- a/sql/field.h +++ b/sql/field.h @@ -1384,6 +1384,8 @@ public: void sql_type(String &str) const; char *pack(char *to, const char *from, uint max_length=~(uint) 0); const char *unpack(char* to, const char *from); + virtual void set_default(); + Field *new_key_field(MEM_ROOT *root, struct st_table *new_table, char *new_ptr, uchar *new_null_ptr, uint new_null_bit); diff --git a/sql/log_event.cc b/sql/log_event.cc index 8a39b1fc4eb..3164a62d876 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -24,6 +24,7 @@ #include "mysql_priv.h" #include "slave.h" #include "rpl_filter.h" +#include "rpl_utility.h" #include #endif /* MYSQL_CLIENT */ #include @@ -5258,38 +5259,86 @@ int Rows_log_event::do_add_row_data(byte *const row_data, #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) /* - Unpack a row into a record. The row is assumed to only consist of the fields - for which the bitset represented by 'arr' and 'bits'; the other parts of the + Unpack a row into a record. + + The row is assumed to only consist of the fields for which the + bitset represented by 'arr' and 'bits'; the other parts of the record are left alone. + + At most 'colcnt' columns are read: if the table is larger than that, + the remaining fields are not filled in. */ -static char const *unpack_row(TABLE *table, - byte *record, char const *row, - MY_BITMAP const *cols) +static int +unpack_row(RELAY_LOG_INFO *rli, + TABLE *table, uint colcnt, byte *record, + char const *row, MY_BITMAP const *cols, + char const **row_end, ulong *master_reclength) { DBUG_ASSERT(record && row); - MY_BITMAP *write_set= table->file->write_set; + my_size_t const n_null_bytes= table->s->null_bytes; my_ptrdiff_t const offset= record - (byte*) table->record[0]; - - memcpy(record, row, n_null_bytes); - char const *ptr= row + n_null_bytes; + memcpy(record, row, n_null_bytes); // [1] + int error= 0; bitmap_set_all(write_set); - Field **const begin_ptr = table->field; - for (Field **field_ptr= begin_ptr ; *field_ptr ; ++field_ptr) - { - Field *const f= *field_ptr; - if (bitmap_is_set(cols, field_ptr - begin_ptr)) + Field **const begin_ptr = table->field; + Field **field_ptr; + { + char const *ptr= row + n_null_bytes; + for (field_ptr= begin_ptr ; *field_ptr ; ++field_ptr) { - /* Field...::unpack() cannot return 0 */ - ptr= f->unpack(f->ptr + offset, ptr); + Field *const f= *field_ptr; + + if (colcnt == 0) + break; + + if (bitmap_is_set(cols, field_ptr - begin_ptr)) + { + /* Field...::unpack() cannot return 0 */ + ptr= f->unpack(f->ptr + offset, ptr); + --colcnt; + } + else + bitmap_clear_bit(write_set, (field_ptr - begin_ptr) + 1); + } + + *row_end = ptr; + if (master_reclength) + { + if (*field_ptr) + *master_reclength = (*field_ptr)->ptr - table->record[0]; + else + *master_reclength = table->s->reclength; + } + } + + /* + Set properties for remaining columns, if there are any. We let the + corresponding bit in the write_set be set, to write the value if + it was not there already. We iterate over all remaining columns, + even if there were an error, to get as many error messages as + possible. We are still able to return a pointer to the next row, + so wedo that. + */ + for ( ; *field_ptr ; ++field_ptr) + { + if ((*field_ptr)->flags & (NOT_NULL_FLAG | NO_DEFAULT_VALUE_FLAG)) + { + slave_print_msg(ERROR_LEVEL, rli, ER_NO_DEFAULT_FOR_FIELD, + "Field `%s` of table `%s`.`%s` " + "has no default value and cannot be NULL", + (*field_ptr)->field_name, table->s->db.str, + table->s->table_name.str); + error = ER_NO_DEFAULT_FOR_FIELD; } else - bitmap_clear_bit(write_set, (field_ptr - begin_ptr) + 1); + (*field_ptr)->set_default(); } - return ptr; + + return error; } int Rows_log_event::exec_event(st_relay_log_info *rli) @@ -5444,7 +5493,11 @@ int Rows_log_event::exec_event(st_relay_log_info *rli) error= do_before_row_operations(table); while (error == 0 && row_start < (const char*)m_rows_end) { - char const *row_end= do_prepare_row(thd, table, row_start); + char const *row_end= NULL; + if ((error= do_prepare_row(thd, rli, table, row_start, &row_end))) + break; // We should to the after-row operation even in the + // case of error + DBUG_ASSERT(row_end != NULL); // cannot happen DBUG_ASSERT(row_end <= (const char*)m_rows_end); @@ -5646,7 +5699,7 @@ void Rows_log_event::pack_info(Protocol *protocol) #endif /************************************************************************** - Table_map_log_event member functions + Table_map_log_event member functions and support functions **************************************************************************/ /* @@ -5910,71 +5963,9 @@ int Table_map_log_event::exec_event(st_relay_log_info *rli) */ DBUG_ASSERT(m_table->in_use); - /* - Check that the number of columns and the field types in the - event match the number of columns and field types in the opened - table. - */ - uint col= m_table->s->fields; - - if (col == m_colcnt) + table_def const def(m_coltype, m_colcnt); + if (def.compatible_with(rli, m_table)) { - while (col-- > 0) - if (m_table->field[col]->type() != m_coltype[col]) - break; - } - - TABLE_SHARE const *const tsh= m_table->s; - - /* - Check the following termination conditions: - - (col == m_table->s->fields) - ==> (m_table->s->fields != m_colcnt) - (0 <= col < m_table->s->fields) - ==> (m_table->field[col]->type() != m_coltype[col]) - - Logically, A ==> B is equivalent to !A || B - - Since col is unsigned, is suffices to check that col <= - tsh->fields. If col wrapped (by decreasing col when it is 0), - the number will be UINT_MAX, which is greater than tsh->fields. - */ - DBUG_ASSERT(!(col == tsh->fields) || tsh->fields != m_colcnt); - DBUG_ASSERT(!(col < tsh->fields) || - (m_table->field[col]->type() != m_coltype[col])); - - if (col <= tsh->fields) - { - /* - If we get here, the number of columns in the event didn't - match the number of columns in the table on the slave, *or* - there were a column in the table on the slave that did not - have the same type as given in the event. - - If 'col' has the value that was assigned to it, it was a - mismatch between the number of columns on the master and the - slave. - */ - if (col == tsh->fields) - { - DBUG_ASSERT(tsh->db.str && tsh->table_name.str); - slave_print_msg(ERROR_LEVEL, rli, ER_BINLOG_ROW_WRONG_TABLE_DEF, - "Table width mismatch - " - "received %u columns, %s.%s has %u columns", - m_colcnt, tsh->db.str, tsh->table_name.str, tsh->fields); - } - else - { - DBUG_ASSERT(col < m_colcnt && col < tsh->fields); - DBUG_ASSERT(tsh->db.str && tsh->table_name.str); - slave_print_msg(ERROR_LEVEL, rli, ER_BINLOG_ROW_WRONG_TABLE_DEF, - "Column %d type mismatch - " - "received type %d, %s.%s has type %d", - col, m_coltype[col], tsh->db.str, tsh->table_name.str, - m_table->field[col]->type()); - } - thd->query_error= 1; DBUG_RETURN(ERR_BAD_TABLE_DEF); } @@ -6085,6 +6076,25 @@ void Table_map_log_event::print(FILE *file, PRINT_EVENT_INFO *print_event_info) } #endif +#ifndef DBUG_OFF +static void +print_column_values(char const *text, THD *thd, TABLE *table) +{ + THD *old_thd= table->in_use; + if (table->in_use == NULL) + table->in_use= thd; + for (Field **fptr= table->field ; *fptr ; ++fptr) + { + char buf[MAX_FIELD_WIDTH]; + String str(buf, sizeof(buf), system_charset_info); + (*fptr)->val_str(&str); + DBUG_PRINT("info", ("%s for column %d is '%s'", + text, fptr - table->field, str.c_ptr())); + } + table->in_use= old_thd; +} +#endif + /************************************************************************** Write_rows_log_event member functions **************************************************************************/ @@ -6169,19 +6179,22 @@ int Write_rows_log_event::do_after_row_operations(TABLE *table, int error) return error; } -char const *Write_rows_log_event::do_prepare_row(THD *thd, TABLE *table, - char const *row_start) +int Write_rows_log_event::do_prepare_row(THD *thd, RELAY_LOG_INFO *rli, + TABLE *table, + char const *row_start, + char const **row_end) { - char const *ptr= row_start; DBUG_ASSERT(table != NULL); - /* - This assertion actually checks that there is at least as many - columns on the slave as on the master. - */ - DBUG_ASSERT(table->s->fields >= m_width); - DBUG_ASSERT(ptr); - ptr= unpack_row(table, (byte*)table->record[0], ptr, &m_cols); - return ptr; + DBUG_ASSERT(row_start && row_end); + + int error; + error= unpack_row(rli, + table, m_width, (byte*)table->record[0], + row_start, &m_cols, row_end, &m_master_reclength); +#ifndef DBUG_OFF + print_column_values("Unpacked value", thd, table); +#endif + return error; } /* @@ -6237,24 +6250,33 @@ namespace { @param thd Thread context for writing the record. @param table Table to which record should be written. - + @param master_reclength + Offset to first column that is not present on the master, + alternatively the length of the record on the master side. @return Error code on failure, 0 on success. */ static int -replace_record(THD *thd, TABLE *table) +replace_record(THD *thd, TABLE *table, + ulong const master_reclength, + uint const master_fields) { + DBUG_ENTER("replace_record"); DBUG_ASSERT(table != NULL && thd != NULL); int error; int keynum; auto_afree_ptr key(NULL); +#ifndef DBUG_OFF + print_column_values("Starting write value", thd, table); +#endif + while ((error= table->file->ha_write_row(table->record[0]))) { if ((keynum= table->file->get_dup_key(error)) < 0) { /* We failed to retrieve the duplicate key */ - return HA_ERR_FOUND_DUPP_KEY; + DBUG_RETURN(HA_ERR_FOUND_DUPP_KEY); } /* @@ -6271,20 +6293,20 @@ replace_record(THD *thd, TABLE *table) { error= table->file->rnd_pos(table->record[1], table->file->dupp_ref); if (error) - return error; + DBUG_RETURN(error); } else { if (table->file->extra(HA_EXTRA_FLUSH_CACHE)) { - return my_errno; + DBUG_RETURN(my_errno); } if (key.get() == NULL) { key.assign(static_cast(my_alloca(table->s->max_unique_length))); if (key.get() == NULL) - return ENOMEM; + DBUG_RETURN(ENOMEM); } key_copy((byte*)key.get(), table->record[0], table->key_info + keynum, 0); @@ -6293,7 +6315,7 @@ replace_record(THD *thd, TABLE *table) table->key_info[keynum].key_length, HA_READ_KEY_EXACT); if (error) - return error; + DBUG_RETURN(error); } /* @@ -6301,6 +6323,59 @@ replace_record(THD *thd, TABLE *table) will enable us to update it or, alternatively, delete it (so that we can insert the new row afterwards). + First we copy the columns into table->record[0] that are not + present on the master from table->record[1], if there are any. + */ + + DBUG_PRINT("info", ("Copying to %p from offset %u to %u", + table->record[0], + master_reclength, table->s->reclength)); +#ifndef DBUG_OFF + print_column_values("After copy value", thd, table); +#endif + if (master_reclength < table->s->reclength) + bmove_align(table->record[0] + master_reclength, + table->record[1] + master_reclength, + table->s->reclength - master_reclength); + + /* + Bit columns are special. We iterate over all the remaining + columns and copy the "extra" bits to the new record. This is + not a very good solution: it should be refactored on + opportunity. + + REFACTORING SUGGESTION (Matz). Introduce a member function + similar to move_field_offset() called copy_field_offset() to + copy field values and implement it for all Field subclasses. Use + this function to copy data from the found record to the record + that are going to be inserted. + + The copy_field_offset() function need to be a virtual function, + which in this case will prevent copying an entire range of + fields efficiently. + */ + { + Field **field_ptr= table->field + master_fields; + for ( ; *field_ptr ; ++field_ptr) + { + switch ((*field_ptr)->real_type()) + { + default: + /* Nothing to do */ + break; + + case FIELD_TYPE_BIT: + Field_bit *f= static_cast(*field_ptr); + my_ptrdiff_t const offset= table->record[1] - table->record[0]; + uchar const bits= + get_rec_bits(f->bit_ptr + offset, f->bit_ofs, f->bit_len); + set_rec_bits(bits, f->bit_ptr, f->bit_ofs, f->bit_len); + break; + } + } + } + + /* REPLACE is defined as either INSERT or DELETE + INSERT. If possible, we can replace it with an UPDATE, but that will not work on InnoDB if FOREIGN KEY checks are necessary. @@ -6320,22 +6395,22 @@ replace_record(THD *thd, TABLE *table) { error=table->file->ha_update_row(table->record[1], table->record[0]); - return error; + DBUG_RETURN(error); } else { if ((error= table->file->ha_delete_row(table->record[1]))) - return error; + DBUG_RETURN(error); /* Will retry ha_write_row() with the offending row removed. */ } } - return error; + DBUG_RETURN(error); } int Write_rows_log_event::do_exec_row(TABLE *table) { DBUG_ASSERT(table != NULL); - int error= replace_record(thd, table); + int error= replace_record(thd, table, m_master_reclength, m_width); return error; } #endif /* !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) */ @@ -6606,20 +6681,22 @@ int Delete_rows_log_event::do_after_row_operations(TABLE *table, int error) return error; } -char const *Delete_rows_log_event::do_prepare_row(THD *thd, TABLE *table, - char const *row_start) +int Delete_rows_log_event::do_prepare_row(THD *thd, RELAY_LOG_INFO *rli, + TABLE *table, + char const *row_start, + char const **row_end) { - char const *ptr= row_start; - DBUG_ASSERT(ptr); + int error; + DBUG_ASSERT(row_start && row_end); /* This assertion actually checks that there is at least as many columns on the slave as on the master. */ DBUG_ASSERT(table->s->fields >= m_width); - DBUG_ASSERT(ptr != NULL); - ptr= unpack_row(table, table->record[0], ptr, &m_cols); - + error= unpack_row(rli, + table, m_width, table->record[0], + row_start, &m_cols, row_end, &m_master_reclength); /* If we will access rows using the random access method, m_key will be set to NULL, so we do not need to make a key copy in that case. @@ -6631,7 +6708,7 @@ char const *Delete_rows_log_event::do_prepare_row(THD *thd, TABLE *table, key_copy(m_key, table->record[0], key_info, 0); } - return ptr; + return error; } int Delete_rows_log_event::do_exec_row(TABLE *table) @@ -6757,11 +6834,13 @@ int Update_rows_log_event::do_after_row_operations(TABLE *table, int error) return error; } -char const *Update_rows_log_event::do_prepare_row(THD *thd, TABLE *table, - char const *row_start) +int Update_rows_log_event::do_prepare_row(THD *thd, RELAY_LOG_INFO *rli, + TABLE *table, + char const *row_start, + char const **row_end) { - char const *ptr= row_start; - DBUG_ASSERT(ptr); + int error; + DBUG_ASSERT(row_start && row_end); /* This assertion actually checks that there is at least as many columns on the slave as on the master. @@ -6769,10 +6848,14 @@ char const *Update_rows_log_event::do_prepare_row(THD *thd, TABLE *table, DBUG_ASSERT(table->s->fields >= m_width); /* record[0] is the before image for the update */ - ptr= unpack_row(table, table->record[0], ptr, &m_cols); - DBUG_ASSERT(ptr != NULL); + error= unpack_row(rli, + table, m_width, table->record[0], + row_start, &m_cols, row_end, &m_master_reclength); + row_start = *row_end; /* m_after_image is the after image for the update */ - ptr= unpack_row(table, m_after_image, ptr, &m_cols); + error= unpack_row(rli, + table, m_width, m_after_image, + row_start, &m_cols, row_end, &m_master_reclength); /* If we will access rows using the random access method, m_key will @@ -6785,7 +6868,7 @@ char const *Update_rows_log_event::do_prepare_row(THD *thd, TABLE *table, key_copy(m_key, table->record[0], key_info, 0); } - return ptr; + return error; } int Update_rows_log_event::do_exec_row(TABLE *table) diff --git a/sql/log_event.h b/sql/log_event.h index b24686514e3..5f0d31b4e11 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -1854,6 +1854,7 @@ protected: ulong m_table_id; /* Table ID */ MY_BITMAP m_cols; /* Bitmap denoting columns available */ ulong m_width; /* The width of the columns bitmap */ + ulong m_master_reclength; /* Length of record on master side */ /* Bit buffer in the same memory as the class */ uint32 m_bitbuf[128/(sizeof(uint32)*8)]; @@ -1907,12 +1908,15 @@ private: since SQL thread specific data is not available: that data is made available for the do_exec function. - RETURN VALUE A pointer to the start of the next row, or NULL if the preparation failed. Currently, preparation cannot fail, but don't rely on this behavior. + + RETURN VALUE + Error code, if something went wrong, 0 otherwise. */ - virtual char const *do_prepare_row(THD*, TABLE*, char const *row_start) = 0; + virtual int do_prepare_row(THD*, RELAY_LOG_INFO*, TABLE*, + char const *row_start, char const **row_end) = 0; /* Primitive to do the actual execution necessary for a row. @@ -1980,10 +1984,11 @@ private: gptr m_memory; byte *m_after_image; - virtual int do_before_row_operations(TABLE *table); - virtual int do_after_row_operations(TABLE *table, int error); - virtual char const *do_prepare_row(THD*, TABLE*, char const *row_start); - virtual int do_exec_row(TABLE *table); + virtual int do_before_row_operations(TABLE *table); + virtual int do_after_row_operations(TABLE *table, int error); + virtual int do_prepare_row(THD*, RELAY_LOG_INFO*, TABLE*, + char const *row_start, char const **row_end); + virtual int do_exec_row(TABLE *table); #endif }; @@ -2044,10 +2049,11 @@ private: byte *m_key; byte *m_after_image; - virtual int do_before_row_operations(TABLE *table); - virtual int do_after_row_operations(TABLE *table, int error); - virtual char const *do_prepare_row(THD*, TABLE*, char const *row_start); - virtual int do_exec_row(TABLE *table); + virtual int do_before_row_operations(TABLE *table); + virtual int do_after_row_operations(TABLE *table, int error); + virtual int do_prepare_row(THD*, RELAY_LOG_INFO*, TABLE*, + char const *row_start, char const **row_end); + virtual int do_exec_row(TABLE *table); #endif /* !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) */ }; @@ -2114,10 +2120,11 @@ private: byte *m_key; byte *m_after_image; - virtual int do_before_row_operations(TABLE *table); - virtual int do_after_row_operations(TABLE *table, int error); - virtual char const *do_prepare_row(THD*, TABLE*, char const *row_start); - virtual int do_exec_row(TABLE *table); + virtual int do_before_row_operations(TABLE *table); + virtual int do_after_row_operations(TABLE *table, int error); + virtual int do_prepare_row(THD*, RELAY_LOG_INFO*, TABLE*, + char const *row_start, char const **row_end); + virtual int do_exec_row(TABLE *table); #endif }; diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index c471b11fee2..b362be6d3b7 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -21,6 +21,9 @@ except the part which must be in the server and in the client. */ +#ifndef MYSQL_PRIV_H +#define MYSQL_PRIV_H + #ifndef MYSQL_CLIENT #include @@ -1773,3 +1776,5 @@ bool schema_table_store_record(THD *thd, TABLE *table); #endif /* MYSQL_SERVER */ #endif /* MYSQL_CLIENT */ + +#endif /* MYSQL_PRIV_H */ diff --git a/sql/rpl_utility.cc b/sql/rpl_utility.cc new file mode 100644 index 00000000000..fc706178aa3 --- /dev/null +++ b/sql/rpl_utility.cc @@ -0,0 +1,156 @@ +/* Copyright 2006 MySQL AB. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include "rpl_utility.h" + +uint32 +field_length_from_packed(enum_field_types const field_type, + byte const *const data) +{ + uint32 length; + + switch (field_type) { + case MYSQL_TYPE_DECIMAL: + case MYSQL_TYPE_NEWDECIMAL: + length= ~0UL; + break; + case MYSQL_TYPE_YEAR: + case MYSQL_TYPE_TINY: + length= 1; + break; + case MYSQL_TYPE_SHORT: + length= 2; + break; + case MYSQL_TYPE_INT24: + length= 3; + break; + case MYSQL_TYPE_LONG: + length= 4; + break; +#ifdef HAVE_LONG_LONG + case MYSQL_TYPE_LONGLONG: + length= 8; + break; +#endif + case MYSQL_TYPE_FLOAT: + length= sizeof(float); + break; + case MYSQL_TYPE_DOUBLE: + length= sizeof(double); + break; + case MYSQL_TYPE_NULL: + length= 0; + break; + case MYSQL_TYPE_NEWDATE: + length= 3; + break; + case MYSQL_TYPE_DATE: + length= 4; + break; + case MYSQL_TYPE_TIME: + length= 3; + break; + case MYSQL_TYPE_TIMESTAMP: + length= 4; + break; + case MYSQL_TYPE_DATETIME: + length= 8; + break; + break; + case MYSQL_TYPE_BIT: + length= ~0UL; + break; + default: + /* This case should never be chosen */ + DBUG_ASSERT(0); + /* If something goes awfully wrong, it's better to get a string than die */ + case MYSQL_TYPE_STRING: + length= uint2korr(data); + break; + + case MYSQL_TYPE_ENUM: + case MYSQL_TYPE_SET: + case MYSQL_TYPE_VAR_STRING: + case MYSQL_TYPE_VARCHAR: + length= ~0UL; // NYI + break; + + case MYSQL_TYPE_TINY_BLOB: + case MYSQL_TYPE_MEDIUM_BLOB: + case MYSQL_TYPE_LONG_BLOB: + case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_GEOMETRY: + length= ~0UL; // NYI + break; + } +} + +/********************************************************************* + * table_def member definitions * + *********************************************************************/ + +/* + Is the definition compatible with a table? + + Compare the definition with a table to see if it is compatible with + it. A table definition is compatible with a table if + - the columns types of the table definition is a (not necessarily + proper) prefix of the column type of the table, or + - the other way around +*/ +int +table_def::compatible_with(RELAY_LOG_INFO *rli, TABLE *table) + const +{ + /* + We only check the initial columns for the tables. + */ + uint const cols_to_check= min(table->s->fields, size()); + int error= 0; + + TABLE_SHARE const *const tsh= table->s; + + /* + To get proper error reporting for all columns of the table, we + both check the width and iterate over all columns. + */ + if (tsh->fields < size()) + { + DBUG_ASSERT(tsh->db.str && tsh->table_name.str); + error= 1; + slave_print_msg(ERROR_LEVEL, rli, ER_BINLOG_ROW_WRONG_TABLE_DEF, + "Table width mismatch - " + "received %u columns, %s.%s has %u columns", + size(), tsh->db.str, tsh->table_name.str, tsh->fields); + } + + for (uint col= 0 ; col < cols_to_check ; ++col) + { + if (table->field[col]->type() != type(col)) + { + DBUG_ASSERT(col < size() && col < tsh->fields); + DBUG_ASSERT(tsh->db.str && tsh->table_name.str); + error= 1; + slave_print_msg(ERROR_LEVEL, rli, ER_BINLOG_ROW_WRONG_TABLE_DEF, + "Column %d type mismatch - " + "received type %d, %s.%s has type %d", + col, type(col), tsh->db.str, tsh->table_name.str, + table->field[col]->type()); + } + } + + return error; +} diff --git a/sql/rpl_utility.h b/sql/rpl_utility.h new file mode 100644 index 00000000000..0ac3c10eec6 --- /dev/null +++ b/sql/rpl_utility.h @@ -0,0 +1,60 @@ +/* Copyright 2006 MySQL AB. All rights reserved. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#ifndef RPL_UTILITY_H +#define RPL_UTILITY_H + +#ifndef __cplusplus +#error "Don't include this C++ header file from a non-C++ file!" +#endif + +#include "mysql_priv.h" + +uint32 +field_length_from_packed(enum_field_types const field_type, + byte const *const data); + +/* + A table definition from the master. + + RESPONSIBILITIES + + - Extract table definition data from the table map event + - Check if table definition in table map is compatible with table + definition on slave + */ + +class table_def +{ +public: + typedef unsigned char field_type; + + table_def(field_type *t, my_size_t s) + : m_type(t), m_size(s) + { + } + + my_size_t size() const { return m_size; } + field_type type(my_ptrdiff_t i) const { return m_type[i]; } + + int compatible_with(RELAY_LOG_INFO *rli, TABLE *table) const; + +private: + my_size_t m_size; + field_type *m_type; +}; + +#endif /* RPL_UTILITY_H */ From 89df5b6b48743083215ab4aa7dc3fefc57e668ed Mon Sep 17 00:00:00 2001 From: "tomas@poseidon.ndb.mysql.com" <> Date: Thu, 4 May 2006 11:15:14 +0200 Subject: [PATCH 02/27] bug (colcnt) + compile fix --- mysql-test/t/disabled.def | 1 + sql/log_event.cc | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index c0827e09990..a3bedbaa22d 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -24,6 +24,7 @@ rpl_deadlock_innodb : BUG#16920 2006-04-12 kent fails in show slave stat rpl_ndb_2innodb : BUG#19004 2006-03-22 tomas ndb: partition by range and update hangs rpl_ndb_2myisam : BUG#19004 2006-03-22 tomas ndb: partition by range and update hangs rpl_ndb_auto_inc : BUG#17086 2006-02-16 jmiller CR: auto_increment_increment and auto_increment_offset produce duplicate key er +rpl_ndb_commit_afterflush : LOCK TABLES cases hang in ndb injector thread rpl_ndb_ddl : result file needs update + test needs to checked rpl_ndb_innodb2ndb : BUG#18094 2006-03-16 mats Slave caches invalid table definition after atlters causes select failure rpl_ndb_log : BUG#18947 2006-03-21 tomas CRBR: order in binlog of create table and insert (on different table) not determ diff --git a/sql/log_event.cc b/sql/log_event.cc index 3164a62d876..9991656c3eb 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -5294,12 +5294,11 @@ unpack_row(RELAY_LOG_INFO *rli, if (colcnt == 0) break; - + --colcnt; if (bitmap_is_set(cols, field_ptr - begin_ptr)) { /* Field...::unpack() cannot return 0 */ ptr= f->unpack(f->ptr + offset, ptr); - --colcnt; } else bitmap_clear_bit(write_set, (field_ptr - begin_ptr) + 1); @@ -6076,6 +6075,7 @@ void Table_map_log_event::print(FILE *file, PRINT_EVENT_INFO *print_event_info) } #endif +#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) #ifndef DBUG_OFF static void print_column_values(char const *text, THD *thd, TABLE *table) @@ -6094,6 +6094,7 @@ print_column_values(char const *text, THD *thd, TABLE *table) table->in_use= old_thd; } #endif +#endif /************************************************************************** Write_rows_log_event member functions From 67909baa285943985a6b4f283f14ff8b6ba467b2 Mon Sep 17 00:00:00 2001 From: "mats@mysql.com" <> Date: Mon, 8 May 2006 20:05:25 +0200 Subject: [PATCH 03/27] WL#3259 (RBR with more columns on slave than on master): Added support for UPDATE. Some minor fixes. --- .../extra/rpl_tests/rpl_row_tabledefs.test | 64 ++-- ...esult => rpl_row_tabledefs_2myisam.result} | 68 +++-- mysql-test/r/rpl_row_tabledefs_3innodb.result | 286 ++++++++++++++++++ mysql-test/r/rpl_row_tabledefs_7ndb.result | 286 ++++++++++++++++++ ...fs.test => rpl_row_tabledefs_2myisam.test} | 0 mysql-test/t/rpl_row_tabledefs_3innodb.test | 9 + sql/field.cc | 32 ++ sql/field.h | 19 ++ sql/log_event.cc | 169 +++++++---- 9 files changed, 828 insertions(+), 105 deletions(-) rename mysql-test/r/{rpl_row_tabledefs.result => rpl_row_tabledefs_2myisam.result} (84%) create mode 100644 mysql-test/r/rpl_row_tabledefs_3innodb.result create mode 100644 mysql-test/r/rpl_row_tabledefs_7ndb.result rename mysql-test/t/{rpl_row_tabledefs.test => rpl_row_tabledefs_2myisam.test} (100%) create mode 100644 mysql-test/t/rpl_row_tabledefs_3innodb.test diff --git a/mysql-test/extra/rpl_tests/rpl_row_tabledefs.test b/mysql-test/extra/rpl_tests/rpl_row_tabledefs.test index 0aabd633394..b17103d8396 100644 --- a/mysql-test/extra/rpl_tests/rpl_row_tabledefs.test +++ b/mysql-test/extra/rpl_tests/rpl_row_tabledefs.test @@ -3,7 +3,14 @@ # Consider making these part of the basic RBR tests. -connection slave; +connection master; +--disable_warnings +--disable_query_log +DROP TABLE IF EXISTS t1_int,t1_bit,t1_char,t1_nodef; +DROP TABLE IF EXISTS t2,t3,t4,t5,t6,t9; +--enable_query_log +--enable_warnings +sync_slave_with_master; STOP SLAVE; SET GLOBAL SQL_MODE='STRICT_ALL_TABLES'; START SLAVE; @@ -26,8 +33,12 @@ sync_slave_with_master; # On the slave, we add one INT column last in table 't1_int', ALTER TABLE t1_int ADD x INT DEFAULT 42; -# ... and add one BIT column last in table 't1_bit', -ALTER TABLE t1_bit ADD x BIT(3) DEFAULT b'011'; +# ... and add BIT columns last in table 't1_bit' to ensure that we +# have at least one extra null byte on the slave, +ALTER TABLE t1_bit + ADD x BIT(3) DEFAULT b'011', + ADD y BIT(5) DEFAULT b'10101', + ADD z BIT(2) DEFAULT b'10'; # ... and add one CHAR column last in table 't1_char', ALTER TABLE t1_char ADD x CHAR(20) DEFAULT 'Just a test'; # ... and add one non-nullable INT column last in table 't1_text' @@ -44,9 +55,9 @@ ALTER TABLE t6 MODIFY c FLOAT; # Insert some values for tables on slave side. These should not be # modified when the row from the master is applied. -INSERT INTO t1_int VALUES (2,4,4711); -INSERT INTO t1_char VALUES (2,4,'Foo is a bar'); -INSERT INTO t1_bit VALUES (2,4,b'101'); +INSERT INTO t1_int VALUES (2, 4, 4711); +INSERT INTO t1_char VALUES (2, 4, 'Foo is a bar'); +INSERT INTO t1_bit VALUES (2, 4, b'101', b'11100', b'01'); --echo **** On Master **** connection master; @@ -62,7 +73,21 @@ SELECT * FROM t1_char; --echo **** On Slave **** sync_slave_with_master; SELECT a,b,x FROM t1_int; -SELECT a,b,HEX(x) FROM t1_bit; +SELECT a,b,HEX(x),HEX(y),HEX(z) FROM t1_bit; +SELECT a,b,x FROM t1_char; + +--echo **** On Master **** +connection master; +UPDATE t1_int SET b=2*b WHERE a=2; +UPDATE t1_char SET b=2*b WHERE a=2; +UPDATE t1_bit SET b=2*b WHERE a=2; +SELECT * FROM t1_int; +SELECT * FROM t1_bit; +SELECT * FROM t1_char; +--echo **** On Slave **** +sync_slave_with_master; +SELECT a,b,x FROM t1_int; +SELECT a,b,HEX(x),HEX(y),HEX(z) FROM t1_bit; SELECT a,b,x FROM t1_char; # Each of these should generate an error and stop the slave @@ -76,9 +101,8 @@ INSERT INTO t1_nodef VALUES (1,2); connection slave; wait_for_slave_to_stop; --replace_result $MASTER_MYPORT MASTER_PORT ---replace_column 1 # 8 # 9 # 23 # 33 # ---vertical_results -SHOW SLAVE STATUS; +--replace_column 1 # 7 # 8 # 9 # 22 # 23 # 33 # +--query_vertical SHOW SLAVE STATUS SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; START SLAVE; @@ -91,9 +115,8 @@ INSERT INTO t2 VALUES (2,4); connection slave; wait_for_slave_to_stop; --replace_result $MASTER_MYPORT MASTER_PORT ---replace_column 1 # 8 # 9 # 23 # 33 # ---vertical_results -SHOW SLAVE STATUS; +--replace_column 1 # 7 # 8 # 9 # 22 # 23 # 33 # +--query_vertical SHOW SLAVE STATUS SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; START SLAVE; @@ -106,9 +129,8 @@ INSERT INTO t4 VALUES (4); connection slave; wait_for_slave_to_stop; --replace_result $MASTER_MYPORT MASTER_PORT ---replace_column 1 # 8 # 9 # 23 # 33 # ---vertical_results -SHOW SLAVE STATUS; +--replace_column 1 # 7 # 8 # 9 # 22 # 23 # 33 # +--query_vertical SHOW SLAVE STATUS SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; START SLAVE; @@ -121,9 +143,8 @@ INSERT INTO t5 VALUES (5,10,25); connection slave; wait_for_slave_to_stop; --replace_result $MASTER_MYPORT MASTER_PORT ---replace_column 1 # 8 # 9 # 23 # 33 # ---vertical_results -SHOW SLAVE STATUS; +--replace_column 1 # 7 # 8 # 9 # 22 # 23 # 33 # +--query_vertical SHOW SLAVE STATUS SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; START SLAVE; @@ -136,9 +157,8 @@ INSERT INTO t6 VALUES (6,12,36); connection slave; wait_for_slave_to_stop; --replace_result $MASTER_MYPORT MASTER_PORT ---replace_column 1 # 8 # 9 # 23 # 33 # ---vertical_results -SHOW SLAVE STATUS; +--replace_column 1 # 7 # 8 # 9 # 22 # 23 # 33 # +--query_vertical SHOW SLAVE STATUS SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; START SLAVE; diff --git a/mysql-test/r/rpl_row_tabledefs.result b/mysql-test/r/rpl_row_tabledefs_2myisam.result similarity index 84% rename from mysql-test/r/rpl_row_tabledefs.result rename to mysql-test/r/rpl_row_tabledefs_2myisam.result index 31a7330041f..37559b0412a 100644 --- a/mysql-test/r/rpl_row_tabledefs.result +++ b/mysql-test/r/rpl_row_tabledefs_2myisam.result @@ -18,16 +18,19 @@ CREATE TABLE t5 (a INT, b INT, c INT) ENGINE='MyISAM'; CREATE TABLE t6 (a INT, b INT, c INT) ENGINE='MyISAM'; CREATE TABLE t9 (a INT) ENGINE='MyISAM'; ALTER TABLE t1_int ADD x INT DEFAULT 42; -ALTER TABLE t1_bit ADD x BIT(3) DEFAULT b'011'; +ALTER TABLE t1_bit +ADD x BIT(3) DEFAULT b'011', +ADD y BIT(5) DEFAULT b'10101', +ADD z BIT(2) DEFAULT b'10'; ALTER TABLE t1_char ADD x CHAR(20) DEFAULT 'Just a test'; ALTER TABLE t1_nodef ADD x INT NOT NULL; ALTER TABLE t2 DROP b; ALTER TABLE t4 MODIFY a FLOAT; ALTER TABLE t5 MODIFY b FLOAT; ALTER TABLE t6 MODIFY c FLOAT; -INSERT INTO t1_int VALUES (2,4,4711); -INSERT INTO t1_char VALUES (2,4,'Foo is a bar'); -INSERT INTO t1_bit VALUES (2,4,b'101'); +INSERT INTO t1_int VALUES (2, 4, 4711); +INSERT INTO t1_char VALUES (2, 4, 'Foo is a bar'); +INSERT INTO t1_bit VALUES (2, 4, b'101', b'11100', b'01'); **** On Master **** INSERT INTO t1_int VALUES (1,2); INSERT INTO t1_int VALUES (2,5); @@ -52,14 +55,43 @@ SELECT a,b,x FROM t1_int; a b x 2 5 4711 1 2 42 -SELECT a,b,HEX(x) FROM t1_bit; -a b HEX(x) -2 5 5 -1 2 3 +SELECT a,b,HEX(x),HEX(y),HEX(z) FROM t1_bit; +a b HEX(x) HEX(y) HEX(z) +2 5 5 1C 1 +1 2 3 15 2 SELECT a,b,x FROM t1_char; a b x 2 5 Foo is a bar 1 2 Just a test +**** On Master **** +UPDATE t1_int SET b=2*b WHERE a=2; +UPDATE t1_char SET b=2*b WHERE a=2; +UPDATE t1_bit SET b=2*b WHERE a=2; +SELECT * FROM t1_int; +a b +1 2 +2 10 +SELECT * FROM t1_bit; +a b +1 2 +2 10 +SELECT * FROM t1_char; +a b +1 2 +2 10 +**** On Slave **** +SELECT a,b,x FROM t1_int; +a b x +2 10 4711 +1 2 42 +SELECT a,b,HEX(x),HEX(y),HEX(z) FROM t1_bit; +a b HEX(x) HEX(y) HEX(z) +2 10 5 1C 1 +1 2 3 15 2 +SELECT a,b,x FROM t1_char; +a b x +2 10 Foo is a bar +1 2 Just a test INSERT INTO t9 VALUES (2); INSERT INTO t1_nodef VALUES (1,2); SHOW SLAVE STATUS; @@ -69,7 +101,7 @@ Master_User root Master_Port MASTER_PORT Connect_Retry 1 Master_Log_File master-bin.000001 -Read_Master_Log_Pos 1934 +Read_Master_Log_Pos # Relay_Log_File # Relay_Log_Pos # Relay_Master_Log_File master-bin.000001 @@ -84,7 +116,7 @@ Replicate_Wild_Ignore_Table Last_Errno 1364 Last_Error Error in Write_rows event: error during transaction execution on table test.t1_nodef Skip_Counter 0 -Exec_Master_Log_Pos 1850 +Exec_Master_Log_Pos # Relay_Log_Space # Until_Condition None Until_Log_File @@ -107,7 +139,7 @@ Master_User root Master_Port MASTER_PORT Connect_Retry 1 Master_Log_File master-bin.000001 -Read_Master_Log_Pos 2085 +Read_Master_Log_Pos # Relay_Log_File # Relay_Log_Pos # Relay_Master_Log_File master-bin.000001 @@ -122,7 +154,7 @@ Replicate_Wild_Ignore_Table Last_Errno 1514 Last_Error Table width mismatch - received 2 columns, test.t2 has 1 columns Skip_Counter 0 -Exec_Master_Log_Pos 2007 +Exec_Master_Log_Pos # Relay_Log_Space # Until_Condition None Until_Log_File @@ -145,7 +177,7 @@ Master_User root Master_Port MASTER_PORT Connect_Retry 1 Master_Log_File master-bin.000001 -Read_Master_Log_Pos 2231 +Read_Master_Log_Pos # Relay_Log_File # Relay_Log_Pos # Relay_Master_Log_File master-bin.000001 @@ -160,7 +192,7 @@ Replicate_Wild_Ignore_Table Last_Errno 1514 Last_Error Column 0 type mismatch - received type 3, test.t4 has type 4 Skip_Counter 0 -Exec_Master_Log_Pos 2158 +Exec_Master_Log_Pos # Relay_Log_Space # Until_Condition None Until_Log_File @@ -183,7 +215,7 @@ Master_User root Master_Port MASTER_PORT Connect_Retry 1 Master_Log_File master-bin.000001 -Read_Master_Log_Pos 2387 +Read_Master_Log_Pos # Relay_Log_File # Relay_Log_Pos # Relay_Master_Log_File master-bin.000001 @@ -198,7 +230,7 @@ Replicate_Wild_Ignore_Table Last_Errno 1514 Last_Error Column 1 type mismatch - received type 3, test.t5 has type 4 Skip_Counter 0 -Exec_Master_Log_Pos 2304 +Exec_Master_Log_Pos # Relay_Log_Space # Until_Condition None Until_Log_File @@ -221,7 +253,7 @@ Master_User root Master_Port MASTER_PORT Connect_Retry 1 Master_Log_File master-bin.000001 -Read_Master_Log_Pos 2543 +Read_Master_Log_Pos # Relay_Log_File # Relay_Log_Pos # Relay_Master_Log_File master-bin.000001 @@ -236,7 +268,7 @@ Replicate_Wild_Ignore_Table Last_Errno 1514 Last_Error Column 2 type mismatch - received type 3, test.t6 has type 4 Skip_Counter 0 -Exec_Master_Log_Pos 2460 +Exec_Master_Log_Pos # Relay_Log_Space # Until_Condition None Until_Log_File diff --git a/mysql-test/r/rpl_row_tabledefs_3innodb.result b/mysql-test/r/rpl_row_tabledefs_3innodb.result new file mode 100644 index 00000000000..17f41850bc7 --- /dev/null +++ b/mysql-test/r/rpl_row_tabledefs_3innodb.result @@ -0,0 +1,286 @@ +stop slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +start slave; +STOP SLAVE; +SET GLOBAL SQL_MODE='STRICT_ALL_TABLES'; +START SLAVE; +CREATE TABLE t1_int (a INT PRIMARY KEY, b INT) ENGINE='InnoDB'; +CREATE TABLE t1_bit (a INT PRIMARY KEY, b INT) ENGINE='InnoDB'; +CREATE TABLE t1_char (a INT PRIMARY KEY, b INT) ENGINE='InnoDB'; +CREATE TABLE t1_nodef (a INT PRIMARY KEY, b INT) ENGINE='InnoDB'; +CREATE TABLE t2 (a INT PRIMARY KEY, b INT) ENGINE='InnoDB'; +CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE='InnoDB'; +CREATE TABLE t4 (a INT) ENGINE='InnoDB'; +CREATE TABLE t5 (a INT, b INT, c INT) ENGINE='InnoDB'; +CREATE TABLE t6 (a INT, b INT, c INT) ENGINE='InnoDB'; +CREATE TABLE t9 (a INT) ENGINE='InnoDB'; +ALTER TABLE t1_int ADD x INT DEFAULT 42; +ALTER TABLE t1_bit +ADD x BIT(3) DEFAULT b'011', +ADD y BIT(5) DEFAULT b'10101', +ADD z BIT(2) DEFAULT b'10'; +ALTER TABLE t1_char ADD x CHAR(20) DEFAULT 'Just a test'; +ALTER TABLE t1_nodef ADD x INT NOT NULL; +ALTER TABLE t2 DROP b; +ALTER TABLE t4 MODIFY a FLOAT; +ALTER TABLE t5 MODIFY b FLOAT; +ALTER TABLE t6 MODIFY c FLOAT; +INSERT INTO t1_int VALUES (2, 4, 4711); +INSERT INTO t1_char VALUES (2, 4, 'Foo is a bar'); +INSERT INTO t1_bit VALUES (2, 4, b'101', b'11100', b'01'); +**** On Master **** +INSERT INTO t1_int VALUES (1,2); +INSERT INTO t1_int VALUES (2,5); +INSERT INTO t1_bit VALUES (1,2); +INSERT INTO t1_bit VALUES (2,5); +INSERT INTO t1_char VALUES (1,2); +INSERT INTO t1_char VALUES (2,5); +SELECT * FROM t1_int; +a b +1 2 +2 5 +SELECT * FROM t1_bit; +a b +1 2 +2 5 +SELECT * FROM t1_char; +a b +1 2 +2 5 +**** On Slave **** +SELECT a,b,x FROM t1_int; +a b x +2 5 4711 +1 2 42 +SELECT a,b,HEX(x),HEX(y),HEX(z) FROM t1_bit; +a b HEX(x) HEX(y) HEX(z) +2 5 5 1C 1 +1 2 3 15 2 +SELECT a,b,x FROM t1_char; +a b x +2 5 Foo is a bar +1 2 Just a test +**** On Master **** +UPDATE t1_int SET b=2*b WHERE a=2; +UPDATE t1_char SET b=2*b WHERE a=2; +UPDATE t1_bit SET b=2*b WHERE a=2; +SELECT * FROM t1_int; +a b +1 2 +2 10 +SELECT * FROM t1_bit; +a b +1 2 +2 10 +SELECT * FROM t1_char; +a b +1 2 +2 10 +**** On Slave **** +SELECT a,b,x FROM t1_int; +a b x +2 10 4711 +1 2 42 +SELECT a,b,HEX(x),HEX(y),HEX(z) FROM t1_bit; +a b HEX(x) HEX(y) HEX(z) +2 10 5 1C 1 +1 2 3 15 2 +SELECT a,b,x FROM t1_char; +a b x +2 10 Foo is a bar +1 2 Just a test +INSERT INTO t9 VALUES (2); +INSERT INTO t1_nodef VALUES (1,2); +SHOW SLAVE STATUS; +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos # +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running No +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 1364 +Last_Error Error in Write_rows event: error during transaction execution on table test.t1_nodef +Skip_Counter 0 +Exec_Master_Log_Pos # +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; +START SLAVE; +INSERT INTO t9 VALUES (2); +INSERT INTO t2 VALUES (2,4); +SHOW SLAVE STATUS; +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos # +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running No +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 1514 +Last_Error Table width mismatch - received 2 columns, test.t2 has 1 columns +Skip_Counter 0 +Exec_Master_Log_Pos # +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; +START SLAVE; +INSERT INTO t9 VALUES (4); +INSERT INTO t4 VALUES (4); +SHOW SLAVE STATUS; +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos # +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running No +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 1514 +Last_Error Column 0 type mismatch - received type 3, test.t4 has type 4 +Skip_Counter 0 +Exec_Master_Log_Pos # +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; +START SLAVE; +INSERT INTO t9 VALUES (5); +INSERT INTO t5 VALUES (5,10,25); +SHOW SLAVE STATUS; +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos # +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running No +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 1514 +Last_Error Column 1 type mismatch - received type 3, test.t5 has type 4 +Skip_Counter 0 +Exec_Master_Log_Pos # +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; +START SLAVE; +INSERT INTO t9 VALUES (6); +INSERT INTO t6 VALUES (6,12,36); +SHOW SLAVE STATUS; +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos # +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running No +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 1514 +Last_Error Column 2 type mismatch - received type 3, test.t6 has type 4 +Skip_Counter 0 +Exec_Master_Log_Pos # +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; +START SLAVE; +DROP TABLE IF EXISTS t1_int,t1_bit,t1_char,t1_nodef; +DROP TABLE IF EXISTS t2,t3,t4,t5,t6,t9; diff --git a/mysql-test/r/rpl_row_tabledefs_7ndb.result b/mysql-test/r/rpl_row_tabledefs_7ndb.result new file mode 100644 index 00000000000..0d0da3b6185 --- /dev/null +++ b/mysql-test/r/rpl_row_tabledefs_7ndb.result @@ -0,0 +1,286 @@ +stop slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +start slave; +STOP SLAVE; +SET GLOBAL SQL_MODE='STRICT_ALL_TABLES'; +START SLAVE; +CREATE TABLE t1_int (a INT PRIMARY KEY, b INT) ENGINE='NDB'; +CREATE TABLE t1_bit (a INT PRIMARY KEY, b INT) ENGINE='NDB'; +CREATE TABLE t1_char (a INT PRIMARY KEY, b INT) ENGINE='NDB'; +CREATE TABLE t1_nodef (a INT PRIMARY KEY, b INT) ENGINE='NDB'; +CREATE TABLE t2 (a INT PRIMARY KEY, b INT) ENGINE='NDB'; +CREATE TABLE t3 (a INT PRIMARY KEY, b INT) ENGINE='NDB'; +CREATE TABLE t4 (a INT) ENGINE='NDB'; +CREATE TABLE t5 (a INT, b INT, c INT) ENGINE='NDB'; +CREATE TABLE t6 (a INT, b INT, c INT) ENGINE='NDB'; +CREATE TABLE t9 (a INT) ENGINE='NDB'; +ALTER TABLE t1_int ADD x INT DEFAULT 42; +ALTER TABLE t1_bit +ADD x BIT(3) DEFAULT b'011', +ADD y BIT(5) DEFAULT b'10101', +ADD z BIT(2) DEFAULT b'10'; +ALTER TABLE t1_char ADD x CHAR(20) DEFAULT 'Just a test'; +ALTER TABLE t1_nodef ADD x INT NOT NULL; +ALTER TABLE t2 DROP b; +ALTER TABLE t4 MODIFY a FLOAT; +ALTER TABLE t5 MODIFY b FLOAT; +ALTER TABLE t6 MODIFY c FLOAT; +INSERT INTO t1_int VALUES (2, 4, 4711); +INSERT INTO t1_char VALUES (2, 4, 'Foo is a bar'); +INSERT INTO t1_bit VALUES (2, 4, b'101', b'11100', b'01'); +**** On Master **** +INSERT INTO t1_int VALUES (1,2); +INSERT INTO t1_int VALUES (2,5); +INSERT INTO t1_bit VALUES (1,2); +INSERT INTO t1_bit VALUES (2,5); +INSERT INTO t1_char VALUES (1,2); +INSERT INTO t1_char VALUES (2,5); +SELECT * FROM t1_int; +a b +1 2 +2 5 +SELECT * FROM t1_bit; +a b +1 2 +2 5 +SELECT * FROM t1_char; +a b +1 2 +2 5 +**** On Slave **** +SELECT a,b,x FROM t1_int; +a b x +1 2 42 +2 5 42 +SELECT a,b,HEX(x),HEX(y),HEX(z) FROM t1_bit; +a b HEX(x) HEX(y) HEX(z) +1 2 3 15 2 +2 5 3 15 2 +SELECT a,b,x FROM t1_char; +a b x +1 2 Just a test +2 5 Just a test +**** On Master **** +UPDATE t1_int SET b=2*b WHERE a=2; +UPDATE t1_char SET b=2*b WHERE a=2; +UPDATE t1_bit SET b=2*b WHERE a=2; +SELECT * FROM t1_int; +a b +1 2 +2 10 +SELECT * FROM t1_bit; +a b +1 2 +2 10 +SELECT * FROM t1_char; +a b +1 2 +2 10 +**** On Slave **** +SELECT a,b,x FROM t1_int; +a b x +1 2 42 +2 10 42 +SELECT a,b,HEX(x),HEX(y),HEX(z) FROM t1_bit; +a b HEX(x) HEX(y) HEX(z) +1 2 3 15 2 +2 10 3 15 2 +SELECT a,b,x FROM t1_char; +a b x +1 2 Just a test +2 10 Just a test +INSERT INTO t9 VALUES (2); +INSERT INTO t1_nodef VALUES (1,2); +SHOW SLAVE STATUS; +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos # +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running No +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 1364 +Last_Error Error in Write_rows event: error during transaction execution on table test.t1_nodef +Skip_Counter 0 +Exec_Master_Log_Pos # +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; +START SLAVE; +INSERT INTO t9 VALUES (2); +INSERT INTO t2 VALUES (2,4); +SHOW SLAVE STATUS; +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos # +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running No +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 1514 +Last_Error Table width mismatch - received 2 columns, test.t2 has 1 columns +Skip_Counter 0 +Exec_Master_Log_Pos # +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; +START SLAVE; +INSERT INTO t9 VALUES (4); +INSERT INTO t4 VALUES (4); +SHOW SLAVE STATUS; +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos # +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running No +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 1514 +Last_Error Column 0 type mismatch - received type 3, test.t4 has type 4 +Skip_Counter 0 +Exec_Master_Log_Pos # +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; +START SLAVE; +INSERT INTO t9 VALUES (5); +INSERT INTO t5 VALUES (5,10,25); +SHOW SLAVE STATUS; +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos # +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running No +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 1514 +Last_Error Column 1 type mismatch - received type 3, test.t5 has type 4 +Skip_Counter 0 +Exec_Master_Log_Pos # +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; +START SLAVE; +INSERT INTO t9 VALUES (6); +INSERT INTO t6 VALUES (6,12,36); +SHOW SLAVE STATUS; +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos # +Relay_Log_File # +Relay_Log_Pos # +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running No +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 1514 +Last_Error Column 2 type mismatch - received type 3, test.t6 has type 4 +Skip_Counter 0 +Exec_Master_Log_Pos # +Relay_Log_Space # +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2; +START SLAVE; +DROP TABLE IF EXISTS t1_int,t1_bit,t1_char,t1_nodef; +DROP TABLE IF EXISTS t2,t3,t4,t5,t6,t9; diff --git a/mysql-test/t/rpl_row_tabledefs.test b/mysql-test/t/rpl_row_tabledefs_2myisam.test similarity index 100% rename from mysql-test/t/rpl_row_tabledefs.test rename to mysql-test/t/rpl_row_tabledefs_2myisam.test diff --git a/mysql-test/t/rpl_row_tabledefs_3innodb.test b/mysql-test/t/rpl_row_tabledefs_3innodb.test new file mode 100644 index 00000000000..7824fbfb663 --- /dev/null +++ b/mysql-test/t/rpl_row_tabledefs_3innodb.test @@ -0,0 +1,9 @@ + +-- source include/have_binlog_format_row.inc +-- source include/have_innodb.inc +-- source include/master-slave.inc + +let $engine_type = 'InnoDB'; +-- source extra/rpl_tests/rpl_row_tabledefs.test + + diff --git a/sql/field.cc b/sql/field.cc index 32e63597c30..3b841c74009 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -1237,6 +1237,14 @@ uint Field::offset() } +my_size_t +Field::do_last_null_byte() const +{ + DBUG_ASSERT(null_ptr == NULL || (byte*) null_ptr >= table->record[0]); + return null_ptr ? (byte*) null_ptr - table->record[0] + 1 : 0; +} + + void Field::copy_from_tmp(int row_offset) { memcpy(ptr,ptr+row_offset,pack_length()); @@ -8012,6 +8020,30 @@ Field_bit::Field_bit(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg, } +my_size_t +Field_bit::do_last_null_byte() const +{ + /* + Code elsewhere is assuming that bytes are 8 bits, so I'm using + that value instead of the correct one: CHAR_BIT. + + REFACTOR SUGGESTION (Matz): Change to use the correct number of + bits. On systems with CHAR_BIT > 8 (not very common), the storage + will lose the extra bits. + */ + DBUG_PRINT("debug", ("bit_ofs=%d, bit_len=%d, bit_ptr=%p", + bit_ofs, bit_len, bit_ptr)); + uchar *result; + if (bit_len == 0) + result= null_ptr; + else if (bit_ofs + bit_len > 8) + result= bit_ptr + 1; + else + result= bit_ptr; + + return result ? (byte*) result - table->record[0] + 1 : 0; +} + Field *Field_bit::new_key_field(MEM_ROOT *root, struct st_table *new_table, char *new_ptr, uchar *new_null_ptr, diff --git a/sql/field.h b/sql/field.h index d8dcb85fd5a..8f782400dcc 100644 --- a/sql/field.h +++ b/sql/field.h @@ -212,6 +212,19 @@ public: { if (null_ptr) null_ptr[row_offset]&= (uchar) ~null_bit; } inline bool maybe_null(void) { return null_ptr != 0 || table->maybe_null; } inline bool real_maybe_null(void) { return null_ptr != 0; } + + /* + Return a pointer to the last byte of the null bytes where the + field conceptually is placed. In the case that the field does not + use any bits of the null bytes, a null pointer is returned. + */ + my_size_t last_null_byte() const { + my_size_t bytes= do_last_null_byte(); + DBUG_PRINT("debug", ("last_null_byte() ==> %d", bytes)); + DBUG_ASSERT(bytes <= table->s->null_bytes); + return bytes; + } + virtual void make_field(Send_field *); virtual void sort_string(char *buff,uint length)=0; virtual bool optimize_range(uint idx, uint part); @@ -371,6 +384,9 @@ public: friend class Item_sum_min; friend class Item_sum_max; friend class Item_func_group_concat; + +private: + virtual my_size_t do_last_null_byte() const; }; @@ -1399,6 +1415,9 @@ public: Field::move_field_offset(ptr_diff); bit_ptr= ADD_TO_PTR(bit_ptr, ptr_diff, uchar*); } + +private: + virtual my_size_t do_last_null_byte() const; }; diff --git a/sql/log_event.cc b/sql/log_event.cc index 9991656c3eb..f62c6b5034f 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -5270,16 +5270,28 @@ int Rows_log_event::do_add_row_data(byte *const row_data, */ static int unpack_row(RELAY_LOG_INFO *rli, - TABLE *table, uint colcnt, byte *record, + TABLE *table, uint const colcnt, byte *record, char const *row, MY_BITMAP const *cols, char const **row_end, ulong *master_reclength) { DBUG_ASSERT(record && row); MY_BITMAP *write_set= table->file->write_set; - - my_size_t const n_null_bytes= table->s->null_bytes; my_ptrdiff_t const offset= record - (byte*) table->record[0]; - memcpy(record, row, n_null_bytes); // [1] + my_size_t master_null_bytes= table->s->null_bytes; + + if (colcnt != table->s->fields) + { + Field **fptr= &table->field[colcnt-1]; + do + master_null_bytes= (*fptr)->last_null_byte(); + while (master_null_bytes == 0 && fptr-- > table->field); + + if (master_null_bytes == 0) + master_null_bytes= table->s->null_bytes; + } + + DBUG_ASSERT(master_null_bytes <= table->s->null_bytes); + memcpy(record, row, master_null_bytes); // [1] int error= 0; bitmap_set_all(write_set); @@ -5287,14 +5299,12 @@ unpack_row(RELAY_LOG_INFO *rli, Field **const begin_ptr = table->field; Field **field_ptr; { - char const *ptr= row + n_null_bytes; - for (field_ptr= begin_ptr ; *field_ptr ; ++field_ptr) + char const *ptr= row + master_null_bytes; + Field **const end_ptr= begin_ptr + colcnt; + for (field_ptr= begin_ptr ; field_ptr < end_ptr ; ++field_ptr) { Field *const f= *field_ptr; - if (colcnt == 0) - break; - --colcnt; if (bitmap_is_set(cols, field_ptr - begin_ptr)) { /* Field...::unpack() cannot return 0 */ @@ -6190,7 +6200,7 @@ int Write_rows_log_event::do_prepare_row(THD *thd, RELAY_LOG_INFO *rli, int error; error= unpack_row(rli, - table, m_width, (byte*)table->record[0], + table, m_width, table->record[0], row_start, &m_cols, row_end, &m_master_reclength); #ifndef DBUG_OFF print_column_values("Unpacked value", thd, table); @@ -6241,6 +6251,79 @@ namespace { } +/* + Copy "extra" columns from record[1] to record[0]. + + Copy the extra fields that are not present on the master but are + present on the slave from record[1] to record[0]. This is used + after fetching a record that are to be updated, either inside + replace_record() or as part of executing an update_row(). + */ +static int +copy_extra_record_fields(TABLE *table, + my_size_t master_reclength, + my_ptrdiff_t master_fields) +{ + DBUG_PRINT("info", ("Copying to %p from field %d at offset %u to field %d at offset %u", + table->record[0], + master_fields, master_reclength, + table->s->fields, table->s->reclength)); + if (master_reclength < table->s->reclength) + bmove_align(table->record[0] + master_reclength, + table->record[1] + master_reclength, + table->s->reclength - master_reclength); + + /* + Bit columns are special. We iterate over all the remaining + columns and copy the "extra" bits to the new record. This is + not a very good solution: it should be refactored on + opportunity. + + REFACTORING SUGGESTION (Matz). Introduce a member function + similar to move_field_offset() called copy_field_offset() to + copy field values and implement it for all Field subclasses. Use + this function to copy data from the found record to the record + that are going to be inserted. + + The copy_field_offset() function need to be a virtual function, + which in this case will prevent copying an entire range of + fields efficiently. + */ + { + Field **field_ptr= table->field + master_fields; + for ( ; *field_ptr ; ++field_ptr) + { + /* + Set the null bit according to the values in record[1] + */ + if ((*field_ptr)->maybe_null() && + (*field_ptr)->is_null_in_record(reinterpret_cast(table->record[1]))) + (*field_ptr)->set_null(); + else + (*field_ptr)->set_notnull(); + + /* + Do the extra work for special columns. + */ + switch ((*field_ptr)->real_type()) + { + default: + /* Nothing to do */ + break; + + case FIELD_TYPE_BIT: + Field_bit *f= static_cast(*field_ptr); + my_ptrdiff_t const offset= table->record[1] - table->record[0]; + uchar const bits= + get_rec_bits(f->bit_ptr + offset, f->bit_ofs, f->bit_len); + set_rec_bits(bits, f->bit_ptr, f->bit_ofs, f->bit_len); + break; + } + } + } + return 0; // All OK +} + /* Replace the provided record in the database. @@ -6327,54 +6410,7 @@ replace_record(THD *thd, TABLE *table, First we copy the columns into table->record[0] that are not present on the master from table->record[1], if there are any. */ - - DBUG_PRINT("info", ("Copying to %p from offset %u to %u", - table->record[0], - master_reclength, table->s->reclength)); -#ifndef DBUG_OFF - print_column_values("After copy value", thd, table); -#endif - if (master_reclength < table->s->reclength) - bmove_align(table->record[0] + master_reclength, - table->record[1] + master_reclength, - table->s->reclength - master_reclength); - - /* - Bit columns are special. We iterate over all the remaining - columns and copy the "extra" bits to the new record. This is - not a very good solution: it should be refactored on - opportunity. - - REFACTORING SUGGESTION (Matz). Introduce a member function - similar to move_field_offset() called copy_field_offset() to - copy field values and implement it for all Field subclasses. Use - this function to copy data from the found record to the record - that are going to be inserted. - - The copy_field_offset() function need to be a virtual function, - which in this case will prevent copying an entire range of - fields efficiently. - */ - { - Field **field_ptr= table->field + master_fields; - for ( ; *field_ptr ; ++field_ptr) - { - switch ((*field_ptr)->real_type()) - { - default: - /* Nothing to do */ - break; - - case FIELD_TYPE_BIT: - Field_bit *f= static_cast(*field_ptr); - my_ptrdiff_t const offset= table->record[1] - table->record[0]; - uchar const bits= - get_rec_bits(f->bit_ptr + offset, f->bit_ofs, f->bit_len); - set_rec_bits(bits, f->bit_ptr, f->bit_ofs, f->bit_len); - break; - } - } - } + copy_extra_record_fields(table, master_reclength, master_fields); /* REPLACE is defined as either INSERT or DELETE + INSERT. If @@ -6887,17 +6923,20 @@ int Update_rows_log_event::do_exec_row(TABLE *table) example, the partition engine). Since find_and_fetch_row() puts the fetched record (i.e., the old - record) in record[0], we have to move it out of the way and into - record[1]. After that, we can put the new record (i.e., the after - image) into record[0]. + record) in record[1], we can keep it there. We put the new record + (i.e., the after image) into record[0], and copy the fields that + are on the slave (i.e., in record[1]) into record[0], effectively + overwriting the default values that where put there by the + unpack_row() function. */ - bmove_align(table->record[1], table->record[0], table->s->reclength); bmove_align(table->record[0], m_after_image, table->s->reclength); + copy_extra_record_fields(table, m_master_reclength, m_width); /* - Now we should have the right row to update. The old row (the one - we're looking for) has to be in record[1] and the new row has to - be in record[0] for all storage engines to work correctly. + Now we have the right row to update. The old row (the one we're + looking for) is in record[1] and the new row has is in record[0]. + We also have copied the original values already in the slave's + database into the after image delivered from the master. */ error= table->file->ha_update_row(table->record[1], table->record[0]); From 6129be9421c2801120a736fc1e4d5771567176d9 Mon Sep 17 00:00:00 2001 From: "guilhem@gbichot3.local" <> Date: Tue, 1 Aug 2006 12:23:02 +0200 Subject: [PATCH 04/27] I had forgotten to delete an already disabled line of C++ code. --- sql/sql_insert.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 25ed03c4051..6ea9246636e 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -2086,8 +2086,6 @@ bool delayed_insert::handle_inserts(void) thd.start_time=row->start_time; thd.query_start_used=row->query_start_used; - /* for the binlog, forget auto_increment ids generated by previous rows */ -// thd.auto_inc_intervals_in_cur_stmt_for_binlog.empty(); thd.first_successful_insert_id_in_prev_stmt= row->first_successful_insert_id_in_prev_stmt; thd.stmt_depends_on_first_successful_insert_id_in_prev_stmt= From 8597ebaed00e5ba789d8387877e67f0d0fd3e6ef Mon Sep 17 00:00:00 2001 From: "grog@eucla.lemis.com" <> Date: Wed, 2 Aug 2006 10:48:47 +0930 Subject: [PATCH 05/27] mysqldump.c: Tidy up style: no space before = or +=. --- client/mysqldump.c | 94 +++++++++++++++++++++++----------------------- 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/client/mysqldump.c b/client/mysqldump.c index 4318e4b9528..5b197499776 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -617,13 +617,13 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), tty_password=1; break; case 'r': - if (!(md_result_file = my_fopen(argument, O_WRONLY | FILE_BINARY, + if (!(md_result_file= my_fopen(argument, O_WRONLY | FILE_BINARY, MYF(MY_WME)))) exit(1); break; case 'W': #ifdef __WIN__ - opt_protocol = MYSQL_PROTOCOL_PIPE; + opt_protocol= MYSQL_PROTOCOL_PIPE; #endif break; case 'N': @@ -638,7 +638,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), #include case 'V': print_version(); exit(0); case 'X': - opt_xml = 1; + opt_xml= 1; extended_insert= opt_drop= opt_lock= opt_disable_keys= opt_autocommit= opt_create_db= 0; break; @@ -1404,7 +1404,7 @@ static uint get_table_structure(char *table, char *db, char *table_type, const char *insert_option; char name_buff[NAME_LEN+3],table_buff[NAME_LEN*2+3]; char table_buff2[NAME_LEN*2+3], query_buff[512]; - FILE *sql_file = md_result_file; + FILE *sql_file= md_result_file; int len; MYSQL_RES *result; MYSQL_ROW row; @@ -1451,7 +1451,7 @@ static uint get_table_structure(char *table, char *db, char *table_type, opt_quoted_table= quote_name(table, table_buff2, 0); if (opt_order_by_primary) - order_by = primary_key_fields(result_table); + order_by= primary_key_fields(result_table); if (!opt_xml && !mysql_query_with_error_report(sock, 0, query_buff)) { @@ -1503,7 +1503,7 @@ static uint get_table_structure(char *table, char *db, char *table_type, field= mysql_fetch_field_direct(result, 0); if (strcmp(field->name, "View") == 0) { - char *scv_buff = NULL; + char *scv_buff= NULL; if (verbose) fprintf(stderr, "-- It's a view, create dummy table for view\n"); @@ -1541,7 +1541,7 @@ static uint get_table_structure(char *table, char *db, char *table_type, my_free(scv_buff, MYF(MY_ALLOW_ZERO_PTR)); safe_exit(EX_MYSQLERR); - DBUG_RETURN(0); + DBUG_RETURN(0); } else my_free(scv_buff, MYF(MY_ALLOW_ZERO_PTR)); @@ -1909,7 +1909,7 @@ static void dump_triggers_for_table (char *table, char *db) char name_buff[NAME_LEN*4+3], table_buff[NAME_LEN*2+3]; char query_buff[512]; uint old_opt_compatible_mode=opt_compatible_mode; - FILE *sql_file = md_result_file; + FILE *sql_file= md_result_file; MYSQL_RES *result; MYSQL_ROW row; @@ -2160,15 +2160,15 @@ static void dump_table(char *table, char *db) end= strmov(end,buff); if (where || order_by) { - query = alloc_query_str((ulong) ((end - query) + 1 + + query= alloc_query_str((ulong) ((end - query) + 1 + (where ? strlen(where) + 7 : 0) + (order_by ? strlen(order_by) + 10 : 0))); - end = strmov(query, query_buf); + end= strmov(query, query_buf); if (where) - end = strxmov(end, " WHERE ", where, NullS); + end= strxmov(end, " WHERE ", where, NullS); if (order_by) - end = strxmov(end, " ORDER BY ", order_by, NullS); + end= strxmov(end, " ORDER BY ", order_by, NullS); } if (mysql_real_query(sock, query, (uint) (end - query))) { @@ -2189,10 +2189,10 @@ static void dump_table(char *table, char *db) result_table); if (where || order_by) { - query = alloc_query_str((ulong) (strlen(query) + 1 + + query= alloc_query_str((ulong) (strlen(query) + 1 + (where ? strlen(where) + 7 : 0) + (order_by ? strlen(order_by) + 10 : 0))); - end = strmov(query, query_buf); + end= strmov(query, query_buf); if (where) { @@ -2201,7 +2201,7 @@ static void dump_table(char *table, char *db) fprintf(md_result_file, "-- WHERE: %s\n", where); check_io(md_result_file); } - end = strxmov(end, " WHERE ", where, NullS); + end= strxmov(end, " WHERE ", where, NullS); } if (order_by) { @@ -2210,7 +2210,7 @@ static void dump_table(char *table, char *db) fprintf(md_result_file, "-- ORDER BY: %s\n", order_by); check_io(md_result_file); } - end = strxmov(end, " ORDER BY ", order_by, NullS); + end= strxmov(end, " ORDER BY ", order_by, NullS); } } if (!opt_xml && !opt_compact) @@ -2283,12 +2283,12 @@ static void dump_table(char *table, char *db) check_io(md_result_file); } - for (i = 0; i < mysql_num_fields(res); i++) + for (i= 0; i < mysql_num_fields(res); i++) { int is_blob; ulong length= lengths[i]; - if (!(field = mysql_fetch_field(res))) + if (!(field= mysql_fetch_field(res))) { my_snprintf(query, QUERY_LENGTH, "%s: Not enough fields from table %s! Aborting.\n", @@ -2360,7 +2360,7 @@ static void dump_table(char *table, char *db) else { /* change any strings ("inf", "-inf", "nan") into NULL */ - char *ptr = row[i]; + char *ptr= row[i]; if (my_isalpha(charset_info, *ptr) || (*ptr == '-' && my_isalpha(charset_info, ptr[1]))) dynstr_append(&extended_row, "NULL"); @@ -2420,7 +2420,7 @@ static void dump_table(char *table, char *db) else { /* change any strings ("inf", "-inf", "nan") into NULL */ - char *ptr = row[i]; + char *ptr= row[i]; if (opt_xml) { print_xml_tag1(md_result_file, "\t\t", "field name=", @@ -2466,10 +2466,10 @@ static void dump_table(char *table, char *db) { ulong row_length; dynstr_append(&extended_row,")"); - row_length = 2 + extended_row.length; + row_length= 2 + extended_row.length; if (total_length + row_length < opt_net_buffer_length) { - total_length += row_length; + total_length+= row_length; fputc(',',md_result_file); /* Always row break */ fputs(extended_row.str,md_result_file); } @@ -2481,7 +2481,7 @@ static void dump_table(char *table, char *db) fputs(insert_pat.str,md_result_file); fputs(extended_row.str,md_result_file); - total_length = row_length+init_length; + total_length= row_length+init_length; } check_io(md_result_file); } @@ -2546,15 +2546,15 @@ err: static char *getTableName(int reset) { - static MYSQL_RES *res = NULL; + static MYSQL_RES *res= NULL; MYSQL_ROW row; if (!res) { - if (!(res = mysql_list_tables(sock,NullS))) + if (!(res= mysql_list_tables(sock,NullS))) return(NULL); } - if ((row = mysql_fetch_row(res))) + if ((row= mysql_fetch_row(res))) return((char*) row[0]); if (reset) @@ -2562,7 +2562,7 @@ static char *getTableName(int reset) else { mysql_free_result(res); - res = NULL; + res= NULL; } return(NULL); } /* getTableName */ @@ -2576,7 +2576,7 @@ static int dump_all_databases() if (mysql_query_with_error_report(sock, &tableres, "SHOW DATABASES")) return 1; - while ((row = mysql_fetch_row(tableres))) + while ((row= mysql_fetch_row(tableres))) { if (dump_all_tables_in_db(row[0])) result=1; @@ -2584,13 +2584,13 @@ static int dump_all_databases() if (seen_views) { if (mysql_query(sock, "SHOW DATABASES") || - !(tableres = mysql_store_result(sock))) + !(tableres= mysql_store_result(sock))) { my_printf_error(0, "Error: Couldn't execute 'SHOW DATABASES': %s", MYF(0), mysql_error(sock)); return 1; } - while ((row = mysql_fetch_row(tableres))) + while ((row= mysql_fetch_row(tableres))) { if (dump_all_views_in_db(row[0])) result=1; @@ -2657,7 +2657,7 @@ static int init_dumping(char *database) "SHOW CREATE DATABASE IF NOT EXISTS %s", qdatabase); - if (mysql_query(sock, qbuf) || !(dbinfo = mysql_store_result(sock))) + if (mysql_query(sock, qbuf) || !(dbinfo= mysql_store_result(sock))) { /* Old server version, dump generic CREATE DATABASE */ if (opt_drop_database) @@ -2674,7 +2674,7 @@ static int init_dumping(char *database) fprintf(md_result_file, "\n/*!40000 DROP DATABASE IF EXISTS %s*/;\n", qdatabase); - row = mysql_fetch_row(dbinfo); + row= mysql_fetch_row(dbinfo); if (row[1]) { fprintf(md_result_file,"\n%s;\n",row[1]); @@ -2983,7 +2983,7 @@ static int do_show_master_status(MYSQL *mysql_con) } else { - row = mysql_fetch_row(master); + row= mysql_fetch_row(master); if (row && row[0] && row[1]) { /* SHOW MASTER STATUS reports file and position */ @@ -3110,7 +3110,7 @@ static void print_value(FILE *file, MYSQL_RES *result, MYSQL_ROW row, MYSQL_FIELD *field; mysql_field_seek(result, 0); - for ( ; (field = mysql_fetch_field(result)) ; row++) + for ( ; (field= mysql_fetch_field(result)) ; row++) { if (!strcmp(field->name,name)) { @@ -3239,17 +3239,17 @@ char check_if_ignore_table(const char *table_name, char *table_type) static char *primary_key_fields(const char *table_name) { - MYSQL_RES *res = NULL; + MYSQL_RES *res= NULL; MYSQL_ROW row; /* SHOW KEYS FROM + table name * 2 (escaped) + 2 quotes + \0 */ char show_keys_buff[15 + 64 * 2 + 3]; - uint result_length = 0; - char *result = 0; + uint result_length= 0; + char *result= 0; my_snprintf(show_keys_buff, sizeof(show_keys_buff), "SHOW KEYS FROM %s", table_name); if (mysql_query(sock, show_keys_buff) || - !(res = mysql_store_result(sock))) + !(res= mysql_store_result(sock))) { fprintf(stderr, "Warning: Couldn't read keys from table %s;" " records are NOT sorted (%s)\n", @@ -3264,12 +3264,12 @@ static char *primary_key_fields(const char *table_name) * row, and UNIQUE keys come before others. So we only need to check * the first key, not all keys. */ - if ((row = mysql_fetch_row(res)) && atoi(row[1]) == 0) + if ((row= mysql_fetch_row(res)) && atoi(row[1]) == 0) { /* Key is unique */ do - result_length += strlen(row[4]) + 1; /* + 1 for ',' or \0 */ - while ((row = mysql_fetch_row(res)) && atoi(row[3]) > 1); + result_length+= strlen(row[4]) + 1; /* + 1 for ',' or \0 */ + while ((row= mysql_fetch_row(res)) && atoi(row[3]) > 1); } /* Build the ORDER BY clause result */ @@ -3277,17 +3277,17 @@ static char *primary_key_fields(const char *table_name) { char *end; /* result (terminating \0 is already in result_length) */ - result = my_malloc(result_length + 10, MYF(MY_WME)); + result= my_malloc(result_length + 10, MYF(MY_WME)); if (!result) { fprintf(stderr, "Error: Not enough memory to store ORDER BY clause\n"); goto cleanup; } mysql_data_seek(res, 0); - row = mysql_fetch_row(res); - end = strmov(result, row[4]); - while ((row = mysql_fetch_row(res)) && atoi(row[3]) > 1) - end = strxmov(end, ",", row[4], NullS); + row= mysql_fetch_row(res); + end= strmov(result, row[4]); + while ((row= mysql_fetch_row(res)) && atoi(row[3]) > 1) + end= strxmov(end, ",", row[4], NullS); } cleanup: @@ -3355,7 +3355,7 @@ static my_bool get_view_structure(char *table, char* db) char table_buff[NAME_LEN*2+3]; char table_buff2[NAME_LEN*2+3]; char query[QUERY_LENGTH]; - FILE *sql_file = md_result_file; + FILE *sql_file= md_result_file; DBUG_ENTER("get_view_structure"); if (tFlag) /* Don't write table creation info */ From 90c9c72605c561fb0ef2b040f7660b8bcc5d28e1 Mon Sep 17 00:00:00 2001 From: "grog@eucla.lemis.com" <> Date: Wed, 2 Aug 2006 11:26:08 +0930 Subject: [PATCH 06/27] BUG#13926: --order-by-primary fails if PKEY contains quote character. Quote PKEY. --- client/mysqldump.c | 16 ++++++-- mysql-test/r/mysqldump.result | 71 +++++++++++++++++++++++++++++++++++ mysql-test/t/mysqldump.test | 20 ++++++++++ 3 files changed, 103 insertions(+), 4 deletions(-) diff --git a/client/mysqldump.c b/client/mysqldump.c index 5b197499776..f8f95ca7fd8 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -3245,6 +3245,8 @@ static char *primary_key_fields(const char *table_name) char show_keys_buff[15 + 64 * 2 + 3]; uint result_length= 0; char *result= 0; + char buff[NAME_LEN * 2 + 3]; + char *quoted_field; my_snprintf(show_keys_buff, sizeof(show_keys_buff), "SHOW KEYS FROM %s", table_name); @@ -3268,8 +3270,10 @@ static char *primary_key_fields(const char *table_name) { /* Key is unique */ do - result_length+= strlen(row[4]) + 1; /* + 1 for ',' or \0 */ - while ((row= mysql_fetch_row(res)) && atoi(row[3]) > 1); + { + quoted_field= quote_name(row[4], buff, 0); + result_length+= strlen(quoted_field) + 1; /* + 1 for ',' or \0 */ + } while ((row= mysql_fetch_row(res)) && atoi(row[3]) > 1); } /* Build the ORDER BY clause result */ @@ -3285,9 +3289,13 @@ static char *primary_key_fields(const char *table_name) } mysql_data_seek(res, 0); row= mysql_fetch_row(res); - end= strmov(result, row[4]); + quoted_field= quote_name(row[4], buff, 0); + end= strmov(result, quoted_field); while ((row= mysql_fetch_row(res)) && atoi(row[3]) > 1) - end= strxmov(end, ",", row[4], NullS); + { + quoted_field= quote_name(row[4], buff, 0); + end= strxmov(end, ",", quoted_field, NullS); + } } cleanup: diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result index 118079906bf..b2a01bde10f 100644 --- a/mysql-test/r/mysqldump.result +++ b/mysql-test/r/mysqldump.result @@ -2867,3 +2867,74 @@ drop view nasishnasifu; drop database mysqldump_views; drop table mysqldump_tables.basetable; drop database mysqldump_tables; +USE test; +DROP TABLE IF EXISTS `t1`; +CREATE TABLE `t1` ( +`a b` INT, +`c"d` INT, +`e``f` INT, +PRIMARY KEY (`a b`, `c"d`, `e``f`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +insert into t1 values (0815, 4711, 2006); +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO,ANSI' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; +DROP TABLE IF EXISTS "t1"; +CREATE TABLE "t1" ( + "a b" int(11) NOT NULL default '0', + "c""d" int(11) NOT NULL default '0', + "e`f" int(11) NOT NULL default '0', + PRIMARY KEY ("a b","c""d","e`f") +); + +LOCK TABLES "t1" WRITE; +/*!40000 ALTER TABLE "t1" DISABLE KEYS */; +INSERT INTO "t1" VALUES (815,4711,2006); +/*!40000 ALTER TABLE "t1" ENABLE KEYS */; +UNLOCK TABLES; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; +DROP TABLE IF EXISTS `t1`; +CREATE TABLE `t1` ( + `a b` int(11) NOT NULL default '0', + `c"d` int(11) NOT NULL default '0', + `e``f` int(11) NOT NULL default '0', + PRIMARY KEY (`a b`,`c"d`,`e``f`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; + +LOCK TABLES `t1` WRITE; +/*!40000 ALTER TABLE `t1` DISABLE KEYS */; +INSERT INTO `t1` VALUES (815,4711,2006); +/*!40000 ALTER TABLE `t1` ENABLE KEYS */; +UNLOCK TABLES; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +DROP TABLE `t1`; +End of 5.0 tests diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test index 858d8910781..a0060863959 100644 --- a/mysql-test/t/mysqldump.test +++ b/mysql-test/t/mysqldump.test @@ -1228,3 +1228,23 @@ drop view nasishnasifu; drop database mysqldump_views; drop table mysqldump_tables.basetable; drop database mysqldump_tables; +USE test; + +# +# BUG#13926: --order-by-primary fails if PKEY contains quote character +# +--disable_warnings +DROP TABLE IF EXISTS `t1`; +CREATE TABLE `t1` ( + `a b` INT, + `c"d` INT, + `e``f` INT, + PRIMARY KEY (`a b`, `c"d`, `e``f`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +insert into t1 values (0815, 4711, 2006); + +--exec $MYSQL_DUMP --skip-comments --compatible=ansi --order-by-primary test t1 +--exec $MYSQL_DUMP --skip-comments --order-by-primary test t1 +DROP TABLE `t1`; +--enable_warnings +--echo End of 5.0 tests From 691355b6a30d772bedfee90953ca3ec00d50cd29 Mon Sep 17 00:00:00 2001 From: "mats@romeo.(none)" <> Date: Wed, 16 Aug 2006 14:55:57 +0200 Subject: [PATCH 07/27] BUG#20863 (if binlog format is changed between update and unlock table, wrong binlogging): Fix to allow the binlog format to be changed between the LOCK and UNLOCK tables, as well as under MIXED mode. --- mysql-test/r/rpl_switch_stm_row_mixed.result | 35 ++++++++++++++--- mysql-test/t/rpl_switch_stm_row_mixed.test | 33 +++++++++++++++- sql/log.cc | 2 +- sql/sql_class.cc | 40 ++++++++++---------- 4 files changed, 83 insertions(+), 27 deletions(-) diff --git a/mysql-test/r/rpl_switch_stm_row_mixed.result b/mysql-test/r/rpl_switch_stm_row_mixed.result index 313037bb9dc..e23749dc402 100644 --- a/mysql-test/r/rpl_switch_stm_row_mixed.result +++ b/mysql-test/r/rpl_switch_stm_row_mixed.result @@ -7,6 +7,8 @@ start slave; drop database if exists mysqltest1; create database mysqltest1; use mysqltest1; +set session binlog_format=row; +set global binlog_format=row; show global variables like "binlog_format%"; Variable_name Value binlog_format ROW @@ -157,11 +159,29 @@ count(*) select count(*) from t5; count(*) 58 +SET SESSION BINLOG_FORMAT=STATEMENT; +CREATE TABLE t11 (song VARCHAR(255)); +LOCK TABLES t11 WRITE; +SET SESSION BINLOG_FORMAT=ROW; +INSERT INTO t11 VALUES('Several Species of Small Furry Animals Gathered Together in a Cave and Grooving With a Pict'); +SET SESSION BINLOG_FORMAT=STATEMENT; +INSERT INTO t11 VALUES('Careful With That Axe, Eugene'); +UNLOCK TABLES; +SELECT * FROM t11; +song Several Species of Small Furry Animals Gathered Together in a Cave and Grooving With a Pict +song Careful With That Axe, Eugene +USE mysqltest1; +SELECT * FROM t11; +song Several Species of Small Furry Animals Gathered Together in a Cave and Grooving With a Pict +song Careful With That Axe, Eugene +SET SESSION BINLOG_FORMAT=MIXED; +CREATE TABLE t12 (data LONG); +LOCK TABLES t12 WRITE; +INSERT INTO t12 VALUES(UUID()); +UNLOCK TABLES; show binlog events from 102; Log_name Pos Event_type Server_id End_log_pos Info master-bin.000001 # Query 1 # drop database if exists mysqltest1 -master-bin.000001 # Table_map 1 # table_id: # (mysql.proc) -master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F master-bin.000001 # Query 1 # create database mysqltest1 master-bin.000001 # Query 1 # use `mysqltest1`; CREATE TABLE t1 (a varchar(100)) master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) @@ -178,10 +198,6 @@ master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) -master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F -master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) -master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("work") master-bin.000001 # User var 1 # @`string`=_latin1 0x656D657267656E6379 COLLATE latin1_swedish_ci master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select @'string' @@ -269,4 +285,11 @@ master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Query 1 # use `mysqltest1`; CREATE TABLE t11 (song VARCHAR(255)) +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t11) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Query 1 # use `mysqltest1`; INSERT INTO t11 VALUES('Careful With That Axe, Eugene') +master-bin.000001 # Query 1 # use `mysqltest1`; CREATE TABLE t12 (data LONG) +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t12) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F drop database mysqltest1; diff --git a/mysql-test/t/rpl_switch_stm_row_mixed.test b/mysql-test/t/rpl_switch_stm_row_mixed.test index 4a79b3995c4..8afc1ea37cf 100644 --- a/mysql-test/t/rpl_switch_stm_row_mixed.test +++ b/mysql-test/t/rpl_switch_stm_row_mixed.test @@ -1,4 +1,4 @@ --- source include/have_binlog_format_row.inc +-- source include/have_row_based.inc -- source include/master-slave.inc connection master; @@ -8,6 +8,9 @@ create database mysqltest1; --enable_warnings use mysqltest1; +set session binlog_format=row; +set global binlog_format=row; + show global variables like "binlog_format%"; show session variables like "binlog_format%"; select @@global.binlog_format, @@session.binlog_format; @@ -196,10 +199,38 @@ if ($you_want_to_test_UDF) select count(*) from t9; } +# +# Bug#20863 If binlog format is changed between update and unlock of +# tables, wrong binlog +# + +connection master; +SET SESSION BINLOG_FORMAT=STATEMENT; +CREATE TABLE t11 (song VARCHAR(255)); +LOCK TABLES t11 WRITE; +SET SESSION BINLOG_FORMAT=ROW; +INSERT INTO t11 VALUES('Several Species of Small Furry Animals Gathered Together in a Cave and Grooving With a Pict'); +SET SESSION BINLOG_FORMAT=STATEMENT; +INSERT INTO t11 VALUES('Careful With That Axe, Eugene'); +UNLOCK TABLES; + +--query_vertical SELECT * FROM t11 +sync_slave_with_master; +USE mysqltest1; +--query_vertical SELECT * FROM t11 + +connection master; +SET SESSION BINLOG_FORMAT=MIXED; +CREATE TABLE t12 (data LONG); +LOCK TABLES t12 WRITE; +INSERT INTO t12 VALUES(UUID()); +UNLOCK TABLES; + --replace_column 2 # 5 # --replace_regex /table_id: [0-9]+/table_id: #/ show binlog events from 102; sync_slave_with_master; + # as we're using UUID we don't SELECT but use "diff" like in rpl_row_UUID --exec $MYSQL_DUMP --compact --order-by-primary --skip-extended-insert --no-create-info mysqltest1 > $MYSQLTEST_VARDIR/tmp/rpl_switch_stm_row_mixed_master.sql --exec $MYSQL_DUMP_SLAVE --compact --order-by-primary --skip-extended-insert --no-create-info mysqltest1 > $MYSQLTEST_VARDIR/tmp/rpl_switch_stm_row_mixed_slave.sql diff --git a/sql/log.cc b/sql/log.cc index ec73400ea3c..b8b0d05b9dc 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -3153,7 +3153,7 @@ int MYSQL_BIN_LOG:: flush_and_set_pending_rows_event(THD *thd, Rows_log_event* event) { DBUG_ENTER("MYSQL_BIN_LOG::flush_and_set_pending_rows_event(event)"); - DBUG_ASSERT(thd->current_stmt_binlog_row_based && mysql_bin_log.is_open()); + DBUG_ASSERT(mysql_bin_log.is_open()); DBUG_PRINT("enter", ("event=%p", event)); int error= 0; diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 285a1e72f6f..8cea6023cf7 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -2649,7 +2649,12 @@ int THD::binlog_delete_row(TABLE* table, bool is_trans, int THD::binlog_flush_pending_rows_event(bool stmt_end) { DBUG_ENTER("THD::binlog_flush_pending_rows_event"); - if (!current_stmt_binlog_row_based || !mysql_bin_log.is_open()) + /* + We shall flush the pending event even if we are not in row-based + mode: it might be the case that we left row-based mode before + flushing anything (e.g., if we have explicitly locked tables). + */ + if (!mysql_bin_log.is_open()) DBUG_RETURN(0); /* @@ -2715,6 +2720,21 @@ int THD::binlog_query(THD::enum_binlog_query_type qtype, DBUG_PRINT("enter", ("qtype=%d, query='%s'", qtype, query)); DBUG_ASSERT(query && mysql_bin_log.is_open()); + /* + If we are not in prelocked mode, mysql_unlock_tables() will be + called after this binlog_query(), so we have to flush the pending + rows event with the STMT_END_F set to unlock all tables at the + slave side as well. + + If we are in prelocked mode, the flushing will be done inside the + top-most close_thread_tables(). + */ +#ifdef HAVE_ROW_BASED_REPLICATION + if (this->prelocked_mode == NON_PRELOCKED) + if (int error= binlog_flush_pending_rows_event(TRUE)) + DBUG_RETURN(error); +#endif /*HAVE_ROW_BASED_REPLICATION*/ + switch (qtype) { case THD::MYSQL_QUERY_TYPE: /* @@ -2728,25 +2748,7 @@ int THD::binlog_query(THD::enum_binlog_query_type qtype, case THD::ROW_QUERY_TYPE: #ifdef HAVE_ROW_BASED_REPLICATION if (current_stmt_binlog_row_based) - { - /* - If thd->lock is set, then we are not inside a stored function. - In that case, mysql_unlock_tables() will be called after this - binlog_query(), so we have to flush the pending rows event - with the STMT_END_F set to unlock all tables at the slave side - as well. - - We will not flush the pending event, if thd->lock is NULL. - This means that we are inside a stored function or trigger, so - the flushing will be done inside the top-most - close_thread_tables(). - */ -#ifdef HAVE_ROW_BASED_REPLICATION - if (this->lock) - DBUG_RETURN(binlog_flush_pending_rows_event(TRUE)); -#endif /*HAVE_ROW_BASED_REPLICATION*/ DBUG_RETURN(0); - } #endif /* Otherwise, we fall through */ case THD::STMT_QUERY_TYPE: From a6461a64e41423bd3c7bf46a3d12ddaf473fdcda Mon Sep 17 00:00:00 2001 From: "mats@romeo.(none)" <> Date: Thu, 17 Aug 2006 09:31:46 +0200 Subject: [PATCH 08/27] BUG#20863 (if binlog format is changed between update and unlock of table, wrong binlog): Post-merge fixes. --- mysql-test/r/rpl_switch_stm_row_mixed.result | 368 +++++++++++++++++-- mysql-test/t/rpl_switch_stm_row_mixed.test | 4 + 2 files changed, 345 insertions(+), 27 deletions(-) diff --git a/mysql-test/r/rpl_switch_stm_row_mixed.result b/mysql-test/r/rpl_switch_stm_row_mixed.result index cb31301bcd3..f0afc6bf34d 100644 --- a/mysql-test/r/rpl_switch_stm_row_mixed.result +++ b/mysql-test/r/rpl_switch_stm_row_mixed.result @@ -336,26 +336,6 @@ count(*) select count(*) from t5; count(*) 58 -SET SESSION BINLOG_FORMAT=STATEMENT; -CREATE TABLE t11 (song VARCHAR(255)); -LOCK TABLES t11 WRITE; -SET SESSION BINLOG_FORMAT=ROW; -INSERT INTO t11 VALUES('Several Species of Small Furry Animals Gathered Together in a Cave and Grooving With a Pict'); -SET SESSION BINLOG_FORMAT=STATEMENT; -INSERT INTO t11 VALUES('Careful With That Axe, Eugene'); -UNLOCK TABLES; -SELECT * FROM t11; -song Several Species of Small Furry Animals Gathered Together in a Cave and Grooving With a Pict -song Careful With That Axe, Eugene -USE mysqltest1; -SELECT * FROM t11; -song Several Species of Small Furry Animals Gathered Together in a Cave and Grooving With a Pict -song Careful With That Axe, Eugene -SET SESSION BINLOG_FORMAT=MIXED; -CREATE TABLE t12 (data LONG); -LOCK TABLES t12 WRITE; -INSERT INTO t12 VALUES(UUID()); -UNLOCK TABLES; select count(*) from t11; count(*) 8 @@ -380,6 +360,28 @@ count(*) select count(*) from t16; count(*) 3 +DROP TABLE IF EXISTS t11; +SET SESSION BINLOG_FORMAT=STATEMENT; +CREATE TABLE t11 (song VARCHAR(255)); +LOCK TABLES t11 WRITE; +SET SESSION BINLOG_FORMAT=ROW; +INSERT INTO t11 VALUES('Several Species of Small Furry Animals Gathered Together in a Cave and Grooving With a Pict'); +SET SESSION BINLOG_FORMAT=STATEMENT; +INSERT INTO t11 VALUES('Careful With That Axe, Eugene'); +UNLOCK TABLES; +SELECT * FROM t11; +song Several Species of Small Furry Animals Gathered Together in a Cave and Grooving With a Pict +song Careful With That Axe, Eugene +USE mysqltest1; +SELECT * FROM t11; +song Several Species of Small Furry Animals Gathered Together in a Cave and Grooving With a Pict +song Careful With That Axe, Eugene +DROP TABLE IF EXISTS t12; +SET SESSION BINLOG_FORMAT=MIXED; +CREATE TABLE t12 (data LONG); +LOCK TABLES t12 WRITE; +INSERT INTO t12 VALUES(UUID()); +UNLOCK TABLES; show binlog events from 102; Log_name Pos Event_type Server_id End_log_pos Info master-bin.000001 # Query 1 # drop database if exists mysqltest1 @@ -485,13 +487,6 @@ master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F -master-bin.000001 # Query 1 # use `mysqltest1`; CREATE TABLE t11 (song VARCHAR(255)) -master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t11) -master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F -master-bin.000001 # Query 1 # use `mysqltest1`; INSERT INTO t11 VALUES('Careful With That Axe, Eugene') -master-bin.000001 # Query 1 # use `mysqltest1`; CREATE TABLE t12 (data LONG) -master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t12) -master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) @@ -688,4 +683,323 @@ master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t16) master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F master-bin.000001 # Query 1 # use `mysqltest1`; insert into t16 values("try_66_") +master-bin.000001 # Query 1 # use `mysqltest1`; DROP TABLE IF EXISTS t11 +master-bin.000001 # Query 1 # use `mysqltest1`; CREATE TABLE t11 (song VARCHAR(255)) +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t11) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Query 1 # use `mysqltest1`; INSERT INTO t11 VALUES('Careful With That Axe, Eugene') +master-bin.000001 # Query 1 # use `mysqltest1`; DROP TABLE IF EXISTS t12 +master-bin.000001 # Query 1 # use `mysqltest1`; CREATE TABLE t12 (data LONG) +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t12) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +show binlog events from 102; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query 1 # drop database if exists mysqltest1 +master-bin.000001 # Query 1 # create database mysqltest1 +master-bin.000001 # Query 1 # use `mysqltest1`; CREATE TABLE t1 (a varchar(100)) +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("work_8_") +master-bin.000001 # User var 1 # @`string`=_latin1 0x656D657267656E63795F375F COLLATE latin1_swedish_ci +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select @'string' +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("work_9_") +master-bin.000001 # User var 1 # @`string`=_latin1 0x656D657267656E63795F375F COLLATE latin1_swedish_ci +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select @'string' +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("for_10_") +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select "yesterday_11_" +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("work_13_") +master-bin.000001 # User var 1 # @`string`=_latin1 0x656D657267656E63795F31325F COLLATE latin1_swedish_ci +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select @'string' +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("work_14_") +master-bin.000001 # User var 1 # @`string`=_latin1 0x656D657267656E63795F31325F COLLATE latin1_swedish_ci +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select @'string' +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("for_15_") +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select "yesterday_16_" +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("work_18_") +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # User var 1 # @`string`=_latin1 0x656D657267656E63795F31375F COLLATE latin1_swedish_ci +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select @'string' +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select "yesterday_21_" +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # User var 1 # @`string`=_latin1 0x656D657267656E63795F31375F COLLATE latin1_swedish_ci +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select @'string' +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select "yesterday_24_" +master-bin.000001 # Query 1 # use `mysqltest1`; CREATE TABLE `t2` ( + `rpad(UUID(),100,' ')` varchar(100) CHARACTER SET utf8 NOT NULL DEFAULT '' +) +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Query 1 # use `mysqltest1`; CREATE TABLE `t3` ( + `1` varbinary(108) NOT NULL DEFAULT '' +) +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t3) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Query 1 # use `mysqltest1`; CREATE TABLE `t4` ( + `a` varchar(100) DEFAULT NULL +) +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t4) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Query 1 # use `mysqltest1`; create table t5 select * from t1 where 3 in (select 1 union select 2 union select curdate() union select 3) +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t5) +master-bin.000001 # Write_rows 1 # table_id: # +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` procedure foo() +begin +insert into t1 values("work_25_"); +insert into t1 values(concat("for_26_",UUID())); +insert into t1 select "yesterday_27_"; +end +master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` procedure foo2() +begin +insert into t1 values(concat("emergency_28_",UUID())); +insert into t1 values("work_29_"); +insert into t1 values(concat("for_30_",UUID())); +set session binlog_format=row; # accepted for stored procs +insert into t1 values("more work_31_"); +set session binlog_format=mixed; +end +master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` function foo3() returns bigint unsigned +begin +set session binlog_format=row; # rejected for stored funcs +insert into t1 values("alarm"); +return 100; +end +master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` procedure foo4(x varchar(100)) +begin +insert into t1 values(concat("work_250_",x)); +insert into t1 select "yesterday_270_"; +end +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values(concat("work_250_", NAME_CONST('x',_latin1'hello'))) +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select "yesterday_270_" +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values(concat("work_250_", NAME_CONST('x',_latin1'world'))) +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select "yesterday_270_" +master-bin.000001 # Query 1 # use `mysqltest1`; drop function foo3 +master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` function foo3() returns bigint unsigned +begin +insert into t1 values("foo3_32_"); +call foo(); +return 100; +end +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2) +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) +master-bin.000001 # Write_rows 1 # table_id: # +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2) +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) +master-bin.000001 # Write_rows 1 # table_id: # +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2) +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) +master-bin.000001 # Write_rows 1 # table_id: # +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` function foo4() returns bigint unsigned +begin +insert into t2 select foo3(); +return 100; +end +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2) +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) +master-bin.000001 # Write_rows 1 # table_id: # +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2) +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) +master-bin.000001 # Write_rows 1 # table_id: # +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2) +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) +master-bin.000001 # Write_rows 1 # table_id: # +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` function foo5() returns bigint unsigned +begin +insert into t2 select UUID(); +return 100; +end +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` function foo6(x varchar(100)) returns bigint unsigned +begin +insert into t2 select x; +return 100; +end +master-bin.000001 # Query 1 # use `mysqltest1`; SELECT `foo6`(_latin1'foo6_1_') +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Query 1 # use `mysqltest1`; CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select uuid() +master-bin.000001 # Query 1 # use `mysqltest1`; create table t11 (data varchar(255)) +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t11) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t11 select TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA='mysqltest1' and TABLE_NAME IN ('v1','t11') +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t11 select TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA='mysqltest1' and TABLE_NAME IN ('v1','t11') +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t11 select TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA='mysqltest1' and TABLE_NAME IN ('v1','t11') +master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` trigger t11_bi before insert on t11 for each row +begin +set NEW.data = concat(NEW.data,UUID()); +end +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t11) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Query 1 # use `mysqltest1`; create table t20 select * from t1 +master-bin.000001 # Query 1 # use `mysqltest1`; create table t21 select * from t2 +master-bin.000001 # Query 1 # use `mysqltest1`; create table t22 select * from t3 +master-bin.000001 # Query 1 # use `mysqltest1`; drop table t1,t2,t3 +master-bin.000001 # Query 1 # use `mysqltest1`; create table t1 (a int primary key auto_increment, b varchar(100)) +master-bin.000001 # Query 1 # use `mysqltest1`; create table t2 (a int primary key auto_increment, b varchar(100)) +master-bin.000001 # Query 1 # use `mysqltest1`; create table t3 (b varchar(100)) +master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` function f (x varchar(100)) returns int deterministic +begin +insert into t1 values(null,x); +insert into t2 values(null,x); +return 1; +end +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2) +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) +master-bin.000001 # Write_rows 1 # table_id: # +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2) +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) +master-bin.000001 # Write_rows 1 # table_id: # +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Intvar 1 # INSERT_ID=3 +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values(null,"try_44_") +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2) +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) +master-bin.000001 # Write_rows 1 # table_id: # +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Query 1 # use `mysqltest1`; create table t12 select * from t1 +master-bin.000001 # Query 1 # use `mysqltest1`; drop table t1 +master-bin.000001 # Query 1 # use `mysqltest1`; create table t1 (a int, b varchar(100), key(a)) +master-bin.000001 # Intvar 1 # INSERT_ID=4 +master-bin.000001 # Query 1 # use `mysqltest1`; SELECT `f`(_latin1'try_45_') +master-bin.000001 # Query 1 # use `mysqltest1`; create table t13 select * from t1 +master-bin.000001 # Query 1 # use `mysqltest1`; drop table t1 +master-bin.000001 # Query 1 # use `mysqltest1`; create table t1 (a int primary key auto_increment, b varchar(100)) +master-bin.000001 # Query 1 # use `mysqltest1`; drop function f +master-bin.000001 # Query 1 # use `mysqltest1`; create table t14 (unique (a)) select * from t2 +master-bin.000001 # Query 1 # use `mysqltest1`; truncate table t2 +master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` function f1 (x varchar(100)) returns int deterministic +begin +insert into t1 values(null,x); +return 1; +end +master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` function f2 (x varchar(100)) returns int deterministic +begin +insert into t2 values(null,x); +return 1; +end +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2) +master-bin.000001 # Write_rows 1 # table_id: # +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2) +master-bin.000001 # Write_rows 1 # table_id: # +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t3) +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2) +master-bin.000001 # Write_rows 1 # table_id: # +master-bin.000001 # Write_rows 1 # table_id: # +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Query 1 # use `mysqltest1`; drop function f2 +master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` function f2 (x varchar(100)) returns int deterministic +begin +declare y int; +insert into t1 values(null,x); +set y = (select count(*) from t2); +return y; +end +master-bin.000001 # Intvar 1 # INSERT_ID=4 +master-bin.000001 # Query 1 # use `mysqltest1`; SELECT `f1`(_latin1'try_53_') +master-bin.000001 # Intvar 1 # INSERT_ID=5 +master-bin.000001 # Query 1 # use `mysqltest1`; SELECT `f2`(_latin1'try_54_') +master-bin.000001 # Query 1 # use `mysqltest1`; drop function f2 +master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` trigger t1_bi before insert on t1 for each row +begin +insert into t2 values(null,"try_55_"); +end +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1) +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2) +master-bin.000001 # Write_rows 1 # table_id: # +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Query 1 # use `mysqltest1`; alter table t1 modify a int, drop primary key +master-bin.000001 # Intvar 1 # INSERT_ID=5 +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values(null,"try_57_") +master-bin.000001 # Query 1 # use `mysqltest1`; CREATE TABLE `t16` ( + `UUID()` varchar(36) CHARACTER SET utf8 NOT NULL DEFAULT '' +) +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t16) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t16) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Query 1 # use `mysqltest1`; insert into t16 values("try_66_") +master-bin.000001 # Query 1 # use `mysqltest1`; DROP TABLE IF EXISTS t11 +master-bin.000001 # Query 1 # use `mysqltest1`; CREATE TABLE t11 (song VARCHAR(255)) +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t11) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Query 1 # use `mysqltest1`; INSERT INTO t11 VALUES('Careful With That Axe, Eugene') +master-bin.000001 # Query 1 # use `mysqltest1`; DROP TABLE IF EXISTS t12 +master-bin.000001 # Query 1 # use `mysqltest1`; CREATE TABLE t12 (data LONG) +master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t12) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F drop database mysqltest1; diff --git a/mysql-test/t/rpl_switch_stm_row_mixed.test b/mysql-test/t/rpl_switch_stm_row_mixed.test index 4cef32161ed..4066794d519 100644 --- a/mysql-test/t/rpl_switch_stm_row_mixed.test +++ b/mysql-test/t/rpl_switch_stm_row_mixed.test @@ -464,12 +464,15 @@ if ($you_want_to_test_UDF) select count(*) from t9; } +sync_slave_with_master; + # # Bug#20863 If binlog format is changed between update and unlock of # tables, wrong binlog # connection master; +DROP TABLE IF EXISTS t11; SET SESSION BINLOG_FORMAT=STATEMENT; CREATE TABLE t11 (song VARCHAR(255)); LOCK TABLES t11 WRITE; @@ -485,6 +488,7 @@ USE mysqltest1; --query_vertical SELECT * FROM t11 connection master; +DROP TABLE IF EXISTS t12; SET SESSION BINLOG_FORMAT=MIXED; CREATE TABLE t12 (data LONG); LOCK TABLES t12 WRITE; From dbc98766b08c3a561fa69ddc221c2a9d697e9d8a Mon Sep 17 00:00:00 2001 From: "mats@romeo.(none)" <> Date: Tue, 22 Aug 2006 10:36:11 +0200 Subject: [PATCH 09/27] WL#3259 (RBR with more columns on slave than on master): Post-merge fixes. --- mysql-test/r/rpl_row_tabledefs_3innodb.result | 8 +- mysql-test/t/disabled.def | 1 + sql/field.cc | 1 + sql/log_event.cc | 105 +++++++++--------- 4 files changed, 59 insertions(+), 56 deletions(-) diff --git a/mysql-test/r/rpl_row_tabledefs_3innodb.result b/mysql-test/r/rpl_row_tabledefs_3innodb.result index 17f41850bc7..0c1b25ec7fc 100644 --- a/mysql-test/r/rpl_row_tabledefs_3innodb.result +++ b/mysql-test/r/rpl_row_tabledefs_3innodb.result @@ -151,7 +151,7 @@ Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table -Last_Errno 1514 +Last_Errno 1522 Last_Error Table width mismatch - received 2 columns, test.t2 has 1 columns Skip_Counter 0 Exec_Master_Log_Pos # @@ -189,7 +189,7 @@ Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table -Last_Errno 1514 +Last_Errno 1522 Last_Error Column 0 type mismatch - received type 3, test.t4 has type 4 Skip_Counter 0 Exec_Master_Log_Pos # @@ -227,7 +227,7 @@ Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table -Last_Errno 1514 +Last_Errno 1522 Last_Error Column 1 type mismatch - received type 3, test.t5 has type 4 Skip_Counter 0 Exec_Master_Log_Pos # @@ -265,7 +265,7 @@ Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table -Last_Errno 1514 +Last_Errno 1522 Last_Error Column 2 type mismatch - received type 3, test.t6 has type 4 Skip_Counter 0 Exec_Master_Log_Pos # diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index a3bedbaa22d..f1322fcb699 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -36,6 +36,7 @@ rpl_row_blob_innodb : BUG#18980 2006-04-10 kent Test fails randomly rpl_row_func003 : BUG#19074 2006-13-04 andrei test failed rpl_row_inexist_tbl : BUG#18948 2006-03-09 mats Disabled since patch makes this test wait forever rpl_sp : BUG#16456 2006-02-16 jmiller +rpl_sp_effects : BUG#19862 2006-08-22 mats Bug appear to be fixed rpl_until : BUG#15886 2006-02-16 jmiller Unstable test case sp-goto : BUG#18949 2006-02-16 jmiller GOTO is currently is disabled - will be fixed in the future mysqldump : BUG#18078 2006-03-10 lars diff --git a/sql/field.cc b/sql/field.cc index 1fe74d5320f..340f33f1e01 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -1255,6 +1255,7 @@ void Field::hash(ulong *nr, ulong *nr2) CHARSET_INFO *cs= charset(); cs->coll->hash_sort(cs, (uchar*) ptr, len, nr, nr2); } +} my_size_t Field::do_last_null_byte() const diff --git a/sql/log_event.cc b/sql/log_event.cc index 4ccd808befc..2a8fd085eee 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -5293,21 +5293,39 @@ int Rows_log_event::do_add_row_data(byte *const row_data, /* Unpack a row into a record. - The row is assumed to only consist of the fields for which the - bitset represented by 'arr' and 'bits'; the other parts of the - record are left alone. + SYNOPSIS + unpack_row() + rli Relay log info + table Table to unpack into + colcnt Number of columns to read from record + record Record where the data should be unpacked + row Packed row data + cols Pointer to columns data to fill in + row_end Pointer to variable that will hold the value of the + one-after-end position for the row + master_reclength + Pointer to variable that will hold the length of the + record on the master side + rw_set Pointer to bitmap that holds either the read_set or the + write_set of the table - At most 'colcnt' columns are read: if the table is larger than that, - the remaining fields are not filled in. + DESCRIPTION + + The row is assumed to only consist of the fields for which the + bitset represented by 'arr' and 'bits'; the other parts of the + record are left alone. + + At most 'colcnt' columns are read: if the table is larger than + that, the remaining fields are not filled in. */ static int unpack_row(RELAY_LOG_INFO *rli, TABLE *table, uint const colcnt, byte *record, char const *row, MY_BITMAP const *cols, - char const **row_end, ulong *master_reclength) + char const **row_end, ulong *master_reclength, + MY_BITMAP* const rw_set) { DBUG_ASSERT(record && row); - MY_BITMAP *write_set= table->write_set; my_ptrdiff_t const offset= record - (byte*) table->record[0]; my_size_t master_null_bytes= table->s->null_bytes; @@ -5326,7 +5344,7 @@ unpack_row(RELAY_LOG_INFO *rli, memcpy(record, row, master_null_bytes); // [1] int error= 0; - bitmap_set_all(write_set); + bitmap_set_all(rw_set); Field **const begin_ptr = table->field; Field **field_ptr; @@ -5339,11 +5357,12 @@ unpack_row(RELAY_LOG_INFO *rli, if (bitmap_is_set(cols, field_ptr - begin_ptr)) { - /* Field...::unpack() cannot return 0 */ ptr= f->unpack(f->ptr + offset, ptr); + /* Field...::unpack() cannot return 0 */ + DBUG_ASSERT(ptr != NULL); } else - bitmap_clear_bit(write_set, (field_ptr - begin_ptr) + 1); + bitmap_clear_bit(rw_set, field_ptr - begin_ptr); } *row_end = ptr; @@ -6102,27 +6121,6 @@ void Table_map_log_event::print(FILE *file, PRINT_EVENT_INFO *print_event_info) } #endif -#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) -#ifndef DBUG_OFF -static void -print_column_values(char const *text, THD *thd, TABLE *table) -{ - THD *old_thd= table->in_use; - if (table->in_use == NULL) - table->in_use= thd; - for (Field **fptr= table->field ; *fptr ; ++fptr) - { - char buf[MAX_FIELD_WIDTH]; - String str(buf, sizeof(buf), system_charset_info); - (*fptr)->val_str(&str); - DBUG_PRINT("info", ("%s for column %d is '%s'", - text, fptr - table->field, str.c_ptr())); - } - table->in_use= old_thd; -} -#endif -#endif - /************************************************************************** Write_rows_log_event member functions **************************************************************************/ @@ -6219,10 +6217,9 @@ int Write_rows_log_event::do_prepare_row(THD *thd, RELAY_LOG_INFO *rli, int error; error= unpack_row(rli, table, m_width, table->record[0], - row_start, &m_cols, row_end, &m_master_reclength); -#ifndef DBUG_OFF - print_column_values("Unpacked value", thd, table); -#endif + row_start, &m_cols, row_end, &m_master_reclength, + table->write_set); + bitmap_copy(table->read_set, table->write_set); return error; } @@ -6345,17 +6342,22 @@ copy_extra_record_fields(TABLE *table, /* Replace the provided record in the database. - Similar to how it is done in mysql_insert(), we first - try to do a ha_write_row() and of that fails due to - duplicated keys (or indices), we do an ha_update_row() - or a ha_delete_row() instead. + SYNOPSIS + replace_record() + thd Thread context for writing the record. + table Table to which record should be written. + master_reclength + Offset to first column that is not present on the master, + alternatively the length of the record on the master + side. - @param thd Thread context for writing the record. - @param table Table to which record should be written. - @param master_reclength - Offset to first column that is not present on the master, - alternatively the length of the record on the master side. - @return Error code on failure, 0 on success. + RETURN VALUE + Error code on failure, 0 on success. + + DESCRIPTION + Similar to how it is done in mysql_insert(), we first try to do + a ha_write_row() and of that fails due to duplicated keys (or + indices), we do an ha_update_row() or a ha_delete_row() instead. */ static int replace_record(THD *thd, TABLE *table, @@ -6369,10 +6371,6 @@ replace_record(THD *thd, TABLE *table, int keynum; auto_afree_ptr key(NULL); -#ifndef DBUG_OFF - print_column_values("Starting write value", thd, table); -#endif - while ((error= table->file->ha_write_row(table->record[0]))) { if ((keynum= table->file->get_dup_key(error)) < 0) @@ -6766,7 +6764,8 @@ int Delete_rows_log_event::do_prepare_row(THD *thd, RELAY_LOG_INFO *rli, error= unpack_row(rli, table, m_width, table->record[0], - row_start, &m_cols, row_end, &m_master_reclength); + row_start, &m_cols, row_end, &m_master_reclength, + table->read_set); /* If we will access rows using the random access method, m_key will be set to NULL, so we do not need to make a key copy in that case. @@ -6908,12 +6907,14 @@ int Update_rows_log_event::do_prepare_row(THD *thd, RELAY_LOG_INFO *rli, /* record[0] is the before image for the update */ error= unpack_row(rli, table, m_width, table->record[0], - row_start, &m_cols, row_end, &m_master_reclength); + row_start, &m_cols, row_end, &m_master_reclength, + table->read_set); row_start = *row_end; /* m_after_image is the after image for the update */ error= unpack_row(rli, table, m_width, m_after_image, - row_start, &m_cols, row_end, &m_master_reclength); + row_start, &m_cols, row_end, &m_master_reclength, + table->write_set); /* If we will access rows using the random access method, m_key will From 794dba439e6d4fe748e42457e9d5ab63807da81c Mon Sep 17 00:00:00 2001 From: "mkindahl@production.mysql.com[mkindahl]" <> Date: Fri, 25 Aug 2006 13:53:16 +0200 Subject: [PATCH 10/27] mytap-changes.patch --- unittest/Makefile.am | 7 +++-- unittest/README.txt | 7 ++++- unittest/examples/Makefile.am | 2 +- unittest/mytap/tap.c | 50 +++++++++++++++++++++++++++++++++-- unittest/mytap/tap.h | 27 ++++++++++++++++--- 5 files changed, 81 insertions(+), 12 deletions(-) diff --git a/unittest/Makefile.am b/unittest/Makefile.am index ca3291efde0..6cca1165cfe 100644 --- a/unittest/Makefile.am +++ b/unittest/Makefile.am @@ -6,10 +6,9 @@ CLEANFILES = unit unittests = mytap mysys -test: unit - ./unit run $(unittests) +test: + perl unit.pl run $(unittests) unit: $(srcdir)/unit.pl - cp $(srcdir)/unit.pl $@ - chmod 700 $@ + install $(srcdir)/unit.pl $@ diff --git a/unittest/README.txt b/unittest/README.txt index 0d8bb9025d8..cefa8753f8f 100644 --- a/unittest/README.txt +++ b/unittest/README.txt @@ -9,7 +9,9 @@ mytap Source for the MyTAP library mysys Tests for mysys components bitmap-t.c Unit test for MY_BITMAP base64-t.c Unit test for base64 encoding functions -examples Example unit tests +examples Example unit tests. + core-t.c Example of raising a signal in the middle of the test + THIS TEST WILL STOP ALL FURTHER TESTING! simple-t.c Example of a standard TAP unit test skip-t.c Example where some test points are skipped skip_all-t.c Example of a test where the entire test is skipped @@ -24,6 +26,9 @@ To make and execute all unit tests in the directory: make test +Observe that the tests in the examples/ directory are just various +examples of tests and are not expected to pass. + Adding unit tests ----------------- diff --git a/unittest/examples/Makefile.am b/unittest/examples/Makefile.am index f3c70b654a1..8aefb351220 100644 --- a/unittest/examples/Makefile.am +++ b/unittest/examples/Makefile.am @@ -5,5 +5,5 @@ AM_LDFLAGS = -L$(top_builddir)/unittest/mytap LDADD = -lmytap -noinst_PROGRAMS = simple-t skip-t todo-t skip_all-t no_plan-t +noinst_PROGRAMS = simple-t skip-t todo-t skip_all-t no_plan-t core-t diff --git a/unittest/mytap/tap.c b/unittest/mytap/tap.c index d3f5013b4c9..17ec51863d9 100644 --- a/unittest/mytap/tap.c +++ b/unittest/mytap/tap.c @@ -20,10 +20,13 @@ #include "tap.h" +#include "my_config.h" + #include #include #include #include +#include /** Test data structure. @@ -70,7 +73,7 @@ emit_tap(int pass, char const *fmt, va_list ap) /** Emit a TAP directive. - TAP directives are comments after a have the form + TAP directives are comments after that have the form: @code ok 1 # skip reason for skipping @@ -96,6 +99,25 @@ emit_endl() fprintf(tapout, "\n"); } +static void +handle_core_signal(int signo) +{ + BAIL_OUT("Signal %d thrown", signo); +} + +void +BAIL_OUT(char const *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + fprintf(tapout, "Bail out! "); + vfprintf(tapout, fmt, ap); + emit_endl(); + va_end(ap); + exit(255); +} + + void diag(char const *fmt, ...) { @@ -103,14 +125,38 @@ diag(char const *fmt, ...) va_start(ap, fmt); fprintf(tapout, "# "); vfprintf(tapout, fmt, ap); - fprintf(tapout, "\n"); + emit_endl(); va_end(ap); } +typedef struct signal_entry { + int signo; + void (*handler)(int); +} signal_entry; + +static signal_entry install_signal[]= { + { SIGQUIT, handle_core_signal }, + { SIGILL, handle_core_signal }, + { SIGABRT, handle_core_signal }, + { SIGFPE, handle_core_signal }, + { SIGSEGV, handle_core_signal }, + { SIGBUS, handle_core_signal }, + { SIGXCPU, handle_core_signal }, + { SIGXFSZ, handle_core_signal }, + { SIGSYS, handle_core_signal }, + { SIGTRAP, handle_core_signal } +}; void plan(int const count) { + /* + Install signal handler + */ + size_t i; + for (i= 0; i < sizeof(install_signal)/sizeof(*install_signal); ++i) + signal(install_signal[i].signo, install_signal[i].handler); + g_test.plan= count; switch (count) { diff --git a/unittest/mytap/tap.h b/unittest/mytap/tap.h index cc1d0926012..5e24c1c8c99 100644 --- a/unittest/mytap/tap.h +++ b/unittest/mytap/tap.h @@ -21,8 +21,6 @@ #ifndef TAP_H #define TAP_H -#include "my_global.h" - /* @defgroup MyTAP MySQL support for performing unit tests according to TAP. @@ -67,6 +65,10 @@ extern "C" { it was called with NO_PLAN, i.e., the test plan will be printed after all the test lines. + The plan() function will install signal handlers for all signals + that generate a core, so if you want to override these signals, do + it after you have called the plan() function. + @param count The planned number of tests to run. */ void plan(int count); @@ -130,10 +132,9 @@ void skip(int how_many, char const *reason, ...) for (i = 0 ; i < 2 ; ++i) ok(duck[i] == paddling, "is duck %d paddling?", i); } + @endcode @see skip - - @endcode */ #define SKIP_BLOCK_IF(SKIP_IF_TRUE, COUNT, REASON) \ if (SKIP_IF_TRUE) skip((COUNT),(REASON)); else @@ -146,6 +147,24 @@ void skip(int how_many, char const *reason, ...) void diag(char const *fmt, ...) __attribute__((format(printf,1,2))); +/** + Print a bail out message. + + A bail out message can be issued when no further testing can be + done, e.g., when there are missing dependencies. + + The test will exit with status 255. This function does not return. + + @note A bail out message is printed if a signal that generates a + core is raised. + + @param fmt Bail out message in printf() format. +*/ + +void BAIL_OUT(char const *fmt, ...) + __attribute__((noreturn, format(printf,1,2))); + + /** Print summary report and return exit status. From 0b7dc2689d64990c155afba76b8a0c9b40134fec Mon Sep 17 00:00:00 2001 From: "mkindahl@dl145h.mysql.com" <> Date: Fri, 25 Aug 2006 16:11:22 +0200 Subject: [PATCH 11/27] Adding missing file --- unittest/examples/core-t.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 unittest/examples/core-t.c diff --git a/unittest/examples/core-t.c b/unittest/examples/core-t.c new file mode 100644 index 00000000000..3572d72868b --- /dev/null +++ b/unittest/examples/core-t.c @@ -0,0 +1,19 @@ + +#include "my_config.h" + +#include +#include + +/* + This is a simple test to demonstrate what happens if a signal that + generates a core is raised. + + Note that this test will stop all further testing! + */ + +int main() { + plan(3); + ok(1, "First test"); + abort(); + return exit_status(); +} From e49db547e673495b4653210eea008ff56f763fe2 Mon Sep 17 00:00:00 2001 From: "mkindahl@dl145h.mysql.com" <> Date: Fri, 25 Aug 2006 16:50:01 +0200 Subject: [PATCH 12/27] BUG#21833 (Prepare_commit_mutex not locked and unlocked under same condition): Adding condition to ensure that mutex are locked and unlocked under same condition. --- sql/ha_innodb.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 00a92e05ffb..d39f87ee3ec 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -7387,7 +7387,9 @@ innobase_xa_prepare( int error = 0; trx_t* trx = check_trx_exists(thd); - if (thd->lex->sql_command != SQLCOM_XA_PREPARE) { + if (thd->lex->sql_command != SQLCOM_XA_PREPARE && + (all || !(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))) + { /* For ibbackup to work the order of transactions in binlog and InnoDB must be the same. Consider the situation From ca1bf4b21ea1973b7d2981a819ea2d5f8eecbae4 Mon Sep 17 00:00:00 2001 From: "mkindahl@dl145h.mysql.com" <> Date: Tue, 29 Aug 2006 22:23:56 +0200 Subject: [PATCH 13/27] Various fixes to make MyTAP build on all platforms. --- unittest/Makefile.am | 6 ++---- unittest/mytap/tap.h | 28 +++++++++++++++++++++++++--- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/unittest/Makefile.am b/unittest/Makefile.am index 6cca1165cfe..f2f7fc0bf7d 100644 --- a/unittest/Makefile.am +++ b/unittest/Makefile.am @@ -1,6 +1,5 @@ SUBDIRS = mytap . mysys examples -noinst_SCRIPTS = unit EXTRA_DIST = unit.pl CLEANFILES = unit @@ -9,6 +8,5 @@ unittests = mytap mysys test: perl unit.pl run $(unittests) -unit: $(srcdir)/unit.pl - install $(srcdir)/unit.pl $@ - +test-verbose: + HARNESS_VERBOSE=1 perl unit.pl run $(unittests) diff --git a/unittest/mytap/tap.h b/unittest/mytap/tap.h index 5e24c1c8c99..51b8c7df04d 100644 --- a/unittest/mytap/tap.h +++ b/unittest/mytap/tap.h @@ -21,9 +21,11 @@ #ifndef TAP_H #define TAP_H -/* - @defgroup MyTAP MySQL support for performing unit tests according to TAP. +#include "my_global.h" +/* + @defgroup MyTAP MySQL support for performing unit tests according to + the Test Anything Protocol (TAP). */ #define NO_PLAN (0) @@ -34,6 +36,7 @@ @internal We are using the "typedef struct X { ... } X" idiom to create class/struct X both in C and C++. */ + typedef struct TEST_DATA { /** Number of tests that is planned to execute. @@ -71,6 +74,7 @@ extern "C" { @param count The planned number of tests to run. */ + void plan(int count); @@ -89,9 +93,11 @@ void plan(int count); @param fmt Format string in printf() format. NULL is allowed, in which case nothing is printed. */ + void ok(int pass, char const *fmt, ...) __attribute__((format(printf,2,3))); + /** Skip a determined number of tests. @@ -116,6 +122,7 @@ void ok(int pass, char const *fmt, ...) @param how_many Number of tests that are to be skipped. @param reason A reason for skipping the tests */ + void skip(int how_many, char const *reason, ...) __attribute__((format(printf,2,3))); @@ -136,17 +143,21 @@ void skip(int how_many, char const *reason, ...) @see skip */ + #define SKIP_BLOCK_IF(SKIP_IF_TRUE, COUNT, REASON) \ if (SKIP_IF_TRUE) skip((COUNT),(REASON)); else + /** Print a diagnostics message. @param fmt Diagnostics message in printf() format. */ + void diag(char const *fmt, ...) __attribute__((format(printf,1,2))); + /** Print a bail out message. @@ -155,6 +166,10 @@ void diag(char const *fmt, ...) The test will exit with status 255. This function does not return. + @code + BAIL_OUT("Lost connection to server %s", server_name); + @endcode + @note A bail out message is printed if a signal that generates a core is raised. @@ -180,6 +195,7 @@ void BAIL_OUT(char const *fmt, ...) @returns EXIT_SUCCESS if all tests passed, EXIT_FAILURE if one or more tests failed. */ + int exit_status(void); @@ -190,9 +206,11 @@ int exit_status(void); automatically call exit(), so there is no need to have checks around it. */ + void skip_all(char const *reason, ...) __attribute__((noreturn, format(printf, 1, 2))); + /** Start section of tests that are not yet ready. @@ -213,14 +231,18 @@ void skip_all(char const *reason, ...) @param message Message that will be printed before the todo tests. */ + void todo_start(char const *message, ...) - __attribute__((format (printf, 1, 2))); + __attribute__((format(printf, 1, 2))); + /** End a section of tests that are not yet ready. */ + void todo_end(); + #ifdef __cplusplus } #endif From 7be4bc4e55ccdd6bd7b35b1b166b2a0a05276249 Mon Sep 17 00:00:00 2001 From: "aelkin/elkin@andrepl.dsl.inet.fi" <> Date: Wed, 30 Aug 2006 10:22:43 +0300 Subject: [PATCH 14/27] Changes made according to HLD/LLD. The following is an excerption from the WL. 1. Change so that MIXED is default format 1.1 to change the default for command line --binlog-format 1.2 to alter global_system_variables.binlog_format calculation basing on command line --binlog-format parameter and its default. 2. Change test suite so that more testing is done by MIXED format. 2.1 to check if there are test cases requiring --binlog-foramt=statement via `source include/have_binlog_format_statement.inc' and affected by altering the latter to be "mixed". 2.2 to check the content of such vulnerable cases to find if extending to the mixed does not modify results. In that case simply substitute source arguments as explained. 2.3 if a test in mixed mode deals with features triggering row-binlogging then if necessary we can switch explicitly to statement mode or create another test to run with non-recommended STATEMENT mode Particullarily, extracting INSERT DELAYED binlogging subtest for statement mode is performed, and the snippet is moved into a separate test file. Note that since now all three modes verify this use case through 3 different tests. No changes in item 3 of HLD appeared to be needed. --- mysql-test/extra/binlog_tests/binlog.test | 22 +------------------ .../binlog_tests/binlog_insert_delayed.test | 22 +++++++++++++++++++ mysql-test/extra/rpl_tests/rpl_loaddata.test | 2 +- .../extra/rpl_tests/rpl_stm_000001.test | 2 +- .../extra/rpl_tests/rpl_stm_charset.test | 2 +- .../include/have_binlog_format_mixed.inc | 4 ++++ .../have_binlog_format_mixed_or_statement.inc | 5 +++++ .../r/binlog_statement_insert_delayed.result | 18 +++++++++++++++ mysql-test/r/binlog_stm_binlog.result | 10 +++++---- mysql-test/r/have_binlog_format_mixed.require | 2 ++ mysql-test/r/rpl_rbr_to_sbr.result | 3 --- mysql-test/t/archive.test | 2 +- .../t/binlog_statement_insert_delayed.test | 6 +++++ mysql-test/t/binlog_stm_binlog.test | 2 +- mysql-test/t/binlog_stm_blackhole.test | 2 +- mysql-test/t/binlog_stm_ctype_cp932.test | 2 +- mysql-test/t/binlog_stm_ctype_ucs.test | 2 +- mysql-test/t/binlog_stm_drop_tmp_tbl.test | 2 +- mysql-test/t/binlog_stm_innodb_stat.test | 2 +- mysql-test/t/binlog_stm_insert_select.test | 2 +- .../t/binlog_stm_mix_innodb_myisam.test | 2 +- mysql-test/t/create_select_tmp.test | 2 +- mysql-test/t/ctype_cp932_binlog_stm.test | 2 +- mysql-test/t/date_formats.test | 6 ++--- mysql-test/t/mysqlbinlog.test | 2 +- mysql-test/t/mysqlbinlog2.test | 2 +- mysql-test/t/ndb_multi.test | 2 +- mysql-test/t/rpl000013.test | 2 +- mysql-test/t/rpl_heap.test | 2 +- mysql-test/t/rpl_loaddata_s.test | 2 +- mysql-test/t/rpl_mixed_ddl_dml.test | 2 +- mysql-test/t/rpl_rbr_to_sbr.test | 3 +-- mysql-test/t/rpl_rewrt_db.test | 2 +- mysql-test/t/rpl_rotate_logs.test | 2 +- mysql-test/t/rpl_stm_EE_err2.test | 2 +- mysql-test/t/rpl_stm_flsh_tbls.test | 2 +- mysql-test/t/rpl_stm_log.test | 2 +- mysql-test/t/rpl_stm_max_relay_size.test | 2 +- mysql-test/t/rpl_stm_multi_query.test | 2 +- mysql-test/t/rpl_stm_mystery22.test | 2 +- mysql-test/t/rpl_stm_no_op.test | 2 +- mysql-test/t/rpl_stm_reset_slave.test | 2 +- mysql-test/t/rpl_stm_until.test | 2 +- mysql-test/t/rpl_temp_table.test | 2 +- mysql-test/t/rpl_trigger.test | 2 +- mysql-test/t/rpl_trunc_temp.test | 2 +- mysql-test/t/user_var-binlog.test | 2 +- sql/mysqld.cc | 12 +++++++++- 48 files changed, 115 insertions(+), 70 deletions(-) create mode 100644 mysql-test/extra/binlog_tests/binlog_insert_delayed.test create mode 100644 mysql-test/include/have_binlog_format_mixed.inc create mode 100644 mysql-test/include/have_binlog_format_mixed_or_statement.inc create mode 100644 mysql-test/r/binlog_statement_insert_delayed.result create mode 100644 mysql-test/r/have_binlog_format_mixed.require create mode 100644 mysql-test/t/binlog_statement_insert_delayed.test diff --git a/mysql-test/extra/binlog_tests/binlog.test b/mysql-test/extra/binlog_tests/binlog.test index 993b3fbf634..af7320a49f6 100644 --- a/mysql-test/extra/binlog_tests/binlog.test +++ b/mysql-test/extra/binlog_tests/binlog.test @@ -60,24 +60,4 @@ insert into t1 values(null); select * from t1; drop table t1; -# Test of binlogging of INSERT_ID with INSERT DELAYED -create table t1 (a int not null auto_increment, primary key (a)) engine=myisam; -# First, avoid BUG#20627: -set @@session.auto_increment_increment=1, @@session.auto_increment_offset=1; -# Verify that only one INSERT_ID event is binlogged. -insert delayed into t1 values (207); - -# We use sleeps between statements, that's the only way to get a -# repeatable binlog in a normal test run and under Valgrind. -# It may be that the "binlog missing rows" of BUG#20821 shows up -# here. -sleep 2; -insert delayed into t1 values (null); -sleep 2; -insert delayed into t1 values (300); -sleep 2; # time for the delayed queries to reach disk -select * from t1; ---replace_column 2 # 5 # ---replace_regex /table_id: [0-9]+/table_id: #/ -show binlog events from 102; -drop table t1; +-- source extra/binlog_tests/binlog_insert_delayed.test diff --git a/mysql-test/extra/binlog_tests/binlog_insert_delayed.test b/mysql-test/extra/binlog_tests/binlog_insert_delayed.test new file mode 100644 index 00000000000..596bb1d5772 --- /dev/null +++ b/mysql-test/extra/binlog_tests/binlog_insert_delayed.test @@ -0,0 +1,22 @@ +# Test of binlogging of INSERT_ID with INSERT DELAYED +create table t1 (a int not null auto_increment, primary key (a)) engine=myisam; +# First, avoid BUG#20627: +set @@session.auto_increment_increment=1, @@session.auto_increment_offset=1; +# Verify that only one INSERT_ID event is binlogged. +# Note, that because of WL#3368 mixed mode binlog records RBR events for the delayed +insert delayed into t1 values (207); + +# We use sleeps between statements, that's the only way to get a +# repeatable binlog in a normal test run and under Valgrind. +# It may be that the "binlog missing rows" of BUG#20821 shows up +# here. +sleep 2; +insert delayed into t1 values (null); +sleep 2; +insert delayed into t1 values (300); +sleep 2; # time for the delayed queries to reach disk +select * from t1; +--replace_column 2 # 5 # +--replace_regex /table_id: [0-9]+/table_id: #/ +show binlog events from 102; +drop table t1; diff --git a/mysql-test/extra/rpl_tests/rpl_loaddata.test b/mysql-test/extra/rpl_tests/rpl_loaddata.test index 08e89c20973..e58908ec7e9 100644 --- a/mysql-test/extra/rpl_tests/rpl_loaddata.test +++ b/mysql-test/extra/rpl_tests/rpl_loaddata.test @@ -1,5 +1,5 @@ # Requires statement logging --- source include/have_binlog_format_statement.inc +-- source include/have_binlog_format_mixed_or_statement.inc # See if replication of a "LOAD DATA in an autoincrement column" # Honours autoincrement values diff --git a/mysql-test/extra/rpl_tests/rpl_stm_000001.test b/mysql-test/extra/rpl_tests/rpl_stm_000001.test index 443ed27053a..8673ae31305 100644 --- a/mysql-test/extra/rpl_tests/rpl_stm_000001.test +++ b/mysql-test/extra/rpl_tests/rpl_stm_000001.test @@ -1,4 +1,4 @@ --- source include/have_binlog_format_statement.inc +-- source include/have_binlog_format_mixed_or_statement.inc -- source include/master-slave.inc create table t1 (word char(20) not null); diff --git a/mysql-test/extra/rpl_tests/rpl_stm_charset.test b/mysql-test/extra/rpl_tests/rpl_stm_charset.test index d29a82cfd31..10b4310127f 100644 --- a/mysql-test/extra/rpl_tests/rpl_stm_charset.test +++ b/mysql-test/extra/rpl_tests/rpl_stm_charset.test @@ -2,7 +2,7 @@ # This test will fail if the server/client does not support enough charsets. # Requires statement logging --- source include/have_binlog_format_statement.inc +-- source include/have_binlog_format_mixed_or_statement.inc source include/master-slave.inc; --disable_warnings diff --git a/mysql-test/include/have_binlog_format_mixed.inc b/mysql-test/include/have_binlog_format_mixed.inc new file mode 100644 index 00000000000..fc5ca61c5a0 --- /dev/null +++ b/mysql-test/include/have_binlog_format_mixed.inc @@ -0,0 +1,4 @@ +-- require r/have_binlog_format_mixed.require +disable_query_log; +show variables like "binlog_format"; +enable_query_log; diff --git a/mysql-test/include/have_binlog_format_mixed_or_statement.inc b/mysql-test/include/have_binlog_format_mixed_or_statement.inc new file mode 100644 index 00000000000..8ee6f2cc030 --- /dev/null +++ b/mysql-test/include/have_binlog_format_mixed_or_statement.inc @@ -0,0 +1,5 @@ +--require r/have_binlog_format_statement.require +--disable_query_log +--replace_result MIXED STATEMENT +show variables like "binlog_format"; +--enable_query_log diff --git a/mysql-test/r/binlog_statement_insert_delayed.result b/mysql-test/r/binlog_statement_insert_delayed.result new file mode 100644 index 00000000000..bae01f7dc5d --- /dev/null +++ b/mysql-test/r/binlog_statement_insert_delayed.result @@ -0,0 +1,18 @@ +create table t1 (a int not null auto_increment, primary key (a)) engine=myisam; +set @@session.auto_increment_increment=1, @@session.auto_increment_offset=1; +insert delayed into t1 values (207); +insert delayed into t1 values (null); +insert delayed into t1 values (300); +select * from t1; +a +207 +208 +300 +show binlog events from 102; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query 1 # use `test`; create table t1 (a int not null auto_increment, primary key (a)) engine=myisam +master-bin.000001 # Query 1 # use `test`; insert delayed into t1 values (207) +master-bin.000001 # Intvar 1 # INSERT_ID=208 +master-bin.000001 # Query 1 # use `test`; insert delayed into t1 values (null) +master-bin.000001 # Query 1 # use `test`; insert delayed into t1 values (300) +drop table t1; diff --git a/mysql-test/r/binlog_stm_binlog.result b/mysql-test/r/binlog_stm_binlog.result index 4e23db4828f..b175089f585 100644 --- a/mysql-test/r/binlog_stm_binlog.result +++ b/mysql-test/r/binlog_stm_binlog.result @@ -172,8 +172,10 @@ master-bin.000001 # Intvar 1 # INSERT_ID=127 master-bin.000001 # Query 1 # use `test`; insert into t1 values(null) master-bin.000001 # Query 1 # use `test`; drop table t1 master-bin.000001 # Query 1 # use `test`; create table t1 (a int not null auto_increment, primary key (a)) engine=myisam -master-bin.000001 # Query 1 # use `test`; insert delayed into t1 values (207) -master-bin.000001 # Intvar 1 # INSERT_ID=208 -master-bin.000001 # Query 1 # use `test`; insert delayed into t1 values (null) -master-bin.000001 # Query 1 # use `test`; insert delayed into t1 values (300) +master-bin.000001 # Table_map 1 # table_id: # (test.t1) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map 1 # table_id: # (test.t1) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map 1 # table_id: # (test.t1) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F drop table t1; diff --git a/mysql-test/r/have_binlog_format_mixed.require b/mysql-test/r/have_binlog_format_mixed.require new file mode 100644 index 00000000000..4b752cbb314 --- /dev/null +++ b/mysql-test/r/have_binlog_format_mixed.require @@ -0,0 +1,2 @@ +Variable_name Value +binlog_format MIXED diff --git a/mysql-test/r/rpl_rbr_to_sbr.result b/mysql-test/r/rpl_rbr_to_sbr.result index c5a672ee13b..4b2d129c732 100644 --- a/mysql-test/r/rpl_rbr_to_sbr.result +++ b/mysql-test/r/rpl_rbr_to_sbr.result @@ -5,9 +5,6 @@ reset slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; SET BINLOG_FORMAT=MIXED; -SELECT @@GLOBAL.BINLOG_FORMAT, @@SESSION.BINLOG_FORMAT; -@@GLOBAL.BINLOG_FORMAT @@SESSION.BINLOG_FORMAT -STATEMENT MIXED SET GLOBAL BINLOG_FORMAT=MIXED; SELECT @@GLOBAL.BINLOG_FORMAT, @@SESSION.BINLOG_FORMAT; @@GLOBAL.BINLOG_FORMAT @@SESSION.BINLOG_FORMAT diff --git a/mysql-test/t/archive.test b/mysql-test/t/archive.test index 294e7730e07..0dccd8f111a 100644 --- a/mysql-test/t/archive.test +++ b/mysql-test/t/archive.test @@ -3,7 +3,7 @@ # Taken FROM the select test # -- source include/have_archive.inc --- source include/have_binlog_format_statement.inc +-- source include/have_binlog_format_mixed_or_statement.inc --disable_warnings drop table if exists t1,t2,t3; diff --git a/mysql-test/t/binlog_statement_insert_delayed.test b/mysql-test/t/binlog_statement_insert_delayed.test new file mode 100644 index 00000000000..3b2c547a901 --- /dev/null +++ b/mysql-test/t/binlog_statement_insert_delayed.test @@ -0,0 +1,6 @@ +# This test is to verify replication with INSERT DELAY through +# unrecommended STATEMENT binlog format + +-- source include/not_embedded.inc +-- source include/have_binlog_format_statement.inc +-- source extra/binlog_tests/binlog_insert_delayed.test diff --git a/mysql-test/t/binlog_stm_binlog.test b/mysql-test/t/binlog_stm_binlog.test index f22e7e45aea..280b7a3aef9 100644 --- a/mysql-test/t/binlog_stm_binlog.test +++ b/mysql-test/t/binlog_stm_binlog.test @@ -13,6 +13,6 @@ drop table t1; # For both statement and row based bin logs 9/19/2005 [jbm] -- source include/not_embedded.inc --- source include/have_binlog_format_statement.inc +-- source include/have_binlog_format_mixed.inc -- source extra/binlog_tests/binlog.test diff --git a/mysql-test/t/binlog_stm_blackhole.test b/mysql-test/t/binlog_stm_blackhole.test index 6047d8ca2fc..02ba2be095b 100644 --- a/mysql-test/t/binlog_stm_blackhole.test +++ b/mysql-test/t/binlog_stm_blackhole.test @@ -2,5 +2,5 @@ # For both statement and row based bin logs 9/19/2005 [jbm] -- source include/not_embedded.inc --- source include/have_binlog_format_statement.inc +-- source include/have_binlog_format_mixed_or_statement.inc -- source extra/binlog_tests/blackhole.test diff --git a/mysql-test/t/binlog_stm_ctype_cp932.test b/mysql-test/t/binlog_stm_ctype_cp932.test index 436f95a2453..c0791d81445 100644 --- a/mysql-test/t/binlog_stm_ctype_cp932.test +++ b/mysql-test/t/binlog_stm_ctype_cp932.test @@ -2,5 +2,5 @@ # For both statement and row based bin logs 9/19/2005 [jbm] -- source include/not_embedded.inc --- source include/have_binlog_format_statement.inc +-- source include/have_binlog_format_mixed_or_statement.inc -- source extra/binlog_tests/ctype_cp932.test diff --git a/mysql-test/t/binlog_stm_ctype_ucs.test b/mysql-test/t/binlog_stm_ctype_ucs.test index a32ac3155c7..c8cd7e06398 100644 --- a/mysql-test/t/binlog_stm_ctype_ucs.test +++ b/mysql-test/t/binlog_stm_ctype_ucs.test @@ -1,6 +1,6 @@ # This is a wrapper for binlog.test so that the same test case can be used # For both statement and row based bin logs 9/19/2005 [jbm] --- source include/have_binlog_format_statement.inc +-- source include/have_binlog_format_mixed_or_statement.inc -- source extra/binlog_tests/ctype_ucs_binlog.test diff --git a/mysql-test/t/binlog_stm_drop_tmp_tbl.test b/mysql-test/t/binlog_stm_drop_tmp_tbl.test index e8acd00c779..6017f272d01 100644 --- a/mysql-test/t/binlog_stm_drop_tmp_tbl.test +++ b/mysql-test/t/binlog_stm_drop_tmp_tbl.test @@ -1,5 +1,5 @@ # This is a wrapper for binlog.test so that the same test case can be used # For both statement and row based bin logs 9/19/2005 [jbm] --- source include/have_binlog_format_statement.inc +-- source include/have_binlog_format_mixed_or_statement.inc -- source extra/binlog_tests/drop_temp_table.test diff --git a/mysql-test/t/binlog_stm_innodb_stat.test b/mysql-test/t/binlog_stm_innodb_stat.test index c6017246e6d..a08039c4a41 100644 --- a/mysql-test/t/binlog_stm_innodb_stat.test +++ b/mysql-test/t/binlog_stm_innodb_stat.test @@ -1,5 +1,5 @@ # This is a wrapper for binlog.test so that the same test case can be used # For both statement and row based bin logs 9/19/2005 [jbm] --- source include/have_binlog_format_statement.inc +-- source include/have_binlog_format_mixed_or_statement.inc -- source extra/binlog_tests/innodb_stat.test diff --git a/mysql-test/t/binlog_stm_insert_select.test b/mysql-test/t/binlog_stm_insert_select.test index 06792990a55..3aefa1e6cf7 100644 --- a/mysql-test/t/binlog_stm_insert_select.test +++ b/mysql-test/t/binlog_stm_insert_select.test @@ -1,5 +1,5 @@ # This is a wrapper for binlog.test so that the same test case can be used # For both statement and row based bin logs 9/19/2005 [jbm] --- source include/have_binlog_format_statement.inc +-- source include/have_binlog_format_mixed_or_statement.inc -- source extra/binlog_tests/insert_select-binlog.test diff --git a/mysql-test/t/binlog_stm_mix_innodb_myisam.test b/mysql-test/t/binlog_stm_mix_innodb_myisam.test index 829cf50fe1e..cb6516a3a2f 100644 --- a/mysql-test/t/binlog_stm_mix_innodb_myisam.test +++ b/mysql-test/t/binlog_stm_mix_innodb_myisam.test @@ -1,7 +1,7 @@ # This is a wrapper for binlog.test so that the same test case can be used # For both statement and row based bin logs 9/19/2005 [jbm] --- source include/have_binlog_format_statement.inc +-- source include/have_binlog_format_mixed_or_statement.inc -- source extra/binlog_tests/mix_innodb_myisam_binlog.test # This piece below cannot be put into diff --git a/mysql-test/t/create_select_tmp.test b/mysql-test/t/create_select_tmp.test index 144bccc5871..ba9898b7752 100644 --- a/mysql-test/t/create_select_tmp.test +++ b/mysql-test/t/create_select_tmp.test @@ -6,7 +6,7 @@ # inconsistency between binlog and the internal list of temp tables. # This does not work for RBR yet. ---source include/have_binlog_format_statement.inc +--source include/have_binlog_format_mixed_or_statement.inc -- source include/have_innodb.inc --disable_warnings diff --git a/mysql-test/t/ctype_cp932_binlog_stm.test b/mysql-test/t/ctype_cp932_binlog_stm.test index 7a0ac671417..6b591fbe5f5 100644 --- a/mysql-test/t/ctype_cp932_binlog_stm.test +++ b/mysql-test/t/ctype_cp932_binlog_stm.test @@ -1,7 +1,7 @@ # This is a wrapper for binlog.test so that the same test case can be used # For both statement and row based bin logs 11/07/2005 [jbm] --- source include/have_binlog_format_statement.inc +-- source include/have_binlog_format_mixed_or_statement.inc -- source extra/binlog_tests/ctype_cp932_binlog.test # diff --git a/mysql-test/t/date_formats.test b/mysql-test/t/date_formats.test index 6898cd5802d..c19ebeb2e28 100644 --- a/mysql-test/t/date_formats.test +++ b/mysql-test/t/date_formats.test @@ -6,9 +6,9 @@ drop table if exists t1; --enable_warnings ---replace_result ROW STATEMENT +--replace_result ROW STATEMENT MIXED SHOW GLOBAL VARIABLES LIKE "%_format%"; ---replace_result ROW STATEMENT +--replace_result ROW STATEMENT MIXED SHOW SESSION VARIABLES LIKE "%_format%"; # @@ -36,7 +36,7 @@ set datetime_format= '%H:%i:%s.%f %m-%d-%Y'; set datetime_format= '%h:%i:%s %p %Y-%m-%d'; set datetime_format= '%h:%i:%s.%f %p %Y-%m-%d'; ---replace_result ROW STATEMENT +--replace_result ROW STATEMENT MIXED SHOW SESSION VARIABLES LIKE "%format"; --error 1231 diff --git a/mysql-test/t/mysqlbinlog.test b/mysql-test/t/mysqlbinlog.test index ceba78bf762..b1ee39479b9 100644 --- a/mysql-test/t/mysqlbinlog.test +++ b/mysql-test/t/mysqlbinlog.test @@ -1,6 +1,6 @@ # We are using .opt file since we need small binlog size # TODO: Need to look at making a row based version once the new row based client is completed. [jbm] --- source include/have_binlog_format_statement.inc +-- source include/have_binlog_format_mixed_or_statement.inc # Embedded server doesn't support binlogging -- source include/not_embedded.inc diff --git a/mysql-test/t/mysqlbinlog2.test b/mysql-test/t/mysqlbinlog2.test index 91da502da02..69cd5d90453 100644 --- a/mysql-test/t/mysqlbinlog2.test +++ b/mysql-test/t/mysqlbinlog2.test @@ -2,7 +2,7 @@ # and a few others. # TODO: Need to look at making row based version once new binlog client is complete. --- source include/have_binlog_format_statement.inc +-- source include/have_binlog_format_mixed_or_statement.inc # Embedded server doesn't support binlogging -- source include/not_embedded.inc diff --git a/mysql-test/t/ndb_multi.test b/mysql-test/t/ndb_multi.test index 36018e6c679..df2cc9c1d8b 100644 --- a/mysql-test/t/ndb_multi.test +++ b/mysql-test/t/ndb_multi.test @@ -1,7 +1,7 @@ -- source include/have_ndb.inc -- source include/have_multi_ndb.inc -- source include/not_embedded.inc --- source include/have_binlog_format_statement.inc +-- source include/have_binlog_format_mixed_or_statement.inc --disable_warnings connection server2; diff --git a/mysql-test/t/rpl000013.test b/mysql-test/t/rpl000013.test index c681e76cf51..69a102e84ce 100644 --- a/mysql-test/t/rpl000013.test +++ b/mysql-test/t/rpl000013.test @@ -7,7 +7,7 @@ # in row-based, it hangs waiting for an offset which is never # reached (the "sync_with_master 1"), logically. ---source include/have_binlog_format_statement.inc +--source include/have_binlog_format_mixed_or_statement.inc source include/master-slave.inc; save_master_pos; connection slave; diff --git a/mysql-test/t/rpl_heap.test b/mysql-test/t/rpl_heap.test index b35983ad4d7..b8972ee9e78 100644 --- a/mysql-test/t/rpl_heap.test +++ b/mysql-test/t/rpl_heap.test @@ -1,5 +1,5 @@ # Requires statement logging --- source include/have_binlog_format_statement.inc +-- source include/have_binlog_format_mixed_or_statement.inc # You must run this test with --manager. diff --git a/mysql-test/t/rpl_loaddata_s.test b/mysql-test/t/rpl_loaddata_s.test index 72a5d1a8ec1..2c94c8ef953 100644 --- a/mysql-test/t/rpl_loaddata_s.test +++ b/mysql-test/t/rpl_loaddata_s.test @@ -2,7 +2,7 @@ # replicated LOAD DATA INFILE correctly when it has binlog_*_db rules. # This is for BUG#1100 (LOAD DATA INFILE was half-logged). --- source include/have_binlog_format_statement.inc +-- source include/have_binlog_format_mixed_or_statement.inc -- source include/master-slave.inc connection slave; diff --git a/mysql-test/t/rpl_mixed_ddl_dml.test b/mysql-test/t/rpl_mixed_ddl_dml.test index 5b9ed6898b8..6a1f81abed3 100644 --- a/mysql-test/t/rpl_mixed_ddl_dml.test +++ b/mysql-test/t/rpl_mixed_ddl_dml.test @@ -1,7 +1,7 @@ # Mixed DDL-DML (CREATE ... SELECT ...) statements can only be # replicated properly in statement-based replication. # Currently statement based due to bug 12345 ---source include/have_binlog_format_statement.inc +--source include/have_binlog_format_mixed_or_statement.inc source include/master-slave.inc; diff --git a/mysql-test/t/rpl_rbr_to_sbr.test b/mysql-test/t/rpl_rbr_to_sbr.test index c10199f8ff5..83a9b08c344 100644 --- a/mysql-test/t/rpl_rbr_to_sbr.test +++ b/mysql-test/t/rpl_rbr_to_sbr.test @@ -1,12 +1,11 @@ -- source include/have_row_based.inc --- source include/have_binlog_format_statement.inc +-- source include/have_binlog_format_mixed_or_statement.inc -- source include/master-slave.inc # Test that the slave temporarily switches to ROW when seeing binrow # events when it is in STATEMENT or MIXED mode SET BINLOG_FORMAT=MIXED; -SELECT @@GLOBAL.BINLOG_FORMAT, @@SESSION.BINLOG_FORMAT; SET GLOBAL BINLOG_FORMAT=MIXED; SELECT @@GLOBAL.BINLOG_FORMAT, @@SESSION.BINLOG_FORMAT; diff --git a/mysql-test/t/rpl_rewrt_db.test b/mysql-test/t/rpl_rewrt_db.test index 8acc05f6ff5..52f04e073dd 100644 --- a/mysql-test/t/rpl_rewrt_db.test +++ b/mysql-test/t/rpl_rewrt_db.test @@ -1,5 +1,5 @@ # TBF - difference in row level logging --- source include/have_binlog_format_statement.inc +-- source include/have_binlog_format_mixed_or_statement.inc -- source include/master-slave.inc --disable_warnings diff --git a/mysql-test/t/rpl_rotate_logs.test b/mysql-test/t/rpl_rotate_logs.test index a5c8a87c74d..2249dff1449 100644 --- a/mysql-test/t/rpl_rotate_logs.test +++ b/mysql-test/t/rpl_rotate_logs.test @@ -13,7 +13,7 @@ # - Test creating a duplicate key error and recover from it # Requires statement logging --- source include/have_binlog_format_statement.inc +-- source include/have_binlog_format_mixed_or_statement.inc connect (master,localhost,root,,test,$MASTER_MYPORT,$MASTER_MYSOCK); --disable_warnings diff --git a/mysql-test/t/rpl_stm_EE_err2.test b/mysql-test/t/rpl_stm_EE_err2.test index dbcc66686ec..face651b9a1 100644 --- a/mysql-test/t/rpl_stm_EE_err2.test +++ b/mysql-test/t/rpl_stm_EE_err2.test @@ -3,6 +3,6 @@ # Date: 2006-01-11 # Purpose: Engine Wrapper for rpl_stm_EE_err2.test ############################## --- source include/have_binlog_format_statement.inc +-- source include/have_binlog_format_mixed_or_statement.inc let $engine_type=myisam; -- source extra/rpl_tests/rpl_stm_EE_err2.test diff --git a/mysql-test/t/rpl_stm_flsh_tbls.test b/mysql-test/t/rpl_stm_flsh_tbls.test index 3a6102de279..43a5234ccc7 100644 --- a/mysql-test/t/rpl_stm_flsh_tbls.test +++ b/mysql-test/t/rpl_stm_flsh_tbls.test @@ -1,5 +1,5 @@ # depends on the binlog output ---source include/have_binlog_format_statement.inc +--source include/have_binlog_format_mixed_or_statement.inc let $rename_event_pos= 652; -- source extra/rpl_tests/rpl_flsh_tbls.test diff --git a/mysql-test/t/rpl_stm_log.test b/mysql-test/t/rpl_stm_log.test index d11e1fd8ac1..5a1e0facc83 100644 --- a/mysql-test/t/rpl_stm_log.test +++ b/mysql-test/t/rpl_stm_log.test @@ -1,5 +1,5 @@ # Requires statement logging --- source include/have_binlog_format_statement.inc +-- source include/have_binlog_format_mixed_or_statement.inc let $engine_type=MyISAM; -- source extra/rpl_tests/rpl_log.test diff --git a/mysql-test/t/rpl_stm_max_relay_size.test b/mysql-test/t/rpl_stm_max_relay_size.test index 50008533388..950aa8b322a 100644 --- a/mysql-test/t/rpl_stm_max_relay_size.test +++ b/mysql-test/t/rpl_stm_max_relay_size.test @@ -4,7 +4,7 @@ # Test of manual relay log rotation with FLUSH LOGS. # Requires statement logging --- source include/have_binlog_format_statement.inc +-- source include/have_binlog_format_mixed_or_statement.inc -- source extra/rpl_tests/rpl_max_relay_size.test # End of 4.1 tests diff --git a/mysql-test/t/rpl_stm_multi_query.test b/mysql-test/t/rpl_stm_multi_query.test index 97c322ac780..c39d1fad015 100644 --- a/mysql-test/t/rpl_stm_multi_query.test +++ b/mysql-test/t/rpl_stm_multi_query.test @@ -4,7 +4,7 @@ # one binlog event containing all queries) # Requires statement logging --- source include/have_binlog_format_statement.inc +-- source include/have_binlog_format_mixed_or_statement.inc -- source extra/rpl_tests/rpl_multi_query.test diff --git a/mysql-test/t/rpl_stm_mystery22.test b/mysql-test/t/rpl_stm_mystery22.test index a43f2610350..017593fdfba 100644 --- a/mysql-test/t/rpl_stm_mystery22.test +++ b/mysql-test/t/rpl_stm_mystery22.test @@ -15,7 +15,7 @@ #should proceed in a correct way. ################################# --- source include/have_binlog_format_statement.inc +-- source include/have_binlog_format_mixed_or_statement.inc -- source include/master-slave.inc # first, cause a duplicate key problem on the slave diff --git a/mysql-test/t/rpl_stm_no_op.test b/mysql-test/t/rpl_stm_no_op.test index f82bbd8cd55..66dc89bd712 100644 --- a/mysql-test/t/rpl_stm_no_op.test +++ b/mysql-test/t/rpl_stm_no_op.test @@ -4,7 +4,7 @@ # case. So this test is meaningul only in statement-based (and if it was # enabled in row-based, it would fail as expected). --- source include/have_binlog_format_statement.inc +-- source include/have_binlog_format_mixed_or_statement.inc source include/master-slave.inc; diff --git a/mysql-test/t/rpl_stm_reset_slave.test b/mysql-test/t/rpl_stm_reset_slave.test index 282033bf6d1..6a99d4e1613 100644 --- a/mysql-test/t/rpl_stm_reset_slave.test +++ b/mysql-test/t/rpl_stm_reset_slave.test @@ -1,5 +1,5 @@ # TBF - difference in row level logging --- source include/have_binlog_format_statement.inc +-- source include/have_binlog_format_mixed_or_statement.inc -- source extra/rpl_tests/rpl_reset_slave.test # End of 4.1 tests diff --git a/mysql-test/t/rpl_stm_until.test b/mysql-test/t/rpl_stm_until.test index 9a4e4471fe1..f42965c0eb0 100644 --- a/mysql-test/t/rpl_stm_until.test +++ b/mysql-test/t/rpl_stm_until.test @@ -1,4 +1,4 @@ --- source include/have_binlog_format_statement.inc +-- source include/have_binlog_format_mixed_or_statement.inc -- source include/master-slave.inc # Test is dependent on binlog positions diff --git a/mysql-test/t/rpl_temp_table.test b/mysql-test/t/rpl_temp_table.test index c29fa8e676d..9b73961aeea 100644 --- a/mysql-test/t/rpl_temp_table.test +++ b/mysql-test/t/rpl_temp_table.test @@ -1,7 +1,7 @@ # drop table t1 t2 t3 are included int master-slave.inc # meaningful only in statement-based: --- source include/have_binlog_format_statement.inc +-- source include/have_binlog_format_mixed_or_statement.inc -- source include/master-slave.inc diff --git a/mysql-test/t/rpl_trigger.test b/mysql-test/t/rpl_trigger.test index 591941c19eb..0f87475ff07 100644 --- a/mysql-test/t/rpl_trigger.test +++ b/mysql-test/t/rpl_trigger.test @@ -2,7 +2,7 @@ # Test of triggers with replication # Adding statement include due to Bug 12574 # TODO: Remove statement include once 12574 is patched ---source include/have_binlog_format_statement.inc +--source include/have_binlog_format_mixed_or_statement.inc --source include/master-slave.inc --disable_warnings diff --git a/mysql-test/t/rpl_trunc_temp.test b/mysql-test/t/rpl_trunc_temp.test index 56f858dc9a2..28bcb0c06c3 100644 --- a/mysql-test/t/rpl_trunc_temp.test +++ b/mysql-test/t/rpl_trunc_temp.test @@ -1,5 +1,5 @@ # Requires statement logging --- source include/have_binlog_format_statement.inc +-- source include/have_binlog_format_mixed_or_statement.inc source include/master-slave.inc; diff --git a/mysql-test/t/user_var-binlog.test b/mysql-test/t/user_var-binlog.test index 7f1561b925b..6615e48ca42 100644 --- a/mysql-test/t/user_var-binlog.test +++ b/mysql-test/t/user_var-binlog.test @@ -1,5 +1,5 @@ # Requires statement logging --- source include/have_binlog_format_statement.inc +-- source include/have_binlog_format_mixed_or_statement.inc # TODO: Create row based version once $MYSQL_BINLOG has new RB version # Embedded server does not support binlogging --source include/not_embedded.inc diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 7561943d197..8f02c0565ff 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3135,7 +3135,11 @@ with --log-bin instead."); global_system_variables.binlog_format= BINLOG_FORMAT_ROW; else #endif +#if defined(HAVE_ROW_BASED_REPLICATION) + global_system_variables.binlog_format= BINLOG_FORMAT_MIXED; +#else global_system_variables.binlog_format= BINLOG_FORMAT_STMT; +#endif } /* Check that we have not let the format to unspecified at this point */ @@ -4936,7 +4940,13 @@ Disable with --skip-bdb (will save memory).", "supports only statement-based binary logging, so only 'statement' is " "a legal value." #endif - , 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }, + , 0, 0, 0, GET_STR, REQUIRED_ARG, +#ifdef HAVE_ROW_BASED_REPLICATION + BINLOG_FORMAT_MIXED +#else + BINLOG_FORMAT_STMT +#endif + , 0, 0, 0, 0, 0 }, {"binlog-do-db", OPT_BINLOG_DO_DB, "Tells the master it should log updates for the specified database, and exclude all others not explicitly mentioned.", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, From d67b341a3744f52fdce594e6d314dc6852b1e8f6 Mon Sep 17 00:00:00 2001 From: "mats@romeo.(none)" <> Date: Wed, 30 Aug 2006 14:10:53 +0200 Subject: [PATCH 15/27] Changes to make unit tests work on OS X and AIX --- unittest/unit.pl | 26 +------------------------- 1 file changed, 1 insertion(+), 25 deletions(-) diff --git a/unittest/unit.pl b/unittest/unit.pl index 3092a874192..28ebb44846d 100644 --- a/unittest/unit.pl +++ b/unittest/unit.pl @@ -1,19 +1,5 @@ #!/usr/bin/perl -# Override _command_line in the standard Perl test harness to prevent -# it from using "perl" to run the test scripts. -package MySQL::Straps; - -use base qw(Test::Harness::Straps); - -use strict; - -sub _command_line { - return $_[1] -} - -package main; - use Test::Harness qw(&runtests $verbose); use File::Find; @@ -37,9 +23,6 @@ unit - Run unit tests in directory my $cmd = shift; -# $Test::Harness::Verbose = 1; -# $Test::Harness::Debug = 1; - if (defined $cmd && exists $dispatch{$cmd}) { $dispatch{$cmd}->(@ARGV); } else { @@ -95,14 +78,7 @@ sub run_cmd (@) { if (@files > 0) { # Removing the first './' from the file names foreach (@files) { s!^\./!! } - - # Install the strap above instead of the default strap. Since - # we are replacing the straps under the feet of Test::Harness, - # we need to do some basic initializations in the new straps. - $Test::Harness::Strap = MySQL::Straps->new; - $Test::Harness::Strap->{callback} = \&Test::Harness::strap_callback - if defined &Test::Harness::strap_callback; - + $ENV{'HARNESS_PERL_SWITCHES'} .= q" -e 'exec @ARGV'"; runtests @files; } } From ebaaee05e1f142fdb2da516af473fc63888c68f2 Mon Sep 17 00:00:00 2001 From: "aelkin/elkin@dsl-hkigw8-feaaf900-177.dhcp.inet.fi" <> Date: Wed, 30 Aug 2006 21:43:05 +0300 Subject: [PATCH 16/27] WL#3368 mixed format as default Two minor fixes: 1. to make make test executes with mixed; 2. proper isolation of binlog_statement_insert_delayed from others through reset master cleaning up binlog todo: adapt this technique to other restarting for binlog tests --- Makefile.am | 6 +++++- mysql-test/t/binlog_statement_insert_delayed.test | 3 +++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index 8a575b3c365..bcffe546e7e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -118,7 +118,7 @@ test-unit: test-ps: cd mysql-test ; \ - ./mysql-test-run.pl $(force) --ps-protocol --mysqld=--binlog-format=statement + ./mysql-test-run.pl $(force) --ps-protocol --mysqld=--binlog-format=mixed test-nr: cd mysql-test ; \ @@ -129,6 +129,10 @@ test-pr: ./mysql-test-run.pl $(force) --ps-protocol --mysqld=--binlog-format=row test-ns: + cd mysql-test ; \ + ./mysql-test-run.pl $(force) --mysqld=--binlog-format=mixed + +test-binlog-statement: cd mysql-test ; \ ./mysql-test-run.pl $(force) --mysqld=--binlog-format=statement diff --git a/mysql-test/t/binlog_statement_insert_delayed.test b/mysql-test/t/binlog_statement_insert_delayed.test index 3b2c547a901..9b78296236f 100644 --- a/mysql-test/t/binlog_statement_insert_delayed.test +++ b/mysql-test/t/binlog_statement_insert_delayed.test @@ -3,4 +3,7 @@ -- source include/not_embedded.inc -- source include/have_binlog_format_statement.inc +-- disable_query_log +reset master; # get rid of previous tests binlog +-- enable_query_log -- source extra/binlog_tests/binlog_insert_delayed.test From 45568bbe11c225aacf87b48ac1d856c1092f0fb6 Mon Sep 17 00:00:00 2001 From: "aelkin/elkin@dsl-hkigw8-feaaf900-177.dhcp.inet.fi" <> Date: Thu, 31 Aug 2006 02:00:40 +0300 Subject: [PATCH 17/27] BUG#18822 LOAD DATA FROM MASTER corrupts data there is a bunch of dups. It has been decided to declare this feature as deprecated. --- sql/sql_yacc.yy | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 162b4183c84..bce9aed79fc 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -4800,14 +4800,16 @@ load: LOAD DATA_SYM load_data_lock opt_local INFILE TEXT_STRING_sys LOAD TABLE_SYM table_ident FROM MASTER_SYM { Lex->sql_command = SQLCOM_LOAD_MASTER_TABLE; + WARN_DEPRECATED("LOAD TABLE FROM MASTER", "mysqldump or future BACKUP/RESTORE DATABASE facility"); if (!Select->add_table_to_list(YYTHD, $3, NULL, TL_OPTION_UPDATING)) YYABORT; - + } | LOAD DATA_SYM FROM MASTER_SYM { Lex->sql_command = SQLCOM_LOAD_MASTER_DATA; + WARN_DEPRECATED("LOAD DATA FROM MASTER", "mysqldump or future BACKUP/RESTORE DATABASE facility"); }; opt_local: From 6ba388d17c96776d8a0551bc60be44883e0b3f8f Mon Sep 17 00:00:00 2001 From: "mats@romeo.(none)" <> Date: Wed, 6 Sep 2006 17:45:27 +0200 Subject: [PATCH 18/27] BUG#17620: Row-based replication fails when query cache enabled on slave Invalidating query cache when processing rows for a statement on the slave. --- mysql-test/r/rpl_row_basic_11bugs.result | 40 ++++++++++++++++++++++++ mysql-test/t/rpl_row_basic_11bugs.test | 40 ++++++++++++++++++++++++ sql/log_event.cc | 6 ++++ 3 files changed, 86 insertions(+) diff --git a/mysql-test/r/rpl_row_basic_11bugs.result b/mysql-test/r/rpl_row_basic_11bugs.result index e8be537816e..d768797717b 100644 --- a/mysql-test/r/rpl_row_basic_11bugs.result +++ b/mysql-test/r/rpl_row_basic_11bugs.result @@ -60,3 +60,43 @@ master-bin.000001 4 Format_desc 1 102 Server ver: SERVER_VERSION, Binlog ver: 4 master-bin.000001 102 Query 1 188 use `test`; CREATE TABLE t1 (a INT) master-bin.000001 188 Table_map 1 227 table_id: # (test.t1) master-bin.000001 227 Write_rows 1 266 table_id: # flags: STMT_END_F +DROP TABLE t1; +================ Test for BUG#17620 ================ +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +start slave; +**** On Slave **** +SET GLOBAL QUERY_CACHE_SIZE=0; +**** On Master **** +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2),(3); +**** On Slave **** +SET GLOBAL QUERY_CACHE_SIZE=16*1024*1024; +**** On Master **** +INSERT INTO t1 VALUES (4),(5),(6); +**** On Slave **** +SELECT * FROM t1; +a +1 +2 +3 +4 +5 +6 +**** On Master **** +INSERT INTO t1 VALUES (7),(8),(9); +**** On Slave **** +SELECT * FROM t1; +a +1 +2 +3 +4 +5 +6 +7 +8 +9 +DROP TABLE t1; diff --git a/mysql-test/t/rpl_row_basic_11bugs.test b/mysql-test/t/rpl_row_basic_11bugs.test index af7e9af4005..e636824284d 100644 --- a/mysql-test/t/rpl_row_basic_11bugs.test +++ b/mysql-test/t/rpl_row_basic_11bugs.test @@ -54,3 +54,43 @@ UPDATE t1 SET a=99 WHERE a = 0; --replace_result $SERVER_VERSION SERVER_VERSION --replace_regex /table_id: [0-9]+/table_id: #/ SHOW BINLOG EVENTS; + +DROP TABLE t1; + +# BUG#17620: Replicate (Row Based) Fails when Query Cache enabled on +# slave +--echo ================ Test for BUG#17620 ================ +--disable_query_log +--source include/master-slave-reset.inc +--enable_query_log + +--echo **** On Slave **** +connection slave; +SET GLOBAL QUERY_CACHE_SIZE=0; + +--echo **** On Master **** +connection master; +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2),(3); + +--echo **** On Slave **** +sync_slave_with_master; +SET GLOBAL QUERY_CACHE_SIZE=16*1024*1024; + +--echo **** On Master **** +connection master; +INSERT INTO t1 VALUES (4),(5),(6); + +--echo **** On Slave **** +sync_slave_with_master; +SELECT * FROM t1; + +--echo **** On Master **** +connection master; +INSERT INTO t1 VALUES (7),(8),(9); + +--echo **** On Slave **** +sync_slave_with_master; +SELECT * FROM t1; + +DROP TABLE t1; diff --git a/sql/log_event.cc b/sql/log_event.cc index ebd90446a7e..d5da1468b14 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -5425,6 +5425,9 @@ int Rows_log_event::exec_event(st_relay_log_info *rli) /* When the open and locking succeeded, we add all the tables to the table map and remove them from tables to lock. + + We also invalidate the query cache for all the tables, since + they will now be changed. */ TABLE_LIST *ptr; @@ -5433,6 +5436,9 @@ int Rows_log_event::exec_event(st_relay_log_info *rli) rli->m_table_map.set_table(ptr->table_id, ptr->table); rli->touching_table(ptr->db, ptr->table_name, ptr->table_id); } +#ifdef HAVE_QUERY_CACHE + query_cache.invalidate_locked_for_write(rli->tables_to_lock); +#endif rli->clear_tables_to_lock(); } From 87de41ad232b0faa6351110f1d6092b3056f8d0a Mon Sep 17 00:00:00 2001 From: "guilhem@gbichot3.local" <> Date: Thu, 7 Sep 2006 18:01:42 +0200 Subject: [PATCH 19/27] Removing sleeps; rpl_row_basic_8partition falls from 2 minutes 15 seconds to less than a second. The sleeps used to be necessary but not anymore as NDB has been fixed wrt sync_slave_with_master. --- mysql-test/include/rpl_multi_engine3.inc | 3 --- 1 file changed, 3 deletions(-) diff --git a/mysql-test/include/rpl_multi_engine3.inc b/mysql-test/include/rpl_multi_engine3.inc index 5d8f7e46409..e1a80df336c 100644 --- a/mysql-test/include/rpl_multi_engine3.inc +++ b/mysql-test/include/rpl_multi_engine3.inc @@ -28,7 +28,6 @@ INSERT INTO t1 VALUES(412,1,'Testing MySQL databases is a cool ', select id,hex(b1),vc,bc,d,f,total,y,t from t1 order by id; sync_slave_with_master; ---sleep 5 --echo --- Select from t1 on slave --- select id,hex(b1),vc,bc,d,f,total,y,t from t1 order by id; @@ -44,7 +43,6 @@ SELECT id,hex(b1),vc,bc,d,f,total,y,t FROM t1 WHERE id = 412; # into the binlog other wise we will miss the update. sync_slave_with_master; ---sleep 5 --echo --- Check Update on slave --- SELECT id,hex(b1),vc,bc,d,f,total,y,t FROM t1 WHERE id = 412; @@ -56,7 +54,6 @@ DELETE FROM t1 WHERE id = 42; SELECT COUNT(*) FROM t1; sync_slave_with_master; ---sleep 5 --echo --- Show current count on slave for t1 --- SELECT COUNT(*) FROM t1; From 090e02092112aafd77589a2c369e392b53c7fcbd Mon Sep 17 00:00:00 2001 From: "mats@romeo.(none)" <> Date: Fri, 8 Sep 2006 10:20:14 +0200 Subject: [PATCH 20/27] Patches to fix problems on Windows --- sql/log_event.cc | 2 +- sql/rpl_utility.cc | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/sql/log_event.cc b/sql/log_event.cc index 2a8fd085eee..0f2bf10212b 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -5369,7 +5369,7 @@ unpack_row(RELAY_LOG_INFO *rli, if (master_reclength) { if (*field_ptr) - *master_reclength = (*field_ptr)->ptr - table->record[0]; + *master_reclength = (*field_ptr)->ptr - (char*) table->record[0]; else *master_reclength = table->s->reclength; } diff --git a/sql/rpl_utility.cc b/sql/rpl_utility.cc index fc706178aa3..5405d022223 100644 --- a/sql/rpl_utility.cc +++ b/sql/rpl_utility.cc @@ -96,6 +96,8 @@ field_length_from_packed(enum_field_types const field_type, length= ~0UL; // NYI break; } + + return length; } /********************************************************************* From f513461030ea9002fbb9d0864914d54706f0e606 Mon Sep 17 00:00:00 2001 From: "mats@romeo.(none)" <> Date: Mon, 11 Sep 2006 10:19:11 +0200 Subject: [PATCH 21/27] WL#3259 (More columns on slave than on master): Adding files to CMakeLists.txt --- sql/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt index 95073b95ad6..8ca38e7b924 100644 --- a/sql/CMakeLists.txt +++ b/sql/CMakeLists.txt @@ -53,7 +53,7 @@ ADD_EXECUTABLE(mysqld ../sql-common/client.c derror.cc des_key_file.cc time.cc tztime.cc uniques.cc unireg.cc item_xmlfunc.cc rpl_tblmap.cc sql_binlog.cc event_scheduler.cc event_timed.cc sql_tablespace.cc events.cc ../sql-common/my_user.c - partition_info.cc rpl_injector.cc sql_locale.cc + partition_info.cc rpl_utility.cc rpl_injector.cc sql_locale.cc ${PROJECT_SOURCE_DIR}/sql/sql_yacc.cc ${PROJECT_SOURCE_DIR}/sql/sql_yacc.h ${PROJECT_SOURCE_DIR}/include/mysqld_error.h From 6ad198e997e82fdc5b44b1a7db2a8856e775b674 Mon Sep 17 00:00:00 2001 From: "lars/lthalmann@mysql.com/dl145j.mysql.com" <> Date: Mon, 11 Sep 2006 14:45:40 +0200 Subject: [PATCH 22/27] Fix WARN_DEPRECATED for 5.0 (it is in 5.1 we should have the extra arguments) --- sql/sql_yacc.yy | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index fbde9e2884f..375f49b1120 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -6873,7 +6873,7 @@ load: LOAD DATA_SYM YYABORT; } lex->sql_command = SQLCOM_LOAD_MASTER_TABLE; - WARN_DEPRECATED(yythd, "5.2", "LOAD TABLE FROM MASTER", + WARN_DEPRECATED("LOAD TABLE FROM MASTER", "mysqldump or future " "BACKUP/RESTORE DATABASE facility"); if (!Select->add_table_to_list(YYTHD, $3, NULL, TL_OPTION_UPDATING)) @@ -6914,7 +6914,7 @@ load_data: FROM MASTER_SYM { Lex->sql_command = SQLCOM_LOAD_MASTER_DATA; - WARN_DEPRECATED(yythd, "5.2", "LOAD DATA FROM MASTER", + WARN_DEPRECATED("LOAD DATA FROM MASTER", "mysqldump or future " "BACKUP/RESTORE DATABASE facility"); }; From 388b4df74eaed770759ef8566f7ee38e724bab83 Mon Sep 17 00:00:00 2001 From: "lars/lthalmann@mysql.com/dl145k.mysql.com" <> Date: Mon, 11 Sep 2006 19:45:09 +0200 Subject: [PATCH 23/27] manual merge --- sql/sql_yacc.yy | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 87657d5f4a6..93a23873c73 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -8744,9 +8744,6 @@ load: LOAD DATA_SYM YYABORT; } lex->sql_command = SQLCOM_LOAD_MASTER_TABLE; - WARN_DEPRECATED("LOAD TABLE FROM MASTER", - "mysqldump or future " - "BACKUP/RESTORE DATABASE facility"); if (!Select->add_table_to_list(YYTHD, $3, NULL, TL_OPTION_UPDATING)) YYABORT; }; @@ -8785,7 +8782,7 @@ load_data: FROM MASTER_SYM { Lex->sql_command = SQLCOM_LOAD_MASTER_DATA; - WARN_DEPRECATED("LOAD DATA FROM MASTER", + WARN_DEPRECATED(yythd, "5.2", "LOAD DATA FROM MASTER", "mysqldump or future " "BACKUP/RESTORE DATABASE facility"); }; From a8836b7dde9db79ddafdffd2277e398cf1b07527 Mon Sep 17 00:00:00 2001 From: "guilhem@gbichot3.local" <> Date: Tue, 12 Sep 2006 15:42:13 +0200 Subject: [PATCH 24/27] Fixing problems I identified in my auto_increment work pushed in July (as part of the auto_increment cleanup of WL#3146; let's not be sad, that monster push still removed serious bugs): one problem with INSERT DELAYED (unexpected interval releases), one with stored functions (wrong auto_inc binlogging). These bugs were not released. --- .../binlog_tests/binlog_insert_delayed.test | 12 ++++++--- .../extra/rpl_tests/rpl_foreign_key.test | 2 +- mysql-test/extra/rpl_tests/rpl_insert_id.test | 26 ++++++++++++++++-- mysql-test/r/binlog_row_binlog.result | 18 +++++++++++++ .../r/binlog_statement_insert_delayed.result | 14 ++++++++++ mysql-test/r/binlog_stm_binlog.result | 18 +++++++++++++ mysql-test/r/rpl_insert_id.result | 27 ++++++++++++++++++- mysql-test/r/rpl_loaddata.result | 6 ++--- mysql-test/r/rpl_ndb_insert_ignore.result | 8 +++--- sql/log.cc | 3 --- sql/sp_head.cc | 13 ++++++++- sql/sql_class.cc | 6 +++++ sql/sql_insert.cc | 21 ++++++++++++--- sql/sql_parse.cc | 9 +++++-- 14 files changed, 160 insertions(+), 23 deletions(-) diff --git a/mysql-test/extra/binlog_tests/binlog_insert_delayed.test b/mysql-test/extra/binlog_tests/binlog_insert_delayed.test index 596bb1d5772..6f504fded96 100644 --- a/mysql-test/extra/binlog_tests/binlog_insert_delayed.test +++ b/mysql-test/extra/binlog_tests/binlog_insert_delayed.test @@ -7,14 +7,20 @@ set @@session.auto_increment_increment=1, @@session.auto_increment_offset=1; insert delayed into t1 values (207); # We use sleeps between statements, that's the only way to get a -# repeatable binlog in a normal test run and under Valgrind. -# It may be that the "binlog missing rows" of BUG#20821 shows up -# here. +# repeatable binlog in a normal test run and under Valgrind. The +# reason is that without sleeps, rows of different INSERT DELAYEDs +# sometimes group together and sometimes not, so the table may be +# unlocked/relocked causing a different number of table map log +# events. sleep 2; insert delayed into t1 values (null); sleep 2; insert delayed into t1 values (300); sleep 2; # time for the delayed queries to reach disk +insert delayed into t1 values (null),(null),(null),(null); +sleep 2; +insert delayed into t1 values (null),(null),(400),(null); +sleep 2; select * from t1; --replace_column 2 # 5 # --replace_regex /table_id: [0-9]+/table_id: #/ diff --git a/mysql-test/extra/rpl_tests/rpl_foreign_key.test b/mysql-test/extra/rpl_tests/rpl_foreign_key.test index d5589d4b5ea..0f4cd856db6 100644 --- a/mysql-test/extra/rpl_tests/rpl_foreign_key.test +++ b/mysql-test/extra/rpl_tests/rpl_foreign_key.test @@ -31,4 +31,4 @@ connection master; SET FOREIGN_KEY_CHECKS=0; DROP TABLE IF EXISTS t1,t2,t3; SET FOREIGN_KEY_CHECKS=1; - +sync_slave_with_master; diff --git a/mysql-test/extra/rpl_tests/rpl_insert_id.test b/mysql-test/extra/rpl_tests/rpl_insert_id.test index 79f8c39e152..88e864967de 100644 --- a/mysql-test/extra/rpl_tests/rpl_insert_id.test +++ b/mysql-test/extra/rpl_tests/rpl_insert_id.test @@ -289,8 +289,30 @@ select * from t1; select * from t2; connection master; -drop table t1, t2; +drop table t1; drop function insid; -sync_slave_with_master; +truncate table t2; +create table t1 (n int primary key auto_increment not null, +b int, unique(b)); +delimiter |; +create procedure foo() +begin + insert into t1 values(null,10); + insert ignore into t1 values(null,10); + insert ignore into t1 values(null,10); + insert into t2 values(null,3); +end| +delimiter ;| +call foo(); +select * from t1; +select * from t2; +sync_slave_with_master; +select * from t1; +select * from t2; + +connection master; +drop table t1, t2; +drop procedure foo; +sync_slave_with_master; diff --git a/mysql-test/r/binlog_row_binlog.result b/mysql-test/r/binlog_row_binlog.result index 28f2284d3d2..8d5025f7602 100644 --- a/mysql-test/r/binlog_row_binlog.result +++ b/mysql-test/r/binlog_row_binlog.result @@ -250,11 +250,21 @@ set @@session.auto_increment_increment=1, @@session.auto_increment_offset=1; insert delayed into t1 values (207); insert delayed into t1 values (null); insert delayed into t1 values (300); +insert delayed into t1 values (null),(null),(null),(null); +insert delayed into t1 values (null),(null),(400),(null); select * from t1; a 207 208 300 +301 +302 +303 +304 +305 +306 +400 +401 show binlog events from 102; Log_name Pos Event_type Server_id End_log_pos Info master-bin.000001 # Query 1 # use `test`; create table t1 (id tinyint auto_increment primary key) @@ -268,4 +278,12 @@ master-bin.000001 # Table_map 1 # table_id: # (test.t1) master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F master-bin.000001 # Table_map 1 # table_id: # (test.t1) master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map 1 # table_id: # (test.t1) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map 1 # table_id: # (test.t1) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map 1 # table_id: # (test.t1) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map 1 # table_id: # (test.t1) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F drop table t1; diff --git a/mysql-test/r/binlog_statement_insert_delayed.result b/mysql-test/r/binlog_statement_insert_delayed.result index bae01f7dc5d..3cf6ba14e02 100644 --- a/mysql-test/r/binlog_statement_insert_delayed.result +++ b/mysql-test/r/binlog_statement_insert_delayed.result @@ -3,11 +3,21 @@ set @@session.auto_increment_increment=1, @@session.auto_increment_offset=1; insert delayed into t1 values (207); insert delayed into t1 values (null); insert delayed into t1 values (300); +insert delayed into t1 values (null),(null),(null),(null); +insert delayed into t1 values (null),(null),(400),(null); select * from t1; a 207 208 300 +301 +302 +303 +304 +305 +306 +400 +401 show binlog events from 102; Log_name Pos Event_type Server_id End_log_pos Info master-bin.000001 # Query 1 # use `test`; create table t1 (a int not null auto_increment, primary key (a)) engine=myisam @@ -15,4 +25,8 @@ master-bin.000001 # Query 1 # use `test`; insert delayed into t1 values (207) master-bin.000001 # Intvar 1 # INSERT_ID=208 master-bin.000001 # Query 1 # use `test`; insert delayed into t1 values (null) master-bin.000001 # Query 1 # use `test`; insert delayed into t1 values (300) +master-bin.000001 # Intvar 1 # INSERT_ID=301 +master-bin.000001 # Query 1 # use `test`; insert delayed into t1 values (null),(null),(null),(null) +master-bin.000001 # Intvar 1 # INSERT_ID=305 +master-bin.000001 # Query 1 # use `test`; insert delayed into t1 values (null),(null),(400),(null) drop table t1; diff --git a/mysql-test/r/binlog_stm_binlog.result b/mysql-test/r/binlog_stm_binlog.result index 171a3c11f07..6589392fe79 100644 --- a/mysql-test/r/binlog_stm_binlog.result +++ b/mysql-test/r/binlog_stm_binlog.result @@ -160,11 +160,21 @@ set @@session.auto_increment_increment=1, @@session.auto_increment_offset=1; insert delayed into t1 values (207); insert delayed into t1 values (null); insert delayed into t1 values (300); +insert delayed into t1 values (null),(null),(null),(null); +insert delayed into t1 values (null),(null),(400),(null); select * from t1; a 207 208 300 +301 +302 +303 +304 +305 +306 +400 +401 show binlog events from 102; Log_name Pos Event_type Server_id End_log_pos Info master-bin.000001 # Query 1 # use `test`; create table t1 (id tinyint auto_increment primary key) @@ -178,4 +188,12 @@ master-bin.000001 # Table_map 1 # table_id: # (test.t1) master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F master-bin.000001 # Table_map 1 # table_id: # (test.t1) master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map 1 # table_id: # (test.t1) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map 1 # table_id: # (test.t1) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map 1 # table_id: # (test.t1) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F +master-bin.000001 # Table_map 1 # table_id: # (test.t1) +master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F drop table t1; diff --git a/mysql-test/r/rpl_insert_id.result b/mysql-test/r/rpl_insert_id.result index 3c33fe1be2b..19518e8745c 100644 --- a/mysql-test/r/rpl_insert_id.result +++ b/mysql-test/r/rpl_insert_id.result @@ -267,5 +267,30 @@ select * from t2; id last_id 4 0 8 0 -drop table t1, t2; +drop table t1; drop function insid; +truncate table t2; +create table t1 (n int primary key auto_increment not null, +b int, unique(b)); +create procedure foo() +begin +insert into t1 values(null,10); +insert ignore into t1 values(null,10); +insert ignore into t1 values(null,10); +insert into t2 values(null,3); +end| +call foo(); +select * from t1; +n b +1 10 +select * from t2; +id last_id +1 3 +select * from t1; +n b +1 10 +select * from t2; +id last_id +1 3 +drop table t1, t2; +drop procedure foo; diff --git a/mysql-test/r/rpl_loaddata.result b/mysql-test/r/rpl_loaddata.result index c22815186d1..cae11e98caa 100644 --- a/mysql-test/r/rpl_loaddata.result +++ b/mysql-test/r/rpl_loaddata.result @@ -28,7 +28,7 @@ day id category name 2003-03-22 2416 a bbbbb show master status; File Position Binlog_Do_DB Binlog_Ignore_DB -slave-bin.000001 1248 +slave-bin.000001 1276 drop table t1; drop table t2; drop table t3; @@ -39,7 +39,7 @@ set global sql_slave_skip_counter=1; start slave; show slave status; Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master -# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 1765 # # master-bin.000001 Yes Yes # 0 0 1765 # None 0 No # +# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 1793 # # master-bin.000001 Yes Yes # 0 0 1793 # None 0 No # set sql_log_bin=0; delete from t1; set sql_log_bin=1; @@ -49,7 +49,7 @@ change master to master_user='test'; change master to master_user='root'; show slave status; Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master -# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 1800 # # master-bin.000001 No No # 0 0 1800 # None 0 No # +# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 1828 # # master-bin.000001 No No # 0 0 1828 # None 0 No # set global sql_slave_skip_counter=1; start slave; set sql_log_bin=0; diff --git a/mysql-test/r/rpl_ndb_insert_ignore.result b/mysql-test/r/rpl_ndb_insert_ignore.result index 4d55328a5d7..030845e89e2 100644 --- a/mysql-test/r/rpl_ndb_insert_ignore.result +++ b/mysql-test/r/rpl_ndb_insert_ignore.result @@ -30,16 +30,16 @@ a b 2 2 3 3 4 4 -7 5 -10 6 +5 5 +6 6 SELECT * FROM t1 ORDER BY a; a b 1 1 2 2 3 3 4 4 -7 5 -10 6 +5 5 +6 6 drop table t1; CREATE TABLE t1 ( a int unsigned not null auto_increment primary key, diff --git a/sql/log.cc b/sql/log.cc index 0336a11d3ad..d15a23de51e 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -3416,9 +3416,6 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info) } } } - /* Forget those values, for next binlogger: */ - thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt= 0; - thd->auto_inc_intervals_in_cur_stmt_for_binlog.empty(); } /* diff --git a/sql/sp_head.cc b/sql/sp_head.cc index fc4aa5e26d6..f9c4cc8c68f 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -794,7 +794,7 @@ int cmp_splocal_locations(Item_splocal * const *a, Item_splocal * const *b) This set is produced by tracking user variable reads during statement execution. - Fo SPs, this has the following implications: + For SPs, this has the following implications: 1) thd->user_var_events may contain events from several SP statements and needs to be valid after exection of these statements was finished. In order to achieve that, we @@ -807,6 +807,14 @@ int cmp_splocal_locations(Item_splocal * const *a, Item_splocal * const *b) reset_dynamic(&thd->user_var_events); calls in several different places. (TODO cosider moving this into mysql_bin_log.write() function) + + 4.2 Auto_increment storage in binlog + + As we may write two statements to binlog from one single logical statement + (case of "SELECT func1(),func2()": it is binlogged as "SELECT func1()" and + then "SELECT func2()"), we need to reset auto_increment binlog variables + after each binlogged SELECT. Otherwise, the auto_increment value of the + first SELECT would be used for the second too. */ @@ -1526,6 +1534,9 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, "failed to reflect this change in the binary log"); } reset_dynamic(&thd->user_var_events); + /* Forget those values, in case more function calls are binlogged: */ + thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt= 0; + thd->auto_inc_intervals_in_cur_stmt_for_binlog.empty(); } } diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 838d91f9c31..35b527584dc 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -634,6 +634,12 @@ bool THD::store_globals() void THD::cleanup_after_query() { + if (!in_sub_stmt) /* stored functions and triggers are a special case */ + { + /* Forget those values, for next binlogger: */ + stmt_depends_on_first_successful_insert_id_in_prev_stmt= 0; + auto_inc_intervals_in_cur_stmt_for_binlog.empty(); + } if (first_successful_insert_id_in_cur_stmt > 0) { /* set what LAST_INSERT_ID() will return */ diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 92cad471cf2..8b51ccef9f9 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -563,7 +563,6 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, free_underlaid_joins(thd, &thd->lex->select_lex); joins_freed= TRUE; - table->file->ha_release_auto_increment(); /* Now all rows are inserted. Time to update logs and sends response to @@ -582,6 +581,11 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, else #endif { + /* + Do not do this release if this is a delayed insert, it would steal + auto_inc values from the delayed_insert thread as they share TABLE. + */ + table->file->ha_release_auto_increment(); if (!thd->prelocked_mode && table->file->ha_end_bulk_insert() && !error) { table->file->print_error(my_errno,MYF(0)); @@ -2106,6 +2110,16 @@ bool delayed_insert::handle_inserts(void) thd.start_time=row->start_time; thd.query_start_used=row->query_start_used; + /* + To get the exact auto_inc interval to store in the binlog we must not + use values from the previous interval (of the previous rows). + */ + bool log_query= (row->log_query && row->query.str != NULL); + if (log_query) + { + table->file->ha_release_auto_increment(); + thd.auto_inc_intervals_in_cur_stmt_for_binlog.empty(); + } thd.first_successful_insert_id_in_prev_stmt= row->first_successful_insert_id_in_prev_stmt; thd.stmt_depends_on_first_successful_insert_id_in_prev_stmt= @@ -2146,7 +2160,7 @@ bool delayed_insert::handle_inserts(void) table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE); } - if (row->log_query && row->query.str != NULL && mysql_bin_log.is_open()) + if (log_query && mysql_bin_log.is_open()) { /* If the query has several rows to insert, only the first row will come @@ -2542,7 +2556,6 @@ bool select_insert::send_data(List &values) table->next_number_field->reset(); } } - table->file->ha_release_auto_increment(); DBUG_RETURN(error); } @@ -2616,6 +2629,7 @@ void select_insert::send_error(uint errcode,const char *err) } } ha_rollback_stmt(thd); + table->file->ha_release_auto_increment(); DBUG_VOID_RETURN; } @@ -2666,6 +2680,7 @@ bool select_insert::send_eof() } if ((error2=ha_autocommit_or_rollback(thd,error)) && ! error) error=error2; + table->file->ha_release_auto_increment(); if (error) { table->file->print_error(error,MYF(0)); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 2aceccd1c92..0bee8fa0c53 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -5861,9 +5861,14 @@ void mysql_reset_thd_for_next_command(THD *thd) DBUG_ASSERT(!thd->spcont); /* not for substatements of routines */ thd->free_list= 0; thd->select_number= 1; + /* + Those two lines below are theoretically unneeded as + THD::cleanup_after_query() should take care of this already. + */ thd->auto_inc_intervals_in_cur_stmt_for_binlog.empty(); - thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt= - thd->query_start_used= 0; + thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt= 0; + + thd->query_start_used= 0; thd->is_fatal_error= thd->time_zone_used= 0; thd->server_status&= ~ (SERVER_MORE_RESULTS_EXISTS | SERVER_QUERY_NO_INDEX_USED | From 9a87889482e8e8daa28a14906aabaae042a82270 Mon Sep 17 00:00:00 2001 From: "aivanov/alexi@mysql.com/mysqld.localdomain" <> Date: Thu, 14 Sep 2006 03:37:40 +0400 Subject: [PATCH 25/27] WL#3247,#3248: Adding [GLOBAL|SESSION]_STATUS and [GLOBAL|SESSION]_VARIABLES tables to INFORMATION_SCHEMA. --- mysql-test/r/information_schema.result | 16 +- mysql-test/r/information_schema_db.result | 4 + mysql-test/r/status.result | 23 +++ mysql-test/r/variables.result | 151 ++++++++++++++ mysql-test/t/status.test | 7 + mysql-test/t/variables.test | 50 +++++ sql/sql_show.cc | 233 +++++++++++++++++++++- sql/table.h | 4 + 8 files changed, 479 insertions(+), 9 deletions(-) diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result index 077fa0f2376..9ba55e42326 100644 --- a/mysql-test/r/information_schema.result +++ b/mysql-test/r/information_schema.result @@ -46,6 +46,8 @@ COLUMN_PRIVILEGES ENGINES EVENTS FILES +GLOBAL_STATUS +GLOBAL_VARIABLES KEY_COLUMN_USAGE PARTITIONS PLUGINS @@ -54,6 +56,8 @@ REFERENTIAL_CONSTRAINTS ROUTINES SCHEMATA SCHEMA_PRIVILEGES +SESSION_STATUS +SESSION_VARIABLES STATISTICS TABLES TABLE_CONSTRAINTS @@ -758,6 +762,7 @@ table_schema table_name column_name information_schema COLUMNS COLUMN_TYPE information_schema EVENTS EVENT_DEFINITION information_schema EVENTS SQL_MODE +information_schema GLOBAL_VARIABLES VARIABLE_VALUE information_schema PARTITIONS PARTITION_EXPRESSION information_schema PARTITIONS SUBPARTITION_EXPRESSION information_schema PARTITIONS PARTITION_DESCRIPTION @@ -765,6 +770,7 @@ information_schema PLUGINS PLUGIN_DESCRIPTION information_schema PROCESSLIST INFO information_schema ROUTINES ROUTINE_DEFINITION information_schema ROUTINES SQL_MODE +information_schema SESSION_VARIABLES VARIABLE_VALUE information_schema TRIGGERS ACTION_CONDITION information_schema TRIGGERS ACTION_STATEMENT information_schema TRIGGERS SQL_MODE @@ -847,7 +853,7 @@ delete from mysql.db where user='mysqltest_4'; flush privileges; SELECT table_schema, count(*) FROM information_schema.TABLES where TABLE_SCHEMA!='cluster' GROUP BY TABLE_SCHEMA; table_schema count(*) -information_schema 23 +information_schema 27 mysql 21 create table t1 (i int, j int); create trigger trg1 before insert on t1 for each row @@ -1240,6 +1246,8 @@ COLUMN_PRIVILEGES TABLE_SCHEMA ENGINES ENGINE EVENTS EVENT_SCHEMA FILES TABLE_SCHEMA +GLOBAL_STATUS VARIABLE_NAME +GLOBAL_VARIABLES VARIABLE_NAME KEY_COLUMN_USAGE CONSTRAINT_SCHEMA PARTITIONS TABLE_SCHEMA PLUGINS PLUGIN_NAME @@ -1248,6 +1256,8 @@ REFERENTIAL_CONSTRAINTS CONSTRAINT_SCHEMA ROUTINES ROUTINE_SCHEMA SCHEMATA SCHEMA_NAME SCHEMA_PRIVILEGES TABLE_SCHEMA +SESSION_STATUS VARIABLE_NAME +SESSION_VARIABLES VARIABLE_NAME STATISTICS TABLE_SCHEMA TABLES TABLE_SCHEMA TABLE_CONSTRAINTS CONSTRAINT_SCHEMA @@ -1278,6 +1288,8 @@ COLUMN_PRIVILEGES TABLE_SCHEMA ENGINES ENGINE EVENTS EVENT_SCHEMA FILES TABLE_SCHEMA +GLOBAL_STATUS VARIABLE_NAME +GLOBAL_VARIABLES VARIABLE_NAME KEY_COLUMN_USAGE CONSTRAINT_SCHEMA PARTITIONS TABLE_SCHEMA PLUGINS PLUGIN_NAME @@ -1286,6 +1298,8 @@ REFERENTIAL_CONSTRAINTS CONSTRAINT_SCHEMA ROUTINES ROUTINE_SCHEMA SCHEMATA SCHEMA_NAME SCHEMA_PRIVILEGES TABLE_SCHEMA +SESSION_STATUS VARIABLE_NAME +SESSION_VARIABLES VARIABLE_NAME STATISTICS TABLE_SCHEMA TABLES TABLE_SCHEMA TABLE_CONSTRAINTS CONSTRAINT_SCHEMA diff --git a/mysql-test/r/information_schema_db.result b/mysql-test/r/information_schema_db.result index faba5e8d83c..db14b7b6600 100644 --- a/mysql-test/r/information_schema_db.result +++ b/mysql-test/r/information_schema_db.result @@ -13,6 +13,8 @@ COLUMN_PRIVILEGES ENGINES EVENTS FILES +GLOBAL_STATUS +GLOBAL_VARIABLES KEY_COLUMN_USAGE PARTITIONS PLUGINS @@ -21,6 +23,8 @@ REFERENTIAL_CONSTRAINTS ROUTINES SCHEMATA SCHEMA_PRIVILEGES +SESSION_STATUS +SESSION_VARIABLES STATISTICS TABLES TABLE_CONSTRAINTS diff --git a/mysql-test/r/status.result b/mysql-test/r/status.result index 83c6a6f5288..48a1d80dc7e 100644 --- a/mysql-test/r/status.result +++ b/mysql-test/r/status.result @@ -3,6 +3,10 @@ show status like 'Table_lock%'; Variable_name Value Table_locks_immediate 0 Table_locks_waited 0 +select * from information_schema.session_status where variable_name like 'Table_lock%'; +VARIABLE_NAME VARIABLE_VALUE +TABLE_LOCKS_IMMEDIATE 0.0000000 +TABLE_LOCKS_WAITED 0.0000000 SET SQL_LOG_BIN=0; drop table if exists t1; create table t1(n int) engine=myisam; @@ -16,6 +20,10 @@ show status like 'Table_lock%'; Variable_name Value Table_locks_immediate 3 Table_locks_waited 1 +select * from information_schema.session_status where variable_name like 'Table_lock%'; +VARIABLE_NAME VARIABLE_VALUE +TABLE_LOCKS_IMMEDIATE 3.0000000 +TABLE_LOCKS_WAITED 1.0000000 drop table t1; select 1; 1 @@ -53,21 +61,36 @@ FLUSH STATUS; SHOW STATUS LIKE 'max_used_connections'; Variable_name Value Max_used_connections 2 +SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME LIKE 'max_used_connections'; +VARIABLE_NAME VARIABLE_VALUE +MAX_USED_CONNECTIONS 2.0000000 SET @save_thread_cache_size=@@thread_cache_size; SET GLOBAL thread_cache_size=3; SHOW STATUS LIKE 'max_used_connections'; Variable_name Value Max_used_connections 4 +SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME LIKE 'max_used_connections'; +VARIABLE_NAME VARIABLE_VALUE +MAX_USED_CONNECTIONS 4.0000000 FLUSH STATUS; SHOW STATUS LIKE 'max_used_connections'; Variable_name Value Max_used_connections 3 +SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME LIKE 'max_used_connections'; +VARIABLE_NAME VARIABLE_VALUE +MAX_USED_CONNECTIONS 3.0000000 SHOW STATUS LIKE 'max_used_connections'; Variable_name Value Max_used_connections 4 +SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME LIKE 'max_used_connections'; +VARIABLE_NAME VARIABLE_VALUE +MAX_USED_CONNECTIONS 4.0000000 SHOW STATUS LIKE 'max_used_connections'; Variable_name Value Max_used_connections 5 +SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME LIKE 'max_used_connections'; +VARIABLE_NAME VARIABLE_VALUE +MAX_USED_CONNECTIONS 5.0000000 SET GLOBAL thread_cache_size=@save_thread_cache_size; show status like 'com_show_status'; Variable_name Value diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result index 3b6bfc60a80..5526ca8634f 100644 --- a/mysql-test/r/variables.result +++ b/mysql-test/r/variables.result @@ -103,21 +103,36 @@ set max_join_size=100; show variables like 'max_join_size'; Variable_name Value max_join_size 100 +select * from information_schema.session_variables where variable_name like 'max_join_size'; +VARIABLE_NAME VARIABLE_VALUE +MAX_JOIN_SIZE 100 show global variables like 'max_join_size'; Variable_name Value max_join_size 10 +select * from information_schema.global_variables where variable_name like 'max_join_size'; +VARIABLE_NAME VARIABLE_VALUE +MAX_JOIN_SIZE 10 set GLOBAL max_join_size=2000; show global variables like 'max_join_size'; Variable_name Value max_join_size 2000 +select * from information_schema.global_variables where variable_name like 'max_join_size'; +VARIABLE_NAME VARIABLE_VALUE +MAX_JOIN_SIZE 2000 set max_join_size=DEFAULT; show variables like 'max_join_size'; Variable_name Value max_join_size 2000 +select * from information_schema.session_variables where variable_name like 'max_join_size'; +VARIABLE_NAME VARIABLE_VALUE +MAX_JOIN_SIZE 2000 set GLOBAL max_join_size=DEFAULT; show global variables like 'max_join_size'; Variable_name Value max_join_size HA_POS_ERROR +select * from information_schema.global_variables where variable_name like 'max_join_size'; +VARIABLE_NAME VARIABLE_VALUE +MAX_JOIN_SIZE HA_POS_ERROR set @@max_join_size=1000, @@global.max_join_size=2000; select @@local.max_join_size, @@global.max_join_size; @@local.max_join_size @@global.max_join_size @@ -149,14 +164,23 @@ set global concurrent_insert=2; show variables like 'concurrent_insert'; Variable_name Value concurrent_insert 2 +select * from information_schema.session_variables where variable_name like 'concurrent_insert'; +VARIABLE_NAME VARIABLE_VALUE +CONCURRENT_INSERT 2 set global concurrent_insert=1; show variables like 'concurrent_insert'; Variable_name Value concurrent_insert 1 +select * from information_schema.session_variables where variable_name like 'concurrent_insert'; +VARIABLE_NAME VARIABLE_VALUE +CONCURRENT_INSERT 1 set global concurrent_insert=0; show variables like 'concurrent_insert'; Variable_name Value concurrent_insert 0 +select * from information_schema.session_variables where variable_name like 'concurrent_insert'; +VARIABLE_NAME VARIABLE_VALUE +CONCURRENT_INSERT 0 set global concurrent_insert=DEFAULT; select @@concurrent_insert; @@concurrent_insert @@ -165,26 +189,44 @@ set global timed_mutexes=ON; show variables like 'timed_mutexes'; Variable_name Value timed_mutexes ON +select * from information_schema.session_variables where variable_name like 'timed_mutexes'; +VARIABLE_NAME VARIABLE_VALUE +TIMED_MUTEXES ON set global timed_mutexes=0; show variables like 'timed_mutexes'; Variable_name Value timed_mutexes OFF +select * from information_schema.session_variables where variable_name like 'timed_mutexes'; +VARIABLE_NAME VARIABLE_VALUE +TIMED_MUTEXES OFF set storage_engine=MYISAM, storage_engine="HEAP", global storage_engine="MERGE"; show local variables like 'storage_engine'; Variable_name Value storage_engine MEMORY +select * from information_schema.session_variables where variable_name like 'storage_engine'; +VARIABLE_NAME VARIABLE_VALUE +STORAGE_ENGINE MEMORY show global variables like 'storage_engine'; Variable_name Value storage_engine MRG_MYISAM +select * from information_schema.global_variables where variable_name like 'storage_engine'; +VARIABLE_NAME VARIABLE_VALUE +STORAGE_ENGINE MRG_MYISAM set GLOBAL query_cache_size=100000; set GLOBAL myisam_max_sort_file_size=2000000; show global variables like 'myisam_max_sort_file_size'; Variable_name Value myisam_max_sort_file_size 1048576 +select * from information_schema.global_variables where variable_name like 'myisam_max_sort_file_size'; +VARIABLE_NAME VARIABLE_VALUE +MYISAM_MAX_SORT_FILE_SIZE 1048576 set GLOBAL myisam_max_sort_file_size=default; show variables like 'myisam_max_sort_file_size'; Variable_name Value myisam_max_sort_file_size FILE_SIZE +select * from information_schema.session_variables where variable_name like 'myisam_max_sort_file_size'; +VARIABLE_NAME VARIABLE_VALUE +MYISAM_MAX_SORT_FILE_SIZE FILE_SIZE set global net_retry_count=10, session net_retry_count=10; set global net_buffer_length=1024, net_write_timeout=200, net_read_timeout=300; set session net_buffer_length=2048, net_write_timeout=500, net_read_timeout=600; @@ -194,12 +236,24 @@ net_buffer_length 1024 net_read_timeout 300 net_retry_count 10 net_write_timeout 200 +select * from information_schema.global_variables where variable_name like 'net_%'; +VARIABLE_NAME VARIABLE_VALUE +NET_BUFFER_LENGTH 1024 +NET_READ_TIMEOUT 300 +NET_RETRY_COUNT 10 +NET_WRITE_TIMEOUT 200 show session variables like 'net_%'; Variable_name Value net_buffer_length 2048 net_read_timeout 600 net_retry_count 10 net_write_timeout 500 +select * from information_schema.session_variables where variable_name like 'net_%'; +VARIABLE_NAME VARIABLE_VALUE +NET_BUFFER_LENGTH 2048 +NET_READ_TIMEOUT 600 +NET_RETRY_COUNT 10 +NET_WRITE_TIMEOUT 500 set session net_buffer_length=8000, global net_read_timeout=900, net_write_timeout=1000; show global variables like 'net_%'; Variable_name Value @@ -207,24 +261,45 @@ net_buffer_length 1024 net_read_timeout 900 net_retry_count 10 net_write_timeout 1000 +select * from information_schema.global_variables where variable_name like 'net_%'; +VARIABLE_NAME VARIABLE_VALUE +NET_BUFFER_LENGTH 1024 +NET_READ_TIMEOUT 900 +NET_RETRY_COUNT 10 +NET_WRITE_TIMEOUT 1000 show session variables like 'net_%'; Variable_name Value net_buffer_length 7168 net_read_timeout 600 net_retry_count 10 net_write_timeout 500 +select * from information_schema.session_variables where variable_name like 'net_%'; +VARIABLE_NAME VARIABLE_VALUE +NET_BUFFER_LENGTH 7168 +NET_READ_TIMEOUT 600 +NET_RETRY_COUNT 10 +NET_WRITE_TIMEOUT 500 set net_buffer_length=1; show variables like 'net_buffer_length'; Variable_name Value net_buffer_length 1024 +select * from information_schema.session_variables where variable_name like 'net_buffer_length'; +VARIABLE_NAME VARIABLE_VALUE +NET_BUFFER_LENGTH 1024 set net_buffer_length=2000000000; show variables like 'net_buffer_length'; Variable_name Value net_buffer_length 1048576 +select * from information_schema.session_variables where variable_name like 'net_buffer_length'; +VARIABLE_NAME VARIABLE_VALUE +NET_BUFFER_LENGTH 1048576 set character set cp1251_koi8; show variables like "character_set_client"; Variable_name Value character_set_client cp1251 +select * from information_schema.session_variables where variable_name like 'character_set_client'; +VARIABLE_NAME VARIABLE_VALUE +CHARACTER_SET_CLIENT cp1251 select @@timestamp>0; @@timestamp>0 1 @@ -239,6 +314,13 @@ query_prealloc_size 8192 range_alloc_block_size 2048 transaction_alloc_block_size 8192 transaction_prealloc_size 4096 +select * from information_schema.session_variables where variable_name like '%alloc%'; +VARIABLE_NAME VARIABLE_VALUE +QUERY_ALLOC_BLOCK_SIZE 8192 +QUERY_PREALLOC_SIZE 8192 +RANGE_ALLOC_BLOCK_SIZE 2048 +TRANSACTION_ALLOC_BLOCK_SIZE 8192 +TRANSACTION_PREALLOC_SIZE 4096 set @@range_alloc_block_size=1024*16; set @@query_alloc_block_size=1024*17+2; set @@query_prealloc_size=1024*18; @@ -254,6 +336,13 @@ query_prealloc_size 18432 range_alloc_block_size 16384 transaction_alloc_block_size 19456 transaction_prealloc_size 20480 +select * from information_schema.session_variables where variable_name like '%alloc%'; +VARIABLE_NAME VARIABLE_VALUE +QUERY_ALLOC_BLOCK_SIZE 17408 +QUERY_PREALLOC_SIZE 18432 +RANGE_ALLOC_BLOCK_SIZE 16384 +TRANSACTION_ALLOC_BLOCK_SIZE 19456 +TRANSACTION_PREALLOC_SIZE 20480 set @@range_alloc_block_size=default; set @@query_alloc_block_size=default, @@query_prealloc_size=default; set transaction_alloc_block_size=default, @@transaction_prealloc_size=default; @@ -264,6 +353,13 @@ query_prealloc_size 8192 range_alloc_block_size 2048 transaction_alloc_block_size 8192 transaction_prealloc_size 4096 +select * from information_schema.session_variables where variable_name like '%alloc%'; +VARIABLE_NAME VARIABLE_VALUE +QUERY_ALLOC_BLOCK_SIZE 8192 +QUERY_PREALLOC_SIZE 8192 +RANGE_ALLOC_BLOCK_SIZE 2048 +TRANSACTION_ALLOC_BLOCK_SIZE 8192 +TRANSACTION_PREALLOC_SIZE 4096 SELECT @@version LIKE 'non-existent'; @@version LIKE 'non-existent' 0 @@ -485,6 +581,9 @@ set global myisam_max_sort_file_size=4294967296; show global variables like 'myisam_max_sort_file_size'; Variable_name Value myisam_max_sort_file_size MAX_FILE_SIZE +select * from information_schema.global_variables where variable_name like 'myisam_max_sort_file_size'; +VARIABLE_NAME VARIABLE_VALUE +MYISAM_MAX_SORT_FILE_SIZE MAX_FILE_SIZE set global myisam_max_sort_file_size=default; select @@global.max_user_connections,@@local.max_join_size; @@global.max_user_connections @@local.max_join_size @@ -524,18 +623,30 @@ set @tstlw = @@log_warnings; show global variables like 'log_warnings'; Variable_name Value log_warnings 1 +select * from information_schema.global_variables where variable_name like 'log_warnings'; +VARIABLE_NAME VARIABLE_VALUE +LOG_WARNINGS 1 set global log_warnings = 0; show global variables like 'log_warnings'; Variable_name Value log_warnings 0 +select * from information_schema.global_variables where variable_name like 'log_warnings'; +VARIABLE_NAME VARIABLE_VALUE +LOG_WARNINGS 0 set global log_warnings = 42; show global variables like 'log_warnings'; Variable_name Value log_warnings 42 +select * from information_schema.global_variables where variable_name like 'log_warnings'; +VARIABLE_NAME VARIABLE_VALUE +LOG_WARNINGS 42 set global log_warnings = @tstlw; show global variables like 'log_warnings'; Variable_name Value log_warnings 1 +select * from information_schema.global_variables where variable_name like 'log_warnings'; +VARIABLE_NAME VARIABLE_VALUE +LOG_WARNINGS 1 create table t1 ( c1 tinyint, c2 smallint, @@ -567,10 +678,16 @@ SET GLOBAL MYISAM_DATA_POINTER_SIZE= 7; SHOW VARIABLES LIKE 'MYISAM_DATA_POINTER_SIZE'; Variable_name Value myisam_data_pointer_size 7 +SELECT * FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE VARIABLE_NAME LIKE 'MYISAM_DATA_POINTER_SIZE'; +VARIABLE_NAME VARIABLE_VALUE +MYISAM_DATA_POINTER_SIZE 7 SET GLOBAL table_open_cache=-1; SHOW VARIABLES LIKE 'table_open_cache'; Variable_name Value table_open_cache 1 +SELECT * FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE VARIABLE_NAME LIKE 'table_open_cache'; +VARIABLE_NAME VARIABLE_VALUE +TABLE_OPEN_CACHE 1 SET GLOBAL table_open_cache=DEFAULT; set character_set_results=NULL; select ifnull(@@character_set_results,"really null"); @@ -639,21 +756,36 @@ set @@sql_big_selects = 1; show variables like 'sql_big_selects'; Variable_name Value sql_big_selects ON +select * from information_schema.session_variables where variable_name like 'sql_big_selects'; +VARIABLE_NAME VARIABLE_VALUE +SQL_BIG_SELECTS ON set @@sql_big_selects = @old_sql_big_selects; set @@sql_notes = 0, @@sql_warnings = 0; show variables like 'sql_notes'; Variable_name Value sql_notes OFF +select * from information_schema.session_variables where variable_name like 'sql_notes'; +VARIABLE_NAME VARIABLE_VALUE +SQL_NOTES OFF show variables like 'sql_warnings'; Variable_name Value sql_warnings OFF +select * from information_schema.session_variables where variable_name like 'sql_warnings'; +VARIABLE_NAME VARIABLE_VALUE +SQL_WARNINGS OFF set @@sql_notes = 1, @@sql_warnings = 1; show variables like 'sql_notes'; Variable_name Value sql_notes ON +select * from information_schema.session_variables where variable_name like 'sql_notes'; +VARIABLE_NAME VARIABLE_VALUE +SQL_NOTES ON show variables like 'sql_warnings'; Variable_name Value sql_warnings ON +select * from information_schema.session_variables where variable_name like 'sql_warnings'; +VARIABLE_NAME VARIABLE_VALUE +SQL_WARNINGS ON select @@system_time_zone; @@system_time_zone # @@ -667,12 +799,21 @@ select @@basedir, @@datadir, @@tmpdir; show variables like 'basedir'; Variable_name Value basedir # +select * from information_schema.session_variables where variable_name like 'basedir'; +VARIABLE_NAME VARIABLE_VALUE +BASEDIR # show variables like 'datadir'; Variable_name Value datadir # +select * from information_schema.session_variables where variable_name like 'datadir'; +VARIABLE_NAME VARIABLE_VALUE +DATADIR # show variables like 'tmpdir'; Variable_name Value tmpdir # +select * from information_schema.session_variables where variable_name like 'tmpdir'; +VARIABLE_NAME VARIABLE_VALUE +TMPDIR # select @@ssl_ca, @@ssl_capath, @@ssl_cert, @@ssl_cipher, @@ssl_key; @@ssl_ca @@ssl_capath @@ssl_cert @@ssl_cipher @@ssl_key # # # # # @@ -683,12 +824,22 @@ ssl_capath # ssl_cert # ssl_cipher # ssl_key # +select * from information_schema.session_variables where variable_name like 'ssl%'; +VARIABLE_NAME VARIABLE_VALUE +SSL_CA # +SSL_CAPATH # +SSL_CERT # +SSL_CIPHER # +SSL_KEY # select @@log_queries_not_using_indexes; @@log_queries_not_using_indexes 0 show variables like 'log_queries_not_using_indexes'; Variable_name Value log_queries_not_using_indexes OFF +select * from information_schema.session_variables where variable_name like 'log_queries_not_using_indexes'; +VARIABLE_NAME VARIABLE_VALUE +LOG_QUERIES_NOT_USING_INDEXES OFF End of 5.0 tests set global binlog_cache_size =@my_binlog_cache_size; set global connect_timeout =@my_connect_timeout; diff --git a/mysql-test/t/status.test b/mysql-test/t/status.test index 55f9d95adc5..2afcd49962c 100644 --- a/mysql-test/t/status.test +++ b/mysql-test/t/status.test @@ -13,6 +13,7 @@ connect (con2,localhost,root,,); flush status; show status like 'Table_lock%'; +select * from information_schema.session_status where variable_name like 'Table_lock%'; connection con1; SET SQL_LOG_BIN=0; --disable_warnings @@ -34,6 +35,7 @@ unlock tables; connection con1; reap; show status like 'Table_lock%'; +select * from information_schema.session_status where variable_name like 'Table_lock%'; drop table t1; disconnect con2; @@ -102,6 +104,7 @@ while ($wait_more) # Prerequisite. SHOW STATUS LIKE 'max_used_connections'; +SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME LIKE 'max_used_connections'; # Save original setting. SET @save_thread_cache_size=@@thread_cache_size; @@ -115,6 +118,7 @@ disconnect con2; # Check that max_used_connections still reflects maximum value. SHOW STATUS LIKE 'max_used_connections'; +SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME LIKE 'max_used_connections'; # Check that after flush max_used_connections equals to current number # of connections. First wait for previous disconnect to finish. @@ -138,15 +142,18 @@ while ($wait_more) --enable_result_log # Check that we don't count disconnected thread any longer. SHOW STATUS LIKE 'max_used_connections'; +SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME LIKE 'max_used_connections'; # Check that max_used_connections is updated when cached thread is # reused... connect (con2,localhost,root,,); SHOW STATUS LIKE 'max_used_connections'; +SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME LIKE 'max_used_connections'; # ...and when new thread is created. connect (con3,localhost,root,,); SHOW STATUS LIKE 'max_used_connections'; +SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME LIKE 'max_used_connections'; # Restore original setting. connection default; diff --git a/mysql-test/t/variables.test b/mysql-test/t/variables.test index 771a4ad3ed3..a33f1f72b8a 100644 --- a/mysql-test/t/variables.test +++ b/mysql-test/t/variables.test @@ -83,16 +83,24 @@ drop table t1; set GLOBAL max_join_size=10; set max_join_size=100; show variables like 'max_join_size'; +select * from information_schema.session_variables where variable_name like 'max_join_size'; --replace_result 18446744073709551615 HA_POS_ERROR 4294967295 HA_POS_ERROR show global variables like 'max_join_size'; +--replace_result 18446744073709551615 HA_POS_ERROR 4294967295 HA_POS_ERROR +select * from information_schema.global_variables where variable_name like 'max_join_size'; set GLOBAL max_join_size=2000; show global variables like 'max_join_size'; +select * from information_schema.global_variables where variable_name like 'max_join_size'; set max_join_size=DEFAULT; --replace_result 18446744073709551615 HA_POS_ERROR 4294967295 HA_POS_ERROR show variables like 'max_join_size'; +--replace_result 18446744073709551615 HA_POS_ERROR 4294967295 HA_POS_ERROR +select * from information_schema.session_variables where variable_name like 'max_join_size'; set GLOBAL max_join_size=DEFAULT; --replace_result 18446744073709551615 HA_POS_ERROR 4294967295 HA_POS_ERROR show global variables like 'max_join_size'; +--replace_result 18446744073709551615 HA_POS_ERROR 4294967295 HA_POS_ERROR +select * from information_schema.global_variables where variable_name like 'max_join_size'; set @@max_join_size=1000, @@global.max_join_size=2000; select @@local.max_join_size, @@global.max_join_size; select @@identity, length(@@version)>0; @@ -106,50 +114,68 @@ set big_tables=OFF, big_tables=ON, big_tables=0, big_tables=1, big_tables="OFF", set global concurrent_insert=2; show variables like 'concurrent_insert'; +select * from information_schema.session_variables where variable_name like 'concurrent_insert'; set global concurrent_insert=1; show variables like 'concurrent_insert'; +select * from information_schema.session_variables where variable_name like 'concurrent_insert'; set global concurrent_insert=0; show variables like 'concurrent_insert'; +select * from information_schema.session_variables where variable_name like 'concurrent_insert'; set global concurrent_insert=DEFAULT; select @@concurrent_insert; set global timed_mutexes=ON; show variables like 'timed_mutexes'; +select * from information_schema.session_variables where variable_name like 'timed_mutexes'; set global timed_mutexes=0; show variables like 'timed_mutexes'; +select * from information_schema.session_variables where variable_name like 'timed_mutexes'; set storage_engine=MYISAM, storage_engine="HEAP", global storage_engine="MERGE"; show local variables like 'storage_engine'; +select * from information_schema.session_variables where variable_name like 'storage_engine'; show global variables like 'storage_engine'; +select * from information_schema.global_variables where variable_name like 'storage_engine'; set GLOBAL query_cache_size=100000; set GLOBAL myisam_max_sort_file_size=2000000; show global variables like 'myisam_max_sort_file_size'; +select * from information_schema.global_variables where variable_name like 'myisam_max_sort_file_size'; set GLOBAL myisam_max_sort_file_size=default; --replace_result 2147483647 FILE_SIZE 9223372036854775807 FILE_SIZE show variables like 'myisam_max_sort_file_size'; +--replace_result 2147483647 FILE_SIZE 9223372036854775807 FILE_SIZE +select * from information_schema.session_variables where variable_name like 'myisam_max_sort_file_size'; set global net_retry_count=10, session net_retry_count=10; set global net_buffer_length=1024, net_write_timeout=200, net_read_timeout=300; set session net_buffer_length=2048, net_write_timeout=500, net_read_timeout=600; show global variables like 'net_%'; +select * from information_schema.global_variables where variable_name like 'net_%'; show session variables like 'net_%'; +select * from information_schema.session_variables where variable_name like 'net_%'; set session net_buffer_length=8000, global net_read_timeout=900, net_write_timeout=1000; show global variables like 'net_%'; +select * from information_schema.global_variables where variable_name like 'net_%'; show session variables like 'net_%'; +select * from information_schema.session_variables where variable_name like 'net_%'; set net_buffer_length=1; show variables like 'net_buffer_length'; +select * from information_schema.session_variables where variable_name like 'net_buffer_length'; set net_buffer_length=2000000000; show variables like 'net_buffer_length'; +select * from information_schema.session_variables where variable_name like 'net_buffer_length'; set character set cp1251_koi8; show variables like "character_set_client"; +select * from information_schema.session_variables where variable_name like 'character_set_client'; select @@timestamp>0; set @@rand_seed1=10000000,@@rand_seed2=1000000; select ROUND(RAND(),5); show variables like '%alloc%'; +select * from information_schema.session_variables where variable_name like '%alloc%'; set @@range_alloc_block_size=1024*16; set @@query_alloc_block_size=1024*17+2; set @@query_prealloc_size=1024*18; @@ -157,10 +183,12 @@ set @@transaction_alloc_block_size=1024*20-1; set @@transaction_prealloc_size=1024*21-1; select @@query_alloc_block_size; show variables like '%alloc%'; +select * from information_schema.session_variables where variable_name like '%alloc%'; set @@range_alloc_block_size=default; set @@query_alloc_block_size=default, @@query_prealloc_size=default; set transaction_alloc_block_size=default, @@transaction_prealloc_size=default; show variables like '%alloc%'; +select * from information_schema.session_variables where variable_name like '%alloc%'; # # Bug #10904 Illegal mix of collations between @@ -363,6 +391,8 @@ set global ft_boolean_syntax = @@init_connect; set global myisam_max_sort_file_size=4294967296; --replace_result 4294967296 MAX_FILE_SIZE 2146435072 MAX_FILE_SIZE show global variables like 'myisam_max_sort_file_size'; +--replace_result 4294967296 MAX_FILE_SIZE 2146435072 MAX_FILE_SIZE +select * from information_schema.global_variables where variable_name like 'myisam_max_sort_file_size'; set global myisam_max_sort_file_size=default; # @@ -398,12 +428,16 @@ SELECT @@global.local.key_buffer_size; # BUG#5135: cannot turn on log_warnings with SET in 4.1 (and 4.0) set @tstlw = @@log_warnings; show global variables like 'log_warnings'; +select * from information_schema.global_variables where variable_name like 'log_warnings'; set global log_warnings = 0; show global variables like 'log_warnings'; +select * from information_schema.global_variables where variable_name like 'log_warnings'; set global log_warnings = 42; show global variables like 'log_warnings'; +select * from information_schema.global_variables where variable_name like 'log_warnings'; set global log_warnings = @tstlw; show global variables like 'log_warnings'; +select * from information_schema.global_variables where variable_name like 'log_warnings'; # # BUG#4788 show create table provides incorrect statement @@ -435,6 +469,7 @@ drop table t1; SET GLOBAL MYISAM_DATA_POINTER_SIZE= 7; SHOW VARIABLES LIKE 'MYISAM_DATA_POINTER_SIZE'; +SELECT * FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE VARIABLE_NAME LIKE 'MYISAM_DATA_POINTER_SIZE'; # # Bug #6958: negative arguments to integer options wrap around @@ -442,6 +477,7 @@ SHOW VARIABLES LIKE 'MYISAM_DATA_POINTER_SIZE'; SET GLOBAL table_open_cache=-1; SHOW VARIABLES LIKE 'table_open_cache'; +SELECT * FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE VARIABLE_NAME LIKE 'table_open_cache'; SET GLOBAL table_open_cache=DEFAULT; # @@ -527,6 +563,7 @@ select @@global.character_set_filesystem; set @old_sql_big_selects = @@sql_big_selects; set @@sql_big_selects = 1; show variables like 'sql_big_selects'; +select * from information_schema.session_variables where variable_name like 'sql_big_selects'; set @@sql_big_selects = @old_sql_big_selects; # @@ -535,10 +572,14 @@ set @@sql_big_selects = @old_sql_big_selects; # set @@sql_notes = 0, @@sql_warnings = 0; show variables like 'sql_notes'; +select * from information_schema.session_variables where variable_name like 'sql_notes'; show variables like 'sql_warnings'; +select * from information_schema.session_variables where variable_name like 'sql_warnings'; set @@sql_notes = 1, @@sql_warnings = 1; show variables like 'sql_notes'; +select * from information_schema.session_variables where variable_name like 'sql_notes'; show variables like 'sql_warnings'; +select * from information_schema.session_variables where variable_name like 'sql_warnings'; # # Bug #12792: @@system_time_zone is not SELECTable. @@ -565,9 +606,15 @@ select @@basedir, @@datadir, @@tmpdir; --replace_column 2 # show variables like 'basedir'; --replace_column 2 # +select * from information_schema.session_variables where variable_name like 'basedir'; +--replace_column 2 # show variables like 'datadir'; --replace_column 2 # +select * from information_schema.session_variables where variable_name like 'datadir'; +--replace_column 2 # show variables like 'tmpdir'; +--replace_column 2 # +select * from information_schema.session_variables where variable_name like 'tmpdir'; # # Bug #19606: make ssl settings available via SHOW VARIABLES and @@variables @@ -577,6 +624,8 @@ show variables like 'tmpdir'; select @@ssl_ca, @@ssl_capath, @@ssl_cert, @@ssl_cipher, @@ssl_key; --replace_column 2 # show variables like 'ssl%'; +--replace_column 2 # +select * from information_schema.session_variables where variable_name like 'ssl%'; # # Bug #19616: make log_queries_not_using_indexes available in SHOW VARIABLES @@ -584,6 +633,7 @@ show variables like 'ssl%'; # select @@log_queries_not_using_indexes; show variables like 'log_queries_not_using_indexes'; +select * from information_schema.session_variables where variable_name like 'log_queries_not_using_indexes'; --echo End of 5.0 tests diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 3acc025b84f..14ca547a527 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1994,15 +1994,22 @@ void remove_status_vars(SHOW_VAR *list) } } +inline void make_upper(char *buf) +{ + for (; *buf; buf++) + *buf= my_toupper(system_charset_info, *buf); +} + static bool show_status_array(THD *thd, const char *wild, SHOW_VAR *variables, enum enum_var_type value_type, struct system_status_var *status_var, - const char *prefix, TABLE *table) + const char *prefix, TABLE *table, + bool ucase_names) { char buff[SHOW_VAR_FUNC_BUFF_SIZE], *prefix_end; - /* the variable name should not be longer then 80 characters */ - char name_buffer[80]; + /* the variable name should not be longer than 64 characters */ + char name_buffer[64]; int len; LEX_STRING null_lex_str; SHOW_VAR tmp, *var; @@ -2020,6 +2027,8 @@ static bool show_status_array(THD *thd, const char *wild, { strnmov(prefix_end, variables->name, len); name_buffer[sizeof(name_buffer)-1]=0; /* Safety */ + if (ucase_names) + make_upper(name_buffer); /* if var->type is SHOW_FUNC, call the function. @@ -2031,8 +2040,8 @@ static bool show_status_array(THD *thd, const char *wild, SHOW_TYPE show_type=var->type; if (show_type == SHOW_ARRAY) { - show_status_array(thd, wild, (SHOW_VAR *) var->value, - value_type, status_var, name_buffer, table); + show_status_array(thd, wild, (SHOW_VAR *) var->value, value_type, + status_var, name_buffer, table, ucase_names); } else { @@ -2041,7 +2050,7 @@ static bool show_status_array(THD *thd, const char *wild, { char *value=var->value; const char *pos, *end; // We assign a lot of const's - long nr; + if (show_type == SHOW_SYS) { show_type= ((sys_var*) value)->type(); @@ -2123,6 +2132,7 @@ static bool show_status_array(THD *thd, const char *wild, table->field[0]->store(name_buffer, strlen(name_buffer), system_charset_info); table->field[1]->store(pos, (uint32) (end - pos), system_charset_info); + table->field[1]->set_notnull(); if (schema_table_store_record(thd, table)) DBUG_RETURN(TRUE); } @@ -4563,7 +4573,7 @@ int fill_variables(THD *thd, TABLE_LIST *tables, COND *cond) const char *wild= lex->wild ? lex->wild->ptr() : NullS; pthread_mutex_lock(&LOCK_global_system_variables); res= show_status_array(thd, wild, init_vars, - lex->option_type, 0, "", tables->table); + lex->option_type, 0, "", tables->table, 0); pthread_mutex_unlock(&LOCK_global_system_variables); DBUG_RETURN(res); } @@ -4583,7 +4593,8 @@ int fill_status(THD *thd, TABLE_LIST *tables, COND *cond) (SHOW_VAR *)all_status_vars.buffer, OPT_GLOBAL, (lex->option_type == OPT_GLOBAL ? - &tmp: thd->initial_status_var), "",tables->table); + &tmp: thd->initial_status_var), + "", tables->table, 0); pthread_mutex_unlock(&LOCK_status); DBUG_RETURN(res); } @@ -4732,6 +4743,21 @@ TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list) DBUG_RETURN(0); } break; + case MYSQL_TYPE_DECIMAL: + if (!(item= new Item_decimal((longlong) fields_info->value, false))) + { + DBUG_RETURN(0); + } + item->unsigned_flag= (fields_info->field_length/10000)%10; + item->decimals= fields_info->field_length%10; + item->max_length= (fields_info->field_length/100)%100; + if (item->unsigned_flag == 0) + item->max_length+= 1; + if (item->decimals > 0) + item->max_length+= 1; + item->set_name(fields_info->field_name, + strlen(fields_info->field_name), cs); + break; default: /* this should be changed when Item_empty_string is fixed(in 4.1) */ if (!(item= new Item_empty_string("", 0, cs))) @@ -5171,6 +5197,173 @@ int fill_schema_files(THD *thd, TABLE_LIST *tables, COND *cond) DBUG_RETURN(0); } +int fill_schema_status(THD *thd, SHOW_VAR *variables, + struct system_status_var *status_var, + const char *prefix, TABLE *table) +{ + SHOW_VAR tmp, *var; + SHOW_TYPE show_type; + LEX_STRING null_lex_str; + char buff[SHOW_VAR_FUNC_BUFF_SIZE]; + char name_buf[64], *name_pos; + int name_len; + DBUG_ENTER("fill_schema_status"); + + null_lex_str.str= 0; + null_lex_str.length= 0; + + name_pos= strnmov(name_buf, prefix, sizeof(name_buf) - 1); + if (*prefix) + *name_pos++= '_'; + name_len= name_buf + sizeof(name_buf) - name_pos; + + for (; variables->name; variables++) + { + strnmov(name_pos, variables->name, name_len); + name_buf[sizeof(name_buf) - 1]= 0; + make_upper(name_buf); + + for (var= variables; var->type == SHOW_FUNC; var= &tmp) + ((mysql_show_var_func)(var->value))(thd, &tmp, buff); + + show_type= var->type; + + if (show_type == SHOW_ARRAY) + { + fill_schema_status(thd, (SHOW_VAR*) var->value, + status_var, name_buf, table); + } + else + { + char *value= var->value; + + restore_record(table, s->default_values); + table->field[0]->store(name_buf, strlen(name_buf), system_charset_info); + + if (show_type == SHOW_SYS) + { + show_type= ((sys_var*) value)->type(); + value= (char*) ((sys_var*) value)->value_ptr(thd, OPT_GLOBAL, + &null_lex_str); + } + + switch (show_type) + { + case SHOW_DOUBLE_STATUS: + value= (char*) status_var + (ulong) value; + table->field[1]->store(*(double*) value); + break; + case SHOW_LONG_STATUS: + value= (char*) status_var + (ulong) value; + /* fall through */ + case SHOW_LONG: + case SHOW_LONG_NOFLUSH: /* the difference lies in refresh_status() */ + table->field[1]->store((longlong) *(long*) value, false); + break; + case SHOW_LONGLONG: + table->field[1]->store(*(longlong*) value, false); + break; + case SHOW_HA_ROWS: + table->field[1]->store((longlong) *(ha_rows*) value, false); + break; + case SHOW_BOOL: + table->field[1]->store((longlong) *(bool*) value, false); + break; + case SHOW_MY_BOOL: + table->field[1]->store((longlong) *(my_bool*) value, false); + break; + case SHOW_INT: + table->field[1]->store((longlong) *(uint32*) value, false); + break; + case SHOW_HAVE: /* always displayed as 0 */ + table->field[1]->store((longlong) 0, false); + break; + case SHOW_CHAR_PTR: + value= *(char**) value; + /* fall through */ + case SHOW_CHAR: /* always displayed as 0 */ + table->field[1]->store((longlong) 0, false); + break; + case SHOW_KEY_CACHE_LONG: + value= (char*) dflt_key_cache + (ulong) value; + table->field[1]->store((longlong) *(long*) value, false); + break; + case SHOW_KEY_CACHE_LONGLONG: + value= (char*) dflt_key_cache + (ulong) value; + table->field[1]->store(*(longlong*) value, false); + break; + case SHOW_UNDEF: /* always displayed as 0 */ + table->field[1]->store((longlong) 0, false); + break; + case SHOW_SYS: /* cannot happen */ + default: + DBUG_ASSERT(0); + break; + } + + table->field[1]->set_notnull(); + if (schema_table_store_record(thd, table)) + DBUG_RETURN(1); + } + } + + DBUG_RETURN(0); +} + +int fill_schema_global_status(THD *thd, TABLE_LIST *tables, COND *cond) +{ + STATUS_VAR tmp; + int res= 0; + DBUG_ENTER("fill_schema_global_status"); + + pthread_mutex_lock(&LOCK_status); + calc_sum_of_all_status(&tmp); + res= fill_schema_status(thd, (SHOW_VAR*) all_status_vars.buffer, + &tmp, "", tables->table); + pthread_mutex_unlock(&LOCK_status); + + DBUG_RETURN(res); +} + +int fill_schema_session_status(THD *thd, TABLE_LIST *tables, COND *cond) +{ + int res= 0; + DBUG_ENTER("fill_schema_session_status"); + + pthread_mutex_lock(&LOCK_status); + res= fill_schema_status(thd, (SHOW_VAR*) all_status_vars.buffer, + &thd->status_var, "", tables->table); + pthread_mutex_unlock(&LOCK_status); + + DBUG_RETURN(res); +} + +int fill_schema_global_variables(THD *thd, TABLE_LIST *tables, COND *cond) +{ + int res= 0; + DBUG_ENTER("fill_schema_global_variables"); + + pthread_mutex_lock(&LOCK_global_system_variables); + res= show_status_array(thd, "", init_vars, OPT_GLOBAL, + NULL, "", tables->table, 1); + pthread_mutex_unlock(&LOCK_global_system_variables); + + DBUG_RETURN(res); +} + +int fill_schema_session_variables(THD *thd, TABLE_LIST *tables, COND *cond) +{ + int res= 0; + DBUG_ENTER("fill_schema_session_variables"); + + pthread_mutex_lock(&LOCK_global_system_variables); + res= show_status_array(thd, "", init_vars, OPT_SESSION, + NULL, "", tables->table, 1); + pthread_mutex_unlock(&LOCK_global_system_variables); + + DBUG_RETURN(res); +} + ST_FIELD_INFO schema_fields_info[]= { {"CATALOG_NAME", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0}, @@ -5523,6 +5716,22 @@ ST_FIELD_INFO variables_fields_info[]= }; +ST_FIELD_INFO status_fields_info[]= +{ + {"VARIABLE_NAME", 64, MYSQL_TYPE_STRING, 0, 0, "Variable_name"}, + {"VARIABLE_VALUE", 2207, MYSQL_TYPE_DECIMAL, 0, 0, "Value"}, + {0, 0, MYSQL_TYPE_STRING, 0, 0, 0} +}; + + +ST_FIELD_INFO system_variables_fields_info[]= +{ + {"VARIABLE_NAME", 64, MYSQL_TYPE_STRING, 0, 0, "Variable_name"}, + {"VARIABLE_VALUE", 65535, MYSQL_TYPE_STRING, 0, 1, "Value"}, + {0, 0, MYSQL_TYPE_STRING, 0, 0, 0} +}; + + ST_FIELD_INFO processlist_fields_info[]= { {"ID", 4, MYSQL_TYPE_LONG, 0, 0, "Id"}, @@ -5635,6 +5844,10 @@ ST_SCHEMA_TABLE schema_tables[]= fill_schema_events, make_old_format, 0, -1, -1, 0}, {"FILES", files_fields_info, create_schema_table, fill_schema_files, 0, 0, -1, -1, 0}, + {"GLOBAL_STATUS", status_fields_info, create_schema_table, + fill_schema_global_status, make_old_format, 0, -1, -1, 0}, + {"GLOBAL_VARIABLES", system_variables_fields_info, create_schema_table, + fill_schema_global_variables, make_old_format, 0, -1, -1, 0}, {"KEY_COLUMN_USAGE", key_column_usage_fields_info, create_schema_table, get_all_tables, 0, get_schema_key_column_usage_record, 4, 5, 0}, {"OPEN_TABLES", open_tables_fields_info, create_schema_table, @@ -5654,6 +5867,10 @@ ST_SCHEMA_TABLE schema_tables[]= fill_schema_shemata, make_schemata_old_format, 0, 1, -1, 0}, {"SCHEMA_PRIVILEGES", schema_privileges_fields_info, create_schema_table, fill_schema_schema_privileges, 0, 0, -1, -1, 0}, + {"SESSION_STATUS", status_fields_info, create_schema_table, + fill_schema_session_status, make_old_format, 0, -1, -1, 0}, + {"SESSION_VARIABLES", system_variables_fields_info, create_schema_table, + fill_schema_session_variables, make_old_format, 0, -1, -1, 0}, {"STATISTICS", stat_fields_info, create_schema_table, get_all_tables, make_old_format, get_schema_stat_record, 1, 2, 0}, {"STATUS", variables_fields_info, create_schema_table, fill_status, diff --git a/sql/table.h b/sql/table.h index 3fb7222cb0d..c490c283b72 100644 --- a/sql/table.h +++ b/sql/table.h @@ -474,6 +474,8 @@ enum enum_schema_tables SCH_ENGINES, SCH_EVENTS, SCH_FILES, + SCH_GLOBAL_STATUS, + SCH_GLOBAL_VARIABLES, SCH_KEY_COLUMN_USAGE, SCH_OPEN_TABLES, SCH_PARTITIONS, @@ -483,6 +485,8 @@ enum enum_schema_tables SCH_PROCEDURES, SCH_SCHEMATA, SCH_SCHEMA_PRIVILEGES, + SCH_SESSION_STATUS, + SCH_SESSION_VARIABLES, SCH_STATISTICS, SCH_STATUS, SCH_TABLES, From 7e95cda2ac097bf2e25cfa444aa738c6ab2af5f6 Mon Sep 17 00:00:00 2001 From: "guilhem@gbichot3.local" <> Date: Thu, 14 Sep 2006 01:37:41 +0200 Subject: [PATCH 26/27] fixes for the my_atomic-t unit test: - compiler warning - detection of pthread_create failure (you will see this message only if you run with "make test-verbose" in unittest; otherwise unit.pl masks all messages from the test but "ok" ones. - the test fails randomly on some machines (I filed it as BUG#22320), on one host it looks like a crash at exit() which a sleep(2) makes disappear. So I add the sleep(2), which can be removed when BUG#22320 is fixed. --- unittest/mysys/my_atomic-t.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/unittest/mysys/my_atomic-t.c b/unittest/mysys/my_atomic-t.c index 4e2e496c3b1..fe93b0942ce 100644 --- a/unittest/mysys/my_atomic-t.c +++ b/unittest/mysys/my_atomic-t.c @@ -32,7 +32,7 @@ pthread_handler_t test_atomic_add_handler(void *arg) { int m=*(int *)arg; int32 x; - for (x=((int)(&m)); m ; m--) + for (x=((int)((long)(&m))); m ; m--) { x=x*m+0x87654321; my_atomic_rwlock_wrlock(&rwl); @@ -104,7 +104,7 @@ pthread_handler_t test_atomic_cas_handler(void *arg) { int m=*(int *)arg, ok; int32 x,y; - for (x=((int)(&m)); m ; m--) + for (x=((int)((long)(&m))); m ; m--) { my_atomic_rwlock_wrlock(&rwl); y=my_atomic_load32(&a32); @@ -140,13 +140,21 @@ void test_atomic(const char *test, pthread_handler handler, int n, int m) diag("Testing %s with %d threads, %d iterations... ", test, n, m); for (N=n ; n ; n--) - pthread_create(&t, &thr_attr, handler, &m); + { + if (pthread_create(&t, &thr_attr, handler, &m) != 0) + { + diag("Could not create thread"); + a32= 1; + goto err; + } + } pthread_mutex_lock(&mutex); while (N) pthread_cond_wait(&cond, &mutex); pthread_mutex_unlock(&mutex); now=my_getsystime()-now; +err: ok(a32 == 0, "tested %s in %g secs", test, ((double)now)/1e7); } @@ -170,6 +178,12 @@ int main() test_atomic("my_atomic_swap32", test_atomic_swap_handler, 100,10000); test_atomic("my_atomic_cas32", test_atomic_cas_handler, 100,10000); + /* + workaround until we know why it crashes randomly on some machine + (BUG#22320). + */ + sleep(2); + pthread_mutex_destroy(&mutex); pthread_cond_destroy(&cond); pthread_attr_destroy(&thr_attr); From 9474d3fe44a4de877a9a0702e48afec1b2e1d02e Mon Sep 17 00:00:00 2001 From: "aivanov/alexi@mysql.com/mysqld.localdomain" <> Date: Thu, 14 Sep 2006 05:35:50 +0400 Subject: [PATCH 27/27] WL#3247,#3248: Adding [GLOBAL|SESSION]_STATUS and [GLOBAL|SESSION]_VARIABLES tables to INFORMATION_SCHEMA. --- mysql-test/r/mysqlshow.result | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/mysql-test/r/mysqlshow.result b/mysql-test/r/mysqlshow.result index 60ad5998465..14d8e4f464b 100644 --- a/mysql-test/r/mysqlshow.result +++ b/mysql-test/r/mysqlshow.result @@ -87,6 +87,8 @@ Database: information_schema | ENGINES | | EVENTS | | FILES | +| GLOBAL_STATUS | +| GLOBAL_VARIABLES | | KEY_COLUMN_USAGE | | PARTITIONS | | PLUGINS | @@ -95,6 +97,8 @@ Database: information_schema | ROUTINES | | SCHEMATA | | SCHEMA_PRIVILEGES | +| SESSION_STATUS | +| SESSION_VARIABLES | | STATISTICS | | TABLES | | TABLE_CONSTRAINTS | @@ -115,6 +119,8 @@ Database: INFORMATION_SCHEMA | ENGINES | | EVENTS | | FILES | +| GLOBAL_STATUS | +| GLOBAL_VARIABLES | | KEY_COLUMN_USAGE | | PARTITIONS | | PLUGINS | @@ -123,6 +129,8 @@ Database: INFORMATION_SCHEMA | ROUTINES | | SCHEMATA | | SCHEMA_PRIVILEGES | +| SESSION_STATUS | +| SESSION_VARIABLES | | STATISTICS | | TABLES | | TABLE_CONSTRAINTS |