From 48e0325c5e22aef8faca34672c30873c361412e1 Mon Sep 17 00:00:00 2001 From: Mattias Jonsson Date: Thu, 8 Jan 2009 15:16:44 +0100 Subject: [PATCH 01/69] Bug#39893: Crash if select on a partitioned table, when partitioning is disabled Problem was that it tried to run partitioning function calls when opening a partitioned table, when it was explicitly disabled. Solution is to check if the partitioning plugin is ready to use before using any partitioning specific calls. mysql-test/r/disabled_partition.require: Bug#39893: Crash if select on a partitioned table, when partitioning is disabled New require file to use when partitioning is disabled (but compiled in) mysql-test/r/not_partition.result: Bug#39893: Crash if select on a partitioned table, when partitioning is disabled Updated testcase mysql-test/r/partition_disabled.result: Bug#39893: Crash if select on a partitioned table, when partitioning is disabled New result file mysql-test/std_data/parts/t1.frm: Bug#39893: Crash if select on a partitioned table, when partitioning is disabled frm file for 'create table t1 (a int) partition by hash (a)' mysql-test/t/not_partition.test: Bug#39893: Crash if select on a partitioned table, when partitioning is disabled Updated test cases mysql-test/t/partition_disabled-master.opt: Bug#39893: Crash if select on a partitioned table, when partitioning is disabled New opt file mysql-test/t/partition_disabled.test: Bug#39893: Crash if select on a partitioned table, when partitioning is disabled New test file (looks like not_partition.test, but with different errors) sql/sql_yacc.yy: Bug#39893: Crash if select on a partitioned table, when partitioning is disabled Better error message (it is already built with partitioning, but is explicitly disabled). sql/table.cc: Bug#39893: Crash if select on a partitioned table, when partitioning is disabled If the partitioning plugin is not ready, fail to open the table. --- mysql-test/r/disabled_partition.require | 2 + mysql-test/r/not_partition.result | 45 ++++++++++ mysql-test/r/partition_disabled.result | 93 +++++++++++++++++++++ mysql-test/std_data/parts/t1.frm | Bin 0 -> 8554 bytes mysql-test/t/not_partition.test | 25 +++++- mysql-test/t/partition_disabled-master.opt | 1 + mysql-test/t/partition_disabled.test | 85 +++++++++++++++++++ sql/sql_yacc.yy | 4 +- sql/table.cc | 9 ++ 9 files changed, 261 insertions(+), 3 deletions(-) create mode 100644 mysql-test/r/disabled_partition.require create mode 100644 mysql-test/r/partition_disabled.result create mode 100644 mysql-test/std_data/parts/t1.frm create mode 100644 mysql-test/t/partition_disabled-master.opt create mode 100644 mysql-test/t/partition_disabled.test diff --git a/mysql-test/r/disabled_partition.require b/mysql-test/r/disabled_partition.require new file mode 100644 index 00000000000..a21c259447a --- /dev/null +++ b/mysql-test/r/disabled_partition.require @@ -0,0 +1,2 @@ +Variable_name Value +have_partitioning DISABLED diff --git a/mysql-test/r/not_partition.result b/mysql-test/r/not_partition.result index 9e205a09d78..f516f8634ce 100644 --- a/mysql-test/r/not_partition.result +++ b/mysql-test/r/not_partition.result @@ -1,3 +1,48 @@ +DROP TABLE IF EXISTS t1; +FLUSH TABLES; +SELECT * FROM t1; +ERROR 42000: Unknown table engine 'partition' +TRUNCATE TABLE t1; +ERROR 42000: Unknown table engine 'partition' +ANALYZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 analyze Error Unknown table engine 'partition' +test.t1 analyze error Corrupt +CHECK TABLE t1; +Table Op Msg_type Msg_text +test.t1 check Error Unknown table engine 'partition' +test.t1 check error Corrupt +OPTIMIZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 optimize Error Unknown table engine 'partition' +test.t1 optimize error Corrupt +REPAIR TABLE t1; +Table Op Msg_type Msg_text +test.t1 repair Error Unknown table engine 'partition' +test.t1 repair error Corrupt +ALTER TABLE t1 REPAIR PARTITION ALL; +Table Op Msg_type Msg_text +test.t1 repair Error Unknown table engine 'partition' +test.t1 repair error Corrupt +ALTER TABLE t1 CHECK PARTITION ALL; +Table Op Msg_type Msg_text +test.t1 check Error Unknown table engine 'partition' +test.t1 check error Corrupt +ALTER TABLE t1 OPTIMIZE PARTITION ALL; +Table Op Msg_type Msg_text +test.t1 optimize Error Unknown table engine 'partition' +test.t1 optimize error Corrupt +ALTER TABLE t1 ANALYZE PARTITION ALL; +Table Op Msg_type Msg_text +test.t1 analyze Error Unknown table engine 'partition' +test.t1 analyze error Corrupt +ALTER TABLE t1 REBUILD PARTITION ALL; +ERROR 42000: Unknown table engine 'partition' +ALTER TABLE t1 ENGINE Memory; +ERROR 42000: Unknown table engine 'partition' +ALTER TABLE t1 ADD (new INT); +ERROR 42000: Unknown table engine 'partition' +DROP TABLE t1; CREATE TABLE t1 ( firstname VARCHAR(25) NOT NULL, lastname VARCHAR(25) NOT NULL, diff --git a/mysql-test/r/partition_disabled.result b/mysql-test/r/partition_disabled.result new file mode 100644 index 00000000000..df36f56a328 --- /dev/null +++ b/mysql-test/r/partition_disabled.result @@ -0,0 +1,93 @@ +DROP TABLE IF EXISTS t1; +FLUSH TABLES; +SELECT * FROM t1; +ERROR HY000: The MySQL server is running with the --skip-partition option so it cannot execute this statement +TRUNCATE TABLE t1; +ERROR HY000: The MySQL server is running with the --skip-partition option so it cannot execute this statement +ANALYZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 analyze Error The MySQL server is running with the --skip-partition option so it cannot execute this statement +test.t1 analyze error Corrupt +CHECK TABLE t1; +Table Op Msg_type Msg_text +test.t1 check Error The MySQL server is running with the --skip-partition option so it cannot execute this statement +test.t1 check error Corrupt +OPTIMIZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 optimize Error The MySQL server is running with the --skip-partition option so it cannot execute this statement +test.t1 optimize error Corrupt +REPAIR TABLE t1; +Table Op Msg_type Msg_text +test.t1 repair Error The MySQL server is running with the --skip-partition option so it cannot execute this statement +test.t1 repair error Corrupt +ALTER TABLE t1 REPAIR PARTITION ALL; +Table Op Msg_type Msg_text +test.t1 repair Error The MySQL server is running with the --skip-partition option so it cannot execute this statement +test.t1 repair error Corrupt +ALTER TABLE t1 CHECK PARTITION ALL; +Table Op Msg_type Msg_text +test.t1 check Error The MySQL server is running with the --skip-partition option so it cannot execute this statement +test.t1 check error Corrupt +ALTER TABLE t1 OPTIMIZE PARTITION ALL; +Table Op Msg_type Msg_text +test.t1 optimize Error The MySQL server is running with the --skip-partition option so it cannot execute this statement +test.t1 optimize error Corrupt +ALTER TABLE t1 ANALYZE PARTITION ALL; +Table Op Msg_type Msg_text +test.t1 analyze Error The MySQL server is running with the --skip-partition option so it cannot execute this statement +test.t1 analyze error Corrupt +ALTER TABLE t1 REBUILD PARTITION ALL; +ERROR HY000: The MySQL server is running with the --skip-partition option so it cannot execute this statement +ALTER TABLE t1 ENGINE Memory; +ERROR HY000: The MySQL server is running with the --skip-partition option so it cannot execute this statement +ALTER TABLE t1 ADD (new INT); +ERROR HY000: The MySQL server is running with the --skip-partition option so it cannot execute this statement +DROP TABLE t1; +CREATE TABLE t1 ( +firstname VARCHAR(25) NOT NULL, +lastname VARCHAR(25) NOT NULL, +username VARCHAR(16) NOT NULL, +email VARCHAR(35), +joined DATE NOT NULL +) +PARTITION BY KEY(joined) +PARTITIONS 6; +ERROR HY000: The MySQL server is running with the --skip-partition option so it cannot execute this statement +ALTER TABLE t1 PARTITION BY KEY(joined) PARTITIONS 2; +ERROR HY000: The MySQL server is running with the --skip-partition option so it cannot execute this statement +drop table t1; +ERROR 42S02: Unknown table 't1' +CREATE TABLE t1 ( +firstname VARCHAR(25) NOT NULL, +lastname VARCHAR(25) NOT NULL, +username VARCHAR(16) NOT NULL, +email VARCHAR(35), +joined DATE NOT NULL +) +PARTITION BY RANGE( YEAR(joined) ) ( +PARTITION p0 VALUES LESS THAN (1960), +PARTITION p1 VALUES LESS THAN (1970), +PARTITION p2 VALUES LESS THAN (1980), +PARTITION p3 VALUES LESS THAN (1990), +PARTITION p4 VALUES LESS THAN MAXVALUE +); +ERROR HY000: The MySQL server is running with the --skip-partition option so it cannot execute this statement +drop table t1; +ERROR 42S02: Unknown table 't1' +CREATE TABLE t1 (id INT, purchased DATE) +PARTITION BY RANGE( YEAR(purchased) ) +SUBPARTITION BY HASH( TO_DAYS(purchased) ) +SUBPARTITIONS 2 ( +PARTITION p0 VALUES LESS THAN (1990), +PARTITION p1 VALUES LESS THAN (2000), +PARTITION p2 VALUES LESS THAN MAXVALUE +); +ERROR HY000: The MySQL server is running with the --skip-partition option so it cannot execute this statement +drop table t1; +ERROR 42S02: Unknown table 't1' +create table t1 (a varchar(10) charset latin1 collate latin1_bin); +insert into t1 values (''),(' '),('a'),('a '),('a '); +explain partitions select * from t1 where a='a ' OR a='a'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 NULL ALL NULL NULL NULL NULL 5 Using where +drop table t1; diff --git a/mysql-test/std_data/parts/t1.frm b/mysql-test/std_data/parts/t1.frm new file mode 100644 index 0000000000000000000000000000000000000000..6709a93310e2e034528a5f0e6fdd63882f4ce62e GIT binary patch literal 8554 zcmeI&F%E(-6b9hG1ri7g17UILC=)Im04G?KD2pQ_4r&Ys@NOQ#`-o3#Iy;j1{{!#Q zrVaT<+NX+A4@eZSl7av(Iz$LNAk`+3^0))}=QRR~0x))tPYO_g0u-PC1t>rP3Q&Lo z6rcbFW-OpFxv%?n5ib389LC{%%4E*8)vjy0X1g)#gQ=^1ZI-?L2jEt+p#TLaKmiI+ zfC3bt00k&O0SZuHt^!9ThyH&Y1%(o^2n6t*LyJtt-zlM$PIL2PWDniL*KrIDEN-%c KCzmIte!>fpart_info= new partition_info(); diff --git a/sql/table.cc b/sql/table.cc index 95753e5353a..bf3c3711f31 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -914,6 +914,15 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head, we unlock the old value of share->db_plugin before replacing it with a globally locked version of tmp_plugin */ + /* Check if the partitioning engine is ready */ + if (!plugin_is_ready(&name, MYSQL_STORAGE_ENGINE_PLUGIN)) + { + error= 8; + my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), + "--skip-partition"); + my_free(buff, MYF(0)); + goto err; + } plugin_unlock(NULL, share->db_plugin); share->db_plugin= ha_lock_engine(NULL, partition_hton); DBUG_PRINT("info", ("setting dbtype to '%.*s' (%d)", From 4b6f5f530f06300a06794d41c96f412cf11325a7 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Thu, 9 Jul 2009 15:05:30 +0300 Subject: [PATCH 02/69] Bug #45962: memory leak after 'sort aborted' errors When the function exits with an error it was not freeing the local Unique class instance. Fixed my making sure all the places where the function returns from are freeing the Unique instance --- sql/opt_range.cc | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/sql/opt_range.cc b/sql/opt_range.cc index e3aef02637f..47067c03a85 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -8065,7 +8065,10 @@ int QUICK_INDEX_MERGE_SELECT::read_keys_and_merge() if (cur_quick->file->inited != handler::NONE) cur_quick->file->ha_index_end(); if (cur_quick->init() || cur_quick->reset()) + { + delete unique; DBUG_RETURN(1); + } } if (result) @@ -8073,13 +8076,17 @@ int QUICK_INDEX_MERGE_SELECT::read_keys_and_merge() if (result != HA_ERR_END_OF_FILE) { cur_quick->range_end(); + delete unique; DBUG_RETURN(result); } break; } if (thd->killed) + { + delete unique; DBUG_RETURN(1); + } /* skip row if it will be retrieved by clustered PK scan */ if (pk_quick_select && pk_quick_select->row_in_ranges()) @@ -8088,8 +8095,10 @@ int QUICK_INDEX_MERGE_SELECT::read_keys_and_merge() cur_quick->file->position(cur_quick->record); result= unique->unique_add((char*)cur_quick->file->ref); if (result) + { + delete unique; DBUG_RETURN(1); - + } } /* From dd10de57d37ccc82bad16f451aa4c8db91e694c2 Mon Sep 17 00:00:00 2001 From: Mattias Jonsson Date: Thu, 6 Aug 2009 14:28:39 +0200 Subject: [PATCH 03/69] Bug#46478: timestamp field incorrectly defaulted when partition is reoganized. Problem was that table->timestamp_field_type was not changed before copying rows between partitions. fixed by setting it to TIMESTAMP_NO_AUTO_SET as the first thing in fast_alter_partition_table, so that all if-branches is covered. --- mysql-test/r/partition.result | 37 +++++++++++++++++++++++++++++++++++ mysql-test/t/partition.test | 25 +++++++++++++++++++++++ sql/sql_partition.cc | 3 +++ 3 files changed, 65 insertions(+) diff --git a/mysql-test/r/partition.result b/mysql-test/r/partition.result index 8b95f4e7e12..ceb1da8349b 100644 --- a/mysql-test/r/partition.result +++ b/mysql-test/r/partition.result @@ -1,4 +1,41 @@ drop table if exists t1, t2; +CREATE TABLE t1 ( +a timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, +b varchar(10), +PRIMARY KEY (a) +) +PARTITION BY RANGE (to_days(a)) ( +PARTITION p1 VALUES LESS THAN (733407), +PARTITION pmax VALUES LESS THAN MAXVALUE +); +INSERT INTO t1 VALUES ('2007-07-30 17:35:48', 'p1'); +INSERT INTO t1 VALUES ('2009-07-14 17:35:55', 'pmax'); +INSERT INTO t1 VALUES ('2009-09-21 17:31:42', 'pmax'); +SELECT * FROM t1; +a b +2007-07-30 17:35:48 p1 +2009-07-14 17:35:55 pmax +2009-09-21 17:31:42 pmax +ALTER TABLE t1 REORGANIZE PARTITION pmax INTO ( +PARTITION p3 VALUES LESS THAN (733969), +PARTITION pmax VALUES LESS THAN MAXVALUE); +SELECT * FROM t1; +a b +2007-07-30 17:35:48 p1 +2009-07-14 17:35:55 pmax +2009-09-21 17:31:42 pmax +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + `b` varchar(10) DEFAULT NULL, + PRIMARY KEY (`a`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +/*!50100 PARTITION BY RANGE (to_days(a)) +(PARTITION p1 VALUES LESS THAN (733407) ENGINE = MyISAM, + PARTITION p3 VALUES LESS THAN (733969) ENGINE = MyISAM, + PARTITION pmax VALUES LESS THAN MAXVALUE ENGINE = MyISAM) */ +DROP TABLE t1; CREATE TABLE t1 (a INT, FOREIGN KEY (a) REFERENCES t0 (a)) ENGINE=MyISAM PARTITION BY HASH (a); diff --git a/mysql-test/t/partition.test b/mysql-test/t/partition.test index 542a992bb0e..74c5f8e0a67 100644 --- a/mysql-test/t/partition.test +++ b/mysql-test/t/partition.test @@ -14,6 +14,31 @@ drop table if exists t1, t2; --enable_warnings +# +# Bug#46478: timestamp field incorrectly defaulted when partition is reorganized +# +CREATE TABLE t1 ( + a timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + b varchar(10), + PRIMARY KEY (a) +) +PARTITION BY RANGE (to_days(a)) ( + PARTITION p1 VALUES LESS THAN (733407), + PARTITION pmax VALUES LESS THAN MAXVALUE +); + +INSERT INTO t1 VALUES ('2007-07-30 17:35:48', 'p1'); +INSERT INTO t1 VALUES ('2009-07-14 17:35:55', 'pmax'); +INSERT INTO t1 VALUES ('2009-09-21 17:31:42', 'pmax'); + +SELECT * FROM t1; +ALTER TABLE t1 REORGANIZE PARTITION pmax INTO ( + PARTITION p3 VALUES LESS THAN (733969), + PARTITION pmax VALUES LESS THAN MAXVALUE); +SELECT * FROM t1; +SHOW CREATE TABLE t1; +DROP TABLE t1; + # # Bug#36001: Partitions: spelling and using some error messages # diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index a181a6b3f13..61766e5c509 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -6077,6 +6077,9 @@ uint fast_alter_partition_table(THD *thd, TABLE *table, lpt->pack_frm_len= 0; thd->work_part_info= part_info; + /* Never update timestamp columns when alter */ + table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET; + if (fast_alter_partition & HA_PARTITION_ONE_PHASE) { /* From f42fab1b76e8435b5de753a35e047b369e07b60a Mon Sep 17 00:00:00 2001 From: Mattias Jonsson Date: Fri, 7 Aug 2009 15:08:32 +0200 Subject: [PATCH 04/69] Bug#32430: 'show innodb status' causes errors Invalid (old?) table or database name in logs Post push patch. Bug was that a non partitioned table file was not converted to system_charset, (due to table_name_len was not set). Also missing DBUG_RETURN. And Innodb adds quotes after calling the function, so I added one more mode where explain_filename does not add quotes. But it still appends the [sub]partition name as a comment. Also caught a minor quoting bug, the character '`' was not quoted in the identifier. (so 'a`b' was quoted as `a`b` and not `a``b`, this is mulitbyte characters aware.) sql/mysql_priv.h: Bug#32430: 'show innodb status' causes errors Invalid (old?) table or database name in logs Added an unquoted mode sql/share/errmsg.txt: Bug#32430: 'show innodb status' causes errors Invalid (old?) table or database name in logs Removed the quoting of identifier, only leaving the translated word. sql/sql_table.cc: Bug#32430: 'show innodb status' causes errors Invalid (old?) table or database name in logs Fixed quoting of '`' Added DBUG_RETURN. Corrected table_name_len. Added unquoted mode. --- sql/mysql_priv.h | 3 +- sql/share/errmsg.txt | 16 +++++----- sql/sql_table.cc | 76 +++++++++++++++++++++++++++++++++++--------- 3 files changed, 71 insertions(+), 24 deletions(-) diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 03c366a45bf..609254448e3 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -2261,7 +2261,8 @@ enum enum_explain_filename_mode { EXPLAIN_ALL_VERBOSE= 0, EXPLAIN_PARTITIONS_VERBOSE, - EXPLAIN_PARTITIONS_AS_COMMENT + EXPLAIN_PARTITIONS_AS_COMMENT, + EXPLAIN_PARTITIONS_AS_COMMENT_NO_QUOTING }; uint explain_filename(const char *from, char *to, uint to_length, enum_explain_filename_mode explain_mode); diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index 5531ee71620..3aba434b284 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -6184,17 +6184,17 @@ ER_FUNC_INEXISTENT_NAME_COLLISION 42000 # When updating these, please update EXPLAIN_FILENAME_MAX_EXTRA_LENGTH in # mysql_priv.h with the new maximal additional length for explain_filename. ER_DATABASE_NAME - eng "Database `%s`" - swe "Databas `%s`" + eng "Database" + swe "Databas" ER_TABLE_NAME - eng "Table `%s`" - swe "Tabell `%s`" + eng "Table" + swe "Tabell" ER_PARTITION_NAME - eng "Partition `%s`" - swe "Partition `%s`" + eng "Partition" + swe "Partition" ER_SUBPARTITION_NAME - eng "Subpartition `%s`" - swe "Subpartition `%s`" + eng "Subpartition" + swe "Subpartition" ER_TEMPORARY_NAME eng "Temporary" swe "Temporr" diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 0066c66eb59..7e4318b7d16 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -72,7 +72,7 @@ static void wait_for_kill_signal(THD *thd) @brief Helper function for explain_filename */ static char* add_identifier(char *to_p, const char * end_p, - const char* name, uint name_len, int errcode) + const char* name, uint name_len, bool add_quotes) { uint res; uint errors; @@ -92,18 +92,44 @@ static char* add_identifier(char *to_p, const char * end_p, res= strconvert(&my_charset_filename, conv_name, system_charset_info, conv_string, FN_REFLEN, &errors); if (!res || errors) + { + DBUG_PRINT("error", ("strconvert of '%s' failed with %u (errors: %u)", conv_name, res, errors)); conv_name= name; + } else { DBUG_PRINT("info", ("conv '%s' -> '%s'", conv_name, conv_string)); conv_name= conv_string; } - if (errcode) - to_p+= my_snprintf(to_p, end_p - to_p, ER(errcode), conv_name); + if (add_quotes && (end_p - to_p > 2)) + { + *(to_p++)= '`'; + while (*conv_name && (end_p - to_p - 1) > 0) + { + uint length= my_mbcharlen(system_charset_info, *conv_name); + if (!length) + length= 1; + if (length == 1 && *conv_name == '`') + { + if ((end_p - to_p) < 3) + break; + *(to_p++)= '`'; + *(to_p++)= *(conv_name++); + } + else if (length < (end_p - to_p)) + { + to_p= strnmov(to_p, conv_name, length); + conv_name+= length; + } + else + break; /* string already filled */ + } + to_p= strnmov(to_p, "`", end_p - to_p); + } else - to_p+= my_snprintf(to_p, end_p - to_p, "`%s`", conv_name); - return to_p; + to_p= strnmov(to_p, conv_name, end_p - to_p); + DBUG_RETURN(to_p); } @@ -135,6 +161,8 @@ static char* add_identifier(char *to_p, const char * end_p, [,[ Temporary| Renamed] Partition `p` [, Subpartition `sp`]] *| (| is really a /, and it is all in one line) + EXPLAIN_PARTITIONS_AS_COMMENT_NO_QUOTING -> + same as above but no quotes are added. @retval Length of returned string */ @@ -245,28 +273,39 @@ uint explain_filename(const char *from, part_name_len-= 5; } } + else + table_name_len= strlen(table_name); if (db_name) { if (explain_mode == EXPLAIN_ALL_VERBOSE) { - to_p= add_identifier(to_p, end_p, db_name, db_name_len, - ER_DATABASE_NAME); + to_p= strnmov(to_p, ER(ER_DATABASE_NAME), end_p - to_p); + *(to_p++)= ' '; + to_p= add_identifier(to_p, end_p, db_name, db_name_len, 1); to_p= strnmov(to_p, ", ", end_p - to_p); } else { - to_p= add_identifier(to_p, end_p, db_name, db_name_len, 0); + to_p= add_identifier(to_p, end_p, db_name, db_name_len, + (explain_mode != + EXPLAIN_PARTITIONS_AS_COMMENT_NO_QUOTING)); to_p= strnmov(to_p, ".", end_p - to_p); } } if (explain_mode == EXPLAIN_ALL_VERBOSE) - to_p= add_identifier(to_p, end_p, table_name, table_name_len, - ER_TABLE_NAME); + { + to_p= strnmov(to_p, ER(ER_TABLE_NAME), end_p - to_p); + *(to_p++)= ' '; + to_p= add_identifier(to_p, end_p, table_name, table_name_len, 1); + } else - to_p= add_identifier(to_p, end_p, table_name, table_name_len, 0); + to_p= add_identifier(to_p, end_p, table_name, table_name_len, + (explain_mode != + EXPLAIN_PARTITIONS_AS_COMMENT_NO_QUOTING)); if (part_name) { - if (explain_mode == EXPLAIN_PARTITIONS_AS_COMMENT) + if (explain_mode == EXPLAIN_PARTITIONS_AS_COMMENT || + explain_mode == EXPLAIN_PARTITIONS_AS_COMMENT_NO_QUOTING) to_p= strnmov(to_p, " /* ", end_p - to_p); else if (explain_mode == EXPLAIN_PARTITIONS_VERBOSE) to_p= strnmov(to_p, " ", end_p - to_p); @@ -280,15 +319,22 @@ uint explain_filename(const char *from, to_p= strnmov(to_p, ER(ER_RENAMED_NAME), end_p - to_p); to_p= strnmov(to_p, " ", end_p - to_p); } + to_p= strnmov(to_p, ER(ER_PARTITION_NAME), end_p - to_p); + *(to_p++)= ' '; to_p= add_identifier(to_p, end_p, part_name, part_name_len, - ER_PARTITION_NAME); + (explain_mode != + EXPLAIN_PARTITIONS_AS_COMMENT_NO_QUOTING)); if (subpart_name) { to_p= strnmov(to_p, ", ", end_p - to_p); + to_p= strnmov(to_p, ER(ER_SUBPARTITION_NAME), end_p - to_p); + *(to_p++)= ' '; to_p= add_identifier(to_p, end_p, subpart_name, subpart_name_len, - ER_SUBPARTITION_NAME); + (explain_mode != + EXPLAIN_PARTITIONS_AS_COMMENT_NO_QUOTING)); } - if (explain_mode == EXPLAIN_PARTITIONS_AS_COMMENT) + if (explain_mode == EXPLAIN_PARTITIONS_AS_COMMENT || + explain_mode == EXPLAIN_PARTITIONS_AS_COMMENT_NO_QUOTING) to_p= strnmov(to_p, " */", end_p - to_p); } DBUG_PRINT("exit", ("to '%s'", to)); From 0d821fafe99fbaf362529f8237b4a61a6394c0fb Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 12 Aug 2009 11:54:05 +0800 Subject: [PATCH 05/69] BUG#45516 SQL thread does not use database charset properly Replication SQL thread does not set database default charset to thd->variables.collation_database properly, when executing LOAD DATA binlog. This bug can be repeated by using "LOAD DATA" command in STATEMENT mode. This patch adds code to find the default character set of the current database then assign it to thd->db_charset when slave server begins to execute a relay log. The test of this bug is added into rpl_loaddata_charset.test --- mysql-test/include/rpl_loaddata_charset.inc | 35 ++++++++++++++++++ mysql-test/r/rpl_loaddata_charset.result | 41 +++++++++++++++++++++ mysql-test/std_data/loaddata_utf8.dat | 3 ++ mysql-test/t/rpl_loaddata_charset.test | 17 +++++++++ sql/log_event.cc | 10 +++++ 5 files changed, 106 insertions(+) create mode 100644 mysql-test/include/rpl_loaddata_charset.inc create mode 100644 mysql-test/std_data/loaddata_utf8.dat diff --git a/mysql-test/include/rpl_loaddata_charset.inc b/mysql-test/include/rpl_loaddata_charset.inc new file mode 100644 index 00000000000..f94ff4ed069 --- /dev/null +++ b/mysql-test/include/rpl_loaddata_charset.inc @@ -0,0 +1,35 @@ +connection master; +--disable_warnings +DROP DATABASE IF EXISTS mysqltest; +--enable_warnings + +CREATE DATABASE mysqltest CHARSET UTF8; +USE mysqltest; +CREATE TABLE t (cl varchar(100)) CHARSET UTF8; + +if (!$LOAD_LOCAL) +{ + LOAD DATA INFILE '../std_data_ln/loaddata_utf8.dat' INTO TABLE t + FIELDS TERMINATED BY ',' LINES TERMINATED BY '\n'; +} +if ($LOAD_LOCAL) +{ + LOAD DATA LOCAL INFILE './std_data/loaddata_utf8.dat' INTO TABLE t + FIELDS TERMINATED BY ',' LINES TERMINATED BY '\n'; +} + +save_master_pos; +echo ----------content on master----------; +SELECT hex(cl) FROM t; + +connection slave; +sync_with_master; +echo ----------content on slave----------; +USE mysqltest; +SELECT hex(cl) FROM t; + +connection master; +DROP DATABASE mysqltest; +save_master_pos; +connection slave; +sync_with_master; diff --git a/mysql-test/r/rpl_loaddata_charset.result b/mysql-test/r/rpl_loaddata_charset.result index 929d06e74cf..47fee19cf5d 100644 --- a/mysql-test/r/rpl_loaddata_charset.result +++ b/mysql-test/r/rpl_loaddata_charset.result @@ -35,3 +35,44 @@ C3BF D0AA D0AA drop table t1; +-------------test bug#45516------------------ +DROP DATABASE IF EXISTS mysqltest; +CREATE DATABASE mysqltest CHARSET UTF8; +USE mysqltest; +CREATE TABLE t (cl varchar(100)) CHARSET UTF8; +LOAD DATA LOCAL INFILE './std_data/loaddata_utf8.dat' INTO TABLE t +FIELDS TERMINATED BY ',' LINES TERMINATED BY '\n'; +----------content on master---------- +SELECT hex(cl) FROM t; +hex(cl) +E4B880E4BA8CE4B889 +E59B9BE4BA94E585AD +E4B883E585ABE4B99D +----------content on slave---------- +USE mysqltest; +SELECT hex(cl) FROM t; +hex(cl) +E4B880E4BA8CE4B889 +E59B9BE4BA94E585AD +E4B883E585ABE4B99D +DROP DATABASE mysqltest; +DROP DATABASE IF EXISTS mysqltest; +CREATE DATABASE mysqltest CHARSET UTF8; +USE mysqltest; +CREATE TABLE t (cl varchar(100)) CHARSET UTF8; +LOAD DATA INFILE '../std_data_ln/loaddata_utf8.dat' INTO TABLE t +FIELDS TERMINATED BY ',' LINES TERMINATED BY '\n'; +----------content on master---------- +SELECT hex(cl) FROM t; +hex(cl) +E4B880E4BA8CE4B889 +E59B9BE4BA94E585AD +E4B883E585ABE4B99D +----------content on slave---------- +USE mysqltest; +SELECT hex(cl) FROM t; +hex(cl) +E4B880E4BA8CE4B889 +E59B9BE4BA94E585AD +E4B883E585ABE4B99D +DROP DATABASE mysqltest; diff --git a/mysql-test/std_data/loaddata_utf8.dat b/mysql-test/std_data/loaddata_utf8.dat new file mode 100644 index 00000000000..fc7a28229d4 --- /dev/null +++ b/mysql-test/std_data/loaddata_utf8.dat @@ -0,0 +1,3 @@ +一二三 +四五六 +七八九 diff --git a/mysql-test/t/rpl_loaddata_charset.test b/mysql-test/t/rpl_loaddata_charset.test index 7f2389cb9f6..05dbdd01b39 100644 --- a/mysql-test/t/rpl_loaddata_charset.test +++ b/mysql-test/t/rpl_loaddata_charset.test @@ -31,3 +31,20 @@ select hex(a) from t1; connection master; drop table t1; sync_slave_with_master; + +# +# Bug#45516 +# When slave SQL thread executing LOAD DATA command, the +# thd->variables.collation_database was not set properly to the default +# database charset +# + +echo -------------test bug#45516------------------; + +# LOAD DATA INFILE +let $LOAD_LOCAL=1; +source include/rpl_loaddata_charset.inc; + +# LOAD DATA LOCAL INFILE +let $LOAD_LOCAL=0; +source include/rpl_loaddata_charset.inc; diff --git a/sql/log_event.cc b/sql/log_event.cc index 9b0f8e97a28..40e29e58ab6 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -1918,6 +1918,8 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli, { const char *new_db= rewrite_db(db); int expected_error,actual_error= 0; + HA_CREATE_INFO db_options; + /* Colleagues: please never free(thd->catalog) in MySQL. This would lead to bugs as here thd->catalog is a part of an alloced block, not an entire @@ -1926,6 +1928,14 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli, */ thd->catalog= catalog_len ? (char *) catalog : (char *)""; thd->set_db(new_db, (uint) strlen(new_db)); /* allocates a copy of 'db' */ + + /* + Setting the character set and collation of the current database thd->db. + */ + load_db_opt_by_name(thd, thd->db, &db_options); + if (db_options.default_table_charset) + thd->db_charset= db_options.default_table_charset; + thd->variables.auto_increment_increment= auto_increment_increment; thd->variables.auto_increment_offset= auto_increment_offset; From 1402275a53db6fc931739de46f88121924de1e02 Mon Sep 17 00:00:00 2001 From: Konstantin Osipov Date: Wed, 12 Aug 2009 14:57:41 +0400 Subject: [PATCH 06/69] A follow up patch for Bug#45829 "CREATE TABLE TRANSACTIONAL PAGE_CHECKSUM ROW_FORMAT=PAGE accepted, does nothing" Remove unused code that would lead to warnings when compiling sql_yacc.yy. sql/handler.h: Remove unused defines. sql/sql_yacc.yy: Remove unused grammar. sql/table.h: Remove unused TABLE members. --- sql/handler.h | 6 ------ sql/sql_yacc.yy | 8 -------- sql/table.h | 4 ---- 3 files changed, 18 deletions(-) diff --git a/sql/handler.h b/sql/handler.h index 01f673ecd51..726926bcb46 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -895,8 +895,6 @@ class partition_info; struct st_partition_iter; #define NOT_A_PARTITION_ID ((uint32)-1) -enum ha_choice { HA_CHOICE_UNDEF, HA_CHOICE_NO, HA_CHOICE_YES }; - typedef struct st_ha_create_information { CHARSET_INFO *table_charset, *default_table_charset; @@ -918,14 +916,10 @@ typedef struct st_ha_create_information uint options; /* OR of HA_CREATE_ options */ uint merge_insert_method; uint extra_size; /* length of extra data segment */ - /** Transactional or not. Unused; reserved for future versions. */ - enum ha_choice transactional; bool table_existed; /* 1 in create if table existed */ bool frm_only; /* 1 if no ha_create_table() */ bool varchar; /* 1 if table has a VARCHAR */ enum ha_storage_media storage_media; /* DEFAULT, DISK or MEMORY */ - /** Per-page checksums or not. Unused; reserved for future versions. */ - enum ha_choice page_checksum; } HA_CREATE_INFO; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 320b43c8e5c..11250404da6 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -494,7 +494,6 @@ Item* handle_sql2003_note184_exception(THD *thd, Item* left, bool equal, enum enum_tx_isolation tx_isolation; enum Cast_target cast_type; enum Item_udftype udf_type; - enum ha_choice choice; CHARSET_INFO *charset; thr_lock_type lock_type; interval_type interval, interval_time_st; @@ -1164,8 +1163,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %type ulonglong_num real_ulonglong_num size_number -%type choice - %type part_bit_expr @@ -9066,11 +9063,6 @@ dec_num: | FLOAT_NUM ; -choice: - ulong_num { $$= $1 != 0 ? HA_CHOICE_YES : HA_CHOICE_NO; } - | DEFAULT { $$= HA_CHOICE_UNDEF; } - ; - procedure_clause: /* empty */ | PROCEDURE ident /* Procedure name */ diff --git a/sql/table.h b/sql/table.h index 653d04b149e..3b6a0871d09 100644 --- a/sql/table.h +++ b/sql/table.h @@ -361,10 +361,6 @@ typedef struct st_table_share } enum row_type row_type; /* How rows are stored */ enum tmp_table_type tmp_table; - /** Transactional or not. Unused; reserved for future versions. */ - enum ha_choice transactional; - /** Per-page checksums or not. Unused; reserved for future versions. */ - enum ha_choice page_checksum; uint ref_count; /* How many TABLE objects uses this */ uint open_count; /* Number of tables in open list */ From b28f09bd8cf65a0ce7dbe8fb04033cdf7f9323ff Mon Sep 17 00:00:00 2001 From: Konstantin Osipov Date: Wed, 12 Aug 2009 17:11:06 +0400 Subject: [PATCH 07/69] A follow up patch for the follow up patch for Bug#45829 "CREATE TABLE TRANSACTIONAL PAGE_CHECKSUM ROW_FORMAT=PAGE accepted, does nothing". Put back stubs for members of structures that are shared between sql/ and pluggable storage engines. to not break ABI unnecessarily. To be NULL-merged into 5.4, where we do break the ABI already. --- sql/handler.h | 4 ++++ sql/table.h | 2 ++ 2 files changed, 6 insertions(+) diff --git a/sql/handler.h b/sql/handler.h index 726926bcb46..f76f940fd37 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -895,6 +895,8 @@ class partition_info; struct st_partition_iter; #define NOT_A_PARTITION_ID ((uint32)-1) +enum enum_ha_unused { HA_CHOICE_UNDEF, HA_CHOICE_NO, HA_CHOICE_YES }; + typedef struct st_ha_create_information { CHARSET_INFO *table_charset, *default_table_charset; @@ -916,10 +918,12 @@ typedef struct st_ha_create_information uint options; /* OR of HA_CREATE_ options */ uint merge_insert_method; uint extra_size; /* length of extra data segment */ + enum enum_ha_unused unused1; bool table_existed; /* 1 in create if table existed */ bool frm_only; /* 1 if no ha_create_table() */ bool varchar; /* 1 if table has a VARCHAR */ enum ha_storage_media storage_media; /* DEFAULT, DISK or MEMORY */ + enum enum_ha_unused unused2; } HA_CREATE_INFO; diff --git a/sql/table.h b/sql/table.h index 3b6a0871d09..40372fa91cf 100644 --- a/sql/table.h +++ b/sql/table.h @@ -361,6 +361,8 @@ typedef struct st_table_share } enum row_type row_type; /* How rows are stored */ enum tmp_table_type tmp_table; + enum enum_ha_unused unused1; + enum enum_ha_unused unused2; uint ref_count; /* How many TABLE objects uses this */ uint open_count; /* Number of tables in open list */ From fce4fa362c5234f1e85212060f61b842844192b7 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 13 Aug 2009 10:48:57 +0800 Subject: [PATCH 08/69] BUG#45574 CREATE IF NOT EXISTS is not binlogged if the object exists There is an inconsistency with DROP DATABASE|TABLE|EVENT IF EXISTS and CREATE DATABASE|TABLE|EVENT IF NOT EXISTS. DROP IF EXISTS statements are binlogged even if either the DB, TABLE or EVENT does not exist. In contrast, Only the CREATE EVENT IF NOT EXISTS is binlogged when the EVENT exists. This patch fixes the following cases for all the replication formats: CREATE DATABASE IF NOT EXISTS. CREATE TABLE IF NOT EXISTS, CREATE TABLE IF NOT EXISTS ... LIKE, CREAET TABLE IF NOT EXISTS ... SELECT. sql/sql_insert.cc: Part of the code was moved from the create_table_from_items to select_create::prepare. When replication is row based, CREATE TABLE IF NOT EXISTS.. SELECT is binlogged if the table exists. --- .../rpl/r/rpl_create_if_not_exists.result | 33 ++++++++ .../rpl_create_tmp_table_if_not_exists.result | 22 +++++ .../suite/rpl/t/rpl_create_if_not_exists.test | 70 ++++++++++++++++ .../t/rpl_create_tmp_table_if_not_exists.test | 41 +++++++++ sql/sql_db.cc | 7 +- sql/sql_insert.cc | 52 +++++++----- sql/sql_table.cc | 83 +++++++++++++------ 7 files changed, 255 insertions(+), 53 deletions(-) create mode 100644 mysql-test/suite/rpl/r/rpl_create_if_not_exists.result create mode 100644 mysql-test/suite/rpl/r/rpl_create_tmp_table_if_not_exists.result create mode 100644 mysql-test/suite/rpl/t/rpl_create_if_not_exists.test create mode 100644 mysql-test/suite/rpl/t/rpl_create_tmp_table_if_not_exists.test diff --git a/mysql-test/suite/rpl/r/rpl_create_if_not_exists.result b/mysql-test/suite/rpl/r/rpl_create_if_not_exists.result new file mode 100644 index 00000000000..536f40dc7f1 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_create_if_not_exists.result @@ -0,0 +1,33 @@ +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; +DROP DATABASE IF EXISTS mysqltest; +CREATE DATABASE IF NOT EXISTS mysqltest; +USE mysqltest; +CREATE TABLE IF NOT EXISTS t(c1 int); +CREATE TABLE IF NOT EXISTS t1 LIKE t; +CREATE TABLE IF NOT EXISTS t2 SELECT * FROM t; +CREATE EVENT IF NOT EXISTS e +ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR +DO SELECT now(); +DROP DATABASE mysqltest; +CREATE DATABASE IF NOT EXISTS mysqltest; +USE mysqltest; +CREATE TABLE IF NOT EXISTS t(c1 int); +CREATE TABLE IF NOT EXISTS t1 LIKE t; +CREATE TABLE IF NOT EXISTS t2 SELECT * FROM t; +CREATE EVENT IF NOT EXISTS e +ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR +DO SELECT now(); +SHOW TABLES in mysqltest; +Tables_in_mysqltest +t +t1 +t2 +SHOW EVENTS in mysqltest; +Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator character_set_client collation_connection Database Collation +mysqltest e @ SYSTEM ONE TIME # NULL NULL NULL NULL SLAVESIDE_DISABLED 1 latin1 latin1_swedish_ci latin1_swedish_ci +DROP DATABASE IF EXISTS mysqltest; diff --git a/mysql-test/suite/rpl/r/rpl_create_tmp_table_if_not_exists.result b/mysql-test/suite/rpl/r/rpl_create_tmp_table_if_not_exists.result new file mode 100644 index 00000000000..8d0b61cc6d8 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_create_tmp_table_if_not_exists.result @@ -0,0 +1,22 @@ +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; +DROP DATABASE IF EXISTS mysqltest; +CREATE TEMPORARY TABLE IF NOT EXISTS tmp(c1 int); +CREATE TEMPORARY TABLE IF NOT EXISTS tmp(c1 int); +CREATE TEMPORARY TABLE IF NOT EXISTS tmp1 LIKE tmp; +CREATE TEMPORARY TABLE IF NOT EXISTS tmp1 LIKE tmp; +CREATE TEMPORARY TABLE IF NOT EXISTS tmp2 SELECT * FROM tmp; +CREATE TEMPORARY TABLE IF NOT EXISTS tmp2 SELECT * FROM tmp; +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # DROP DATABASE IF EXISTS mysqltest +master-bin.000001 # Query # # use `test`; CREATE TEMPORARY TABLE IF NOT EXISTS tmp(c1 int) +master-bin.000001 # Query # # use `test`; CREATE TEMPORARY TABLE IF NOT EXISTS tmp(c1 int) +master-bin.000001 # Query # # use `test`; CREATE TEMPORARY TABLE IF NOT EXISTS tmp1 LIKE tmp +master-bin.000001 # Query # # use `test`; CREATE TEMPORARY TABLE IF NOT EXISTS tmp1 LIKE tmp +master-bin.000001 # Query # # use `test`; CREATE TEMPORARY TABLE IF NOT EXISTS tmp2 SELECT * FROM tmp +master-bin.000001 # Query # # use `test`; CREATE TEMPORARY TABLE IF NOT EXISTS tmp2 SELECT * FROM tmp diff --git a/mysql-test/suite/rpl/t/rpl_create_if_not_exists.test b/mysql-test/suite/rpl/t/rpl_create_if_not_exists.test new file mode 100644 index 00000000000..5faf95a4d84 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_create_if_not_exists.test @@ -0,0 +1,70 @@ +# BUG#45574: +# SP: CREATE DATABASE|TABLE IF NOT EXISTS not binlogged if routine exists. +# +# There is an inconsistency with DROP DATABASE|TABLE|EVENT IF EXISTS and +# CREATE DATABASE|TABLE|EVENT IF NOT EXISTS. DROP IF EXISTS statements are +# binlogged even if either the DB, TABLE or EVENT does not exist. In +# contrast, Only the CREATE EVENT IF NOT EXISTS is binlogged when the EVENT +# exists. +# +# This problem caused some of the tests to fail randomly on PB or PB2. +# +# Description: +# Fixed this bug by adding calls to write_bin_log in: +# mysql_create_db +# mysql_create_table_no_lock +# mysql_create_like_table +# create_table_from_items +# +# Test is implemented as follows: +# i) test each "CREATE IF NOT EXISTS" (DDL), found in MySQL 5.1 manual +# exclude CREATE TEMPORARY TABLE, on existent objects; +# +# Note: +# rpl_create_tmp_table_if_not_exists.test tests CREATE TEMPORARY TABLE cases. +# +# References: +# http://dev.mysql.com/doc/refman/5.1/en/sql-syntax-data-definition.html +# + +source include/master-slave.inc; +disable_warnings; +DROP DATABASE IF EXISTS mysqltest; + +CREATE DATABASE IF NOT EXISTS mysqltest; +USE mysqltest; +CREATE TABLE IF NOT EXISTS t(c1 int); +CREATE TABLE IF NOT EXISTS t1 LIKE t; +CREATE TABLE IF NOT EXISTS t2 SELECT * FROM t; +CREATE EVENT IF NOT EXISTS e +ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR +DO SELECT now(); +sync_slave_with_master; + +connection slave; +#DROP database from slave. +#The database and all tables can be recreated in slave +#if binlog of the second CREATE command is recorded and sent from master to slave. +DROP DATABASE mysqltest; + +connection master; +CREATE DATABASE IF NOT EXISTS mysqltest; +USE mysqltest; +CREATE TABLE IF NOT EXISTS t(c1 int); +CREATE TABLE IF NOT EXISTS t1 LIKE t; +CREATE TABLE IF NOT EXISTS t2 SELECT * FROM t; +CREATE EVENT IF NOT EXISTS e +ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR +DO SELECT now(); +sync_slave_with_master; + +connection slave; +SHOW TABLES in mysqltest; +#Execution time changes in each run. So we disregard it by calling replace_column. +replace_column 6 #; +SHOW EVENTS in mysqltest; + + +connection master; +DROP DATABASE IF EXISTS mysqltest; +source include/master-slave-end.inc; diff --git a/mysql-test/suite/rpl/t/rpl_create_tmp_table_if_not_exists.test b/mysql-test/suite/rpl/t/rpl_create_tmp_table_if_not_exists.test new file mode 100644 index 00000000000..a06dfa54cb1 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_create_tmp_table_if_not_exists.test @@ -0,0 +1,41 @@ +# BUG#45574: +# SP: CREATE DATABASE|TABLE IF NOT EXISTS not binlogged if routine exists. +# +# There is an inconsistency with DROP DATABASE|TABLE|EVENT IF EXISTS and +# CREATE DATABASE|TABLE|EVENT IF NOT EXISTS. DROP IF EXISTS statements are +# binlogged even if either the DB, TABLE or EVENT does not exist. In +# contrast, Only the CREATE EVENT IF NOT EXISTS is binlogged when the EVENT +# exists. +# +# This problem caused some of the tests to fail randomly on PB or PB2. +# +# Test is implemented as follows: +# +# i) test each "CREATE TEMPORARY TABLE IF EXISTS" (DDL), found in MySQL +# 5.1 manual, on existent objects; +# ii) show binlog events; +# +# Note: +# rpl_create_if_not_exists.test tests other cases. +# +# References: +# http://dev.mysql.com/doc/refman/5.1/en/sql-syntax-data-definition.html +# + +source include/master-slave.inc; +#CREATE TEMPORARY TABLE statements are not binlogged in row mode, +#So it must be test by itself. +source include/have_binlog_format_mixed_or_statement.inc; +disable_warnings; + +DROP DATABASE IF EXISTS mysqltest; + +CREATE TEMPORARY TABLE IF NOT EXISTS tmp(c1 int); +CREATE TEMPORARY TABLE IF NOT EXISTS tmp(c1 int); +CREATE TEMPORARY TABLE IF NOT EXISTS tmp1 LIKE tmp; +CREATE TEMPORARY TABLE IF NOT EXISTS tmp1 LIKE tmp; +CREATE TEMPORARY TABLE IF NOT EXISTS tmp2 SELECT * FROM tmp; +CREATE TEMPORARY TABLE IF NOT EXISTS tmp2 SELECT * FROM tmp; +source include/show_binlog_events.inc; + +source include/master-slave-end.inc; diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 98d17fdd318..3fca5bd7df6 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -658,10 +658,8 @@ int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info, } push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_DB_CREATE_EXISTS, ER(ER_DB_CREATE_EXISTS), db); - if (!silent) - my_ok(thd); error= 0; - goto exit; + goto not_silent; } else { @@ -698,7 +696,8 @@ int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info, happened. (This is a very unlikely senario) */ } - + +not_silent: if (!silent) { char *query; diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 7d581f8c3a9..a799cbea4c2 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -3392,25 +3392,6 @@ static TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, bool not_used; DBUG_ENTER("create_table_from_items"); - DBUG_EXECUTE_IF("sleep_create_select_before_check_if_exists", my_sleep(6000000);); - - if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE) && - create_table->table->db_stat) - { - /* Table already exists and was open at open_and_lock_tables() stage. */ - if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS) - { - create_info->table_existed= 1; // Mark that table existed - push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, - ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR), - create_table->table_name); - DBUG_RETURN(create_table->table); - } - - my_error(ER_TABLE_EXISTS_ERROR, MYF(0), create_table->table_name); - DBUG_RETURN(0); - } - tmp_table.alias= 0; tmp_table.timestamp_field= 0; tmp_table.s= &share; @@ -3612,10 +3593,35 @@ select_create::prepare(List &values, SELECT_LEX_UNIT *u) thd->binlog_start_trans_and_stmt(); } - if (!(table= create_table_from_items(thd, create_info, create_table, - alter_info, &values, - &extra_lock, hook_ptr))) - DBUG_RETURN(-1); // abort() deletes table + DBUG_EXECUTE_IF("sleep_create_select_before_check_if_exists", my_sleep(6000000);); + + if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE) && + create_table->table->db_stat) + { + /* Table already exists and was open at open_and_lock_tables() stage. */ + if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS) + { + /* Mark that table existed */ + create_info->table_existed= 1; + push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, + ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR), + create_table->table_name); + if (thd->current_stmt_binlog_row_based) + binlog_show_create_table(&(create_table->table), 1); + table= create_table->table; + } + else + { + my_error(ER_TABLE_EXISTS_ERROR, MYF(0), create_table->table_name); + DBUG_RETURN(-1); + } + } + else + if (!(table= create_table_from_items(thd, create_info, create_table, + alter_info, &values, + &extra_lock, hook_ptr))) + /* abort() deletes table */ + DBUG_RETURN(-1); if (extra_lock) { diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 0066c66eb59..81d00f46000 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -3475,6 +3475,41 @@ void sp_prepare_create_field(THD *thd, Create_field *sql_field) } +/* + Write CREATE TABLE binlog + + SYNOPSIS + write_create_table_bin_log() + thd Thread object + create_info Create information + internal_tmp_table Set to 1 if this is an internal temporary table + + DESCRIPTION + This function only is called in mysql_create_table_no_lock and + mysql_create_table + + RETURN VALUES + NONE + */ +static inline void write_create_table_bin_log(THD *thd, + const HA_CREATE_INFO *create_info, + bool internal_tmp_table) +{ + /* + Don't write statement if: + - It is an internal temporary table, + - Row-based logging is used and it we are creating a temporary table, or + - The binary log is not open. + Otherwise, the statement shall be binlogged. + */ + if (!internal_tmp_table && + (!thd->current_stmt_binlog_row_based || + (thd->current_stmt_binlog_row_based && + !(create_info->options & HA_LEX_CREATE_TMP_TABLE)))) + write_bin_log(thd, TRUE, thd->query, thd->query_length); +} + + /* Create a table @@ -3738,6 +3773,7 @@ bool mysql_create_table_no_lock(THD *thd, ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR), alias); error= 0; + write_create_table_bin_log(thd, create_info, internal_tmp_table); goto err; } my_error(ER_TABLE_EXISTS_ERROR, MYF(0), alias); @@ -3858,18 +3894,7 @@ bool mysql_create_table_no_lock(THD *thd, thd->thread_specific_used= TRUE; } - /* - Don't write statement if: - - It is an internal temporary table, - - Row-based logging is used and it we are creating a temporary table, or - - The binary log is not open. - Otherwise, the statement shall be binlogged. - */ - if (!internal_tmp_table && - (!thd->current_stmt_binlog_row_based || - (thd->current_stmt_binlog_row_based && - !(create_info->options & HA_LEX_CREATE_TMP_TABLE)))) - write_bin_log(thd, TRUE, thd->query, thd->query_length); + write_create_table_bin_log(thd, create_info, internal_tmp_table); error= FALSE; unlock_and_end: VOID(pthread_mutex_unlock(&LOCK_open)); @@ -3885,6 +3910,7 @@ warn: ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR), alias); create_info->table_existed= 1; // Mark that table existed + write_create_table_bin_log(thd, create_info, internal_tmp_table); goto unlock_and_end; } @@ -3936,6 +3962,7 @@ bool mysql_create_table(THD *thd, const char *db, const char *table_name, table_name); create_info->table_existed= 1; result= FALSE; + write_create_table_bin_log(thd, create_info, internal_tmp_table); } else { @@ -5276,6 +5303,24 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table, goto err; /* purecov: inspected */ } +goto binlog; + +table_exists: + if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS) + { + char warn_buff[MYSQL_ERRMSG_SIZE]; + my_snprintf(warn_buff, sizeof(warn_buff), + ER(ER_TABLE_EXISTS_ERROR), table_name); + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, + ER_TABLE_EXISTS_ERROR,warn_buff); + } + else + { + my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name); + goto err; + } + +binlog: DBUG_EXECUTE_IF("sleep_create_like_before_binlogging", my_sleep(6000000);); /* @@ -5339,20 +5384,6 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table, write_bin_log(thd, TRUE, thd->query, thd->query_length); res= FALSE; - goto err; - -table_exists: - if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS) - { - char warn_buff[MYSQL_ERRMSG_SIZE]; - my_snprintf(warn_buff, sizeof(warn_buff), - ER(ER_TABLE_EXISTS_ERROR), table_name); - push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, - ER_TABLE_EXISTS_ERROR,warn_buff); - res= FALSE; - } - else - my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name); err: if (name_lock) From 78585a25ff19eb304185d50f864138e0b5f29106 Mon Sep 17 00:00:00 2001 From: Alfranio Correia Date: Thu, 13 Aug 2009 17:21:01 +0100 Subject: [PATCH 09/69] BUG#46130 Slave does not correctly handle "expected errors" In STATEMENT based replication, a statement that failed on the master but that updated non-transactional tables is written to binary log with the error code appended to it. On the slave, the statement is executed and the same error is expected. However, when an "expected error" did not happen on the slave and was either ignored or was related to a concurrency issue on the master, the slave did not rollback the effects of the statement and as such inconsistencies might happen. To fix the problem, we automatically rollback a statement that should have failed on a slave but succeded and whose expected failure is either ignored or stems from a concurrency issue on the master. --- mysql-test/suite/rpl/r/rpl_concurrency_error.result | 2 ++ mysql-test/suite/rpl/t/rpl_concurrency_error.test | 13 ++++++------- sql/log_event.cc | 13 +++++++++++-- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/mysql-test/suite/rpl/r/rpl_concurrency_error.result b/mysql-test/suite/rpl/r/rpl_concurrency_error.result index 88ad3da6450..83e5f66a9c4 100644 --- a/mysql-test/suite/rpl/r/rpl_concurrency_error.result +++ b/mysql-test/suite/rpl/r/rpl_concurrency_error.result @@ -101,6 +101,8 @@ master-bin.000001 # Query # # use `test`; UPDATE t SET f = 'dark blue 1' WHERE f master-bin.000001 # Query # # use `test`; INSERT INTO t VALUES (6 + (1 * 10),"brown") master-bin.000001 # Query # # use `test`; INSERT INTO n VALUES (now(),"brown") master-bin.000001 # Xid # # COMMIT /* XID */ +source include/diff_master_slave.inc; +source include/diff_master_slave.inc; ######################################################################## # Cleanup ######################################################################## diff --git a/mysql-test/suite/rpl/t/rpl_concurrency_error.test b/mysql-test/suite/rpl/t/rpl_concurrency_error.test index 816abb5739f..da2951afb1a 100644 --- a/mysql-test/suite/rpl/t/rpl_concurrency_error.test +++ b/mysql-test/suite/rpl/t/rpl_concurrency_error.test @@ -125,14 +125,13 @@ while ($type) connection master; sync_slave_with_master; -# Re-enable this after fixing BUG#46130 -#connection master; -#let $diff_statement= SELECT * FROM t order by i; -#source include/diff_master_slave.inc; +connection master; +let $diff_statement= SELECT * FROM t order by i; +source include/diff_master_slave.inc; -#connection master; -#let $diff_statement= SELECT * FROM n order by d, f; -#source include/diff_master_slave.inc; +connection master; +let $diff_statement= SELECT * FROM n order by d, f; +source include/diff_master_slave.inc; --echo ######################################################################## --echo # Cleanup diff --git a/sql/log_event.cc b/sql/log_event.cc index e7cbbaba38e..49d5478c3c4 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -3160,7 +3160,7 @@ compare_errors: /* If we expected a non-zero error code, and we don't get the same error - code, and none of them should be ignored. + code, and it should be ignored or is related to a concurrency issue. */ actual_error= thd->is_error() ? thd->main_da.sql_errno() : 0; DBUG_PRINT("info",("expected_error: %d sql_errno: %d", @@ -3183,7 +3183,8 @@ Default database: '%s'. Query: '%s'", thd->is_slave_error= 1; } /* - If we get the same error code as expected, or they should be ignored. + If we get the same error code as expected and it is not a concurrency + issue, or should be ignored. */ else if ((expected_error == actual_error && !concurrency_error_code(expected_error)) || @@ -3193,6 +3194,14 @@ Default database: '%s'. Query: '%s'", clear_all_errors(thd, const_cast(rli)); thd->killed= THD::NOT_KILLED; } + /* + If we expected a non-zero error code and get nothing and, it is a concurrency + issue or should be ignored. + */ + else if (expected_error && !actual_error && + (concurrency_error_code(expected_error) || + ignored_error_code(expected_error))) + ha_autocommit_or_rollback(thd, TRUE); /* Other cases: mostly we expected no error and get one. */ From 3b1280fa7eb411fdeaf60cbf023ff2580caecce7 Mon Sep 17 00:00:00 2001 From: Ramil Kalimullin Date: Fri, 14 Aug 2009 00:49:28 +0500 Subject: [PATCH 10/69] Fix for bug #46614: Assertion in show_create_trigger() on SHOW CREATE TRIGGER + MERGE table Problem: SHOW CREATE TRIGGER erroneously relies on fact that we have the only underlying table for a trigger (wrong for merge tables). Fix: remove erroneous assert(). mysql-test/r/merge.result: Fix for bug #46614: Assertion in show_create_trigger() on SHOW CREATE TRIGGER + MERGE table - test result. mysql-test/t/merge.test: Fix for bug #46614: Assertion in show_create_trigger() on SHOW CREATE TRIGGER + MERGE table - test case. sql/sql_show.cc: Fix for bug #46614: Assertion in show_create_trigger() on SHOW CREATE TRIGGER + MERGE table - unnecessary assert() removed as we may have more than 1 tables open e.g. for a merge table. --- mysql-test/r/merge.result | 12 ++++++++++++ mysql-test/t/merge.test | 11 +++++++++++ sql/sql_show.cc | 2 -- 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/merge.result b/mysql-test/r/merge.result index d3563e9f1c1..893ea5acf88 100644 --- a/mysql-test/r/merge.result +++ b/mysql-test/r/merge.result @@ -2207,4 +2207,16 @@ ERROR HY000: Table storage engine for 'm1' doesn't have this option DROP TABLE m1,t1,t2,t3,t4,t5,t6,t7; SELECT 1 FROM m1; ERROR 42S02: Table 'test.m1' doesn't exist +# +# Bug #46614: Assertion in show_create_trigger() +# +CREATE TABLE t1(a int); +CREATE TABLE t2(a int); +CREATE TABLE t3(a int) ENGINE = MERGE UNION(t1, t2); +CREATE TRIGGER tr1 AFTER INSERT ON t3 FOR EACH ROW CALL foo(); +SHOW CREATE TRIGGER tr1; +Trigger sql_mode SQL Original Statement character_set_client collation_connection Database Collation +tr1 CREATE DEFINER=`root`@`localhost` TRIGGER tr1 AFTER INSERT ON t3 FOR EACH ROW CALL foo() latin1 latin1_swedish_ci latin1_swedish_ci +DROP TRIGGER tr1; +DROP TABLE t1, t2, t3; End of 5.1 tests diff --git a/mysql-test/t/merge.test b/mysql-test/t/merge.test index 39c805d2b5b..015ae28c155 100644 --- a/mysql-test/t/merge.test +++ b/mysql-test/t/merge.test @@ -1622,4 +1622,15 @@ DROP TABLE m1,t1,t2,t3,t4,t5,t6,t7; --error ER_NO_SUCH_TABLE SELECT 1 FROM m1; # Should not hang! +--echo # +--echo # Bug #46614: Assertion in show_create_trigger() +--echo # +CREATE TABLE t1(a int); +CREATE TABLE t2(a int); +CREATE TABLE t3(a int) ENGINE = MERGE UNION(t1, t2); +CREATE TRIGGER tr1 AFTER INSERT ON t3 FOR EACH ROW CALL foo(); +SHOW CREATE TRIGGER tr1; +DROP TRIGGER tr1; +DROP TABLE t1, t2, t3; + --echo End of 5.1 tests diff --git a/sql/sql_show.cc b/sql/sql_show.cc index ae75609e2b6..5c2c351652b 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -7071,8 +7071,6 @@ bool show_create_trigger(THD *thd, const sp_name *trg_name) /* Perform closing actions and return error status. */ } - DBUG_ASSERT(num_tables == 1); - Table_triggers_list *triggers= lst->table->triggers; if (!triggers) From 050c36c7de50cc7258cde0826f8802928a8ef2c5 Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Thu, 13 Aug 2009 17:07:20 -0300 Subject: [PATCH 11/69] Bug#46013: rpl_extraColmaster_myisam fails on pb2 Bug#45243: crash on win in sql thread clear_tables_to_lock() -> free() Bug#45242: crash on win in mysql_close() -> free() Bug#45238: rpl_slave_skip, rpl_change_master failed (lost connection) for STOP SLAVE Bug#46030: rpl_truncate_3innodb causes server crash on windows Bug#46014: rpl_stm_reset_slave crashes the server sporadically in pb2 When killing a user session on the server, it's necessary to interrupt (notify) the thread associated with the session that the connection is being killed so that the thread is woken up if waiting for I/O. On a few platforms (Mac, Windows and HP-UX) where the SIGNAL_WITH_VIO_CLOSE flag is defined, this interruption procedure is to asynchronously close the underlying socket of the connection. In order to enable this schema, each connection serving thread registers its VIO (I/O interface) so that other threads can access it and close the connection. But only the owner thread of the VIO might delete it as to guarantee that other threads won't see freed memory (the thread unregisters the VIO before deleting it). A side note: closing the socket introduces a harmless race that might cause a thread attempt to read from a closed socket, but this is deemed acceptable. The problem is that this infrastructure was meant to only be used by server threads, but the slave I/O thread was registering the VIO of a mysql handle (a client API structure that represents a connection to another server instance) as a active connection of the thread. But under some circumstances such as network failures, the client API might destroy the VIO associated with a handle at will, yet the VIO wouldn't be properly unregistered. This could lead to accesses to freed data if a thread attempted to kill a slave I/O thread whose connection was already broken. There was a attempt to work around this by checking whether the socket was being interrupted, but this hack didn't work as intended due to the aforementioned race -- attempting to read from the socket would yield a "bad file descriptor" error. The solution is to add a hook to the client API that is called from the client code before the VIO of a handle is deleted. This hook allows the slave I/O thread to detach the active vio so it does not point to freed memory. server-tools/instance-manager/mysql_connection.cc: Add stub method required for linking. sql-common/client.c: Invoke hook. sql/client_settings.h: Export hook. sql/slave.cc: Introduce hook that clears the active VIO before it is freed by the client API. --- .../instance-manager/mysql_connection.cc | 12 +++++++++ sql-common/client.c | 3 +++ sql/client_settings.h | 8 ++++++ sql/slave.cc | 25 +++++++++++++++++++ 4 files changed, 48 insertions(+) diff --git a/server-tools/instance-manager/mysql_connection.cc b/server-tools/instance-manager/mysql_connection.cc index 1803108c39d..fc7b4ef591b 100644 --- a/server-tools/instance-manager/mysql_connection.cc +++ b/server-tools/instance-manager/mysql_connection.cc @@ -120,6 +120,18 @@ void my_net_local_init(NET *net) C_MODE_END +/* + Unused stub hook required for linking the client API. +*/ + +C_MODE_START + +void slave_io_thread_detach_vio() +{ +} + +C_MODE_END + /* Every resource, which we can fail to acquire, is allocated in init(). diff --git a/sql-common/client.c b/sql-common/client.c index 5475d5d5160..0cd7ef78478 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -911,6 +911,9 @@ void end_server(MYSQL *mysql) { init_sigpipe_variables DBUG_PRINT("info",("Net: %s", vio_description(mysql->net.vio))); +#ifdef MYSQL_SERVER + slave_io_thread_detach_vio(); +#endif set_sigpipe(mysql); vio_delete(mysql->net.vio); reset_sigpipe(mysql); diff --git a/sql/client_settings.h b/sql/client_settings.h index f0742cd8046..4f06c15a29e 100644 --- a/sql/client_settings.h +++ b/sql/client_settings.h @@ -33,3 +33,11 @@ #define mysql_server_init(a,b,c) 0 +#ifdef HAVE_REPLICATION +C_MODE_START +void slave_io_thread_detach_vio(); +C_MODE_END +#else +#define slave_io_thread_detach_vio() +#endif + diff --git a/sql/slave.cc b/sql/slave.cc index c5565902832..17855ed04e5 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -4737,6 +4737,31 @@ void end_relay_log_info(RELAY_LOG_INFO* rli) DBUG_VOID_RETURN; } + +/** + Hook to detach the active VIO before closing a connection handle. + + The client API might close the connection (and associated data) + in case it encounters a unrecoverable (network) error. This hook + is called from the client code before the VIO handle is deleted + allows the thread to detach the active vio so it does not point + to freed memory. + + Other calls to THD::clear_active_vio throughout this module are + redundant due to the hook but are left in place for illustrative + purposes. +*/ + +extern "C" void slave_io_thread_detach_vio() +{ +#ifdef SIGNAL_WITH_VIO_CLOSE + THD *thd= current_thd; + if (thd->slave_thread) + thd->clear_active_vio(); +#endif +} + + /* Try to connect until successful or slave killed From 40defb1d53e6978bdfcd4fc67f638cb56fa58ebb Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Wed, 19 Aug 2009 10:59:17 +0300 Subject: [PATCH 12/69] backport of Chad's fix for bug #39326 to 5.0-bugteam --- scripts/mysqld_safe.sh | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/scripts/mysqld_safe.sh b/scripts/mysqld_safe.sh index e6b015e7d16..71b833c80cf 100644 --- a/scripts/mysqld_safe.sh +++ b/scripts/mysqld_safe.sh @@ -113,16 +113,27 @@ parse_arguments() { MY_PWD=`pwd` # Check for the directories we would expect from a binary release install -if test -f ./share/mysql/english/errmsg.sys -a -x ./bin/mysqld +if test -n "$MY_BASEDIR_VERSION" -a -d "$MY_BASEDIR_VERSION" +then + # BASEDIR is already overridden on command line. Do not re-set. + + # Use BASEDIR to discover le. + if test -x "$MY_BASEDIR_VERSION/libexec/mysqld" + then + ledir="$MY_BASEDIR_VERSION/libexec" + else + ledir="$MY_BASEDIR_VERSION/bin" + fi +elif test -f ./share/mysql/english/errmsg.sys -a -x "$MY_PWD/bin/mysqld" then MY_BASEDIR_VERSION=$MY_PWD # Where bin, share and data are ledir=$MY_BASEDIR_VERSION/bin # Where mysqld is + ledir="$MY_PWD/bin" # Where mysqld is # Check for the directories we would expect from a source install -elif test -f ./share/mysql/english/errmsg.sys -a \ - -x ./libexec/mysqld +elif test -f ./share/mysql/english/errmsg.sys -a -x "$MY_PWD/libexec/mysqld" then MY_BASEDIR_VERSION=$MY_PWD # Where libexec, share and var are - ledir=$MY_BASEDIR_VERSION/libexec # Where mysqld is + ledir="$MY_PWD/libexec" # Where mysqld is # Since we didn't find anything, used the compiled-in defaults else MY_BASEDIR_VERSION=@prefix@ @@ -181,7 +192,10 @@ err_log= # Get first arguments from the my.cnf file, groups [mysqld] and [mysqld_safe] # and then merge with the command line arguments -if test -x ./bin/my_print_defaults +if test -x "$MY_BASEDIR_VERSION/bin/my_print_defaults" +then + print_defaults="$MY_BASEDIR_VERSION/bin/my_print_defaults" +elif test -x ./bin/my_print_defaults then print_defaults="./bin/my_print_defaults" elif test -x @bindir@/my_print_defaults From 0665536995fa1afe4ac71e13451dd8258063ff36 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Wed, 19 Aug 2009 15:14:57 +0300 Subject: [PATCH 13/69] Bug #46019: ERROR 1356 When selecting from within another view that has Group By Table access rights checking function check_grant() assumed that no view is opened when it's called. This is not true with nested views where the inner view needs materialization. In this case the view is already materialized when check_grant() is called for it. This caused check_grant() to not look for table level grants on the materialized view table. Fixed by checking if a view is already materialized and if it is check table level grants using the original table name (not the ones of the materialized temp table). --- mysql-test/r/view_grant.result | 24 +++++++++++++++++++++++ mysql-test/t/view_grant.test | 36 ++++++++++++++++++++++++++++++++++ sql/sql_acl.cc | 12 ++++++++---- sql/table.h | 23 ++++++++++++++++++++++ 4 files changed, 91 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/view_grant.result b/mysql-test/r/view_grant.result index e7a50451cec..c9b31b00f69 100644 --- a/mysql-test/r/view_grant.result +++ b/mysql-test/r/view_grant.result @@ -945,4 +945,28 @@ DROP USER foo; DROP VIEW db1.v1; DROP TABLE db1.t1; DROP DATABASE db1; +# +# Bug #46019: ERROR 1356 When selecting from within another +# view that has Group By +# +CREATE DATABASE db1; +USE db1; +CREATE TABLE t1 (a INT); +CREATE SQL SECURITY INVOKER VIEW v1 AS +SELECT a FROM t1 GROUP BY a; +CREATE SQL SECURITY INVOKER VIEW v2 AS +SELECT a FROM v1; +CREATE USER u1; +GRANT SELECT ON TABLE t1 TO u1; +GRANT SELECT, SHOW VIEW ON TABLE v1 TO u1; +GRANT SELECT, SHOW VIEW ON TABLE v2 TO u1; +SELECT a FROM v1; +a +SELECT a FROM v2; +a +DROP USER u1; +DROP VIEW v1,v2; +DROP TABLE t1; +USE test; +DROP DATABASE db1; End of 5.0 tests. diff --git a/mysql-test/t/view_grant.test b/mysql-test/t/view_grant.test index ff17cde5184..0a8456afec2 100644 --- a/mysql-test/t/view_grant.test +++ b/mysql-test/t/view_grant.test @@ -1232,6 +1232,42 @@ DROP TABLE db1.t1; DROP DATABASE db1; connection default; + +--echo # +--echo # Bug #46019: ERROR 1356 When selecting from within another +--echo # view that has Group By +--echo # + +CREATE DATABASE db1; +USE db1; + +CREATE TABLE t1 (a INT); + +CREATE SQL SECURITY INVOKER VIEW v1 AS + SELECT a FROM t1 GROUP BY a; + +CREATE SQL SECURITY INVOKER VIEW v2 AS + SELECT a FROM v1; + +CREATE USER u1; + +GRANT SELECT ON TABLE t1 TO u1; +GRANT SELECT, SHOW VIEW ON TABLE v1 TO u1; +GRANT SELECT, SHOW VIEW ON TABLE v2 TO u1; + +CONNECT (u1, localhost, u1,,db1); +CONNECTION u1; + +SELECT a FROM v1; +SELECT a FROM v2; + +CONNECTION default; +DISCONNECT u1; +DROP USER u1; +DROP VIEW v1,v2; +DROP TABLE t1; +USE test; +DROP DATABASE db1; --echo End of 5.0 tests. # Wait till we reached the initial number of concurrent sessions diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index ab4e518d5dd..a411101fcfd 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -3650,11 +3650,14 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables, continue; // ok if (!(~table->grant.privilege & want_access) || - table->derived || table->schema_table) + table->is_non_materialized_derived_table() || table->schema_table) { /* It is subquery in the FROM clause. VIEW set table->derived after - table opening, but this function always called before table opening. + table opening, but this function is mostly called before table opening. + When it's called after table opening e.g. for nested views with + materialization we shoud check the materialized table for access as + any other table. */ if (!table->referencing_view) { @@ -3667,9 +3670,10 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables, } continue; } + if (!(grant_table= table_hash_search(sctx->host, sctx->ip, - table->db, sctx->priv_user, - table->table_name,0))) + table->get_db_name(), sctx->priv_user, + table->get_table_name(), 0))) { want_access &= ~table->grant.privilege; goto err; // No grants diff --git a/sql/table.h b/sql/table.h index db996d45320..ce9364fad4d 100644 --- a/sql/table.h +++ b/sql/table.h @@ -771,6 +771,29 @@ struct TABLE_LIST void reinit_before_use(THD *thd); Item_subselect *containing_subselect(); + /** + @brief True if this TABLE_LIST represents an not yet materialized + derived table, i.e. the result of a subquery or view execution. + */ + bool is_non_materialized_derived_table() const + { + return derived && !derived_result; + } + + /** + @brief Returns the name of the database that the referenced table belongs + to. + */ + char *get_db_name() { return view != NULL ? view_db.str : db; } + + /** + @brief Returns the name of the table that this TABLE_LIST represents. + + @details The unqualified table name or view name for a table or view, + respectively. + */ + char *get_table_name() { return view != NULL ? view_name.str : table_name; } + private: bool prep_check_option(THD *thd, uint8 check_opt_type); bool prep_where(THD *thd, Item **conds, bool no_where_clause); From 152943f39f487795f3d1d6910d1ee9f736feae44 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Wed, 19 Aug 2009 17:53:43 +0300 Subject: [PATCH 14/69] Bug #46807: subselect test fails on PB-2 with a crash The check for stack overflow was independent of the size of the structure stored in the heap. Fixed by adding sizeof(PARAM) to the requested free heap size. --- sql/opt_range.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 32f9b0df4c0..d007009d62c 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -2063,7 +2063,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, KEY *key_info; PARAM param; - if (check_stack_overrun(thd, 2*STACK_MIN_SIZE, buff)) + if (check_stack_overrun(thd, 2*STACK_MIN_SIZE + sizeof(PARAM), buff)) DBUG_RETURN(0); // Fatal error flag is set /* set up parameter that is passed to all functions */ From 40b9df39955c37dfe7341f3d8a7e883c48b630a2 Mon Sep 17 00:00:00 2001 From: Alfranio Correia Date: Wed, 19 Aug 2009 16:38:18 +0100 Subject: [PATCH 15/69] BUG#45694 Deadlock in replicated statement is not retried If the SQL Thread fails to execute an event due to a temporary error (e.g. ER_LOCK_DEADLOCK) and the option "--slave_transaction_retries" is set the SQL Thread should not be aborted and the transaction should be restarted from the beginning and re-executed. Unfortunately, a wrong interpretation of the THD::is_fatal_error was preventing this behavior. In a nutshell, "this variable is set to TRUE if an execution of a compound statement cannot continue. In particular, it is used to disable access to the CONTINUE or EXIT handlers of stored routines. So even temporary errors may have this variable set. To fix the bug, we have done what follows: DBUG_ENTER("has_temporary_error"); - if (thd->is_fatal_error) - DBUG_RETURN(0); - DBUG_EXECUTE_IF("all_errors_are_temporary_errors", if (thd->main_da.is_error()) { --- sql/slave.cc | 3 --- 1 file changed, 3 deletions(-) diff --git a/sql/slave.cc b/sql/slave.cc index 3b64e23ece5..1a903d8ac12 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -2010,9 +2010,6 @@ static int has_temporary_error(THD *thd) { DBUG_ENTER("has_temporary_error"); - if (thd->is_fatal_error) - DBUG_RETURN(0); - DBUG_EXECUTE_IF("all_errors_are_temporary_errors", if (thd->main_da.is_error()) { From e66fba53a76b54d63d7ce6edc680a2e8886018d8 Mon Sep 17 00:00:00 2001 From: Martin Hansson Date: Thu, 20 Aug 2009 13:56:29 +0200 Subject: [PATCH 16/69] Bug#46616: Assertion `!table->auto_increment_field_not_null' on view manipulations The bespoke flag was not properly reset after last call to fill_record. Fixed by resetting in caller mysql_update. mysql-test/r/auto_increment.result: Bug#46616: Test result. mysql-test/t/auto_increment.test: Bug#46616: Test case. sql/sql_update.cc: Bug#46616: Fix. --- mysql-test/r/auto_increment.result | 14 ++++++++++++++ mysql-test/t/auto_increment.test | 16 ++++++++++++++++ sql/sql_update.cc | 1 + 3 files changed, 31 insertions(+) diff --git a/mysql-test/r/auto_increment.result b/mysql-test/r/auto_increment.result index 90ba00e1019..44b2e3797b2 100644 --- a/mysql-test/r/auto_increment.result +++ b/mysql-test/r/auto_increment.result @@ -440,3 +440,17 @@ a val 2 1 3 1 drop table t1; +# +# Bug#46616: Assertion `!table->auto_increment_field_not_null' on view +# manipulations +# +CREATE TABLE t1 ( a INT ); +INSERT INTO t1 VALUES (1), (1); +CREATE TABLE t2 ( a INT AUTO_INCREMENT KEY ); +CREATE TABLE IF NOT EXISTS t2 AS SELECT a FROM t1; +ERROR 23000: Duplicate entry '1' for key 1 +UPDATE t2 SET a = 2; +SELECT a FROM t2; +a +2 +DROP TABLE t1, t2; diff --git a/mysql-test/t/auto_increment.test b/mysql-test/t/auto_increment.test index 5d22bdd46a0..00849a3b131 100644 --- a/mysql-test/t/auto_increment.test +++ b/mysql-test/t/auto_increment.test @@ -292,3 +292,19 @@ update t1 set a=2 where a=1; insert into t1 (val) values (1); select * from t1; drop table t1; +--echo # +--echo # Bug#46616: Assertion `!table->auto_increment_field_not_null' on view +--echo # manipulations +--echo # +CREATE TABLE t1 ( a INT ); +INSERT INTO t1 VALUES (1), (1); + +CREATE TABLE t2 ( a INT AUTO_INCREMENT KEY ); +--error ER_DUP_ENTRY +CREATE TABLE IF NOT EXISTS t2 AS SELECT a FROM t1; + +UPDATE t2 SET a = 2; + +SELECT a FROM t2; + +DROP TABLE t1, t2; diff --git a/sql/sql_update.cc b/sql/sql_update.cc index f95f0a22a71..c18c34fc1d1 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -527,6 +527,7 @@ int mysql_update(THD *thd, table->file->unlock_row(); thd->row_count++; } + table->auto_increment_field_not_null= FALSE; /* Caching the killed status to pass as the arg to query event constuctor; The cached value can not change whereas the killed status can From fb9ba3734bf1faaecbdab204b0bcdd8954da944f Mon Sep 17 00:00:00 2001 From: Ramil Kalimullin Date: Fri, 21 Aug 2009 10:55:35 +0500 Subject: [PATCH 17/69] Fix for bug #46456 [Ver->Prg]: HANDLER OPEN + TRUNCATE + DROP (temporary) TABLE, crash Problem: if one has an open "HANDLER t1", further "TRUNCATE t1" doesn't close the handler and leaves handler table hash in an inconsistent state, that may lead to a server crash. Fix: TRUNCATE should implicitly close all open handlers. Doc. request: the fact should be described in the manual accordingly. mysql-test/r/handler_myisam.result: Fix for bug #46456 [Ver->Prg]: HANDLER OPEN + TRUNCATE + DROP (temporary) TABLE, crash - test result. mysql-test/t/handler_myisam.test: Fix for bug #46456 [Ver->Prg]: HANDLER OPEN + TRUNCATE + DROP (temporary) TABLE, crash - test case. sql/sql_delete.cc: Fix for bug #46456 [Ver->Prg]: HANDLER OPEN + TRUNCATE + DROP (temporary) TABLE, crash - remove all truncated tables from the HANDLER's hash. --- mysql-test/r/handler_myisam.result | 16 ++++++++++++++++ mysql-test/t/handler_myisam.test | 19 +++++++++++++++++++ sql/sql_delete.cc | 4 ++++ 3 files changed, 39 insertions(+) diff --git a/mysql-test/r/handler_myisam.result b/mysql-test/r/handler_myisam.result index dde6a4586bc..90a1bdfe6be 100644 --- a/mysql-test/r/handler_myisam.result +++ b/mysql-test/r/handler_myisam.result @@ -741,3 +741,19 @@ USE information_schema; HANDLER COLUMNS OPEN; ERROR HY000: Incorrect usage of HANDLER OPEN and information_schema USE test; +# +# BUG #46456: HANDLER OPEN + TRUNCATE + DROP (temporary) TABLE, crash +# +CREATE TABLE t1 AS SELECT 1 AS f1; +HANDLER t1 OPEN; +TRUNCATE t1; +HANDLER t1 READ FIRST; +ERROR 42S02: Unknown table 't1' in HANDLER +DROP TABLE t1; +CREATE TEMPORARY TABLE t1 AS SELECT 1 AS f1; +HANDLER t1 OPEN; +TRUNCATE t1; +HANDLER t1 READ FIRST; +ERROR 42S02: Unknown table 't1' in HANDLER +DROP TABLE t1; +End of 5.1 tests diff --git a/mysql-test/t/handler_myisam.test b/mysql-test/t/handler_myisam.test index 644c28de5b2..da02a90af0f 100644 --- a/mysql-test/t/handler_myisam.test +++ b/mysql-test/t/handler_myisam.test @@ -19,3 +19,22 @@ let $other_engine_type= MEMORY; let $other_handler_engine_type= MyISAM; --source include/handler.inc + +--echo # +--echo # BUG #46456: HANDLER OPEN + TRUNCATE + DROP (temporary) TABLE, crash +--echo # +CREATE TABLE t1 AS SELECT 1 AS f1; +HANDLER t1 OPEN; +TRUNCATE t1; +--error ER_UNKNOWN_TABLE +HANDLER t1 READ FIRST; +DROP TABLE t1; + +CREATE TEMPORARY TABLE t1 AS SELECT 1 AS f1; +HANDLER t1 OPEN; +TRUNCATE t1; +--error ER_UNKNOWN_TABLE +HANDLER t1 READ FIRST; +DROP TABLE t1; + +--echo End of 5.1 tests diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 0d4bf3f0b8f..d2f90fa9288 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -1066,6 +1066,10 @@ bool mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok) DBUG_ENTER("mysql_truncate"); bzero((char*) &create_info,sizeof(create_info)); + + /* Remove tables from the HANDLER's hash. */ + mysql_ha_rm_tables(thd, table_list, FALSE); + /* If it is a temporary table, close and regenerate it */ if (!dont_send_ok && (table= find_temporary_table(thd, table_list))) { From 66ce3dee92858acb6f67f8d1751144f7a468a545 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Fri, 21 Aug 2009 17:10:55 +0300 Subject: [PATCH 18/69] Revert of the fix for bug #46019. --- mysql-test/r/view_grant.result | 24 ----------------------- mysql-test/t/view_grant.test | 36 ---------------------------------- sql/sql_acl.cc | 12 ++++-------- sql/table.h | 23 ---------------------- 4 files changed, 4 insertions(+), 91 deletions(-) diff --git a/mysql-test/r/view_grant.result b/mysql-test/r/view_grant.result index c9b31b00f69..e7a50451cec 100644 --- a/mysql-test/r/view_grant.result +++ b/mysql-test/r/view_grant.result @@ -945,28 +945,4 @@ DROP USER foo; DROP VIEW db1.v1; DROP TABLE db1.t1; DROP DATABASE db1; -# -# Bug #46019: ERROR 1356 When selecting from within another -# view that has Group By -# -CREATE DATABASE db1; -USE db1; -CREATE TABLE t1 (a INT); -CREATE SQL SECURITY INVOKER VIEW v1 AS -SELECT a FROM t1 GROUP BY a; -CREATE SQL SECURITY INVOKER VIEW v2 AS -SELECT a FROM v1; -CREATE USER u1; -GRANT SELECT ON TABLE t1 TO u1; -GRANT SELECT, SHOW VIEW ON TABLE v1 TO u1; -GRANT SELECT, SHOW VIEW ON TABLE v2 TO u1; -SELECT a FROM v1; -a -SELECT a FROM v2; -a -DROP USER u1; -DROP VIEW v1,v2; -DROP TABLE t1; -USE test; -DROP DATABASE db1; End of 5.0 tests. diff --git a/mysql-test/t/view_grant.test b/mysql-test/t/view_grant.test index 0a8456afec2..ff17cde5184 100644 --- a/mysql-test/t/view_grant.test +++ b/mysql-test/t/view_grant.test @@ -1232,42 +1232,6 @@ DROP TABLE db1.t1; DROP DATABASE db1; connection default; - ---echo # ---echo # Bug #46019: ERROR 1356 When selecting from within another ---echo # view that has Group By ---echo # - -CREATE DATABASE db1; -USE db1; - -CREATE TABLE t1 (a INT); - -CREATE SQL SECURITY INVOKER VIEW v1 AS - SELECT a FROM t1 GROUP BY a; - -CREATE SQL SECURITY INVOKER VIEW v2 AS - SELECT a FROM v1; - -CREATE USER u1; - -GRANT SELECT ON TABLE t1 TO u1; -GRANT SELECT, SHOW VIEW ON TABLE v1 TO u1; -GRANT SELECT, SHOW VIEW ON TABLE v2 TO u1; - -CONNECT (u1, localhost, u1,,db1); -CONNECTION u1; - -SELECT a FROM v1; -SELECT a FROM v2; - -CONNECTION default; -DISCONNECT u1; -DROP USER u1; -DROP VIEW v1,v2; -DROP TABLE t1; -USE test; -DROP DATABASE db1; --echo End of 5.0 tests. # Wait till we reached the initial number of concurrent sessions diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index a411101fcfd..ab4e518d5dd 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -3650,14 +3650,11 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables, continue; // ok if (!(~table->grant.privilege & want_access) || - table->is_non_materialized_derived_table() || table->schema_table) + table->derived || table->schema_table) { /* It is subquery in the FROM clause. VIEW set table->derived after - table opening, but this function is mostly called before table opening. - When it's called after table opening e.g. for nested views with - materialization we shoud check the materialized table for access as - any other table. + table opening, but this function always called before table opening. */ if (!table->referencing_view) { @@ -3670,10 +3667,9 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables, } continue; } - if (!(grant_table= table_hash_search(sctx->host, sctx->ip, - table->get_db_name(), sctx->priv_user, - table->get_table_name(), 0))) + table->db, sctx->priv_user, + table->table_name,0))) { want_access &= ~table->grant.privilege; goto err; // No grants diff --git a/sql/table.h b/sql/table.h index ce9364fad4d..db996d45320 100644 --- a/sql/table.h +++ b/sql/table.h @@ -771,29 +771,6 @@ struct TABLE_LIST void reinit_before_use(THD *thd); Item_subselect *containing_subselect(); - /** - @brief True if this TABLE_LIST represents an not yet materialized - derived table, i.e. the result of a subquery or view execution. - */ - bool is_non_materialized_derived_table() const - { - return derived && !derived_result; - } - - /** - @brief Returns the name of the database that the referenced table belongs - to. - */ - char *get_db_name() { return view != NULL ? view_db.str : db; } - - /** - @brief Returns the name of the table that this TABLE_LIST represents. - - @details The unqualified table name or view name for a table or view, - respectively. - */ - char *get_table_name() { return view != NULL ? view_name.str : table_name; } - private: bool prep_check_option(THD *thd, uint8 check_opt_type); bool prep_where(THD *thd, Item **conds, bool no_where_clause); From a4e832d69d0ff3301c9ba631bbbaa091c7d18187 Mon Sep 17 00:00:00 2001 From: Mattias Jonsson Date: Fri, 21 Aug 2009 17:38:29 +0200 Subject: [PATCH 19/69] Bug#46639: 1030 (HY000): Got error 124 from storage engine on INSERT ... SELECT ... Problem was that when bulk insert is used on an empty table/partition, it disables the indexes for better performance, but in this specific case it also tries to read from that partition using an index, which is not possible since it has been disabled. Solution was to allow index reads on disabled indexes if there are no records. Also reverted the patch for bug#38005, since that was a workaround in the partitioning engine instead of a fix in myisam. mysql-test/r/partition.result: Bug#46639: 1030 (HY000): Got error 124 from storage engine on INSERT ... SELECT ... updated result file mysql-test/t/partition.test: Bug#46639: 1030 (HY000): Got error 124 from storage engine on INSERT ... SELECT ... Added testcase sql/ha_partition.cc: Bug#46639: 1030 (HY000): Got error 124 from storage engine on INSERT ... SELECT ... reverted the patch for bug#38005, since that was a workaround around this problem, not needed after fixing it in myisam. storage/myisam/mi_search.c: Bug#46639: 1030 (HY000): Got error 124 from storage engine on INSERT ... SELECT ... Return HA_ERR_END_OF_FILE instead of HA_ERR_WRONG_INDEX when there are no rows. --- mysql-test/r/partition.result | 14 ++++++++++++++ mysql-test/t/partition.test | 22 ++++++++++++++++++++++ sql/ha_partition.cc | 33 --------------------------------- storage/myisam/mi_search.c | 10 ++++++++-- 4 files changed, 44 insertions(+), 35 deletions(-) diff --git a/mysql-test/r/partition.result b/mysql-test/r/partition.result index 40c2728ce26..2d54a66fe11 100644 --- a/mysql-test/r/partition.result +++ b/mysql-test/r/partition.result @@ -1,5 +1,19 @@ drop table if exists t1, t2; CREATE TABLE t1 ( +a int NOT NULL, +b int NOT NULL); +CREATE TABLE t2 ( +a int NOT NULL, +b int NOT NULL, +INDEX(b) +) +PARTITION BY HASH(a) PARTITIONS 2; +INSERT INTO t1 VALUES (399, 22); +INSERT INTO t2 VALUES (1, 22), (1, 42); +INSERT INTO t2 SELECT 1, 399 FROM t2, t1 +WHERE t1.b = t2.b; +DROP TABLE t1, t2; +CREATE TABLE t1 ( a timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, b varchar(10), PRIMARY KEY (a) diff --git a/mysql-test/t/partition.test b/mysql-test/t/partition.test index 0363327a675..c5ed098b678 100644 --- a/mysql-test/t/partition.test +++ b/mysql-test/t/partition.test @@ -14,6 +14,28 @@ drop table if exists t1, t2; --enable_warnings +# +# Bug#46639: 1030 (HY000): Got error 124 from storage engine on +# INSERT ... SELECT ... +CREATE TABLE t1 ( + a int NOT NULL, + b int NOT NULL); + +CREATE TABLE t2 ( + a int NOT NULL, + b int NOT NULL, + INDEX(b) +) +PARTITION BY HASH(a) PARTITIONS 2; + +INSERT INTO t1 VALUES (399, 22); +INSERT INTO t2 VALUES (1, 22), (1, 42); + +INSERT INTO t2 SELECT 1, 399 FROM t2, t1 +WHERE t1.b = t2.b; + +DROP TABLE t1, t2; + # # Bug#46478: timestamp field incorrectly defaulted when partition is reorganized # diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index b345648260c..ac8c46ec4e3 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -4414,17 +4414,6 @@ int ha_partition::handle_unordered_scan_next_partition(uchar * buf) break; case partition_index_first: DBUG_PRINT("info", ("index_first on partition %d", i)); - /* MyISAM engine can fail if we call index_first() when indexes disabled */ - /* that happens if the table is empty. */ - /* Here we use file->stats.records instead of file->records() because */ - /* file->records() is supposed to return an EXACT count, and it can be */ - /* possibly slow. We don't need an exact number, an approximate one- from*/ - /* the last ::info() call - is sufficient. */ - if (file->stats.records == 0) - { - error= HA_ERR_END_OF_FILE; - break; - } error= file->index_first(buf); break; case partition_index_first_unordered: @@ -4512,32 +4501,10 @@ int ha_partition::handle_ordered_index_scan(uchar *buf, bool reverse_order) m_start_key.flag); break; case partition_index_first: - /* MyISAM engine can fail if we call index_first() when indexes disabled */ - /* that happens if the table is empty. */ - /* Here we use file->stats.records instead of file->records() because */ - /* file->records() is supposed to return an EXACT count, and it can be */ - /* possibly slow. We don't need an exact number, an approximate one- from*/ - /* the last ::info() call - is sufficient. */ - if (file->stats.records == 0) - { - error= HA_ERR_END_OF_FILE; - break; - } error= file->index_first(rec_buf_ptr); reverse_order= FALSE; break; case partition_index_last: - /* MyISAM engine can fail if we call index_last() when indexes disabled */ - /* that happens if the table is empty. */ - /* Here we use file->stats.records instead of file->records() because */ - /* file->records() is supposed to return an EXACT count, and it can be */ - /* possibly slow. We don't need an exact number, an approximate one- from*/ - /* the last ::info() call - is sufficient. */ - if (file->stats.records == 0) - { - error= HA_ERR_END_OF_FILE; - break; - } error= file->index_last(rec_buf_ptr); reverse_order= TRUE; break; diff --git a/storage/myisam/mi_search.c b/storage/myisam/mi_search.c index 1dd6c6b5f0d..766e54bde30 100644 --- a/storage/myisam/mi_search.c +++ b/storage/myisam/mi_search.c @@ -28,9 +28,15 @@ int _mi_check_index(MI_INFO *info, int inx) { if (inx == -1) /* Use last index */ inx=info->lastinx; - if (inx < 0 || ! mi_is_key_active(info->s->state.key_map, inx)) + if (inx < 0) { - my_errno=HA_ERR_WRONG_INDEX; + my_errno= HA_ERR_WRONG_INDEX; + return -1; + } + if (!mi_is_key_active(info->s->state.key_map, inx)) + { + my_errno= info->s->state.state.records ? HA_ERR_WRONG_INDEX : + HA_ERR_END_OF_FILE; return -1; } if (info->lastinx != inx) /* Index changed */ From 11dd1d6d84a6214eff61e2efd6c73369bb44adbc Mon Sep 17 00:00:00 2001 From: Anurag Shekhar Date: Mon, 24 Aug 2009 13:15:51 +0530 Subject: [PATCH 20/69] Bug #44723 Larger read_buffer_size values can cause performance decrease for INSERTs Bulk inserts (multiple row, CREATE ... SELECT, INSERT ... SELECT) into MyISAM tables were performed inefficiently. This was mainly affecting use cases where read_buffer_size was considerably large (>256K) and low number of rows was inserted (e.g. 30-100). The problem was that during I/O cache initialization (this happens before each bulk insert) allocated I/O buffer was unnecessarily initialized to '\0'. This was happening because of mess in flag values. MyISAM informs I/O cache to wait for free space (if out of disk space) by passing MY_WAIT_IF_FULL flag. Since MY_WAIT_IF_FULL and MY_ZEROFILL have the same values, memory allocator was initializing memory to '\0'. The performance gain provided with this patch may only be visible with non-debug binaries, since safemalloc always initializes allocated memory to 0xA5A5... mysys/mf_iocache.c: Remove MY_WAIT_IF_FULL from myflags before calling my_malloc to prevent conflict with MY_ZEROFILL. --- mysys/mf_iocache.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/mysys/mf_iocache.c b/mysys/mf_iocache.c index d2ace12da4d..3aab904a6e0 100644 --- a/mysys/mf_iocache.c +++ b/mysys/mf_iocache.c @@ -233,10 +233,13 @@ int init_io_cache(IO_CACHE *info, File file, uint cachesize, buffer_block = cachesize; if (type == SEQ_READ_APPEND) buffer_block *= 2; - if ((info->buffer= - (byte*) my_malloc(buffer_block, - MYF((cache_myflags & ~ MY_WME) | - (cachesize == min_cache ? MY_WME : 0)))) != 0) + /* + Unset MY_WAIT_IF_FULL bit if it is set, to prevent conflict with + MY_ZEROFILL. + */ + myf flag = MYF((cache_myflags & ~ (MY_WME | MY_WAIT_IF_FULL)) | + (cachesize == min_cache ? MY_WME : 0)); + if ((info->buffer= (byte*) my_malloc(buffer_block, flag)) != 0) { info->write_buffer=info->buffer; if (type == SEQ_READ_APPEND) From 7492d622e44d7d3fd424bd24fd53131fe06d1c22 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Mon, 24 Aug 2009 15:28:03 +0300 Subject: [PATCH 21/69] Bug #37044: Read overflow in opt_range.cc found during "make test" The code was using a special global buffer for the value of IS NULL ranges. This was not always long enough to be copied by a regular memcpy. As a result read buffer overflows may occur. Fixed by setting the null byte to 1 and setting the rest of the field disk image to NULL with a bzero (instead of relying on the buffer and memcpy()). --- sql/opt_range.cc | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/sql/opt_range.cc b/sql/opt_range.cc index d007009d62c..778fc418392 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -8308,11 +8308,21 @@ get_constant_key_infix(KEY *index_info, SEL_ARG *index_range_tree, return FALSE; uint field_length= cur_part->store_length; - if ((cur_range->maybe_null && + if (cur_range->maybe_null && cur_range->min_value[0] && cur_range->max_value[0]) - || - (memcmp(cur_range->min_value, cur_range->max_value, field_length) == 0)) - { /* cur_range specifies 'IS NULL' or an equality condition. */ + { + /* + cur_range specifies 'IS NULL'. In this case the argument points to a "null value" (is_null_string) + that may not always be long enough for a direct memcpy to a field. + */ + DBUG_ASSERT (field_length > 0); + *key_ptr= 1; + bzero(key_ptr+1,field_length-1); + key_ptr+= field_length; + *key_infix_len+= field_length; + } + else if (memcmp(cur_range->min_value, cur_range->max_value, field_length) == 0) + { /* cur_range specifies an equality condition. */ memcpy(key_ptr, cur_range->min_value, field_length); key_ptr+= field_length; *key_infix_len+= field_length; From fc3945950452a12ea7e47c685a73d5d22d338ec2 Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Mon, 24 Aug 2009 16:47:08 -0300 Subject: [PATCH 22/69] Bug#45261: Crash, stored procedure + decimal The problem was that creating a DECIMAL column from a decimal value could lead to a failed assertion as decimal values can have a higher precision than those attached to a table. The assert could be triggered by creating a table from a decimal with a large (> 30) scale. Also, there was a problem in calculating the number of digits in the integral and fractional parts if both exceeded the maximum number of digits permitted by the new decimal type. The solution is to ensure that truncation procedure is executed when deducing a DECIMAL column from a decimal value of higher precision. If the integer part is equal to or bigger than the maximum precision for the DECIMAL type (65), the integer part is truncated to fit and the fractional becomes zero. Otherwise, the fractional part is truncated to fit into the space left after the integer part is copied. This patch borrows code and ideas from Martin Hansson's patch. mysql-test/r/type_newdecimal.result: Add test case result for Bug#45261. Also, update test case to reflect that an additive operation increases the precision of the resulting type by 1. mysql-test/t/type_newdecimal.test: Add test case for Bug#45261 sql/field.cc: Added DBUG_ASSERT to ensure object's invariant is maintained. Implement method to create a field to hold a decimal value from an item. sql/field.h: Explain member variable. Add method to create a new decimal field. sql/item.cc: The precision should only be capped when storing the value on a table. Also, this makes it impossible to calculate the integer part if Item::decimals (the scale) is larger than the precision. sql/item.h: Simplify calculation of integer part. sql/item_cmpfunc.cc: Do not limit the precision. It will be capped later. sql/item_func.cc: Use new method for allocating a new decimal field. Add a specialized method for retrieving the precision of a user variable item. sql/item_func.h: Add method to return the precision of a user variable. sql/item_sum.cc: Use new method for allocating a new decimal field. sql/my_decimal.h: The integer part could be improperly calculated for a decimal with 31 digits in the fractional part. sql/sql_select.cc: Use new method which truncates the integer or decimal parts as needed. --- mysql-test/r/type_newdecimal.result | 220 +++++++++++++++++++++++++++- mysql-test/t/type_newdecimal.test | 134 +++++++++++++++++ sql/field.cc | 85 +++++++++++ sql/field.h | 9 ++ sql/item.cc | 25 ++-- sql/item.h | 3 +- sql/item_cmpfunc.cc | 6 +- sql/item_func.cc | 52 ++----- sql/item_func.h | 1 + sql/item_sum.cc | 3 +- sql/my_decimal.h | 14 +- sql/sql_select.cc | 41 +----- 12 files changed, 483 insertions(+), 110 deletions(-) diff --git a/mysql-test/r/type_newdecimal.result b/mysql-test/r/type_newdecimal.result index 748aadee4fb..c3d1e400b23 100644 --- a/mysql-test/r/type_newdecimal.result +++ b/mysql-test/r/type_newdecimal.result @@ -1495,9 +1495,9 @@ CREATE TABLE t1 (a int DEFAULT NULL, b int DEFAULT NULL); INSERT INTO t1 VALUES (3,30), (1,10), (2,10); SELECT a+CAST(1 AS decimal(65,30)) AS aa, SUM(b) FROM t1 GROUP BY aa; aa SUM(b) -2.000000000000000000000000000000 10 -3.000000000000000000000000000000 10 -4.000000000000000000000000000000 30 +2.00000000000000000000000000000 10 +3.00000000000000000000000000000 10 +4.00000000000000000000000000000 30 SELECT a+CAST(1 AS decimal(65,31)) AS aa, SUM(b) FROM t1 GROUP BY aa; ERROR 42000: Too big scale 31 specified for column '1'. Maximum is 30. DROP TABLE t1; @@ -1521,13 +1521,13 @@ f1 DROP TABLE t1; CREATE TABLE t1 SELECT 123451234512345123451234512345123451234512345.678906789067890678906789067890678906789067890 AS f1; Warnings: -Warning 1264 Out of range value for column 'f1' at row 1 +Note 1265 Data truncated for column 'f1' at row 1 DESC t1; Field Type Null Key Default Extra -f1 decimal(65,30) NO 0.000000000000000000000000000000 +f1 decimal(65,20) NO 0.00000000000000000000 SELECT f1 FROM t1; f1 -99999999999999999999999999999999999.999999999999999999999999999999 +123451234512345123451234512345123451234512345.67890678906789067891 DROP TABLE t1; select (1.20396873 * 0.89550000 * 0.68000000 * 1.08721696 * 0.99500000 * 1.01500000 * 1.01500000 * 0.99500000); @@ -1595,7 +1595,7 @@ Warnings: Note 1265 Data truncated for column 'my_col' at row 1 DESCRIBE t1; Field Type Null Key Default Extra -my_col decimal(65,30) NO 0.000000000000000000000000000000 +my_col decimal(32,30) NO 0.000000000000000000000000000000 SELECT my_col FROM t1; my_col 1.123456789123456789123456789123 @@ -1625,8 +1625,212 @@ Warnings: Note 1265 Data truncated for column 'my_col' at row 1 DESCRIBE t1; Field Type Null Key Default Extra -my_col decimal(65,30) YES NULL +my_col decimal(30,30) YES NULL SELECT my_col FROM t1; my_col 0.012345687012345687012345687012 DROP TABLE t1; +# +# Bug#45261: Crash, stored procedure + decimal +# +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 SELECT +/* 81 */ 100000000000000000000000000000000000000000000000000000000000000000000000000000001 +AS c1; +Warnings: +Warning 1264 Out of range value for column 'c1' at row 1 +DESC t1; +Field Type Null Key Default Extra +c1 decimal(65,0) NO 0 +SELECT * FROM t1; +c1 +99999999999999999999999999999999999999999999999999999999999999999 +DROP TABLE t1; +CREATE TABLE t1 SELECT +/* 81 */ 100000000000000000000000000000000000000000000000000000000000000000000000000000001. +AS c1; +Warnings: +Warning 1264 Out of range value for column 'c1' at row 1 +DESC t1; +Field Type Null Key Default Extra +c1 decimal(65,0) NO 0 +SELECT * FROM t1; +c1 +99999999999999999999999999999999999999999999999999999999999999999 +DROP TABLE t1; +CREATE TABLE t1 SELECT +/* 81 */ 100000000000000000000000000000000000000000000000000000000000000000000000000000001.1 /* 1 */ +AS c1; +Warnings: +Warning 1264 Out of range value for column 'c1' at row 1 +DESC t1; +Field Type Null Key Default Extra +c1 decimal(65,0) NO 0 +SELECT * FROM t1; +c1 +99999999999999999999999999999999999999999999999999999999999999999 +DROP TABLE t1; +CREATE TABLE t1 SELECT +/* 82 */ 1000000000000000000000000000000000000000000000000000000000000000000000000000000001 +AS c1; +Warnings: +Error 1292 Truncated incorrect DECIMAL value: '' +DESC t1; +Field Type Null Key Default Extra +c1 decimal(65,0) NO 0 +SELECT * FROM t1; +c1 +99999999999999999999999999999999999999999999999999999999999999999 +DROP TABLE t1; +CREATE TABLE t1 SELECT +/* 40 */ 1000000000000000000000000000000000000001.1000000000000000000000000000000000000001 /* 40 */ +AS c1; +DESC t1; +Field Type Null Key Default Extra +c1 decimal(65,25) NO 0.0000000000000000000000000 +SELECT * FROM t1; +c1 +1000000000000000000000000000000000000001.1000000000000000000000000 +DROP TABLE t1; +CREATE TABLE t1 SELECT +/* 1 */ 1.10000000000000000000000000000000000000000000000000000000000000000000000000000001 /* 80 */ +AS c1; +DESC t1; +Field Type Null Key Default Extra +c1 decimal(31,30) NO 0.000000000000000000000000000000 +SELECT * FROM t1; +c1 +1.100000000000000000000000000000 +DROP TABLE t1; +CREATE TABLE t1 SELECT +/* 1 */ 1.100000000000000000000000000000000000000000000000000000000000000000000000000000001 /* 81 */ +AS c1; +DESC t1; +Field Type Null Key Default Extra +c1 decimal(31,30) NO 0.000000000000000000000000000000 +SELECT * FROM t1; +c1 +1.100000000000000000000000000000 +DROP TABLE t1; +CREATE TABLE t1 SELECT +.100000000000000000000000000000000000000000000000000000000000000000000000000000001 /* 81 */ +AS c1; +Warnings: +Note 1265 Data truncated for column 'c1' at row 1 +DESC t1; +Field Type Null Key Default Extra +c1 decimal(30,30) NO 0.000000000000000000000000000000 +SELECT * FROM t1; +c1 +0.100000000000000000000000000000 +DROP TABLE t1; +CREATE TABLE t1 SELECT +/* 45 */ 123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345 /* 45 */ +AS c1; +Warnings: +Note 1265 Data truncated for column 'c1' at row 1 +DESC t1; +Field Type Null Key Default Extra +c1 decimal(65,20) NO 0.00000000000000000000 +SELECT * FROM t1; +c1 +123456789012345678901234567890123456789012345.12345678901234567890 +DROP TABLE t1; +CREATE TABLE t1 SELECT +/* 65 */ 12345678901234567890123456789012345678901234567890123456789012345.1 /* 1 */ +AS c1; +Warnings: +Note 1265 Data truncated for column 'c1' at row 1 +DESC t1; +Field Type Null Key Default Extra +c1 decimal(65,0) NO 0 +SELECT * FROM t1; +c1 +12345678901234567890123456789012345678901234567890123456789012345 +DROP TABLE t1; +CREATE TABLE t1 SELECT +/* 66 */ 123456789012345678901234567890123456789012345678901234567890123456.1 /* 1 */ +AS c1; +Warnings: +Warning 1264 Out of range value for column 'c1' at row 1 +DESC t1; +Field Type Null Key Default Extra +c1 decimal(65,0) NO 0 +SELECT * FROM t1; +c1 +99999999999999999999999999999999999999999999999999999999999999999 +DROP TABLE t1; +CREATE TABLE t1 SELECT +.123456789012345678901234567890123456789012345678901234567890123456 /* 66 */ +AS c1; +Warnings: +Note 1265 Data truncated for column 'c1' at row 1 +DESC t1; +Field Type Null Key Default Extra +c1 decimal(30,30) NO 0.000000000000000000000000000000 +SELECT * FROM t1; +c1 +0.123456789012345678901234567890 +DROP TABLE t1; +CREATE TABLE t1 AS SELECT 123.1234567890123456789012345678901 /* 31 */ AS c1; +Warnings: +Note 1265 Data truncated for column 'c1' at row 1 +DESC t1; +Field Type Null Key Default Extra +c1 decimal(33,30) NO 0.000000000000000000000000000000 +SELECT * FROM t1; +c1 +123.123456789012345678901234567890 +DROP TABLE t1; +CREATE TABLE t1 SELECT 1.1 + CAST(1 AS DECIMAL(65,30)) AS c1; +DESC t1; +Field Type Null Key Default Extra +c1 decimal(65,29) NO 0.00000000000000000000000000000 +SELECT * FROM t1; +c1 +2.10000000000000000000000000000 +DROP TABLE t1; +# +# Test that the integer and decimal parts are properly calculated. +# +CREATE TABLE t1 (a DECIMAL(30,30)); +INSERT INTO t1 VALUES (0.1),(0.2),(0.3); +CREATE TABLE t2 SELECT MIN(a + 0.0000000000000000000000000000001) AS c1 FROM t1; +Warnings: +Note 1265 Data truncated for column 'c1' at row 3 +DESC t2; +Field Type Null Key Default Extra +c1 decimal(32,30) YES NULL +DROP TABLE t1,t2; +CREATE TABLE t1 (a DECIMAL(30,30)); +INSERT INTO t1 VALUES (0.1),(0.2),(0.3); +CREATE TABLE t2 SELECT IFNULL(a + 0.0000000000000000000000000000001, NULL) AS c1 FROM t1; +Warnings: +Note 1265 Data truncated for column 'c1' at row 1 +Note 1265 Data truncated for column 'c1' at row 2 +Note 1265 Data truncated for column 'c1' at row 3 +DESC t2; +Field Type Null Key Default Extra +c1 decimal(32,30) YES NULL +DROP TABLE t1,t2; +CREATE TABLE t1 (a DECIMAL(30,30)); +INSERT INTO t1 VALUES (0.1),(0.2),(0.3); +CREATE TABLE t2 SELECT CASE a WHEN 0.1 THEN 0.0000000000000000000000000000000000000000000000000000000000000000001 END AS c1 FROM t1; +Warnings: +Note 1265 Data truncated for column 'c1' at row 1 +DESC t2; +Field Type Null Key Default Extra +c1 decimal(31,30) YES NULL +DROP TABLE t1,t2; +# +# Test that variables get maximum precision. +# +SET @decimal= 1.1; +CREATE TABLE t1 SELECT @decimal AS c1; +DESC t1; +Field Type Null Key Default Extra +c1 decimal(65,30) YES NULL +SELECT * FROM t1; +c1 +1.100000000000000000000000000000 +DROP TABLE t1; diff --git a/mysql-test/t/type_newdecimal.test b/mysql-test/t/type_newdecimal.test index cd3c3f81510..65bafaae77e 100644 --- a/mysql-test/t/type_newdecimal.test +++ b/mysql-test/t/type_newdecimal.test @@ -1286,3 +1286,137 @@ CREATE TABLE t1 SELECT 1 % .1234567891234567891234567891234567891234567891234567 DESCRIBE t1; SELECT my_col FROM t1; DROP TABLE t1; + +--echo # +--echo # Bug#45261: Crash, stored procedure + decimal +--echo # + +--disable_warnings +DROP TABLE IF EXISTS t1; +--enable_warnings + +CREATE TABLE t1 SELECT + /* 81 */ 100000000000000000000000000000000000000000000000000000000000000000000000000000001 + AS c1; +DESC t1; +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 SELECT + /* 81 */ 100000000000000000000000000000000000000000000000000000000000000000000000000000001. + AS c1; +DESC t1; +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 SELECT + /* 81 */ 100000000000000000000000000000000000000000000000000000000000000000000000000000001.1 /* 1 */ + AS c1; +DESC t1; +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 SELECT + /* 82 */ 1000000000000000000000000000000000000000000000000000000000000000000000000000000001 + AS c1; +DESC t1; +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 SELECT + /* 40 */ 1000000000000000000000000000000000000001.1000000000000000000000000000000000000001 /* 40 */ + AS c1; +DESC t1; +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 SELECT + /* 1 */ 1.10000000000000000000000000000000000000000000000000000000000000000000000000000001 /* 80 */ + AS c1; +DESC t1; +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 SELECT + /* 1 */ 1.100000000000000000000000000000000000000000000000000000000000000000000000000000001 /* 81 */ + AS c1; +DESC t1; +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 SELECT + .100000000000000000000000000000000000000000000000000000000000000000000000000000001 /* 81 */ + AS c1; +DESC t1; +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 SELECT + /* 45 */ 123456789012345678901234567890123456789012345.123456789012345678901234567890123456789012345 /* 45 */ + AS c1; +DESC t1; +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 SELECT + /* 65 */ 12345678901234567890123456789012345678901234567890123456789012345.1 /* 1 */ + AS c1; +DESC t1; +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 SELECT + /* 66 */ 123456789012345678901234567890123456789012345678901234567890123456.1 /* 1 */ + AS c1; +DESC t1; +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 SELECT + .123456789012345678901234567890123456789012345678901234567890123456 /* 66 */ + AS c1; +DESC t1; +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 AS SELECT 123.1234567890123456789012345678901 /* 31 */ AS c1; +DESC t1; +SELECT * FROM t1; +DROP TABLE t1; + +CREATE TABLE t1 SELECT 1.1 + CAST(1 AS DECIMAL(65,30)) AS c1; +DESC t1; +SELECT * FROM t1; +DROP TABLE t1; + +--echo # +--echo # Test that the integer and decimal parts are properly calculated. +--echo # + +CREATE TABLE t1 (a DECIMAL(30,30)); +INSERT INTO t1 VALUES (0.1),(0.2),(0.3); +CREATE TABLE t2 SELECT MIN(a + 0.0000000000000000000000000000001) AS c1 FROM t1; +DESC t2; +DROP TABLE t1,t2; + +CREATE TABLE t1 (a DECIMAL(30,30)); +INSERT INTO t1 VALUES (0.1),(0.2),(0.3); +CREATE TABLE t2 SELECT IFNULL(a + 0.0000000000000000000000000000001, NULL) AS c1 FROM t1; +DESC t2; +DROP TABLE t1,t2; + +CREATE TABLE t1 (a DECIMAL(30,30)); +INSERT INTO t1 VALUES (0.1),(0.2),(0.3); +CREATE TABLE t2 SELECT CASE a WHEN 0.1 THEN 0.0000000000000000000000000000000000000000000000000000000000000000001 END AS c1 FROM t1; +DESC t2; +DROP TABLE t1,t2; + +--echo # +--echo # Test that variables get maximum precision. +--echo # + +SET @decimal= 1.1; +CREATE TABLE t1 SELECT @decimal AS c1; +DESC t1; +SELECT * FROM t1; +DROP TABLE t1; diff --git a/sql/field.cc b/sql/field.cc index 3bfb54fbd15..426effa57cd 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -2485,12 +2485,97 @@ Field_new_decimal::Field_new_decimal(uint32 len_arg, { precision= my_decimal_length_to_precision(len_arg, dec_arg, unsigned_arg); set_if_smaller(precision, DECIMAL_MAX_PRECISION); + DBUG_ASSERT(precision >= dec); DBUG_ASSERT((precision <= DECIMAL_MAX_PRECISION) && (dec <= DECIMAL_MAX_SCALE)); bin_size= my_decimal_get_binary_size(precision, dec); } +/** + Create a field to hold a decimal value from an item. + + @remark The MySQL DECIMAL data type has a characteristic that needs to be + taken into account when deducing the type from a Item_decimal. + + But first, let's briefly recap what is the new MySQL DECIMAL type: + + The declaration syntax for a decimal is DECIMAL(M,D), where: + + * M is the maximum number of digits (the precision). + It has a range of 1 to 65. + * D is the number of digits to the right of the decimal separator (the scale). + It has a range of 0 to 30 and must be no larger than M. + + D and M are used to determine the storage requirements for the integer + and fractional parts of each value. The integer part is to the left of + the decimal separator and to the right is the fractional part. Hence: + + M is the number of digits for the integer and fractional part. + D is the number of digits for the fractional part. + + Consequently, M - D is the number of digits for the integer part. For + example, a DECIMAL(20,10) column has ten digits on either side of + the decimal separator. + + The characteristic that needs to be taken into account is that the + backing type for Item_decimal is a my_decimal that has a higher + precision (DECIMAL_MAX_POSSIBLE_PRECISION, see my_decimal.h) than + DECIMAL. + + Drawing a comparison between my_decimal and DECIMAL: + + * M has a range of 1 to 81. + * D has a range of 0 to 81. + + There can be a difference in range if the decimal contains a integer + part. This is because the fractional part must always be on a group + boundary, leaving at least one group for the integer part. Since each + group is 9 (DIG_PER_DEC1) digits and there are 9 (DECIMAL_BUFF_LENGTH) + groups, the fractional part is limited to 72 digits if there is at + least one digit in the integral part. + + Although the backing type for a DECIMAL is also my_decimal, every + time a my_decimal is stored in a DECIMAL field, the precision and + scale are explicitly capped at 65 (DECIMAL_MAX_PRECISION) and 30 + (DECIMAL_MAX_SCALE) digits, following my_decimal truncation procedure + (FIX_INTG_FRAC_ERROR). +*/ + +Field_new_decimal * +Field_new_decimal::new_decimal_field(const Item *item) +{ + uint32 len; + uint intg= item->decimal_int_part(), scale= item->decimals; + + DBUG_ASSERT(item->decimal_precision() >= item->decimals); + + /* + Employ a procedure along the lines of the my_decimal truncation process: + - If the integer part is equal to or bigger than the maximum precision: + Truncate integer part to fit and the fractional becomes zero. + - Otherwise: + Truncate fractional part to fit. + */ + if (intg >= DECIMAL_MAX_PRECISION) + { + intg= DECIMAL_MAX_PRECISION; + scale= 0; + } + else + { + uint room= min(DECIMAL_MAX_PRECISION - intg, DECIMAL_MAX_SCALE); + if (scale > room) + scale= room; + } + + len= my_decimal_precision_to_length(intg + scale, scale, item->unsigned_flag); + + return new Field_new_decimal(len, item->maybe_null, item->name, scale, + item->unsigned_flag); +} + + int Field_new_decimal::reset(void) { store_value(&decimal_zero); diff --git a/sql/field.h b/sql/field.h index 5136f760fc1..a9299256f88 100644 --- a/sql/field.h +++ b/sql/field.h @@ -608,6 +608,10 @@ protected: class Field_num :public Field { public: + /** + The scale of the Field's value, i.e. the number of digits to the right + of the decimal point. + */ const uint8 dec; bool zerofill,unsigned_flag; // Purify cannot handle bit fields Field_num(uchar *ptr_arg,uint32 len_arg, uchar *null_ptr_arg, @@ -766,6 +770,11 @@ public: Field_new_decimal(uint32 len_arg, bool maybe_null_arg, const char *field_name_arg, uint8 dec_arg, bool unsigned_arg); + /* + Create a field to hold a decimal value from an item. + Truncates the precision and/or scale if necessary. + */ + static Field_new_decimal *new_decimal_field(const Item *item); enum_field_types type() const { return MYSQL_TYPE_NEWDECIMAL;} enum ha_base_keytype key_type() const { return HA_KEYTYPE_BINARY; } Item_result result_type () const { return DECIMAL_RESULT; } diff --git a/sql/item.cc b/sql/item.cc index 2640b74851b..9551c5feaff 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -435,17 +435,26 @@ Item::Item(THD *thd, Item *item): } +/** + Decimal precision of the item. + + @remark The precision must not be capped as it can be used in conjunction + with Item::decimals to determine the size of the integer part when + constructing a decimal data type. + + @see Item::decimal_int_part() + @see Item::decimals +*/ + uint Item::decimal_precision() const { + uint precision= max_length; Item_result restype= result_type(); if ((restype == DECIMAL_RESULT) || (restype == INT_RESULT)) - { - uint prec= - my_decimal_length_to_precision(max_length, decimals, unsigned_flag); - return min(prec, DECIMAL_MAX_PRECISION); - } - return min(max_length, DECIMAL_MAX_PRECISION); + precision= my_decimal_length_to_precision(max_length, decimals, unsigned_flag); + + return precision; } @@ -4902,9 +4911,7 @@ Field *Item::tmp_table_field_from_field_type(TABLE *table, bool fixed_length) switch (field_type()) { case MYSQL_TYPE_DECIMAL: case MYSQL_TYPE_NEWDECIMAL: - field= new Field_new_decimal((uchar*) 0, max_length, null_ptr, 0, - Field::NONE, name, decimals, 0, - unsigned_flag); + field= Field_new_decimal::new_decimal_field(this); break; case MYSQL_TYPE_TINY: field= new Field_tiny((uchar*) 0, max_length, null_ptr, 0, Field::NONE, diff --git a/sql/item.h b/sql/item.h index 3dfcd7c2612..464085cb101 100644 --- a/sql/item.h +++ b/sql/item.h @@ -755,9 +755,10 @@ public: virtual cond_result eq_cmp_result() const { return COND_OK; } inline uint float_length(uint decimals_par) const { return decimals != NOT_FIXED_DEC ? (DBL_DIG+2+decimals_par) : DBL_DIG+8;} + /** Returns the uncapped decimal precision of this item. */ virtual uint decimal_precision() const; inline int decimal_int_part() const - { return my_decimal_int_part(decimal_precision(), decimals); } + { return decimal_precision() - decimals; } /* Returns true if this is constant (during query execution, i.e. its value will not change until next fix_fields) and its value is known. diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 1ff9ca6a419..53feb753844 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -2183,7 +2183,7 @@ uint Item_func_ifnull::decimal_precision() const int arg1_int_part= args[1]->decimal_int_part(); int max_int_part= max(arg0_int_part, arg1_int_part); int precision= max_int_part + decimals; - return min(precision, DECIMAL_MAX_PRECISION); + return precision; } @@ -2367,7 +2367,7 @@ uint Item_func_if::decimal_precision() const int arg1_prec= args[1]->decimal_int_part(); int arg2_prec= args[2]->decimal_int_part(); int precision=max(arg1_prec,arg2_prec) + decimals; - return min(precision, DECIMAL_MAX_PRECISION); + return precision; } @@ -2775,7 +2775,7 @@ uint Item_func_case::decimal_precision() const if (else_expr_num != -1) set_if_bigger(max_int_part, args[else_expr_num]->decimal_int_part()); - return min(max_int_part + decimals, DECIMAL_MAX_PRECISION); + return max_int_part + decimals; } diff --git a/sql/item_func.cc b/sql/item_func.cc index 55d4b37ddb0..6abc78371db 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -452,45 +452,8 @@ Field *Item_func::tmp_table_field(TABLE *table) return make_string_field(table); break; case DECIMAL_RESULT: - { - uint8 dec= decimals; - uint8 intg= decimal_precision() - dec; - uint32 len= max_length; - - /* - Trying to put too many digits overall in a DECIMAL(prec,dec) - will always throw a warning. We must limit dec to - DECIMAL_MAX_SCALE however to prevent an assert() later. - */ - - if (dec > 0) - { - int overflow; - - dec= min(dec, DECIMAL_MAX_SCALE); - - /* - If the value still overflows the field with the corrected dec, - we'll throw out decimals rather than integers. This is still - bad and of course throws a truncation warning. - */ - - const int required_length= - my_decimal_precision_to_length(intg + dec, dec, - unsigned_flag); - - overflow= required_length - len; - - if (overflow > 0) - dec= max(0, dec - overflow); // too long, discard fract - else - /* Corrected value fits. */ - len= required_length; - } - - field= new Field_new_decimal(len, maybe_null, name, dec, unsigned_flag); + field= Field_new_decimal::new_decimal_field(this); break; - } case ROW_RESULT: default: // This case should never be chosen @@ -4781,6 +4744,19 @@ void Item_func_get_user_var::fix_length_and_dec() } +uint Item_func_get_user_var::decimal_precision() const +{ + uint precision= max_length; + Item_result restype= result_type(); + + /* Default to maximum as the precision is unknown a priori. */ + if ((restype == DECIMAL_RESULT) || (restype == INT_RESULT)) + precision= DECIMAL_MAX_PRECISION; + + return precision; +} + + bool Item_func_get_user_var::const_item() const { return (!var_entry || current_thd->query_id != var_entry->update_query_id); diff --git a/sql/item_func.h b/sql/item_func.h index 025ac12fe07..fdbbff89e60 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -1393,6 +1393,7 @@ public: table_map used_tables() const { return const_item() ? 0 : RAND_TABLE_BIT; } bool eq(const Item *item, bool binary_cmp) const; + uint decimal_precision() const; private: bool set_value(THD *thd, sp_rcontext *ctx, Item **it); diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 38251294053..08a48c6ce2f 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -517,8 +517,7 @@ Field *Item_sum::create_tmp_field(bool group, TABLE *table, name, table->s, collation.collation); break; case DECIMAL_RESULT: - field= new Field_new_decimal(max_length, maybe_null, name, - decimals, unsigned_flag); + field= Field_new_decimal::new_decimal_field(this); break; case ROW_RESULT: default: diff --git a/sql/my_decimal.h b/sql/my_decimal.h index 21669e82c44..b1df1395dcd 100644 --- a/sql/my_decimal.h +++ b/sql/my_decimal.h @@ -48,10 +48,12 @@ C_MODE_END digits * number of decimal digits in one our big digit - number of decimal digits in one our big digit decreased by 1 (because we always put decimal point on the border of our big digits)) + + This value is 65 due to historical reasons partly due to it being used + as the maximum allowed precision and not the actual maximum precision. */ #define DECIMAL_MAX_PRECISION (DECIMAL_MAX_POSSIBLE_PRECISION - 8*2) #define DECIMAL_MAX_SCALE 30 -#define DECIMAL_NOT_SPECIFIED 31 /** maximum length of string representation (number of maximum decimal @@ -75,12 +77,6 @@ inline uint my_decimal_size(uint precision, uint scale) } -inline int my_decimal_int_part(uint precision, uint decimals) -{ - return precision - ((decimals == DECIMAL_NOT_SPECIFIED) ? 0 : decimals); -} - - /** my_decimal class limits 'decimal_t' type to what we need in MySQL. @@ -184,7 +180,7 @@ inline uint my_decimal_length_to_precision(uint length, uint scale, } inline uint32 my_decimal_precision_to_length_no_truncation(uint precision, - uint8 scale, + uint scale, bool unsigned_flag) { /* @@ -196,7 +192,7 @@ inline uint32 my_decimal_precision_to_length_no_truncation(uint precision, (unsigned_flag || !precision ? 0 : 1)); } -inline uint32 my_decimal_precision_to_length(uint precision, uint8 scale, +inline uint32 my_decimal_precision_to_length(uint precision, uint scale, bool unsigned_flag) { /* diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 7f6c5e834a3..5cb0de1ba5c 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -9377,47 +9377,8 @@ static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table, new_field->set_derivation(item->collation.derivation); break; case DECIMAL_RESULT: - { - uint8 dec= item->decimals; - uint8 intg= ((Item_decimal *) item)->decimal_precision() - dec; - uint32 len= item->max_length; - - /* - Trying to put too many digits overall in a DECIMAL(prec,dec) - will always throw a warning. We must limit dec to - DECIMAL_MAX_SCALE however to prevent an assert() later. - */ - - if (dec > 0) - { - signed int overflow; - - dec= min(dec, DECIMAL_MAX_SCALE); - - /* - If the value still overflows the field with the corrected dec, - we'll throw out decimals rather than integers. This is still - bad and of course throws a truncation warning. - +1: for decimal point - */ - - const int required_length= - my_decimal_precision_to_length(intg + dec, dec, - item->unsigned_flag); - - overflow= required_length - len; - - if (overflow > 0) - dec= max(0, dec - overflow); // too long, discard fract - else - /* Corrected value fits. */ - len= required_length; - } - - new_field= new Field_new_decimal(len, maybe_null, item->name, - dec, item->unsigned_flag); + new_field= Field_new_decimal::new_decimal_field(item); break; - } case ROW_RESULT: default: // This case should never be choosen From 4655118bea2bcb14a06f01046fb06052fd37214c Mon Sep 17 00:00:00 2001 From: Mattias Jonsson Date: Wed, 26 Aug 2009 12:51:23 +0200 Subject: [PATCH 23/69] Bug#46362: Endpoint should be set to false for TO_DAYS(DATE) There were a problem since pruning uses the field for comparison (while evaluate_join_record uses longlong), resulting in pruning failures when comparing DATE to DATETIME. Fix was to always comparing DATE vs DATETIME as DATETIME, by adding ' 00:00:00' to the DATE string. And adding optimization for comparing with 23:59:59, so that DATETIME_col > '2001-02-03 23:59:59' -> TO_DAYS(DATETIME_col) > TO_DAYS('2001-02-03 23:59:59') instead of '>='. mysql-test/r/partition_pruning.result: Bug#46362: Endpoint should be set to false for TO_DAYS(DATE) Updated result-file mysql-test/t/partition_pruning.test: Bug#46362: Endpoint should be set to false for TO_DAYS(DATE) Added testcases. sql-common/my_time.c: Bug#46362: Endpoint should be set to false for TO_DAYS(DATE) removed duplicate assignment. sql/item.cc: Bug#46362: Endpoint should be set to false for TO_DAYS(DATE) Changed field_is_equal_to_item into field_cmp_to_item, to better handling DATE vs DATETIME comparision. sql/item.h: Bug#46362: Endpoint should be set to false for TO_DAYS(DATE) Updated comment sql/item_timefunc.cc: Bug#46362: Endpoint should be set to false for TO_DAYS(DATE) Added optimization (pruning) of DATETIME where time-part is 23:59:59 sql/opt_range.cc: Bug#46362: Endpoint should be set to false for TO_DAYS(DATE) Using the new stored_field_cmp_to_item for better pruning. --- mysql-test/r/partition_pruning.result | 621 ++++++++++++++++++++++++++ mysql-test/t/partition_pruning.test | 308 +++++++++++++ sql-common/my_time.c | 4 +- sql/item.cc | 50 ++- sql/item.h | 6 +- sql/item_timefunc.cc | 10 +- sql/opt_range.cc | 15 +- 7 files changed, 989 insertions(+), 25 deletions(-) diff --git a/mysql-test/r/partition_pruning.result b/mysql-test/r/partition_pruning.result index 26ddc92e97b..abaa37715bf 100644 --- a/mysql-test/r/partition_pruning.result +++ b/mysql-test/r/partition_pruning.result @@ -1,4 +1,625 @@ drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +# Test with DATETIME column NOT NULL +CREATE TABLE t1 ( +a int(10) unsigned NOT NULL, +b DATETIME NOT NULL, +PRIMARY KEY (a, b) +) PARTITION BY RANGE (TO_DAYS(b)) +(PARTITION p20090401 VALUES LESS THAN (TO_DAYS('2009-04-02')), +PARTITION p20090402 VALUES LESS THAN (TO_DAYS('2009-04-03')), +PARTITION p20090403 VALUES LESS THAN (TO_DAYS('2009-04-04')), +PARTITION p20090404 VALUES LESS THAN (TO_DAYS('2009-04-05')), +PARTITION p20090405 VALUES LESS THAN MAXVALUE); +INSERT INTO t1 VALUES (1, '2009-01-01'), (1, '2009-04-01'), (2, '2009-04-01'), +(1, '2009-04-02'), (2, '2009-04-02'), (1, '2009-04-02 23:59:59'), +(1, '2009-04-03'), (2, '2009-04-03'), (1, '2009-04-04'), (2, '2009-04-04'), +(1, '2009-04-05'), (1, '2009-04-06'), (1, '2009-04-07'); +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < CAST('2009-04-03' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402 index NULL PRIMARY 12 NULL 6 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= CAST('2009-04-03' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402,p20090403 index NULL PRIMARY 12 NULL 8 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = CAST('2009-04-03' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403 index NULL PRIMARY 12 NULL 8 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= CAST('2009-04-03' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403,p20090404,p20090405 index NULL PRIMARY 12 NULL 13 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > CAST('2009-04-03' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403,p20090404,p20090405 index NULL PRIMARY 12 NULL 13 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE b < CAST('2009-04-02 23:59:59' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402 index NULL PRIMARY 12 NULL 13 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE b <= CAST('2009-04-02 23:59:59' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402 index NULL PRIMARY 12 NULL 13 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE b = CAST('2009-04-02 23:59:59' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090402 index NULL PRIMARY 12 NULL 13 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE b >= CAST('2009-04-02 23:59:59' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090402,p20090403,p20090404,p20090405 index NULL PRIMARY 12 NULL 13 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE b > CAST('2009-04-02 23:59:59' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403,p20090404,p20090405 index NULL PRIMARY 12 NULL 13 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < CAST('2009-04-03' AS DATE); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402 index NULL PRIMARY 12 NULL 13 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= CAST('2009-04-03' AS DATE); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402,p20090403 index NULL PRIMARY 12 NULL 13 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = CAST('2009-04-03' AS DATE); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403 index NULL PRIMARY 12 NULL 13 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= CAST('2009-04-03' AS DATE); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403,p20090404,p20090405 index NULL PRIMARY 12 NULL 13 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > CAST('2009-04-03' AS DATE); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403,p20090404,p20090405 index NULL PRIMARY 12 NULL 13 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < '2009-04-03 00:00:00'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402 index NULL PRIMARY 12 NULL 13 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= '2009-04-03 00:00:00'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402,p20090403 index NULL PRIMARY 12 NULL 13 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = '2009-04-03 00:00:00'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403 index NULL PRIMARY 12 NULL 13 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= '2009-04-03 00:00:00'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403,p20090404,p20090405 index NULL PRIMARY 12 NULL 13 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > '2009-04-03 00:00:00'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403,p20090404,p20090405 index NULL PRIMARY 12 NULL 13 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < '2009-04-02 23:59:59'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402 index NULL PRIMARY 12 NULL 13 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= '2009-04-02 23:59:59'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402 index NULL PRIMARY 12 NULL 13 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = '2009-04-02 23:59:59'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090402 index NULL PRIMARY 12 NULL 13 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= '2009-04-02 23:59:59'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090402,p20090403,p20090404,p20090405 index NULL PRIMARY 12 NULL 13 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > '2009-04-02 23:59:59'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403,p20090404,p20090405 index NULL PRIMARY 12 NULL 13 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < '2009-04-03'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402 index NULL PRIMARY 12 NULL 13 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= '2009-04-03'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402,p20090403 index NULL PRIMARY 12 NULL 13 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = '2009-04-03'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403 index NULL PRIMARY 12 NULL 13 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= '2009-04-03'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403,p20090404,p20090405 index NULL PRIMARY 12 NULL 13 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > '2009-04-03'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403,p20090404,p20090405 index NULL PRIMARY 12 NULL 13 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE b < CAST('2009-04-03 00:00:01' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402,p20090403 index NULL PRIMARY 12 NULL 13 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE b <= CAST('2009-04-03 00:00:01' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402,p20090403 index NULL PRIMARY 12 NULL 13 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE b = CAST('2009-04-03 00:00:01' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403 index NULL PRIMARY 12 NULL 13 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE b >= CAST('2009-04-03 00:00:01' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403,p20090404,p20090405 index NULL PRIMARY 12 NULL 13 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE b > CAST('2009-04-03 00:00:01' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403,p20090404,p20090405 index NULL PRIMARY 12 NULL 13 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE b < CAST('2009-04-02 23:59:58' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402 index NULL PRIMARY 12 NULL 13 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE b <= CAST('2009-04-02 23:59:58' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402 index NULL PRIMARY 12 NULL 13 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE b = CAST('2009-04-02 23:59:58' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090402 index NULL PRIMARY 12 NULL 13 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE b >= CAST('2009-04-02 23:59:58' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090402,p20090403,p20090404,p20090405 index NULL PRIMARY 12 NULL 13 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE b > CAST('2009-04-02 23:59:58' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090402,p20090403,p20090404,p20090405 index NULL PRIMARY 12 NULL 13 Using where; Using index +DROP TABLE t1; +# Test with DATE column NOT NULL +CREATE TABLE t1 ( +a int(10) unsigned NOT NULL, +b DATE NOT NULL, +PRIMARY KEY (a, b) +) PARTITION BY RANGE (TO_DAYS(b)) +(PARTITION p20090401 VALUES LESS THAN (TO_DAYS('2009-04-02')), +PARTITION p20090402 VALUES LESS THAN (TO_DAYS('2009-04-03')), +PARTITION p20090403 VALUES LESS THAN (TO_DAYS('2009-04-04')), +PARTITION p20090404 VALUES LESS THAN (TO_DAYS('2009-04-05')), +PARTITION p20090405 VALUES LESS THAN MAXVALUE); +INSERT INTO t1 VALUES (1, '2009-01-01'), (1, '2009-04-01'), (2, '2009-04-01'), +(1, '2009-04-02'), (2, '2009-04-02'), (1, '2009-04-03'), (2, '2009-04-03'), +(1, '2009-04-04'), (2, '2009-04-04'), (1, '2009-04-05'), (1, '2009-04-06'), +(1, '2009-04-07'); +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < CAST('2009-04-03' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402 index NULL PRIMARY 7 NULL 5 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= CAST('2009-04-03' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402,p20090403 index NULL PRIMARY 7 NULL 7 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = CAST('2009-04-03' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403 index NULL PRIMARY 7 NULL 7 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= CAST('2009-04-03' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403,p20090404,p20090405 index NULL PRIMARY 7 NULL 12 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > CAST('2009-04-03' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090404,p20090405 index NULL PRIMARY 7 NULL 12 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE b < CAST('2009-04-02 23:59:59' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402 index NULL PRIMARY 7 NULL 12 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE b <= CAST('2009-04-02 23:59:59' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402 index NULL PRIMARY 7 NULL 12 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE b = CAST('2009-04-02 23:59:59' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE b >= CAST('2009-04-02 23:59:59' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403,p20090404,p20090405 index NULL PRIMARY 7 NULL 12 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE b > CAST('2009-04-02 23:59:59' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403,p20090404,p20090405 index NULL PRIMARY 7 NULL 12 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < CAST('2009-04-03' AS DATE); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402 index NULL PRIMARY 7 NULL 12 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= CAST('2009-04-03' AS DATE); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402,p20090403 index NULL PRIMARY 7 NULL 12 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = CAST('2009-04-03' AS DATE); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403 index NULL PRIMARY 7 NULL 12 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= CAST('2009-04-03' AS DATE); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403,p20090404,p20090405 index NULL PRIMARY 7 NULL 12 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > CAST('2009-04-03' AS DATE); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090404,p20090405 index NULL PRIMARY 7 NULL 12 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < '2009-04-03 00:00:00'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402 index NULL PRIMARY 7 NULL 12 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= '2009-04-03 00:00:00'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402,p20090403 index NULL PRIMARY 7 NULL 12 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = '2009-04-03 00:00:00'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403 index NULL PRIMARY 7 NULL 12 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= '2009-04-03 00:00:00'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403,p20090404,p20090405 index NULL PRIMARY 7 NULL 12 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > '2009-04-03 00:00:00'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090404,p20090405 index NULL PRIMARY 7 NULL 12 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < '2009-04-02 23:59:59'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402 index NULL PRIMARY 7 NULL 12 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= '2009-04-02 23:59:59'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402 index NULL PRIMARY 7 NULL 12 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = '2009-04-02 23:59:59'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= '2009-04-02 23:59:59'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403,p20090404,p20090405 index NULL PRIMARY 7 NULL 12 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > '2009-04-02 23:59:59'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403,p20090404,p20090405 index NULL PRIMARY 7 NULL 12 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < '2009-04-03'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402 index NULL PRIMARY 7 NULL 12 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= '2009-04-03'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402,p20090403 index NULL PRIMARY 7 NULL 12 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = '2009-04-03'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403 index NULL PRIMARY 7 NULL 12 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= '2009-04-03'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403,p20090404,p20090405 index NULL PRIMARY 7 NULL 12 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > '2009-04-03'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090404,p20090405 index NULL PRIMARY 7 NULL 12 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE b < CAST('2009-04-03 00:00:01' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402,p20090403 index NULL PRIMARY 7 NULL 12 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE b <= CAST('2009-04-03 00:00:01' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402,p20090403 index NULL PRIMARY 7 NULL 12 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE b = CAST('2009-04-03 00:00:01' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE b >= CAST('2009-04-03 00:00:01' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090404,p20090405 index NULL PRIMARY 7 NULL 12 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE b > CAST('2009-04-03 00:00:01' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090404,p20090405 index NULL PRIMARY 7 NULL 12 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE b < CAST('2009-04-02 23:59:58' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402 index NULL PRIMARY 7 NULL 12 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE b <= CAST('2009-04-02 23:59:58' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402 index NULL PRIMARY 7 NULL 12 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE b = CAST('2009-04-02 23:59:58' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE b >= CAST('2009-04-02 23:59:58' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403,p20090404,p20090405 index NULL PRIMARY 7 NULL 12 Using where; Using index +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE b > CAST('2009-04-02 23:59:58' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403,p20090404,p20090405 index NULL PRIMARY 7 NULL 12 Using where; Using index +DROP TABLE t1; +# Test with DATETIME column NULL +CREATE TABLE t1 ( +a int(10) unsigned NOT NULL, +b DATETIME NULL +) PARTITION BY RANGE (TO_DAYS(b)) +(PARTITION p20090401 VALUES LESS THAN (TO_DAYS('2009-04-02')), +PARTITION p20090402 VALUES LESS THAN (TO_DAYS('2009-04-03')), +PARTITION p20090403 VALUES LESS THAN (TO_DAYS('2009-04-04')), +PARTITION p20090404 VALUES LESS THAN (TO_DAYS('2009-04-05')), +PARTITION p20090405 VALUES LESS THAN MAXVALUE); +INSERT INTO t1 VALUES (1, '2009-01-01'), (1, '2009-04-01'), (2, '2009-04-01'), +(1, '2009-04-02'), (2, '2009-04-02'), (1, '2009-04-02 23:59:59'), +(1, '2009-04-03'), (2, '2009-04-03'), (1, '2009-04-04'), (2, '2009-04-04'), +(1, '2009-04-05'), (1, '2009-04-06'), (1, '2009-04-07'); +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < CAST('2009-04-03' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402 ALL NULL NULL NULL NULL 6 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= CAST('2009-04-03' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402,p20090403 ALL NULL NULL NULL NULL 8 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = CAST('2009-04-03' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403 ALL NULL NULL NULL NULL 8 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= CAST('2009-04-03' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 13 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > CAST('2009-04-03' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 13 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE b < CAST('2009-04-02 23:59:59' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402 ALL NULL NULL NULL NULL 13 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE b <= CAST('2009-04-02 23:59:59' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402 ALL NULL NULL NULL NULL 13 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE b = CAST('2009-04-02 23:59:59' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090402 ALL NULL NULL NULL NULL 13 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE b >= CAST('2009-04-02 23:59:59' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090402,p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 13 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE b > CAST('2009-04-02 23:59:59' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 13 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < CAST('2009-04-03' AS DATE); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402 ALL NULL NULL NULL NULL 13 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= CAST('2009-04-03' AS DATE); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402,p20090403 ALL NULL NULL NULL NULL 13 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = CAST('2009-04-03' AS DATE); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403 ALL NULL NULL NULL NULL 13 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= CAST('2009-04-03' AS DATE); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 13 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > CAST('2009-04-03' AS DATE); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 13 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < '2009-04-03 00:00:00'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402 ALL NULL NULL NULL NULL 13 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= '2009-04-03 00:00:00'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402,p20090403 ALL NULL NULL NULL NULL 13 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = '2009-04-03 00:00:00'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403 ALL NULL NULL NULL NULL 13 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= '2009-04-03 00:00:00'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 13 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > '2009-04-03 00:00:00'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 13 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < '2009-04-02 23:59:59'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402 ALL NULL NULL NULL NULL 13 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= '2009-04-02 23:59:59'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402 ALL NULL NULL NULL NULL 13 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = '2009-04-02 23:59:59'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090402 ALL NULL NULL NULL NULL 13 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= '2009-04-02 23:59:59'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090402,p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 13 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > '2009-04-02 23:59:59'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 13 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < '2009-04-03'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402 ALL NULL NULL NULL NULL 13 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= '2009-04-03'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402,p20090403 ALL NULL NULL NULL NULL 13 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = '2009-04-03'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403 ALL NULL NULL NULL NULL 13 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= '2009-04-03'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 13 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > '2009-04-03'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 13 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE b < CAST('2009-04-03 00:00:01' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402,p20090403 ALL NULL NULL NULL NULL 13 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE b <= CAST('2009-04-03 00:00:01' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402,p20090403 ALL NULL NULL NULL NULL 13 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE b = CAST('2009-04-03 00:00:01' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403 ALL NULL NULL NULL NULL 13 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE b >= CAST('2009-04-03 00:00:01' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 13 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE b > CAST('2009-04-03 00:00:01' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 13 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE b < CAST('2009-04-02 23:59:58' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402 ALL NULL NULL NULL NULL 13 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE b <= CAST('2009-04-02 23:59:58' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402 ALL NULL NULL NULL NULL 13 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE b = CAST('2009-04-02 23:59:58' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090402 ALL NULL NULL NULL NULL 13 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE b >= CAST('2009-04-02 23:59:58' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090402,p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 13 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE b > CAST('2009-04-02 23:59:58' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090402,p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 13 Using where +DROP TABLE t1; +# Test with DATE column NULL +CREATE TABLE t1 ( +a int(10) unsigned NOT NULL, +b DATE NULL +) PARTITION BY RANGE (TO_DAYS(b)) +(PARTITION p20090401 VALUES LESS THAN (TO_DAYS('2009-04-02')), +PARTITION p20090402 VALUES LESS THAN (TO_DAYS('2009-04-03')), +PARTITION p20090403 VALUES LESS THAN (TO_DAYS('2009-04-04')), +PARTITION p20090404 VALUES LESS THAN (TO_DAYS('2009-04-05')), +PARTITION p20090405 VALUES LESS THAN MAXVALUE); +INSERT INTO t1 VALUES (1, '2009-01-01'), (1, '2009-04-01'), (2, '2009-04-01'), +(1, '2009-04-02'), (2, '2009-04-02'), (1, '2009-04-03'), (2, '2009-04-03'), +(1, '2009-04-04'), (2, '2009-04-04'), (1, '2009-04-05'), (1, '2009-04-06'), +(1, '2009-04-07'); +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < CAST('2009-04-03' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402 ALL NULL NULL NULL NULL 5 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= CAST('2009-04-03' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402,p20090403 ALL NULL NULL NULL NULL 7 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = CAST('2009-04-03' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403 ALL NULL NULL NULL NULL 7 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= CAST('2009-04-03' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 12 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > CAST('2009-04-03' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090404,p20090405 ALL NULL NULL NULL NULL 12 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE b < CAST('2009-04-02 23:59:59' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402 ALL NULL NULL NULL NULL 12 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE b <= CAST('2009-04-02 23:59:59' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402 ALL NULL NULL NULL NULL 12 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE b = CAST('2009-04-02 23:59:59' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE b >= CAST('2009-04-02 23:59:59' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 12 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE b > CAST('2009-04-02 23:59:59' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 12 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < CAST('2009-04-03' AS DATE); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402 ALL NULL NULL NULL NULL 12 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= CAST('2009-04-03' AS DATE); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402,p20090403 ALL NULL NULL NULL NULL 12 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = CAST('2009-04-03' AS DATE); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403 ALL NULL NULL NULL NULL 12 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= CAST('2009-04-03' AS DATE); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 12 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > CAST('2009-04-03' AS DATE); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090404,p20090405 ALL NULL NULL NULL NULL 12 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < '2009-04-03 00:00:00'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402 ALL NULL NULL NULL NULL 12 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= '2009-04-03 00:00:00'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402,p20090403 ALL NULL NULL NULL NULL 12 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = '2009-04-03 00:00:00'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403 ALL NULL NULL NULL NULL 12 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= '2009-04-03 00:00:00'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 12 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > '2009-04-03 00:00:00'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090404,p20090405 ALL NULL NULL NULL NULL 12 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < '2009-04-02 23:59:59'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402 ALL NULL NULL NULL NULL 12 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= '2009-04-02 23:59:59'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402 ALL NULL NULL NULL NULL 12 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = '2009-04-02 23:59:59'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= '2009-04-02 23:59:59'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 12 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > '2009-04-02 23:59:59'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 12 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < '2009-04-03'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402 ALL NULL NULL NULL NULL 12 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= '2009-04-03'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402,p20090403 ALL NULL NULL NULL NULL 12 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = '2009-04-03'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403 ALL NULL NULL NULL NULL 12 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= '2009-04-03'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 12 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > '2009-04-03'; +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090404,p20090405 ALL NULL NULL NULL NULL 12 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE b < CAST('2009-04-03 00:00:01' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402,p20090403 ALL NULL NULL NULL NULL 12 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE b <= CAST('2009-04-03 00:00:01' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402,p20090403 ALL NULL NULL NULL NULL 12 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE b = CAST('2009-04-03 00:00:01' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE b >= CAST('2009-04-03 00:00:01' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090404,p20090405 ALL NULL NULL NULL NULL 12 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE b > CAST('2009-04-03 00:00:01' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090404,p20090405 ALL NULL NULL NULL NULL 12 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE b < CAST('2009-04-02 23:59:58' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402 ALL NULL NULL NULL NULL 12 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE b <= CAST('2009-04-02 23:59:58' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090401,p20090402 ALL NULL NULL NULL NULL 12 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE b = CAST('2009-04-02 23:59:58' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE b >= CAST('2009-04-02 23:59:58' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 12 Using where +EXPLAIN PARTITIONS SELECT * FROM t1 +WHERE b > CAST('2009-04-02 23:59:58' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE t1 p20090403,p20090404,p20090405 ALL NULL NULL NULL NULL 12 Using where +DROP TABLE t1; +# For better code coverage of the patch +CREATE TABLE t1 ( +a int(10) unsigned NOT NULL, +b DATE +) PARTITION BY RANGE ( TO_DAYS(b) ) +(PARTITION p20090401 VALUES LESS THAN (TO_DAYS('2009-04-02')), +PARTITION p20090402 VALUES LESS THAN (TO_DAYS('2009-04-03')), +PARTITION p20090403 VALUES LESS THAN (TO_DAYS('2009-04-04')), +PARTITION p20090404 VALUES LESS THAN (TO_DAYS('2009-04-05')), +PARTITION p20090405 VALUES LESS THAN MAXVALUE); +INSERT INTO t1 VALUES (1, '2009-01-01'), (2, NULL); +# test with an invalid date, which lead to item->null_value is set. +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < CAST('2009-04-99' AS DATETIME); +id select_type table partitions type possible_keys key key_len ref rows Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +Warnings: +Warning 1292 Incorrect datetime value: '2009-04-99' +Warning 1292 Incorrect datetime value: '2009-04-99' +DROP TABLE t1; CREATE TABLE t1 (a INT NOT NULL AUTO_INCREMENT, b DATETIME, diff --git a/mysql-test/t/partition_pruning.test b/mysql-test/t/partition_pruning.test index ad102062ef8..ef28820852e 100644 --- a/mysql-test/t/partition_pruning.test +++ b/mysql-test/t/partition_pruning.test @@ -8,6 +8,314 @@ drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; --enable_warnings +# +# Bug#46362: Endpoint should be set to false for TO_DAYS(DATE) +# +# There is a problem when comparing DATE with DATETIME. +# In pruning it is converted into the field type +# and in row evaluation it is converted to longlong +# (like a DATETIME). +--echo # Test with DATETIME column NOT NULL +CREATE TABLE t1 ( + a int(10) unsigned NOT NULL, + b DATETIME NOT NULL, + PRIMARY KEY (a, b) +) PARTITION BY RANGE (TO_DAYS(b)) +(PARTITION p20090401 VALUES LESS THAN (TO_DAYS('2009-04-02')), + PARTITION p20090402 VALUES LESS THAN (TO_DAYS('2009-04-03')), + PARTITION p20090403 VALUES LESS THAN (TO_DAYS('2009-04-04')), + PARTITION p20090404 VALUES LESS THAN (TO_DAYS('2009-04-05')), + PARTITION p20090405 VALUES LESS THAN MAXVALUE); +INSERT INTO t1 VALUES (1, '2009-01-01'), (1, '2009-04-01'), (2, '2009-04-01'), + (1, '2009-04-02'), (2, '2009-04-02'), (1, '2009-04-02 23:59:59'), + (1, '2009-04-03'), (2, '2009-04-03'), (1, '2009-04-04'), (2, '2009-04-04'), + (1, '2009-04-05'), (1, '2009-04-06'), (1, '2009-04-07'); +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < CAST('2009-04-03' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= CAST('2009-04-03' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = CAST('2009-04-03' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= CAST('2009-04-03' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > CAST('2009-04-03' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 + WHERE b < CAST('2009-04-02 23:59:59' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 + WHERE b <= CAST('2009-04-02 23:59:59' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 + WHERE b = CAST('2009-04-02 23:59:59' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 + WHERE b >= CAST('2009-04-02 23:59:59' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 + WHERE b > CAST('2009-04-02 23:59:59' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < CAST('2009-04-03' AS DATE); +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= CAST('2009-04-03' AS DATE); +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = CAST('2009-04-03' AS DATE); +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= CAST('2009-04-03' AS DATE); +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > CAST('2009-04-03' AS DATE); +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < '2009-04-03 00:00:00'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= '2009-04-03 00:00:00'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = '2009-04-03 00:00:00'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= '2009-04-03 00:00:00'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > '2009-04-03 00:00:00'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < '2009-04-02 23:59:59'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= '2009-04-02 23:59:59'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = '2009-04-02 23:59:59'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= '2009-04-02 23:59:59'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > '2009-04-02 23:59:59'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < '2009-04-03'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= '2009-04-03'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = '2009-04-03'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= '2009-04-03'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > '2009-04-03'; +EXPLAIN PARTITIONS SELECT * FROM t1 + WHERE b < CAST('2009-04-03 00:00:01' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 + WHERE b <= CAST('2009-04-03 00:00:01' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 + WHERE b = CAST('2009-04-03 00:00:01' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 + WHERE b >= CAST('2009-04-03 00:00:01' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 + WHERE b > CAST('2009-04-03 00:00:01' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 + WHERE b < CAST('2009-04-02 23:59:58' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 + WHERE b <= CAST('2009-04-02 23:59:58' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 + WHERE b = CAST('2009-04-02 23:59:58' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 + WHERE b >= CAST('2009-04-02 23:59:58' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 + WHERE b > CAST('2009-04-02 23:59:58' AS DATETIME); +DROP TABLE t1; + +--echo # Test with DATE column NOT NULL +CREATE TABLE t1 ( + a int(10) unsigned NOT NULL, + b DATE NOT NULL, + PRIMARY KEY (a, b) +) PARTITION BY RANGE (TO_DAYS(b)) +(PARTITION p20090401 VALUES LESS THAN (TO_DAYS('2009-04-02')), + PARTITION p20090402 VALUES LESS THAN (TO_DAYS('2009-04-03')), + PARTITION p20090403 VALUES LESS THAN (TO_DAYS('2009-04-04')), + PARTITION p20090404 VALUES LESS THAN (TO_DAYS('2009-04-05')), + PARTITION p20090405 VALUES LESS THAN MAXVALUE); +INSERT INTO t1 VALUES (1, '2009-01-01'), (1, '2009-04-01'), (2, '2009-04-01'), + (1, '2009-04-02'), (2, '2009-04-02'), (1, '2009-04-03'), (2, '2009-04-03'), + (1, '2009-04-04'), (2, '2009-04-04'), (1, '2009-04-05'), (1, '2009-04-06'), + (1, '2009-04-07'); +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < CAST('2009-04-03' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= CAST('2009-04-03' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = CAST('2009-04-03' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= CAST('2009-04-03' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > CAST('2009-04-03' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 + WHERE b < CAST('2009-04-02 23:59:59' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 + WHERE b <= CAST('2009-04-02 23:59:59' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 + WHERE b = CAST('2009-04-02 23:59:59' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 + WHERE b >= CAST('2009-04-02 23:59:59' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 + WHERE b > CAST('2009-04-02 23:59:59' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < CAST('2009-04-03' AS DATE); +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= CAST('2009-04-03' AS DATE); +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = CAST('2009-04-03' AS DATE); +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= CAST('2009-04-03' AS DATE); +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > CAST('2009-04-03' AS DATE); +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < '2009-04-03 00:00:00'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= '2009-04-03 00:00:00'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = '2009-04-03 00:00:00'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= '2009-04-03 00:00:00'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > '2009-04-03 00:00:00'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < '2009-04-02 23:59:59'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= '2009-04-02 23:59:59'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = '2009-04-02 23:59:59'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= '2009-04-02 23:59:59'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > '2009-04-02 23:59:59'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < '2009-04-03'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= '2009-04-03'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = '2009-04-03'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= '2009-04-03'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > '2009-04-03'; +EXPLAIN PARTITIONS SELECT * FROM t1 + WHERE b < CAST('2009-04-03 00:00:01' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 + WHERE b <= CAST('2009-04-03 00:00:01' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 + WHERE b = CAST('2009-04-03 00:00:01' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 + WHERE b >= CAST('2009-04-03 00:00:01' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 + WHERE b > CAST('2009-04-03 00:00:01' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 + WHERE b < CAST('2009-04-02 23:59:58' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 + WHERE b <= CAST('2009-04-02 23:59:58' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 + WHERE b = CAST('2009-04-02 23:59:58' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 + WHERE b >= CAST('2009-04-02 23:59:58' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 + WHERE b > CAST('2009-04-02 23:59:58' AS DATETIME); +DROP TABLE t1; + +--echo # Test with DATETIME column NULL +CREATE TABLE t1 ( + a int(10) unsigned NOT NULL, + b DATETIME NULL +) PARTITION BY RANGE (TO_DAYS(b)) +(PARTITION p20090401 VALUES LESS THAN (TO_DAYS('2009-04-02')), + PARTITION p20090402 VALUES LESS THAN (TO_DAYS('2009-04-03')), + PARTITION p20090403 VALUES LESS THAN (TO_DAYS('2009-04-04')), + PARTITION p20090404 VALUES LESS THAN (TO_DAYS('2009-04-05')), + PARTITION p20090405 VALUES LESS THAN MAXVALUE); +INSERT INTO t1 VALUES (1, '2009-01-01'), (1, '2009-04-01'), (2, '2009-04-01'), + (1, '2009-04-02'), (2, '2009-04-02'), (1, '2009-04-02 23:59:59'), + (1, '2009-04-03'), (2, '2009-04-03'), (1, '2009-04-04'), (2, '2009-04-04'), + (1, '2009-04-05'), (1, '2009-04-06'), (1, '2009-04-07'); +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < CAST('2009-04-03' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= CAST('2009-04-03' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = CAST('2009-04-03' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= CAST('2009-04-03' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > CAST('2009-04-03' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 + WHERE b < CAST('2009-04-02 23:59:59' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 + WHERE b <= CAST('2009-04-02 23:59:59' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 + WHERE b = CAST('2009-04-02 23:59:59' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 + WHERE b >= CAST('2009-04-02 23:59:59' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 + WHERE b > CAST('2009-04-02 23:59:59' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < CAST('2009-04-03' AS DATE); +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= CAST('2009-04-03' AS DATE); +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = CAST('2009-04-03' AS DATE); +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= CAST('2009-04-03' AS DATE); +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > CAST('2009-04-03' AS DATE); +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < '2009-04-03 00:00:00'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= '2009-04-03 00:00:00'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = '2009-04-03 00:00:00'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= '2009-04-03 00:00:00'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > '2009-04-03 00:00:00'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < '2009-04-02 23:59:59'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= '2009-04-02 23:59:59'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = '2009-04-02 23:59:59'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= '2009-04-02 23:59:59'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > '2009-04-02 23:59:59'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < '2009-04-03'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= '2009-04-03'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = '2009-04-03'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= '2009-04-03'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > '2009-04-03'; +EXPLAIN PARTITIONS SELECT * FROM t1 + WHERE b < CAST('2009-04-03 00:00:01' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 + WHERE b <= CAST('2009-04-03 00:00:01' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 + WHERE b = CAST('2009-04-03 00:00:01' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 + WHERE b >= CAST('2009-04-03 00:00:01' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 + WHERE b > CAST('2009-04-03 00:00:01' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 + WHERE b < CAST('2009-04-02 23:59:58' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 + WHERE b <= CAST('2009-04-02 23:59:58' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 + WHERE b = CAST('2009-04-02 23:59:58' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 + WHERE b >= CAST('2009-04-02 23:59:58' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 + WHERE b > CAST('2009-04-02 23:59:58' AS DATETIME); +DROP TABLE t1; + +--echo # Test with DATE column NULL +CREATE TABLE t1 ( + a int(10) unsigned NOT NULL, + b DATE NULL +) PARTITION BY RANGE (TO_DAYS(b)) +(PARTITION p20090401 VALUES LESS THAN (TO_DAYS('2009-04-02')), + PARTITION p20090402 VALUES LESS THAN (TO_DAYS('2009-04-03')), + PARTITION p20090403 VALUES LESS THAN (TO_DAYS('2009-04-04')), + PARTITION p20090404 VALUES LESS THAN (TO_DAYS('2009-04-05')), + PARTITION p20090405 VALUES LESS THAN MAXVALUE); +INSERT INTO t1 VALUES (1, '2009-01-01'), (1, '2009-04-01'), (2, '2009-04-01'), + (1, '2009-04-02'), (2, '2009-04-02'), (1, '2009-04-03'), (2, '2009-04-03'), + (1, '2009-04-04'), (2, '2009-04-04'), (1, '2009-04-05'), (1, '2009-04-06'), + (1, '2009-04-07'); +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < CAST('2009-04-03' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= CAST('2009-04-03' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = CAST('2009-04-03' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= CAST('2009-04-03' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > CAST('2009-04-03' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 + WHERE b < CAST('2009-04-02 23:59:59' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 + WHERE b <= CAST('2009-04-02 23:59:59' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 + WHERE b = CAST('2009-04-02 23:59:59' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 + WHERE b >= CAST('2009-04-02 23:59:59' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 + WHERE b > CAST('2009-04-02 23:59:59' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < CAST('2009-04-03' AS DATE); +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= CAST('2009-04-03' AS DATE); +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = CAST('2009-04-03' AS DATE); +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= CAST('2009-04-03' AS DATE); +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > CAST('2009-04-03' AS DATE); +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < '2009-04-03 00:00:00'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= '2009-04-03 00:00:00'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = '2009-04-03 00:00:00'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= '2009-04-03 00:00:00'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > '2009-04-03 00:00:00'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < '2009-04-02 23:59:59'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= '2009-04-02 23:59:59'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = '2009-04-02 23:59:59'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= '2009-04-02 23:59:59'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > '2009-04-02 23:59:59'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < '2009-04-03'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b <= '2009-04-03'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b = '2009-04-03'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b >= '2009-04-03'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b > '2009-04-03'; +EXPLAIN PARTITIONS SELECT * FROM t1 + WHERE b < CAST('2009-04-03 00:00:01' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 + WHERE b <= CAST('2009-04-03 00:00:01' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 + WHERE b = CAST('2009-04-03 00:00:01' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 + WHERE b >= CAST('2009-04-03 00:00:01' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 + WHERE b > CAST('2009-04-03 00:00:01' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 + WHERE b < CAST('2009-04-02 23:59:58' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 + WHERE b <= CAST('2009-04-02 23:59:58' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 + WHERE b = CAST('2009-04-02 23:59:58' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 + WHERE b >= CAST('2009-04-02 23:59:58' AS DATETIME); +EXPLAIN PARTITIONS SELECT * FROM t1 + WHERE b > CAST('2009-04-02 23:59:58' AS DATETIME); +DROP TABLE t1; + +--echo # For better code coverage of the patch +CREATE TABLE t1 ( + a int(10) unsigned NOT NULL, + b DATE +) PARTITION BY RANGE ( TO_DAYS(b) ) +(PARTITION p20090401 VALUES LESS THAN (TO_DAYS('2009-04-02')), + PARTITION p20090402 VALUES LESS THAN (TO_DAYS('2009-04-03')), + PARTITION p20090403 VALUES LESS THAN (TO_DAYS('2009-04-04')), + PARTITION p20090404 VALUES LESS THAN (TO_DAYS('2009-04-05')), + PARTITION p20090405 VALUES LESS THAN MAXVALUE); +INSERT INTO t1 VALUES (1, '2009-01-01'), (2, NULL); +--echo # test with an invalid date, which lead to item->null_value is set. +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE b < CAST('2009-04-99' AS DATETIME); +DROP TABLE t1; + # # Bug#40972: some sql execution lead the whole database crashing # diff --git a/sql-common/my_time.c b/sql-common/my_time.c index 747c5797ed4..a1b85049934 100644 --- a/sql-common/my_time.c +++ b/sql-common/my_time.c @@ -450,9 +450,7 @@ str_to_datetime(const char *str, uint length, MYSQL_TIME *l_time, } } - DBUG_RETURN(l_time->time_type= - (number_of_fields <= 3 ? MYSQL_TIMESTAMP_DATE : - MYSQL_TIMESTAMP_DATETIME)); + DBUG_RETURN(l_time->time_type); err: bzero((char*) l_time, sizeof(*l_time)); diff --git a/sql/item.cc b/sql/item.cc index 2640b74851b..79ae4b20f30 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -6846,14 +6846,21 @@ void resolve_const_item(THD *thd, Item **ref, Item *comp_item) } /** - Return true if the value stored in the field is equal to the const - item. + Compare the value stored in field, with the original item. - We need to use this on the range optimizer because in some cases - we can't store the value in the field without some precision/character loss. + @param field field which the item is converted and stored in + @param item original item + + @return Return an integer greater than, equal to, or less than 0 if + the value stored in the field is greater than, equal to, + or less than the original item + + @note We only use this on the range optimizer/partition pruning, + because in some cases we can't store the value in the field + without some precision/character loss. */ -bool field_is_equal_to_item(Field *field,Item *item) +int stored_field_cmp_to_item(Field *field, Item *item) { Item_result res_type=item_cmp_type(field->result_type(), @@ -6864,28 +6871,49 @@ bool field_is_equal_to_item(Field *field,Item *item) char field_buff[MAX_FIELD_WIDTH]; String item_tmp(item_buff,sizeof(item_buff),&my_charset_bin),*item_result; String field_tmp(field_buff,sizeof(field_buff),&my_charset_bin); + enum_field_types field_type; item_result=item->val_str(&item_tmp); if (item->null_value) - return 1; // This must be true + return 0; field->val_str(&field_tmp); - return !stringcmp(&field_tmp,item_result); + + /* + If comparing DATE with DATETIME, append the time-part to the DATE. + So that the strings are equally formatted. + A DATE converted to string is 10 characters, and a DATETIME converted + to string is 19 characters. + */ + field_type= field->type(); + if (field_type == MYSQL_TYPE_DATE && + item_result->length() == 19) + field_tmp.append(" 00:00:00"); + else if (field_type == MYSQL_TYPE_DATETIME && + item_result->length() == 10) + item_result->append(" 00:00:00"); + + return stringcmp(&field_tmp,item_result); } if (res_type == INT_RESULT) - return 1; // Both where of type int + return 0; // Both are of type int if (res_type == DECIMAL_RESULT) { my_decimal item_buf, *item_val, field_buf, *field_val; item_val= item->val_decimal(&item_buf); if (item->null_value) - return 1; // This must be true + return 0; field_val= field->val_decimal(&field_buf); - return !my_decimal_cmp(item_val, field_val); + return my_decimal_cmp(item_val, field_val); } double result= item->val_real(); if (item->null_value) + return 0; + double field_result= field->val_real(); + if (field_result < result) + return -1; + else if (field_result > result) return 1; - return result == field->val_real(); + return 0; } Item_cache* Item_cache::get_cache(const Item *item) diff --git a/sql/item.h b/sql/item.h index 3dfcd7c2612..8b37bd3c26d 100644 --- a/sql/item.h +++ b/sql/item.h @@ -576,8 +576,8 @@ public: left_endp FALSE <=> The interval is "x < const" or "x <= const" TRUE <=> The interval is "x > const" or "x >= const" - incl_endp IN TRUE <=> the comparison is '<' or '>' - FALSE <=> the comparison is '<=' or '>=' + incl_endp IN FALSE <=> the comparison is '<' or '>' + TRUE <=> the comparison is '<=' or '>=' OUT The same but for the "F(x) $CMP$ F(const)" comparison DESCRIPTION @@ -3117,4 +3117,4 @@ void mark_select_range_as_dependent(THD *thd, extern Cached_item *new_Cached_item(THD *thd, Item *item); extern Item_result item_cmp_type(Item_result a,Item_result b); extern void resolve_const_item(THD *thd, Item **ref, Item *cmp_item); -extern bool field_is_equal_to_item(Field *field,Item *item); +extern int stored_field_cmp_to_item(Field *field, Item *item); diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index d79b0b02998..eebede32f8d 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -991,15 +991,19 @@ longlong Item_func_to_days::val_int_endpoint(bool left_endp, bool *incl_endp) point to day bound ("strictly less" comparison stays intact): col < '2007-09-15 00:00:00' -> TO_DAYS(col) < TO_DAYS('2007-09-15') + col > '2007-09-15 23:59:59' -> TO_DAYS(col) > TO_DAYS('2007-09-15') which is different from the general case ("strictly less" changes to "less or equal"): col < '2007-09-15 12:34:56' -> TO_DAYS(col) <= TO_DAYS('2007-09-15') */ - if (!left_endp && !(ltime.hour || ltime.minute || ltime.second || - ltime.second_part)) - ; /* do nothing */ + if ((!left_endp && !(ltime.hour || ltime.minute || ltime.second || + ltime.second_part)) || + (left_endp && ltime.hour == 23 && ltime.minute == 59 && + ltime.second == 59)) + /* do nothing */ + ; else *incl_endp= TRUE; return res; diff --git a/sql/opt_range.cc b/sql/opt_range.cc index e3aef02637f..96631a741da 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -5855,7 +5855,7 @@ get_mm_leaf(RANGE_OPT_PARAM *param, COND *conf_func, Field *field, but we'll need to convert '>' to '>=' and '<' to '<='. This will be done together with other types at the end of this function - (grep for field_is_equal_to_item) + (grep for stored_field_cmp_to_item) */ } else @@ -5930,7 +5930,7 @@ get_mm_leaf(RANGE_OPT_PARAM *param, COND *conf_func, Field *field, switch (type) { case Item_func::LT_FUNC: - if (field_is_equal_to_item(field,value)) + if (stored_field_cmp_to_item(field,value) == 0) tree->max_flag=NEAR_MAX; /* fall through */ case Item_func::LE_FUNC: @@ -5944,11 +5944,16 @@ get_mm_leaf(RANGE_OPT_PARAM *param, COND *conf_func, Field *field, break; case Item_func::GT_FUNC: /* Don't use open ranges for partial key_segments */ - if (field_is_equal_to_item(field,value) && - !(key_part->flag & HA_PART_KEY_SEG)) + if ((!(key_part->flag & HA_PART_KEY_SEG)) && + (stored_field_cmp_to_item(field, value) <= 0)) tree->min_flag=NEAR_MIN; - /* fall through */ + tree->max_flag= NO_MAX_RANGE; + break; case Item_func::GE_FUNC: + /* Don't use open ranges for partial key_segments */ + if ((!(key_part->flag & HA_PART_KEY_SEG)) && + (stored_field_cmp_to_item(field,value) < 0)) + tree->min_flag= NEAR_MIN; tree->max_flag=NO_MAX_RANGE; break; case Item_func::SP_EQUALS_FUNC: From 67214ef4334deccdd1f1d89c49c4edecd9075962 Mon Sep 17 00:00:00 2001 From: Mattias Jonsson Date: Wed, 26 Aug 2009 12:59:49 +0200 Subject: [PATCH 24/69] Bug#20577: Partitions: use of to_days() function leads to selection failures Problem was that the partition containing NULL values was pruned away, since '2001-01-01' < '2001-02-00' but TO_DAYS('2001-02-00') is NULL. Added the NULL partition for RANGE/LIST partitioning on TO_DAYS() function to be scanned too. Also fixed a bug that added ALLOW_INVALID_DATES to sql_mode (SELECT * FROM t WHERE date_col < '1999-99-99' on a RANGE/LIST partitioned table would add it). mysql-test/include/partition_date_range.inc: Bug#20577: Partitions: use of to_days() function leads to selection failures Added include file to decrease test code duplication mysql-test/r/partition_pruning.result: Bug#20577: Partitions: use of to_days() function leads to selection failures Added test results mysql-test/r/partition_range.result: Bug#20577: Partitions: use of to_days() function leads to selection failures Updated test result. This fix adds the partition containing NULL values to the list of partitions to be scanned. mysql-test/t/partition_pruning.test: Bug#20577: Partitions: use of to_days() function leads to selection failures Added test case sql/item.h: Bug#20577: Partitions: use of to_days() function leads to selection failures Added MONOTONIC_*INCREASE_NOT_NULL values to be used by TO_DAYS. sql/item_timefunc.cc: Bug#20577: Partitions: use of to_days() function leads to selection failures Calculate the number of days as return value even for invalid dates. This is so that pruning can be used even for invalid dates. sql/opt_range.cc: Bug#20577: Partitions: use of to_days() function leads to selection failures Fixed a bug that added ALLOW_INVALID_DATES to sql_mode (SELECT * FROM t WHERE date_col < '1999-99-99' on a RANGE/LIST partitioned table would add it). sql/partition_info.h: Bug#20577: Partitions: use of to_days() function leads to selection failures Resetting ret_null_part when a single partition is to be used, this to avoid adding the NULL partition. sql/sql_partition.cc: Bug#20577: Partitions: use of to_days() function leads to selection failures Always include the NULL partition if RANGE or LIST. Use the returned value for the function for pruning, even if it is marked as NULL, so that even '2000-00-00' can be used for pruning, even if TO_DAYS('2000-00-00') is NULL. Changed == to >= in get_next_partition_id_list to avoid crash if part_iter->part_nums is not correctly setup. --- mysql-test/include/partition_date_range.inc | 63 +++ mysql-test/r/partition_pruning.result | 425 ++++++++++++++++++++ mysql-test/r/partition_range.result | 4 +- mysql-test/t/partition_pruning.test | 44 ++ sql/item.h | 9 +- sql/item_timefunc.cc | 21 +- sql/opt_range.cc | 4 + sql/partition_info.h | 1 + sql/sql_partition.cc | 65 ++- 9 files changed, 624 insertions(+), 12 deletions(-) create mode 100644 mysql-test/include/partition_date_range.inc diff --git a/mysql-test/include/partition_date_range.inc b/mysql-test/include/partition_date_range.inc new file mode 100644 index 00000000000..c54396af9cb --- /dev/null +++ b/mysql-test/include/partition_date_range.inc @@ -0,0 +1,63 @@ +# Created for verifying bug#20577. +# expects TABLE t1 (... , a DATE, ...) + +--sorted_result +SELECT * FROM t1 WHERE a < '1001-01-01'; +--sorted_result +SELECT * FROM t1 WHERE a <= '1001-01-01'; +--sorted_result +SELECT * FROM t1 WHERE a >= '1001-01-01'; +--sorted_result +SELECT * FROM t1 WHERE a > '1001-01-01'; +--sorted_result +SELECT * FROM t1 WHERE a = '1001-01-01'; +--sorted_result +SELECT * FROM t1 WHERE a < '1001-00-00'; +--sorted_result +SELECT * FROM t1 WHERE a <= '1001-00-00'; +--sorted_result +SELECT * FROM t1 WHERE a >= '1001-00-00'; +--sorted_result +SELECT * FROM t1 WHERE a > '1001-00-00'; +--sorted_result +SELECT * FROM t1 WHERE a = '1001-00-00'; +--sorted_result +SELECT * FROM t1 WHERE a < '1999-02-31'; +--sorted_result +SELECT * FROM t1 WHERE a <= '1999-02-31'; +--sorted_result +SELECT * FROM t1 WHERE a >= '1999-02-31'; +--sorted_result +SELECT * FROM t1 WHERE a > '1999-02-31'; +--sorted_result +SELECT * FROM t1 WHERE a = '1999-02-31'; +--sorted_result +SELECT * FROM t1 WHERE a BETWEEN '0000-00-00' AND '1002-00-00'; +--sorted_result +SELECT * FROM t1 WHERE a BETWEEN '0000-00-00' AND '1001-01-01'; +--sorted_result +SELECT * FROM t1 WHERE a BETWEEN '0001-01-02' AND '1002-00-00'; +--sorted_result +SELECT * FROM t1 WHERE a BETWEEN '0001-01-01' AND '1001-01-01'; +if ($explain_partitions) +{ +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < '1001-01-01'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= '1001-01-01'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= '1001-01-01'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > '1001-01-01'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = '1001-01-01'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < '1001-00-00'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= '1001-00-00'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= '1001-00-00'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > '1001-00-00'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = '1001-00-00'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < '1999-02-31'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= '1999-02-31'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= '1999-02-31'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > '1999-02-31'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = '1999-02-31'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a BETWEEN '0000-00-00' AND '1002-00-00'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a BETWEEN '0000-00-00' AND '1001-01-01'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a BETWEEN '0001-01-02' AND '1002-00-00'; +EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a BETWEEN '0001-01-01' AND '1001-01-01'; +} diff --git a/mysql-test/r/partition_pruning.result b/mysql-test/r/partition_pruning.result index 26ddc92e97b..7ac1e24cfab 100644 --- a/mysql-test/r/partition_pruning.result +++ b/mysql-test/r/partition_pruning.result @@ -1,4 +1,429 @@ drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +# test of RANGE and index +CREATE TABLE t1 (a DATE, KEY(a)) +PARTITION BY RANGE (TO_DAYS(a)) +(PARTITION `pNULL` VALUES LESS THAN (0), +PARTITION `p0001-01-01` VALUES LESS THAN (366 + 1), +PARTITION `p1001-01-01` VALUES LESS THAN (TO_DAYS('1001-01-01') + 1), +PARTITION `p2001-01-01` VALUES LESS THAN (TO_DAYS('2001-01-01') + 1)); +INSERT INTO t1 VALUES ('0000-00-00'), ('0000-01-02'), ('0001-01-01'), +('1001-00-00'), ('1001-01-01'), ('1002-00-00'), ('2001-01-01'); +SELECT * FROM t1 WHERE a < '1001-01-01'; +a +0000-00-00 +0000-01-02 +0001-01-01 +1001-00-00 +SELECT * FROM t1 WHERE a <= '1001-01-01'; +a +0000-00-00 +0000-01-02 +0001-01-01 +1001-00-00 +1001-01-01 +SELECT * FROM t1 WHERE a >= '1001-01-01'; +a +1001-01-01 +1002-00-00 +2001-01-01 +SELECT * FROM t1 WHERE a > '1001-01-01'; +a +1002-00-00 +2001-01-01 +SELECT * FROM t1 WHERE a = '1001-01-01'; +a +1001-01-01 +SELECT * FROM t1 WHERE a < '1001-00-00'; +a +0000-00-00 +0000-01-02 +0001-01-01 +SELECT * FROM t1 WHERE a <= '1001-00-00'; +a +0000-00-00 +0000-01-02 +0001-01-01 +1001-00-00 +SELECT * FROM t1 WHERE a >= '1001-00-00'; +a +1001-00-00 +1001-01-01 +1002-00-00 +2001-01-01 +SELECT * FROM t1 WHERE a > '1001-00-00'; +a +1001-01-01 +1002-00-00 +2001-01-01 +SELECT * FROM t1 WHERE a = '1001-00-00'; +a +1001-00-00 +SELECT * FROM t1 WHERE a < '1999-02-31'; +a +0000-00-00 +0000-01-02 +0001-01-01 +1001-00-00 +1001-01-01 +1002-00-00 +SELECT * FROM t1 WHERE a <= '1999-02-31'; +a +0000-00-00 +0000-01-02 +0001-01-01 +1001-00-00 +1001-01-01 +1002-00-00 +SELECT * FROM t1 WHERE a >= '1999-02-31'; +a +2001-01-01 +SELECT * FROM t1 WHERE a > '1999-02-31'; +a +2001-01-01 +SELECT * FROM t1 WHERE a = '1999-02-31'; +a +Warning 1292 Incorrect date value: '1999-02-31' for column 'a' at row 1 +Warnings: +SELECT * FROM t1 WHERE a BETWEEN '0000-00-00' AND '1002-00-00'; +a +0000-00-00 +0000-01-02 +0001-01-01 +1001-00-00 +1001-01-01 +1002-00-00 +SELECT * FROM t1 WHERE a BETWEEN '0000-00-00' AND '1001-01-01'; +a +0000-00-00 +0000-01-02 +0001-01-01 +1001-00-00 +1001-01-01 +SELECT * FROM t1 WHERE a BETWEEN '0001-01-02' AND '1002-00-00'; +a +1001-00-00 +1001-01-01 +1002-00-00 +SELECT * FROM t1 WHERE a BETWEEN '0001-01-01' AND '1001-01-01'; +a +0001-01-01 +1001-00-00 +1001-01-01 +# test without index +ALTER TABLE t1 DROP KEY a; +SELECT * FROM t1 WHERE a < '1001-01-01'; +a +0000-00-00 +0000-01-02 +0001-01-01 +1001-00-00 +SELECT * FROM t1 WHERE a <= '1001-01-01'; +a +0000-00-00 +0000-01-02 +0001-01-01 +1001-00-00 +1001-01-01 +SELECT * FROM t1 WHERE a >= '1001-01-01'; +a +1001-01-01 +1002-00-00 +2001-01-01 +SELECT * FROM t1 WHERE a > '1001-01-01'; +a +1002-00-00 +2001-01-01 +SELECT * FROM t1 WHERE a = '1001-01-01'; +a +1001-01-01 +SELECT * FROM t1 WHERE a < '1001-00-00'; +a +0000-00-00 +0000-01-02 +0001-01-01 +SELECT * FROM t1 WHERE a <= '1001-00-00'; +a +0000-00-00 +0000-01-02 +0001-01-01 +1001-00-00 +SELECT * FROM t1 WHERE a >= '1001-00-00'; +a +1001-00-00 +1001-01-01 +1002-00-00 +2001-01-01 +SELECT * FROM t1 WHERE a > '1001-00-00'; +a +1001-01-01 +1002-00-00 +2001-01-01 +SELECT * FROM t1 WHERE a = '1001-00-00'; +a +1001-00-00 +SELECT * FROM t1 WHERE a < '1999-02-31'; +a +0000-00-00 +0000-01-02 +0001-01-01 +1001-00-00 +1001-01-01 +1002-00-00 +SELECT * FROM t1 WHERE a <= '1999-02-31'; +a +0000-00-00 +0000-01-02 +0001-01-01 +1001-00-00 +1001-01-01 +1002-00-00 +SELECT * FROM t1 WHERE a >= '1999-02-31'; +a +2001-01-01 +SELECT * FROM t1 WHERE a > '1999-02-31'; +a +2001-01-01 +SELECT * FROM t1 WHERE a = '1999-02-31'; +a +SELECT * FROM t1 WHERE a BETWEEN '0000-00-00' AND '1002-00-00'; +a +0000-00-00 +0000-01-02 +0001-01-01 +1001-00-00 +1001-01-01 +1002-00-00 +SELECT * FROM t1 WHERE a BETWEEN '0000-00-00' AND '1001-01-01'; +a +0000-00-00 +0000-01-02 +0001-01-01 +1001-00-00 +1001-01-01 +SELECT * FROM t1 WHERE a BETWEEN '0001-01-02' AND '1002-00-00'; +a +1001-00-00 +1001-01-01 +1002-00-00 +SELECT * FROM t1 WHERE a BETWEEN '0001-01-01' AND '1001-01-01'; +a +0001-01-01 +1001-00-00 +1001-01-01 +DROP TABLE t1; +# test of LIST and index +CREATE TABLE t1 (a DATE, KEY(a)) +PARTITION BY LIST (TO_DAYS(a)) +(PARTITION `p0001-01-01` VALUES IN (TO_DAYS('0001-01-01')), +PARTITION `p2001-01-01` VALUES IN (TO_DAYS('2001-01-01')), +PARTITION `pNULL` VALUES IN (NULL), +PARTITION `p0000-01-02` VALUES IN (TO_DAYS('0000-01-02')), +PARTITION `p1001-01-01` VALUES IN (TO_DAYS('1001-01-01'))); +INSERT INTO t1 VALUES ('0000-00-00'), ('0000-01-02'), ('0001-01-01'), +('1001-00-00'), ('1001-01-01'), ('1002-00-00'), ('2001-01-01'); +SELECT * FROM t1 WHERE a < '1001-01-01'; +a +0000-00-00 +0000-01-02 +0001-01-01 +1001-00-00 +SELECT * FROM t1 WHERE a <= '1001-01-01'; +a +0000-00-00 +0000-01-02 +0001-01-01 +1001-00-00 +1001-01-01 +SELECT * FROM t1 WHERE a >= '1001-01-01'; +a +1001-01-01 +1002-00-00 +2001-01-01 +SELECT * FROM t1 WHERE a > '1001-01-01'; +a +1002-00-00 +2001-01-01 +SELECT * FROM t1 WHERE a = '1001-01-01'; +a +1001-01-01 +SELECT * FROM t1 WHERE a < '1001-00-00'; +a +0000-00-00 +0000-01-02 +0001-01-01 +SELECT * FROM t1 WHERE a <= '1001-00-00'; +a +0000-00-00 +0000-01-02 +0001-01-01 +1001-00-00 +SELECT * FROM t1 WHERE a >= '1001-00-00'; +a +1001-00-00 +1001-01-01 +1002-00-00 +2001-01-01 +SELECT * FROM t1 WHERE a > '1001-00-00'; +a +1001-01-01 +1002-00-00 +2001-01-01 +SELECT * FROM t1 WHERE a = '1001-00-00'; +a +1001-00-00 +SELECT * FROM t1 WHERE a < '1999-02-31'; +a +0000-00-00 +0000-01-02 +0001-01-01 +1001-00-00 +1001-01-01 +1002-00-00 +SELECT * FROM t1 WHERE a <= '1999-02-31'; +a +0000-00-00 +0000-01-02 +0001-01-01 +1001-00-00 +1001-01-01 +1002-00-00 +SELECT * FROM t1 WHERE a >= '1999-02-31'; +a +2001-01-01 +SELECT * FROM t1 WHERE a > '1999-02-31'; +a +2001-01-01 +SELECT * FROM t1 WHERE a = '1999-02-31'; +a +Warning 1292 Incorrect date value: '1999-02-31' for column 'a' at row 1 +Warnings: +SELECT * FROM t1 WHERE a BETWEEN '0000-00-00' AND '1002-00-00'; +a +0000-00-00 +0000-01-02 +0001-01-01 +1001-00-00 +1001-01-01 +1002-00-00 +SELECT * FROM t1 WHERE a BETWEEN '0000-00-00' AND '1001-01-01'; +a +0000-00-00 +0000-01-02 +0001-01-01 +1001-00-00 +1001-01-01 +SELECT * FROM t1 WHERE a BETWEEN '0001-01-02' AND '1002-00-00'; +a +1001-00-00 +1001-01-01 +1002-00-00 +SELECT * FROM t1 WHERE a BETWEEN '0001-01-01' AND '1001-01-01'; +a +0001-01-01 +1001-00-00 +1001-01-01 +# test without index +ALTER TABLE t1 DROP KEY a; +SELECT * FROM t1 WHERE a < '1001-01-01'; +a +0000-00-00 +0000-01-02 +0001-01-01 +1001-00-00 +SELECT * FROM t1 WHERE a <= '1001-01-01'; +a +0000-00-00 +0000-01-02 +0001-01-01 +1001-00-00 +1001-01-01 +SELECT * FROM t1 WHERE a >= '1001-01-01'; +a +1001-01-01 +1002-00-00 +2001-01-01 +SELECT * FROM t1 WHERE a > '1001-01-01'; +a +1002-00-00 +2001-01-01 +SELECT * FROM t1 WHERE a = '1001-01-01'; +a +1001-01-01 +SELECT * FROM t1 WHERE a < '1001-00-00'; +a +0000-00-00 +0000-01-02 +0001-01-01 +SELECT * FROM t1 WHERE a <= '1001-00-00'; +a +0000-00-00 +0000-01-02 +0001-01-01 +1001-00-00 +SELECT * FROM t1 WHERE a >= '1001-00-00'; +a +1001-00-00 +1001-01-01 +1002-00-00 +2001-01-01 +SELECT * FROM t1 WHERE a > '1001-00-00'; +a +1001-01-01 +1002-00-00 +2001-01-01 +SELECT * FROM t1 WHERE a = '1001-00-00'; +a +1001-00-00 +SELECT * FROM t1 WHERE a < '1999-02-31'; +a +0000-00-00 +0000-01-02 +0001-01-01 +1001-00-00 +1001-01-01 +1002-00-00 +SELECT * FROM t1 WHERE a <= '1999-02-31'; +a +0000-00-00 +0000-01-02 +0001-01-01 +1001-00-00 +1001-01-01 +1002-00-00 +SELECT * FROM t1 WHERE a >= '1999-02-31'; +a +2001-01-01 +SELECT * FROM t1 WHERE a > '1999-02-31'; +a +2001-01-01 +SELECT * FROM t1 WHERE a = '1999-02-31'; +a +SELECT * FROM t1 WHERE a BETWEEN '0000-00-00' AND '1002-00-00'; +a +0000-00-00 +0000-01-02 +0001-01-01 +1001-00-00 +1001-01-01 +1002-00-00 +SELECT * FROM t1 WHERE a BETWEEN '0000-00-00' AND '1001-01-01'; +a +0000-00-00 +0000-01-02 +0001-01-01 +1001-00-00 +1001-01-01 +SELECT * FROM t1 WHERE a BETWEEN '0001-01-02' AND '1002-00-00'; +a +1001-00-00 +1001-01-01 +1002-00-00 +SELECT * FROM t1 WHERE a BETWEEN '0001-01-01' AND '1001-01-01'; +a +0001-01-01 +1001-00-00 +1001-01-01 +DROP TABLE t1; CREATE TABLE t1 (a INT NOT NULL AUTO_INCREMENT, b DATETIME, diff --git a/mysql-test/r/partition_range.result b/mysql-test/r/partition_range.result index e8fc55b759b..02d2f6359c5 100644 --- a/mysql-test/r/partition_range.result +++ b/mysql-test/r/partition_range.result @@ -745,7 +745,7 @@ a EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= '2004-07-01' AND a <= '2004-09-30'; id select_type table partitions type possible_keys key key_len ref rows Extra -1 SIMPLE t1 p407,p408,p409 ALL NULL NULL NULL NULL 9 Using where +1 SIMPLE t1 p3xx,p407,p408,p409 ALL NULL NULL NULL NULL 18 Using where SELECT * from t1 WHERE (a >= '2004-07-01' AND a <= '2004-09-30') OR (a >= '2005-07-01' AND a <= '2005-09-30'); @@ -772,7 +772,7 @@ EXPLAIN PARTITIONS SELECT * from t1 WHERE (a >= '2004-07-01' AND a <= '2004-09-30') OR (a >= '2005-07-01' AND a <= '2005-09-30'); id select_type table partitions type possible_keys key key_len ref rows Extra -1 SIMPLE t1 p407,p408,p409,p507,p508,p509 ALL NULL NULL NULL NULL 18 Using where +1 SIMPLE t1 p3xx,p407,p408,p409,p507,p508,p509 ALL NULL NULL NULL NULL 27 Using where DROP TABLE t1; create table t1 (a int); insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); diff --git a/mysql-test/t/partition_pruning.test b/mysql-test/t/partition_pruning.test index ad102062ef8..511cfa595a4 100644 --- a/mysql-test/t/partition_pruning.test +++ b/mysql-test/t/partition_pruning.test @@ -8,6 +8,50 @@ drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; --enable_warnings +# +# Bug#20577: Partitions: use of to_days() function leads to selection failures +# +--let $explain_partitions= 1; +--let $verify_without_partitions= 0; +--echo # test of RANGE and index +CREATE TABLE t1 (a DATE, KEY(a)) +PARTITION BY RANGE (TO_DAYS(a)) +(PARTITION `pNULL` VALUES LESS THAN (0), + PARTITION `p0001-01-01` VALUES LESS THAN (366 + 1), + PARTITION `p1001-01-01` VALUES LESS THAN (TO_DAYS('1001-01-01') + 1), + PARTITION `p2001-01-01` VALUES LESS THAN (TO_DAYS('2001-01-01') + 1)); +if ($verify_without_partitions) +{ +ALTER TABLE t1 REMOVE PARTITIONING; +} +INSERT INTO t1 VALUES ('0000-00-00'), ('0000-01-02'), ('0001-01-01'), + ('1001-00-00'), ('1001-01-01'), ('1002-00-00'), ('2001-01-01'); +--source include/partition_date_range.inc +--echo # test without index +ALTER TABLE t1 DROP KEY a; +--source include/partition_date_range.inc +DROP TABLE t1; + +--echo # test of LIST and index +CREATE TABLE t1 (a DATE, KEY(a)) +PARTITION BY LIST (TO_DAYS(a)) +(PARTITION `p0001-01-01` VALUES IN (TO_DAYS('0001-01-01')), + PARTITION `p2001-01-01` VALUES IN (TO_DAYS('2001-01-01')), + PARTITION `pNULL` VALUES IN (NULL), + PARTITION `p0000-01-02` VALUES IN (TO_DAYS('0000-01-02')), + PARTITION `p1001-01-01` VALUES IN (TO_DAYS('1001-01-01'))); +if ($verify_without_partitions) +{ +ALTER TABLE t1 REMOVE PARTITIONING; +} +INSERT INTO t1 VALUES ('0000-00-00'), ('0000-01-02'), ('0001-01-01'), + ('1001-00-00'), ('1001-01-01'), ('1002-00-00'), ('2001-01-01'); +--source include/partition_date_range.inc +--echo # test without index +ALTER TABLE t1 DROP KEY a; +--source include/partition_date_range.inc +DROP TABLE t1; + # # Bug#40972: some sql execution lead the whole database crashing # diff --git a/sql/item.h b/sql/item.h index 3dfcd7c2612..30478ddf13d 100644 --- a/sql/item.h +++ b/sql/item.h @@ -397,13 +397,20 @@ public: from INT_RESULT, may be NULL, or are unsigned. It will be possible to address this issue once the related partitioning bugs (BUG#16002, BUG#15447, BUG#13436) are fixed. + + The NOT_NULL enums are used in TO_DAYS, since TO_DAYS('2001-00-00') returns + NULL which puts those rows into the NULL partition, but + '2000-12-31' < '2001-00-00' < '2001-01-01'. So special handling is needed + for this (see Bug#20577). */ typedef enum monotonicity_info { NON_MONOTONIC, /* none of the below holds */ MONOTONIC_INCREASING, /* F() is unary and (x < y) => (F(x) <= F(y)) */ - MONOTONIC_STRICT_INCREASING /* F() is unary and (x < y) => (F(x) < F(y)) */ + MONOTONIC_INCREASING_NOT_NULL, /* But only for valid/real x and y */ + MONOTONIC_STRICT_INCREASING,/* F() is unary and (x < y) => (F(x) < F(y)) */ + MONOTONIC_STRICT_INCREASING_NOT_NULL /* But only for valid/real x and y */ } enum_monotonicity_info; /*************************************************************************/ diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index d79b0b02998..eefe47232ae 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -960,9 +960,9 @@ enum_monotonicity_info Item_func_to_days::get_monotonicity_info() const if (args[0]->type() == Item::FIELD_ITEM) { if (args[0]->field_type() == MYSQL_TYPE_DATE) - return MONOTONIC_STRICT_INCREASING; + return MONOTONIC_STRICT_INCREASING_NOT_NULL; if (args[0]->field_type() == MYSQL_TYPE_DATETIME) - return MONOTONIC_INCREASING; + return MONOTONIC_INCREASING_NOT_NULL; } return NON_MONOTONIC; } @@ -973,12 +973,27 @@ longlong Item_func_to_days::val_int_endpoint(bool left_endp, bool *incl_endp) DBUG_ASSERT(fixed == 1); MYSQL_TIME ltime; longlong res; - if (get_arg0_date(<ime, TIME_NO_ZERO_DATE)) + int dummy; /* unused */ + if (get_arg0_date(<ime, TIME_FUZZY_DATE)) { /* got NULL, leave the incl_endp intact */ return LONGLONG_MIN; } res=(longlong) calc_daynr(ltime.year,ltime.month,ltime.day); + /* Set to NULL if invalid date, but keep the value */ + null_value= check_date(<ime, + (ltime.year || ltime.month || ltime.day), + (TIME_NO_ZERO_IN_DATE | TIME_NO_ZERO_DATE), + &dummy); + if (null_value) + { + /* + Even if the evaluation return NULL, the calc_daynr is useful for pruning + */ + if (args[0]->field_type() != MYSQL_TYPE_DATE) + *incl_endp= TRUE; + return res; + } if (args[0]->field_type() == MYSQL_TYPE_DATE) { diff --git a/sql/opt_range.cc b/sql/opt_range.cc index e3aef02637f..e26d91dcd44 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -5826,6 +5826,7 @@ get_mm_leaf(RANGE_OPT_PARAM *param, COND *conf_func, Field *field, { tree= new (alloc) SEL_ARG(field, 0, 0); tree->type= SEL_ARG::IMPOSSIBLE; + field->table->in_use->variables.sql_mode= orig_sql_mode; goto end; } else @@ -5859,7 +5860,10 @@ get_mm_leaf(RANGE_OPT_PARAM *param, COND *conf_func, Field *field, */ } else + { + field->table->in_use->variables.sql_mode= orig_sql_mode; goto end; + } } } diff --git a/sql/partition_info.h b/sql/partition_info.h index 415f955d5d4..8832b6ee409 100644 --- a/sql/partition_info.h +++ b/sql/partition_info.h @@ -300,6 +300,7 @@ static inline void init_single_partition_iterator(uint32 part_id, { part_iter->part_nums.start= part_iter->part_nums.cur= part_id; part_iter->part_nums.end= part_id+1; + part_iter->ret_null_part= part_iter->ret_null_part_orig= FALSE; part_iter->get_next= get_next_partition_id_range; } diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 61766e5c509..ad24af12087 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -2766,8 +2766,24 @@ uint32 get_list_array_idx_for_endpoint(partition_info *part_info, if (part_info->part_expr->null_value) { - DBUG_RETURN(0); + /* + Special handling for MONOTONIC functions that can return NULL for + values that are comparable. I.e. + '2000-00-00' can be compared to '2000-01-01' but TO_DAYS('2000-00-00') + returns NULL which cannot be compared used <, >, <=, >= etc. + + Otherwise, just return the the first index (lowest value). + */ + enum_monotonicity_info monotonic; + monotonic= part_info->part_expr->get_monotonicity_info(); + if (monotonic != MONOTONIC_INCREASING_NOT_NULL && + monotonic != MONOTONIC_STRICT_INCREASING_NOT_NULL) + { + /* F(col) can not return NULL, return index with lowest value */ + DBUG_RETURN(0); + } } + if (unsigned_flag) part_func_value-= 0x8000000000000000ULL; DBUG_ASSERT(part_info->no_list_values); @@ -2916,11 +2932,29 @@ uint32 get_partition_id_range_for_endpoint(partition_info *part_info, if (part_info->part_expr->null_value) { - uint32 ret_part_id= 0; - if (!left_endpoint && include_endpoint) - ret_part_id= 1; - DBUG_RETURN(ret_part_id); + /* + Special handling for MONOTONIC functions that can return NULL for + values that are comparable. I.e. + '2000-00-00' can be compared to '2000-01-01' but TO_DAYS('2000-00-00') + returns NULL which cannot be compared used <, >, <=, >= etc. + + Otherwise, just return the first partition + (may be included if not left endpoint) + */ + enum_monotonicity_info monotonic; + monotonic= part_info->part_expr->get_monotonicity_info(); + if (monotonic != MONOTONIC_INCREASING_NOT_NULL && + monotonic != MONOTONIC_STRICT_INCREASING_NOT_NULL) + { + /* F(col) can not return NULL, return partition with lowest value */ + if (!left_endpoint && include_endpoint) + DBUG_RETURN(1); + DBUG_RETURN(0); + + } } + + if (unsigned_flag) part_func_value-= 0x8000000000000000ULL; if (left_endpoint && !include_endpoint) @@ -6733,6 +6767,19 @@ int get_part_iter_for_interval_via_mapping(partition_info *part_info, } else assert(0); + + if (part_info->part_type == RANGE_PARTITION || + part_info->has_null_value) + { + enum_monotonicity_info monotonic; + monotonic= part_info->part_expr->get_monotonicity_info(); + if (monotonic == MONOTONIC_INCREASING_NOT_NULL || + monotonic == MONOTONIC_STRICT_INCREASING_NOT_NULL) + { + /* col is NOT NULL, but F(col) can return NULL, add NULL partition */ + part_iter->ret_null_part= part_iter->ret_null_part_orig= TRUE; + } + } /* Find minimum: Do special handling if the interval has left bound in form @@ -6959,7 +7006,13 @@ uint32 get_next_partition_id_range(PARTITION_ITERATOR* part_iter) { if (part_iter->part_nums.cur >= part_iter->part_nums.end) { + if (part_iter->ret_null_part) + { + part_iter->ret_null_part= FALSE; + return 0; /* NULL always in first range partition */ + } part_iter->part_nums.cur= part_iter->part_nums.start; + part_iter->ret_null_part= part_iter->ret_null_part_orig; return NOT_A_PARTITION_ID; } else @@ -6987,7 +7040,7 @@ uint32 get_next_partition_id_range(PARTITION_ITERATOR* part_iter) uint32 get_next_partition_id_list(PARTITION_ITERATOR *part_iter) { - if (part_iter->part_nums.cur == part_iter->part_nums.end) + if (part_iter->part_nums.cur >= part_iter->part_nums.end) { if (part_iter->ret_null_part) { From 6c2b32515e1856b65feedec2ebe47843f416b2ad Mon Sep 17 00:00:00 2001 From: Alfranio Correia Date: Thu, 27 Aug 2009 00:13:03 +0100 Subject: [PATCH 25/69] BUG#28976 Mixing trans and non-trans tables in one transaction results in incorrect binlog Mixing transactional (T) and non-transactional (N) tables on behalf of a transaction may lead to inconsistencies among masters and slaves in STATEMENT mode. The problem stems from the fact that although modifications done to non-transactional tables on behalf of a transaction become immediately visible to other connections they do not immediately get to the binary log and therefore consistency is broken. Although there may be issues in mixing T and M tables in STATEMENT mode, there are safe combinations that clients find useful. In this bug, we fix the following issue. Mixing N and T tables in multi-level (e.g. a statement that fires a trigger) or multi-table table statements (e.g. update t1, t2...) were not handled correctly. In such cases, it was not possible to distinguish when a T table was updated if the sequence of changes was N and T. In a nutshell, just the flag "modified_non_trans_table" was not enough to reflect that both a N and T tables were changed. To circumvent this issue, we check if an engine is registered in the handler's list and changed something which means that a T table was modified. Check WL 2687 for a full-fledged patch that will make the use of either the MIXED or ROW modes completely safe. mysql-test/suite/binlog/r/binlog_row_mix_innodb_myisam.result: Truncate statement is wrapped in BEGIN/COMMIT. mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result: Truncate statement is wrapped in BEGIN/COMMIT. --- .../extra/rpl_tests/rpl_mixing_engines.test | 727 +++++++++++++++ mysql-test/include/commit.inc | 4 +- mysql-test/r/commit_1innodb.result | 8 +- .../r/binlog_row_mix_innodb_myisam.result | 4 + .../r/binlog_stm_mix_innodb_myisam.result | 6 + .../suite/rpl/r/rpl_innodb_mixed_dml.result | 2 + .../suite/rpl/r/rpl_stm_mixing_engines.result | 871 ++++++++++++++++++ .../suite/rpl/t/rpl_stm_mixing_engines.test | 5 + sql/log.cc | 22 +- 9 files changed, 1642 insertions(+), 7 deletions(-) create mode 100644 mysql-test/extra/rpl_tests/rpl_mixing_engines.test create mode 100644 mysql-test/suite/rpl/r/rpl_stm_mixing_engines.result create mode 100644 mysql-test/suite/rpl/t/rpl_stm_mixing_engines.test diff --git a/mysql-test/extra/rpl_tests/rpl_mixing_engines.test b/mysql-test/extra/rpl_tests/rpl_mixing_engines.test new file mode 100644 index 00000000000..73713b7998b --- /dev/null +++ b/mysql-test/extra/rpl_tests/rpl_mixing_engines.test @@ -0,0 +1,727 @@ +################################################################################### +# This test checks if transactions that mixes transactional and non-transactional +# tables are correctly handled in statement mode. In an nutshell, we have what +# follows: +# +# 1) "B T T C" generates in binlog the "B T T C" entries. +# +# 2) "B T T R" generates in binlog an "empty" entry. +# +# 3) "B T N C" generates in binlog the "B T N C" entries. +# +# 4) "B T N R" generates in binlog the "B T N R" entries. +# +# 5) "T" generates in binlog the "B T C" entry. +# +# 6) "N" generates in binlog the "N" entry. +# +# 7) "M" generates in binglog the "B M C" entries. +# +# 8) "B N N T C" generates in binglog the "N N B T C" entries. +# +# 9) "B N N T R" generates in binlog the "N N B T R" entries. +# +# 10) "B N N C" generates in binglog the "N N" entries. +# +# 11) "B N N R" generates in binlog the "N N" entries. +# +# 12) "B M T C" generates in the binlog the "B M T C" entries. +# +# 13) "B M T R" generates in the binlog the "B M T R" entries. +################################################################################### + +--echo ################################################################################### +--echo # CONFIGURATION +--echo ################################################################################### +connection master; + +SET SQL_LOG_BIN=0; +CREATE TABLE nt_1 (a text, b int PRIMARY KEY, c text) ENGINE = MyISAM; +CREATE TABLE nt_2 (a text, b int PRIMARY KEY, c text) ENGINE = MyISAM; +CREATE TABLE nt_3 (a text, b int PRIMARY KEY, c text) ENGINE = MyISAM; +CREATE TABLE nt_4 (a text, b int PRIMARY KEY, c text) ENGINE = MyISAM; +CREATE TABLE tt_1 (a text, b int PRIMARY KEY, c text) ENGINE = Innodb; +CREATE TABLE tt_2 (a text, b int PRIMARY KEY, c text) ENGINE = Innodb; +CREATE TABLE tt_3 (a text, b int PRIMARY KEY, c text) ENGINE = Innodb; +CREATE TABLE tt_4 (a text, b int PRIMARY KEY, c text) ENGINE = Innodb; +SET SQL_LOG_BIN=1; + +connection slave; + +SET SQL_LOG_BIN=0; +CREATE TABLE nt_1 (a text, b int PRIMARY KEY, c text) ENGINE = MyISAM; +CREATE TABLE nt_2 (a text, b int PRIMARY KEY, c text) ENGINE = MyISAM; +CREATE TABLE nt_3 (a text, b int PRIMARY KEY, c text) ENGINE = MyISAM; +CREATE TABLE nt_4 (a text, b int PRIMARY KEY, c text) ENGINE = MyISAM; +CREATE TABLE tt_1 (a text, b int PRIMARY KEY, c text) ENGINE = Innodb; +CREATE TABLE tt_2 (a text, b int PRIMARY KEY, c text) ENGINE = Innodb; +CREATE TABLE tt_3 (a text, b int PRIMARY KEY, c text) ENGINE = Innodb; +CREATE TABLE tt_4 (a text, b int PRIMARY KEY, c text) ENGINE = Innodb; +SET SQL_LOG_BIN=1; + +connection master; + +DELIMITER |; + +CREATE FUNCTION f1 () RETURNS VARCHAR(64) +BEGIN + RETURN "Testing..."; +END| + +CREATE FUNCTION f2 () RETURNS VARCHAR(64) +BEGIN + RETURN f1(); +END| + +CREATE PROCEDURE pc_i_tt_3 (IN x INT, IN y VARCHAR(64)) +BEGIN + INSERT INTO tt_3 VALUES (y,x,x); +END| + +CREATE TRIGGER tr_i_tt_3_to_nt_3 BEFORE INSERT ON tt_3 FOR EACH ROW +BEGIN + INSERT INTO nt_3 VALUES (NEW.a, NEW.b, NEW.c); +END| + +CREATE TRIGGER tr_i_nt_4_to_tt_4 BEFORE INSERT ON nt_4 FOR EACH ROW +BEGIN + INSERT INTO tt_4 VALUES (NEW.a, NEW.b, NEW.c); +END| + +DELIMITER ;| + +--echo ################################################################################### +--echo # MIXING TRANSACTIONAL and NON-TRANSACTIONAL TABLES +--echo ################################################################################### +connection master; + +let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1); +--echo # +--echo #1) "B T T C" generates in binlog the "B T T C" entries. +--echo # +BEGIN; +INSERT INTO tt_1 VALUES ("new text 4", 4, "new text 4"); +INSERT INTO tt_2 VALUES ("new text 4", 4, "new text 4"); +COMMIT; + +--source include/show_binlog_events.inc + +--echo +--echo +--echo +--echo +let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1); +--echo # +--echo #1.e) "B T T C" with error in T generates in binlog the "B T T C" entries. +--echo # +INSERT INTO tt_1 VALUES ("new text -2", -2, "new text -2"); +BEGIN; +--error ER_DUP_ENTRY +INSERT INTO tt_1 VALUES ("new text -1", -1, "new text -1"), ("new text -2", -2, "new text -2"); +INSERT INTO tt_2 VALUES ("new text -3", -3, "new text -3"); +COMMIT; + +BEGIN; +INSERT INTO tt_2 VALUES ("new text -5", -5, "new text -5"); +--error ER_DUP_ENTRY +INSERT INTO tt_2 VALUES ("new text -4", -4, "new text -4"), ("new text -5", -5, "new text -5"); +COMMIT; + +--source include/show_binlog_events.inc + +--echo +--echo +--echo +--echo +let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1); +--echo # +--echo #2) "B T T R" generates in binlog an "empty" entry. +--echo # +BEGIN; +INSERT INTO tt_1 VALUES ("new text 5", 5, "new text 5"); +INSERT INTO tt_2 VALUES ("new text 5", 5, "new text 5"); +ROLLBACK; + +--source include/show_binlog_events.inc + +--echo +--echo +--echo +--echo +let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1); +--echo # +--echo #2.e) "B T T R" with error in T generates in binlog an "empty" entry. +--echo # +INSERT INTO tt_1 VALUES ("new text -7", -7, "new text -7"); +BEGIN; +--error ER_DUP_ENTRY +INSERT INTO tt_1 VALUES ("new text -6", -6, "new text -6"), ("new text -7", -7, "new text -7"); +INSERT INTO tt_2 VALUES ("new text -8", -8, "new text -8"); +ROLLBACK; + +BEGIN; +INSERT INTO tt_2 VALUES ("new text -10", -10, "new text -10"); +--error ER_DUP_ENTRY +INSERT INTO tt_2 VALUES ("new text -9", -9, "new text -9"), ("new text -10", -10, "new text -10"); +ROLLBACK; + +--source include/show_binlog_events.inc + +--echo +--echo +--echo +--echo +let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1); +--echo # +--echo #3) "B T N C" generates in binlog the "B T N C" entries. +--echo # +BEGIN; +INSERT INTO tt_1 VALUES ("new text 6", 6, "new text 6"); +INSERT INTO nt_1 VALUES ("new text 6", 6, "new text 6"); +COMMIT; + +--source include/show_binlog_events.inc + +--echo +--echo +--echo +--echo +let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1); +--echo # +--echo #3.e) "B T N C" with error in either T or N generates in binlog the "B T N C" entries. +--echo # +INSERT INTO tt_1 VALUES ("new text -12", -12, "new text -12"); +BEGIN; +--error ER_DUP_ENTRY +INSERT INTO tt_1 VALUES ("new text -11", -11, "new text -11"), ("new text -12", -12, "new text -12"); +INSERT INTO nt_1 VALUES ("new text -13", -13, "new text -13"); +COMMIT; + +BEGIN; +INSERT INTO tt_1 VALUES ("new text -14", -14, "new text -14"); +INSERT INTO nt_1 VALUES ("new text -16", -16, "new text -16"); +--error ER_DUP_ENTRY +INSERT INTO nt_1 VALUES ("new text -15", -15, "new text -15"), ("new text -16", -16, "new text -16"); +COMMIT; + +--source include/show_binlog_events.inc + +--echo +--echo +--echo +--echo +let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1); +--echo # +--echo #4) "B T N R" generates in binlog the "B T N R" entries. +--echo # +BEGIN; +INSERT INTO tt_1 VALUES ("new text 7", 7, "new text 7"); +INSERT INTO nt_1 VALUES ("new text 7", 7, "new text 7"); +ROLLBACK; + +--source include/show_binlog_events.inc + +--echo +--echo +--echo +--echo +let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1); +--echo # +--echo #4.e) "B T N R" with error in either T or N generates in binlog the "B T N R" entries. +--echo # +INSERT INTO tt_1 VALUES ("new text -17", -17, "new text -17"); +BEGIN; +--error ER_DUP_ENTRY +INSERT INTO tt_1 VALUES ("new text -16", -16, "new text -16"), ("new text -17", -17, "new text -17"); +INSERT INTO nt_1 VALUES ("new text -18", -18, "new text -18"); +ROLLBACK; + +BEGIN; +INSERT INTO tt_1 VALUES ("new text -19", -19, "new text -19"); +INSERT INTO nt_1 VALUES ("new text -21", -21, "new text -21"); +--error ER_DUP_ENTRY +INSERT INTO nt_1 VALUES ("new text -20", -20, "new text -20"), ("new text -21", -21, "new text -21"); +ROLLBACK; + +--source include/show_binlog_events.inc + +--echo +--echo +--echo +--echo +let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1); +--echo # +--echo #5) "T" generates in binlog the "B T C" entry. +--echo # +INSERT INTO tt_1 VALUES ("new text 8", 8, "new text 8"); + +--source include/show_binlog_events.inc + +--echo +--echo +--echo +--echo +let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1); +--echo # +--echo #5.e) "T" with error in T generates in binlog an "empty" entry. +--echo # +INSERT INTO tt_1 VALUES ("new text -1", -1, "new text -1"); +--error ER_DUP_ENTRY +INSERT INTO tt_1 VALUES ("new text -1", -1, "new text -1"), ("new text -22", -22, "new text -22"); +--error ER_DUP_ENTRY +INSERT INTO tt_1 VALUES ("new text -23", -23, "new text -23"), ("new text -1", -1, "new text -1"); + +--source include/show_binlog_events.inc + +--echo +--echo +--echo +--echo +let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1); +--echo # +--echo #6) "N" generates in binlog the "N" entry. +--echo # +INSERT INTO nt_1 VALUES ("new text 9", 9, "new text 9"); + +--source include/show_binlog_events.inc + +--echo +--echo +--echo +--echo +let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1); +--echo # +--echo #6.e) "N" with error in N generates in binlog an empty entry if the error +--echo # happens in the first tuple. Otherwise, generates the "N" entry and +--echo # the error is appended. +--echo # +INSERT INTO nt_1 VALUES ("new text -1", -1, "new text -1"); +--error ER_DUP_ENTRY +INSERT INTO nt_1 VALUES ("new text -1", -1, "new text -1"); +--error ER_DUP_ENTRY +INSERT INTO nt_1 VALUES ("new text -24", -24, "new text -24"), ("new text -1", -1, "new text -1"); + +--source include/show_binlog_events.inc + +--echo +--echo +--echo +--echo +let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1); +--echo # +--echo #7) "M" generates in binglog the "B M C" entries. +--echo # + +DELETE FROM nt_1; + +INSERT INTO nt_1 SELECT * FROM tt_1; + +DELETE FROM tt_1; + +INSERT INTO tt_1 SELECT * FROM nt_1; + +INSERT INTO tt_3 VALUES ("new text 000", 000, ''); + +INSERT INTO tt_3 VALUES("new text 100", 100, f1()); + +INSERT INTO nt_4 VALUES("new text 100", 100, f1()); + +INSERT INTO tt_3 VALUES("new text 200", 200, f2()); + +INSERT INTO nt_4 VALUES ("new text 300", 300, ''); + +INSERT INTO nt_4 VALUES ("new text 400", 400, f1()); + +INSERT INTO nt_4 VALUES ("new text 500", 500, f2()); + +CALL pc_i_tt_3(600, "Testing..."); + +UPDATE nt_3, nt_4, tt_3, tt_4 SET nt_3.a= "new text 1", nt_4.a= "new text 1", tt_3.a= "new text 1", tt_4.a= "new text 1" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100; + +UPDATE tt_3, tt_4, nt_3, nt_4 SET tt_3.a= "new text 2", tt_4.a= "new text 2", nt_3.a= "new text 2", nt_4.a = "new text 2" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100; + +UPDATE tt_3, nt_3, nt_4, tt_4 SET tt_3.a= "new text 3", nt_3.a= "new text 3", nt_4.a= "new text 3", tt_4.a = "new text 3" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100; + +UPDATE tt_3, nt_3, nt_4, tt_4 SET tt_3.a= "new text 4", nt_3.a= "new text 4", nt_4.a= "new text 4", tt_4.a = "new text 4" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100; + +--source include/show_binlog_events.inc + +--echo +--echo +--echo +--echo +let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1); +--echo # +--echo #7.e) "M" with error in M generates in binglog the "B M R" entries. +--echo # + +INSERT INTO nt_3 VALUES ("new text -26", -26, ''); +SELECT * FROM tt_3; +--error ER_DUP_ENTRY +INSERT INTO tt_3 VALUES ("new text -25", -25, ''), ("new text -26", -26, ''); +SELECT * FROM tt_3; + +INSERT INTO tt_4 VALUES ("new text -26", -26, ''); +SELECT * FROM nt_4; +--error ER_DUP_ENTRY +INSERT INTO nt_4 VALUES ("new text -25", -25, ''), ("new text -26", -26, ''); +SELECT * FROM nt_4; + +--source include/show_binlog_events.inc + +--echo +--echo +--echo +--echo +let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1); +--echo # +--echo #8) "B N N T C" generates in binglog the "N N B T C" entries. +--echo # +BEGIN; +INSERT INTO nt_1 VALUES ("new text 10", 10, "new text 10"); +INSERT INTO nt_2 VALUES ("new text 10", 10, "new text 10"); +INSERT INTO tt_1 VALUES ("new text 10", 10, "new text 10"); +COMMIT; + +--source include/show_binlog_events.inc + +--echo +--echo +--echo +--echo +--echo # +--echo #8.e) "B N N T R" See 6.e and 9.e. +--echo # + +--echo +--echo +--echo +--echo +let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1); +--echo # +--echo #9) "B N N T R" generates in binlog the "N N B T R" entries. +--echo # +BEGIN; +INSERT INTO nt_1 VALUES ("new text 11", 11, "new text 11"); +INSERT INTO nt_2 VALUES ("new text 11", 11, "new text 11"); +INSERT INTO tt_1 VALUES ("new text 11", 11, "new text 11"); +ROLLBACK; + +--source include/show_binlog_events.inc + +--echo +--echo +--echo +--echo +let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1); +--echo # +--echo #9.e) "B N N T R" with error in N generates in binlog the "N N B T R" entries. +--echo # +BEGIN; +INSERT INTO nt_1 VALUES ("new text -25", -25, "new text -25"); +INSERT INTO nt_2 VALUES ("new text -25", -25, "new text -25"); +--error ER_DUP_ENTRY +INSERT INTO nt_2 VALUES ("new text -26", -26, "new text -26"), ("new text -25", -25, "new text -25"); +INSERT INTO tt_1 VALUES ("new text -27", -27, "new text -27"); +ROLLBACK; + +--source include/show_binlog_events.inc + +--echo +--echo +--echo +--echo +let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1); +--echo # +--echo #10) "B N N C" generates in binglog the "N N" entries. +--echo # +BEGIN; +INSERT INTO nt_1 VALUES ("new text 12", 12, "new text 12"); +INSERT INTO nt_2 VALUES ("new text 12", 12, "new text 12"); +COMMIT; + +--source include/show_binlog_events.inc + +--echo +--echo +--echo +--echo +--echo # +--echo #10.e) "B N N C" See 6.e and 9.e. +--echo # + +--echo +--echo +--echo +--echo +let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1); +--echo # +--echo #11) "B N N R" generates in binlog the "N N" entries. +--echo # +BEGIN; +INSERT INTO nt_1 VALUES ("new text 13", 13, "new text 13"); +INSERT INTO nt_2 VALUES ("new text 13", 13, "new text 13"); +ROLLBACK; + +--source include/show_binlog_events.inc + +--echo +--echo +--echo +--echo +--echo # +--echo #11.e) "B N N R" See 6.e and 9.e. +--echo # + +--echo +--echo +--echo +--echo +let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1); +--echo # +--echo #12) "B M T C" generates in the binlog the "B M T C" entries. +--echo # +DELETE FROM nt_1; +BEGIN; +INSERT INTO nt_1 SELECT * FROM tt_1; +INSERT INTO tt_2 VALUES ("new text 14", 14, "new text 14"); +COMMIT; + +DELETE FROM tt_1; +BEGIN; +INSERT INTO tt_1 SELECT * FROM nt_1; +INSERT INTO tt_2 VALUES ("new text 15", 15, "new text 15"); +COMMIT; + +BEGIN; +INSERT INTO tt_3 VALUES ("new text 700", 700, ''); +INSERT INTO tt_1 VALUES ("new text 800", 800, ''); +COMMIT; + +BEGIN; +INSERT INTO tt_3 VALUES("new text 900", 900, f1()); +INSERT INTO tt_1 VALUES ("new text 1000", 1000, ''); +COMMIT; + +BEGIN; +INSERT INTO tt_3 VALUES(1100, 1100, f2()); +INSERT INTO tt_1 VALUES ("new text 1200", 1200, ''); +COMMIT; + +BEGIN; +INSERT INTO nt_4 VALUES ("new text 1300", 1300, ''); +INSERT INTO tt_1 VALUES ("new text 1400", 1400, ''); +COMMIT; + +BEGIN; +INSERT INTO nt_4 VALUES("new text 1500", 1500, f1()); +INSERT INTO tt_1 VALUES ("new text 1600", 1600, ''); +COMMIT; + +BEGIN; +INSERT INTO nt_4 VALUES("new text 1700", 1700, f2()); +INSERT INTO tt_1 VALUES ("new text 1800", 1800, ''); +COMMIT; + +BEGIN; +CALL pc_i_tt_3(1900, "Testing..."); +INSERT INTO tt_1 VALUES ("new text 2000", 2000, ''); +COMMIT; + +BEGIN; +UPDATE nt_3, nt_4, tt_3, tt_4 SET nt_3.a= "new text 5", nt_4.a= "new text 5", tt_3.a= "new text 5", tt_4.a= "new text 5" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100; +INSERT INTO tt_1 VALUES ("new text 2100", 2100, ''); +COMMIT; + +BEGIN; +UPDATE tt_3, tt_4, nt_3, nt_4 SET tt_3.a= "new text 6", tt_4.a= "new text 6", nt_3.a= "new text 6", nt_4.a = "new text 6" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100; +INSERT INTO tt_1 VALUES ("new text 2200", 2200, ''); +COMMIT; + +BEGIN; +UPDATE tt_3, nt_3, nt_4, tt_4 SET tt_3.a= "new text 7", nt_3.a= "new text 7", nt_4.a= "new text 7", tt_4.a = "new text 7" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100; +INSERT INTO tt_1 VALUES ("new text 2300", 2300, ''); +COMMIT; + +BEGIN; +UPDATE tt_3, nt_3, nt_4, tt_4 SET tt_3.a= "new text 8", nt_3.a= "new text 8", nt_4.a= "new text 8", tt_4.a = "new text 8" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100; +INSERT INTO tt_1 VALUES ("new text 2400", 2400, ''); +COMMIT; + +--source include/show_binlog_events.inc + +--echo +--echo +--echo +--echo +let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1); +--echo # +--echo #12.e) "B M T C" with error in M generates in the binlog the "B M T C" entries. +--echo # + +--echo # There is a bug in the slave that needs to be fixed before enabling +--echo # this part of the test. A bug report will be filed referencing this +--echo # test case. +# +#BEGIN; +#INSERT INTO nt_3 VALUES ("new text -28", -28, ''); +#--error ER_DUP_ENTRY +#INSERT INTO tt_3 VALUES ("new text -27", -27, ''), ("new text -28", -28, ''); +#INSERT INTO tt_1 VALUES ("new text -27", -27, ''); +#COMMIT; +# +#BEGIN; +#INSERT INTO tt_4 VALUES ("new text -28", -28, ''); +#--error ER_DUP_ENTRY +#INSERT INTO nt_4 VALUES ("new text -27", -27, ''), ("new text -28", -28, ''); +#INSERT INTO tt_1 VALUES ("new text -28", -28, ''); +#COMMIT; +# +--source include/show_binlog_events.inc + +--echo +--echo +--echo +--echo +let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1); +--echo # +--echo #13) "B M T R" generates in the binlog the "B M T R" entries +--echo # + +DELETE FROM nt_1; +BEGIN; +INSERT INTO nt_1 SELECT * FROM tt_1; +INSERT INTO tt_2 VALUES ("new text 17", 17, "new text 17"); +ROLLBACK; + +DELETE FROM tt_1; +BEGIN; +INSERT INTO tt_1 SELECT * FROM nt_1; +INSERT INTO tt_2 VALUES ("new text 18", 18, "new text 18"); +ROLLBACK; +INSERT INTO tt_1 SELECT * FROM nt_1; + +BEGIN; +INSERT INTO tt_3 VALUES ("new text 2500", 2500, ''); +INSERT INTO tt_1 VALUES ("new text 2600", 2600, ''); +ROLLBACK; + +BEGIN; +INSERT INTO tt_3 VALUES("new text 2700", 2700, f1()); +INSERT INTO tt_1 VALUES ("new text 2800", 2800, ''); +ROLLBACK; + +BEGIN; +INSERT INTO tt_3 VALUES(2900, 2900, f2()); +INSERT INTO tt_1 VALUES ("new text 3000", 3000, ''); +ROLLBACK; + +BEGIN; +INSERT INTO nt_4 VALUES ("new text 3100", 3100, ''); +INSERT INTO tt_1 VALUES ("new text 3200", 3200, ''); +ROLLBACK; + +BEGIN; +INSERT INTO nt_4 VALUES("new text 3300", 3300, f1()); +INSERT INTO tt_1 VALUES ("new text 3400", 3400, ''); +ROLLBACK; + +BEGIN; +INSERT INTO nt_4 VALUES("new text 3500", 3500, f2()); +INSERT INTO tt_1 VALUES ("new text 3600", 3600, ''); +ROLLBACK; + +BEGIN; +CALL pc_i_tt_3(3700, "Testing..."); +INSERT INTO tt_1 VALUES ("new text 3700", 3700, ''); +ROLLBACK; + +BEGIN; +UPDATE nt_3, nt_4, tt_3, tt_4 SET nt_3.a= "new text 9", nt_4.a= "new text 9", tt_3.a= "new text 9", tt_4.a= "new text 9" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100; +INSERT INTO tt_1 VALUES ("new text 3800", 3800, ''); +ROLLBACK; + +BEGIN; +UPDATE tt_3, tt_4, nt_3, nt_4 SET tt_3.a= "new text 10", tt_4.a= "new text 10", nt_3.a= "new text 10", nt_4.a = "new text 10" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100; +INSERT INTO tt_1 VALUES ("new text 3900", 3900, ''); +ROLLBACK; + +BEGIN; +UPDATE tt_3, nt_3, nt_4, tt_4 SET tt_3.a= "new text 11", nt_3.a= "new text 11", nt_4.a= "new text 11", tt_4.a = "new text 11" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100; +INSERT INTO tt_1 VALUES ("new text 4000", 4000, ''); +ROLLBACK; + +BEGIN; +UPDATE tt_3, nt_3, nt_4, tt_4 SET tt_3.a= "new text 12", nt_3.a= "new text 12", nt_4.a= "new text 12", tt_4.a = "new text 12" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100; +INSERT INTO tt_1 VALUES ("new text 4100", 4100, ''); +ROLLBACK; + +--source include/show_binlog_events.inc + +--echo +--echo +--echo +--echo +let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1); +--echo # +--echo #13.e) "B M T R" with error in M generates in the binlog the "B M T R" entries. +--echo # + +BEGIN; +INSERT INTO nt_3 VALUES ("new text -30", -30, ''); +--error ER_DUP_ENTRY +INSERT INTO tt_3 VALUES ("new text -29", -29, ''), ("new text -30", -30, ''); +INSERT INTO tt_1 VALUES ("new text -30", -30, ''); +ROLLBACK; + +BEGIN; +INSERT INTO tt_4 VALUES ("new text -30", -30, ''); +--error ER_DUP_ENTRY +INSERT INTO nt_4 VALUES ("new text -29", -29, ''), ("new text -30", -30, ''); +INSERT INTO tt_1 VALUES ("new text -31", -31, ''); +ROLLBACK; + +--source include/show_binlog_events.inc + +--echo +--echo +--echo +--echo +let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1); +--echo # +--echo #14) "B M T R" with error in M generates in the binlog the "B M T R" entries. +--echo # + +BEGIN; +INSERT INTO tt_4 VALUES ("new text -32", -32, ''); +TRUNCATE TABLE tt_4; +INSERT INTO tt_4 VALUES ("new text -33", -33, ''); +ROLLBACK; + +--source include/show_binlog_events.inc + +connection master; +sync_slave_with_master; + +--exec $MYSQL_DUMP --compact --order-by-primary --skip-extended-insert --no-create-info test > $MYSQLTEST_VARDIR/tmp/test-master.sql +--exec $MYSQL_DUMP_SLAVE --compact --order-by-primary --skip-extended-insert --no-create-info test > $MYSQLTEST_VARDIR/tmp/test-slave.sql +--diff_files $MYSQLTEST_VARDIR/tmp/test-master.sql $MYSQLTEST_VARDIR/tmp/test-slave.sql + +--echo ################################################################################### +--echo # CLEAN +--echo ################################################################################### + +connection master; +DROP TABLE tt_1; +DROP TABLE tt_2; +DROP TABLE tt_3; +DROP TABLE tt_4; +DROP TABLE nt_1; +DROP TABLE nt_2; +DROP TABLE nt_3; +DROP TABLE nt_4; +DROP PROCEDURE pc_i_tt_3; +DROP FUNCTION f1; +DROP FUNCTION f2; + +sync_slave_with_master; diff --git a/mysql-test/include/commit.inc b/mysql-test/include/commit.inc index d412eae8364..d91ba8291fd 100644 --- a/mysql-test/include/commit.inc +++ b/mysql-test/include/commit.inc @@ -725,9 +725,9 @@ call p_verify_status_increment(4, 4, 4, 4); alter table t3 add column (b int); call p_verify_status_increment(2, 0, 2, 0); alter table t3 rename t4; -call p_verify_status_increment(1, 0, 1, 0); +call p_verify_status_increment(2, 2, 2, 2); rename table t4 to t3; -call p_verify_status_increment(1, 0, 1, 0); +call p_verify_status_increment(2, 2, 2, 2); truncate table t3; call p_verify_status_increment(4, 4, 4, 4); create view v1 as select * from t2; diff --git a/mysql-test/r/commit_1innodb.result b/mysql-test/r/commit_1innodb.result index cabd4c29c1d..51c4ac3002c 100644 --- a/mysql-test/r/commit_1innodb.result +++ b/mysql-test/r/commit_1innodb.result @@ -841,17 +841,17 @@ call p_verify_status_increment(2, 0, 2, 0); SUCCESS alter table t3 rename t4; -call p_verify_status_increment(1, 0, 1, 0); +call p_verify_status_increment(2, 2, 2, 2); SUCCESS rename table t4 to t3; -call p_verify_status_increment(1, 0, 1, 0); +call p_verify_status_increment(2, 2, 2, 2); SUCCESS truncate table t3; call p_verify_status_increment(4, 4, 4, 4); -ERROR -Expected commit increment: 4 actual: 2 +SUCCESS + create view v1 as select * from t2; call p_verify_status_increment(1, 0, 1, 0); SUCCESS diff --git a/mysql-test/suite/binlog/r/binlog_row_mix_innodb_myisam.result b/mysql-test/suite/binlog/r/binlog_row_mix_innodb_myisam.result index 4d639c3da68..9ae5121f618 100644 --- a/mysql-test/suite/binlog/r/binlog_row_mix_innodb_myisam.result +++ b/mysql-test/suite/binlog/r/binlog_row_mix_innodb_myisam.result @@ -379,7 +379,9 @@ master-bin.000001 # Query # # BEGIN master-bin.000001 # Table_map # # table_id: # (test.t1) master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F master-bin.000001 # Query # # COMMIT +master-bin.000001 # Query # # BEGIN master-bin.000001 # Query # # use `test`; TRUNCATE table t2 +master-bin.000001 # Xid # # COMMIT /* XID */ master-bin.000001 # Query # # BEGIN master-bin.000001 # Table_map # # table_id: # (test.t1) master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F @@ -838,8 +840,10 @@ UPDATE t4,t3 SET t4.a=t3.a + bug27417(1) /* top level non-ta table */; ERROR 23000: Duplicate entry '2' for key 'PRIMARY' show binlog events from ; Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # BEGIN master-bin.000001 # Intvar # # INSERT_ID=6 master-bin.000001 # Query # # use `test`; UPDATE t4,t3 SET t4.a=t3.a + bug27417(1) /* top level non-ta table */ +master-bin.000001 # Query # # ROLLBACK select count(*) from t1 /* must be 4 */; count(*) 4 diff --git a/mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result b/mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result index 95773a247b9..1ded5c8b622 100644 --- a/mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result +++ b/mysql-test/suite/binlog/r/binlog_stm_mix_innodb_myisam.result @@ -346,7 +346,9 @@ master-bin.000001 # Query # # use `test`; INSERT INTO t1 values (3,3) master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS t2 master-bin.000001 # Query # # use `test`; CREATE TABLE t2 (a int, b int, primary key (a)) engine=innodb master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (4,4) +master-bin.000001 # Query # # BEGIN master-bin.000001 # Query # # use `test`; TRUNCATE table t2 +master-bin.000001 # Xid # # COMMIT /* XID */ master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (5,5) master-bin.000001 # Query # # use `test`; DROP TABLE t2 master-bin.000001 # Query # # use `test`; INSERT INTO t1 values (6,6) @@ -545,8 +547,10 @@ UPDATE t4,t3 SET t4.a=t3.a + bug27417(1) /* top level non-ta table */; ERROR 23000: Duplicate entry '2' for key 'PRIMARY' show binlog events from ; Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # BEGIN master-bin.000001 # Intvar # # INSERT_ID=6 master-bin.000001 # Query # # use `test`; UPDATE t4,t3 SET t4.a=t3.a + bug27417(1) /* top level non-ta table */ +master-bin.000001 # Query # # ROLLBACK /* the output must denote there is the query */; select count(*) from t1 /* must be 4 */; count(*) @@ -782,8 +786,10 @@ UPDATE t4,t3 SET t4.a=t3.a + bug27417(1) /* top level non-ta table */; ERROR 23000: Duplicate entry '2' for key 'PRIMARY' show binlog events from ; Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # BEGIN master-bin.000001 # Intvar # # INSERT_ID=6 master-bin.000001 # Query # # use `test`; UPDATE t4,t3 SET t4.a=t3.a + bug27417(1) /* top level non-ta table */ +master-bin.000001 # Query # # ROLLBACK select count(*) from t1 /* must be 4 */; count(*) 4 diff --git a/mysql-test/suite/rpl/r/rpl_innodb_mixed_dml.result b/mysql-test/suite/rpl/r/rpl_innodb_mixed_dml.result index 033f71c16b7..6c5ab43da5f 100644 --- a/mysql-test/suite/rpl/r/rpl_innodb_mixed_dml.result +++ b/mysql-test/suite/rpl/r/rpl_innodb_mixed_dml.result @@ -963,7 +963,9 @@ master-bin.000001 # Xid 1 # # master-bin.000001 # Query 1 # BEGIN master-bin.000001 # Query 1 # use `test_rpl`; INSERT INTO t1 VALUES(1, 't1, text 1') master-bin.000001 # Xid 1 # # +master-bin.000001 # Query 1 # BEGIN master-bin.000001 # Query 1 # use `test_rpl`; TRUNCATE t1 +master-bin.000001 # Xid 1 # # master-bin.000001 # Query 1 # BEGIN master-bin.000001 # Query 1 # use `test_rpl`; DELETE FROM t1 master-bin.000001 # Xid 1 # # diff --git a/mysql-test/suite/rpl/r/rpl_stm_mixing_engines.result b/mysql-test/suite/rpl/r/rpl_stm_mixing_engines.result new file mode 100644 index 00000000000..f8510b3a85e --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_stm_mixing_engines.result @@ -0,0 +1,871 @@ +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; +################################################################################### +# CONFIGURATION +################################################################################### +SET SQL_LOG_BIN=0; +CREATE TABLE nt_1 (a text, b int PRIMARY KEY, c text) ENGINE = MyISAM; +CREATE TABLE nt_2 (a text, b int PRIMARY KEY, c text) ENGINE = MyISAM; +CREATE TABLE nt_3 (a text, b int PRIMARY KEY, c text) ENGINE = MyISAM; +CREATE TABLE nt_4 (a text, b int PRIMARY KEY, c text) ENGINE = MyISAM; +CREATE TABLE tt_1 (a text, b int PRIMARY KEY, c text) ENGINE = Innodb; +CREATE TABLE tt_2 (a text, b int PRIMARY KEY, c text) ENGINE = Innodb; +CREATE TABLE tt_3 (a text, b int PRIMARY KEY, c text) ENGINE = Innodb; +CREATE TABLE tt_4 (a text, b int PRIMARY KEY, c text) ENGINE = Innodb; +SET SQL_LOG_BIN=1; +SET SQL_LOG_BIN=0; +CREATE TABLE nt_1 (a text, b int PRIMARY KEY, c text) ENGINE = MyISAM; +CREATE TABLE nt_2 (a text, b int PRIMARY KEY, c text) ENGINE = MyISAM; +CREATE TABLE nt_3 (a text, b int PRIMARY KEY, c text) ENGINE = MyISAM; +CREATE TABLE nt_4 (a text, b int PRIMARY KEY, c text) ENGINE = MyISAM; +CREATE TABLE tt_1 (a text, b int PRIMARY KEY, c text) ENGINE = Innodb; +CREATE TABLE tt_2 (a text, b int PRIMARY KEY, c text) ENGINE = Innodb; +CREATE TABLE tt_3 (a text, b int PRIMARY KEY, c text) ENGINE = Innodb; +CREATE TABLE tt_4 (a text, b int PRIMARY KEY, c text) ENGINE = Innodb; +SET SQL_LOG_BIN=1; +CREATE FUNCTION f1 () RETURNS VARCHAR(64) +BEGIN +RETURN "Testing..."; +END| +CREATE FUNCTION f2 () RETURNS VARCHAR(64) +BEGIN +RETURN f1(); +END| +CREATE PROCEDURE pc_i_tt_3 (IN x INT, IN y VARCHAR(64)) +BEGIN +INSERT INTO tt_3 VALUES (y,x,x); +END| +CREATE TRIGGER tr_i_tt_3_to_nt_3 BEFORE INSERT ON tt_3 FOR EACH ROW +BEGIN +INSERT INTO nt_3 VALUES (NEW.a, NEW.b, NEW.c); +END| +CREATE TRIGGER tr_i_nt_4_to_tt_4 BEFORE INSERT ON nt_4 FOR EACH ROW +BEGIN +INSERT INTO tt_4 VALUES (NEW.a, NEW.b, NEW.c); +END| +################################################################################### +# MIXING TRANSACTIONAL and NON-TRANSACTIONAL TABLES +################################################################################### +# +#1) "B T T C" generates in binlog the "B T T C" entries. +# +BEGIN; +INSERT INTO tt_1 VALUES ("new text 4", 4, "new text 4"); +INSERT INTO tt_2 VALUES ("new text 4", 4, "new text 4"); +COMMIT; +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text 4", 4, "new text 4") +master-bin.000001 # Query # # use `test`; INSERT INTO tt_2 VALUES ("new text 4", 4, "new text 4") +master-bin.000001 # Xid # # COMMIT /* XID */ + + + + +# +#1.e) "B T T C" with error in T generates in binlog the "B T T C" entries. +# +INSERT INTO tt_1 VALUES ("new text -2", -2, "new text -2"); +BEGIN; +INSERT INTO tt_1 VALUES ("new text -1", -1, "new text -1"), ("new text -2", -2, "new text -2"); +ERROR 23000: Duplicate entry '-2' for key 'PRIMARY' +INSERT INTO tt_2 VALUES ("new text -3", -3, "new text -3"); +COMMIT; +BEGIN; +INSERT INTO tt_2 VALUES ("new text -5", -5, "new text -5"); +INSERT INTO tt_2 VALUES ("new text -4", -4, "new text -4"), ("new text -5", -5, "new text -5"); +ERROR 23000: Duplicate entry '-5' for key 'PRIMARY' +COMMIT; +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text -2", -2, "new text -2") +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_2 VALUES ("new text -3", -3, "new text -3") +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_2 VALUES ("new text -5", -5, "new text -5") +master-bin.000001 # Xid # # COMMIT /* XID */ + + + + +# +#2) "B T T R" generates in binlog an "empty" entry. +# +BEGIN; +INSERT INTO tt_1 VALUES ("new text 5", 5, "new text 5"); +INSERT INTO tt_2 VALUES ("new text 5", 5, "new text 5"); +ROLLBACK; +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info + + + + +# +#2.e) "B T T R" with error in T generates in binlog an "empty" entry. +# +INSERT INTO tt_1 VALUES ("new text -7", -7, "new text -7"); +BEGIN; +INSERT INTO tt_1 VALUES ("new text -6", -6, "new text -6"), ("new text -7", -7, "new text -7"); +ERROR 23000: Duplicate entry '-7' for key 'PRIMARY' +INSERT INTO tt_2 VALUES ("new text -8", -8, "new text -8"); +ROLLBACK; +BEGIN; +INSERT INTO tt_2 VALUES ("new text -10", -10, "new text -10"); +INSERT INTO tt_2 VALUES ("new text -9", -9, "new text -9"), ("new text -10", -10, "new text -10"); +ERROR 23000: Duplicate entry '-10' for key 'PRIMARY' +ROLLBACK; +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text -7", -7, "new text -7") +master-bin.000001 # Xid # # COMMIT /* XID */ + + + + +# +#3) "B T N C" generates in binlog the "B T N C" entries. +# +BEGIN; +INSERT INTO tt_1 VALUES ("new text 6", 6, "new text 6"); +INSERT INTO nt_1 VALUES ("new text 6", 6, "new text 6"); +COMMIT; +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text 6", 6, "new text 6") +master-bin.000001 # Query # # use `test`; INSERT INTO nt_1 VALUES ("new text 6", 6, "new text 6") +master-bin.000001 # Xid # # COMMIT /* XID */ + + + + +# +#3.e) "B T N C" with error in either T or N generates in binlog the "B T N C" entries. +# +INSERT INTO tt_1 VALUES ("new text -12", -12, "new text -12"); +BEGIN; +INSERT INTO tt_1 VALUES ("new text -11", -11, "new text -11"), ("new text -12", -12, "new text -12"); +ERROR 23000: Duplicate entry '-12' for key 'PRIMARY' +INSERT INTO nt_1 VALUES ("new text -13", -13, "new text -13"); +COMMIT; +BEGIN; +INSERT INTO tt_1 VALUES ("new text -14", -14, "new text -14"); +INSERT INTO nt_1 VALUES ("new text -16", -16, "new text -16"); +INSERT INTO nt_1 VALUES ("new text -15", -15, "new text -15"), ("new text -16", -16, "new text -16"); +ERROR 23000: Duplicate entry '-16' for key 'PRIMARY' +COMMIT; +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text -12", -12, "new text -12") +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Query # # use `test`; INSERT INTO nt_1 VALUES ("new text -13", -13, "new text -13") +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text -14", -14, "new text -14") +master-bin.000001 # Query # # use `test`; INSERT INTO nt_1 VALUES ("new text -16", -16, "new text -16") +master-bin.000001 # Query # # use `test`; INSERT INTO nt_1 VALUES ("new text -15", -15, "new text -15"), ("new text -16", -16, "new text -16") +master-bin.000001 # Xid # # COMMIT /* XID */ + + + + +# +#4) "B T N R" generates in binlog the "B T N R" entries. +# +BEGIN; +INSERT INTO tt_1 VALUES ("new text 7", 7, "new text 7"); +INSERT INTO nt_1 VALUES ("new text 7", 7, "new text 7"); +ROLLBACK; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text 7", 7, "new text 7") +master-bin.000001 # Query # # use `test`; INSERT INTO nt_1 VALUES ("new text 7", 7, "new text 7") +master-bin.000001 # Query # # ROLLBACK + + + + +# +#4.e) "B T N R" with error in either T or N generates in binlog the "B T N R" entries. +# +INSERT INTO tt_1 VALUES ("new text -17", -17, "new text -17"); +BEGIN; +INSERT INTO tt_1 VALUES ("new text -16", -16, "new text -16"), ("new text -17", -17, "new text -17"); +ERROR 23000: Duplicate entry '-17' for key 'PRIMARY' +INSERT INTO nt_1 VALUES ("new text -18", -18, "new text -18"); +ROLLBACK; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +BEGIN; +INSERT INTO tt_1 VALUES ("new text -19", -19, "new text -19"); +INSERT INTO nt_1 VALUES ("new text -21", -21, "new text -21"); +INSERT INTO nt_1 VALUES ("new text -20", -20, "new text -20"), ("new text -21", -21, "new text -21"); +ERROR 23000: Duplicate entry '-21' for key 'PRIMARY' +ROLLBACK; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text -17", -17, "new text -17") +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Query # # use `test`; INSERT INTO nt_1 VALUES ("new text -18", -18, "new text -18") +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text -19", -19, "new text -19") +master-bin.000001 # Query # # use `test`; INSERT INTO nt_1 VALUES ("new text -21", -21, "new text -21") +master-bin.000001 # Query # # use `test`; INSERT INTO nt_1 VALUES ("new text -20", -20, "new text -20"), ("new text -21", -21, "new text -21") +master-bin.000001 # Query # # ROLLBACK + + + + +# +#5) "T" generates in binlog the "B T C" entry. +# +INSERT INTO tt_1 VALUES ("new text 8", 8, "new text 8"); +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text 8", 8, "new text 8") +master-bin.000001 # Xid # # COMMIT /* XID */ + + + + +# +#5.e) "T" with error in T generates in binlog an "empty" entry. +# +INSERT INTO tt_1 VALUES ("new text -1", -1, "new text -1"); +INSERT INTO tt_1 VALUES ("new text -1", -1, "new text -1"), ("new text -22", -22, "new text -22"); +ERROR 23000: Duplicate entry '-1' for key 'PRIMARY' +INSERT INTO tt_1 VALUES ("new text -23", -23, "new text -23"), ("new text -1", -1, "new text -1"); +ERROR 23000: Duplicate entry '-1' for key 'PRIMARY' +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text -1", -1, "new text -1") +master-bin.000001 # Xid # # COMMIT /* XID */ + + + + +# +#6) "N" generates in binlog the "N" entry. +# +INSERT INTO nt_1 VALUES ("new text 9", 9, "new text 9"); +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_1 VALUES ("new text 9", 9, "new text 9") + + + + +# +#6.e) "N" with error in N generates in binlog an empty entry if the error +# happens in the first tuple. Otherwise, generates the "N" entry and +# the error is appended. +# +INSERT INTO nt_1 VALUES ("new text -1", -1, "new text -1"); +INSERT INTO nt_1 VALUES ("new text -1", -1, "new text -1"); +ERROR 23000: Duplicate entry '-1' for key 'PRIMARY' +INSERT INTO nt_1 VALUES ("new text -24", -24, "new text -24"), ("new text -1", -1, "new text -1"); +ERROR 23000: Duplicate entry '-1' for key 'PRIMARY' +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_1 VALUES ("new text -1", -1, "new text -1") +master-bin.000001 # Query # # use `test`; INSERT INTO nt_1 VALUES ("new text -24", -24, "new text -24"), ("new text -1", -1, "new text -1") + + + + +# +#7) "M" generates in binglog the "B M C" entries. +# +DELETE FROM nt_1; +INSERT INTO nt_1 SELECT * FROM tt_1; +DELETE FROM tt_1; +INSERT INTO tt_1 SELECT * FROM nt_1; +INSERT INTO tt_3 VALUES ("new text 000", 000, ''); +INSERT INTO tt_3 VALUES("new text 100", 100, f1()); +INSERT INTO nt_4 VALUES("new text 100", 100, f1()); +INSERT INTO tt_3 VALUES("new text 200", 200, f2()); +INSERT INTO nt_4 VALUES ("new text 300", 300, ''); +INSERT INTO nt_4 VALUES ("new text 400", 400, f1()); +INSERT INTO nt_4 VALUES ("new text 500", 500, f2()); +CALL pc_i_tt_3(600, "Testing..."); +UPDATE nt_3, nt_4, tt_3, tt_4 SET nt_3.a= "new text 1", nt_4.a= "new text 1", tt_3.a= "new text 1", tt_4.a= "new text 1" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100; +UPDATE tt_3, tt_4, nt_3, nt_4 SET tt_3.a= "new text 2", tt_4.a= "new text 2", nt_3.a= "new text 2", nt_4.a = "new text 2" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100; +UPDATE tt_3, nt_3, nt_4, tt_4 SET tt_3.a= "new text 3", nt_3.a= "new text 3", nt_4.a= "new text 3", tt_4.a = "new text 3" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100; +UPDATE tt_3, nt_3, nt_4, tt_4 SET tt_3.a= "new text 4", nt_3.a= "new text 4", nt_4.a= "new text 4", tt_4.a = "new text 4" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100; +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; DELETE FROM nt_1 +master-bin.000001 # Query # # use `test`; INSERT INTO nt_1 SELECT * FROM tt_1 +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; DELETE FROM tt_1 +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 SELECT * FROM nt_1 +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_3 VALUES ("new text 000", 000, '') +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_3 VALUES("new text 100", 100, f1()) +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO nt_4 VALUES("new text 100", 100, f1()) +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_3 VALUES("new text 200", 200, f2()) +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO nt_4 VALUES ("new text 300", 300, '') +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO nt_4 VALUES ("new text 400", 400, f1()) +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO nt_4 VALUES ("new text 500", 500, f2()) +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_3 VALUES ( NAME_CONST('y',_latin1'Testing...' COLLATE 'latin1_swedish_ci'), NAME_CONST('x',600), NAME_CONST('x',600)) +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; UPDATE nt_3, nt_4, tt_3, tt_4 SET nt_3.a= "new text 1", nt_4.a= "new text 1", tt_3.a= "new text 1", tt_4.a= "new text 1" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100 +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; UPDATE tt_3, tt_4, nt_3, nt_4 SET tt_3.a= "new text 2", tt_4.a= "new text 2", nt_3.a= "new text 2", nt_4.a = "new text 2" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100 +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; UPDATE tt_3, nt_3, nt_4, tt_4 SET tt_3.a= "new text 3", nt_3.a= "new text 3", nt_4.a= "new text 3", tt_4.a = "new text 3" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100 +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; UPDATE tt_3, nt_3, nt_4, tt_4 SET tt_3.a= "new text 4", nt_3.a= "new text 4", nt_4.a= "new text 4", tt_4.a = "new text 4" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100 +master-bin.000001 # Xid # # COMMIT /* XID */ + + + + +# +#7.e) "M" with error in M generates in binglog the "B M R" entries. +# +INSERT INTO nt_3 VALUES ("new text -26", -26, ''); +SELECT * FROM tt_3; +a b c +new text 000 0 +new text 4 100 Testing... +new text 200 200 Testing... +Testing... 600 600 +INSERT INTO tt_3 VALUES ("new text -25", -25, ''), ("new text -26", -26, ''); +ERROR 23000: Duplicate entry '-26' for key 'PRIMARY' +SELECT * FROM tt_3; +a b c +new text 000 0 +new text 4 100 Testing... +new text 200 200 Testing... +Testing... 600 600 +INSERT INTO tt_4 VALUES ("new text -26", -26, ''); +SELECT * FROM nt_4; +a b c +new text 4 100 Testing... +new text 300 300 +new text 400 400 Testing... +new text 500 500 Testing... +INSERT INTO nt_4 VALUES ("new text -25", -25, ''), ("new text -26", -26, ''); +ERROR 23000: Duplicate entry '-26' for key 'PRIMARY' +SELECT * FROM nt_4; +a b c +new text 4 100 Testing... +new text 300 300 +new text 400 400 Testing... +new text 500 500 Testing... +new text -25 -25 +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_3 VALUES ("new text -26", -26, '') +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_3 VALUES ("new text -25", -25, ''), ("new text -26", -26, '') +master-bin.000001 # Query # # ROLLBACK +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_4 VALUES ("new text -26", -26, '') +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO nt_4 VALUES ("new text -25", -25, ''), ("new text -26", -26, '') +master-bin.000001 # Query # # ROLLBACK + + + + +# +#8) "B N N T C" generates in binglog the "N N B T C" entries. +# +BEGIN; +INSERT INTO nt_1 VALUES ("new text 10", 10, "new text 10"); +INSERT INTO nt_2 VALUES ("new text 10", 10, "new text 10"); +INSERT INTO tt_1 VALUES ("new text 10", 10, "new text 10"); +COMMIT; +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_1 VALUES ("new text 10", 10, "new text 10") +master-bin.000001 # Query # # use `test`; INSERT INTO nt_2 VALUES ("new text 10", 10, "new text 10") +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text 10", 10, "new text 10") +master-bin.000001 # Xid # # COMMIT /* XID */ + + + + +# +#8.e) "B N N T R" See 6.e and 9.e. +# + + + + +# +#9) "B N N T R" generates in binlog the "N N B T R" entries. +# +BEGIN; +INSERT INTO nt_1 VALUES ("new text 11", 11, "new text 11"); +INSERT INTO nt_2 VALUES ("new text 11", 11, "new text 11"); +INSERT INTO tt_1 VALUES ("new text 11", 11, "new text 11"); +ROLLBACK; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_1 VALUES ("new text 11", 11, "new text 11") +master-bin.000001 # Query # # use `test`; INSERT INTO nt_2 VALUES ("new text 11", 11, "new text 11") +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text 11", 11, "new text 11") +master-bin.000001 # Query # # ROLLBACK + + + + +# +#9.e) "B N N T R" with error in N generates in binlog the "N N B T R" entries. +# +BEGIN; +INSERT INTO nt_1 VALUES ("new text -25", -25, "new text -25"); +INSERT INTO nt_2 VALUES ("new text -25", -25, "new text -25"); +INSERT INTO nt_2 VALUES ("new text -26", -26, "new text -26"), ("new text -25", -25, "new text -25"); +ERROR 23000: Duplicate entry '-25' for key 'PRIMARY' +INSERT INTO tt_1 VALUES ("new text -27", -27, "new text -27"); +ROLLBACK; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_1 VALUES ("new text -25", -25, "new text -25") +master-bin.000001 # Query # # use `test`; INSERT INTO nt_2 VALUES ("new text -25", -25, "new text -25") +master-bin.000001 # Query # # use `test`; INSERT INTO nt_2 VALUES ("new text -26", -26, "new text -26"), ("new text -25", -25, "new text -25") +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text -27", -27, "new text -27") +master-bin.000001 # Query # # ROLLBACK + + + + +# +#10) "B N N C" generates in binglog the "N N" entries. +# +BEGIN; +INSERT INTO nt_1 VALUES ("new text 12", 12, "new text 12"); +INSERT INTO nt_2 VALUES ("new text 12", 12, "new text 12"); +COMMIT; +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_1 VALUES ("new text 12", 12, "new text 12") +master-bin.000001 # Query # # use `test`; INSERT INTO nt_2 VALUES ("new text 12", 12, "new text 12") + + + + +# +#10.e) "B N N C" See 6.e and 9.e. +# + + + + +# +#11) "B N N R" generates in binlog the "N N" entries. +# +BEGIN; +INSERT INTO nt_1 VALUES ("new text 13", 13, "new text 13"); +INSERT INTO nt_2 VALUES ("new text 13", 13, "new text 13"); +ROLLBACK; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_1 VALUES ("new text 13", 13, "new text 13") +master-bin.000001 # Query # # use `test`; INSERT INTO nt_2 VALUES ("new text 13", 13, "new text 13") + + + + +# +#11.e) "B N N R" See 6.e and 9.e. +# + + + + +# +#12) "B M T C" generates in the binlog the "B M T C" entries. +# +DELETE FROM nt_1; +BEGIN; +INSERT INTO nt_1 SELECT * FROM tt_1; +INSERT INTO tt_2 VALUES ("new text 14", 14, "new text 14"); +COMMIT; +DELETE FROM tt_1; +BEGIN; +INSERT INTO tt_1 SELECT * FROM nt_1; +INSERT INTO tt_2 VALUES ("new text 15", 15, "new text 15"); +COMMIT; +BEGIN; +INSERT INTO tt_3 VALUES ("new text 700", 700, ''); +INSERT INTO tt_1 VALUES ("new text 800", 800, ''); +COMMIT; +BEGIN; +INSERT INTO tt_3 VALUES("new text 900", 900, f1()); +INSERT INTO tt_1 VALUES ("new text 1000", 1000, ''); +COMMIT; +BEGIN; +INSERT INTO tt_3 VALUES(1100, 1100, f2()); +INSERT INTO tt_1 VALUES ("new text 1200", 1200, ''); +COMMIT; +BEGIN; +INSERT INTO nt_4 VALUES ("new text 1300", 1300, ''); +INSERT INTO tt_1 VALUES ("new text 1400", 1400, ''); +COMMIT; +BEGIN; +INSERT INTO nt_4 VALUES("new text 1500", 1500, f1()); +INSERT INTO tt_1 VALUES ("new text 1600", 1600, ''); +COMMIT; +BEGIN; +INSERT INTO nt_4 VALUES("new text 1700", 1700, f2()); +INSERT INTO tt_1 VALUES ("new text 1800", 1800, ''); +COMMIT; +BEGIN; +CALL pc_i_tt_3(1900, "Testing..."); +INSERT INTO tt_1 VALUES ("new text 2000", 2000, ''); +COMMIT; +BEGIN; +UPDATE nt_3, nt_4, tt_3, tt_4 SET nt_3.a= "new text 5", nt_4.a= "new text 5", tt_3.a= "new text 5", tt_4.a= "new text 5" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100; +INSERT INTO tt_1 VALUES ("new text 2100", 2100, ''); +COMMIT; +BEGIN; +UPDATE tt_3, tt_4, nt_3, nt_4 SET tt_3.a= "new text 6", tt_4.a= "new text 6", nt_3.a= "new text 6", nt_4.a = "new text 6" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100; +INSERT INTO tt_1 VALUES ("new text 2200", 2200, ''); +COMMIT; +BEGIN; +UPDATE tt_3, nt_3, nt_4, tt_4 SET tt_3.a= "new text 7", nt_3.a= "new text 7", nt_4.a= "new text 7", tt_4.a = "new text 7" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100; +INSERT INTO tt_1 VALUES ("new text 2300", 2300, ''); +COMMIT; +BEGIN; +UPDATE tt_3, nt_3, nt_4, tt_4 SET tt_3.a= "new text 8", nt_3.a= "new text 8", nt_4.a= "new text 8", tt_4.a = "new text 8" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100; +INSERT INTO tt_1 VALUES ("new text 2400", 2400, ''); +COMMIT; +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; DELETE FROM nt_1 +master-bin.000001 # Query # # use `test`; INSERT INTO nt_1 SELECT * FROM tt_1 +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_2 VALUES ("new text 14", 14, "new text 14") +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; DELETE FROM tt_1 +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 SELECT * FROM nt_1 +master-bin.000001 # Query # # use `test`; INSERT INTO tt_2 VALUES ("new text 15", 15, "new text 15") +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_3 VALUES ("new text 700", 700, '') +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text 800", 800, '') +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_3 VALUES("new text 900", 900, f1()) +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text 1000", 1000, '') +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_3 VALUES(1100, 1100, f2()) +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text 1200", 1200, '') +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO nt_4 VALUES ("new text 1300", 1300, '') +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text 1400", 1400, '') +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO nt_4 VALUES("new text 1500", 1500, f1()) +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text 1600", 1600, '') +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO nt_4 VALUES("new text 1700", 1700, f2()) +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text 1800", 1800, '') +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_3 VALUES ( NAME_CONST('y',_latin1'Testing...' COLLATE 'latin1_swedish_ci'), NAME_CONST('x',1900), NAME_CONST('x',1900)) +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text 2000", 2000, '') +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; UPDATE nt_3, nt_4, tt_3, tt_4 SET nt_3.a= "new text 5", nt_4.a= "new text 5", tt_3.a= "new text 5", tt_4.a= "new text 5" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100 +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text 2100", 2100, '') +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; UPDATE tt_3, tt_4, nt_3, nt_4 SET tt_3.a= "new text 6", tt_4.a= "new text 6", nt_3.a= "new text 6", nt_4.a = "new text 6" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100 +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text 2200", 2200, '') +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; UPDATE tt_3, nt_3, nt_4, tt_4 SET tt_3.a= "new text 7", nt_3.a= "new text 7", nt_4.a= "new text 7", tt_4.a = "new text 7" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100 +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text 2300", 2300, '') +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; UPDATE tt_3, nt_3, nt_4, tt_4 SET tt_3.a= "new text 8", nt_3.a= "new text 8", nt_4.a= "new text 8", tt_4.a = "new text 8" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100 +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text 2400", 2400, '') +master-bin.000001 # Xid # # COMMIT /* XID */ + + + + +# +#12.e) "B M T C" with error in M generates in the binlog the "B M T C" entries. +# +# There is a bug in the slave that needs to be fixed before enabling +# this part of the test. A bug report will be filed referencing this +# test case. +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info + + + + +# +#13) "B M T R" generates in the binlog the "B M T R" entries +# +DELETE FROM nt_1; +BEGIN; +INSERT INTO nt_1 SELECT * FROM tt_1; +INSERT INTO tt_2 VALUES ("new text 17", 17, "new text 17"); +ROLLBACK; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +DELETE FROM tt_1; +BEGIN; +INSERT INTO tt_1 SELECT * FROM nt_1; +INSERT INTO tt_2 VALUES ("new text 18", 18, "new text 18"); +ROLLBACK; +INSERT INTO tt_1 SELECT * FROM nt_1; +BEGIN; +INSERT INTO tt_3 VALUES ("new text 2500", 2500, ''); +INSERT INTO tt_1 VALUES ("new text 2600", 2600, ''); +ROLLBACK; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +BEGIN; +INSERT INTO tt_3 VALUES("new text 2700", 2700, f1()); +INSERT INTO tt_1 VALUES ("new text 2800", 2800, ''); +ROLLBACK; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +BEGIN; +INSERT INTO tt_3 VALUES(2900, 2900, f2()); +INSERT INTO tt_1 VALUES ("new text 3000", 3000, ''); +ROLLBACK; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +BEGIN; +INSERT INTO nt_4 VALUES ("new text 3100", 3100, ''); +INSERT INTO tt_1 VALUES ("new text 3200", 3200, ''); +ROLLBACK; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +BEGIN; +INSERT INTO nt_4 VALUES("new text 3300", 3300, f1()); +INSERT INTO tt_1 VALUES ("new text 3400", 3400, ''); +ROLLBACK; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +BEGIN; +INSERT INTO nt_4 VALUES("new text 3500", 3500, f2()); +INSERT INTO tt_1 VALUES ("new text 3600", 3600, ''); +ROLLBACK; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +BEGIN; +CALL pc_i_tt_3(3700, "Testing..."); +INSERT INTO tt_1 VALUES ("new text 3700", 3700, ''); +ROLLBACK; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +BEGIN; +UPDATE nt_3, nt_4, tt_3, tt_4 SET nt_3.a= "new text 9", nt_4.a= "new text 9", tt_3.a= "new text 9", tt_4.a= "new text 9" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100; +INSERT INTO tt_1 VALUES ("new text 3800", 3800, ''); +ROLLBACK; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +BEGIN; +UPDATE tt_3, tt_4, nt_3, nt_4 SET tt_3.a= "new text 10", tt_4.a= "new text 10", nt_3.a= "new text 10", nt_4.a = "new text 10" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100; +INSERT INTO tt_1 VALUES ("new text 3900", 3900, ''); +ROLLBACK; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +BEGIN; +UPDATE tt_3, nt_3, nt_4, tt_4 SET tt_3.a= "new text 11", nt_3.a= "new text 11", nt_4.a= "new text 11", tt_4.a = "new text 11" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100; +INSERT INTO tt_1 VALUES ("new text 4000", 4000, ''); +ROLLBACK; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +BEGIN; +UPDATE tt_3, nt_3, nt_4, tt_4 SET tt_3.a= "new text 12", nt_3.a= "new text 12", nt_4.a= "new text 12", tt_4.a = "new text 12" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100; +INSERT INTO tt_1 VALUES ("new text 4100", 4100, ''); +ROLLBACK; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; DELETE FROM nt_1 +master-bin.000001 # Query # # use `test`; INSERT INTO nt_1 SELECT * FROM tt_1 +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_2 VALUES ("new text 17", 17, "new text 17") +master-bin.000001 # Query # # ROLLBACK +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; DELETE FROM tt_1 +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 SELECT * FROM nt_1 +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_3 VALUES ("new text 2500", 2500, '') +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text 2600", 2600, '') +master-bin.000001 # Query # # ROLLBACK +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_3 VALUES("new text 2700", 2700, f1()) +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text 2800", 2800, '') +master-bin.000001 # Query # # ROLLBACK +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_3 VALUES(2900, 2900, f2()) +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text 3000", 3000, '') +master-bin.000001 # Query # # ROLLBACK +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO nt_4 VALUES ("new text 3100", 3100, '') +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text 3200", 3200, '') +master-bin.000001 # Query # # ROLLBACK +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO nt_4 VALUES("new text 3300", 3300, f1()) +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text 3400", 3400, '') +master-bin.000001 # Query # # ROLLBACK +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO nt_4 VALUES("new text 3500", 3500, f2()) +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text 3600", 3600, '') +master-bin.000001 # Query # # ROLLBACK +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_3 VALUES ( NAME_CONST('y',_latin1'Testing...' COLLATE 'latin1_swedish_ci'), NAME_CONST('x',3700), NAME_CONST('x',3700)) +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text 3700", 3700, '') +master-bin.000001 # Query # # ROLLBACK +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; UPDATE nt_3, nt_4, tt_3, tt_4 SET nt_3.a= "new text 9", nt_4.a= "new text 9", tt_3.a= "new text 9", tt_4.a= "new text 9" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100 +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text 3800", 3800, '') +master-bin.000001 # Query # # ROLLBACK +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; UPDATE tt_3, tt_4, nt_3, nt_4 SET tt_3.a= "new text 10", tt_4.a= "new text 10", nt_3.a= "new text 10", nt_4.a = "new text 10" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100 +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text 3900", 3900, '') +master-bin.000001 # Query # # ROLLBACK +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; UPDATE tt_3, nt_3, nt_4, tt_4 SET tt_3.a= "new text 11", nt_3.a= "new text 11", nt_4.a= "new text 11", tt_4.a = "new text 11" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100 +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text 4000", 4000, '') +master-bin.000001 # Query # # ROLLBACK +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; UPDATE tt_3, nt_3, nt_4, tt_4 SET tt_3.a= "new text 12", nt_3.a= "new text 12", nt_4.a= "new text 12", tt_4.a = "new text 12" where nt_3.b = nt_4.b and nt_4.b = tt_3.b and tt_3.b = tt_4.b and tt_4.b = 100 +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text 4100", 4100, '') +master-bin.000001 # Query # # ROLLBACK + + + + +# +#13.e) "B M T R" with error in M generates in the binlog the "B M T R" entries. +# +BEGIN; +INSERT INTO nt_3 VALUES ("new text -30", -30, ''); +INSERT INTO tt_3 VALUES ("new text -29", -29, ''), ("new text -30", -30, ''); +ERROR 23000: Duplicate entry '-30' for key 'PRIMARY' +INSERT INTO tt_1 VALUES ("new text -30", -30, ''); +ROLLBACK; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +BEGIN; +INSERT INTO tt_4 VALUES ("new text -30", -30, ''); +INSERT INTO nt_4 VALUES ("new text -29", -29, ''), ("new text -30", -30, ''); +ERROR 23000: Duplicate entry '-30' for key 'PRIMARY' +INSERT INTO tt_1 VALUES ("new text -31", -31, ''); +ROLLBACK; +Warnings: +Warning 1196 Some non-transactional changed tables couldn't be rolled back +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_3 VALUES ("new text -30", -30, '') +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_3 VALUES ("new text -29", -29, ''), ("new text -30", -30, '') +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text -30", -30, '') +master-bin.000001 # Query # # ROLLBACK +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_4 VALUES ("new text -30", -30, '') +master-bin.000001 # Query # # use `test`; INSERT INTO nt_4 VALUES ("new text -29", -29, ''), ("new text -30", -30, '') +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text -31", -31, '') +master-bin.000001 # Query # # ROLLBACK + + + + +# +#14) "B M T R" with error in M generates in the binlog the "B M T R" entries. +# +BEGIN; +INSERT INTO tt_4 VALUES ("new text -32", -32, ''); +TRUNCATE TABLE tt_4; +INSERT INTO tt_4 VALUES ("new text -33", -33, ''); +ROLLBACK; +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_4 VALUES ("new text -32", -32, '') +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; TRUNCATE TABLE tt_4 +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_4 VALUES ("new text -33", -33, '') +master-bin.000001 # Xid # # COMMIT /* XID */ +################################################################################### +# CLEAN +################################################################################### +DROP TABLE tt_1; +DROP TABLE tt_2; +DROP TABLE tt_3; +DROP TABLE tt_4; +DROP TABLE nt_1; +DROP TABLE nt_2; +DROP TABLE nt_3; +DROP TABLE nt_4; +DROP PROCEDURE pc_i_tt_3; +DROP FUNCTION f1; +DROP FUNCTION f2; diff --git a/mysql-test/suite/rpl/t/rpl_stm_mixing_engines.test b/mysql-test/suite/rpl/t/rpl_stm_mixing_engines.test new file mode 100644 index 00000000000..0097fde874a --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_stm_mixing_engines.test @@ -0,0 +1,5 @@ +--source include/have_binlog_format_statement.inc +--source include/master-slave.inc +--source include/have_innodb.inc + +--source extra/rpl_tests/rpl_mixing_engines.test diff --git a/sql/log.cc b/sql/log.cc index bb81d0c723e..282312d28e2 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1264,6 +1264,25 @@ int LOGGER::set_handlers(uint error_log_printer, return 0; } +/** + This function checks if a transactional talbe was updated by the + current statement. + + @param thd The client thread that executed the current statement. + @return + @c true if a transactional table was updated, @false otherwise. +*/ +static bool stmt_has_updated_trans_table(THD *thd) +{ + Ha_trx_info *ha_info; + + for (ha_info= thd->transaction.stmt.ha_list; ha_info; ha_info= ha_info->next()) + { + if (ha_info->is_trx_read_write() && ha_info->ht() != binlog_hton) + return (TRUE); + } + return (FALSE); +} /* Save position of binary log transaction cache. @@ -4060,7 +4079,8 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info) (binlog_trx_data*) thd_get_ha_data(thd, binlog_hton); IO_CACHE *trans_log= &trx_data->trans_log; my_off_t trans_log_pos= my_b_tell(trans_log); - if (event_info->get_cache_stmt() || trans_log_pos != 0) + if (event_info->get_cache_stmt() || trans_log_pos != 0 || + stmt_has_updated_trans_table(thd)) { DBUG_PRINT("info", ("Using trans_log: cache: %d, trans_log_pos: %lu", event_info->get_cache_stmt(), From 1759f9ecb4a8ba67804410a8902c00ebbe12545a Mon Sep 17 00:00:00 2001 From: Alfranio Correia Date: Thu, 27 Aug 2009 10:32:27 +0100 Subject: [PATCH 26/69] Post-fix for BUG#28976. Updated main.mysqlbinlog_row_trans's result file as TRUNCATE statements are wrapped in BEGIN...COMMIT. --- mysql-test/r/mysqlbinlog_row_trans.result | 34 ++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/mysqlbinlog_row_trans.result b/mysql-test/r/mysqlbinlog_row_trans.result index d0180e4a7a3..9c3348a9e76 100644 --- a/mysql-test/r/mysqlbinlog_row_trans.result +++ b/mysql-test/r/mysqlbinlog_row_trans.result @@ -215,7 +215,7 @@ COMMIT/*!*/; # at # #010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0 SET TIMESTAMP=1000000000/*!*/; -TRUNCATE TABLE t1 +BEGIN /*!*/; # at # #010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0 @@ -223,6 +223,22 @@ SET TIMESTAMP=1000000000/*!*/; TRUNCATE TABLE t1 /*!*/; # at # +#010909 4:46:40 server id 1 end_log_pos # Xid = # +COMMIT/*!*/; +# at # +#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0 +SET TIMESTAMP=1000000000/*!*/; +BEGIN +/*!*/; +# at # +#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0 +SET TIMESTAMP=1000000000/*!*/; +TRUNCATE TABLE t1 +/*!*/; +# at # +#010909 4:46:40 server id 1 end_log_pos # Xid = # +COMMIT/*!*/; +# at # #010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0 SET TIMESTAMP=1000000000/*!*/; BEGIN @@ -331,9 +347,17 @@ COMMIT/*!*/; # at # #010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0 SET TIMESTAMP=1000000000/*!*/; +BEGIN +/*!*/; +# at # +#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0 +SET TIMESTAMP=1000000000/*!*/; TRUNCATE TABLE t1 /*!*/; # at # +#010909 4:46:40 server id 1 end_log_pos # Xid = # +COMMIT/*!*/; +# at # #010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0 SET TIMESTAMP=1000000000/*!*/; TRUNCATE TABLE t2 @@ -449,9 +473,17 @@ ROLLBACK # at # #010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0 SET TIMESTAMP=1000000000/*!*/; +BEGIN +/*!*/; +# at # +#010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0 +SET TIMESTAMP=1000000000/*!*/; TRUNCATE TABLE t1 /*!*/; # at # +#010909 4:46:40 server id 1 end_log_pos # Xid = # +COMMIT/*!*/; +# at # #010909 4:46:40 server id 1 end_log_pos # Query thread_id=# exec_time=# error_code=0 SET TIMESTAMP=1000000000/*!*/; TRUNCATE TABLE t2 From 367c14b854f4afe6cfd41b9f56bf8fbf3c337b65 Mon Sep 17 00:00:00 2001 From: Sergey Glukhov Date: Thu, 27 Aug 2009 15:22:19 +0500 Subject: [PATCH 27/69] Bug#46184 Crash, SELECT ... FROM derived table procedure analyze The crash happens because select_union object is used as result set for queries which have derived tables. select_union use temporary table as data storage and if fields count exceeds 10(count of values for procedure ANALYSE()) then we get a crash on fill_record() function. mysql-test/r/analyse.result: test result mysql-test/r/subselect.result: result fix mysql-test/t/analyse.test: test case mysql-test/t/subselect.test: test fix sql/sql_yacc.yy: The crash happens because select_union object is used as result set for queries which have derived tables. select_union use temporary table as data storage and if fields count exceeds 10(count of values for procedure ANALYSE()) then we get a crash on fill_record() function. --- mysql-test/r/analyse.result | 9 ++++++--- mysql-test/r/subselect.result | 2 +- mysql-test/t/analyse.test | 10 ++++++++++ mysql-test/t/subselect.test | 2 +- sql/sql_yacc.yy | 3 ++- 5 files changed, 20 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/analyse.result b/mysql-test/r/analyse.result index 49722d5b0ab..1e3a2985f74 100644 --- a/mysql-test/r/analyse.result +++ b/mysql-test/r/analyse.result @@ -28,9 +28,7 @@ test.t1.bool N Y 1 1 0 0 1.0000 NULL ENUM('N','Y') NOT NULL test.t1.d 2002-03-03 2002-03-05 10 10 0 0 10.0000 NULL ENUM('2002-03-03','2002-03-04','2002-03-05') NOT NULL drop table t1,t2; EXPLAIN SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE(); -id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY system NULL NULL NULL NULL 1 -2 DERIVED NULL NULL NULL NULL NULL NULL NULL No tables used +ERROR HY000: Incorrect usage of PROCEDURE and subquery create table t1 (a int not null); create table t2 select * from t1 where 0=1 procedure analyse(); show create table t2; @@ -153,4 +151,9 @@ select f3 from t1 procedure analyse(1, 1); Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype test.t1.f3 5.99999 9.55555 7 7 0 0 7.77777 1.77778 FLOAT(6,5) NOT NULL drop table t1; +CREATE TABLE t1(a INT,b INT,c INT,d INT,e INT,f INT,g INT,h INT,i INT,j INT,k INT); +INSERT INTO t1 VALUES (); +SELECT * FROM (SELECT * FROM t1) d PROCEDURE ANALYSE(); +ERROR HY000: Incorrect usage of PROCEDURE and subquery +DROP TABLE t1; End of 4.1 tests diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 324a6073426..3f6e82fb57e 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -75,7 +75,7 @@ SELECT 1 FROM (SELECT 1 as a) b WHERE 1 IN (SELECT (SELECT a)); select (SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE(1)); ERROR HY000: Incorrect usage of PROCEDURE and subquery SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE((SELECT 1)); -ERROR HY000: Incorrect parameters to procedure 'ANALYSE' +ERROR HY000: Incorrect usage of PROCEDURE and subquery SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NULL; ERROR 42S22: Unknown column 'a' in 'field list' SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NOT NULL; diff --git a/mysql-test/t/analyse.test b/mysql-test/t/analyse.test index efcf5f6421c..d8466df14bf 100644 --- a/mysql-test/t/analyse.test +++ b/mysql-test/t/analyse.test @@ -14,6 +14,7 @@ create table t2 select * from t1 procedure analyse(); select * from t2; drop table t1,t2; +--error ER_WRONG_USAGE EXPLAIN SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE(); # @@ -102,4 +103,13 @@ select f2 from t1 procedure analyse(1, 1); select f3 from t1 procedure analyse(1, 1); drop table t1; +# +# Bug#46184 Crash, SELECT ... FROM derived table procedure analyze +# +CREATE TABLE t1(a INT,b INT,c INT,d INT,e INT,f INT,g INT,h INT,i INT,j INT,k INT); +INSERT INTO t1 VALUES (); +--error ER_WRONG_USAGE +SELECT * FROM (SELECT * FROM t1) d PROCEDURE ANALYSE(); +DROP TABLE t1; + --echo End of 4.1 tests diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 9d4fc9030f2..36a885350f6 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -30,7 +30,7 @@ SELECT 1 IN (SELECT 1); SELECT 1 FROM (SELECT 1 as a) b WHERE 1 IN (SELECT (SELECT a)); -- error ER_WRONG_USAGE select (SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE(1)); --- error ER_WRONG_PARAMETERS_TO_PROCEDURE +-- error ER_WRONG_USAGE SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE((SELECT 1)); -- error ER_BAD_FIELD_ERROR SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NULL; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index b38b6e96890..09a0a4b2f12 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -7334,7 +7334,8 @@ procedure_clause: MYSQL_YYABORT; } - if (&lex->select_lex != lex->current_select) + if (&lex->select_lex != lex->current_select || + lex->select_lex.get_table_list()->derived) { my_error(ER_WRONG_USAGE, MYF(0), "PROCEDURE", "subquery"); MYSQL_YYABORT; From a22c29d5e49fddf8cf55f3b1bf51e02b03696b7f Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Thu, 27 Aug 2009 14:40:42 +0300 Subject: [PATCH 28/69] Bug #46749: Segfault in add_key_fields() with outer subquery level field references This error requires a combination of factors : 1. An "impossible where" in the outermost SELECT 2. An aggregate in the outermost SELECT 3. A correlated subquery with a WHERE clause that includes an outer field reference as a top level WHERE sargable predicate When JOIN::optimize detects an "impossible WHERE" it will bail out without doing the rest of the work and initializations. It will not call make_join_statistics() as well. And make_join_statistics fills in various structures for each table referenced. When processing the result of the "impossible WHERE" the query must send a single row of data if there are aggregate functions in it. In this case the server marks all the aggregates as having received no rows and calls the relevant Item::val_xxx() method on the SELECT list. However if this SELECT list happens to contain a correlated subquery this subquery is evaluated in a normal evaluation mode. And if this correlated subquery has a reference to a field from the outermost "impossible where" SELECT the add_key_fields will mistakenly consider the outer field reference as a "local" field reference when looking for sargable predicates. But since the SELECT where the outer field reference refers to is not completely initialized due to the "impossible WHERE" in this level we'll get a NULL pointer reference. Fixed by making a better condition for discovering if a field is "local" to the SELECT level being processed. It's not enough to look for OUTER_REF_TABLE_BIT in this case since for outer references to constant tables the Item_field::used_tables() will return 0 regardless of whether the field reference is from the local SELECT or not. --- mysql-test/r/subselect.result | 28 ++++++++++++++++++++++++ mysql-test/t/subselect.test | 31 ++++++++++++++++++++++++++ sql/sql_select.cc | 41 +++++++++++++++++++++++++---------- 3 files changed, 88 insertions(+), 12 deletions(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 3f6e82fb57e..eacde19ab1c 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -4474,4 +4474,32 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY C ALL NULL NULL NULL NULL 20 Using where DROP TABLE C; # End of test for bug#45061. +# +# Bug #46749: Segfault in add_key_fields() with outer subquery level +# field references +# +CREATE TABLE t1 ( +a int, +b int, +UNIQUE (a), KEY (b) +); +INSERT INTO t1 VALUES (1,1), (2,1); +CREATE TABLE st1 like t1; +INSERT INTO st1 VALUES (1,1), (2,1); +CREATE TABLE st2 like t1; +INSERT INTO st2 VALUES (1,1), (2,1); +EXPLAIN +SELECT MAX(b), (SELECT COUNT(*) FROM st1,st2 WHERE st2.b <= t1.b) +FROM t1 +WHERE a = 230; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables +2 DEPENDENT SUBQUERY st1 index NULL a 5 NULL 2 Using index +2 DEPENDENT SUBQUERY st2 index b b 5 NULL 2 Using where; Using index +SELECT MAX(b), (SELECT COUNT(*) FROM st1,st2 WHERE st2.b <= t1.b) +FROM t1 +WHERE a = 230; +MAX(b) (SELECT COUNT(*) FROM st1,st2 WHERE st2.b <= t1.b) +NULL 0 +DROP TABLE t1, st1, st2; End of 5.0 tests. diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 36a885350f6..79918ca78a2 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -3450,4 +3450,35 @@ DROP TABLE C; --echo # End of test for bug#45061. +--echo # +--echo # Bug #46749: Segfault in add_key_fields() with outer subquery level +--echo # field references +--echo # + +CREATE TABLE t1 ( + a int, + b int, + UNIQUE (a), KEY (b) +); +INSERT INTO t1 VALUES (1,1), (2,1); + +CREATE TABLE st1 like t1; +INSERT INTO st1 VALUES (1,1), (2,1); + +CREATE TABLE st2 like t1; +INSERT INTO st2 VALUES (1,1), (2,1); + +# should have "impossible where" +EXPLAIN +SELECT MAX(b), (SELECT COUNT(*) FROM st1,st2 WHERE st2.b <= t1.b) +FROM t1 +WHERE a = 230; + +# should not crash +SELECT MAX(b), (SELECT COUNT(*) FROM st1,st2 WHERE st2.b <= t1.b) +FROM t1 +WHERE a = 230; + +DROP TABLE t1, st1, st2; + --echo End of 5.0 tests. diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 0a5706ee989..ff179c432a8 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -3207,6 +3207,28 @@ add_key_equal_fields(KEY_FIELD **key_fields, uint and_level, } } + +/** + Check if an expression is a non-outer field. + + Checks if an expression is a field and belongs to the current select. + + @param field Item expression to check + + @return boolean + @retval TRUE the expression is a local field + @retval FALSE it's something else +*/ + +inline static bool +is_local_field (Item *field) +{ + field= field->real_item(); + return field->type() == Item::FIELD_ITEM && + !((Item_field *)field)->depended_from; +} + + static void add_key_fields(JOIN *join, KEY_FIELD **key_fields, uint *and_level, COND *cond, table_map usable_tables, @@ -3282,13 +3304,12 @@ add_key_fields(JOIN *join, KEY_FIELD **key_fields, uint *and_level, { Item **values; // BETWEEN, IN, NE - if (cond_func->key_item()->real_item()->type() == Item::FIELD_ITEM && + if (is_local_field (cond_func->key_item()) && !(cond_func->used_tables() & OUTER_REF_TABLE_BIT)) { values= cond_func->arguments()+1; if (cond_func->functype() == Item_func::NE_FUNC && - cond_func->arguments()[1]->real_item()->type() == Item::FIELD_ITEM && - !(cond_func->arguments()[0]->used_tables() & OUTER_REF_TABLE_BIT)) + is_local_field (cond_func->arguments()[1])) values--; DBUG_ASSERT(cond_func->functype() != Item_func::IN_FUNC || cond_func->argument_count() != 2); @@ -3304,9 +3325,7 @@ add_key_fields(JOIN *join, KEY_FIELD **key_fields, uint *and_level, for (uint i= 1 ; i < cond_func->argument_count() ; i++) { Item_field *field_item; - if (cond_func->arguments()[i]->real_item()->type() == Item::FIELD_ITEM - && - !(cond_func->arguments()[i]->used_tables() & OUTER_REF_TABLE_BIT)) + if (is_local_field (cond_func->arguments()[i])) { field_item= (Item_field *) (cond_func->arguments()[i]->real_item()); add_key_equal_fields(key_fields, *and_level, cond_func, @@ -3322,8 +3341,7 @@ add_key_fields(JOIN *join, KEY_FIELD **key_fields, uint *and_level, bool equal_func=(cond_func->functype() == Item_func::EQ_FUNC || cond_func->functype() == Item_func::EQUAL_FUNC); - if (cond_func->arguments()[0]->real_item()->type() == Item::FIELD_ITEM && - !(cond_func->arguments()[0]->used_tables() & OUTER_REF_TABLE_BIT)) + if (is_local_field (cond_func->arguments()[0])) { add_key_equal_fields(key_fields, *and_level, cond_func, (Item_field*) (cond_func->arguments()[0])->real_item(), @@ -3331,9 +3349,8 @@ add_key_fields(JOIN *join, KEY_FIELD **key_fields, uint *and_level, cond_func->arguments()+1, 1, usable_tables, sargables); } - if (cond_func->arguments()[1]->real_item()->type() == Item::FIELD_ITEM && - cond_func->functype() != Item_func::LIKE_FUNC && - !(cond_func->arguments()[1]->used_tables() & OUTER_REF_TABLE_BIT)) + if (is_local_field (cond_func->arguments()[1]) && + cond_func->functype() != Item_func::LIKE_FUNC) { add_key_equal_fields(key_fields, *and_level, cond_func, (Item_field*) (cond_func->arguments()[1])->real_item(), @@ -3345,7 +3362,7 @@ add_key_fields(JOIN *join, KEY_FIELD **key_fields, uint *and_level, } case Item_func::OPTIMIZE_NULL: /* column_name IS [NOT] NULL */ - if (cond_func->arguments()[0]->real_item()->type() == Item::FIELD_ITEM && + if (is_local_field (cond_func->arguments()[0]) && !(cond_func->used_tables() & OUTER_REF_TABLE_BIT)) { Item *tmp=new Item_null; From 354f5f7bac16a688f8c851cbf866120871713105 Mon Sep 17 00:00:00 2001 From: Alfranio Correia Date: Thu, 27 Aug 2009 13:46:29 +0100 Subject: [PATCH 29/69] BUG#46864 Incorrect update of InnoDB table on slave when using trigger with myisam table Slave does not correctly handle "expected errors" leading to inconsistencies between the mater and slave. Specifically, when a statement changes both transactional and non-transactional tables, the transactional changes are automatically rolled back on the master but the slave ignores the error and does not roll them back thus leading to inconsistencies. To fix the problem, we automatically roll back a statement that fails on the slave but note that the transaction is not rolled back unless a "rollback" command is in the relay log file. mysql-test/extra/rpl_tests/rpl_mixing_engines.test: Enabled item 13.e which was disabled because of the bug fixed by the current and removed item 14 which was introduced by mistake. --- .../extra/rpl_tests/rpl_mixing_engines.test | 47 ++++++------------- .../suite/rpl/r/rpl_stm_mixing_engines.result | 45 +++++++++--------- sql/log_event.cc | 9 ++++ 3 files changed, 46 insertions(+), 55 deletions(-) diff --git a/mysql-test/extra/rpl_tests/rpl_mixing_engines.test b/mysql-test/extra/rpl_tests/rpl_mixing_engines.test index 73713b7998b..cbda85527f1 100644 --- a/mysql-test/extra/rpl_tests/rpl_mixing_engines.test +++ b/mysql-test/extra/rpl_tests/rpl_mixing_engines.test @@ -562,21 +562,21 @@ let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1); --echo # There is a bug in the slave that needs to be fixed before enabling --echo # this part of the test. A bug report will be filed referencing this --echo # test case. -# -#BEGIN; -#INSERT INTO nt_3 VALUES ("new text -28", -28, ''); -#--error ER_DUP_ENTRY -#INSERT INTO tt_3 VALUES ("new text -27", -27, ''), ("new text -28", -28, ''); -#INSERT INTO tt_1 VALUES ("new text -27", -27, ''); -#COMMIT; -# -#BEGIN; -#INSERT INTO tt_4 VALUES ("new text -28", -28, ''); -#--error ER_DUP_ENTRY -#INSERT INTO nt_4 VALUES ("new text -27", -27, ''), ("new text -28", -28, ''); -#INSERT INTO tt_1 VALUES ("new text -28", -28, ''); -#COMMIT; -# + +BEGIN; +INSERT INTO nt_3 VALUES ("new text -28", -28, ''); +--error ER_DUP_ENTRY +INSERT INTO tt_3 VALUES ("new text -27", -27, ''), ("new text -28", -28, ''); +INSERT INTO tt_1 VALUES ("new text -27", -27, ''); +COMMIT; + +BEGIN; +INSERT INTO tt_4 VALUES ("new text -28", -28, ''); +--error ER_DUP_ENTRY +INSERT INTO nt_4 VALUES ("new text -27", -27, ''), ("new text -28", -28, ''); +INSERT INTO tt_1 VALUES ("new text -28", -28, ''); +COMMIT; + --source include/show_binlog_events.inc --echo @@ -683,23 +683,6 @@ ROLLBACK; --source include/show_binlog_events.inc ---echo ---echo ---echo ---echo -let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1); ---echo # ---echo #14) "B M T R" with error in M generates in the binlog the "B M T R" entries. ---echo # - -BEGIN; -INSERT INTO tt_4 VALUES ("new text -32", -32, ''); -TRUNCATE TABLE tt_4; -INSERT INTO tt_4 VALUES ("new text -33", -33, ''); -ROLLBACK; - ---source include/show_binlog_events.inc - connection master; sync_slave_with_master; diff --git a/mysql-test/suite/rpl/r/rpl_stm_mixing_engines.result b/mysql-test/suite/rpl/r/rpl_stm_mixing_engines.result index f8510b3a85e..03223166f44 100644 --- a/mysql-test/suite/rpl/r/rpl_stm_mixing_engines.result +++ b/mysql-test/suite/rpl/r/rpl_stm_mixing_engines.result @@ -652,8 +652,30 @@ master-bin.000001 # Xid # # COMMIT /* XID */ # There is a bug in the slave that needs to be fixed before enabling # this part of the test. A bug report will be filed referencing this # test case. +BEGIN; +INSERT INTO nt_3 VALUES ("new text -28", -28, ''); +INSERT INTO tt_3 VALUES ("new text -27", -27, ''), ("new text -28", -28, ''); +ERROR 23000: Duplicate entry '-28' for key 'PRIMARY' +INSERT INTO tt_1 VALUES ("new text -27", -27, ''); +COMMIT; +BEGIN; +INSERT INTO tt_4 VALUES ("new text -28", -28, ''); +INSERT INTO nt_4 VALUES ("new text -27", -27, ''), ("new text -28", -28, ''); +ERROR 23000: Duplicate entry '-28' for key 'PRIMARY' +INSERT INTO tt_1 VALUES ("new text -28", -28, ''); +COMMIT; show binlog events from ; Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `test`; INSERT INTO nt_3 VALUES ("new text -28", -28, '') +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_3 VALUES ("new text -27", -27, ''), ("new text -28", -28, '') +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text -27", -27, '') +master-bin.000001 # Xid # # COMMIT /* XID */ +master-bin.000001 # Query # # BEGIN +master-bin.000001 # Query # # use `test`; INSERT INTO tt_4 VALUES ("new text -28", -28, '') +master-bin.000001 # Query # # use `test`; INSERT INTO nt_4 VALUES ("new text -27", -27, ''), ("new text -28", -28, '') +master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text -28", -28, '') +master-bin.000001 # Xid # # COMMIT /* XID */ @@ -832,29 +854,6 @@ master-bin.000001 # Query # # use `test`; INSERT INTO tt_4 VALUES ("new text -30 master-bin.000001 # Query # # use `test`; INSERT INTO nt_4 VALUES ("new text -29", -29, ''), ("new text -30", -30, '') master-bin.000001 # Query # # use `test`; INSERT INTO tt_1 VALUES ("new text -31", -31, '') master-bin.000001 # Query # # ROLLBACK - - - - -# -#14) "B M T R" with error in M generates in the binlog the "B M T R" entries. -# -BEGIN; -INSERT INTO tt_4 VALUES ("new text -32", -32, ''); -TRUNCATE TABLE tt_4; -INSERT INTO tt_4 VALUES ("new text -33", -33, ''); -ROLLBACK; -show binlog events from ; -Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 # Query # # BEGIN -master-bin.000001 # Query # # use `test`; INSERT INTO tt_4 VALUES ("new text -32", -32, '') -master-bin.000001 # Xid # # COMMIT /* XID */ -master-bin.000001 # Query # # BEGIN -master-bin.000001 # Query # # use `test`; TRUNCATE TABLE tt_4 -master-bin.000001 # Xid # # COMMIT /* XID */ -master-bin.000001 # Query # # BEGIN -master-bin.000001 # Query # # use `test`; INSERT INTO tt_4 VALUES ("new text -33", -33, '') -master-bin.000001 # Xid # # COMMIT /* XID */ ################################################################################### # CLEAN ################################################################################### diff --git a/sql/log_event.cc b/sql/log_event.cc index 375f9cf1859..0cda724b698 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -3202,6 +3202,15 @@ Default database: '%s'. Query: '%s'", DBUG_PRINT("info",("error ignored")); clear_all_errors(thd, const_cast(rli)); thd->killed= THD::NOT_KILLED; + /* + When an error is expected and matches the actual error the + slave does not report any error and by consequence changes + on transactional tables are not rolled back in the function + close_thread_tables(). For that reason, we explicitly roll + them back here. + */ + if (expected_error && expected_error == actual_error) + ha_autocommit_or_rollback(thd, TRUE); } /* If we expected a non-zero error code and get nothing and, it is a concurrency From ea06bbd2b0cc4e33b3350ef0bff25b0c1d1c2e95 Mon Sep 17 00:00:00 2001 From: Alfranio Correia Date: Thu, 27 Aug 2009 17:28:09 +0100 Subject: [PATCH 30/69] BUG#46861 Auto-closing of temporary tables broken by replicate-rewrite-db When a connection is dropped any remaining temporary table is also automatically dropped and the SQL statement of this operation is written to the binary log in order to drop such tables on the slave and keep the slave in sync. Specifically, the current code base creates the following type of statement: DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `db`.`table`; Unfortunately, appending the database to the table name in this manner circumvents the replicate-rewrite-db option (and any options that check the current database). To solve the issue, we started writing the statement to the binary as follows: use `db`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `table`; --- mysql-test/r/drop_temp_table.result | 2 +- mysql-test/r/mix_innodb_myisam_binlog.result | 2 +- mysql-test/r/rpl_drop_temp.result | 7 + mysql-test/r/rpl_rewrite_db.result | 127 +++++++++++++++ mysql-test/t/rpl_drop_temp.test | 15 +- mysql-test/t/rpl_rewrite_db-slave.opt | 2 +- mysql-test/t/rpl_rewrite_db.test | 155 +++++++++++++++++++ sql/sql_base.cc | 19 ++- 8 files changed, 315 insertions(+), 14 deletions(-) diff --git a/mysql-test/r/drop_temp_table.result b/mysql-test/r/drop_temp_table.result index 96481341bd6..ff200d09de4 100644 --- a/mysql-test/r/drop_temp_table.result +++ b/mysql-test/r/drop_temp_table.result @@ -18,5 +18,5 @@ master-bin.000001 # Query 1 # create database `drop-temp+table-test` master-bin.000001 # Query 1 # use `drop-temp+table-test`; create temporary table shortn1 (a int) master-bin.000001 # Query 1 # use `drop-temp+table-test`; create temporary table `table:name` (a int) master-bin.000001 # Query 1 # use `drop-temp+table-test`; create temporary table shortn2 (a int) -master-bin.000001 # Query 1 # use `drop-temp+table-test`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `drop-temp+table-test`.`shortn2`,`drop-temp+table-test`.`table:name`,`drop-temp+table-test`.`shortn1` +master-bin.000001 # Query 1 # use `drop-temp+table-test`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `shortn2`,`table:name`,`shortn1` drop database `drop-temp+table-test`; diff --git a/mysql-test/r/mix_innodb_myisam_binlog.result b/mysql-test/r/mix_innodb_myisam_binlog.result index eda3ff41c89..21bc6501dac 100644 --- a/mysql-test/r/mix_innodb_myisam_binlog.result +++ b/mysql-test/r/mix_innodb_myisam_binlog.result @@ -260,7 +260,7 @@ master-bin.000001 # Query # # use `test`; create table t0 (n int) master-bin.000001 # Query # # use `test`; insert t0 select * from t1 master-bin.000001 # Query # # use `test`; insert into t0 select GET_LOCK("lock1",null) master-bin.000001 # Query # # use `test`; create table t2 (n int) engine=innodb -master-bin.000001 # Query # # use `test`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `test`.`t1`,`test`.`ti` +master-bin.000001 # Query # # use `test`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `t1`,`ti` do release_lock("lock1"); drop table t0,t2; reset master; diff --git a/mysql-test/r/rpl_drop_temp.result b/mysql-test/r/rpl_drop_temp.result index 04fe094ea26..fff179d7056 100644 --- a/mysql-test/r/rpl_drop_temp.result +++ b/mysql-test/r/rpl_drop_temp.result @@ -5,8 +5,15 @@ reset slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; create database if not exists mysqltest; +use mysqltest; create temporary table mysqltest.t1 (n int); create temporary table mysqltest.t2 (n int); +select get_lock("con_temp",10); +get_lock("con_temp",10) +1 +select get_lock("con_temp",10); +get_lock("con_temp",10) +1 show status like 'Slave_open_temp_tables'; Variable_name Value Slave_open_temp_tables 0 diff --git a/mysql-test/r/rpl_rewrite_db.result b/mysql-test/r/rpl_rewrite_db.result index 1b843bffdca..46e12bc166b 100644 --- a/mysql-test/r/rpl_rewrite_db.result +++ b/mysql-test/r/rpl_rewrite_db.result @@ -90,5 +90,132 @@ a b 2 row 2 3 row 3 0 +set sql_log_bin= 0; drop database rewrite; +set sql_log_bin= 1; +set sql_log_bin= 0; drop table t1; +set sql_log_bin= 1; + +**** +**** Bug #46861 Auto-closing of temporary tables broken by replicate-rewrite-db +**** + +**** +**** Preparing the environment +**** +SET sql_log_bin= 0; +CREATE DATABASE database_master_temp_01; +CREATE DATABASE database_master_temp_02; +CREATE DATABASE database_master_temp_03; +SET sql_log_bin= 1; +SET sql_log_bin= 0; +CREATE DATABASE database_slave_temp_01; +CREATE DATABASE database_slave_temp_02; +CREATE DATABASE database_slave_temp_03; +SET sql_log_bin= 1; + +**** +**** Creating temporary tables on different databases with different connections +**** +**** con_temp_01 --> creates +**** t_01_01_temp on database_master_temp_01 +**** +**** con_temp_02 --> creates +**** t_01_01_temp on database_master_temp_01 +**** t_02_01_temp, t_02_02_temp on database_master_temp_02 +**** +**** con_temp_02 --> creates +**** t_01_01_temp on database_master_temp_01 +**** t_02_01_temp, t_02_02_temp on database_master_temp_02 +**** t_03_01_temp, t_03_02_temp, t_03_03_temp on database_master_temp_03 +**** + +con_temp_01 + +USE database_master_temp_01; +CREATE TEMPORARY TABLE t_01_01_temp(a int); +INSERT INTO t_01_01_temp VALUES(1); + +con_temp_02 + +USE database_master_temp_01; +CREATE TEMPORARY TABLE t_01_01_temp(a int); +INSERT INTO t_01_01_temp VALUES(1); +USE database_master_temp_02; +CREATE TEMPORARY TABLE t_02_01_temp(a int); +INSERT INTO t_02_01_temp VALUES(1); +CREATE TEMPORARY TABLE t_02_02_temp(a int); +INSERT INTO t_02_02_temp VALUES(1); + +con_temp_03 + +USE database_master_temp_01; +CREATE TEMPORARY TABLE t_01_01_temp(a int); +INSERT INTO t_01_01_temp VALUES(1); +USE database_master_temp_02; +CREATE TEMPORARY TABLE t_02_01_temp(a int); +INSERT INTO t_02_01_temp VALUES(1); +CREATE TEMPORARY TABLE t_02_02_temp(a int); +INSERT INTO t_02_02_temp VALUES(1); +USE database_master_temp_03; +CREATE TEMPORARY TABLE t_03_01_temp(a int); +INSERT INTO t_03_01_temp VALUES(1); +CREATE TEMPORARY TABLE t_03_02_temp(a int); +INSERT INTO t_03_02_temp VALUES(1); +CREATE TEMPORARY TABLE t_03_03_temp(a int); +INSERT INTO t_03_03_temp VALUES(1); + +**** Dropping the connections +**** We want to SHOW BINLOG EVENTS, to know what was logged. But there is no +**** guarantee that logging of the terminated con1 has been done yet.a To be +**** sure that logging has been done, we use a user lock. + +show status like 'Slave_open_temp_tables'; +Variable_name Value +Slave_open_temp_tables 10 +select get_lock("con_01",10); +get_lock("con_01",10) +1 +select get_lock("con_01",10); +get_lock("con_01",10) +1 +select get_lock("con_02",10); +get_lock("con_02",10) +1 +select get_lock("con_02",10); +get_lock("con_02",10) +1 +select get_lock("con_03",10); +get_lock("con_03",10) +1 +select get_lock("con_03",10); +get_lock("con_03",10) +1 + +**** Checking the binary log and temporary tables + +show status like 'Slave_open_temp_tables'; +Variable_name Value +Slave_open_temp_tables 0 +show binlog events from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Query # # use `database_master_temp_01`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `t_01_01_temp` +master-bin.000001 # Query # # use `database_master_temp_02`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `t_02_02_temp`,`t_02_01_temp` +master-bin.000001 # Query # # use `database_master_temp_01`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `t_01_01_temp` +master-bin.000001 # Query # # use `database_master_temp_03`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `t_03_03_temp`,`t_03_02_temp`,`t_03_01_temp` +master-bin.000001 # Query # # use `database_master_temp_02`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `t_02_02_temp`,`t_02_01_temp` +master-bin.000001 # Query # # use `database_master_temp_01`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `t_01_01_temp` +**** +**** Cleaning up the test case +**** +SET sql_log_bin= 0; +DROP DATABASE database_master_temp_01; +DROP DATABASE database_master_temp_02; +DROP DATABASE database_master_temp_03; +SET sql_log_bin= 1; +SET sql_log_bin= 0; +DROP DATABASE database_slave_temp_01; +DROP DATABASE database_slave_temp_02; +DROP DATABASE database_slave_temp_03; +SET sql_log_bin= 1; diff --git a/mysql-test/t/rpl_drop_temp.test b/mysql-test/t/rpl_drop_temp.test index 55a4e741d7c..c22bcbe63d0 100644 --- a/mysql-test/t/rpl_drop_temp.test +++ b/mysql-test/t/rpl_drop_temp.test @@ -3,15 +3,22 @@ source include/master-slave.inc; create database if not exists mysqltest; --enable_warnings +connect (con_temp,127.0.0.1,root,,test,$MASTER_MYPORT,); + +connection con_temp; +use mysqltest; create temporary table mysqltest.t1 (n int); create temporary table mysqltest.t2 (n int); -sync_slave_with_master; +select get_lock("con_temp",10); + connection master; -disconnect master; +disconnect con_temp; +select get_lock("con_temp",10); +sync_slave_with_master; + connection slave; ---real_sleep 3 # time for DROP to be written show status like 'Slave_open_temp_tables'; -connection default; +connection master; drop database mysqltest; # End of 4.1 tests diff --git a/mysql-test/t/rpl_rewrite_db-slave.opt b/mysql-test/t/rpl_rewrite_db-slave.opt index a462ad19ba0..290b92e0a3e 100644 --- a/mysql-test/t/rpl_rewrite_db-slave.opt +++ b/mysql-test/t/rpl_rewrite_db-slave.opt @@ -1 +1 @@ -"--replicate-rewrite-db=test->rewrite" "--replicate-rewrite-db=mysqltest1->test" +"--replicate-rewrite-db=test->rewrite" "--replicate-rewrite-db=mysqltest1->test" "--replicate-rewrite-db=database_master_temp_01->database_slave_temp_01" "--replicate-rewrite-db=database_master_temp_02->database_slave_temp_02" "--replicate-rewrite-db=database_master_temp_03->database_slave_temp_03" diff --git a/mysql-test/t/rpl_rewrite_db.test b/mysql-test/t/rpl_rewrite_db.test index 6b8624aff39..a9742f252be 100644 --- a/mysql-test/t/rpl_rewrite_db.test +++ b/mysql-test/t/rpl_rewrite_db.test @@ -73,9 +73,164 @@ connection slave; # The empty line last comes from the end line field in the file select * from rewrite.t1; +set sql_log_bin= 0; drop database rewrite; +set sql_log_bin= 1; connection master; +set sql_log_bin= 0; drop table t1; +set sql_log_bin= 1; # End of 4.1 tests + +--echo +--echo **** +--echo **** Bug #46861 Auto-closing of temporary tables broken by replicate-rewrite-db +--echo **** +--echo + +--echo **** +--echo **** Preparing the environment +--echo **** +connection master; + +connect (con_temp_03,127.0.0.1,root,,test,$MASTER_MYPORT,); +connect (con_temp_02,127.0.0.1,root,,test,$MASTER_MYPORT,); +connect (con_temp_01,127.0.0.1,root,,test,$MASTER_MYPORT,); + +connection master; +SET sql_log_bin= 0; +CREATE DATABASE database_master_temp_01; +CREATE DATABASE database_master_temp_02; +CREATE DATABASE database_master_temp_03; +SET sql_log_bin= 1; + +connection slave; +SET sql_log_bin= 0; +CREATE DATABASE database_slave_temp_01; +CREATE DATABASE database_slave_temp_02; +CREATE DATABASE database_slave_temp_03; +SET sql_log_bin= 1; + +--echo +--echo **** +--echo **** Creating temporary tables on different databases with different connections +--echo **** +--echo **** con_temp_01 --> creates +--echo **** t_01_01_temp on database_master_temp_01 +--echo **** +--echo **** con_temp_02 --> creates +--echo **** t_01_01_temp on database_master_temp_01 +--echo **** t_02_01_temp, t_02_02_temp on database_master_temp_02 +--echo **** +--echo **** con_temp_02 --> creates +--echo **** t_01_01_temp on database_master_temp_01 +--echo **** t_02_01_temp, t_02_02_temp on database_master_temp_02 +--echo **** t_03_01_temp, t_03_02_temp, t_03_03_temp on database_master_temp_03 +--echo **** + +--echo +--echo con_temp_01 +--echo +connection con_temp_01; +USE database_master_temp_01; +CREATE TEMPORARY TABLE t_01_01_temp(a int); +INSERT INTO t_01_01_temp VALUES(1); + +--echo +--echo con_temp_02 +--echo +connection con_temp_02; +USE database_master_temp_01; +CREATE TEMPORARY TABLE t_01_01_temp(a int); +INSERT INTO t_01_01_temp VALUES(1); +USE database_master_temp_02; +CREATE TEMPORARY TABLE t_02_01_temp(a int); +INSERT INTO t_02_01_temp VALUES(1); +CREATE TEMPORARY TABLE t_02_02_temp(a int); +INSERT INTO t_02_02_temp VALUES(1); + +--echo +--echo con_temp_03 +--echo +connection con_temp_03; +USE database_master_temp_01; +CREATE TEMPORARY TABLE t_01_01_temp(a int); +INSERT INTO t_01_01_temp VALUES(1); +USE database_master_temp_02; +CREATE TEMPORARY TABLE t_02_01_temp(a int); +INSERT INTO t_02_01_temp VALUES(1); +CREATE TEMPORARY TABLE t_02_02_temp(a int); +INSERT INTO t_02_02_temp VALUES(1); +USE database_master_temp_03; +CREATE TEMPORARY TABLE t_03_01_temp(a int); +INSERT INTO t_03_01_temp VALUES(1); +CREATE TEMPORARY TABLE t_03_02_temp(a int); +INSERT INTO t_03_02_temp VALUES(1); +CREATE TEMPORARY TABLE t_03_03_temp(a int); +INSERT INTO t_03_03_temp VALUES(1); + +--echo +--echo **** Dropping the connections +--echo **** We want to SHOW BINLOG EVENTS, to know what was logged. But there is no +--echo **** guarantee that logging of the terminated con1 has been done yet.a To be +--echo **** sure that logging has been done, we use a user lock. +--echo +connection master; +sync_slave_with_master; +connection slave; +show status like 'Slave_open_temp_tables'; + +connection master; +let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1); +connection con_temp_01; +select get_lock("con_01",10); +connection master; +disconnect con_temp_01; +select get_lock("con_01",10); + +connection con_temp_02; +select get_lock("con_02",10); +connection master; +disconnect con_temp_02; +select get_lock("con_02",10); + +connection con_temp_03; +select get_lock("con_03",10); +connection master; +disconnect con_temp_03; +select get_lock("con_03",10); + +--echo +--echo **** Checking the binary log and temporary tables +--echo +connection master; +sync_slave_with_master; +connection slave; +show status like 'Slave_open_temp_tables'; + +connection master; +--source include/show_binlog_events.inc + +--echo **** +--echo **** Cleaning up the test case +--echo **** +connection master; +SET sql_log_bin= 0; +DROP DATABASE database_master_temp_01; +DROP DATABASE database_master_temp_02; +DROP DATABASE database_master_temp_03; +SET sql_log_bin= 1; + +connection slave; +SET sql_log_bin= 0; +DROP DATABASE database_slave_temp_01; +DROP DATABASE database_slave_temp_02; +DROP DATABASE database_slave_temp_03; +SET sql_log_bin= 1; + +connection master; +sync_slave_with_master; + +# end of 5.0 tests diff --git a/sql/sql_base.cc b/sql/sql_base.cc index d969c837891..bc9aa50cb82 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -769,19 +769,23 @@ void close_temporary_tables(THD *thd) { /* Set pseudo_thread_id to be that of the processed table */ thd->variables.pseudo_thread_id= tmpkeyval(thd, table); - /* Loop forward through all tables within the sublist of - common pseudo_thread_id to create single DROP query */ + String db; + db.append(table->s->db); + /* Loop forward through all tables that belong to a common database + within the sublist of common pseudo_thread_id to create single + DROP query + */ for (s_query.length(stub_len); table && is_user_table(table) && - tmpkeyval(thd, table) == thd->variables.pseudo_thread_id; + tmpkeyval(thd, table) == thd->variables.pseudo_thread_id && + strlen(table->s->db) == db.length() && + strcmp(table->s->db, db.ptr()) == 0; table= next) { /* - We are going to add 4 ` around the db/table names and possible more - due to special characters in the names + We are going to add ` around the table names and possible more + due to special characters */ - append_identifier(thd, &s_query, table->s->db, strlen(table->s->db)); - s_query.q_append('.'); append_identifier(thd, &s_query, table->s->table_name, strlen(table->s->table_name)); s_query.q_append(','); @@ -794,6 +798,7 @@ void close_temporary_tables(THD *thd) Query_log_event qinfo(thd, s_query.ptr(), s_query.length() - 1 /* to remove trailing ',' */, 0, FALSE); + qinfo.db= db.ptr(); thd->variables.character_set_client= cs_save; /* Imagine the thread had created a temp table, then was doing a SELECT, and From 169f7da04c4ffc43355d5a632a8013bc4caea39b Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Fri, 28 Aug 2009 12:06:59 -0300 Subject: [PATCH 31/69] Fix for a few assorted compiler warnings. client/mysql.cc: Remove leading whitespace. Remove extra text after #else directive. client/mysqldump.c: Function does not take a parameter. mysys/array.c: buffer is a uchar pointer. sql/item.cc: Assert if it should not happen. storage/myisam/mi_check.c: Cast to expected type. This is probably a bug, but it is casted in a similar way in another part of the code. storage/ndb/include/mgmapi/ndb_logevent.h: Apply fix from cluster team. tests/mysql_client_test.c: Remove extraneous slash. --- client/mysql.cc | 18 +- client/mysqldump.c | 6 +- mysys/array.c | 2 +- sql/item.cc | 3 +- storage/myisam/mi_check.c | 2 +- storage/ndb/include/mgmapi/ndb_logevent.h | 683 +++++++++++----------- tests/mysql_client_test.c | 2 +- 7 files changed, 371 insertions(+), 345 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index dc7022a0ffa..1491ff1b059 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -86,7 +86,7 @@ extern "C" { #endif #undef bcmp // Fix problem with new readline -#if defined( __WIN__) +#if defined(__WIN__) #include #elif !defined(__NETWARE__) #include @@ -106,7 +106,7 @@ extern "C" { #define cmp_database(cs,A,B) strcmp((A),(B)) #endif -#if !defined( __WIN__) && !defined(__NETWARE__) && !defined(THREAD) +#if !defined(__WIN__) && !defined(__NETWARE__) && !defined(THREAD) #define USE_POPEN #endif @@ -1862,7 +1862,7 @@ static int read_and_execute(bool interactive) if (opt_outfile && glob_buffer.is_empty()) fflush(OUTFILE); -#if defined( __WIN__) || defined(__NETWARE__) +#if defined(__WIN__) || defined(__NETWARE__) tee_fputs(prompt, stdout); #if defined(__NETWARE__) line=fgets(linebuffer, sizeof(linebuffer)-1, stdin); @@ -1873,7 +1873,7 @@ static int read_and_execute(bool interactive) if (p != NULL) *p = '\0'; } -#else defined(__WIN__) +#else if (!tmpbuf.is_alloced()) tmpbuf.alloc(65535); tmpbuf.length(0); @@ -1899,7 +1899,7 @@ static int read_and_execute(bool interactive) if (opt_outfile) fputs(prompt, OUTFILE); line= readline(prompt); -#endif /* defined( __WIN__) || defined(__NETWARE__) */ +#endif /* defined(__WIN__) || defined(__NETWARE__) */ /* When Ctrl+d or Ctrl+z is pressed, the line may be NULL on some OS @@ -1947,10 +1947,10 @@ static int read_and_execute(bool interactive) } } -#if defined( __WIN__) || defined(__NETWARE__) +#if defined(__WIN__) || defined(__NETWARE__) buffer.free(); #endif -#if defined( __WIN__) +#if defined(__WIN__) tmpbuf.free(); #endif @@ -4602,7 +4602,7 @@ void tee_putc(int c, FILE *file) putc(c, OUTFILE); } -#if defined( __WIN__) || defined(__NETWARE__) +#if defined(__WIN__) || defined(__NETWARE__) #include #else #include @@ -4614,7 +4614,7 @@ void tee_putc(int c, FILE *file) static ulong start_timer(void) { -#if defined( __WIN__) || defined(__NETWARE__) +#if defined(__WIN__) || defined(__NETWARE__) return clock(); #else struct tms tms_tmp; diff --git a/client/mysqldump.c b/client/mysqldump.c index cac27424d6e..e9e3124b9cb 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -5008,7 +5008,7 @@ int main(int argc, char **argv) exit_code= get_options(&argc, &argv); if (exit_code) { - free_resources(0); + free_resources(); exit(exit_code); } @@ -5016,14 +5016,14 @@ int main(int argc, char **argv) { if(!(stderror_file= freopen(log_error_file, "a+", stderr))) { - free_resources(0); + free_resources(); exit(EX_MYSQLERR); } } if (connect_to_db(current_host, current_user, opt_password)) { - free_resources(0); + free_resources(); exit(EX_MYSQLERR); } if (!path) diff --git a/mysys/array.c b/mysys/array.c index b65bd28616d..a1c49c2589d 100644 --- a/mysys/array.c +++ b/mysys/array.c @@ -67,7 +67,7 @@ my_bool init_dynamic_array2(DYNAMIC_ARRAY *array, uint element_size, Since the dynamic array is usable even if allocation fails here malloc should not throw an error */ - if (!(array->buffer= (char*) my_malloc_ci(element_size*init_alloc, MYF(0)))) + if (!(array->buffer= (uchar*) my_malloc_ci(element_size*init_alloc, MYF(0)))) array->max_element=0; DBUG_RETURN(FALSE); } diff --git a/sql/item.cc b/sql/item.cc index 0ebb1d61a28..c1ba6fe77a3 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -3305,8 +3305,7 @@ Item_copy *Item_copy::create (Item *item) new Item_copy_uint (item) : new Item_copy_int (item); case DECIMAL_RESULT: return new Item_copy_decimal (item); - - case ROW_RESULT: + default: DBUG_ASSERT (0); } /* should not happen */ diff --git a/storage/myisam/mi_check.c b/storage/myisam/mi_check.c index 535b4f7f537..1cb0613331d 100644 --- a/storage/myisam/mi_check.c +++ b/storage/myisam/mi_check.c @@ -1549,7 +1549,7 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info, if (!param->using_global_keycache) VOID(init_key_cache(dflt_key_cache, param->key_cache_block_size, - param->use_buffers, 0, 0)); + (size_t) param->use_buffers, 0, 0)); if (init_io_cache(¶m->read_cache,info->dfile, (uint) param->read_buffer_length, diff --git a/storage/ndb/include/mgmapi/ndb_logevent.h b/storage/ndb/include/mgmapi/ndb_logevent.h index 70691f6fd28..519c13b2ca9 100644 --- a/storage/ndb/include/mgmapi/ndb_logevent.h +++ b/storage/ndb/include/mgmapi/ndb_logevent.h @@ -272,6 +272,300 @@ extern "C" { #endif }; + struct ndb_logevent_Connected { + unsigned node; + }; + + struct ndb_logevent_Disconnected { + unsigned node; + }; + + struct ndb_logevent_CommunicationClosed { + unsigned node; + }; + + struct ndb_logevent_CommunicationOpened { + unsigned node; + }; + + struct ndb_logevent_ConnectedApiVersion { + unsigned node; + unsigned version; + }; + + /* CHECKPOINT */ + struct ndb_logevent_GlobalCheckpointStarted { + unsigned gci; + }; + struct ndb_logevent_GlobalCheckpointCompleted { + unsigned gci; + }; + struct ndb_logevent_LocalCheckpointStarted { + unsigned lci; + unsigned keep_gci; + unsigned restore_gci; + }; + struct ndb_logevent_LocalCheckpointCompleted { + unsigned lci; + }; + struct ndb_logevent_LCPStoppedInCalcKeepGci { + unsigned data; + }; + struct ndb_logevent_LCPFragmentCompleted { + unsigned node; + unsigned table_id; + unsigned fragment_id; + }; + struct ndb_logevent_UndoLogBlocked { + unsigned acc_count; + unsigned tup_count; + }; + + /* STARTUP */ + struct ndb_logevent_NDBStartStarted { + unsigned version; + }; + struct ndb_logevent_NDBStartCompleted { + unsigned version; + }; + struct ndb_logevent_STTORRYRecieved { + }; + struct ndb_logevent_StartPhaseCompleted { + unsigned phase; + unsigned starttype; + }; + struct ndb_logevent_CM_REGCONF { + unsigned own_id; + unsigned president_id; + unsigned dynamic_id; + }; + struct ndb_logevent_CM_REGREF { + unsigned own_id; + unsigned other_id; + unsigned cause; + }; + struct ndb_logevent_FIND_NEIGHBOURS { + unsigned own_id; + unsigned left_id; + unsigned right_id; + unsigned dynamic_id; + }; + struct ndb_logevent_NDBStopStarted { + unsigned stoptype; + }; + struct ndb_logevent_NDBStopCompleted { + unsigned action; + unsigned signum; + }; + struct ndb_logevent_NDBStopForced { + unsigned action; + unsigned signum; + unsigned error; + unsigned sphase; + unsigned extra; + }; + struct ndb_logevent_NDBStopAborted { + }; + struct ndb_logevent_StartREDOLog { + unsigned node; + unsigned keep_gci; + unsigned completed_gci; + unsigned restorable_gci; + }; + struct ndb_logevent_StartLog { + unsigned log_part; + unsigned start_mb; + unsigned stop_mb; + unsigned gci; + }; + struct ndb_logevent_UNDORecordsExecuted { + unsigned block; + unsigned data1; + unsigned data2; + unsigned data3; + unsigned data4; + unsigned data5; + unsigned data6; + unsigned data7; + unsigned data8; + unsigned data9; + unsigned data10; + }; + + /* NODERESTART */ + struct ndb_logevent_NR_CopyDict { + }; + struct ndb_logevent_NR_CopyDistr { + }; + struct ndb_logevent_NR_CopyFragsStarted { + unsigned dest_node; + }; + struct ndb_logevent_NR_CopyFragDone { + unsigned dest_node; + unsigned table_id; + unsigned fragment_id; + }; + struct ndb_logevent_NR_CopyFragsCompleted { + unsigned dest_node; + }; + + struct ndb_logevent_NodeFailCompleted { + unsigned block; /* 0 = all */ + unsigned failed_node; + unsigned completing_node; /* 0 = all */ + }; + struct ndb_logevent_NODE_FAILREP { + unsigned failed_node; + unsigned failure_state; + }; + struct ndb_logevent_ArbitState { + unsigned code; /* code & state << 16 */ + unsigned arbit_node; + unsigned ticket_0; + unsigned ticket_1; + /* TODO */ + }; + struct ndb_logevent_ArbitResult { + unsigned code; /* code & state << 16 */ + unsigned arbit_node; + unsigned ticket_0; + unsigned ticket_1; + /* TODO */ + }; + struct ndb_logevent_GCP_TakeoverStarted { + }; + struct ndb_logevent_GCP_TakeoverCompleted { + }; + struct ndb_logevent_LCP_TakeoverStarted { + }; + struct ndb_logevent_LCP_TakeoverCompleted { + unsigned state; + }; + + /* STATISTIC */ + struct ndb_logevent_TransReportCounters { + unsigned trans_count; + unsigned commit_count; + unsigned read_count; + unsigned simple_read_count; + unsigned write_count; + unsigned attrinfo_count; + unsigned conc_op_count; + unsigned abort_count; + unsigned scan_count; + unsigned range_scan_count; + }; + struct ndb_logevent_OperationReportCounters { + unsigned ops; + }; + struct ndb_logevent_TableCreated { + unsigned table_id; + }; + struct ndb_logevent_JobStatistic { + unsigned mean_loop_count; + }; + struct ndb_logevent_SendBytesStatistic { + unsigned to_node; + unsigned mean_sent_bytes; + }; + struct ndb_logevent_ReceiveBytesStatistic { + unsigned from_node; + unsigned mean_received_bytes; + }; + struct ndb_logevent_MemoryUsage { + int gth; + /* union is for compatibility backward. + * page_size_kb member variable should be removed in the future + */ + union { + unsigned page_size_kb; + unsigned page_size_bytes; + }; + unsigned pages_used; + unsigned pages_total; + unsigned block; + }; + + /* ERROR */ + struct ndb_logevent_TransporterError { + unsigned to_node; + unsigned code; + }; + struct ndb_logevent_TransporterWarning { + unsigned to_node; + unsigned code; + }; + struct ndb_logevent_MissedHeartbeat { + unsigned node; + unsigned count; + }; + struct ndb_logevent_DeadDueToHeartbeat { + unsigned node; + }; + struct ndb_logevent_WarningEvent { + /* TODO */ + }; + + /* INFO */ + struct ndb_logevent_SentHeartbeat { + unsigned node; + }; + struct ndb_logevent_CreateLogBytes { + unsigned node; + }; + struct ndb_logevent_InfoEvent { + /* TODO */ + }; + struct ndb_logevent_EventBufferStatus { + unsigned usage; + unsigned alloc; + unsigned max; + unsigned apply_gci_l; + unsigned apply_gci_h; + unsigned latest_gci_l; + unsigned latest_gci_h; + }; + + /** Log event data for @ref NDB_LE_BackupStarted */ + struct ndb_logevent_BackupStarted { + unsigned starting_node; + unsigned backup_id; + }; + /** Log event data @ref NDB_LE_BackupFailedToStart */ + struct ndb_logevent_BackupFailedToStart { + unsigned starting_node; + unsigned error; + }; + /** Log event data @ref NDB_LE_BackupCompleted */ + struct ndb_logevent_BackupCompleted { + unsigned starting_node; + unsigned backup_id; + unsigned start_gci; + unsigned stop_gci; + unsigned n_records; + unsigned n_log_records; + unsigned n_bytes; + unsigned n_log_bytes; + }; + /** Log event data @ref NDB_LE_BackupAborted */ + struct ndb_logevent_BackupAborted { + unsigned starting_node; + unsigned backup_id; + unsigned error; + }; + /** Log event data @ref NDB_LE_SingleUser */ + struct ndb_logevent_SingleUser { + unsigned type; + unsigned node_id; + }; + /** Log even data @ref NDB_LE_StartReport */ + struct ndb_logevent_StartReport { + unsigned report_type; + unsigned remaining_time; + unsigned bitmask_size; + unsigned bitmask_data[1]; + }; + /** * Structure to store and retrieve log event information. * @see @ref secSLogEvents @@ -305,354 +599,87 @@ extern "C" { */ union { /* CONNECT */ - /** Log event specific data for for corresponding NDB_LE_ log event */ - struct { - unsigned node; - } Connected; - - /** Log event specific data for for corresponding NDB_LE_ log event */ - struct { - unsigned node; - } Disconnected; - - /** Log event specific data for for corresponding NDB_LE_ log event */ - struct { - unsigned node; - } CommunicationClosed; - - /** Log event specific data for for corresponding NDB_LE_ log event */ - struct { - unsigned node; - } CommunicationOpened; - - /** Log event specific data for for corresponding NDB_LE_ log event */ - struct { - unsigned node; - unsigned version; - } ConnectedApiVersion; + struct ndb_logevent_Connected Connected; + struct ndb_logevent_Disconnected Disconnected; + struct ndb_logevent_CommunicationClosed CommunicationClosed; + struct ndb_logevent_CommunicationOpened CommunicationOpened; + struct ndb_logevent_ConnectedApiVersion ConnectedApiVersion; /* CHECKPOINT */ - /** Log event specific data for for corresponding NDB_LE_ log event */ - struct { - unsigned gci; - } GlobalCheckpointStarted; - /** Log event specific data for for corresponding NDB_LE_ log event */ - struct { - unsigned gci; - } GlobalCheckpointCompleted; - /** Log event specific data for for corresponding NDB_LE_ log event */ - struct { - unsigned lci; - unsigned keep_gci; - unsigned restore_gci; - } LocalCheckpointStarted; - /** Log event specific data for for corresponding NDB_LE_ log event */ - struct { - unsigned lci; - } LocalCheckpointCompleted; - /** Log event specific data for for corresponding NDB_LE_ log event */ - struct { - unsigned data; - } LCPStoppedInCalcKeepGci; - /** Log event specific data for for corresponding NDB_LE_ log event */ - struct { - unsigned node; - unsigned table_id; - unsigned fragment_id; - } LCPFragmentCompleted; - /** Log event specific data for for corresponding NDB_LE_ log event */ - struct { - unsigned acc_count; - unsigned tup_count; - } UndoLogBlocked; + struct ndb_logevent_GlobalCheckpointStarted GlobalCheckpointStarted; + struct ndb_logevent_GlobalCheckpointCompleted GlobalCheckpointCompleted; + struct ndb_logevent_LocalCheckpointStarted LocalCheckpointStarted; + struct ndb_logevent_LocalCheckpointCompleted LocalCheckpointCompleted; + struct ndb_logevent_LCPStoppedInCalcKeepGci LCPStoppedInCalcKeepGci; + struct ndb_logevent_LCPFragmentCompleted LCPFragmentCompleted; + struct ndb_logevent_UndoLogBlocked UndoLogBlocked; /* STARTUP */ - /** Log event specific data for for corresponding NDB_LE_ log event */ - struct { - unsigned version; - } NDBStartStarted; - /** Log event specific data for for corresponding NDB_LE_ log event */ - struct { - unsigned version; - } NDBStartCompleted; - /** Log event specific data for for corresponding NDB_LE_ log event */ - struct { - } STTORRYRecieved; - /** Log event specific data for for corresponding NDB_LE_ log event */ - struct { - unsigned phase; - unsigned starttype; - } StartPhaseCompleted; - /** Log event specific data for for corresponding NDB_LE_ log event */ - struct { - unsigned own_id; - unsigned president_id; - unsigned dynamic_id; - } CM_REGCONF; - /** Log event specific data for for corresponding NDB_LE_ log event */ - struct { - unsigned own_id; - unsigned other_id; - unsigned cause; - } CM_REGREF; - /** Log event specific data for for corresponding NDB_LE_ log event */ - struct { - unsigned own_id; - unsigned left_id; - unsigned right_id; - unsigned dynamic_id; - } FIND_NEIGHBOURS; - /** Log event specific data for for corresponding NDB_LE_ log event */ - struct { - unsigned stoptype; - } NDBStopStarted; - /** Log event specific data for for corresponding NDB_LE_ log event */ - struct { - unsigned action; - unsigned signum; - } NDBStopCompleted; - /** Log event specific data for for corresponding NDB_LE_ log event */ - struct { - unsigned action; - unsigned signum; - unsigned error; - unsigned sphase; - unsigned extra; - } NDBStopForced; - /** Log event specific data for for corresponding NDB_LE_ log event */ - struct { - } NDBStopAborted; - /** Log event specific data for for corresponding NDB_LE_ log event */ - struct { - unsigned node; - unsigned keep_gci; - unsigned completed_gci; - unsigned restorable_gci; - } StartREDOLog; - /** Log event specific data for for corresponding NDB_LE_ log event */ - struct { - unsigned log_part; - unsigned start_mb; - unsigned stop_mb; - unsigned gci; - } StartLog; - /** Log event specific data for for corresponding NDB_LE_ log event */ - struct { - unsigned block; - unsigned data1; - unsigned data2; - unsigned data3; - unsigned data4; - unsigned data5; - unsigned data6; - unsigned data7; - unsigned data8; - unsigned data9; - unsigned data10; - } UNDORecordsExecuted; + struct ndb_logevent_NDBStartStarted NDBStartStarted; + struct ndb_logevent_NDBStartCompleted NDBStartCompleted; + struct ndb_logevent_STTORRYRecieved STTORRYRecieved; + struct ndb_logevent_StartPhaseCompleted StartPhaseCompleted; + struct ndb_logevent_CM_REGCONF CM_REGCONF; + struct ndb_logevent_CM_REGREF CM_REGREF; + struct ndb_logevent_FIND_NEIGHBOURS FIND_NEIGHBOURS; + struct ndb_logevent_NDBStopStarted NDBStopStarted; + struct ndb_logevent_NDBStopCompleted NDBStopCompleted; + struct ndb_logevent_NDBStopForced NDBStopForced; + struct ndb_logevent_NDBStopAborted NDBStopAborted; + struct ndb_logevent_StartREDOLog StartREDOLog; + struct ndb_logevent_StartLog StartLog; + struct ndb_logevent_UNDORecordsExecuted UNDORecordsExecuted; /* NODERESTART */ - /** Log event specific data for for corresponding NDB_LE_ log event */ - struct { - } NR_CopyDict; - /** Log event specific data for for corresponding NDB_LE_ log event */ - struct { - } NR_CopyDistr; - /** Log event specific data for for corresponding NDB_LE_ log event */ - struct { - unsigned dest_node; - } NR_CopyFragsStarted; - /** Log event specific data for for corresponding NDB_LE_ log event */ - struct { - unsigned dest_node; - unsigned table_id; - unsigned fragment_id; - } NR_CopyFragDone; - /** Log event specific data for for corresponding NDB_LE_ log event */ - struct { - unsigned dest_node; - } NR_CopyFragsCompleted; + struct ndb_logevent_NR_CopyDict NR_CopyDict; + struct ndb_logevent_NR_CopyDistr NR_CopyDistr; + struct ndb_logevent_NR_CopyFragsStarted NR_CopyFragsStarted; + struct ndb_logevent_NR_CopyFragDone NR_CopyFragDone; + struct ndb_logevent_NR_CopyFragsCompleted NR_CopyFragsCompleted; - /** Log event specific data for for corresponding NDB_LE_ log event */ - struct { - unsigned block; /* 0 = all */ - unsigned failed_node; - unsigned completing_node; /* 0 = all */ - } NodeFailCompleted; - /** Log event specific data for for corresponding NDB_LE_ log event */ - struct { - unsigned failed_node; - unsigned failure_state; - } NODE_FAILREP; - /** Log event specific data for for corresponding NDB_LE_ log event */ - struct { - unsigned code; /* code & state << 16 */ - unsigned arbit_node; - unsigned ticket_0; - unsigned ticket_1; - /* TODO */ - } ArbitState; - /** Log event specific data for for corresponding NDB_LE_ log event */ - struct { - unsigned code; /* code & state << 16 */ - unsigned arbit_node; - unsigned ticket_0; - unsigned ticket_1; - /* TODO */ - } ArbitResult; - /** Log event specific data for for corresponding NDB_LE_ log event */ - struct { - } GCP_TakeoverStarted; - /** Log event specific data for for corresponding NDB_LE_ log event */ - struct { - } GCP_TakeoverCompleted; - /** Log event specific data for for corresponding NDB_LE_ log event */ - struct { - } LCP_TakeoverStarted; - /** Log event specific data for for corresponding NDB_LE_ log event */ - struct { - unsigned state; - } LCP_TakeoverCompleted; + struct ndb_logevent_NodeFailCompleted NodeFailCompleted; + struct ndb_logevent_NODE_FAILREP NODE_FAILREP; + struct ndb_logevent_ArbitState ArbitState; + struct ndb_logevent_ArbitResult ArbitResult; + struct ndb_logevent_GCP_TakeoverStarted GCP_TakeoverStarted; + struct ndb_logevent_GCP_TakeoverCompleted GCP_TakeoverCompleted; + struct ndb_logevent_LCP_TakeoverStarted LCP_TakeoverStarted; + struct ndb_logevent_LCP_TakeoverCompleted LCP_TakeoverCompleted; /* STATISTIC */ - /** Log event specific data for for corresponding NDB_LE_ log event */ - struct { - unsigned trans_count; - unsigned commit_count; - unsigned read_count; - unsigned simple_read_count; - unsigned write_count; - unsigned attrinfo_count; - unsigned conc_op_count; - unsigned abort_count; - unsigned scan_count; - unsigned range_scan_count; - } TransReportCounters; - /** Log event specific data for for corresponding NDB_LE_ log event */ - struct { - unsigned ops; - } OperationReportCounters; - /** Log event specific data for for corresponding NDB_LE_ log event */ - struct { - unsigned table_id; - } TableCreated; - /** Log event specific data for for corresponding NDB_LE_ log event */ - struct { - unsigned mean_loop_count; - } JobStatistic; - /** Log event specific data for for corresponding NDB_LE_ log event */ - struct { - unsigned to_node; - unsigned mean_sent_bytes; - } SendBytesStatistic; - /** Log event specific data for for corresponding NDB_LE_ log event */ - struct { - unsigned from_node; - unsigned mean_received_bytes; - } ReceiveBytesStatistic; - /** Log event specific data for for corresponding NDB_LE_ log event */ - struct { - int gth; - /* union is for compatibility backward. - * page_size_kb member variable should be removed in the future - */ - union { - unsigned page_size_kb; - unsigned page_size_bytes; - }; - unsigned pages_used; - unsigned pages_total; - unsigned block; - } MemoryUsage; + struct ndb_logevent_TransReportCounters TransReportCounters; + struct ndb_logevent_OperationReportCounters OperationReportCounters; + struct ndb_logevent_TableCreated TableCreated; + struct ndb_logevent_JobStatistic JobStatistic; + struct ndb_logevent_SendBytesStatistic SendBytesStatistic; + struct ndb_logevent_ReceiveBytesStatistic ReceiveBytesStatistic; + struct ndb_logevent_MemoryUsage MemoryUsage; /* ERROR */ - /** Log event specific data for for corresponding NDB_LE_ log event */ - struct { - unsigned to_node; - unsigned code; - } TransporterError; - /** Log event specific data for for corresponding NDB_LE_ log event */ - struct { - unsigned to_node; - unsigned code; - } TransporterWarning; - /** Log event specific data for for corresponding NDB_LE_ log event */ - struct { - unsigned node; - unsigned count; - } MissedHeartbeat; - /** Log event specific data for for corresponding NDB_LE_ log event */ - struct { - unsigned node; - } DeadDueToHeartbeat; - /** Log event specific data for for corresponding NDB_LE_ log event */ - struct { - /* TODO */ - } WarningEvent; + struct ndb_logevent_TransporterError TransporterError; + struct ndb_logevent_TransporterWarning TransporterWarning; + struct ndb_logevent_MissedHeartbeat MissedHeartbeat; + struct ndb_logevent_DeadDueToHeartbeat DeadDueToHeartbeat; + struct ndb_logevent_WarningEvent WarningEvent; /* INFO */ - /** Log event specific data for for corresponding NDB_LE_ log event */ - struct { - unsigned node; - } SentHeartbeat; - /** Log event specific data for for corresponding NDB_LE_ log event */ - struct { - unsigned node; - } CreateLogBytes; - /** Log event specific data for for corresponding NDB_LE_ log event */ - struct { - /* TODO */ - } InfoEvent; - /** Log event specific data for for corresponding NDB_LE_ log event */ - struct { - unsigned usage; - unsigned alloc; - unsigned max; - unsigned apply_gci_l; - unsigned apply_gci_h; - unsigned latest_gci_l; - unsigned latest_gci_h; - } EventBufferStatus; + struct ndb_logevent_SentHeartbeat SentHeartbeat; + struct ndb_logevent_CreateLogBytes CreateLogBytes; + struct ndb_logevent_InfoEvent InfoEvent; + struct ndb_logevent_EventBufferStatus EventBufferStatus; /** Log event data for @ref NDB_LE_BackupStarted */ - struct { - unsigned starting_node; - unsigned backup_id; - } BackupStarted; + struct ndb_logevent_BackupStarted BackupStarted; /** Log event data @ref NDB_LE_BackupFailedToStart */ - struct { - unsigned starting_node; - unsigned error; - } BackupFailedToStart; + struct ndb_logevent_BackupFailedToStart BackupFailedToStart; /** Log event data @ref NDB_LE_BackupCompleted */ - struct { - unsigned starting_node; - unsigned backup_id; - unsigned start_gci; - unsigned stop_gci; - unsigned n_records; - unsigned n_log_records; - unsigned n_bytes; - unsigned n_log_bytes; - } BackupCompleted; + struct ndb_logevent_BackupCompleted BackupCompleted; /** Log event data @ref NDB_LE_BackupAborted */ - struct { - unsigned starting_node; - unsigned backup_id; - unsigned error; - } BackupAborted; + struct ndb_logevent_BackupAborted BackupAborted; /** Log event data @ref NDB_LE_SingleUser */ - struct { - unsigned type; - unsigned node_id; - } SingleUser; + struct ndb_logevent_SingleUser SingleUser; /** Log even data @ref NDB_LE_StartReport */ - struct { - unsigned report_type; - unsigned remaining_time; - unsigned bitmask_size; - unsigned bitmask_data[1]; - } StartReport; + struct ndb_logevent_StartReport StartReport; #ifndef DOXYGEN_FIX }; #else diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 9d61d6edd3e..300b0347233 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -4262,7 +4262,7 @@ static void test_fetch_date() myheader("test_fetch_date"); - /* Will not work if sql_mode is NO_ZERO_DATE (implicit if TRADITIONAL) /*/ + /* Will not work if sql_mode is NO_ZERO_DATE (implicit if TRADITIONAL) */ rc= mysql_query(mysql, "SET SQL_MODE=''"); myquery(rc); From 1ba25ae47caace207cda0be2b7994a1a845e6cce Mon Sep 17 00:00:00 2001 From: Staale Smedseng Date: Fri, 28 Aug 2009 17:51:31 +0200 Subject: [PATCH 32/69] Bug #43414 Parenthesis (and other) warnings compiling MySQL with gcc 4.3.2 This patch fixes a number of GCC warnings about variables used before initialized. A new macro UNINIT_VAR() is introduced for use in the variable declaration, and LINT_INIT() usage will be gradually deprecated. (A workaround is used for g++, pending a patch for a g++ bug.) GCC warnings for unused results (attribute warn_unused_result) for a number of system calls (present at least in later Ubuntus, where the usual void cast trick doesn't work) are also fixed. client/mysqlmanager-pwgen.c: A fix for warn_unused_result, adding fallback to use of srand()/rand() if /dev/random cannot be used. Also actually adds calls to rand() in the second branch so that it actually creates a random password. --- client/mysql.cc | 3 ++- client/mysql_upgrade.c | 3 ++- client/mysqladmin.cc | 6 ++++-- client/mysqlmanager-pwgen.c | 19 ++++++++++++------- client/mysqltest.c | 15 +++++++-------- cmd-line-utils/readline/bind.c | 6 ++---- cmd-line-utils/readline/histfile.c | 7 ++++--- cmd-line-utils/readline/undo.c | 3 ++- heap/hp_test2.c | 3 +-- include/my_global.h | 13 +++++++++++++ libmysql/libmysql.c | 3 +-- myisam/ft_boolean_search.c | 4 +--- myisam/mi_check.c | 18 +++++++----------- myisam/mi_create.c | 2 +- myisam/mi_delete.c | 2 +- myisam/mi_dynrec.c | 9 +++------ myisam/mi_open.c | 2 +- myisam/mi_packrec.c | 2 +- myisam/mi_search.c | 5 ++--- myisam/mi_update.c | 5 +---- myisam/sort.c | 4 ++-- myisammrg/myrg_open.c | 4 +--- myisammrg/myrg_rkey.c | 9 +++------ mysys/mf_pack.c | 3 +-- mysys/my_copy.c | 5 +++-- mysys/my_getopt.c | 2 +- mysys/my_redel.c | 3 ++- mysys/typelib.c | 4 ++-- regex/regcomp.c | 6 +++--- sql-common/client.c | 5 ++--- sql-common/my_time.c | 3 +-- sql/field.cc | 19 ++++++------------- sql/ha_myisammrg.cc | 2 +- sql/item.cc | 7 ++----- sql/item_cmpfunc.cc | 17 +++++------------ sql/item_create.cc | 6 ++++-- sql/item_func.cc | 12 ++++-------- sql/lock.cc | 3 +-- sql/log.cc | 3 ++- sql/opt_range.cc | 8 ++++---- sql/spatial.cc | 13 +++---------- sql/sql_acl.cc | 10 +++------- sql/sql_base.cc | 6 ++---- sql/sql_parse.cc | 4 ++-- sql/sql_prepare.cc | 3 +-- sql/sql_show.cc | 7 ++----- sql/sql_update.cc | 4 +--- sql/sql_view.cc | 3 +-- strings/ctype-ucs2.c | 9 +++------ strings/ctype-utf8.c | 6 ++---- strings/decimal.c | 13 ++++--------- 51 files changed, 142 insertions(+), 191 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index 0d61ed4ec88..d103a3eec17 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -3728,7 +3728,8 @@ com_edit(String *buffer,char *line __attribute__((unused))) !(editor = (char *)getenv("VISUAL"))) editor = "vi"; strxmov(buff,editor," ",filename,NullS); - (void) system(buff); + if(system(buff) == -1) + goto err; MY_STAT stat_arg; if (!my_stat(filename,&stat_arg,MYF(MY_WME))) diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c index ff414fff592..efa23610574 100644 --- a/client/mysql_upgrade.c +++ b/client/mysql_upgrade.c @@ -526,6 +526,7 @@ static int upgrade_already_done(void) FILE *in; char upgrade_info_file[FN_REFLEN]= {0}; char buf[sizeof(MYSQL_SERVER_VERSION)+1]; + char *res; if (get_upgrade_info_file_name(upgrade_info_file)) return 0; /* Could not get filename => not sure */ @@ -538,7 +539,7 @@ static int upgrade_already_done(void) will be detected by the strncmp */ bzero(buf, sizeof(buf)); - fgets(buf, sizeof(buf), in); + res= fgets(buf, sizeof(buf), in); my_fclose(in, MYF(0)); diff --git a/client/mysqladmin.cc b/client/mysqladmin.cc index 24b95be8626..699c2081b86 100644 --- a/client/mysqladmin.cc +++ b/client/mysqladmin.cc @@ -1050,14 +1050,16 @@ static void usage(void) static int drop_db(MYSQL *mysql, const char *db) { char name_buff[FN_REFLEN+20], buf[10]; + char *input; + if (!option_force) { puts("Dropping the database is potentially a very bad thing to do."); puts("Any data stored in the database will be destroyed.\n"); printf("Do you really want to drop the '%s' database [y/N] ",db); fflush(stdout); - VOID(fgets(buf,sizeof(buf)-1,stdin)); - if ((*buf != 'y') && (*buf != 'Y')) + input= fgets(buf, sizeof(buf)-1, stdin); + if (!input || ((*input != 'y') && (*input != 'Y'))) { puts("\nOK, aborting database drop!"); return -1; diff --git a/client/mysqlmanager-pwgen.c b/client/mysqlmanager-pwgen.c index 568358b1cda..1be4d8b6970 100644 --- a/client/mysqlmanager-pwgen.c +++ b/client/mysqlmanager-pwgen.c @@ -104,29 +104,34 @@ void get_pass(char* pw, int len) { FILE* fp; char* pw_end=pw+len; + size_t elements_read= 0; /* /dev/random is more secure than rand() because the seed is easy to predict, so we resort to rand() only if /dev/random is not available */ if ((fp=fopen("/dev/random","r"))) { - fread(pw,len,1,fp); - fclose(fp); - while (pwmysql; for (;;) { - MYSQL_RES *res; + MYSQL_RES *UNINIT_VAR(res); MYSQL_ROW row; int done; - LINT_INIT(res); if (mysql_query(mysql,"show status like 'Slave_running'") || !(res=mysql_store_result(mysql))) @@ -4710,13 +4711,12 @@ my_bool end_of_query(int c) int read_line(char *buf, int size) { - char c, last_quote; + char c, UNINIT_VAR(last_quote); char *p= buf, *buf_end= buf + size - 1; int skip_char= 0; enum {R_NORMAL, R_Q, R_SLASH_IN_Q, R_COMMENT, R_LINE_START} state= R_LINE_START; DBUG_ENTER("read_line"); - LINT_INIT(last_quote); start_lineno= cur_file->lineno; DBUG_PRINT("info", ("Starting to read at lineno: %d", start_lineno)); @@ -5978,8 +5978,7 @@ void run_query_normal(struct st_connection *cn, struct st_command *command, if (!disable_result_log) { - ulonglong affected_rows; /* Ok to be undef if 'disable_info' is set */ - LINT_INIT(affected_rows); + ulonglong UNINIT_VAR(affected_rows); /* Ok to be undef if 'disable_info' is set */ if (res) { diff --git a/cmd-line-utils/readline/bind.c b/cmd-line-utils/readline/bind.c index aa5bd3d829a..85f6b432bf8 100644 --- a/cmd-line-utils/readline/bind.c +++ b/cmd-line-utils/readline/bind.c @@ -339,9 +339,7 @@ rl_generic_bind (type, keyseq, data, map) char *keys; int keys_len; register int i; - KEYMAP_ENTRY k; - - k.function = 0; + KEYMAP_ENTRY k= { 0, NULL }; /* If no keys to bind to, exit right away. */ if (keyseq == 0 || *keyseq == 0) @@ -776,7 +774,7 @@ _rl_read_file (filename, sizep) file_size = (size_t)finfo.st_size; /* check for overflow on very large files */ -if ((sizeof(off_t) > sizeof(size_t) && finfo.st_size > (off_t)(size_t)~0) || + if ((sizeof(off_t) > sizeof(size_t) && finfo.st_size > (off_t)(size_t)~0) || file_size + 1 < file_size) { if (file >= 0) diff --git a/cmd-line-utils/readline/histfile.c b/cmd-line-utils/readline/histfile.c index 118c5ebd328..cbd367542ce 100644 --- a/cmd-line-utils/readline/histfile.c +++ b/cmd-line-utils/readline/histfile.c @@ -186,7 +186,7 @@ read_history_range (filename, from, to) file_size = (size_t)finfo.st_size; /* check for overflow on very large files */ -if ((sizeof(off_t) > sizeof(size_t) && finfo.st_size > (off_t)(size_t)~0) || + if ((sizeof(off_t) > sizeof(size_t) && finfo.st_size > (off_t)(size_t)~0) || file_size + 1 < file_size) { errno = overflow_errno; @@ -311,6 +311,7 @@ history_truncate_file (fname, lines) int file, chars_read, rv; struct stat finfo; size_t file_size; + size_t bytes_written; buffer = (char *)NULL; filename = history_filename (fname); @@ -340,7 +341,7 @@ history_truncate_file (fname, lines) file_size = (size_t)finfo.st_size; /* check for overflow on very large files */ -if ((sizeof(off_t) > sizeof(size_t) && finfo.st_size > (off_t)(size_t)~0) || + if ((sizeof(off_t) > sizeof(size_t) && finfo.st_size > (off_t)(size_t)~0) || file_size + 1 < file_size) { close (file); @@ -400,7 +401,7 @@ if ((sizeof(off_t) > sizeof(size_t) && finfo.st_size > (off_t)(size_t)~0) || truncate to. */ if (bp > buffer && ((file = open (filename, O_WRONLY|O_TRUNC|O_BINARY, 0600)) != -1)) { - write (file, bp, chars_read - (bp - buffer)); + bytes_written= write (file, bp, chars_read - (bp - buffer)); #if defined (__BEOS__) /* BeOS ignores O_TRUNC. */ diff --git a/cmd-line-utils/readline/undo.c b/cmd-line-utils/readline/undo.c index 79846c26024..c6bd044c3a3 100644 --- a/cmd-line-utils/readline/undo.c +++ b/cmd-line-utils/readline/undo.c @@ -137,7 +137,8 @@ UNDO_LIST * _rl_copy_undo_list (head) UNDO_LIST *head; { - UNDO_LIST *list, *new, *roving, *c; + UNDO_LIST *list, *new, *c; + UNDO_LIST *roving= NULL; list = head; new = 0; diff --git a/heap/hp_test2.c b/heap/hp_test2.c index 73cad6c2043..dc4ad316d24 100644 --- a/heap/hp_test2.c +++ b/heap/hp_test2.c @@ -61,11 +61,10 @@ int main(int argc, char *argv[]) HP_INFO *file,*file2; HP_KEYDEF keyinfo[MAX_KEYS]; HA_KEYSEG keyseg[MAX_KEYS*5]; - HEAP_PTR position; + HEAP_PTR UNINIT_VAR(position); HP_CREATE_INFO hp_create_info; CHARSET_INFO *cs= &my_charset_latin1; MY_INIT(argv[0]); /* init my_sys library & pthreads */ - LINT_INIT(position); filename= "test2"; filename2= "test2_2"; diff --git a/include/my_global.h b/include/my_global.h index 5c07aa00b32..0b5458215c6 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -464,6 +464,19 @@ int __void__; #define PURIFY_OR_LINT_INIT(var) #endif +/* + Suppress uninitialized variable warning without generating code. + + The _cplusplus is a temporary workaround for C++ code pending a fix + for a g++ bug (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34772). +*/ +#if defined(_lint) || defined(FORCE_INIT_OF_VARS) || defined(__cplusplus) || \ + !defined(__GNUC__) +#define UNINIT_VAR(x) x= 0 +#else +#define UNINIT_VAR(x) x= x +#endif + /* Define some useful general macros */ #if !defined(max) #define max(a, b) ((a) > (b) ? (a) : (b)) diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index d18ed04e273..1fa3181b1be 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -1619,8 +1619,7 @@ myodbc_remove_escape(MYSQL *mysql,char *name) char *to; #ifdef USE_MB my_bool use_mb_flag=use_mb(mysql->charset); - char *end; - LINT_INIT(end); + char *UNINIT_VAR(end); if (use_mb_flag) for (end=name; *end ; end++) ; #endif diff --git a/myisam/ft_boolean_search.c b/myisam/ft_boolean_search.c index 255c51fd33a..50f2cd52b3d 100644 --- a/myisam/ft_boolean_search.c +++ b/myisam/ft_boolean_search.c @@ -218,11 +218,9 @@ static int _ft2_search(FTB *ftb, FTB_WORD *ftbw, my_bool init_search) int subkeys=1; my_bool can_go_down; MI_INFO *info=ftb->info; - uint off, extra=HA_FT_WLEN+info->s->base.rec_reflength; + uint UNINIT_VAR(off), extra=HA_FT_WLEN+info->s->base.rec_reflength; byte *lastkey_buf=ftbw->word+ftbw->off; - LINT_INIT(off); - LINT_INIT(off); if (ftbw->flags & FTB_FLAG_TRUNC) lastkey_buf+=ftbw->len; diff --git a/myisam/mi_check.c b/myisam/mi_check.c index 285a31d34c6..80a90977609 100644 --- a/myisam/mi_check.c +++ b/myisam/mi_check.c @@ -140,11 +140,10 @@ int chk_del(MI_CHECK *param, register MI_INFO *info, uint test_flag) { reg2 ha_rows i; uint delete_link_length; - my_off_t empty,next_link,old_link; + my_off_t empty,next_link,UNINIT_VAR(old_link); char buff[22],buff2[22]; DBUG_ENTER("chk_del"); - LINT_INIT(old_link); param->record_checksum=0; delete_link_length=((info->s->options & HA_OPTION_PACK_RECORD) ? 20 : info->s->rec_reflength+1); @@ -936,11 +935,11 @@ static uint isam_key_length(MI_INFO *info, register MI_KEYDEF *keyinfo) int chk_data_link(MI_CHECK *param, MI_INFO *info,int extend) { int error,got_error,flag; - uint key,left_length,b_type,field; + uint key,UNINIT_VAR(left_length),b_type,field; ha_rows records,del_blocks; - my_off_t used,empty,pos,splits,start_recpos, + my_off_t used,empty,pos,splits,UNINIT_VAR(start_recpos), del_length,link_used,start_block; - byte *record= 0, *to; + byte *record= 0, *UNINIT_VAR(to); char llbuff[22],llbuff2[22],llbuff3[22]; ha_checksum intern_record_checksum; ha_checksum key_checksum[MI_MAX_POSSIBLE_KEY]; @@ -965,7 +964,6 @@ int chk_data_link(MI_CHECK *param, MI_INFO *info,int extend) records=del_blocks=0; used=link_used=splits=del_length=0; intern_record_checksum=param->glob_crc=0; - LINT_INIT(left_length); LINT_INIT(start_recpos); LINT_INIT(to); got_error=error=0; empty=info->s->pack.header_length; @@ -2222,9 +2220,8 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, ulong *rec_per_key_part; char llbuff[22]; SORT_INFO sort_info; - ulonglong key_map; + ulonglong UNINIT_VAR(key_map); DBUG_ENTER("mi_repair_by_sort"); - LINT_INIT(key_map); start_records=info->state->records; got_error=1; @@ -2620,11 +2617,10 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info, IO_CACHE new_data_cache; /* For non-quick repair. */ IO_CACHE_SHARE io_share; SORT_INFO sort_info; - ulonglong key_map; + ulonglong UNINIT_VAR(key_map); pthread_attr_t thr_attr; ulong max_pack_reclength; DBUG_ENTER("mi_repair_parallel"); - LINT_INIT(key_map); start_records=info->state->records; got_error=1; @@ -3206,7 +3202,7 @@ static int sort_get_next_record(MI_SORT_PARAM *sort_param) int parallel_flag; uint found_record,b_type,left_length; my_off_t pos; - byte *to; + byte *UNINIT_VAR(to); MI_BLOCK_INFO block_info; SORT_INFO *sort_info=sort_param->sort_info; MI_CHECK *param=sort_info->param; diff --git a/myisam/mi_create.c b/myisam/mi_create.c index bb53393c345..43639409014 100644 --- a/myisam/mi_create.c +++ b/myisam/mi_create.c @@ -37,7 +37,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, MI_CREATE_INFO *ci,uint flags) { register uint i,j; - File dfile,file; + File UNINIT_VAR(dfile),file; int errpos,save_errno, create_mode= O_RDWR | O_TRUNC; myf create_flag; uint fields,length,max_key_length,packed,pointer,real_length_diff, diff --git a/myisam/mi_delete.c b/myisam/mi_delete.c index e08e5097e33..327a977dcca 100644 --- a/myisam/mi_delete.c +++ b/myisam/mi_delete.c @@ -220,7 +220,7 @@ static int d_search(register MI_INFO *info, register MI_KEYDEF *keyinfo, uint length,nod_flag,search_key_length; my_bool last_key; uchar *leaf_buff,*keypos; - my_off_t leaf_page,next_block; + my_off_t UNINIT_VAR(leaf_page),next_block; uchar lastkey[MI_MAX_KEY_BUFF]; DBUG_ENTER("d_search"); DBUG_DUMP("page",(uchar*) anc_buff,mi_getint(anc_buff)); diff --git a/myisam/mi_dynrec.c b/myisam/mi_dynrec.c index 3542a82be59..af911428d11 100644 --- a/myisam/mi_dynrec.c +++ b/myisam/mi_dynrec.c @@ -1234,16 +1234,14 @@ void _my_store_blob_length(byte *pos,uint pack_length,uint length) int _mi_read_dynamic_record(MI_INFO *info, my_off_t filepos, byte *buf) { int block_of_record; - uint b_type,left_length; - byte *to; + uint b_type,UNINIT_VAR(left_length); + byte *UNINIT_VAR(to); MI_BLOCK_INFO block_info; File file; DBUG_ENTER("mi_read_dynamic_record"); if (filepos != HA_OFFSET_ERROR) { - LINT_INIT(to); - LINT_INIT(left_length); file=info->dfile; block_of_record= 0; /* First block of record is numbered as zero. */ block_info.second_read= 0; @@ -1506,13 +1504,12 @@ int _mi_read_rnd_dynamic_record(MI_INFO *info, byte *buf, { int block_of_record, info_read, save_errno; uint left_len,b_type; - byte *to; + byte *UNINIT_VAR(to); MI_BLOCK_INFO block_info; MYISAM_SHARE *share=info->s; DBUG_ENTER("_mi_read_rnd_dynamic_record"); info_read=0; - LINT_INIT(to); if (info->lock_type == F_UNLCK) { diff --git a/myisam/mi_open.c b/myisam/mi_open.c index d9b7f6453db..285e295d999 100644 --- a/myisam/mi_open.c +++ b/myisam/mi_open.c @@ -678,7 +678,7 @@ err: byte *mi_alloc_rec_buff(MI_INFO *info, ulong length, byte **buf) { uint extra; - uint32 old_length; + uint32 UNINIT_VAR(old_length); LINT_INIT(old_length); if (! *buf || length > (old_length=mi_get_rec_buff_len(info, *buf))) diff --git a/myisam/mi_packrec.c b/myisam/mi_packrec.c index 68911d7f129..75cf45d5434 100644 --- a/myisam/mi_packrec.c +++ b/myisam/mi_packrec.c @@ -1362,7 +1362,7 @@ uint _mi_pack_get_block_info(MI_INFO *myisam, MI_BIT_BUFF *bit_buff, File file, my_off_t filepos) { uchar *header=info->header; - uint head_length,ref_length; + uint head_length, UNINIT_VAR(ref_length); LINT_INIT(ref_length); if (file >= 0) diff --git a/myisam/mi_search.c b/myisam/mi_search.c index 795c7ee55c3..3b1cd6158f2 100644 --- a/myisam/mi_search.c +++ b/myisam/mi_search.c @@ -240,12 +240,11 @@ int _mi_seq_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page, uchar *key, uint key_len, uint comp_flag, uchar **ret_pos, uchar *buff, my_bool *last_key) { - int flag; - uint nod_flag,length,not_used[2]; + int UNINIT_VAR(flag); + uint nod_flag,UNINIT_VAR(length),not_used[2]; uchar t_buff[MI_MAX_KEY_BUFF],*end; DBUG_ENTER("_mi_seq_search"); - LINT_INIT(flag); LINT_INIT(length); end= page+mi_getint(page); nod_flag=mi_test_if_nod(page); page+=2+nod_flag; diff --git a/myisam/mi_update.c b/myisam/mi_update.c index bea457d2e9a..fa0797b1d61 100644 --- a/myisam/mi_update.c +++ b/myisam/mi_update.c @@ -27,11 +27,8 @@ int mi_update(register MI_INFO *info, const byte *oldrec, byte *newrec) bool auto_key_changed=0; ulonglong changed; MYISAM_SHARE *share=info->s; - ha_checksum old_checksum; + ha_checksum UNINIT_VAR(old_checksum); DBUG_ENTER("mi_update"); - LINT_INIT(new_key); - LINT_INIT(changed); - LINT_INIT(old_checksum); DBUG_EXECUTE_IF("myisam_pretend_crashed_table_on_usage", mi_print_error(info->s, HA_ERR_CRASHED); diff --git a/myisam/sort.c b/myisam/sort.c index 2465227a449..f418be6a72d 100644 --- a/myisam/sort.c +++ b/myisam/sort.c @@ -489,7 +489,7 @@ int thr_write_keys(MI_SORT_PARAM *sort_param) { SORT_INFO *sort_info=sort_param->sort_info; MI_CHECK *param=sort_info->param; - ulong length, keys; + ulong UNINIT_VAR(length), keys; ulong *rec_per_key_part=param->rec_per_key_part; int got_error=sort_info->got_error; uint i; @@ -896,7 +896,7 @@ merge_buffers(MI_SORT_PARAM *info, uint keys, IO_CACHE *from_file, int error; uint sort_length,maxcount; ha_rows count; - my_off_t to_start_filepos; + my_off_t UNINIT_VAR(to_start_filepos); uchar *strpos; BUFFPEK *buffpek,**refpek; QUEUE queue; diff --git a/myisammrg/myrg_open.c b/myisammrg/myrg_open.c index 4e61f42efce..8cccb81f6c7 100644 --- a/myisammrg/myrg_open.c +++ b/myisammrg/myrg_open.c @@ -32,7 +32,7 @@ MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking) { int save_errno,errpos=0; - uint files= 0, i, dir_length, length, key_parts, min_keys= 0; + uint files= 0, i, dir_length, length, UNINIT_VAR(key_parts), min_keys= 0; ulonglong file_offset=0; char name_buff[FN_REFLEN*2],buff[FN_REFLEN],*end; MYRG_INFO *m_info=0; @@ -43,8 +43,6 @@ MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking) my_bool bad_children= FALSE; DBUG_ENTER("myrg_open"); - LINT_INIT(key_parts); - bzero((char*) &file,sizeof(file)); if ((fd=my_open(fn_format(name_buff,name,"",MYRG_NAME_EXT,4), O_RDONLY | O_SHARE,MYF(0))) < 0) diff --git a/myisammrg/myrg_rkey.c b/myisammrg/myrg_rkey.c index 627839331c6..2b8091cb43a 100644 --- a/myisammrg/myrg_rkey.c +++ b/myisammrg/myrg_rkey.c @@ -38,16 +38,13 @@ int myrg_rkey(MYRG_INFO *info,byte *buf,int inx, const byte *key, uint key_len, enum ha_rkey_function search_flag) { - byte *key_buff; - uint pack_key_length; - uint16 last_used_keyseg; + byte *UNINIT_VAR(key_buff); + uint UNINIT_VAR(pack_key_length); + uint16 UNINIT_VAR(last_used_keyseg); MYRG_TABLE *table; MI_INFO *mi; int err; DBUG_ENTER("myrg_rkey"); - LINT_INIT(key_buff); - LINT_INIT(pack_key_length); - LINT_INIT(last_used_keyseg); if (_myrg_init_queue(info,inx,search_flag)) DBUG_RETURN(my_errno); diff --git a/mysys/mf_pack.c b/mysys/mf_pack.c index 0157a65311a..d2bac95b391 100644 --- a/mysys/mf_pack.c +++ b/mysys/mf_pack.c @@ -33,12 +33,11 @@ static my_string NEAR_F expand_tilde(my_string *path); void pack_dirname(my_string to, const char *from) { int cwd_err; - uint d_length,length,buff_length; + uint d_length,length,UNINIT_VAR(buff_length); my_string start; char buff[FN_REFLEN]; DBUG_ENTER("pack_dirname"); - LINT_INIT(buff_length); (void) intern_filename(to,from); /* Change to intern name */ #ifdef FN_DEVCHAR diff --git a/mysys/my_copy.c b/mysys/my_copy.c index ec642b4083c..b6bb925e898 100644 --- a/mysys/my_copy.c +++ b/mysys/my_copy.c @@ -57,6 +57,7 @@ int my_copy(const char *from, const char *to, myf MyFlags) File from_file,to_file; char buff[IO_SIZE]; MY_STAT stat_buff,new_stat_buff; + int res; DBUG_ENTER("my_copy"); DBUG_PRINT("my",("from %s to %s MyFlags %d", from, to, MyFlags)); @@ -93,9 +94,9 @@ int my_copy(const char *from, const char *to, myf MyFlags) if (MyFlags & MY_HOLD_ORIGINAL_MODES && !new_file_stat) DBUG_RETURN(0); /* File copyed but not stat */ - VOID(chmod(to, stat_buff.st_mode & 07777)); /* Copy modes */ + res= chmod(to, stat_buff.st_mode & 07777); /* Copy modes */ #if !defined(MSDOS) && !defined(__WIN__) && !defined(__EMX__) && !defined(OS2) && !defined(__NETWARE__) - VOID(chown(to, stat_buff.st_uid,stat_buff.st_gid)); /* Copy ownership */ + res= chown(to, stat_buff.st_uid,stat_buff.st_gid); /* Copy ownership */ #endif #if !defined(VMS) && !defined(__ZTC__) if (MyFlags & MY_COPYTIME) diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c index 3bb500616a1..22b404bdd25 100644 --- a/mysys/my_getopt.c +++ b/mysys/my_getopt.c @@ -100,7 +100,7 @@ int handle_options(int *argc, char ***argv, uint opt_found, argvpos= 0, length, i; my_bool end_of_options= 0, must_be_var, set_maximum_value, option_is_loose; - char **pos, **pos_end, *optend, *prev_found, + char **pos, **pos_end, *optend, *UNINIT_VAR(prev_found), *opt_str, key_name[FN_REFLEN]; const struct my_option *optp; gptr *value; diff --git a/mysys/my_redel.c b/mysys/my_redel.c index 0aec395cf65..03c1021a954 100644 --- a/mysys/my_redel.c +++ b/mysys/my_redel.c @@ -77,6 +77,7 @@ end: int my_copystat(const char *from, const char *to, int MyFlags) { struct stat statbuf; + int res; if (stat((char*) from, &statbuf)) { @@ -95,7 +96,7 @@ int my_copystat(const char *from, const char *to, int MyFlags) if (MyFlags & MY_LINK_WARNING) my_error(EE_LINK_WARNING,MYF(ME_BELL+ME_WAITTANG),from,statbuf.st_nlink); } - VOID(chown(to, statbuf.st_uid, statbuf.st_gid)); /* Copy ownership */ + res= chown(to, statbuf.st_uid, statbuf.st_gid); /* Copy ownership */ #endif /* MSDOS */ #ifndef VMS diff --git a/mysys/typelib.c b/mysys/typelib.c index 4fab6f20493..7416738ece7 100644 --- a/mysys/typelib.c +++ b/mysys/typelib.c @@ -44,7 +44,8 @@ int find_type(my_string x, TYPELIB *typelib, uint full_name) { - int find,pos,findpos; + int find,pos; + int UNINIT_VAR(findpos); /* guarded by find */ reg1 my_string i; reg2 const char *j; DBUG_ENTER("find_type"); @@ -55,7 +56,6 @@ int find_type(my_string x, TYPELIB *typelib, uint full_name) DBUG_PRINT("exit",("no count")); DBUG_RETURN(0); } - LINT_INIT(findpos); find=0; for (pos=0 ; (j=typelib->type_names[pos]) ; pos++) { diff --git a/regex/regcomp.c b/regex/regcomp.c index 9cba56a97dd..0a65c5021fb 100644 --- a/regex/regcomp.c +++ b/regex/regcomp.c @@ -213,11 +213,11 @@ register struct parse *p; int stop; /* character this ERE should end at */ { register char c; - register sopno prevback; - register sopno prevfwd; + register sopno UNINIT_VAR(prevback); + register sopno UNINIT_VAR(prevfwd); register sopno conc; register int first = 1; /* is this the first alternative? */ - LINT_INIT(prevback); LINT_INIT(prevfwd); + for (;;) { /* do a bunch of concatenated expressions */ conc = HERE(); diff --git a/sql-common/client.c b/sql-common/client.c index 0cd7ef78478..8f1f4a1fd5a 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -1633,7 +1633,7 @@ mysql_ssl_free(MYSQL *mysql __attribute__((unused))) */ const char * STDCALL -mysql_get_ssl_cipher(MYSQL *mysql) +mysql_get_ssl_cipher(MYSQL *mysql __attribute__((unused))) { DBUG_ENTER("mysql_get_ssl_cipher"); #ifdef HAVE_OPENSSL @@ -1829,7 +1829,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, uint port, const char *unix_socket,ulong client_flag) { char buff[NAME_LEN+USERNAME_LENGTH+100]; - char *end,*host_info; + char *end,*host_info= NULL; my_socket sock; in_addr_t ip_addr; struct sockaddr_in sock_addr; @@ -1847,7 +1847,6 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, #endif init_sigpipe_variables DBUG_ENTER("mysql_real_connect"); - LINT_INIT(host_info); DBUG_PRINT("enter",("host: %s db: %s user: %s", host ? host : "(Null)", diff --git a/sql-common/my_time.c b/sql-common/my_time.c index 16a64ebd947..d2ef9da25f5 100644 --- a/sql-common/my_time.c +++ b/sql-common/my_time.c @@ -160,7 +160,7 @@ enum enum_mysql_timestamp_type str_to_datetime(const char *str, uint length, MYSQL_TIME *l_time, uint flags, int *was_cut) { - uint field_length, year_length, digits, i, number_of_fields; + uint field_length, UNINIT_VAR(year_length), digits, i, number_of_fields; uint date[MAX_DATE_PARTS], date_len[MAX_DATE_PARTS]; uint add_hours= 0, start_loop; ulong not_zero_date, allow_space; @@ -174,7 +174,6 @@ str_to_datetime(const char *str, uint length, MYSQL_TIME *l_time, DBUG_PRINT("ENTER",("str: %.*s",length,str)); LINT_INIT(field_length); - LINT_INIT(year_length); LINT_INIT(last_field_pos); *was_cut= 0; diff --git a/sql/field.cc b/sql/field.cc index 2322c5d7b9d..b61e5fd2d79 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -1736,16 +1736,16 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs) Pointers used when digits move from the left of the '.' to the right of the '.' (explained below) */ - const char *int_digits_tail_from; + const char *UNINIT_VAR(int_digits_tail_from); /* Number of 0 that need to be added at the left of the '.' (1E3: 3 zeros) */ - uint int_digits_added_zeros; + uint UNINIT_VAR(int_digits_added_zeros); /* Pointer used when digits move from the right of the '.' to the left of the '.' */ - const char *frac_digits_head_end; + const char *UNINIT_VAR(frac_digits_head_end); /* Number of 0 that need to be added at the right of the '.' (for 1E-3) */ - uint frac_digits_added_zeros; + uint UNINIT_VAR(frac_digits_added_zeros); char *pos,*tmp_left_pos,*tmp_right_pos; /* Pointers that are used as limits (begin and end of the field buffer) */ char *left_wall,*right_wall; @@ -1756,11 +1756,6 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs) */ bool is_cuted_fields_incr=0; - LINT_INIT(int_digits_tail_from); - LINT_INIT(int_digits_added_zeros); - LINT_INIT(frac_digits_head_end); - LINT_INIT(frac_digits_added_zeros); - /* There are three steps in this function : - parse the input string @@ -8854,10 +8849,8 @@ Field *make_field(char *ptr, uint32 field_length, const char *field_name, struct st_table *table) { - uchar *bit_ptr; - uchar bit_offset; - LINT_INIT(bit_ptr); - LINT_INIT(bit_offset); + uchar *UNINIT_VAR(bit_ptr); + uchar UNINIT_VAR(bit_offset); if (field_type == FIELD_TYPE_BIT && !f_bit_as_char(pack_flag)) { bit_ptr= null_pos; diff --git a/sql/ha_myisammrg.cc b/sql/ha_myisammrg.cc index fef2e21d271..7983ffbc6c8 100644 --- a/sql/ha_myisammrg.cc +++ b/sql/ha_myisammrg.cc @@ -78,7 +78,7 @@ static void split_file_name(const char *file_name, extern "C" void myrg_print_wrong_table(const char *table_name) { - LEX_STRING db, name; + LEX_STRING db= {NULL, 0}, name; char buf[FN_REFLEN]; split_file_name(table_name, &db, &name); memcpy(buf, db.str, db.length); diff --git a/sql/item.cc b/sql/item.cc index eecb48aa16f..03d752a85d9 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1635,7 +1635,7 @@ bool agg_item_collations_for_comparison(DTCollation &c, const char *fname, bool agg_item_set_converter(DTCollation &coll, const char *fname, Item **args, uint nargs, uint flags, int item_sep) { - Item **arg, *safe_args[2]; + Item **arg, *safe_args[2]= {NULL, NULL}; /* For better error reporting: save the first and the second argument. @@ -1644,8 +1644,6 @@ bool agg_item_set_converter(DTCollation &coll, const char *fname, doesn't display each argument's characteristics. - if nargs is 1, then this error cannot happen. */ - LINT_INIT(safe_args[0]); - LINT_INIT(safe_args[1]); if (nargs >=2 && nargs <= 3) { safe_args[0]= args[0]; @@ -5122,9 +5120,8 @@ bool Item_null::send(Protocol *protocol, String *packet) bool Item::send(Protocol *protocol, String *buffer) { - bool result; + bool UNINIT_VAR(result); // Will be set if null_value == 0 enum_field_types f_type; - LINT_INIT(result); // Will be set if null_value == 0 switch ((f_type=field_type())) { default: diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index c940c4ab3c0..8c655cdc369 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -352,8 +352,7 @@ static bool convert_constant_item(THD *thd, Item_field *field_item, /* For comparison purposes allow invalid dates like 2000-01-32 */ ulong orig_sql_mode= thd->variables.sql_mode; enum_check_fields orig_count_cuted_fields= thd->count_cuted_fields; - ulonglong orig_field_val; /* original field value if valid */ - LINT_INIT(orig_field_val); + ulonglong UNINIT_VAR(orig_field_val); /* original field value if valid */ thd->variables.sql_mode= (orig_sql_mode & ~MODE_NO_ZERO_DATE) | MODE_INVALID_DATES; thd->count_cuted_fields= CHECK_FIELD_IGNORE; @@ -2453,19 +2452,13 @@ Item_func_nullif::is_null() Item *Item_func_case::find_item(String *str) { - String *first_expr_str, *tmp; - my_decimal *first_expr_dec, first_expr_dec_val; - longlong first_expr_int; - double first_expr_real; + String *UNINIT_VAR(first_expr_str), *tmp; + my_decimal *UNINIT_VAR(first_expr_dec), first_expr_dec_val; + longlong UNINIT_VAR(first_expr_int); + double UNINIT_VAR(first_expr_real); char buff[MAX_FIELD_WIDTH]; String buff_str(buff,sizeof(buff),default_charset()); - /* These will be initialized later */ - LINT_INIT(first_expr_str); - LINT_INIT(first_expr_int); - LINT_INIT(first_expr_real); - LINT_INIT(first_expr_dec); - if (first_expr_num != -1) { switch (cmp_type) diff --git a/sql/item_create.cc b/sql/item_create.cc index c897b7aef79..cbd015f300b 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -451,10 +451,9 @@ Item *create_func_cast(Item *a, Cast_target cast_type, const char *c_len, const char *c_dec, CHARSET_INFO *cs) { - Item *res; + Item *UNINIT_VAR(res); ulong len; uint dec; - LINT_INIT(res); switch (cast_type) { case ITEM_CAST_BINARY: res= new Item_func_binary(a); break; @@ -542,6 +541,9 @@ Item *create_func_cast(Item *a, Cast_target cast_type, res= new Item_char_typecast(a, len, cs ? cs : current_thd->variables.collation_connection); break; + + default: + DBUG_ASSERT(0); } return res; } diff --git a/sql/item_func.cc b/sql/item_func.cc index 6193ab285f2..3c1e2126008 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -2275,9 +2275,8 @@ void Item_func_min_max::fix_length_and_dec() uint Item_func_min_max::cmp_datetimes(ulonglong *value) { - longlong min_max; + longlong UNINIT_VAR(min_max); uint min_max_idx= 0; - LINT_INIT(min_max); for (uint i=0; i < arg_count ; i++) { @@ -2345,8 +2344,7 @@ String *Item_func_min_max::val_str(String *str) } case STRING_RESULT: { - String *res; - LINT_INIT(res); + String *UNINIT_VAR(res); for (uint i=0; i < arg_count ; i++) { if (i == 0) @@ -2435,8 +2433,7 @@ longlong Item_func_min_max::val_int() my_decimal *Item_func_min_max::val_decimal(my_decimal *dec) { DBUG_ASSERT(fixed == 1); - my_decimal tmp_buf, *tmp, *res; - LINT_INIT(res); + my_decimal tmp_buf, *tmp, *UNINIT_VAR(res); if (compare_as_dates) { @@ -4974,8 +4971,7 @@ void Item_func_match::init_search(bool no_order) bool Item_func_match::fix_fields(THD *thd, Item **ref) { DBUG_ASSERT(fixed == 0); - Item *item; - LINT_INIT(item); // Safe as arg_count is > 1 + Item *UNINIT_VAR(item); // Safe as arg_count is > 1 maybe_null=1; join_key=0; diff --git a/sql/lock.cc b/sql/lock.cc index 3102497576f..97abd76b7c2 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -1216,11 +1216,10 @@ void unlock_global_read_lock(THD *thd) bool wait_if_global_read_lock(THD *thd, bool abort_on_refresh, bool is_not_commit) { - const char *old_message; + const char *UNINIT_VAR(old_message); bool result= 0, need_exit_cond; DBUG_ENTER("wait_if_global_read_lock"); - LINT_INIT(old_message); /* Assert that we do not own LOCK_open. If we would own it, other threads could not close their tables. This would make a pretty diff --git a/sql/log.cc b/sql/log.cc index ec8f5fe820b..c042651216c 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -2635,9 +2635,10 @@ bool flush_error_log() else result= 1; #else + FILE *reopen; my_rename(log_error_file,err_renamed,MYF(0)); if (freopen(log_error_file,"a+",stdout)) - freopen(log_error_file,"a+",stderr); + reopen= freopen(log_error_file,"a+",stderr); else result= 1; #endif diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 778fc418392..fdf6cc03a44 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -3514,11 +3514,10 @@ static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree, { int idx; SEL_ARG **key,**end, **key_to_read= NULL; - ha_rows best_records; + ha_rows UNINIT_VAR(best_records); /* protected by key_to_read */ TRP_RANGE* read_plan= NULL; bool pk_is_clustered= param->table->file->primary_key_is_clustered(); DBUG_ENTER("get_key_scans_params"); - LINT_INIT(best_records); /* protected by key_to_read */ /* Note that there may be trees that have type SEL_TREE::KEY but contain no key reads at all, e.g. tree for expression "key1 is not null" where key1 @@ -5370,8 +5369,7 @@ static bool eq_tree(SEL_ARG* a,SEL_ARG *b) SEL_ARG * SEL_ARG::insert(SEL_ARG *key) { - SEL_ARG *element,**par,*last_element; - LINT_INIT(par); LINT_INIT(last_element); + SEL_ARG *element,**UNINIT_VAR(par),*UNINIT_VAR(last_element); for (element= this; element != &null_element ; ) { @@ -7918,7 +7916,9 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree) goto next_index; } else + { DBUG_ASSERT(FALSE); + } /* Check (SA2). */ if (min_max_arg_item) diff --git a/sql/spatial.cc b/sql/spatial.cc index 80506f16d0f..6e1da589527 100644 --- a/sql/spatial.cc +++ b/sql/spatial.cc @@ -935,13 +935,10 @@ int Gis_polygon::interior_ring_n(uint32 num, String *result) const int Gis_polygon::centroid_xy(double *x, double *y) const { uint32 n_linear_rings; - double res_area; - double res_cx, res_cy; + double UNINIT_VAR(res_area); + double UNINIT_VAR(res_cx), UNINIT_VAR(res_cy); const char *data= m_data; bool first_loop= 1; - LINT_INIT(res_area); - LINT_INIT(res_cx); - LINT_INIT(res_cy); if (no_data(data, 4)) return 1; @@ -1634,14 +1631,10 @@ int Gis_multi_polygon::centroid(String *result) const uint32 n_polygons; bool first_loop= 1; Gis_polygon p; - double res_area, res_cx, res_cy; + double UNINIT_VAR(res_area), UNINIT_VAR(res_cx), UNINIT_VAR(res_cy); double cur_area, cur_cx, cur_cy; const char *data= m_data; - LINT_INIT(res_area); - LINT_INIT(res_cx); - LINT_INIT(res_cy); - if (no_data(data, 4)) return 1; n_polygons= uint4korr(data); diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index ab4e518d5dd..ea17a4227ef 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -5067,17 +5067,13 @@ static int handle_grant_struct(uint struct_no, bool drop, uint elements; const char *user; const char *host; - ACL_USER *acl_user; - ACL_DB *acl_db; - GRANT_NAME *grant_name; + ACL_USER *UNINIT_VAR(acl_user); + ACL_DB *UNINIT_VAR(acl_db); + GRANT_NAME *UNINIT_VAR(grant_name); DBUG_ENTER("handle_grant_struct"); DBUG_PRINT("info",("scan struct: %u search: '%s'@'%s'", struct_no, user_from->user.str, user_from->host.str)); - LINT_INIT(acl_user); - LINT_INIT(acl_db); - LINT_INIT(grant_name); - safe_mutex_assert_owner(&acl_cache->lock); /* Get the number of elements in the in-memory structure. */ diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 6a99d5d1541..db4ab29d6de 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -706,7 +706,7 @@ void close_temporary_tables(THD *thd) return; } - TABLE *next, + TABLE *UNINIT_VAR(next), *prev_table /* prev link is not maintained in TABLE's double-linked list */; bool was_quote_show= true; /* to assume thd->options has OPTION_QUOTE_SHOW_CREATE */ // Better add "if exists", in case a RESET MASTER has been done @@ -716,7 +716,6 @@ void close_temporary_tables(THD *thd) memcpy(buf, stub, stub_len); String s_query= String(buf, sizeof(buf), system_charset_info); bool found_user_tables= false; - LINT_INIT(next); /* insertion sort of temp tables by pseudo_thread_id to build ordered list @@ -4142,8 +4141,7 @@ find_item_in_list(Item *find, List &items, uint *counter, (and not an item that happens to have a name). */ bool is_ref_by_name= 0; - uint unaliased_counter; - LINT_INIT(unaliased_counter); // Dependent on found_unaliased + uint UNINIT_VAR(unaliased_counter); // Dependent on found_unaliased *resolution= NOT_RESOLVED; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 45f70964f50..65b2a9d60b0 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1325,7 +1325,7 @@ pthread_handler_t handle_bootstrap(void *arg) thd->init_for_queries(); while (fgets(buff, thd->net.max_packet, file)) { - char *query; + char *query, *res; ulong length= (ulong) strlen(buff); while (buff[length-1] != '\n' && !feof(file)) { @@ -1340,7 +1340,7 @@ pthread_handler_t handle_bootstrap(void *arg) break; } buff= (char*) thd->net.buff; - fgets(buff + length, thd->net.max_packet - length, file); + res= fgets(buff + length, thd->net.max_packet - length, file); length+= (ulong) strlen(buff + length); } if (thd->is_fatal_error) diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index d14f14b526e..06f77f9689c 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -2072,10 +2072,9 @@ void mysql_sql_stmt_prepare(THD *thd) LEX_STRING *name= &lex->prepared_stmt_name; Prepared_statement *stmt; const char *query; - uint query_len; + uint UNINIT_VAR(query_len); DBUG_ENTER("mysql_sql_stmt_prepare"); DBUG_ASSERT(thd->protocol == &thd->protocol_simple); - LINT_INIT(query_len); if ((stmt= (Prepared_statement*) thd->stmt_map.find_by_name(name))) { diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 9eac750c22e..13045280c5f 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -2172,8 +2172,8 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) ST_SCHEMA_TABLE *schema_table= tables->schema_table; SELECT_LEX sel; INDEX_FIELD_VALUES idx_field_vals; - char path[FN_REFLEN], *end, *base_name, *orig_base_name, *file_name; - uint len; + char path[FN_REFLEN], *UNINIT_VAR(end), *base_name, *orig_base_name, *file_name; + uint UNINIT_VAR(len); bool with_i_schema; enum enum_schema_tables schema_table_idx; List bases; @@ -2190,9 +2190,6 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) #endif DBUG_ENTER("get_all_tables"); - LINT_INIT(end); - LINT_INIT(len); - lex->view_prepare_mode= TRUE; lex->reset_n_backup_query_tables_list(&query_tables_list_backup); diff --git a/sql/sql_update.cc b/sql/sql_update.cc index c18c34fc1d1..06d1bcaa8fb 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -125,7 +125,7 @@ int mysql_update(THD *thd, uint want_privilege; #endif uint table_count= 0; - query_id_t query_id=thd->query_id, timestamp_query_id; + query_id_t query_id=thd->query_id, UNINIT_VAR(timestamp_query_id); ha_rows updated, found; key_map old_used_keys; TABLE *table; @@ -137,8 +137,6 @@ int mysql_update(THD *thd, THD::killed_state killed_status= THD::NOT_KILLED; DBUG_ENTER("mysql_update"); - LINT_INIT(timestamp_query_id); - for ( ; ; ) { if (open_tables(thd, &table_list, &table_count, 0)) diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 96077aeeb12..8cf25e9d88c 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -955,7 +955,7 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table, TABLE_LIST *top_view= table->top_table(); int res; bool result, view_is_mergeable; - TABLE_LIST *view_main_select_tables; + TABLE_LIST *UNINIT_VAR(view_main_select_tables); DBUG_ENTER("mysql_make_view"); DBUG_PRINT("info", ("table: 0x%lx (%s)", (ulong) table, table->table_name)); @@ -1218,7 +1218,6 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table, view_is_mergeable= (table->algorithm != VIEW_ALGORITHM_TMPTABLE && lex->can_be_merged()); - LINT_INIT(view_main_select_tables); if (view_is_mergeable) { diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c index 65e4182d564..6657ef01785 100644 --- a/strings/ctype-ucs2.c +++ b/strings/ctype-ucs2.c @@ -202,11 +202,10 @@ static int my_strnncoll_ucs2(CHARSET_INFO *cs, my_bool t_is_prefix) { int s_res,t_res; - my_wc_t s_wc,t_wc; + my_wc_t UNINIT_VAR(s_wc),t_wc; const uchar *se=s+slen; const uchar *te=t+tlen; MY_UNICASE_INFO **uni_plane= cs->caseinfo; - LINT_INIT(s_wc); while ( s < se && t < te ) { @@ -317,11 +316,10 @@ static int my_strncasecmp_ucs2(CHARSET_INFO *cs, const char *s, const char *t, uint len) { int s_res,t_res; - my_wc_t s_wc,t_wc; + my_wc_t UNINIT_VAR(s_wc),t_wc; const char *se=s+len; const char *te=t+len; MY_UNICASE_INFO **uni_plane= cs->caseinfo; - LINT_INIT(s_wc); while ( s < se && t < te ) { @@ -1385,10 +1383,9 @@ int my_strnncoll_ucs2_bin(CHARSET_INFO *cs, my_bool t_is_prefix) { int s_res,t_res; - my_wc_t s_wc,t_wc; + my_wc_t UNINIT_VAR(s_wc),t_wc; const uchar *se=s+slen; const uchar *te=t+tlen; - LINT_INIT(s_wc); while ( s < se && t < te ) { diff --git a/strings/ctype-utf8.c b/strings/ctype-utf8.c index 4682868562f..3fcde4aca64 100644 --- a/strings/ctype-utf8.c +++ b/strings/ctype-utf8.c @@ -2306,11 +2306,10 @@ static int my_strnncoll_utf8(CHARSET_INFO *cs, my_bool t_is_prefix) { int s_res,t_res; - my_wc_t s_wc,t_wc; + my_wc_t UNINIT_VAR(s_wc), t_wc; const uchar *se=s+slen; const uchar *te=t+tlen; MY_UNICASE_INFO **uni_plane= cs->caseinfo; - LINT_INIT(s_wc); while ( s < se && t < te ) { @@ -2377,10 +2376,9 @@ static int my_strnncollsp_utf8(CHARSET_INFO *cs, my_bool diff_if_only_endspace_difference) { int s_res, t_res, res; - my_wc_t s_wc,t_wc; + my_wc_t UNINIT_VAR(s_wc),t_wc; const uchar *se= s+slen, *te= t+tlen; MY_UNICASE_INFO **uni_plane= cs->caseinfo; - LINT_INIT(s_wc); #ifndef VARCHAR_WITH_DIFF_ENDSPACE_ARE_DIFFERENT_FOR_UNIQUE diff_if_only_endspace_difference= 0; diff --git a/strings/decimal.c b/strings/decimal.c index c535d0f73dc..7c2c2999fb8 100644 --- a/strings/decimal.c +++ b/strings/decimal.c @@ -1359,8 +1359,7 @@ int bin2decimal(char *from, decimal_t *to, int precision, int scale) if (intg0x) { int i=dig2bytes[intg0x]; - dec1 x; - LINT_INIT(x); + dec1 UNINIT_VAR(x); switch (i) { case 1: x=mi_sint1korr(from); break; @@ -1401,8 +1400,7 @@ int bin2decimal(char *from, decimal_t *to, int precision, int scale) if (frac0x) { int i=dig2bytes[frac0x]; - dec1 x; - LINT_INIT(x); + dec1 UNINIT_VAR(x); switch (i) { case 1: x=mi_sint1korr(from); break; @@ -1480,7 +1478,7 @@ decimal_round(decimal_t *from, decimal_t *to, int scale, decimal_round_mode mode) { int frac0=scale>0 ? ROUND_UP(scale) : scale/DIG_PER_DEC1, - frac1=ROUND_UP(from->frac), round_digit, + frac1=ROUND_UP(from->frac), UNINIT_VAR(round_digit), intg0=ROUND_UP(from->intg), error=E_DEC_OK, len=to->len, intg1=ROUND_UP(from->intg + (((intg0 + frac0)>0) && (from->buf[0] == DIG_MAX))); @@ -1489,7 +1487,6 @@ decimal_round(decimal_t *from, decimal_t *to, int scale, sanity(to); - LINT_INIT(round_digit); switch (mode) { case HALF_UP: case HALF_EVEN: round_digit=5; break; @@ -2117,13 +2114,11 @@ static int do_div_mod(decimal_t *from1, decimal_t *from2, { int frac1=ROUND_UP(from1->frac)*DIG_PER_DEC1, prec1=from1->intg+frac1, frac2=ROUND_UP(from2->frac)*DIG_PER_DEC1, prec2=from2->intg+frac2, - error, i, intg0, frac0, len1, len2, dintg, div_mod=(!mod); + UNINIT_VAR(error), i, intg0, frac0, len1, len2, dintg, div_mod=(!mod); dec1 *buf0, *buf1=from1->buf, *buf2=from2->buf, *tmp1, *start2, *stop2, *stop1, *stop0, norm2, carry, *start1, dcarry; dec2 norm_factor, x, guess, y; - LINT_INIT(error); - if (mod) to=mod; From dc7106f5cae48d59ec6d30ad289d085e82f4bd7c Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Fri, 28 Aug 2009 18:49:16 -0300 Subject: [PATCH 33/69] Reduce test case runtime. mysql-test/r/lock_multi_bug38499.result: Update test case result. mysql-test/r/lock_multi_bug38691.result: Update test case result. mysql-test/t/lock_multi_bug38499.test: Do not sync .frm files. mysql-test/t/lock_multi_bug38691.test: Do not sync .frm files. --- mysql-test/r/lock_multi_bug38499.result | 3 +++ mysql-test/r/lock_multi_bug38691.result | 3 +++ mysql-test/t/lock_multi_bug38499.test | 5 +++++ mysql-test/t/lock_multi_bug38691.test | 5 +++++ 4 files changed, 16 insertions(+) diff --git a/mysql-test/r/lock_multi_bug38499.result b/mysql-test/r/lock_multi_bug38499.result index fd0f2138a8d..9b3f57c8e53 100644 --- a/mysql-test/r/lock_multi_bug38499.result +++ b/mysql-test/r/lock_multi_bug38499.result @@ -1,3 +1,5 @@ +SET @odl_sync_frm = @@global.sync_frm; +SET @@global.sync_frm = OFF; DROP TABLE IF EXISTS t1; CREATE TABLE t1( a INT, b INT ); INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3), (4, 4); @@ -17,3 +19,4 @@ ALTER TABLE t1 ADD COLUMN a INT; # 2.2.1. normal mode # 2.2.2. PS mode DROP TABLE t1; +SET @@global.sync_frm = @odl_sync_frm; diff --git a/mysql-test/r/lock_multi_bug38691.result b/mysql-test/r/lock_multi_bug38691.result index 74b9603d8e3..d0aa1c0277c 100644 --- a/mysql-test/r/lock_multi_bug38691.result +++ b/mysql-test/r/lock_multi_bug38691.result @@ -1,3 +1,5 @@ +SET @odl_sync_frm = @@global.sync_frm; +SET @@global.sync_frm = OFF; DROP TABLE IF EXISTS t1,t2,t3; CREATE TABLE t1 ( a int(11) unsigned default NULL, @@ -15,3 +17,4 @@ CREATE TABLE t3 SELECT * FROM t1; # normal mode # PS mode DROP TABLE t1, t2, t3; +SET @@global.sync_frm = @odl_sync_frm; diff --git a/mysql-test/t/lock_multi_bug38499.test b/mysql-test/t/lock_multi_bug38499.test index 8178987e802..3d3f084ba5f 100644 --- a/mysql-test/t/lock_multi_bug38499.test +++ b/mysql-test/t/lock_multi_bug38499.test @@ -5,6 +5,9 @@ # Save the initial number of concurrent sessions --source include/count_sessions.inc +SET @odl_sync_frm = @@global.sync_frm; +SET @@global.sync_frm = OFF; + connect (locker,localhost,root,,); connect (writer,localhost,root,,); @@ -214,6 +217,8 @@ DROP TABLE t1; --disconnect locker --disconnect writer +SET @@global.sync_frm = @odl_sync_frm; + # End of 5.0 tests # Wait till all disconnects are completed diff --git a/mysql-test/t/lock_multi_bug38691.test b/mysql-test/t/lock_multi_bug38691.test index 0458f31579e..881a0d8e502 100644 --- a/mysql-test/t/lock_multi_bug38691.test +++ b/mysql-test/t/lock_multi_bug38691.test @@ -8,6 +8,9 @@ # Save the initial number of concurrent sessions --source include/count_sessions.inc +SET @odl_sync_frm = @@global.sync_frm; +SET @@global.sync_frm = OFF; + # Test to see if select will get the lock ahead of low priority update connect (locker,localhost,root,,); @@ -136,6 +139,8 @@ DROP TABLE t1, t2, t3; --disconnect locker --disconnect writer +SET @@global.sync_frm = @odl_sync_frm; + # Wait till all disconnects are completed --source include/wait_until_count_sessions.inc From f32c08bd0ca20d23e95ca46912044d48282cfd6f Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 29 Aug 2009 16:52:22 +0800 Subject: [PATCH 34/69] Bug #44331 Restore of database with events produces warning in replication If an EVENT is created without the DEFINER clause set explicitly or with it set to CURRENT_USER, the master and slaves become inconsistent. This issue stems from the fact that in both cases, the DEFINER is set to the CURRENT_USER of the current thread. On the master, the CURRENT_USER is the mysqld's user, while on the slave, the CURRENT_USER is empty for the SQL Thread which is responsible for executing the statement. To fix the problem, we do what follows. If the definer is not set explicitly, a DEFINER clause is added when writing the query into binlog; if 'CURRENT_USER' is used as the DEFINER, it is replaced with the value of the current user before writing to binlog. mysql-test/suite/rpl/r/rpl_create_if_not_exists.result: Updated the result file after fixing bug#44331 mysql-test/suite/rpl/r/rpl_drop_if_exists.result: Updated the result file after fixing bug#44331 mysql-test/suite/rpl/r/rpl_events.result: Test result of Bug#44331 mysql-test/suite/rpl/r/rpl_innodb_mixed_dml.result: Updated the result file after fixing bug#44331 mysql-test/suite/rpl/t/rpl_events.test: Added test to verify if the definer is consistent between master and slave when the event is created without the DEFINER clause set explicitly or the DEFINER is set to CURRENT_USER sql/events.cc: The "create_query_string" function is added to create a new query string for removing executable comments. sql/sql_yacc.yy: The remember_name token was added for recording the offset of EVENT_SYM. --- .../rpl/r/rpl_create_if_not_exists.result | 2 +- .../suite/rpl/r/rpl_drop_if_exists.result | 4 +- mysql-test/suite/rpl/r/rpl_events.result | 42 +++++++++++++++++ .../suite/rpl/r/rpl_innodb_mixed_dml.result | 4 +- mysql-test/suite/rpl/t/rpl_events.test | 46 +++++++++++++++++-- sql/events.cc | 38 ++++++++++++++- sql/sql_yacc.yy | 7 +-- 7 files changed, 131 insertions(+), 12 deletions(-) diff --git a/mysql-test/suite/rpl/r/rpl_create_if_not_exists.result b/mysql-test/suite/rpl/r/rpl_create_if_not_exists.result index 536f40dc7f1..12a956a6ce6 100644 --- a/mysql-test/suite/rpl/r/rpl_create_if_not_exists.result +++ b/mysql-test/suite/rpl/r/rpl_create_if_not_exists.result @@ -29,5 +29,5 @@ t1 t2 SHOW EVENTS in mysqltest; Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator character_set_client collation_connection Database Collation -mysqltest e @ SYSTEM ONE TIME # NULL NULL NULL NULL SLAVESIDE_DISABLED 1 latin1 latin1_swedish_ci latin1_swedish_ci +mysqltest e root@localhost SYSTEM ONE TIME # NULL NULL NULL NULL SLAVESIDE_DISABLED 1 latin1 latin1_swedish_ci latin1_swedish_ci DROP DATABASE IF EXISTS mysqltest; diff --git a/mysql-test/suite/rpl/r/rpl_drop_if_exists.result b/mysql-test/suite/rpl/r/rpl_drop_if_exists.result index 59a2470cfdb..e2d4c727c98 100644 --- a/mysql-test/suite/rpl/r/rpl_drop_if_exists.result +++ b/mysql-test/suite/rpl/r/rpl_drop_if_exists.result @@ -43,7 +43,7 @@ master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS db_bug_13684.t master-bin.000001 # Query # # DROP DATABASE IF EXISTS db_bug_13684 master-bin.000001 # Query # # CREATE DATABASE db_bug_13684 master-bin.000001 # Query # # use `test`; CREATE TABLE db_bug_13684.t (a int) -master-bin.000001 # Query # # use `test`; CREATE EVENT db_bug_13684.e +master-bin.000001 # Query # # use `test`; CREATE DEFINER=`root`@`localhost` EVENT db_bug_13684.e ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR DO UPDATE db_bug_13684.t SET a = a + 1 @@ -75,7 +75,7 @@ master-bin.000001 # Query # # use `test`; DROP TABLE IF EXISTS db_bug_13684.t master-bin.000001 # Query # # DROP DATABASE IF EXISTS db_bug_13684 master-bin.000001 # Query # # CREATE DATABASE db_bug_13684 master-bin.000001 # Query # # use `test`; CREATE TABLE db_bug_13684.t (a int) -master-bin.000001 # Query # # use `test`; CREATE EVENT db_bug_13684.e +master-bin.000001 # Query # # use `test`; CREATE DEFINER=`root`@`localhost` EVENT db_bug_13684.e ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 1 HOUR DO UPDATE db_bug_13684.t SET a = a + 1 diff --git a/mysql-test/suite/rpl/r/rpl_events.result b/mysql-test/suite/rpl/r/rpl_events.result index b797183f9d2..8538d2ca373 100644 --- a/mysql-test/suite/rpl/r/rpl_events.result +++ b/mysql-test/suite/rpl/r/rpl_events.result @@ -191,5 +191,47 @@ select * from t28953; END;| ALTER EVENT event1 RENAME TO event2; DROP EVENT event2; +CREATE TABLE test.t1(details CHAR(30)); +CREATE EVENT /*!50000 event44331_1 */ +ON SCHEDULE AT CURRENT_TIMESTAMP +ON COMPLETION PRESERVE DISABLE +DO INSERT INTO test.t1 VALUES('event event44331_1 fired - no definer'); +CREATE DEFINER=CURRENT_USER /*!50000 EVENT event44331_2 */ +ON SCHEDULE AT CURRENT_TIMESTAMP +ON COMPLETION PRESERVE DISABLE +DO INSERT INTO test.t1 VALUES('event event44331_2 fired - DEFINER=CURRENT_USER'); +CREATE DEFINER=CURRENT_USER() EVENT event44331_3 +ON SCHEDULE AT CURRENT_TIMESTAMP +ON COMPLETION PRESERVE DISABLE +DO INSERT INTO test.t1 VALUES('event event44331_3 fired - DEFINER=CURRENT_USER() function'); +CREATE /*!50000 DEFINER='user44331' */ EVENT event44331_4 +ON SCHEDULE AT CURRENT_TIMESTAMP +ON COMPLETION PRESERVE DISABLE +DO INSERT INTO test.t1 VALUES('event event44331_4 fired - DEFINER=user1'); +Warnings: +Note 1449 The user specified as a definer ('user44331'@'%') does not exist +#on master +select EVENT_SCHEMA, EVENT_NAME, DEFINER from information_schema.events +where EVENT_NAME='event44331_1' || EVENT_NAME='event44331_2' || +EVENT_NAME='event44331_3' || EVENT_NAME='event44331_4'; +EVENT_SCHEMA EVENT_NAME DEFINER +test event44331_1 root@localhost +test event44331_2 root@localhost +test event44331_3 root@localhost +test event44331_4 user44331@% +#on slave +select EVENT_SCHEMA, EVENT_NAME, DEFINER from information_schema.events +where EVENT_NAME='event44331_1' || EVENT_NAME='event44331_2' || +EVENT_NAME='event44331_3' || EVENT_NAME='event44331_4'; +EVENT_SCHEMA EVENT_NAME DEFINER +test event44331_1 root@localhost +test event44331_2 root@localhost +test event44331_3 root@localhost +test event44331_4 user44331@% SET @@global.event_scheduler= @old_event_scheduler; DROP TABLE t28953; +DROP TABLE t1; +DROP EVENT event44331_1; +DROP EVENT event44331_2; +DROP EVENT event44331_3; +DROP EVENT event44331_4; diff --git a/mysql-test/suite/rpl/r/rpl_innodb_mixed_dml.result b/mysql-test/suite/rpl/r/rpl_innodb_mixed_dml.result index 6c5ab43da5f..81c486cb43c 100644 --- a/mysql-test/suite/rpl/r/rpl_innodb_mixed_dml.result +++ b/mysql-test/suite/rpl/r/rpl_innodb_mixed_dml.result @@ -690,7 +690,7 @@ test_rpl e1 root@localhost SYSTEM RECURRING NULL 1 # # NULL ENABLED 1 latin1 lat USE test_rpl; SHOW EVENTS; Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator character_set_client collation_connection Database Collation -test_rpl e1 @ SYSTEM RECURRING NULL 1 # # NULL SLAVESIDE_DISABLED 1 latin1 latin1_swedish_ci latin1_swedish_ci +test_rpl e1 root@localhost SYSTEM RECURRING NULL 1 # # NULL SLAVESIDE_DISABLED 1 latin1 latin1_swedish_ci latin1_swedish_ci ==========MASTER========== SELECT COUNT(*) FROM t1; COUNT(*) @@ -1078,7 +1078,7 @@ master-bin.000001 # Query 1 # use `test_rpl`; GRANT EVENT ON *.* TO 'root'@'loca master-bin.000001 # Query 1 # BEGIN master-bin.000001 # Query 1 # use `test_rpl`; INSERT INTO t1 VALUES(1, 'test1') master-bin.000001 # Xid 1 # # -master-bin.000001 # Query 1 # use `test_rpl`; CREATE EVENT e1 ON SCHEDULE EVERY '1' SECOND COMMENT 'e_second_comment' DO DELETE FROM t1 +master-bin.000001 # Query 1 # use `test_rpl`; CREATE DEFINER=`root`@`localhost` EVENT e1 ON SCHEDULE EVERY '1' SECOND COMMENT 'e_second_comment' DO DELETE FROM t1 master-bin.000001 # Query 1 # use `test_rpl`; ALTER EVENT e1 RENAME TO e2 master-bin.000001 # Query 1 # use `test_rpl`; DROP EVENT e2 master-bin.000001 # Query 1 # BEGIN diff --git a/mysql-test/suite/rpl/t/rpl_events.test b/mysql-test/suite/rpl/t/rpl_events.test index d06a3118389..f306fb10972 100644 --- a/mysql-test/suite/rpl/t/rpl_events.test +++ b/mysql-test/suite/rpl/t/rpl_events.test @@ -46,12 +46,52 @@ connection master; DROP EVENT event2; -sync_slave_with_master; +# +# BUG#44331 +# This test verifies if the definer is consistent between master and slave, +# when the event is created without the DEFINER clause set explicitly or the +# DEFINER is set to CURRENT_USER +# +CREATE TABLE test.t1(details CHAR(30)); -# Doing cleanup of the table referred to in the event to guarantee -# that there is no bad timing cauing it to try to access the table. +CREATE EVENT /*!50000 event44331_1 */ + ON SCHEDULE AT CURRENT_TIMESTAMP + ON COMPLETION PRESERVE DISABLE + DO INSERT INTO test.t1 VALUES('event event44331_1 fired - no definer'); + +CREATE DEFINER=CURRENT_USER /*!50000 EVENT event44331_2 */ + ON SCHEDULE AT CURRENT_TIMESTAMP + ON COMPLETION PRESERVE DISABLE + DO INSERT INTO test.t1 VALUES('event event44331_2 fired - DEFINER=CURRENT_USER'); + +CREATE DEFINER=CURRENT_USER() EVENT event44331_3 + ON SCHEDULE AT CURRENT_TIMESTAMP + ON COMPLETION PRESERVE DISABLE + DO INSERT INTO test.t1 VALUES('event event44331_3 fired - DEFINER=CURRENT_USER() function'); + +CREATE /*!50000 DEFINER='user44331' */ EVENT event44331_4 + ON SCHEDULE AT CURRENT_TIMESTAMP + ON COMPLETION PRESERVE DISABLE + DO INSERT INTO test.t1 VALUES('event event44331_4 fired - DEFINER=user1'); + +--echo #on master +select EVENT_SCHEMA, EVENT_NAME, DEFINER from information_schema.events + where EVENT_NAME='event44331_1' || EVENT_NAME='event44331_2' || + EVENT_NAME='event44331_3' || EVENT_NAME='event44331_4'; + +sync_slave_with_master; +connection slave; +--echo #on slave +select EVENT_SCHEMA, EVENT_NAME, DEFINER from information_schema.events + where EVENT_NAME='event44331_1' || EVENT_NAME='event44331_2' || + EVENT_NAME='event44331_3' || EVENT_NAME='event44331_4'; connection master; SET @@global.event_scheduler= @old_event_scheduler; DROP TABLE t28953; +DROP TABLE t1; +DROP EVENT event44331_1; +DROP EVENT event44331_2; +DROP EVENT event44331_3; +DROP EVENT event44331_4; sync_slave_with_master; diff --git a/sql/events.cc b/sql/events.cc index 10edfff2402..34da0e185b7 100644 --- a/sql/events.cc +++ b/sql/events.cc @@ -341,6 +341,33 @@ common_1_lev_code: } +/** + Create a new query string for removing executable comments + for avoiding leak and keeping consistency of the execution + on master and slave. + + @param[in] thd Thread handler + @param[in] buf Query string + + @return + 0 ok + 1 error +*/ +static int +create_query_string(THD *thd, String *buf) +{ + /* Append the "CREATE" part of the query */ + if (buf->append(STRING_WITH_LEN("CREATE "))) + return 1; + /* Append definer */ + append_definer(thd, buf, &(thd->lex->definer->user), &(thd->lex->definer->host)); + /* Append the left part of thd->query after "DEFINER" part */ + if (buf->append(thd->lex->stmt_definition_begin)) + return 1; + + return 0; +} + /** Create a new event. @@ -439,7 +466,16 @@ Events::create_event(THD *thd, Event_parse_data *parse_data, { /* Binlog the create event. */ DBUG_ASSERT(thd->query && thd->query_length); - write_bin_log(thd, TRUE, thd->query, thd->query_length); + String log_query; + if (create_query_string(thd, &log_query)) + { + sql_print_error("Event Error: An error occurred while creating query string, " + "before writing it into binary log."); + DBUG_RETURN(TRUE); + } + /* If the definer is not set or set to CURRENT_USER, the value of CURRENT_USER + will be written into the binary log as the definer for the SQL thread. */ + write_bin_log(thd, TRUE, log_query.c_ptr(), log_query.length()); } } pthread_mutex_unlock(&LOCK_event_metadata); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index c7e955d122d..a18f57bf9cf 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1809,15 +1809,16 @@ server_option: ; event_tail: - EVENT_SYM opt_if_not_exists sp_name + remember_name EVENT_SYM opt_if_not_exists sp_name { THD *thd= YYTHD; LEX *lex=Lex; - lex->create_info.options= $2; + lex->stmt_definition_begin= $1; + lex->create_info.options= $3; if (!(lex->event_parse_data= Event_parse_data::new_instance(thd))) MYSQL_YYABORT; - lex->event_parse_data->identifier= $3; + lex->event_parse_data->identifier= $4; lex->event_parse_data->on_completion= Event_parse_data::ON_COMPLETION_DROP; From 6ce48392ea410ecb9937ea07943cc6434a5ac378 Mon Sep 17 00:00:00 2001 From: Alexey Kopytov Date: Sun, 30 Aug 2009 11:03:37 +0400 Subject: [PATCH 35/69] Bug #46607: Assertion failed: (cond_type == Item::FUNC_ITEM) results in server crash check_group_min_max_predicates() assumed the input condition item to be one of COND_ITEM, SUBSELECT_ITEM, or FUNC_ITEM. Since a condition of the form "field" is also a valid condition equivalent to "field <> 0", using such a condition in a query where the loose index scan was chosen resulted in a debug assertion failure. Fixed by handling conditions of the FIELD_ITEM type in check_group_min_max_predicates(). mysql-test/r/group_min_max.result: Added a test case for bug #46607. mysql-test/t/group_min_max.test: Added a test case for bug #46607. sql/opt_range.cc: Handle conditions of the FUNC_ITEM type in check_group_mix_max_predicates(). --- mysql-test/r/group_min_max.result | 12 ++++++++++++ mysql-test/t/group_min_max.test | 15 +++++++++++++++ sql/opt_range.cc | 12 +++++++++++- 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/group_min_max.result b/mysql-test/r/group_min_max.result index 27448d3e949..ac9a53ca238 100644 --- a/mysql-test/r/group_min_max.result +++ b/mysql-test/r/group_min_max.result @@ -2502,3 +2502,15 @@ a MAX(b) 2 1 DROP TABLE t; End of 5.0 tests +# +# Bug #46607: Assertion failed: (cond_type == Item::FUNC_ITEM) results in +# server crash +# +CREATE TABLE t (a INT, b INT, INDEX (a,b)); +INSERT INTO t VALUES (2,0), (2,0), (2,1), (2,1); +INSERT INTO t SELECT * FROM t; +SELECT a, MAX(b) FROM t WHERE b GROUP BY a; +a MAX(b) +2 1 +DROP TABLE t; +End of 5.1 tests diff --git a/mysql-test/t/group_min_max.test b/mysql-test/t/group_min_max.test index 981be3efece..c09a4fbf490 100644 --- a/mysql-test/t/group_min_max.test +++ b/mysql-test/t/group_min_max.test @@ -1018,3 +1018,18 @@ DROP TABLE t; --echo End of 5.0 tests + +--echo # +--echo # Bug #46607: Assertion failed: (cond_type == Item::FUNC_ITEM) results in +--echo # server crash +--echo # + +CREATE TABLE t (a INT, b INT, INDEX (a,b)); +INSERT INTO t VALUES (2,0), (2,0), (2,1), (2,1); +INSERT INTO t SELECT * FROM t; + +SELECT a, MAX(b) FROM t WHERE b GROUP BY a; + +DROP TABLE t; + +--echo End of 5.1 tests diff --git a/sql/opt_range.cc b/sql/opt_range.cc index e3aef02637f..d7438b7b9cc 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -9628,7 +9628,17 @@ check_group_min_max_predicates(COND *cond, Item_field *min_max_arg_item, */ if (cond_type == Item::SUBSELECT_ITEM) DBUG_RETURN(FALSE); - + + /* + Condition of the form 'field' is equivalent to 'field <> 0' and thus + satisfies the SA3 condition. + */ + if (cond_type == Item::FIELD_ITEM) + { + DBUG_PRINT("info", ("Analyzing: %s", cond->full_name())); + DBUG_RETURN(TRUE); + } + /* We presume that at this point there are no other Items than functions. */ DBUG_ASSERT(cond_type == Item::FUNC_ITEM); From a00ba9ebea078f7dc12f7cd298782d1ada4bb4e9 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 31 Aug 2009 10:26:01 +0800 Subject: [PATCH 36/69] Bug #44331 Restore of database with events produces warning in replication Update the test case for BUG#44331 to fix the push build failure. --- mysql-test/suite/rpl/r/rpl_events.result | 24 ++++++++++++++++++++---- mysql-test/suite/rpl/t/rpl_events.test | 18 ++++++++++++++---- 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/mysql-test/suite/rpl/r/rpl_events.result b/mysql-test/suite/rpl/r/rpl_events.result index 8538d2ca373..b3fd85d7e28 100644 --- a/mysql-test/suite/rpl/r/rpl_events.result +++ b/mysql-test/suite/rpl/r/rpl_events.result @@ -212,21 +212,37 @@ Warnings: Note 1449 The user specified as a definer ('user44331'@'%') does not exist #on master select EVENT_SCHEMA, EVENT_NAME, DEFINER from information_schema.events -where EVENT_NAME='event44331_1' || EVENT_NAME='event44331_2' || -EVENT_NAME='event44331_3' || EVENT_NAME='event44331_4'; +where EVENT_NAME='event44331_1'; EVENT_SCHEMA EVENT_NAME DEFINER test event44331_1 root@localhost +select EVENT_SCHEMA, EVENT_NAME, DEFINER from information_schema.events +where EVENT_NAME='event44331_2'; +EVENT_SCHEMA EVENT_NAME DEFINER test event44331_2 root@localhost +select EVENT_SCHEMA, EVENT_NAME, DEFINER from information_schema.events +where EVENT_NAME='event44331_3'; +EVENT_SCHEMA EVENT_NAME DEFINER test event44331_3 root@localhost +select EVENT_SCHEMA, EVENT_NAME, DEFINER from information_schema.events +where EVENT_NAME='event44331_4'; +EVENT_SCHEMA EVENT_NAME DEFINER test event44331_4 user44331@% #on slave select EVENT_SCHEMA, EVENT_NAME, DEFINER from information_schema.events -where EVENT_NAME='event44331_1' || EVENT_NAME='event44331_2' || -EVENT_NAME='event44331_3' || EVENT_NAME='event44331_4'; +where EVENT_NAME='event44331_1'; EVENT_SCHEMA EVENT_NAME DEFINER test event44331_1 root@localhost +select EVENT_SCHEMA, EVENT_NAME, DEFINER from information_schema.events +where EVENT_NAME='event44331_2'; +EVENT_SCHEMA EVENT_NAME DEFINER test event44331_2 root@localhost +select EVENT_SCHEMA, EVENT_NAME, DEFINER from information_schema.events +where EVENT_NAME='event44331_3'; +EVENT_SCHEMA EVENT_NAME DEFINER test event44331_3 root@localhost +select EVENT_SCHEMA, EVENT_NAME, DEFINER from information_schema.events +where EVENT_NAME='event44331_4'; +EVENT_SCHEMA EVENT_NAME DEFINER test event44331_4 user44331@% SET @@global.event_scheduler= @old_event_scheduler; DROP TABLE t28953; diff --git a/mysql-test/suite/rpl/t/rpl_events.test b/mysql-test/suite/rpl/t/rpl_events.test index f306fb10972..7720ad6658c 100644 --- a/mysql-test/suite/rpl/t/rpl_events.test +++ b/mysql-test/suite/rpl/t/rpl_events.test @@ -76,15 +76,25 @@ CREATE /*!50000 DEFINER='user44331' */ EVENT event44331_4 --echo #on master select EVENT_SCHEMA, EVENT_NAME, DEFINER from information_schema.events - where EVENT_NAME='event44331_1' || EVENT_NAME='event44331_2' || - EVENT_NAME='event44331_3' || EVENT_NAME='event44331_4'; + where EVENT_NAME='event44331_1'; +select EVENT_SCHEMA, EVENT_NAME, DEFINER from information_schema.events + where EVENT_NAME='event44331_2'; +select EVENT_SCHEMA, EVENT_NAME, DEFINER from information_schema.events + where EVENT_NAME='event44331_3'; +select EVENT_SCHEMA, EVENT_NAME, DEFINER from information_schema.events + where EVENT_NAME='event44331_4'; sync_slave_with_master; connection slave; --echo #on slave select EVENT_SCHEMA, EVENT_NAME, DEFINER from information_schema.events - where EVENT_NAME='event44331_1' || EVENT_NAME='event44331_2' || - EVENT_NAME='event44331_3' || EVENT_NAME='event44331_4'; + where EVENT_NAME='event44331_1'; +select EVENT_SCHEMA, EVENT_NAME, DEFINER from information_schema.events + where EVENT_NAME='event44331_2'; +select EVENT_SCHEMA, EVENT_NAME, DEFINER from information_schema.events + where EVENT_NAME='event44331_3'; +select EVENT_SCHEMA, EVENT_NAME, DEFINER from information_schema.events + where EVENT_NAME='event44331_4'; connection master; SET @@global.event_scheduler= @old_event_scheduler; From d85148d84c88adebddbe4983efffdb5101d7963d Mon Sep 17 00:00:00 2001 From: "Tatiana A. Nurnberg" Date: Mon, 31 Aug 2009 10:01:13 -0700 Subject: [PATCH 37/69] Bug#35132: MySQLadmin --wait ping always crashes on Windows systems Failing to connect would release parts of the MYSQL struct. We would then proceed to try again to connect without re- initializing the struct. We prevent the unwanted freeing of data we'll still need now. client/mysqladmin.cc: Losing a connection (or not even getting on in the first place) should not trash the MYSQL-struct. Add a lot of comments. Rewrite re-connection fu. sql-common/client.c: Assert against bad parameters usually caused by de-initing a MYSQL-struct without re-initing it again before re-use. --- client/mysqladmin.cc | 128 +++++++++++++++++++++++++++++++++---------- sql-common/client.c | 9 +++ 2 files changed, 108 insertions(+), 29 deletions(-) diff --git a/client/mysqladmin.cc b/client/mysqladmin.cc index 699c2081b86..1ff9012780e 100644 --- a/client/mysqladmin.cc +++ b/client/mysqladmin.cc @@ -22,6 +22,7 @@ #endif #include #include +#include #ifdef LATER_HAVE_NDBCLUSTER_DB #include "../ndb/src/mgmclient/ndb_mgmclient.h" @@ -358,6 +359,11 @@ int main(int argc,char *argv[]) mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, default_charset); if (sql_connect(&mysql, option_wait)) { + /* + We couldn't get an initial connection and will definitely exit. + The following just determines the exit-code we'll give. + */ + unsigned int err= mysql_errno(&mysql); if (err >= CR_MIN_ERROR && err <= CR_MAX_ERROR) error= 1; @@ -376,30 +382,69 @@ int main(int argc,char *argv[]) } else { + /* + --count=0 aborts right here. Otherwise iff --sleep=t ("interval") + is given a t!=0, we get an endless loop, or n iterations if --count=n + was given an n!=0. If --sleep wasn't given, we get one iteration. + + To wit, --wait loops the connection-attempts, while --sleep loops + the command execution (endlessly if no --count is given). + */ + while (!interrupted && (!opt_count_iterations || nr_iterations)) { new_line = 0; - if ((error=execute_commands(&mysql,argc,commands))) + + if ((error= execute_commands(&mysql,argc,commands))) { + /* + Unknown/malformed command always aborts and can't be --forced. + If the user got confused about the syntax, proceeding would be + dangerous ... + */ if (error > 0) - break; /* Wrong command error */ - if (!option_force) + break; + + /* + Command was well-formed, but failed on the server. Might succeed + on retry (if conditions on server change etc.), but needs --force + to retry. + */ + if (!option_force) + break; + } /* if((error= ... */ + + if (interval) /* --sleep=interval given */ + { + /* + If connection was dropped (unintentionally, or due to SHUTDOWN), + re-establish it if --wait ("retry-connect") was given and user + didn't signal for us to die. Otherwise, signal failure. + */ + + if (mysql.net.vio == 0) { if (option_wait && !interrupted) { - mysql_close(&mysql); - if (!sql_connect(&mysql, option_wait)) - { - sleep(1); /* Don't retry too rapidly */ - continue; /* Retry */ - } + sleep(1); + sql_connect(&mysql, option_wait); + /* + continue normally and decrease counters so that + "mysqladmin --count=1 --wait=1 shutdown" + cannot loop endlessly. + */ } - error=1; - break; - } - } - if (interval) - { + else + { + /* + connexion broke, and we have no order to re-establish it. fail. + */ + if (!option_force) + error= 1; + break; + } + } /* lost connection */ + sleep(interval); if (new_line) puts(""); @@ -407,10 +452,11 @@ int main(int argc,char *argv[]) nr_iterations--; } else - break; - } - mysql_close(&mysql); - } + break; /* no --sleep, done looping */ + } /* command-loop */ + } /* got connection */ + + mysql_close(&mysql); my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR)); my_free(user,MYF(MY_ALLOW_ZERO_PTR)); #ifdef HAVE_SMEM @@ -428,6 +474,17 @@ static sig_handler endprog(int signal_number __attribute__((unused))) interrupted=1; } +/** + @brief connect to server, optionally waiting for same to come up + + @param mysql connection struct + @param wait wait for server to come up? + (0: no, ~0: forever, n: cycles) + + @return Operation result + @retval 0 success + @retval 1 failure +*/ static my_bool sql_connect(MYSQL *mysql, uint wait) { @@ -436,7 +493,7 @@ static my_bool sql_connect(MYSQL *mysql, uint wait) for (;;) { if (mysql_real_connect(mysql,host,user,opt_password,NullS,tcp_port, - unix_port, 0)) + unix_port, CLIENT_REMEMBER_OPTIONS)) { mysql->reconnect= 1; if (info) @@ -447,9 +504,9 @@ static my_bool sql_connect(MYSQL *mysql, uint wait) return 0; } - if (!wait) + if (!wait) // was or reached 0, fail { - if (!option_silent) + if (!option_silent) // print diagnostics { if (!host) host= (char*) LOCAL_HOST; @@ -473,11 +530,18 @@ static my_bool sql_connect(MYSQL *mysql, uint wait) } return 1; } + if (wait != (uint) ~0) - wait--; /* One less retry */ + wait--; /* count down, one less retry */ + if ((mysql_errno(mysql) != CR_CONN_HOST_ERROR) && (mysql_errno(mysql) != CR_CONNECTION_ERROR)) { + /* + Error is worse than "server doesn't answer (yet?)"; + fail even if we still have "wait-coins" unless --force + was also given. + */ fprintf(stderr,"Got error: %s\n", mysql_error(mysql)); if (!option_force) return 1; @@ -501,11 +565,18 @@ static my_bool sql_connect(MYSQL *mysql, uint wait) } -/* - Execute a command. - Return 0 on ok - -1 on retryable error - 1 on fatal error +/** + @brief Execute all commands + + @details We try to execute all commands we were given, in the order + given, but return with non-zero as soon as we encounter trouble. + By that token, individual commands can be considered a conjunction + with boolean short-cut. + + @return success? + @retval 0 Yes! ALL commands worked! + @retval 1 No, one failed and will never work (malformed): fatal error! + @retval -1 No, one failed on the server, may work next time! */ static int execute_commands(MYSQL *mysql,int argc, char **argv) @@ -575,7 +646,6 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv) mysql_error(mysql)); return -1; } - mysql_close(mysql); /* Close connection to avoid error messages */ argc=1; /* force SHUTDOWN to be the last command */ if (got_pidfile) { diff --git a/sql-common/client.c b/sql-common/client.c index 8f1f4a1fd5a..89de74ebd58 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -416,6 +416,15 @@ HANDLE create_shared_memory(MYSQL *mysql,NET *net, uint connect_timeout) const char *prefix; int i; + /* + If this is NULL, somebody freed the MYSQL* options. mysql_close() + is a good candidate. We don't just silently (re)set it to + def_shared_memory_base_name as that would create really confusing/buggy + behavior if the user passed in a different name on the command-line or + in a my.cnf. + */ + DBUG_ASSERT(shared_memory_base_name != NULL); + /* get enough space base-name + '_' + longest suffix we might ever send */ From 82a5cfa5ab5eb62b5de3d440cc842a07643cb0bb Mon Sep 17 00:00:00 2001 From: Mattias Jonsson Date: Tue, 1 Sep 2009 13:04:56 +0200 Subject: [PATCH 38/69] Post fix patch for bug#20577 and bug#46362. On 64-bits machines the calculation gets the wrong types and results in very large numbers. Fixed by explicitly cast month to (int) --- sql-common/my_time.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sql-common/my_time.c b/sql-common/my_time.c index 18358519023..2ec1fc253a7 100644 --- a/sql-common/my_time.c +++ b/sql-common/my_time.c @@ -775,11 +775,12 @@ long calc_daynr(uint year,uint month,uint day) if (y == 0 && month == 0 && day == 0) DBUG_RETURN(0); /* Skip errors */ - delsum= (long) (365L * y+ 31*(month-1) +day); + /* Cast to int to be able to handle month == 0 */ + delsum= (long) (365 * y + 31 *((int) month - 1) + (int) day); if (month <= 2) y--; else - delsum-= (long) (month*4+23)/10; + delsum-= (long) ((int) month * 4 + 23) / 10; temp=(int) ((y/100+1)*3)/4; DBUG_PRINT("exit",("year: %d month: %d day: %d -> daynr: %ld", y+(month <= 2),month,day,delsum+y/4-temp)); From 8c7c09cc636a745fb88e00a5e0a2b2738ab5945e Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Tue, 1 Sep 2009 09:32:26 -0300 Subject: [PATCH 39/69] Bug#45611: Minor code cleanup Remove a self assignment. Rework a few constructs to avoid a potential overflow. Based upon patch contributed by Michal Hrusecky storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp: Remove self assignment, the object is being initialized. storage/ndb/src/mgmsrv/InitConfigFileParser.cpp: Setup the string in a single snprintf. --- storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp | 4 ++-- storage/ndb/src/mgmsrv/InitConfigFileParser.cpp | 7 +++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp b/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp index a61a5bc035c..8f8d4aad9ab 100644 --- a/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp +++ b/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp @@ -7521,8 +7521,8 @@ void Dbdict::execGET_TABINFOREQ(Signal* signal) return; } releaseSections(signal); - - DictObject * old_ptr_p = old_ptr_p = get_object(tableName, len); + + DictObject * old_ptr_p = get_object(tableName, len); if(old_ptr_p) obj_id = old_ptr_p->m_id; } else { diff --git a/storage/ndb/src/mgmsrv/InitConfigFileParser.cpp b/storage/ndb/src/mgmsrv/InitConfigFileParser.cpp index 569cb1eb654..560a9559999 100644 --- a/storage/ndb/src/mgmsrv/InitConfigFileParser.cpp +++ b/storage/ndb/src/mgmsrv/InitConfigFileParser.cpp @@ -208,11 +208,10 @@ InitConfigFileParser::run_config_rules(Context& ctx) ctx.m_config->put("NoOfNodes", nNodes); char tmpLine[MAX_LINE_LENGTH]; - BaseString::snprintf(tmpLine, MAX_LINE_LENGTH, "EXTERNAL SYSTEM_"); - strncat(tmpLine, system, MAX_LINE_LENGTH); - strncat(tmpLine, ":NoOfConnections", MAX_LINE_LENGTH); + BaseString::snprintf(tmpLine, MAX_LINE_LENGTH, + "EXTERNAL SYSTEM_%s:NoOfConnections", system); ctx.m_config->put(tmpLine, nExtConnections); - + Config * ret = new Config(); ret->m_configValues = (struct ndb_mgm_configuration*)ctx.m_configValues.getConfigValues(); ret->m_oldConfig = ctx.m_config; ctx.m_config = 0; From 2c6789aa3bcfcd21dd3c913ffe567e352b0a9280 Mon Sep 17 00:00:00 2001 From: Mattias Jonsson Date: Tue, 1 Sep 2009 14:53:27 +0200 Subject: [PATCH 40/69] post push fix for bug#20577 and bug#46362, disabling warnings --- mysql-test/include/partition_date_range.inc | 6 ++++++ mysql-test/r/partition_pruning.result | 12 ++++++++---- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/mysql-test/include/partition_date_range.inc b/mysql-test/include/partition_date_range.inc index c54396af9cb..5093cb3701d 100644 --- a/mysql-test/include/partition_date_range.inc +++ b/mysql-test/include/partition_date_range.inc @@ -21,6 +21,8 @@ SELECT * FROM t1 WHERE a >= '1001-00-00'; SELECT * FROM t1 WHERE a > '1001-00-00'; --sorted_result SELECT * FROM t1 WHERE a = '1001-00-00'; +--echo # Disabling warnings for the invalid date +--disable_warnings --sorted_result SELECT * FROM t1 WHERE a < '1999-02-31'; --sorted_result @@ -31,6 +33,7 @@ SELECT * FROM t1 WHERE a >= '1999-02-31'; SELECT * FROM t1 WHERE a > '1999-02-31'; --sorted_result SELECT * FROM t1 WHERE a = '1999-02-31'; +--enable_warnings --sorted_result SELECT * FROM t1 WHERE a BETWEEN '0000-00-00' AND '1002-00-00'; --sorted_result @@ -51,11 +54,14 @@ EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= '1001-00-00'; EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= '1001-00-00'; EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > '1001-00-00'; EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = '1001-00-00'; +--echo # Disabling warnings for the invalid date +--disable_warnings EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < '1999-02-31'; EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= '1999-02-31'; EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= '1999-02-31'; EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > '1999-02-31'; EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = '1999-02-31'; +--enable_warnings EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a BETWEEN '0000-00-00' AND '1002-00-00'; EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a BETWEEN '0000-00-00' AND '1001-01-01'; EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a BETWEEN '0001-01-02' AND '1002-00-00'; diff --git a/mysql-test/r/partition_pruning.result b/mysql-test/r/partition_pruning.result index 86aa89be8a7..769d499fc0a 100644 --- a/mysql-test/r/partition_pruning.result +++ b/mysql-test/r/partition_pruning.result @@ -58,6 +58,7 @@ a SELECT * FROM t1 WHERE a = '1001-00-00'; a 1001-00-00 +# Disabling warnings for the invalid date SELECT * FROM t1 WHERE a < '1999-02-31'; a 0000-00-00 @@ -82,8 +83,6 @@ a 2001-01-01 SELECT * FROM t1 WHERE a = '1999-02-31'; a -Warning 1292 Incorrect date value: '1999-02-31' for column 'a' at row 1 -Warnings: SELECT * FROM t1 WHERE a BETWEEN '0000-00-00' AND '1002-00-00'; a 0000-00-00 @@ -139,6 +138,7 @@ id select_type table partitions type possible_keys key key_len ref rows Extra EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = '1001-00-00'; id select_type table partitions type possible_keys key key_len ref rows Extra 1 SIMPLE t1 pNULL ref a a 4 const 1 Using where; Using index +# Disabling warnings for the invalid date EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < '1999-02-31'; id select_type table partitions type possible_keys key key_len ref rows Extra 1 SIMPLE t1 pNULL,p0001-01-01,p1001-01-01,p2001-01-01 range a a 4 NULL 5 Using where; Using index @@ -218,6 +218,7 @@ a SELECT * FROM t1 WHERE a = '1001-00-00'; a 1001-00-00 +# Disabling warnings for the invalid date SELECT * FROM t1 WHERE a < '1999-02-31'; a 0000-00-00 @@ -297,6 +298,7 @@ id select_type table partitions type possible_keys key key_len ref rows Extra EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = '1001-00-00'; id select_type table partitions type possible_keys key key_len ref rows Extra 1 SIMPLE t1 pNULL ALL NULL NULL NULL NULL 7 Using where +# Disabling warnings for the invalid date EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < '1999-02-31'; id select_type table partitions type possible_keys key key_len ref rows Extra 1 SIMPLE t1 pNULL,p0001-01-01,p1001-01-01,p2001-01-01 ALL NULL NULL NULL NULL 7 Using where @@ -385,6 +387,7 @@ a SELECT * FROM t1 WHERE a = '1001-00-00'; a 1001-00-00 +# Disabling warnings for the invalid date SELECT * FROM t1 WHERE a < '1999-02-31'; a 0000-00-00 @@ -409,8 +412,6 @@ a 2001-01-01 SELECT * FROM t1 WHERE a = '1999-02-31'; a -Warning 1292 Incorrect date value: '1999-02-31' for column 'a' at row 1 -Warnings: SELECT * FROM t1 WHERE a BETWEEN '0000-00-00' AND '1002-00-00'; a 0000-00-00 @@ -466,6 +467,7 @@ id select_type table partitions type possible_keys key key_len ref rows Extra EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = '1001-00-00'; id select_type table partitions type possible_keys key key_len ref rows Extra 1 SIMPLE t1 pNULL ref a a 4 const 1 Using where; Using index +# Disabling warnings for the invalid date EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < '1999-02-31'; id select_type table partitions type possible_keys key key_len ref rows Extra 1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02,p1001-01-01 range a a 4 NULL 5 Using where; Using index @@ -545,6 +547,7 @@ a SELECT * FROM t1 WHERE a = '1001-00-00'; a 1001-00-00 +# Disabling warnings for the invalid date SELECT * FROM t1 WHERE a < '1999-02-31'; a 0000-00-00 @@ -624,6 +627,7 @@ id select_type table partitions type possible_keys key key_len ref rows Extra EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = '1001-00-00'; id select_type table partitions type possible_keys key key_len ref rows Extra 1 SIMPLE t1 pNULL ALL NULL NULL NULL NULL 7 Using where +# Disabling warnings for the invalid date EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < '1999-02-31'; id select_type table partitions type possible_keys key key_len ref rows Extra 1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02,p1001-01-01 ALL NULL NULL NULL NULL 7 Using where From c001f9cc16a345a08e51a4bf1a6b2642038aacfc Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Tue, 1 Sep 2009 16:39:13 +0300 Subject: [PATCH 41/69] Fixed a problem in how BUILD/check_cpu handles Core 2 Duo processors. This fixes the regression introduced in 5.1 that prevents 64 bit builds on Intel while still keeping the core2 hack operational so the cluster can build. --- BUILD/check-cpu | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/BUILD/check-cpu b/BUILD/check-cpu index 9fa48adfb5f..c0e87a675cb 100755 --- a/BUILD/check-cpu +++ b/BUILD/check-cpu @@ -70,6 +70,11 @@ check_cpu () { Alpha*EV6*) cpu_arg="ev6"; ;; + #Core 2 Duo + *Intel*Core\(TM\)2*) + cpu_arg="nocona" + core2="yes" + ;; # Intel ia32 *Intel*Core*|*X[eE][oO][nN]*) # a Xeon is just another pentium4 ... @@ -134,10 +139,6 @@ check_cpu () { *i386*) cpu_arg="i386" ;; - #Core 2 Duo - *Intel*Core\(TM\)2*) - cpu_arg="nocona" - ;; # Intel ia64 *Itanium*) cpu_arg="itanium" From 27065edafbe0bfaa2a0fab4b230d910a21014c90 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Wed, 2 Sep 2009 13:09:01 +0300 Subject: [PATCH 42/69] fixed compilation warnings --- tests/mysql_client_test.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 300b0347233..9394b0df40b 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -16997,7 +16997,7 @@ static void test_bug20023() { MYSQL con; - int sql_big_selects_orig; + int sql_big_selects_orig= 0; /* Type of max_join_size is ha_rows, which might be ulong or off_t depending on the platform or configure options. Preserve the string @@ -17005,10 +17005,10 @@ static void test_bug20023() */ char max_join_size_orig[32]; - int sql_big_selects_2; - int sql_big_selects_3; - int sql_big_selects_4; - int sql_big_selects_5; + int sql_big_selects_2= 0; + int sql_big_selects_3= 0; + int sql_big_selects_4= 0; + int sql_big_selects_5= 0; char query_buffer[MAX_TEST_QUERY_LENGTH]; @@ -17147,7 +17147,7 @@ static void bug31418_impl() MYSQL con; my_bool is_null; - int rc; + int rc= 0; /* Create a new connection. */ From f0720480dc641195999086b5c36d3d6a03b1a935 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Wed, 2 Sep 2009 13:22:47 +0300 Subject: [PATCH 43/69] Fixed win32 compilation warnings --- mysys/my_redel.c | 2 ++ sql/sql_table.cc | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/mysys/my_redel.c b/mysys/my_redel.c index c03d1bc7c25..6521253f949 100644 --- a/mysys/my_redel.c +++ b/mysys/my_redel.c @@ -76,7 +76,9 @@ end: int my_copystat(const char *from, const char *to, int MyFlags) { struct stat statbuf; +#if !defined(__WIN__) && !defined(__NETWARE__) int res; +#endif if (stat((char*) from, &statbuf)) { diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 9f88fa93c06..4ec104aedc3 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -117,7 +117,7 @@ static char* add_identifier(char *to_p, const char * end_p, *(to_p++)= '`'; *(to_p++)= *(conv_name++); } - else if (length < (end_p - to_p)) + else if (((long) length) < (end_p - to_p)) { to_p= strnmov(to_p, conv_name, length); conv_name+= length; From 453a941d50dc8ad60539812736021d74598f9ba7 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Wed, 2 Sep 2009 13:23:37 +0300 Subject: [PATCH 44/69] moved version to 5.0-main --- .bzr-mysql/default.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.bzr-mysql/default.conf b/.bzr-mysql/default.conf index 557df1b1ffe..f79c1cd6319 100644 --- a/.bzr-mysql/default.conf +++ b/.bzr-mysql/default.conf @@ -1,4 +1,4 @@ [MYSQL] post_commit_to = "commits@lists.mysql.com" post_push_to = "commits@lists.mysql.com" -tree_name = "mysql-5.0-bugteam" +tree_name = "mysql-5.0" From 3668f8a5be32bc273d0ae29c85be3ab7ec5b3cd0 Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Wed, 2 Sep 2009 08:45:48 -0300 Subject: [PATCH 45/69] Increase thread stack size on HP-UX when built with debug. --- storage/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/storage/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp b/storage/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp index 5300d5bbfd9..c107baca39f 100644 --- a/storage/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp +++ b/storage/ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp @@ -106,8 +106,13 @@ void AsyncFile::doStart() { // Stacksize for filesystem threads - // An 8k stack should be enough +#if !defined(DBUG_OFF) && defined (__hpux) + // Empirical evidence indicates at least 32k + const NDB_THREAD_STACKSIZE stackSize = 32768; +#else + // Otherwise an 8k stack should be enough const NDB_THREAD_STACKSIZE stackSize = 8192; +#endif char buf[16]; numAsyncFiles++; From e512d6943447aae62c77b98bc75512387b991cdc Mon Sep 17 00:00:00 2001 From: Davi Arnaut Date: Wed, 2 Sep 2009 09:02:22 -0300 Subject: [PATCH 46/69] Post-merge fix. Observe C declaration placement rules. --- mysys/mf_iocache.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/mysys/mf_iocache.c b/mysys/mf_iocache.c index 3aab904a6e0..c4c48f9c121 100644 --- a/mysys/mf_iocache.c +++ b/mysys/mf_iocache.c @@ -228,18 +228,20 @@ int init_io_cache(IO_CACHE *info, File file, uint cachesize, for (;;) { uint buffer_block; + /* + Unset MY_WAIT_IF_FULL bit if it is set, to prevent conflict with + MY_ZEROFILL. + */ + myf flags= (myf) (cache_myflags & ~(MY_WME | MY_WAIT_IF_FULL)); + if (cachesize < min_cache) cachesize = min_cache; buffer_block = cachesize; if (type == SEQ_READ_APPEND) buffer_block *= 2; - /* - Unset MY_WAIT_IF_FULL bit if it is set, to prevent conflict with - MY_ZEROFILL. - */ - myf flag = MYF((cache_myflags & ~ (MY_WME | MY_WAIT_IF_FULL)) | - (cachesize == min_cache ? MY_WME : 0)); - if ((info->buffer= (byte*) my_malloc(buffer_block, flag)) != 0) + if (cachesize == min_cache) + flags|= (myf) MY_WME; + if ((info->buffer= (byte*) my_malloc(buffer_block, flags)) != 0) { info->write_buffer=info->buffer; if (type == SEQ_READ_APPEND) From 7c9e39f5c5a57c1d68c146b3982d643f93750eda Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Wed, 2 Sep 2009 15:20:47 +0300 Subject: [PATCH 47/69] fixed a valgrind warning in partitioning code --- sql/sql_partition.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index d433ba0b0cc..08ff2daacb9 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -6909,6 +6909,7 @@ int get_part_iter_for_interval_via_walking(partition_info *part_info, Field *field; uint total_parts; partition_iter_func get_next_func; + part_iter->ret_null_part= part_iter->ret_null_part_orig= FALSE; if (is_subpart) { field= part_info->subpart_field_array[0]; From 183607b8c864684a67fea2c11fa2755abd11f6ab Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Wed, 2 Sep 2009 16:36:52 +0300 Subject: [PATCH 48/69] Backported the --parallel=str option from mtr2 for backward compatibility with the newer pb2 testing environments --- mysql-test/mysql-test-run.pl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index f60701b7b49..e98e05eadb1 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -302,6 +302,7 @@ our $debug_compiled_binaries; our %mysqld_variables; +our $opt_parallel; my $source_dist= 0; our $opt_max_save_core= 5; @@ -645,6 +646,7 @@ sub command_line_setup () { 'testcase-timeout=i' => \$opt_testcase_timeout, 'suite-timeout=i' => \$opt_suite_timeout, 'warnings|log-warnings' => \$opt_warnings, + 'parallel=s' => \$opt_parallel, # Options which are no longer used (map { $_ => \&warn_about_removed_option } @removed_options), @@ -5278,6 +5280,7 @@ Misc options the specified test case (if any) fast Don't try to clean up from earlier runs reorder Reorder tests to get fewer server restarts + parallel=STR Compatibility slot. Ignored. help Get this help text testcase-timeout=MINUTES Max test case run time (default $default_testcase_timeout) From b64e7fb5befaee89f1db90db05e80e4249feba77 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Wed, 2 Sep 2009 18:42:08 +0300 Subject: [PATCH 49/69] fixed a valgrind warning in partition_pruning --- sql/partition_info.h | 1 + 1 file changed, 1 insertion(+) diff --git a/sql/partition_info.h b/sql/partition_info.h index 8832b6ee409..9f438e8260b 100644 --- a/sql/partition_info.h +++ b/sql/partition_info.h @@ -311,5 +311,6 @@ void init_all_partitions_iterator(partition_info *part_info, { part_iter->part_nums.start= part_iter->part_nums.cur= 0; part_iter->part_nums.end= part_info->no_parts; + part_iter->ret_null_part= part_iter->ret_null_part_orig= FALSE; part_iter->get_next= get_next_partition_id_range; } From c7d32876f345785580a7cf286542ccf390b4e1fa Mon Sep 17 00:00:00 2001 From: Jonathan Perkin Date: Fri, 4 Sep 2009 17:45:07 +0200 Subject: [PATCH 50/69] Install mysqld.lib --- scripts/make_win_bin_dist | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/make_win_bin_dist b/scripts/make_win_bin_dist index 9c17c26b445..fdb34f2f48d 100755 --- a/scripts/make_win_bin_dist +++ b/scripts/make_win_bin_dist @@ -280,6 +280,7 @@ cp include/mysql/plugin.h $DESTDIR/include/mysql/ mkdir -p $DESTDIR/lib/opt mkdir -p $DESTDIR/lib/plugin +cp sql/$TARGET/mysqld.lib $DESTDIR/lib/ cp libmysql/$TARGET/libmysql.dll \ libmysql/$TARGET/libmysql.lib \ libmysql/$TARGET/mysqlclient.lib \ From 79181a1c6956be5dc6b439a35947f90dc1f75b8d Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 16 Oct 2009 14:45:42 +0200 Subject: [PATCH 51/69] After-merge fixes for MySQL 5.1.39 merge. Some pbxt test suite files needed updating due to similar changes after bugfixes in MySQL 5.1.39. --- mysql-test/suite/pbxt/r/partition_range.result | 4 ++-- mysql-test/suite/pbxt/r/subselect.result | 2 +- mysql-test/suite/pbxt/t/subselect.test | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/mysql-test/suite/pbxt/r/partition_range.result b/mysql-test/suite/pbxt/r/partition_range.result index f204be71e4f..4f41c667a5d 100644 --- a/mysql-test/suite/pbxt/r/partition_range.result +++ b/mysql-test/suite/pbxt/r/partition_range.result @@ -710,7 +710,7 @@ a EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= '2004-07-01' AND a <= '2004-09-30'; id select_type table partitions type possible_keys key key_len ref rows Extra -1 SIMPLE t1 p407,p408,p409 ALL NULL NULL NULL NULL 9 Using where +1 SIMPLE t1 p3xx,p407,p408,p409 ALL NULL NULL NULL NULL 18 Using where SELECT * from t1 WHERE (a >= '2004-07-01' AND a <= '2004-09-30') OR (a >= '2005-07-01' AND a <= '2005-09-30'); @@ -737,5 +737,5 @@ EXPLAIN PARTITIONS SELECT * from t1 WHERE (a >= '2004-07-01' AND a <= '2004-09-30') OR (a >= '2005-07-01' AND a <= '2005-09-30'); id select_type table partitions type possible_keys key key_len ref rows Extra -1 SIMPLE t1 p407,p408,p409,p507,p508,p509 ALL NULL NULL NULL NULL 18 Using where +1 SIMPLE t1 p3xx,p407,p408,p409,p507,p508,p509 ALL NULL NULL NULL NULL 27 Using where DROP TABLE t1; diff --git a/mysql-test/suite/pbxt/r/subselect.result b/mysql-test/suite/pbxt/r/subselect.result index bae93f76b2c..bb2073030e3 100644 --- a/mysql-test/suite/pbxt/r/subselect.result +++ b/mysql-test/suite/pbxt/r/subselect.result @@ -75,7 +75,7 @@ SELECT 1 FROM (SELECT 1 as a) b WHERE 1 IN (SELECT (SELECT a)); select (SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE(1)); ERROR HY000: Incorrect usage of PROCEDURE and subquery SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE((SELECT 1)); -ERROR HY000: Incorrect parameters to procedure 'ANALYSE' +ERROR HY000: Incorrect usage of PROCEDURE and subquery SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NULL; ERROR 42S22: Unknown column 'a' in 'field list' SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NOT NULL; diff --git a/mysql-test/suite/pbxt/t/subselect.test b/mysql-test/suite/pbxt/t/subselect.test index 708d3214cf7..c0e61de9872 100644 --- a/mysql-test/suite/pbxt/t/subselect.test +++ b/mysql-test/suite/pbxt/t/subselect.test @@ -30,7 +30,7 @@ SELECT 1 IN (SELECT 1); SELECT 1 FROM (SELECT 1 as a) b WHERE 1 IN (SELECT (SELECT a)); -- error 1221 select (SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE(1)); --- error 1108 +-- error ER_WRONG_USAGE SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE((SELECT 1)); -- error ER_BAD_FIELD_ERROR SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NULL; From 51186f1d3d38d4fbd4e9f0ff1a67c78ea9920fbf Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 16 Oct 2009 17:01:36 +0200 Subject: [PATCH 52/69] When running with --skip-safemalloc, still do some basic, but cheap, overrun checks. This greatly helps with eg. slow hosts in Buildbot. --- mysys/safemalloc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mysys/safemalloc.c b/mysys/safemalloc.c index a69051e6674..627e860fac8 100644 --- a/mysys/safemalloc.c +++ b/mysys/safemalloc.c @@ -272,6 +272,9 @@ void _myfree(void *ptr, const char *filename, uint lineno, myf myflags) irem= (struct st_irem *) ((char*) ptr- ALIGN_SIZE(sizeof(struct st_irem))- sf_malloc_prehunc); + if (sf_malloc_quick) + (void) _checkchunk(irem, filename, lineno); + /* Check to make sure that we have a real remember structure. Note: this test could fail for four reasons: From b587e79bc921b94032e40af7bbb54e807fcacee0 Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Mon, 26 Oct 2009 17:01:05 +0200 Subject: [PATCH 53/69] Added symbolic link to from scripts/mysql_install_db to bin to address a documented problem Test if libexec exists, to go around problem if configure was done with --libexecdir=/usr/local/mysql/bin --- scripts/make_binary_distribution.sh | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/scripts/make_binary_distribution.sh b/scripts/make_binary_distribution.sh index 9595a56ef62..0f35270b4e8 100644 --- a/scripts/make_binary_distribution.sh +++ b/scripts/make_binary_distribution.sh @@ -293,11 +293,6 @@ if [ x"$BASE_SYSTEM" != x"netware" ] ; then fi fi - # FIXME let this script be in "bin/", where it is in the RPMs? - # http://dev.mysql.com/doc/refman/5.1/en/mysql-install-db-problems.html - mkdir $DEST/scripts - mv $DEST/bin/mysql_install_db $DEST/scripts/ - # Note, no legacy "safe_mysqld" link to "mysqld_safe" in 5.1 # Copy readme and license files @@ -330,18 +325,25 @@ if [ x"$BASE_SYSTEM" != x"netware" ] ; then # # Move things to make them easier to find in tar installation # - mv $DEST/libexec/* $DEST/bin + + # The following test is needed if the original configure was done with + # something like --libexecdir=/usr/local/mysql/bin + if test -f $DEST/libexec/mysqld + then + mv $DEST/libexec/* $DEST/bin + rmdir $DEST/libexec + fi mv $DEST/share/man $DEST mv $DEST/share/mysql/binary-configure $DEST/configure mv $DEST/share/mysql/*.sql $DEST/share mv $DEST/share/mysql/*.cnf $DEST/share/mysql/*.server $DEST/share/mysql/mysql-log-rotate $DEST/support-files - rmdir $DEST/libexec # # Move some scripts that are only run once to 'scripts' directory # but add symbolic links instead to old place for compatibility # - for i in mysql_secure_installation mysql_fix_extensions mysql_fix_privilege_tables + mkdir $DEST/scripts + for i in mysql_secure_installation mysql_fix_extensions mysql_fix_privilege_tables mysql_install_db do mv $DEST/bin/$i $DEST/scripts ln -s "../scripts/$i" $DEST/bin/$i From 358327618d5a71138be6ca27a4c8472723b67c45 Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Wed, 28 Oct 2009 09:52:34 +0200 Subject: [PATCH 54/69] Speed up of test suite: - Added --disable_query_log ; begin ; .... commit; --enable_query_log around all while loops that does insert --- mysql-test/r/alter_table.result | 110 ----- mysql-test/r/func_misc.result | 4 - mysql-test/r/gis-rtree.result | 450 ----------------- mysql-test/r/innodb_xtradb_bug317074.result | 27 ++ mysql-test/r/merge.result | 50 -- mysql-test/r/myisam_debug.result | 10 - mysql-test/suite/parts/inc/partition.pre | 2 + .../suite/parts/inc/partition_bigint.inc | 2 + .../suite/parts/inc/partition_binary.inc | 16 +- mysql-test/suite/parts/inc/partition_bit.inc | 4 + mysql-test/suite/parts/inc/partition_char.inc | 15 +- mysql-test/suite/parts/inc/partition_date.inc | 14 +- .../suite/parts/inc/partition_datetime.inc | 13 +- .../suite/parts/inc/partition_decimal.inc | 8 + .../suite/parts/inc/partition_double.inc | 10 + mysql-test/suite/parts/inc/partition_enum.inc | 10 +- .../suite/parts/inc/partition_float.inc | 10 + mysql-test/suite/parts/inc/partition_int.inc | 2 + .../suite/parts/inc/partition_mediumint.inc | 2 + .../suite/parts/inc/partition_smallint.inc | 2 + mysql-test/suite/parts/inc/partition_time.inc | 13 +- .../suite/parts/inc/partition_timestamp.inc | 13 +- .../suite/parts/inc/partition_tinyint.inc | 2 + .../suite/parts/inc/partition_varbinary.inc | 15 +- .../suite/parts/inc/partition_varchar.inc | 15 +- mysql-test/suite/parts/inc/partition_year.inc | 2 + .../parts/r/partition_char_innodb.result | Bin 57481 -> 50278 bytes .../parts/r/partition_char_myisam.result | Bin 57481 -> 50278 bytes .../parts/r/partition_datetime_innodb.result | 451 ------------------ .../parts/r/partition_datetime_myisam.result | 451 ------------------ .../t/part_supported_sql_func_innodb.test | 2 + .../parts/t/partition_alter1_1_2_innodb.test | 2 + .../parts/t/partition_alter4_myisam.test | 2 + mysql-test/t/almost_full.test | 2 + mysql-test/t/alter_table.test | 10 + mysql-test/t/archive.test | 2 + mysql-test/t/bench_count_distinct.test | 6 +- mysql-test/t/change_user.test | 4 +- mysql-test/t/check.test | 6 +- mysql-test/t/count_distinct2.test | 12 +- mysql-test/t/count_distinct3.test | 3 +- mysql-test/t/ctype_euckr.test | 2 + mysql-test/t/derived.test | 6 +- mysql-test/t/events_time_zone.test | 2 + mysql-test/t/fulltext2.test | 4 + mysql-test/t/func_misc.test | 4 + mysql-test/t/gis-rtree.test | 12 + mysql-test/t/heap.test | 13 +- mysql-test/t/innodb_xtradb_bug317074.test | 13 +- mysql-test/t/insert.test | 7 +- mysql-test/t/kill.test | 6 + mysql-test/t/merge.test | 4 + mysql-test/t/multi_update.test | 12 +- mysql-test/t/multi_update2.test | 3 +- mysql-test/t/myisam.test | 18 +- mysql-test/t/myisam_debug.test | 4 + mysql-test/t/myisampack.test | 2 + mysql-test/t/order_by.test | 6 +- mysql-test/t/order_fill_sortbuf.test | 6 +- mysql-test/t/partition.test | 4 + mysql-test/t/partition_archive.test | 2 + mysql-test/t/select_found.test | 6 +- mysql-test/t/sp-big.test | 2 + mysql-test/t/subselect.test | 14 +- mysql-test/t/warnings.test | 6 +- 65 files changed, 341 insertions(+), 1591 deletions(-) diff --git a/mysql-test/r/alter_table.result b/mysql-test/r/alter_table.result index 18c137614fc..b1e13f0f879 100644 --- a/mysql-test/r/alter_table.result +++ b/mysql-test/r/alter_table.result @@ -143,16 +143,6 @@ t1 1 n4 1 n4 A NULL NULL NULL YES BTREE disabled t1 1 n4 2 n1 A NULL NULL NULL BTREE disabled t1 1 n4 3 n2 A NULL NULL NULL YES BTREE disabled t1 1 n4 4 n3 A NULL NULL NULL YES BTREE disabled -insert into t1 values(10,RAND()*1000,RAND()*1000,RAND()); -insert into t1 values(9,RAND()*1000,RAND()*1000,RAND()); -insert into t1 values(8,RAND()*1000,RAND()*1000,RAND()); -insert into t1 values(7,RAND()*1000,RAND()*1000,RAND()); -insert into t1 values(6,RAND()*1000,RAND()*1000,RAND()); -insert into t1 values(5,RAND()*1000,RAND()*1000,RAND()); -insert into t1 values(4,RAND()*1000,RAND()*1000,RAND()); -insert into t1 values(3,RAND()*1000,RAND()*1000,RAND()); -insert into t1 values(2,RAND()*1000,RAND()*1000,RAND()); -insert into t1 values(1,RAND()*1000,RAND()*1000,RAND()); alter table t1 enable keys; show keys from t1; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment @@ -183,106 +173,6 @@ i int(10) unsigned NO PRI NULL auto_increment c char(10) YES NULL drop table t1; create table t1 (a int, b int); -insert into t1 values(1,100), (2,100), (3, 100); -insert into t1 values(1,99), (2,99), (3, 99); -insert into t1 values(1,98), (2,98), (3, 98); -insert into t1 values(1,97), (2,97), (3, 97); -insert into t1 values(1,96), (2,96), (3, 96); -insert into t1 values(1,95), (2,95), (3, 95); -insert into t1 values(1,94), (2,94), (3, 94); -insert into t1 values(1,93), (2,93), (3, 93); -insert into t1 values(1,92), (2,92), (3, 92); -insert into t1 values(1,91), (2,91), (3, 91); -insert into t1 values(1,90), (2,90), (3, 90); -insert into t1 values(1,89), (2,89), (3, 89); -insert into t1 values(1,88), (2,88), (3, 88); -insert into t1 values(1,87), (2,87), (3, 87); -insert into t1 values(1,86), (2,86), (3, 86); -insert into t1 values(1,85), (2,85), (3, 85); -insert into t1 values(1,84), (2,84), (3, 84); -insert into t1 values(1,83), (2,83), (3, 83); -insert into t1 values(1,82), (2,82), (3, 82); -insert into t1 values(1,81), (2,81), (3, 81); -insert into t1 values(1,80), (2,80), (3, 80); -insert into t1 values(1,79), (2,79), (3, 79); -insert into t1 values(1,78), (2,78), (3, 78); -insert into t1 values(1,77), (2,77), (3, 77); -insert into t1 values(1,76), (2,76), (3, 76); -insert into t1 values(1,75), (2,75), (3, 75); -insert into t1 values(1,74), (2,74), (3, 74); -insert into t1 values(1,73), (2,73), (3, 73); -insert into t1 values(1,72), (2,72), (3, 72); -insert into t1 values(1,71), (2,71), (3, 71); -insert into t1 values(1,70), (2,70), (3, 70); -insert into t1 values(1,69), (2,69), (3, 69); -insert into t1 values(1,68), (2,68), (3, 68); -insert into t1 values(1,67), (2,67), (3, 67); -insert into t1 values(1,66), (2,66), (3, 66); -insert into t1 values(1,65), (2,65), (3, 65); -insert into t1 values(1,64), (2,64), (3, 64); -insert into t1 values(1,63), (2,63), (3, 63); -insert into t1 values(1,62), (2,62), (3, 62); -insert into t1 values(1,61), (2,61), (3, 61); -insert into t1 values(1,60), (2,60), (3, 60); -insert into t1 values(1,59), (2,59), (3, 59); -insert into t1 values(1,58), (2,58), (3, 58); -insert into t1 values(1,57), (2,57), (3, 57); -insert into t1 values(1,56), (2,56), (3, 56); -insert into t1 values(1,55), (2,55), (3, 55); -insert into t1 values(1,54), (2,54), (3, 54); -insert into t1 values(1,53), (2,53), (3, 53); -insert into t1 values(1,52), (2,52), (3, 52); -insert into t1 values(1,51), (2,51), (3, 51); -insert into t1 values(1,50), (2,50), (3, 50); -insert into t1 values(1,49), (2,49), (3, 49); -insert into t1 values(1,48), (2,48), (3, 48); -insert into t1 values(1,47), (2,47), (3, 47); -insert into t1 values(1,46), (2,46), (3, 46); -insert into t1 values(1,45), (2,45), (3, 45); -insert into t1 values(1,44), (2,44), (3, 44); -insert into t1 values(1,43), (2,43), (3, 43); -insert into t1 values(1,42), (2,42), (3, 42); -insert into t1 values(1,41), (2,41), (3, 41); -insert into t1 values(1,40), (2,40), (3, 40); -insert into t1 values(1,39), (2,39), (3, 39); -insert into t1 values(1,38), (2,38), (3, 38); -insert into t1 values(1,37), (2,37), (3, 37); -insert into t1 values(1,36), (2,36), (3, 36); -insert into t1 values(1,35), (2,35), (3, 35); -insert into t1 values(1,34), (2,34), (3, 34); -insert into t1 values(1,33), (2,33), (3, 33); -insert into t1 values(1,32), (2,32), (3, 32); -insert into t1 values(1,31), (2,31), (3, 31); -insert into t1 values(1,30), (2,30), (3, 30); -insert into t1 values(1,29), (2,29), (3, 29); -insert into t1 values(1,28), (2,28), (3, 28); -insert into t1 values(1,27), (2,27), (3, 27); -insert into t1 values(1,26), (2,26), (3, 26); -insert into t1 values(1,25), (2,25), (3, 25); -insert into t1 values(1,24), (2,24), (3, 24); -insert into t1 values(1,23), (2,23), (3, 23); -insert into t1 values(1,22), (2,22), (3, 22); -insert into t1 values(1,21), (2,21), (3, 21); -insert into t1 values(1,20), (2,20), (3, 20); -insert into t1 values(1,19), (2,19), (3, 19); -insert into t1 values(1,18), (2,18), (3, 18); -insert into t1 values(1,17), (2,17), (3, 17); -insert into t1 values(1,16), (2,16), (3, 16); -insert into t1 values(1,15), (2,15), (3, 15); -insert into t1 values(1,14), (2,14), (3, 14); -insert into t1 values(1,13), (2,13), (3, 13); -insert into t1 values(1,12), (2,12), (3, 12); -insert into t1 values(1,11), (2,11), (3, 11); -insert into t1 values(1,10), (2,10), (3, 10); -insert into t1 values(1,9), (2,9), (3, 9); -insert into t1 values(1,8), (2,8), (3, 8); -insert into t1 values(1,7), (2,7), (3, 7); -insert into t1 values(1,6), (2,6), (3, 6); -insert into t1 values(1,5), (2,5), (3, 5); -insert into t1 values(1,4), (2,4), (3, 4); -insert into t1 values(1,3), (2,3), (3, 3); -insert into t1 values(1,2), (2,2), (3, 2); -insert into t1 values(1,1), (2,1), (3, 1); alter table t1 add unique (a,b), add key (b); show keys from t1; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment diff --git a/mysql-test/r/func_misc.result b/mysql-test/r/func_misc.result index 81dddd0f648..d939d72f7ef 100644 --- a/mysql-test/r/func_misc.result +++ b/mysql-test/r/func_misc.result @@ -116,10 +116,6 @@ CREATE TEMPORARY TABLE t_history (attempt SMALLINT, start_ts DATETIME, end_ts DATETIME, start_cached INTEGER, end_cached INTEGER); CREATE TABLE t1 (f1 BIGINT); -INSERT INTO t1 VALUES (1); -INSERT INTO t1 VALUES (1); -INSERT INTO t1 VALUES (1); -INSERT INTO t1 VALUES (1); INSERT INTO t_history SET attempt = 4 - 4 + 1, start_ts = NOW(), start_cached = 0; diff --git a/mysql-test/r/gis-rtree.result b/mysql-test/r/gis-rtree.result index b030139e40e..77c340bbdec 100644 --- a/mysql-test/r/gis-rtree.result +++ b/mysql-test/r/gis-rtree.result @@ -12,156 +12,6 @@ t1 CREATE TABLE `t1` ( PRIMARY KEY (`fid`), SPATIAL KEY `g` (`g`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(150 150, 150 150)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(149 149, 151 151)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(148 148, 152 152)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(147 147, 153 153)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(146 146, 154 154)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(145 145, 155 155)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(144 144, 156 156)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(143 143, 157 157)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(142 142, 158 158)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(141 141, 159 159)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(140 140, 160 160)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(139 139, 161 161)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(138 138, 162 162)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(137 137, 163 163)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(136 136, 164 164)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(135 135, 165 165)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(134 134, 166 166)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(133 133, 167 167)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(132 132, 168 168)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(131 131, 169 169)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(130 130, 170 170)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(129 129, 171 171)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(128 128, 172 172)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(127 127, 173 173)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(126 126, 174 174)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(125 125, 175 175)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(124 124, 176 176)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(123 123, 177 177)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(122 122, 178 178)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(121 121, 179 179)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(120 120, 180 180)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(119 119, 181 181)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(118 118, 182 182)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(117 117, 183 183)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(116 116, 184 184)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(115 115, 185 185)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(114 114, 186 186)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(113 113, 187 187)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(112 112, 188 188)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(111 111, 189 189)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(110 110, 190 190)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(109 109, 191 191)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(108 108, 192 192)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(107 107, 193 193)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(106 106, 194 194)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(105 105, 195 195)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(104 104, 196 196)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(103 103, 197 197)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(102 102, 198 198)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(101 101, 199 199)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(100 100, 200 200)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(99 99, 201 201)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(98 98, 202 202)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(97 97, 203 203)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(96 96, 204 204)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(95 95, 205 205)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(94 94, 206 206)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(93 93, 207 207)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(92 92, 208 208)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(91 91, 209 209)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(90 90, 210 210)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(89 89, 211 211)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(88 88, 212 212)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(87 87, 213 213)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(86 86, 214 214)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(85 85, 215 215)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(84 84, 216 216)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(83 83, 217 217)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(82 82, 218 218)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(81 81, 219 219)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(80 80, 220 220)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(79 79, 221 221)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(78 78, 222 222)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(77 77, 223 223)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(76 76, 224 224)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(75 75, 225 225)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(74 74, 226 226)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(73 73, 227 227)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(72 72, 228 228)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(71 71, 229 229)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(70 70, 230 230)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(69 69, 231 231)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(68 68, 232 232)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(67 67, 233 233)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(66 66, 234 234)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(65 65, 235 235)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(64 64, 236 236)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(63 63, 237 237)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(62 62, 238 238)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(61 61, 239 239)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(60 60, 240 240)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(59 59, 241 241)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(58 58, 242 242)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(57 57, 243 243)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(56 56, 244 244)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(55 55, 245 245)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(54 54, 246 246)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(53 53, 247 247)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(52 52, 248 248)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(51 51, 249 249)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(50 50, 250 250)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(49 49, 251 251)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(48 48, 252 252)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(47 47, 253 253)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(46 46, 254 254)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(45 45, 255 255)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(44 44, 256 256)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(43 43, 257 257)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(42 42, 258 258)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(41 41, 259 259)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(40 40, 260 260)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(39 39, 261 261)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(38 38, 262 262)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(37 37, 263 263)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(36 36, 264 264)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(35 35, 265 265)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(34 34, 266 266)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(33 33, 267 267)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(32 32, 268 268)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(31 31, 269 269)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(30 30, 270 270)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(29 29, 271 271)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(28 28, 272 272)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(27 27, 273 273)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(26 26, 274 274)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(25 25, 275 275)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(24 24, 276 276)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(23 23, 277 277)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(22 22, 278 278)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(21 21, 279 279)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(20 20, 280 280)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(19 19, 281 281)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(18 18, 282 282)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(17 17, 283 283)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(16 16, 284 284)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(15 15, 285 285)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(14 14, 286 286)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(13 13, 287 287)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(12 12, 288 288)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(11 11, 289 289)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(10 10, 290 290)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(9 9, 291 291)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(8 8, 292 292)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(7 7, 293 293)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(6 6, 294 294)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(5 5, 295 295)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(4 4, 296 296)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(3 3, 297 297)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(2 2, 298 298)')); -INSERT INTO t1 (g) VALUES (GeomFromText('LineString(1 1, 299 299)')); SELECT count(*) FROM t1; count(*) 150 @@ -186,106 +36,6 @@ CREATE TABLE t2 ( fid INT NOT NULL AUTO_INCREMENT PRIMARY KEY, g GEOMETRY NOT NULL ) ENGINE=MyISAM; -INSERT INTO t2 (g) VALUES (LineString(Point(10 * 10 - 9, 10 * 10 - 9), Point(10 * 10, 10 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(10 * 10 - 9, 9 * 10 - 9), Point(10 * 10, 9 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(10 * 10 - 9, 8 * 10 - 9), Point(10 * 10, 8 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(10 * 10 - 9, 7 * 10 - 9), Point(10 * 10, 7 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(10 * 10 - 9, 6 * 10 - 9), Point(10 * 10, 6 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(10 * 10 - 9, 5 * 10 - 9), Point(10 * 10, 5 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(10 * 10 - 9, 4 * 10 - 9), Point(10 * 10, 4 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(10 * 10 - 9, 3 * 10 - 9), Point(10 * 10, 3 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(10 * 10 - 9, 2 * 10 - 9), Point(10 * 10, 2 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(10 * 10 - 9, 1 * 10 - 9), Point(10 * 10, 1 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(9 * 10 - 9, 10 * 10 - 9), Point(9 * 10, 10 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(9 * 10 - 9, 9 * 10 - 9), Point(9 * 10, 9 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(9 * 10 - 9, 8 * 10 - 9), Point(9 * 10, 8 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(9 * 10 - 9, 7 * 10 - 9), Point(9 * 10, 7 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(9 * 10 - 9, 6 * 10 - 9), Point(9 * 10, 6 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(9 * 10 - 9, 5 * 10 - 9), Point(9 * 10, 5 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(9 * 10 - 9, 4 * 10 - 9), Point(9 * 10, 4 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(9 * 10 - 9, 3 * 10 - 9), Point(9 * 10, 3 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(9 * 10 - 9, 2 * 10 - 9), Point(9 * 10, 2 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(9 * 10 - 9, 1 * 10 - 9), Point(9 * 10, 1 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(8 * 10 - 9, 10 * 10 - 9), Point(8 * 10, 10 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(8 * 10 - 9, 9 * 10 - 9), Point(8 * 10, 9 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(8 * 10 - 9, 8 * 10 - 9), Point(8 * 10, 8 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(8 * 10 - 9, 7 * 10 - 9), Point(8 * 10, 7 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(8 * 10 - 9, 6 * 10 - 9), Point(8 * 10, 6 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(8 * 10 - 9, 5 * 10 - 9), Point(8 * 10, 5 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(8 * 10 - 9, 4 * 10 - 9), Point(8 * 10, 4 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(8 * 10 - 9, 3 * 10 - 9), Point(8 * 10, 3 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(8 * 10 - 9, 2 * 10 - 9), Point(8 * 10, 2 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(8 * 10 - 9, 1 * 10 - 9), Point(8 * 10, 1 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(7 * 10 - 9, 10 * 10 - 9), Point(7 * 10, 10 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(7 * 10 - 9, 9 * 10 - 9), Point(7 * 10, 9 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(7 * 10 - 9, 8 * 10 - 9), Point(7 * 10, 8 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(7 * 10 - 9, 7 * 10 - 9), Point(7 * 10, 7 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(7 * 10 - 9, 6 * 10 - 9), Point(7 * 10, 6 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(7 * 10 - 9, 5 * 10 - 9), Point(7 * 10, 5 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(7 * 10 - 9, 4 * 10 - 9), Point(7 * 10, 4 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(7 * 10 - 9, 3 * 10 - 9), Point(7 * 10, 3 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(7 * 10 - 9, 2 * 10 - 9), Point(7 * 10, 2 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(7 * 10 - 9, 1 * 10 - 9), Point(7 * 10, 1 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(6 * 10 - 9, 10 * 10 - 9), Point(6 * 10, 10 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(6 * 10 - 9, 9 * 10 - 9), Point(6 * 10, 9 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(6 * 10 - 9, 8 * 10 - 9), Point(6 * 10, 8 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(6 * 10 - 9, 7 * 10 - 9), Point(6 * 10, 7 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(6 * 10 - 9, 6 * 10 - 9), Point(6 * 10, 6 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(6 * 10 - 9, 5 * 10 - 9), Point(6 * 10, 5 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(6 * 10 - 9, 4 * 10 - 9), Point(6 * 10, 4 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(6 * 10 - 9, 3 * 10 - 9), Point(6 * 10, 3 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(6 * 10 - 9, 2 * 10 - 9), Point(6 * 10, 2 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(6 * 10 - 9, 1 * 10 - 9), Point(6 * 10, 1 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(5 * 10 - 9, 10 * 10 - 9), Point(5 * 10, 10 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(5 * 10 - 9, 9 * 10 - 9), Point(5 * 10, 9 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(5 * 10 - 9, 8 * 10 - 9), Point(5 * 10, 8 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(5 * 10 - 9, 7 * 10 - 9), Point(5 * 10, 7 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(5 * 10 - 9, 6 * 10 - 9), Point(5 * 10, 6 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(5 * 10 - 9, 5 * 10 - 9), Point(5 * 10, 5 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(5 * 10 - 9, 4 * 10 - 9), Point(5 * 10, 4 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(5 * 10 - 9, 3 * 10 - 9), Point(5 * 10, 3 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(5 * 10 - 9, 2 * 10 - 9), Point(5 * 10, 2 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(5 * 10 - 9, 1 * 10 - 9), Point(5 * 10, 1 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(4 * 10 - 9, 10 * 10 - 9), Point(4 * 10, 10 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(4 * 10 - 9, 9 * 10 - 9), Point(4 * 10, 9 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(4 * 10 - 9, 8 * 10 - 9), Point(4 * 10, 8 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(4 * 10 - 9, 7 * 10 - 9), Point(4 * 10, 7 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(4 * 10 - 9, 6 * 10 - 9), Point(4 * 10, 6 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(4 * 10 - 9, 5 * 10 - 9), Point(4 * 10, 5 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(4 * 10 - 9, 4 * 10 - 9), Point(4 * 10, 4 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(4 * 10 - 9, 3 * 10 - 9), Point(4 * 10, 3 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(4 * 10 - 9, 2 * 10 - 9), Point(4 * 10, 2 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(4 * 10 - 9, 1 * 10 - 9), Point(4 * 10, 1 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(3 * 10 - 9, 10 * 10 - 9), Point(3 * 10, 10 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(3 * 10 - 9, 9 * 10 - 9), Point(3 * 10, 9 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(3 * 10 - 9, 8 * 10 - 9), Point(3 * 10, 8 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(3 * 10 - 9, 7 * 10 - 9), Point(3 * 10, 7 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(3 * 10 - 9, 6 * 10 - 9), Point(3 * 10, 6 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(3 * 10 - 9, 5 * 10 - 9), Point(3 * 10, 5 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(3 * 10 - 9, 4 * 10 - 9), Point(3 * 10, 4 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(3 * 10 - 9, 3 * 10 - 9), Point(3 * 10, 3 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(3 * 10 - 9, 2 * 10 - 9), Point(3 * 10, 2 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(3 * 10 - 9, 1 * 10 - 9), Point(3 * 10, 1 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(2 * 10 - 9, 10 * 10 - 9), Point(2 * 10, 10 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(2 * 10 - 9, 9 * 10 - 9), Point(2 * 10, 9 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(2 * 10 - 9, 8 * 10 - 9), Point(2 * 10, 8 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(2 * 10 - 9, 7 * 10 - 9), Point(2 * 10, 7 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(2 * 10 - 9, 6 * 10 - 9), Point(2 * 10, 6 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(2 * 10 - 9, 5 * 10 - 9), Point(2 * 10, 5 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(2 * 10 - 9, 4 * 10 - 9), Point(2 * 10, 4 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(2 * 10 - 9, 3 * 10 - 9), Point(2 * 10, 3 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(2 * 10 - 9, 2 * 10 - 9), Point(2 * 10, 2 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(2 * 10 - 9, 1 * 10 - 9), Point(2 * 10, 1 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(1 * 10 - 9, 10 * 10 - 9), Point(1 * 10, 10 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(1 * 10 - 9, 9 * 10 - 9), Point(1 * 10, 9 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(1 * 10 - 9, 8 * 10 - 9), Point(1 * 10, 8 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(1 * 10 - 9, 7 * 10 - 9), Point(1 * 10, 7 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(1 * 10 - 9, 6 * 10 - 9), Point(1 * 10, 6 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(1 * 10 - 9, 5 * 10 - 9), Point(1 * 10, 5 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(1 * 10 - 9, 4 * 10 - 9), Point(1 * 10, 4 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(1 * 10 - 9, 3 * 10 - 9), Point(1 * 10, 3 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(1 * 10 - 9, 2 * 10 - 9), Point(1 * 10, 2 * 10))); -INSERT INTO t2 (g) VALUES (LineString(Point(1 * 10 - 9, 1 * 10 - 9), Point(1 * 10, 1 * 10))); ALTER TABLE t2 ADD SPATIAL KEY(g); SHOW CREATE TABLE t2; Table Create Table @@ -309,404 +59,204 @@ fid AsText(g) 56 LINESTRING(41 41,50 50) 45 LINESTRING(51 51,60 60) 55 LINESTRING(41 51,50 60) -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 10 * 10 - 9), Point(10 * 10, 10 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 9 * 10 - 9), Point(10 * 10, 9 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 8 * 10 - 9), Point(10 * 10, 8 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 7 * 10 - 9), Point(10 * 10, 7 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 6 * 10 - 9), Point(10 * 10, 6 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 5 * 10 - 9), Point(10 * 10, 5 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 4 * 10 - 9), Point(10 * 10, 4 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 3 * 10 - 9), Point(10 * 10, 3 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 2 * 10 - 9), Point(10 * 10, 2 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(10 * 10 - 9, 1 * 10 - 9), Point(10 * 10, 1 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 10 * 10 - 9), Point(9 * 10, 10 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 9 * 10 - 9), Point(9 * 10, 9 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 8 * 10 - 9), Point(9 * 10, 8 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 7 * 10 - 9), Point(9 * 10, 7 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 6 * 10 - 9), Point(9 * 10, 6 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 5 * 10 - 9), Point(9 * 10, 5 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 4 * 10 - 9), Point(9 * 10, 4 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 3 * 10 - 9), Point(9 * 10, 3 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 2 * 10 - 9), Point(9 * 10, 2 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(9 * 10 - 9, 1 * 10 - 9), Point(9 * 10, 1 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 10 * 10 - 9), Point(8 * 10, 10 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 9 * 10 - 9), Point(8 * 10, 9 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 8 * 10 - 9), Point(8 * 10, 8 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 7 * 10 - 9), Point(8 * 10, 7 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 6 * 10 - 9), Point(8 * 10, 6 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 5 * 10 - 9), Point(8 * 10, 5 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 4 * 10 - 9), Point(8 * 10, 4 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 3 * 10 - 9), Point(8 * 10, 3 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 2 * 10 - 9), Point(8 * 10, 2 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(8 * 10 - 9, 1 * 10 - 9), Point(8 * 10, 1 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 10 * 10 - 9), Point(7 * 10, 10 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 9 * 10 - 9), Point(7 * 10, 9 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 8 * 10 - 9), Point(7 * 10, 8 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 7 * 10 - 9), Point(7 * 10, 7 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 6 * 10 - 9), Point(7 * 10, 6 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 5 * 10 - 9), Point(7 * 10, 5 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 4 * 10 - 9), Point(7 * 10, 4 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 3 * 10 - 9), Point(7 * 10, 3 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 2 * 10 - 9), Point(7 * 10, 2 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(7 * 10 - 9, 1 * 10 - 9), Point(7 * 10, 1 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 10 * 10 - 9), Point(6 * 10, 10 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 9 * 10 - 9), Point(6 * 10, 9 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 8 * 10 - 9), Point(6 * 10, 8 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 7 * 10 - 9), Point(6 * 10, 7 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 6 * 10 - 9), Point(6 * 10, 6 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 5 * 10 - 9), Point(6 * 10, 5 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 4 * 10 - 9), Point(6 * 10, 4 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 3 * 10 - 9), Point(6 * 10, 3 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 2 * 10 - 9), Point(6 * 10, 2 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(6 * 10 - 9, 1 * 10 - 9), Point(6 * 10, 1 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 10 * 10 - 9), Point(5 * 10, 10 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 9 * 10 - 9), Point(5 * 10, 9 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 8 * 10 - 9), Point(5 * 10, 8 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 7 * 10 - 9), Point(5 * 10, 7 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 6 * 10 - 9), Point(5 * 10, 6 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 5 * 10 - 9), Point(5 * 10, 5 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 4 * 10 - 9), Point(5 * 10, 4 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 3 * 10 - 9), Point(5 * 10, 3 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 2 * 10 - 9), Point(5 * 10, 2 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(5 * 10 - 9, 1 * 10 - 9), Point(5 * 10, 1 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 10 * 10 - 9), Point(4 * 10, 10 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 9 * 10 - 9), Point(4 * 10, 9 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 8 * 10 - 9), Point(4 * 10, 8 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 7 * 10 - 9), Point(4 * 10, 7 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 6 * 10 - 9), Point(4 * 10, 6 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 5 * 10 - 9), Point(4 * 10, 5 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 4 * 10 - 9), Point(4 * 10, 4 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 3 * 10 - 9), Point(4 * 10, 3 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 2 * 10 - 9), Point(4 * 10, 2 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(4 * 10 - 9, 1 * 10 - 9), Point(4 * 10, 1 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 10 * 10 - 9), Point(3 * 10, 10 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 9 * 10 - 9), Point(3 * 10, 9 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 8 * 10 - 9), Point(3 * 10, 8 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 7 * 10 - 9), Point(3 * 10, 7 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 6 * 10 - 9), Point(3 * 10, 6 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 5 * 10 - 9), Point(3 * 10, 5 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 4 * 10 - 9), Point(3 * 10, 4 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 3 * 10 - 9), Point(3 * 10, 3 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 2 * 10 - 9), Point(3 * 10, 2 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(3 * 10 - 9, 1 * 10 - 9), Point(3 * 10, 1 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 10 * 10 - 9), Point(2 * 10, 10 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 9 * 10 - 9), Point(2 * 10, 9 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 8 * 10 - 9), Point(2 * 10, 8 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 7 * 10 - 9), Point(2 * 10, 7 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 6 * 10 - 9), Point(2 * 10, 6 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 5 * 10 - 9), Point(2 * 10, 5 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 4 * 10 - 9), Point(2 * 10, 4 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 3 * 10 - 9), Point(2 * 10, 3 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 2 * 10 - 9), Point(2 * 10, 2 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(2 * 10 - 9, 1 * 10 - 9), Point(2 * 10, 1 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 10 * 10 - 9), Point(1 * 10, 10 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 9 * 10 - 9), Point(1 * 10, 9 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 8 * 10 - 9), Point(1 * 10, 8 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 7 * 10 - 9), Point(1 * 10, 7 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 6 * 10 - 9), Point(1 * 10, 6 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 5 * 10 - 9), Point(1 * 10, 5 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 4 * 10 - 9), Point(1 * 10, 4 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 3 * 10 - 9), Point(1 * 10, 3 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 2 * 10 - 9), Point(1 * 10, 2 * 10)))); -SELECT count(*) FROM t2; count(*) 100 -DELETE FROM t2 WHERE Within(g, Envelope(GeometryFromWKB(Point(1 * 10 - 9, 1 * 10 - 9), Point(1 * 10, 1 * 10)))); -SELECT count(*) FROM t2; count(*) 100 DROP TABLE t2; diff --git a/mysql-test/r/innodb_xtradb_bug317074.result b/mysql-test/r/innodb_xtradb_bug317074.result index 52c758a5eed..5789c07282e 100644 --- a/mysql-test/r/innodb_xtradb_bug317074.result +++ b/mysql-test/r/innodb_xtradb_bug317074.result @@ -3,3 +3,30 @@ SET @old_innodb_file_per_table=@@innodb_file_per_table; SET @old_innodb_file_format_check=@@innodb_file_format_check; SET GLOBAL innodb_file_format='Barracuda'; SET GLOBAL innodb_file_per_table=ON; +DROP TABLE IF EXISTS `test1`; +CREATE TABLE IF NOT EXISTS `test1` ( +`a` int primary key auto_increment, +`b` int default 0, +`c` char(100) default 'testtest' +) ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8; +set autocommit=0; +CREATE PROCEDURE insert_many(p1 int) +BEGIN +SET @x = 0; +SET @y = 0; +REPEAT +insert into test1 set b=1; +SET @x = @x + 1; +SET @y = @y + 1; +IF @y >= 1000 THEN +commit; +SET @y = 0; +END IF; +UNTIL @x >= p1 END REPEAT; +END| +DROP PROCEDURE insert_many; +ALTER TABLE test1 ENGINE=MyISAM; +DROP TABLE test1; +SET GLOBAL innodb_file_format=@old_innodb_file_format; +SET GLOBAL innodb_file_per_table=@old_innodb_file_per_table; +SET GLOBAL innodb_file_format_check=@old_innodb_file_format_check; diff --git a/mysql-test/r/merge.result b/mysql-test/r/merge.result index 6820466eef1..f9f6e1edf6c 100644 --- a/mysql-test/r/merge.result +++ b/mysql-test/r/merge.result @@ -1846,56 +1846,6 @@ c1 DROP TABLE t1, t2, t3; CREATE TABLE t1 (id INTEGER, grp TINYINT, id_rev INTEGER); SET @rnd_max= 2147483647; -SET @rnd= RAND(); -SET @id = CAST(@rnd * @rnd_max AS UNSIGNED); -SET @id_rev= @rnd_max - @id; -SET @grp= CAST(127.0 * @rnd AS UNSIGNED); -INSERT INTO t1 (id, grp, id_rev) VALUES (@id, @grp, @id_rev); -SET @rnd= RAND(); -SET @id = CAST(@rnd * @rnd_max AS UNSIGNED); -SET @id_rev= @rnd_max - @id; -SET @grp= CAST(127.0 * @rnd AS UNSIGNED); -INSERT INTO t1 (id, grp, id_rev) VALUES (@id, @grp, @id_rev); -SET @rnd= RAND(); -SET @id = CAST(@rnd * @rnd_max AS UNSIGNED); -SET @id_rev= @rnd_max - @id; -SET @grp= CAST(127.0 * @rnd AS UNSIGNED); -INSERT INTO t1 (id, grp, id_rev) VALUES (@id, @grp, @id_rev); -SET @rnd= RAND(); -SET @id = CAST(@rnd * @rnd_max AS UNSIGNED); -SET @id_rev= @rnd_max - @id; -SET @grp= CAST(127.0 * @rnd AS UNSIGNED); -INSERT INTO t1 (id, grp, id_rev) VALUES (@id, @grp, @id_rev); -SET @rnd= RAND(); -SET @id = CAST(@rnd * @rnd_max AS UNSIGNED); -SET @id_rev= @rnd_max - @id; -SET @grp= CAST(127.0 * @rnd AS UNSIGNED); -INSERT INTO t1 (id, grp, id_rev) VALUES (@id, @grp, @id_rev); -SET @rnd= RAND(); -SET @id = CAST(@rnd * @rnd_max AS UNSIGNED); -SET @id_rev= @rnd_max - @id; -SET @grp= CAST(127.0 * @rnd AS UNSIGNED); -INSERT INTO t1 (id, grp, id_rev) VALUES (@id, @grp, @id_rev); -SET @rnd= RAND(); -SET @id = CAST(@rnd * @rnd_max AS UNSIGNED); -SET @id_rev= @rnd_max - @id; -SET @grp= CAST(127.0 * @rnd AS UNSIGNED); -INSERT INTO t1 (id, grp, id_rev) VALUES (@id, @grp, @id_rev); -SET @rnd= RAND(); -SET @id = CAST(@rnd * @rnd_max AS UNSIGNED); -SET @id_rev= @rnd_max - @id; -SET @grp= CAST(127.0 * @rnd AS UNSIGNED); -INSERT INTO t1 (id, grp, id_rev) VALUES (@id, @grp, @id_rev); -SET @rnd= RAND(); -SET @id = CAST(@rnd * @rnd_max AS UNSIGNED); -SET @id_rev= @rnd_max - @id; -SET @grp= CAST(127.0 * @rnd AS UNSIGNED); -INSERT INTO t1 (id, grp, id_rev) VALUES (@id, @grp, @id_rev); -SET @rnd= RAND(); -SET @id = CAST(@rnd * @rnd_max AS UNSIGNED); -SET @id_rev= @rnd_max - @id; -SET @grp= CAST(127.0 * @rnd AS UNSIGNED); -INSERT INTO t1 (id, grp, id_rev) VALUES (@id, @grp, @id_rev); set @@read_buffer_size=2*1024*1024; CREATE TABLE t2 SELECT * FROM t1; INSERT INTO t1 (id, grp, id_rev) SELECT id, grp, id_rev FROM t2; diff --git a/mysql-test/r/myisam_debug.result b/mysql-test/r/myisam_debug.result index c128bfffce9..7268113552f 100644 --- a/mysql-test/r/myisam_debug.result +++ b/mysql-test/r/myisam_debug.result @@ -12,16 +12,6 @@ CREATE TABLE `t2` ( KEY (id1), KEY(id) ) ENGINE=MyISAM; INSERT INTO t2 (id) VALUES (123); -INSERT INTO t2 (id) SELECT id FROM t2; -INSERT INTO t2 (id) SELECT id FROM t2; -INSERT INTO t2 (id) SELECT id FROM t2; -INSERT INTO t2 (id) SELECT id FROM t2; -INSERT INTO t2 (id) SELECT id FROM t2; -INSERT INTO t2 (id) SELECT id FROM t2; -INSERT INTO t2 (id) SELECT id FROM t2; -INSERT INTO t2 (id) SELECT id FROM t2; -INSERT INTO t2 (id) SELECT id FROM t2; -INSERT INTO t2 (id) SELECT id FROM t2; # Switch to insert Connection SET SESSION debug='+d,wait_in_enable_indexes'; # Send insert data diff --git a/mysql-test/suite/parts/inc/partition.pre b/mysql-test/suite/parts/inc/partition.pre index 7c3b0d9d1ef..f9b361c787c 100644 --- a/mysql-test/suite/parts/inc/partition.pre +++ b/mysql-test/suite/parts/inc/partition.pre @@ -152,6 +152,7 @@ ENGINE = MEMORY; --echo # Logging of INSERTs into t0_template suppressed --disable_query_log let $num= `SELECT @max_row`; +begin; while ($num) { eval INSERT INTO t0_template @@ -160,6 +161,7 @@ f_charbig = '===$num==='; dec $num; } +commit; --enable_query_log # Auxiliary table used for comparisons of table definitions and file lists diff --git a/mysql-test/suite/parts/inc/partition_bigint.inc b/mysql-test/suite/parts/inc/partition_bigint.inc index 307387ccce1..dfab6dc6c09 100644 --- a/mysql-test/suite/parts/inc/partition_bigint.inc +++ b/mysql-test/suite/parts/inc/partition_bigint.inc @@ -32,11 +32,13 @@ delete from t2; let $count=$maxrows; --echo $maxrows inserts; --disable_query_log +begin; while ($count) { eval insert into t2 values ($count); dec $count; } +commit; --enable_query_log select count(*) from t2; drop table t2; diff --git a/mysql-test/suite/parts/inc/partition_binary.inc b/mysql-test/suite/parts/inc/partition_binary.inc index 68e9e56e29e..08db71b6483 100644 --- a/mysql-test/suite/parts/inc/partition_binary.inc +++ b/mysql-test/suite/parts/inc/partition_binary.inc @@ -22,13 +22,16 @@ show create table t2; let $count=26; let $letter=0; --echo $count inserts; -#--disable_query_log +--disable_query_log +begin; while ($count) { eval insert into t2 values (repeat(char(ascii('a')+$letter),$count+54)); dec $count; inc $letter; } +commit; +--enable_query_log select count(*) from t2; select hex(a) from t2; drop table t2; @@ -48,13 +51,16 @@ show create table t3; let $count=26; let $letter=0; --echo $count inserts; -#--disable_query_log +--disable_query_log +begin; while ($count) { eval insert into t3 values (repeat(char(ascii('a')+$letter),$count+54)); dec $count; inc $letter; } +commit; +--enable_query_log select count(*) from t3; select hex(a) from t3; drop table t3; @@ -73,14 +79,16 @@ show create table t4; let $count=26; let $letter=0; --echo $count inserts; -#--disable_query_log +--disable_query_log +begin; while ($count) { eval insert into t4 values (repeat(char(ascii('a')+$letter),$count+54)); dec $count; inc $letter; } - +commit; +--enable_query_log select count(*) from t4; select hex(a) from t4; drop table t4; diff --git a/mysql-test/suite/parts/inc/partition_bit.inc b/mysql-test/suite/parts/inc/partition_bit.inc index 5bbf0058028..4badbe59a79 100644 --- a/mysql-test/suite/parts/inc/partition_bit.inc +++ b/mysql-test/suite/parts/inc/partition_bit.inc @@ -74,11 +74,13 @@ show create table t3; let $count=255; --echo $count inserts; --disable_query_log +begin; while ($count) { eval insert into t3 values ($count); dec $count; } +commit; --enable_query_log select hex(a) from t3 where a=b'01010101'; delete from t3 where a=b'01010101'; @@ -96,11 +98,13 @@ show create table t4; let $count=32; --echo $count inserts; --disable_query_log +begin; while ($count) { eval insert into t4 values ($count); dec $count; } +commit; --enable_query_log select hex(a) from t4 where a=b'00000001'; delete from t4 where a=b'00000001'; diff --git a/mysql-test/suite/parts/inc/partition_char.inc b/mysql-test/suite/parts/inc/partition_char.inc index 1db9642c002..0fa28370c83 100644 --- a/mysql-test/suite/parts/inc/partition_char.inc +++ b/mysql-test/suite/parts/inc/partition_char.inc @@ -21,13 +21,16 @@ show create table t2; let $count=26; let $letter=0; --echo $count inserts; -#--disable_query_log +--disable_query_log +begin; while ($count) { eval insert into t2 values (repeat(char(ascii('a')+$letter),$count+54)); dec $count; inc $letter; } +commit; +--enable_query_log select count(*) from t2; select * from t2; drop table t2; @@ -47,13 +50,16 @@ show create table t3; let $count=26; let $letter=0; --echo $count inserts; -#--disable_query_log +--disable_query_log +begin; while ($count) { eval insert into t3 values (repeat(char(ascii('a')+$letter),$count+54)); dec $count; inc $letter; } +commit; +--enable_query_log select count(*) from t3; select a from t3; drop table t3; @@ -71,13 +77,16 @@ show create table t4; let $count=26; let $letter=0; --echo $count inserts; -#--disable_query_log +--disable_query_log +begin; while ($count) { eval insert into t4 values (repeat(char(ascii('a')+$letter),$count+54)); dec $count; inc $letter; } +commit; +--enable_query_log select count(*) from t4; select a from t4; drop table t4; diff --git a/mysql-test/suite/parts/inc/partition_date.inc b/mysql-test/suite/parts/inc/partition_date.inc index b538a5a9d8b..11e683881e5 100644 --- a/mysql-test/suite/parts/inc/partition_date.inc +++ b/mysql-test/suite/parts/inc/partition_date.inc @@ -23,7 +23,8 @@ select * from t2; delete from t2; let $count=28; --echo $count inserts; -#--disable_query_log +--disable_query_log +begin; while ($count) { eval insert into t2 values (19700101+$count-1); @@ -31,7 +32,8 @@ eval insert into t2 values (19700201+$count-1); eval insert into t2 values (19700301+$count-1); dec $count; } -#--enable_query_log +commit; +--enable_query_log select count(*) from t2; select * from t2; drop table t2; @@ -47,11 +49,15 @@ partition quarter4 values less than (13) show create table t3; let $count=12; --echo $count inserts; +--disable_query_log +begin; while ($count) { eval insert into t3 values (adddate(19700101,interval $count-1 month)); dec $count; } +commit; +--enable_query_log select count(*) from t3; select * from t3; drop table t3; @@ -67,11 +73,15 @@ partition quarter4 values in (10,11,12) show create table t4; let $count=12; --echo $count inserts; +--disable_query_log +begin; while ($count) { eval insert into t4 values (adddate(19700101,interval $count-1 month)); dec $count; } +commit; +--enable_query_log select count(*) from t4; select * from t4; drop table t4; diff --git a/mysql-test/suite/parts/inc/partition_datetime.inc b/mysql-test/suite/parts/inc/partition_datetime.inc index b9b277a0fcc..e2135d90667 100644 --- a/mysql-test/suite/parts/inc/partition_datetime.inc +++ b/mysql-test/suite/parts/inc/partition_datetime.inc @@ -23,12 +23,15 @@ select * from t2; delete from t2; let $count=59; --echo $count inserts; -#--disable_query_log +--disable_query_log +begin; while ($count) { eval insert into t2 values (19700101000000+$count); dec $count; } +commit; +--enable_query_log select count(*) from t2; select * from t2; drop table t2; @@ -44,11 +47,15 @@ partition quarter4 values less than (13) show create table t3; let $count=12; --echo $count inserts; +--disable_query_log +begin; while ($count) { eval insert into t3 values (adddate(19700101000000,interval $count-1 month)); dec $count; } +commit; +--enable_query_log select count(*) from t3; select * from t3; drop table t3; @@ -64,11 +71,15 @@ partition quarter4 values in (10,11,12) show create table t4; let $count=12; --echo $count inserts; +--disable_query_log +begin; while ($count) { eval insert into t4 values (adddate(19700101000000,interval $count-1 month)); dec $count; } +commit; +--enable_query_log select count(*) from t4; select * from t4; drop table t4; diff --git a/mysql-test/suite/parts/inc/partition_decimal.inc b/mysql-test/suite/parts/inc/partition_decimal.inc index 17cef08e275..95ef878b957 100644 --- a/mysql-test/suite/parts/inc/partition_decimal.inc +++ b/mysql-test/suite/parts/inc/partition_decimal.inc @@ -24,6 +24,7 @@ delete from t2; let $count=$maxrows; --echo $count*3 inserts; --disable_query_log +begin; while ($count) { eval insert into t2 values ($count); @@ -31,6 +32,7 @@ eval insert into t2 values ($count+0.333333333); eval insert into t2 values ($count+0.755555555); dec $count; } +commit; --enable_query_log select count(*) from t2; drop table t2; @@ -53,6 +55,8 @@ partition pa10 values less than (10) show create table t3; let $count=9; --echo $count*3 inserts; +--disable_query_log +begin; while ($count) { eval insert into t3 values ($count); @@ -60,6 +64,7 @@ eval insert into t3 values ($count+0.333333333); eval insert into t3 values ($count+0.755555555); dec $count; } +commit; --enable_query_log select count(*) from t3; drop table t3; @@ -75,6 +80,8 @@ partition pa10 values in (9,10) show create table t4; let $count=9; --echo $count*3 inserts; +--disable_query_log +begin; while ($count) { eval insert into t4 values ($count); @@ -82,6 +89,7 @@ eval insert into t4 values ($count+0.333333333); eval insert into t4 values ($count+0.755555555); dec $count; } +commit; --enable_query_log select count(*) from t4; drop table t4; diff --git a/mysql-test/suite/parts/inc/partition_double.inc b/mysql-test/suite/parts/inc/partition_double.inc index befbe860b86..aef5aa4f675 100644 --- a/mysql-test/suite/parts/inc/partition_double.inc +++ b/mysql-test/suite/parts/inc/partition_double.inc @@ -24,6 +24,7 @@ delete from t2; let $count=$maxrows; --echo $maxrows*3 inserts; --disable_query_log +begin; while ($count) { eval insert into t2 values ($count); @@ -31,6 +32,7 @@ eval insert into t2 values ($count+0.33); eval insert into t2 values ($count+0.75); dec $count; } +commit; --enable_query_log select count(*) from t2; drop table t2; @@ -52,6 +54,8 @@ partition pa10 values less than (10) show create table t3; let $count=9; --echo $count*3 inserts; +--disable_query_log +begin; while ($count) { eval insert into t3 values ($count); @@ -59,6 +63,8 @@ eval insert into t3 values ($count+0.33); eval insert into t3 values ($count+0.75); dec $count; } +commit; +--enable_query_log select count(*) from t3; select * from t3; drop table t3; @@ -72,6 +78,8 @@ partition pa10 values in (7,8,9,10) show create table t4; let $count=9; --echo $count*3 inserts; +--disable_query_log +begin; while ($count) { eval insert into t4 values ($count); @@ -79,6 +87,8 @@ eval insert into t4 values ($count+0.33); eval insert into t4 values ($count+0.75); dec $count; } +commit; +--enable_query_log select count(*) from t4; select * from t4; drop table t4; diff --git a/mysql-test/suite/parts/inc/partition_enum.inc b/mysql-test/suite/parts/inc/partition_enum.inc index 9f2c5976097..a545d7fd8c7 100644 --- a/mysql-test/suite/parts/inc/partition_enum.inc +++ b/mysql-test/suite/parts/inc/partition_enum.inc @@ -26,12 +26,15 @@ partition by key (a) partitions 27; show create table t2; let $letter=26; --echo $count inserts; -#--disable_query_log +--disable_query_log +begin; while ($letter) { eval insert into t2 values (char(ascii('A')+$letter)); dec $letter; } +commit; +--enable_query_log insert into t2 values ('1'),('2'),('3'),('4'),('5'),('6'),('7'),('8'),('9'),('0'); select count(*) from t2; select * from t2; @@ -55,12 +58,15 @@ partition pa36 values less than (37) show create table t3; let $letter=36; --echo $count inserts; -#--disable_query_log +--disable_query_log + begin; while ($letter) { #eval insert into t3 values ($letter); dec $letter; } +commit; +--enable_query_log select count(*) from t3; select * from t3; drop table t3; diff --git a/mysql-test/suite/parts/inc/partition_float.inc b/mysql-test/suite/parts/inc/partition_float.inc index 34f14137d4d..8da12a3e5bd 100644 --- a/mysql-test/suite/parts/inc/partition_float.inc +++ b/mysql-test/suite/parts/inc/partition_float.inc @@ -28,6 +28,7 @@ delete from t2; let $count=$maxrows; --echo $maxrows*3 inserts; --disable_query_log +begin; while ($count) { eval insert into t2 values ($count); @@ -35,6 +36,7 @@ eval insert into t2 values ($count+0.33); eval insert into t2 values ($count+0.75); dec $count; } +commit; --enable_query_log select count(*) from t2; drop table t2; @@ -55,6 +57,8 @@ partition pa10 values less than (10) show create table t3; let $count=9; --echo $count*3 inserts; +--disable_query_log +begin; while ($count) { eval insert into t3 values ($count); @@ -62,6 +66,8 @@ eval insert into t3 values ($count+0.33); eval insert into t3 values ($count+0.75); dec $count; } +commit; +--enable_query_log select count(*) from t3; select * from t3; drop table t3; @@ -75,6 +81,8 @@ partition pa10 values in (7,8,9,10) show create table t4; let $count=9; --echo $count*3 inserts; +--disable_query_log +begin; while ($count) { eval insert into t4 values ($count); @@ -82,6 +90,8 @@ eval insert into t4 values ($count+0.33); eval insert into t4 values ($count+0.75); dec $count; } +commit; +--enable_query_log select count(*) from t4; select * from t4; drop table t4; diff --git a/mysql-test/suite/parts/inc/partition_int.inc b/mysql-test/suite/parts/inc/partition_int.inc index 02de94e5172..f457bb53479 100644 --- a/mysql-test/suite/parts/inc/partition_int.inc +++ b/mysql-test/suite/parts/inc/partition_int.inc @@ -28,11 +28,13 @@ delete from t2; let $count=$maxrows; --echo $count inserts; --disable_query_log +begin; while ($count) { eval insert into t2 values ($count); dec $count; } +commit; --enable_query_log select count(*) from t2; drop table t2; diff --git a/mysql-test/suite/parts/inc/partition_mediumint.inc b/mysql-test/suite/parts/inc/partition_mediumint.inc index 5d141bf05a4..564abe33a3c 100644 --- a/mysql-test/suite/parts/inc/partition_mediumint.inc +++ b/mysql-test/suite/parts/inc/partition_mediumint.inc @@ -28,11 +28,13 @@ delete from t2; let $count=$maxrows; --echo $maxrows inserts; --disable_query_log +begin; while ($count) { eval insert into t2 values ($count); dec $count; } +commit; --enable_query_log select count(*) from t2; drop table t2; diff --git a/mysql-test/suite/parts/inc/partition_smallint.inc b/mysql-test/suite/parts/inc/partition_smallint.inc index f1a70c337c2..0908e7e69a4 100644 --- a/mysql-test/suite/parts/inc/partition_smallint.inc +++ b/mysql-test/suite/parts/inc/partition_smallint.inc @@ -28,11 +28,13 @@ delete from t2; let $count=$maxrows; --echo $count inserts; --disable_query_log +begin; while ($count) { eval insert into t2 values ($count); dec $count; } +commit; --enable_query_log select count(*) from t2; drop table t2; diff --git a/mysql-test/suite/parts/inc/partition_time.inc b/mysql-test/suite/parts/inc/partition_time.inc index 008963ed934..674fe546a1f 100644 --- a/mysql-test/suite/parts/inc/partition_time.inc +++ b/mysql-test/suite/parts/inc/partition_time.inc @@ -23,12 +23,15 @@ select * from t2; delete from t2; let $count=59; --echo $count inserts; -#--disable_query_log +--disable_query_log +begin; while ($count) { eval insert into t2 values (000100+$count); dec $count; } +commit; +--enable_query_log select count(*) from t2; select * from t2; drop table t2; @@ -44,11 +47,15 @@ partition quarter4 values less than (61) show create table t3; let $count=59; --echo $count inserts; +--disable_query_log +begin; while ($count) { eval insert into t3 values (100000+$count); dec $count; } +commit; +--enable_query_log select count(*) from t3; select * from t3; drop table t3; @@ -64,11 +71,15 @@ partition quarter4 values in (46,47,48,49,50,51,52,53,54,55,56,57,58,59,60) show create table t4; let $count=59; --echo $count inserts; +--disable_query_log +begin; while ($count) { eval insert into t4 values (100000+$count); dec $count; } +commit; +--enable_query_log select count(*) from t4; select * from t4; drop table t4; diff --git a/mysql-test/suite/parts/inc/partition_timestamp.inc b/mysql-test/suite/parts/inc/partition_timestamp.inc index d152c82a76f..4ec42471de9 100644 --- a/mysql-test/suite/parts/inc/partition_timestamp.inc +++ b/mysql-test/suite/parts/inc/partition_timestamp.inc @@ -23,12 +23,15 @@ select * from t2; delete from t2; let $count=59; --echo $count inserts; -#--disable_query_log +--disable_query_log +begin; while ($count) { eval insert into t2 values (19710101000000+$count); dec $count; } +commit; +--enable_query_log select count(*) from t2; select * from t2; drop table t2; @@ -44,11 +47,15 @@ partition quarter4 values less than (13) show create table t3; let $count=12; --echo $count inserts; +--disable_query_log +begin; while ($count) { eval insert into t3 values (date_add('1970-01-01 00:00:00',interval $count-1 month)); dec $count; } +commit; +--enable_query_log select count(*) from t3; select * from t3; drop table t3; @@ -64,11 +71,15 @@ partition quarter4 values in (10,11,12) show create table t4; let $count=12; --echo $count inserts; +--disable_query_log +begin; while ($count) { eval insert into t4 values (date_add('1970-01-01 00:00:00',interval $count-1 month)); dec $count; } +commit; +--enable_query_log select count(*) from t4; select * from t4; drop table t4; diff --git a/mysql-test/suite/parts/inc/partition_tinyint.inc b/mysql-test/suite/parts/inc/partition_tinyint.inc index 9954a00e819..9b77c7b3f67 100644 --- a/mysql-test/suite/parts/inc/partition_tinyint.inc +++ b/mysql-test/suite/parts/inc/partition_tinyint.inc @@ -28,11 +28,13 @@ delete from t2; let $count=255; --echo 255 inserts; --disable_query_log +begin; while ($count) { eval insert into t2 values ($count); dec $count; } +commit; --enable_query_log select count(*) from t2; drop table t2; diff --git a/mysql-test/suite/parts/inc/partition_varbinary.inc b/mysql-test/suite/parts/inc/partition_varbinary.inc index 02d9f68f1a2..04ba66d87ea 100644 --- a/mysql-test/suite/parts/inc/partition_varbinary.inc +++ b/mysql-test/suite/parts/inc/partition_varbinary.inc @@ -21,13 +21,16 @@ show create table t2; let $count=26; let $letter=0; --echo $count inserts; -#--disable_query_log +--disable_query_log +begin; while ($count) { eval insert into t2 values (repeat(char(ascii('a')+$letter),$count*$count)); dec $count; inc $letter; } +commit; +--enable_query_log select count(*) from t2; select * from t2; drop table t2; @@ -47,13 +50,16 @@ show create table t3; let $count=26; let $letter=0; --echo $count inserts; -#--disable_query_log +--disable_query_log +begin; while ($count) { eval insert into t3 values (repeat(char(ascii('a')+$letter),$count+54)); dec $count; inc $letter; } +commit; +--enable_query_log select count(*) from t3; select hex(a) from t3; drop table t3; @@ -71,13 +77,16 @@ show create table t4; let $count=26; let $letter=0; --echo $count inserts; -#--disable_query_log +--disable_query_log +begin; while ($count) { eval insert into t4 values (repeat(char(ascii('a')+$letter),$count+54)); dec $count; inc $letter; } +commit; +--enable_query_log select count(*) from t4; select hex(a) from t4; drop table t4; diff --git a/mysql-test/suite/parts/inc/partition_varchar.inc b/mysql-test/suite/parts/inc/partition_varchar.inc index f1412d3aae5..33c61034a52 100644 --- a/mysql-test/suite/parts/inc/partition_varchar.inc +++ b/mysql-test/suite/parts/inc/partition_varchar.inc @@ -21,13 +21,16 @@ show create table t2; let $count=26; let $letter=0; --echo $count inserts; -#--disable_query_log +--disable_query_log +begin; while ($count) { eval insert into t2 values (repeat(char(ascii('a')+$letter),$count*$count)); dec $count; inc $letter; } +commit; +--enable_query_log select count(*) from t2; select * from t2; drop table t2; @@ -46,13 +49,16 @@ show create table t3; let $count=26; let $letter=0; --echo $count inserts; -#--disable_query_log +--disable_query_log +begin; while ($count) { eval insert into t3 values (repeat(char(ascii('a')+$letter),$count+54)); dec $count; inc $letter; } +commit; +--enable_query_log select count(*) from t3; select * from t3; drop table t3; @@ -70,13 +76,16 @@ show create table t4; let $count=26; let $letter=0; --echo $count inserts; -#--disable_query_log +--disable_query_log +begin; while ($count) { eval insert into t4 values (repeat(char(ascii('a')+$letter),$count+54)); dec $count; inc $letter; } +commit; +--enable_query_log select count(*) from t4; select * from t4; drop table t4; diff --git a/mysql-test/suite/parts/inc/partition_year.inc b/mysql-test/suite/parts/inc/partition_year.inc index 5fb46c1756b..2be9d158090 100644 --- a/mysql-test/suite/parts/inc/partition_year.inc +++ b/mysql-test/suite/parts/inc/partition_year.inc @@ -24,11 +24,13 @@ delete from t2; let $count=255; --echo $count inserts; --disable_query_log +begin; while ($count) { eval insert into t2 values (1901+$count); dec $count; } +commit; --enable_query_log select count(*) from t2; select * from t2; diff --git a/mysql-test/suite/parts/r/partition_char_innodb.result b/mysql-test/suite/parts/r/partition_char_innodb.result index dc7d259c2af66d732b0c449debfe02886127d4a8..6f4a107f8404ddb32ac9af6b432dd5c45c0a4e92 100644 GIT binary patch delta 83 zcmeA?$o#B>c|#t@L4Nz2RbIBP|5deH+Cn*2` literal 57481 zcmeHQTX)*H7Cx`tze48;@TjZUfJr7R4cGy}c!E$s2vIU%!6MF07&3b9)1)=X_(9bHlpdts%RyT#LC6cQ$p0 zw&mK)wK{!-IxAW-M$xF%O3WF!%(?IPIlCM7Zmr=1`^$bPTBQ=Roo_wI-YpzE&fs9L z!02vV4(rHR$f(4MfuHXzo!weL{~Qi}jCPGOyX`stHJ^%QJjSX7VpXPNRTjspPRFV~ z#;OMLGDjyrUJhfYs+aUqzOlm?*5AaV%`L>FzC=$=I{ zJ=&S>u8rC5T4)_bYt-%aM9*FNtz6=U`CCo)$x|Ku%9J`%)?%eJkg^&pWd$iKu~Jr% z(ukF^hLn1&lqOP^W2LN@xV{}LL%*w zCP_zjf{wl>=jdBvj=m@5sF#qV|0d(;uS6X6lW=sKfFoyfM}v(W-EHdVe;Ya)ZsusT zkt25#NB0{z`a8a(AF&<%jO*wjrlWu2ISS4(F$!W)cEPG_r{{>})zEcWFOFK7wb>dg zvq5I5wb|JP)|nOIOs&m+w||On2a^R_@19IO-$yyuF88lL-@;F(k!$hKIq`V?=^i=f zf6C;K*OIKUQs94^8{KzCE5>HAOF`_}ibT)X)%o!##EOXoDln9nkQJuig4 zI@sHl%h}g%5Af!+pvp;S6$gE`dNSiq?zkD*QSv_7p z^V6r0%vv^&^jVXK8jzVumj~8ofkrax**mhpn0(ZM%&n{)`CxoDs3dbcTSqq7l9yVL z*~rq77q(}GPBQnhb7X}n`Kbq)`&l{i!}RP>O6EZ}j_j}`Pcf29yWRneftrgW9 zPkH2(%~_>;>MyoSH{JW&8m>k|@go(XOe#PWpreEXqD*n?3H}(YFi~bOQG}Q-#zd)= z%g+ZBWdYiQ`so*QAn!OdznHx$`;2n{AVD+x!AHIw?^HIymkOW=d3%%1@6OeE_Bcct zf3GjHdaAR2k*`$|wI&BP@2Z3QvM=6+X=*Z)$!(aXYWM`xt)%y1(hO6eGDh3kNFsn~ z0HleWQX+t9*oq`_N{Ilb0eB~JO1Te{2C$#VDJ24!27sZ+DJ24!22i8ODJ24!1|X%# zDJ24!2JoiHDdj#)8UUjrr}PlOG{96vPbv|>G=O78Pbv|>G(d7iPbv|>Gys7`Pb&9e z(f~geJ*h+h)ASgUtBcLyjc;mli{cB>I;YLxv>y zmli{UB=(mULw@82Oj-=-k;q?~l%31~f32w`sA!4@jWY6Tfl82X4kQdWm?(Ck z%Iq0%AX$LPB*7|GUg>ZkQIOCC@kUiv334Dw@YdvDU{y}5IglV!Zep0bxy~p#z~Q8T zi(hI!i2*VvgzNk)vq=h!IvGgoEas9B%yuGJ-Kk`f3_y4iAmhI(k3_)B6Tm;;D2pV( z(>I4-UnhqIAlf&^c%RB(bHMkwfbkmx#jk@izbTmfJQV$g@baTkbb$G_K;@T%$In5- zKLWl>0C)OlZ3}M?sVE#-9iP#CKqF=4y$-ng48NYh@IcvlD?9JCzvQThp&U@AgQ4tE z4_`P3l%4krf59(_Jk?phq_?SPiOPYEt#YO&ic9Uhlbrqq0Cy{80KtDB{9rQ}zdO{n z@L$?j`$OAu?eUb$c(vbZHrh?rZtR^j*|lq2vm!BeZCwM)bZUzF1XHent#_r&v^Qj! z%rn#;MYY&2m$+dnTkpUWZWbO>*?O-+>s7Yi?pkoY%GTTJ--om`W$PWr93ef*);p?_ zqT)X@4s5Jd=G$;tQ6HHD%GUcC*i&b@ipthI9gFJhma1&M6SS$$YF5hDd$m<{He)DT z?~GZND_ifUvMpD(-U(QjD_ieX_T|df`&XG*XC_}|>%ESNc4Bdqt@p$Tz{5$xQg4*+Y<(}X1*!lz(49aL+ zeCmV1mv|APEH-khwG-Fc3iWZYyK#>YMnyvv~fv>{X z;7#~C{1*H+e7V3WVqbs+r$~7Qe-3{E{~o>te+l1){{a6H{uBIXQNk52z7%NlZX{q; zWYm+gD)O4{n(T_ot*FfMc~xRh&@}{%n~b_JZYr;|Z3>#~ph^AaZC&}v8ah4a+vs=l zuU_efS$lP0xfXMW_f8k~T{rCOV92_I{{5}P3RZzxE*ruqOkcL~h2jz}Ff7LKSm%;Kx&oNGF3TRHYi3RHrT4 zrZVl(KGcmS9YP~GqGS4l-a+*^r87FG3wlp2x}-LJppW#4KGPL_nbH83qWX+%H+&j^ z2x=DK{D~20v}*`OaNa-}>eV6xWqsB_S${N8j>Xj{80pm{z?%f{J=u=;xi=ALa(^no zkNCSl+n!7Z*kE{L4_W7dS#oB;(OfxZ2O>Tp^=vy2sPPSyHBNJXcOxv^q2-HqY3&y9 zknacP3Zf$OvxNnv%Y=bCESp4lrO!@3<}>8`!OT|9EkyOz)MEWVEXe*q%`Dz5)A9Xj zx!)>f+w@zeygrm6Ch8cgk7Rf(L$uY&H2zdxpULoCh8Hq?FT+b2wq^K1h9714S%z0K z{32TZlHK=3OO=sCdliL_yN(0il=n^URq~K~)kN1Ie?Q`0Rgd`}^8TIQ)tqpz!l&G; z@)`Fkea^jVUvRJD?|Dn6yX0Qw+uW=E2ksH@k$;lUKXZ?WD-JSHzb_oqvQTn-LO_t; z3*zh(gR@T#&OSjn`y`28&m#(FpDdh3&xwLTpidgkK5;nv3&OVVibMH-o zT%S;!eNu7uiN%?FZw_Sp1mi47_DB~mYdP^7D1FPsL+73jX>d=AtZ+|{ta4A2tZ`45 zG`Xiu*14xoZgEee+~&|JQTH-OnIQs?R>=%WzUl`7QaX54x3_19J7Z=*5ehCi0wovK6junVgo=uLgf&7{#XUlkP+4)0uuiD1 zxJS4}sIa(4xJ{_CxJOtyZbjZ25LU=}yba9XH zoFMDs9^nN++QmJ>_XK$t_Xr{H;tt`ZxaLB|hvY-eht!KJgdYiVFYXaS?!_I#&*GYk zi2zyvCIbyF{2oHI16+wvwvF|s37!6+6FyInF_yr-NI1|^2`i4@dXBwYICh-D!CryU zWSLHAPJh`CSe7h7Z+QIq&eGYf_0w0s%j~u{R>k>LEaNd2{(d)!Rhf=eSsbf69jp2n zs~X5lDF4k?>%7H|u7KqFJ8Q7Llk+|HwP*KlSZ~Ax@m9Y-_<<#?p2HrA_=<%sw>NMW zEy5c|#t@L4Nz2RbIBP|5deH+Cn*2` literal 57481 zcmeHQTX)*H7Cx`tze48;@TjZUfJr7R4cGy}c!E$s2vIU%!6MF07&3b9)1)=X_(9bHlpdts%RyT#LC6cQ$p0 zw&mK)wK{!-IxAW-M$xF%O3WF!%(?IPIlCM7Zmr=1`^$bPTBQ=Roo_wI-YuLy9A7q0 z3yki@<*<&7g^Wt982I_l(%G%`^UvYn$7t6mv)i8IU-PM0#$&8XAXa5MR%LOl>U6B? zW2|Z*FQc?Wqwj+sY=-z9Y6~{J+V^-OZ^+eO?YEkZc9XRmdnZkH?dsPcjInF$I>4&4 z^ENyCaB{-&So7@d@mX`%;}<(<9yUIlwAubqqjlMA@AfUX z=jilC`**FZm&@#;(P|&JkI&E8o}Z0XqT=JPf|;j{&wsYgKV7n226mnvpH1%k!tlT= z4s{A9HG)aO<3Q5Nilmk0NvkW8R)b0LHUgy@vq?)#dqX{EWDi}|bKHRt%)hPvy**;Z zp?wF5Ef%Z-7cyGntXSw2#3}GZH@4)H@lTxsH>)M_+U>sGb(zM#4hOf$c84soQg*3V zAZ_|P)Y;I@y;t_*yFIj-wF}u0@3=$vcj)wF7dNt9`Jhvnj&%dsKn!0p0?$MiN^nw^ zk_E+YE;cvA!QEu++nE^*jbsPI$p|@OMt$J`WGo(ljM)LmNNE6?3?i4HKy=ZDiSAkS z(xaW}?%J5`u7%c7v_{=tPxRcS-^wL!n7`FzpFGvkuS}^UWi3`p11YPqQdW?%5-VjD zDUDbuYe=cbN@*fxIabPgiR;_3Qf?vTR;-lUNLi1SQil-fF@*?Hq{ovY9b%-%6C)jR zq{ovZ9fG9C6C@pyq{ova9ipVi6D1w86i<|N$WlB}(jiOnM9F|C#gilhk`zyn3`foCh{z}AAKM6;-2{>{#cQn}8(cPww{_3p{k^L>j8o3t#oD+}NpYD-! z{-;d-crD2qD+T_yxzT-REU0%C(#S(%J2fzjRJ>jQK3{*YiTy ztAo8=$=q%?-^^Y3k$9S|1@L?F!B}at3-$Jtdz6%mSK91Cp~#DltJIm4+h4lHPpt^T z0&Us~QCgh@SFbiT!u%z6C&3Cn!Sb52Jb~?EG&>n(d9um|Nm-u2uy(b*m9jipgGtKr zWX3*w*5L2yEl;LqUik3#Oui$etDC&^(okq^dagGw^Dvvp*HEqSR0 znT;$Rd0~52=p=J5J4aTSlAn5zxu2CIKTOXKrDPstCNtn^`#W#PTfBO6Fnu zN0u0puewmZoc56~hG&afs_W?<*g4z*IH4% z@svki*_>6nr~YEQbkn`Rt>J1k6hBfC%A^8B0Xj-JAj%ZCp5Twc3KL}p6Ge#WVoa1; zx%_-EQ5K**sGoi@2l9?X^NZQ5vd=gN01`B_AAIE7@lItEe5nA6kheG4{O(+xXOBaa z@%Q>7tEW2a7x`KhQEPHw^R7C$FZ<$Mn5HH(ncRkHs)kQ6-AZ~NCe1JfDr2;rjU)n? z20)s~DJ24!hOI~fN3!VN#cKLG2}?Xe`ztKNTPpfF=R-B ze`zr!NMe6!G2};Xz@){H9*O*=N!iH^@YkA3f{La%ur>!a)+i&d7N`XI=0L)5gNb4n zs?44N2a*MtOcJb8<&_Qx5(NoO5N}jvl^_R_1aD0a23F;?ngauPc0HS?kjQ6PwHV1r<3mCsKQ2aVL^P7Un&qL8~2roYxMF*H)3sinNc>EkR z{3GDI1aPN+*0%8Wkcz^Q)$tkK2Q*Sv-s^y?&+zLB3=fo@x3cqI`%8|B7|H=Q*m_sWOnXCy z$vi{tQB;fVa)}$Jvh@y3;b!46m96(Gv|eTF?XCsat8Bfk{(VSGQ?}k=%n{O~Y`vo@ zDJuRmz#mgxw7?MWnZpry?>R7b!PHaw%+TQXeSm&*?Lb*!8kF8H&!Jv%B z#iu?9e2Et!>LP?dBYa!HZeIRoPLr)_cgUg!9nf1knS1uQjcr42W80YD#2Y1XBb~8w{Lo+5dtY|UW1r({Eqv;y(75FNA z4c>&W!*9WF!?@aOOs@bBSU@R#sy_z&8oQoW`ci>#)u>At(B1d_Hp*u^? zGTfG7IiNCh2ltL!)JpyU4t$;QFH|vS2Yx)Yh;%ZjLRG4fNp;$y zZ7S0q?L*yY(jhd0BRZx(=p9s#Q#zw_x}f*eqDyMi2l_~#=rdi>mnjWkDXP!NcEhIu zh@fTx&Yu{8M!SYk1m_Kup_KrVKcQ?Yq9a_FbCj=TExPae)bfjIjl;_MTNGxy#U z$n^=u*(ViepIDr^_vS#hPcY7cWRG<5vX&FSfzr23Jaq2qkOud($O`xL$SU_V$r|@` zNt1ipWSx8Zu>=N~ox~M_40NRoo*q36&N12^}ghygj7xxH{2@)@Ugh0}-Q%f@Me z(PWuUXik6G4_KBgL2r2c`OebWt@YDazsu~lH&(^@R4n5$7XE%WiB*}7RaqRXIvuO} z7^@n{ODO-%R_naQj;?^@`a5f|y_54j_O)mCZ&+`{1o2kCKlp(qte(RjiTH|zEw?vt z7A?Xi$F@m%BPRYxnS52h=UY~*`x=g2SVOlb1Q|=X%yMp+ kYyVuadLUz{ULk6)Aevfoto!9XgV)raQH4cQ%W8H14-2*bLI3~& diff --git a/mysql-test/suite/parts/r/partition_datetime_innodb.result b/mysql-test/suite/parts/r/partition_datetime_innodb.result index 67517ff5943..6c889fdf623 100644 --- a/mysql-test/suite/parts/r/partition_datetime_innodb.result +++ b/mysql-test/suite/parts/r/partition_datetime_innodb.result @@ -60,65 +60,6 @@ a 2020-12-31 10:11:12 delete from t2; 59 inserts; -insert into t2 values (19710101000000+59); -insert into t2 values (19710101000000+58); -insert into t2 values (19710101000000+57); -insert into t2 values (19710101000000+56); -insert into t2 values (19710101000000+55); -insert into t2 values (19710101000000+54); -insert into t2 values (19710101000000+53); -insert into t2 values (19710101000000+52); -insert into t2 values (19710101000000+51); -insert into t2 values (19710101000000+50); -insert into t2 values (19710101000000+49); -insert into t2 values (19710101000000+48); -insert into t2 values (19710101000000+47); -insert into t2 values (19710101000000+46); -insert into t2 values (19710101000000+45); -insert into t2 values (19710101000000+44); -insert into t2 values (19710101000000+43); -insert into t2 values (19710101000000+42); -insert into t2 values (19710101000000+41); -insert into t2 values (19710101000000+40); -insert into t2 values (19710101000000+39); -insert into t2 values (19710101000000+38); -insert into t2 values (19710101000000+37); -insert into t2 values (19710101000000+36); -insert into t2 values (19710101000000+35); -insert into t2 values (19710101000000+34); -insert into t2 values (19710101000000+33); -insert into t2 values (19710101000000+32); -insert into t2 values (19710101000000+31); -insert into t2 values (19710101000000+30); -insert into t2 values (19710101000000+29); -insert into t2 values (19710101000000+28); -insert into t2 values (19710101000000+27); -insert into t2 values (19710101000000+26); -insert into t2 values (19710101000000+25); -insert into t2 values (19710101000000+24); -insert into t2 values (19710101000000+23); -insert into t2 values (19710101000000+22); -insert into t2 values (19710101000000+21); -insert into t2 values (19710101000000+20); -insert into t2 values (19710101000000+19); -insert into t2 values (19710101000000+18); -insert into t2 values (19710101000000+17); -insert into t2 values (19710101000000+16); -insert into t2 values (19710101000000+15); -insert into t2 values (19710101000000+14); -insert into t2 values (19710101000000+13); -insert into t2 values (19710101000000+12); -insert into t2 values (19710101000000+11); -insert into t2 values (19710101000000+10); -insert into t2 values (19710101000000+9); -insert into t2 values (19710101000000+8); -insert into t2 values (19710101000000+7); -insert into t2 values (19710101000000+6); -insert into t2 values (19710101000000+5); -insert into t2 values (19710101000000+4); -insert into t2 values (19710101000000+3); -insert into t2 values (19710101000000+2); -insert into t2 values (19710101000000+1); select count(*) from t2; count(*) 59 @@ -206,18 +147,6 @@ SUBPARTITIONS 3 PARTITION quarter3 VALUES LESS THAN (10) ENGINE = InnoDB, PARTITION quarter4 VALUES LESS THAN (13) ENGINE = InnoDB) */ 12 inserts; -insert into t3 values (date_add('1970-01-01 00:00:00',interval 12-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 11-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 10-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 9-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 8-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 7-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 6-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 5-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 4-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 3-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 2-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 1-1 month)); Warnings: Warning 1264 Out of range value for column 'a' at row 1 select count(*) from t3; @@ -260,18 +189,6 @@ SUBPARTITIONS 3 PARTITION quarter3 VALUES IN (7,8,9) ENGINE = InnoDB, PARTITION quarter4 VALUES IN (10,11,12) ENGINE = InnoDB) */ 12 inserts; -insert into t4 values (date_add('1970-01-01 00:00:00',interval 12-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 11-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 10-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 9-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 8-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 7-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 6-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 5-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 4-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 3-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 2-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 1-1 month)); Warnings: Warning 1264 Out of range value for column 'a' at row 1 select count(*) from t4; @@ -354,90 +271,6 @@ a 2020-12-31 delete from t2; 28 inserts; -insert into t2 values (19700101+28-1); -insert into t2 values (19700201+28-1); -insert into t2 values (19700301+28-1); -insert into t2 values (19700101+27-1); -insert into t2 values (19700201+27-1); -insert into t2 values (19700301+27-1); -insert into t2 values (19700101+26-1); -insert into t2 values (19700201+26-1); -insert into t2 values (19700301+26-1); -insert into t2 values (19700101+25-1); -insert into t2 values (19700201+25-1); -insert into t2 values (19700301+25-1); -insert into t2 values (19700101+24-1); -insert into t2 values (19700201+24-1); -insert into t2 values (19700301+24-1); -insert into t2 values (19700101+23-1); -insert into t2 values (19700201+23-1); -insert into t2 values (19700301+23-1); -insert into t2 values (19700101+22-1); -insert into t2 values (19700201+22-1); -insert into t2 values (19700301+22-1); -insert into t2 values (19700101+21-1); -insert into t2 values (19700201+21-1); -insert into t2 values (19700301+21-1); -insert into t2 values (19700101+20-1); -insert into t2 values (19700201+20-1); -insert into t2 values (19700301+20-1); -insert into t2 values (19700101+19-1); -insert into t2 values (19700201+19-1); -insert into t2 values (19700301+19-1); -insert into t2 values (19700101+18-1); -insert into t2 values (19700201+18-1); -insert into t2 values (19700301+18-1); -insert into t2 values (19700101+17-1); -insert into t2 values (19700201+17-1); -insert into t2 values (19700301+17-1); -insert into t2 values (19700101+16-1); -insert into t2 values (19700201+16-1); -insert into t2 values (19700301+16-1); -insert into t2 values (19700101+15-1); -insert into t2 values (19700201+15-1); -insert into t2 values (19700301+15-1); -insert into t2 values (19700101+14-1); -insert into t2 values (19700201+14-1); -insert into t2 values (19700301+14-1); -insert into t2 values (19700101+13-1); -insert into t2 values (19700201+13-1); -insert into t2 values (19700301+13-1); -insert into t2 values (19700101+12-1); -insert into t2 values (19700201+12-1); -insert into t2 values (19700301+12-1); -insert into t2 values (19700101+11-1); -insert into t2 values (19700201+11-1); -insert into t2 values (19700301+11-1); -insert into t2 values (19700101+10-1); -insert into t2 values (19700201+10-1); -insert into t2 values (19700301+10-1); -insert into t2 values (19700101+9-1); -insert into t2 values (19700201+9-1); -insert into t2 values (19700301+9-1); -insert into t2 values (19700101+8-1); -insert into t2 values (19700201+8-1); -insert into t2 values (19700301+8-1); -insert into t2 values (19700101+7-1); -insert into t2 values (19700201+7-1); -insert into t2 values (19700301+7-1); -insert into t2 values (19700101+6-1); -insert into t2 values (19700201+6-1); -insert into t2 values (19700301+6-1); -insert into t2 values (19700101+5-1); -insert into t2 values (19700201+5-1); -insert into t2 values (19700301+5-1); -insert into t2 values (19700101+4-1); -insert into t2 values (19700201+4-1); -insert into t2 values (19700301+4-1); -insert into t2 values (19700101+3-1); -insert into t2 values (19700201+3-1); -insert into t2 values (19700301+3-1); -insert into t2 values (19700101+2-1); -insert into t2 values (19700201+2-1); -insert into t2 values (19700301+2-1); -insert into t2 values (19700101+1-1); -insert into t2 values (19700201+1-1); -insert into t2 values (19700301+1-1); select count(*) from t2; count(*) 84 @@ -550,18 +383,6 @@ SUBPARTITIONS 3 PARTITION quarter3 VALUES LESS THAN (10) ENGINE = InnoDB, PARTITION quarter4 VALUES LESS THAN (13) ENGINE = InnoDB) */ 12 inserts; -insert into t3 values (adddate(19700101,interval 12-1 month)); -insert into t3 values (adddate(19700101,interval 11-1 month)); -insert into t3 values (adddate(19700101,interval 10-1 month)); -insert into t3 values (adddate(19700101,interval 9-1 month)); -insert into t3 values (adddate(19700101,interval 8-1 month)); -insert into t3 values (adddate(19700101,interval 7-1 month)); -insert into t3 values (adddate(19700101,interval 6-1 month)); -insert into t3 values (adddate(19700101,interval 5-1 month)); -insert into t3 values (adddate(19700101,interval 4-1 month)); -insert into t3 values (adddate(19700101,interval 3-1 month)); -insert into t3 values (adddate(19700101,interval 2-1 month)); -insert into t3 values (adddate(19700101,interval 1-1 month)); select count(*) from t3; count(*) 12 @@ -602,18 +423,6 @@ SUBPARTITIONS 3 PARTITION quarter3 VALUES IN (7,8,9) ENGINE = InnoDB, PARTITION quarter4 VALUES IN (10,11,12) ENGINE = InnoDB) */ 12 inserts; -insert into t4 values (adddate(19700101,interval 12-1 month)); -insert into t4 values (adddate(19700101,interval 11-1 month)); -insert into t4 values (adddate(19700101,interval 10-1 month)); -insert into t4 values (adddate(19700101,interval 9-1 month)); -insert into t4 values (adddate(19700101,interval 8-1 month)); -insert into t4 values (adddate(19700101,interval 7-1 month)); -insert into t4 values (adddate(19700101,interval 6-1 month)); -insert into t4 values (adddate(19700101,interval 5-1 month)); -insert into t4 values (adddate(19700101,interval 4-1 month)); -insert into t4 values (adddate(19700101,interval 3-1 month)); -insert into t4 values (adddate(19700101,interval 2-1 month)); -insert into t4 values (adddate(19700101,interval 1-1 month)); select count(*) from t4; count(*) 12 @@ -694,65 +503,6 @@ a 14:15:16 delete from t2; 59 inserts; -insert into t2 values (000100+59); -insert into t2 values (000100+58); -insert into t2 values (000100+57); -insert into t2 values (000100+56); -insert into t2 values (000100+55); -insert into t2 values (000100+54); -insert into t2 values (000100+53); -insert into t2 values (000100+52); -insert into t2 values (000100+51); -insert into t2 values (000100+50); -insert into t2 values (000100+49); -insert into t2 values (000100+48); -insert into t2 values (000100+47); -insert into t2 values (000100+46); -insert into t2 values (000100+45); -insert into t2 values (000100+44); -insert into t2 values (000100+43); -insert into t2 values (000100+42); -insert into t2 values (000100+41); -insert into t2 values (000100+40); -insert into t2 values (000100+39); -insert into t2 values (000100+38); -insert into t2 values (000100+37); -insert into t2 values (000100+36); -insert into t2 values (000100+35); -insert into t2 values (000100+34); -insert into t2 values (000100+33); -insert into t2 values (000100+32); -insert into t2 values (000100+31); -insert into t2 values (000100+30); -insert into t2 values (000100+29); -insert into t2 values (000100+28); -insert into t2 values (000100+27); -insert into t2 values (000100+26); -insert into t2 values (000100+25); -insert into t2 values (000100+24); -insert into t2 values (000100+23); -insert into t2 values (000100+22); -insert into t2 values (000100+21); -insert into t2 values (000100+20); -insert into t2 values (000100+19); -insert into t2 values (000100+18); -insert into t2 values (000100+17); -insert into t2 values (000100+16); -insert into t2 values (000100+15); -insert into t2 values (000100+14); -insert into t2 values (000100+13); -insert into t2 values (000100+12); -insert into t2 values (000100+11); -insert into t2 values (000100+10); -insert into t2 values (000100+9); -insert into t2 values (000100+8); -insert into t2 values (000100+7); -insert into t2 values (000100+6); -insert into t2 values (000100+5); -insert into t2 values (000100+4); -insert into t2 values (000100+3); -insert into t2 values (000100+2); -insert into t2 values (000100+1); select count(*) from t2; count(*) 59 @@ -840,65 +590,6 @@ SUBPARTITIONS 3 PARTITION quarter3 VALUES LESS THAN (46) ENGINE = InnoDB, PARTITION quarter4 VALUES LESS THAN (61) ENGINE = InnoDB) */ 59 inserts; -insert into t3 values (100000+59); -insert into t3 values (100000+58); -insert into t3 values (100000+57); -insert into t3 values (100000+56); -insert into t3 values (100000+55); -insert into t3 values (100000+54); -insert into t3 values (100000+53); -insert into t3 values (100000+52); -insert into t3 values (100000+51); -insert into t3 values (100000+50); -insert into t3 values (100000+49); -insert into t3 values (100000+48); -insert into t3 values (100000+47); -insert into t3 values (100000+46); -insert into t3 values (100000+45); -insert into t3 values (100000+44); -insert into t3 values (100000+43); -insert into t3 values (100000+42); -insert into t3 values (100000+41); -insert into t3 values (100000+40); -insert into t3 values (100000+39); -insert into t3 values (100000+38); -insert into t3 values (100000+37); -insert into t3 values (100000+36); -insert into t3 values (100000+35); -insert into t3 values (100000+34); -insert into t3 values (100000+33); -insert into t3 values (100000+32); -insert into t3 values (100000+31); -insert into t3 values (100000+30); -insert into t3 values (100000+29); -insert into t3 values (100000+28); -insert into t3 values (100000+27); -insert into t3 values (100000+26); -insert into t3 values (100000+25); -insert into t3 values (100000+24); -insert into t3 values (100000+23); -insert into t3 values (100000+22); -insert into t3 values (100000+21); -insert into t3 values (100000+20); -insert into t3 values (100000+19); -insert into t3 values (100000+18); -insert into t3 values (100000+17); -insert into t3 values (100000+16); -insert into t3 values (100000+15); -insert into t3 values (100000+14); -insert into t3 values (100000+13); -insert into t3 values (100000+12); -insert into t3 values (100000+11); -insert into t3 values (100000+10); -insert into t3 values (100000+9); -insert into t3 values (100000+8); -insert into t3 values (100000+7); -insert into t3 values (100000+6); -insert into t3 values (100000+5); -insert into t3 values (100000+4); -insert into t3 values (100000+3); -insert into t3 values (100000+2); -insert into t3 values (100000+1); select count(*) from t3; count(*) 59 @@ -986,65 +677,6 @@ SUBPARTITIONS 3 PARTITION quarter3 VALUES IN (31,32,33,34,35,36,37,38,39,40,41,42,43,44,45) ENGINE = InnoDB, PARTITION quarter4 VALUES IN (46,47,48,49,50,51,52,53,54,55,56,57,58,59,60) ENGINE = InnoDB) */ 59 inserts; -insert into t4 values (100000+59); -insert into t4 values (100000+58); -insert into t4 values (100000+57); -insert into t4 values (100000+56); -insert into t4 values (100000+55); -insert into t4 values (100000+54); -insert into t4 values (100000+53); -insert into t4 values (100000+52); -insert into t4 values (100000+51); -insert into t4 values (100000+50); -insert into t4 values (100000+49); -insert into t4 values (100000+48); -insert into t4 values (100000+47); -insert into t4 values (100000+46); -insert into t4 values (100000+45); -insert into t4 values (100000+44); -insert into t4 values (100000+43); -insert into t4 values (100000+42); -insert into t4 values (100000+41); -insert into t4 values (100000+40); -insert into t4 values (100000+39); -insert into t4 values (100000+38); -insert into t4 values (100000+37); -insert into t4 values (100000+36); -insert into t4 values (100000+35); -insert into t4 values (100000+34); -insert into t4 values (100000+33); -insert into t4 values (100000+32); -insert into t4 values (100000+31); -insert into t4 values (100000+30); -insert into t4 values (100000+29); -insert into t4 values (100000+28); -insert into t4 values (100000+27); -insert into t4 values (100000+26); -insert into t4 values (100000+25); -insert into t4 values (100000+24); -insert into t4 values (100000+23); -insert into t4 values (100000+22); -insert into t4 values (100000+21); -insert into t4 values (100000+20); -insert into t4 values (100000+19); -insert into t4 values (100000+18); -insert into t4 values (100000+17); -insert into t4 values (100000+16); -insert into t4 values (100000+15); -insert into t4 values (100000+14); -insert into t4 values (100000+13); -insert into t4 values (100000+12); -insert into t4 values (100000+11); -insert into t4 values (100000+10); -insert into t4 values (100000+9); -insert into t4 values (100000+8); -insert into t4 values (100000+7); -insert into t4 values (100000+6); -insert into t4 values (100000+5); -insert into t4 values (100000+4); -insert into t4 values (100000+3); -insert into t4 values (100000+2); -insert into t4 values (100000+1); select count(*) from t4; count(*) 59 @@ -1172,65 +804,6 @@ a 2020-12-31 10:11:12 delete from t2; 59 inserts; -insert into t2 values (19700101000000+59); -insert into t2 values (19700101000000+58); -insert into t2 values (19700101000000+57); -insert into t2 values (19700101000000+56); -insert into t2 values (19700101000000+55); -insert into t2 values (19700101000000+54); -insert into t2 values (19700101000000+53); -insert into t2 values (19700101000000+52); -insert into t2 values (19700101000000+51); -insert into t2 values (19700101000000+50); -insert into t2 values (19700101000000+49); -insert into t2 values (19700101000000+48); -insert into t2 values (19700101000000+47); -insert into t2 values (19700101000000+46); -insert into t2 values (19700101000000+45); -insert into t2 values (19700101000000+44); -insert into t2 values (19700101000000+43); -insert into t2 values (19700101000000+42); -insert into t2 values (19700101000000+41); -insert into t2 values (19700101000000+40); -insert into t2 values (19700101000000+39); -insert into t2 values (19700101000000+38); -insert into t2 values (19700101000000+37); -insert into t2 values (19700101000000+36); -insert into t2 values (19700101000000+35); -insert into t2 values (19700101000000+34); -insert into t2 values (19700101000000+33); -insert into t2 values (19700101000000+32); -insert into t2 values (19700101000000+31); -insert into t2 values (19700101000000+30); -insert into t2 values (19700101000000+29); -insert into t2 values (19700101000000+28); -insert into t2 values (19700101000000+27); -insert into t2 values (19700101000000+26); -insert into t2 values (19700101000000+25); -insert into t2 values (19700101000000+24); -insert into t2 values (19700101000000+23); -insert into t2 values (19700101000000+22); -insert into t2 values (19700101000000+21); -insert into t2 values (19700101000000+20); -insert into t2 values (19700101000000+19); -insert into t2 values (19700101000000+18); -insert into t2 values (19700101000000+17); -insert into t2 values (19700101000000+16); -insert into t2 values (19700101000000+15); -insert into t2 values (19700101000000+14); -insert into t2 values (19700101000000+13); -insert into t2 values (19700101000000+12); -insert into t2 values (19700101000000+11); -insert into t2 values (19700101000000+10); -insert into t2 values (19700101000000+9); -insert into t2 values (19700101000000+8); -insert into t2 values (19700101000000+7); -insert into t2 values (19700101000000+6); -insert into t2 values (19700101000000+5); -insert into t2 values (19700101000000+4); -insert into t2 values (19700101000000+3); -insert into t2 values (19700101000000+2); -insert into t2 values (19700101000000+1); select count(*) from t2; count(*) 59 @@ -1318,18 +891,6 @@ SUBPARTITIONS 3 PARTITION quarter3 VALUES LESS THAN (10) ENGINE = InnoDB, PARTITION quarter4 VALUES LESS THAN (13) ENGINE = InnoDB) */ 12 inserts; -insert into t3 values (adddate(19700101000000,interval 12-1 month)); -insert into t3 values (adddate(19700101000000,interval 11-1 month)); -insert into t3 values (adddate(19700101000000,interval 10-1 month)); -insert into t3 values (adddate(19700101000000,interval 9-1 month)); -insert into t3 values (adddate(19700101000000,interval 8-1 month)); -insert into t3 values (adddate(19700101000000,interval 7-1 month)); -insert into t3 values (adddate(19700101000000,interval 6-1 month)); -insert into t3 values (adddate(19700101000000,interval 5-1 month)); -insert into t3 values (adddate(19700101000000,interval 4-1 month)); -insert into t3 values (adddate(19700101000000,interval 3-1 month)); -insert into t3 values (adddate(19700101000000,interval 2-1 month)); -insert into t3 values (adddate(19700101000000,interval 1-1 month)); select count(*) from t3; count(*) 12 @@ -1370,18 +931,6 @@ SUBPARTITIONS 3 PARTITION quarter3 VALUES IN (7,8,9) ENGINE = InnoDB, PARTITION quarter4 VALUES IN (10,11,12) ENGINE = InnoDB) */ 12 inserts; -insert into t4 values (adddate(19700101000000,interval 12-1 month)); -insert into t4 values (adddate(19700101000000,interval 11-1 month)); -insert into t4 values (adddate(19700101000000,interval 10-1 month)); -insert into t4 values (adddate(19700101000000,interval 9-1 month)); -insert into t4 values (adddate(19700101000000,interval 8-1 month)); -insert into t4 values (adddate(19700101000000,interval 7-1 month)); -insert into t4 values (adddate(19700101000000,interval 6-1 month)); -insert into t4 values (adddate(19700101000000,interval 5-1 month)); -insert into t4 values (adddate(19700101000000,interval 4-1 month)); -insert into t4 values (adddate(19700101000000,interval 3-1 month)); -insert into t4 values (adddate(19700101000000,interval 2-1 month)); -insert into t4 values (adddate(19700101000000,interval 1-1 month)); select count(*) from t4; count(*) 12 diff --git a/mysql-test/suite/parts/r/partition_datetime_myisam.result b/mysql-test/suite/parts/r/partition_datetime_myisam.result index ad542870e65..5e9801d8571 100644 --- a/mysql-test/suite/parts/r/partition_datetime_myisam.result +++ b/mysql-test/suite/parts/r/partition_datetime_myisam.result @@ -60,65 +60,6 @@ a 2020-12-31 10:11:12 delete from t2; 59 inserts; -insert into t2 values (19710101000000+59); -insert into t2 values (19710101000000+58); -insert into t2 values (19710101000000+57); -insert into t2 values (19710101000000+56); -insert into t2 values (19710101000000+55); -insert into t2 values (19710101000000+54); -insert into t2 values (19710101000000+53); -insert into t2 values (19710101000000+52); -insert into t2 values (19710101000000+51); -insert into t2 values (19710101000000+50); -insert into t2 values (19710101000000+49); -insert into t2 values (19710101000000+48); -insert into t2 values (19710101000000+47); -insert into t2 values (19710101000000+46); -insert into t2 values (19710101000000+45); -insert into t2 values (19710101000000+44); -insert into t2 values (19710101000000+43); -insert into t2 values (19710101000000+42); -insert into t2 values (19710101000000+41); -insert into t2 values (19710101000000+40); -insert into t2 values (19710101000000+39); -insert into t2 values (19710101000000+38); -insert into t2 values (19710101000000+37); -insert into t2 values (19710101000000+36); -insert into t2 values (19710101000000+35); -insert into t2 values (19710101000000+34); -insert into t2 values (19710101000000+33); -insert into t2 values (19710101000000+32); -insert into t2 values (19710101000000+31); -insert into t2 values (19710101000000+30); -insert into t2 values (19710101000000+29); -insert into t2 values (19710101000000+28); -insert into t2 values (19710101000000+27); -insert into t2 values (19710101000000+26); -insert into t2 values (19710101000000+25); -insert into t2 values (19710101000000+24); -insert into t2 values (19710101000000+23); -insert into t2 values (19710101000000+22); -insert into t2 values (19710101000000+21); -insert into t2 values (19710101000000+20); -insert into t2 values (19710101000000+19); -insert into t2 values (19710101000000+18); -insert into t2 values (19710101000000+17); -insert into t2 values (19710101000000+16); -insert into t2 values (19710101000000+15); -insert into t2 values (19710101000000+14); -insert into t2 values (19710101000000+13); -insert into t2 values (19710101000000+12); -insert into t2 values (19710101000000+11); -insert into t2 values (19710101000000+10); -insert into t2 values (19710101000000+9); -insert into t2 values (19710101000000+8); -insert into t2 values (19710101000000+7); -insert into t2 values (19710101000000+6); -insert into t2 values (19710101000000+5); -insert into t2 values (19710101000000+4); -insert into t2 values (19710101000000+3); -insert into t2 values (19710101000000+2); -insert into t2 values (19710101000000+1); select count(*) from t2; count(*) 59 @@ -206,18 +147,6 @@ SUBPARTITIONS 3 PARTITION quarter3 VALUES LESS THAN (10) ENGINE = MyISAM, PARTITION quarter4 VALUES LESS THAN (13) ENGINE = MyISAM) */ 12 inserts; -insert into t3 values (date_add('1970-01-01 00:00:00',interval 12-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 11-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 10-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 9-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 8-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 7-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 6-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 5-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 4-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 3-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 2-1 month)); -insert into t3 values (date_add('1970-01-01 00:00:00',interval 1-1 month)); Warnings: Warning 1264 Out of range value for column 'a' at row 1 select count(*) from t3; @@ -260,18 +189,6 @@ SUBPARTITIONS 3 PARTITION quarter3 VALUES IN (7,8,9) ENGINE = MyISAM, PARTITION quarter4 VALUES IN (10,11,12) ENGINE = MyISAM) */ 12 inserts; -insert into t4 values (date_add('1970-01-01 00:00:00',interval 12-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 11-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 10-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 9-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 8-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 7-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 6-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 5-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 4-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 3-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 2-1 month)); -insert into t4 values (date_add('1970-01-01 00:00:00',interval 1-1 month)); Warnings: Warning 1264 Out of range value for column 'a' at row 1 select count(*) from t4; @@ -354,90 +271,6 @@ a 2020-12-31 delete from t2; 28 inserts; -insert into t2 values (19700101+28-1); -insert into t2 values (19700201+28-1); -insert into t2 values (19700301+28-1); -insert into t2 values (19700101+27-1); -insert into t2 values (19700201+27-1); -insert into t2 values (19700301+27-1); -insert into t2 values (19700101+26-1); -insert into t2 values (19700201+26-1); -insert into t2 values (19700301+26-1); -insert into t2 values (19700101+25-1); -insert into t2 values (19700201+25-1); -insert into t2 values (19700301+25-1); -insert into t2 values (19700101+24-1); -insert into t2 values (19700201+24-1); -insert into t2 values (19700301+24-1); -insert into t2 values (19700101+23-1); -insert into t2 values (19700201+23-1); -insert into t2 values (19700301+23-1); -insert into t2 values (19700101+22-1); -insert into t2 values (19700201+22-1); -insert into t2 values (19700301+22-1); -insert into t2 values (19700101+21-1); -insert into t2 values (19700201+21-1); -insert into t2 values (19700301+21-1); -insert into t2 values (19700101+20-1); -insert into t2 values (19700201+20-1); -insert into t2 values (19700301+20-1); -insert into t2 values (19700101+19-1); -insert into t2 values (19700201+19-1); -insert into t2 values (19700301+19-1); -insert into t2 values (19700101+18-1); -insert into t2 values (19700201+18-1); -insert into t2 values (19700301+18-1); -insert into t2 values (19700101+17-1); -insert into t2 values (19700201+17-1); -insert into t2 values (19700301+17-1); -insert into t2 values (19700101+16-1); -insert into t2 values (19700201+16-1); -insert into t2 values (19700301+16-1); -insert into t2 values (19700101+15-1); -insert into t2 values (19700201+15-1); -insert into t2 values (19700301+15-1); -insert into t2 values (19700101+14-1); -insert into t2 values (19700201+14-1); -insert into t2 values (19700301+14-1); -insert into t2 values (19700101+13-1); -insert into t2 values (19700201+13-1); -insert into t2 values (19700301+13-1); -insert into t2 values (19700101+12-1); -insert into t2 values (19700201+12-1); -insert into t2 values (19700301+12-1); -insert into t2 values (19700101+11-1); -insert into t2 values (19700201+11-1); -insert into t2 values (19700301+11-1); -insert into t2 values (19700101+10-1); -insert into t2 values (19700201+10-1); -insert into t2 values (19700301+10-1); -insert into t2 values (19700101+9-1); -insert into t2 values (19700201+9-1); -insert into t2 values (19700301+9-1); -insert into t2 values (19700101+8-1); -insert into t2 values (19700201+8-1); -insert into t2 values (19700301+8-1); -insert into t2 values (19700101+7-1); -insert into t2 values (19700201+7-1); -insert into t2 values (19700301+7-1); -insert into t2 values (19700101+6-1); -insert into t2 values (19700201+6-1); -insert into t2 values (19700301+6-1); -insert into t2 values (19700101+5-1); -insert into t2 values (19700201+5-1); -insert into t2 values (19700301+5-1); -insert into t2 values (19700101+4-1); -insert into t2 values (19700201+4-1); -insert into t2 values (19700301+4-1); -insert into t2 values (19700101+3-1); -insert into t2 values (19700201+3-1); -insert into t2 values (19700301+3-1); -insert into t2 values (19700101+2-1); -insert into t2 values (19700201+2-1); -insert into t2 values (19700301+2-1); -insert into t2 values (19700101+1-1); -insert into t2 values (19700201+1-1); -insert into t2 values (19700301+1-1); select count(*) from t2; count(*) 84 @@ -550,18 +383,6 @@ SUBPARTITIONS 3 PARTITION quarter3 VALUES LESS THAN (10) ENGINE = MyISAM, PARTITION quarter4 VALUES LESS THAN (13) ENGINE = MyISAM) */ 12 inserts; -insert into t3 values (adddate(19700101,interval 12-1 month)); -insert into t3 values (adddate(19700101,interval 11-1 month)); -insert into t3 values (adddate(19700101,interval 10-1 month)); -insert into t3 values (adddate(19700101,interval 9-1 month)); -insert into t3 values (adddate(19700101,interval 8-1 month)); -insert into t3 values (adddate(19700101,interval 7-1 month)); -insert into t3 values (adddate(19700101,interval 6-1 month)); -insert into t3 values (adddate(19700101,interval 5-1 month)); -insert into t3 values (adddate(19700101,interval 4-1 month)); -insert into t3 values (adddate(19700101,interval 3-1 month)); -insert into t3 values (adddate(19700101,interval 2-1 month)); -insert into t3 values (adddate(19700101,interval 1-1 month)); select count(*) from t3; count(*) 12 @@ -602,18 +423,6 @@ SUBPARTITIONS 3 PARTITION quarter3 VALUES IN (7,8,9) ENGINE = MyISAM, PARTITION quarter4 VALUES IN (10,11,12) ENGINE = MyISAM) */ 12 inserts; -insert into t4 values (adddate(19700101,interval 12-1 month)); -insert into t4 values (adddate(19700101,interval 11-1 month)); -insert into t4 values (adddate(19700101,interval 10-1 month)); -insert into t4 values (adddate(19700101,interval 9-1 month)); -insert into t4 values (adddate(19700101,interval 8-1 month)); -insert into t4 values (adddate(19700101,interval 7-1 month)); -insert into t4 values (adddate(19700101,interval 6-1 month)); -insert into t4 values (adddate(19700101,interval 5-1 month)); -insert into t4 values (adddate(19700101,interval 4-1 month)); -insert into t4 values (adddate(19700101,interval 3-1 month)); -insert into t4 values (adddate(19700101,interval 2-1 month)); -insert into t4 values (adddate(19700101,interval 1-1 month)); select count(*) from t4; count(*) 12 @@ -694,65 +503,6 @@ a 14:15:16 delete from t2; 59 inserts; -insert into t2 values (000100+59); -insert into t2 values (000100+58); -insert into t2 values (000100+57); -insert into t2 values (000100+56); -insert into t2 values (000100+55); -insert into t2 values (000100+54); -insert into t2 values (000100+53); -insert into t2 values (000100+52); -insert into t2 values (000100+51); -insert into t2 values (000100+50); -insert into t2 values (000100+49); -insert into t2 values (000100+48); -insert into t2 values (000100+47); -insert into t2 values (000100+46); -insert into t2 values (000100+45); -insert into t2 values (000100+44); -insert into t2 values (000100+43); -insert into t2 values (000100+42); -insert into t2 values (000100+41); -insert into t2 values (000100+40); -insert into t2 values (000100+39); -insert into t2 values (000100+38); -insert into t2 values (000100+37); -insert into t2 values (000100+36); -insert into t2 values (000100+35); -insert into t2 values (000100+34); -insert into t2 values (000100+33); -insert into t2 values (000100+32); -insert into t2 values (000100+31); -insert into t2 values (000100+30); -insert into t2 values (000100+29); -insert into t2 values (000100+28); -insert into t2 values (000100+27); -insert into t2 values (000100+26); -insert into t2 values (000100+25); -insert into t2 values (000100+24); -insert into t2 values (000100+23); -insert into t2 values (000100+22); -insert into t2 values (000100+21); -insert into t2 values (000100+20); -insert into t2 values (000100+19); -insert into t2 values (000100+18); -insert into t2 values (000100+17); -insert into t2 values (000100+16); -insert into t2 values (000100+15); -insert into t2 values (000100+14); -insert into t2 values (000100+13); -insert into t2 values (000100+12); -insert into t2 values (000100+11); -insert into t2 values (000100+10); -insert into t2 values (000100+9); -insert into t2 values (000100+8); -insert into t2 values (000100+7); -insert into t2 values (000100+6); -insert into t2 values (000100+5); -insert into t2 values (000100+4); -insert into t2 values (000100+3); -insert into t2 values (000100+2); -insert into t2 values (000100+1); select count(*) from t2; count(*) 59 @@ -840,65 +590,6 @@ SUBPARTITIONS 3 PARTITION quarter3 VALUES LESS THAN (46) ENGINE = MyISAM, PARTITION quarter4 VALUES LESS THAN (61) ENGINE = MyISAM) */ 59 inserts; -insert into t3 values (100000+59); -insert into t3 values (100000+58); -insert into t3 values (100000+57); -insert into t3 values (100000+56); -insert into t3 values (100000+55); -insert into t3 values (100000+54); -insert into t3 values (100000+53); -insert into t3 values (100000+52); -insert into t3 values (100000+51); -insert into t3 values (100000+50); -insert into t3 values (100000+49); -insert into t3 values (100000+48); -insert into t3 values (100000+47); -insert into t3 values (100000+46); -insert into t3 values (100000+45); -insert into t3 values (100000+44); -insert into t3 values (100000+43); -insert into t3 values (100000+42); -insert into t3 values (100000+41); -insert into t3 values (100000+40); -insert into t3 values (100000+39); -insert into t3 values (100000+38); -insert into t3 values (100000+37); -insert into t3 values (100000+36); -insert into t3 values (100000+35); -insert into t3 values (100000+34); -insert into t3 values (100000+33); -insert into t3 values (100000+32); -insert into t3 values (100000+31); -insert into t3 values (100000+30); -insert into t3 values (100000+29); -insert into t3 values (100000+28); -insert into t3 values (100000+27); -insert into t3 values (100000+26); -insert into t3 values (100000+25); -insert into t3 values (100000+24); -insert into t3 values (100000+23); -insert into t3 values (100000+22); -insert into t3 values (100000+21); -insert into t3 values (100000+20); -insert into t3 values (100000+19); -insert into t3 values (100000+18); -insert into t3 values (100000+17); -insert into t3 values (100000+16); -insert into t3 values (100000+15); -insert into t3 values (100000+14); -insert into t3 values (100000+13); -insert into t3 values (100000+12); -insert into t3 values (100000+11); -insert into t3 values (100000+10); -insert into t3 values (100000+9); -insert into t3 values (100000+8); -insert into t3 values (100000+7); -insert into t3 values (100000+6); -insert into t3 values (100000+5); -insert into t3 values (100000+4); -insert into t3 values (100000+3); -insert into t3 values (100000+2); -insert into t3 values (100000+1); select count(*) from t3; count(*) 59 @@ -986,65 +677,6 @@ SUBPARTITIONS 3 PARTITION quarter3 VALUES IN (31,32,33,34,35,36,37,38,39,40,41,42,43,44,45) ENGINE = MyISAM, PARTITION quarter4 VALUES IN (46,47,48,49,50,51,52,53,54,55,56,57,58,59,60) ENGINE = MyISAM) */ 59 inserts; -insert into t4 values (100000+59); -insert into t4 values (100000+58); -insert into t4 values (100000+57); -insert into t4 values (100000+56); -insert into t4 values (100000+55); -insert into t4 values (100000+54); -insert into t4 values (100000+53); -insert into t4 values (100000+52); -insert into t4 values (100000+51); -insert into t4 values (100000+50); -insert into t4 values (100000+49); -insert into t4 values (100000+48); -insert into t4 values (100000+47); -insert into t4 values (100000+46); -insert into t4 values (100000+45); -insert into t4 values (100000+44); -insert into t4 values (100000+43); -insert into t4 values (100000+42); -insert into t4 values (100000+41); -insert into t4 values (100000+40); -insert into t4 values (100000+39); -insert into t4 values (100000+38); -insert into t4 values (100000+37); -insert into t4 values (100000+36); -insert into t4 values (100000+35); -insert into t4 values (100000+34); -insert into t4 values (100000+33); -insert into t4 values (100000+32); -insert into t4 values (100000+31); -insert into t4 values (100000+30); -insert into t4 values (100000+29); -insert into t4 values (100000+28); -insert into t4 values (100000+27); -insert into t4 values (100000+26); -insert into t4 values (100000+25); -insert into t4 values (100000+24); -insert into t4 values (100000+23); -insert into t4 values (100000+22); -insert into t4 values (100000+21); -insert into t4 values (100000+20); -insert into t4 values (100000+19); -insert into t4 values (100000+18); -insert into t4 values (100000+17); -insert into t4 values (100000+16); -insert into t4 values (100000+15); -insert into t4 values (100000+14); -insert into t4 values (100000+13); -insert into t4 values (100000+12); -insert into t4 values (100000+11); -insert into t4 values (100000+10); -insert into t4 values (100000+9); -insert into t4 values (100000+8); -insert into t4 values (100000+7); -insert into t4 values (100000+6); -insert into t4 values (100000+5); -insert into t4 values (100000+4); -insert into t4 values (100000+3); -insert into t4 values (100000+2); -insert into t4 values (100000+1); select count(*) from t4; count(*) 59 @@ -1172,65 +804,6 @@ a 2020-12-31 10:11:12 delete from t2; 59 inserts; -insert into t2 values (19700101000000+59); -insert into t2 values (19700101000000+58); -insert into t2 values (19700101000000+57); -insert into t2 values (19700101000000+56); -insert into t2 values (19700101000000+55); -insert into t2 values (19700101000000+54); -insert into t2 values (19700101000000+53); -insert into t2 values (19700101000000+52); -insert into t2 values (19700101000000+51); -insert into t2 values (19700101000000+50); -insert into t2 values (19700101000000+49); -insert into t2 values (19700101000000+48); -insert into t2 values (19700101000000+47); -insert into t2 values (19700101000000+46); -insert into t2 values (19700101000000+45); -insert into t2 values (19700101000000+44); -insert into t2 values (19700101000000+43); -insert into t2 values (19700101000000+42); -insert into t2 values (19700101000000+41); -insert into t2 values (19700101000000+40); -insert into t2 values (19700101000000+39); -insert into t2 values (19700101000000+38); -insert into t2 values (19700101000000+37); -insert into t2 values (19700101000000+36); -insert into t2 values (19700101000000+35); -insert into t2 values (19700101000000+34); -insert into t2 values (19700101000000+33); -insert into t2 values (19700101000000+32); -insert into t2 values (19700101000000+31); -insert into t2 values (19700101000000+30); -insert into t2 values (19700101000000+29); -insert into t2 values (19700101000000+28); -insert into t2 values (19700101000000+27); -insert into t2 values (19700101000000+26); -insert into t2 values (19700101000000+25); -insert into t2 values (19700101000000+24); -insert into t2 values (19700101000000+23); -insert into t2 values (19700101000000+22); -insert into t2 values (19700101000000+21); -insert into t2 values (19700101000000+20); -insert into t2 values (19700101000000+19); -insert into t2 values (19700101000000+18); -insert into t2 values (19700101000000+17); -insert into t2 values (19700101000000+16); -insert into t2 values (19700101000000+15); -insert into t2 values (19700101000000+14); -insert into t2 values (19700101000000+13); -insert into t2 values (19700101000000+12); -insert into t2 values (19700101000000+11); -insert into t2 values (19700101000000+10); -insert into t2 values (19700101000000+9); -insert into t2 values (19700101000000+8); -insert into t2 values (19700101000000+7); -insert into t2 values (19700101000000+6); -insert into t2 values (19700101000000+5); -insert into t2 values (19700101000000+4); -insert into t2 values (19700101000000+3); -insert into t2 values (19700101000000+2); -insert into t2 values (19700101000000+1); select count(*) from t2; count(*) 59 @@ -1318,18 +891,6 @@ SUBPARTITIONS 3 PARTITION quarter3 VALUES LESS THAN (10) ENGINE = MyISAM, PARTITION quarter4 VALUES LESS THAN (13) ENGINE = MyISAM) */ 12 inserts; -insert into t3 values (adddate(19700101000000,interval 12-1 month)); -insert into t3 values (adddate(19700101000000,interval 11-1 month)); -insert into t3 values (adddate(19700101000000,interval 10-1 month)); -insert into t3 values (adddate(19700101000000,interval 9-1 month)); -insert into t3 values (adddate(19700101000000,interval 8-1 month)); -insert into t3 values (adddate(19700101000000,interval 7-1 month)); -insert into t3 values (adddate(19700101000000,interval 6-1 month)); -insert into t3 values (adddate(19700101000000,interval 5-1 month)); -insert into t3 values (adddate(19700101000000,interval 4-1 month)); -insert into t3 values (adddate(19700101000000,interval 3-1 month)); -insert into t3 values (adddate(19700101000000,interval 2-1 month)); -insert into t3 values (adddate(19700101000000,interval 1-1 month)); select count(*) from t3; count(*) 12 @@ -1370,18 +931,6 @@ SUBPARTITIONS 3 PARTITION quarter3 VALUES IN (7,8,9) ENGINE = MyISAM, PARTITION quarter4 VALUES IN (10,11,12) ENGINE = MyISAM) */ 12 inserts; -insert into t4 values (adddate(19700101000000,interval 12-1 month)); -insert into t4 values (adddate(19700101000000,interval 11-1 month)); -insert into t4 values (adddate(19700101000000,interval 10-1 month)); -insert into t4 values (adddate(19700101000000,interval 9-1 month)); -insert into t4 values (adddate(19700101000000,interval 8-1 month)); -insert into t4 values (adddate(19700101000000,interval 7-1 month)); -insert into t4 values (adddate(19700101000000,interval 6-1 month)); -insert into t4 values (adddate(19700101000000,interval 5-1 month)); -insert into t4 values (adddate(19700101000000,interval 4-1 month)); -insert into t4 values (adddate(19700101000000,interval 3-1 month)); -insert into t4 values (adddate(19700101000000,interval 2-1 month)); -insert into t4 values (adddate(19700101000000,interval 1-1 month)); select count(*) from t4; count(*) 12 diff --git a/mysql-test/suite/parts/t/part_supported_sql_func_innodb.test b/mysql-test/suite/parts/t/part_supported_sql_func_innodb.test index e8d263e369c..eebad5b0d4f 100644 --- a/mysql-test/suite/parts/t/part_supported_sql_func_innodb.test +++ b/mysql-test/suite/parts/t/part_supported_sql_func_innodb.test @@ -25,6 +25,8 @@ let $debug= 0; let $do_long_tests= 1; +# +--include/big_test.inc # The server must support partitioning. --source include/have_partition.inc diff --git a/mysql-test/suite/parts/t/partition_alter1_1_2_innodb.test b/mysql-test/suite/parts/t/partition_alter1_1_2_innodb.test index f2e057fbbd1..be39f53e93b 100644 --- a/mysql-test/suite/parts/t/partition_alter1_1_2_innodb.test +++ b/mysql-test/suite/parts/t/partition_alter1_1_2_innodb.test @@ -43,6 +43,8 @@ SET @max_row = 20; let $more_trigger_tests= 0; let $more_pk_ui_tests= 0; +# Slow running test +--include/big_test.inc # This test relies on connecting externally from mysqltest, doesn't # work with embedded. --source include/not_embedded.inc diff --git a/mysql-test/suite/parts/t/partition_alter4_myisam.test b/mysql-test/suite/parts/t/partition_alter4_myisam.test index bd27e0f7cd3..a4fd6d5d70c 100644 --- a/mysql-test/suite/parts/t/partition_alter4_myisam.test +++ b/mysql-test/suite/parts/t/partition_alter4_myisam.test @@ -40,6 +40,8 @@ SET @max_row = 20; let $more_trigger_tests= 0; let $more_pk_ui_tests= 0; +# Slow running test +--include/big_test.inc # This test relies on connecting externally from mysqltest, doesn't # work with embedded. --source include/not_embedded.inc diff --git a/mysql-test/t/almost_full.test b/mysql-test/t/almost_full.test index 5c67ab3c088..c192a7c1cd4 100644 --- a/mysql-test/t/almost_full.test +++ b/mysql-test/t/almost_full.test @@ -11,11 +11,13 @@ CREATE TABLE t1 (a int auto_increment primary key not null, b longtext) ENGINE=M --disable_query_log let $1= 303; +begin; while ($1) { INSERT INTO t1 SET b=repeat('a',200); dec $1; } +commit; --enable_query_log DELETE FROM t1 WHERE a=1 or a=5; diff --git a/mysql-test/t/alter_table.test b/mysql-test/t/alter_table.test index 5233d64f44a..efda5fc1893 100644 --- a/mysql-test/t/alter_table.test +++ b/mysql-test/t/alter_table.test @@ -121,11 +121,15 @@ alter table t1 disable keys; show keys from t1; #let $1=10000; let $1=10; +--disable_query_log +begin; while ($1) { eval insert into t1 values($1,RAND()*1000,RAND()*1000,RAND()); dec $1; } +commit; +--enable_query_log alter table t1 enable keys; show keys from t1; drop table t1; @@ -144,11 +148,15 @@ drop table t1; create table t1 (a int, b int); let $1=100; +--disable_query_log +begin; while ($1) { eval insert into t1 values(1,$1), (2,$1), (3, $1); dec $1; } +commit; +--enable_query_log alter table t1 add unique (a,b), add key (b); show keys from t1; analyze table t1; @@ -966,12 +974,14 @@ DROP TABLE t1; create table t1(f1 int not null, f2 int not null, key (f1), key (f2)); let $count= 50; --disable_query_log +begin; while ($count) { EVAL insert into t1 values (1,1),(1,1),(1,1),(1,1),(1,1); EVAL insert into t1 values (2,2),(2,2),(2,2),(2,2),(2,2); dec $count ; } +commit; --enable_query_log select index_length into @unpaked_keys_size from diff --git a/mysql-test/t/archive.test b/mysql-test/t/archive.test index 7139d95ab49..5864e539b08 100644 --- a/mysql-test/t/archive.test +++ b/mysql-test/t/archive.test @@ -1576,11 +1576,13 @@ CREATE TABLE t1(a VARCHAR(510)) ENGINE = ARCHIVE; let $bug31036=41; --disable_query_log +begin; while($bug31036) { INSERT INTO t1(a) VALUES (REPEAT('a', 510)); dec $bug31036; } +commit; --enable_query_log INSERT INTO t1(a) VALUES (''); diff --git a/mysql-test/t/bench_count_distinct.test b/mysql-test/t/bench_count_distinct.test index 131208f1fa1..87e3d75e996 100644 --- a/mysql-test/t/bench_count_distinct.test +++ b/mysql-test/t/bench_count_distinct.test @@ -7,14 +7,16 @@ drop table if exists t1; --enable_warnings create table t1(n int not null, key(n)) delay_key_write = 1; let $1=100; -disable_query_log; +--disable_query_log +begin; while ($1) { eval insert into t1 values($1); eval insert into t1 values($1); dec $1; } -enable_query_log; +commit; +--enable_query_log select count(distinct n) from t1; explain extended select count(distinct n) from t1; drop table t1; diff --git a/mysql-test/t/change_user.test b/mysql-test/t/change_user.test index 540f9d1b53f..46bf1d2a92c 100644 --- a/mysql-test/t/change_user.test +++ b/mysql-test/t/change_user.test @@ -57,13 +57,13 @@ FLUSH STATUS; --disable_query_log let $i = 100; - +begin; while ($i) { dec $i; - SELECT 1; } +commit; --enable_query_log --enable_result_log diff --git a/mysql-test/t/check.test b/mysql-test/t/check.test index ff23b352b5a..78644523976 100644 --- a/mysql-test/t/check.test +++ b/mysql-test/t/check.test @@ -12,13 +12,15 @@ drop view if exists v1; # Add a lot of keys to slow down check create table t1(n int not null, key(n), key(n), key(n), key(n)); let $1=10000; -disable_query_log; +--disable_query_log +begin; while ($1) { eval insert into t1 values ($1); dec $1; } -enable_query_log; +commit; +--enable_query_log send check table t1 extended; connection con2; insert into t1 values (200000); diff --git a/mysql-test/t/count_distinct2.test b/mysql-test/t/count_distinct2.test index 8dcb2a70065..95086ad04aa 100644 --- a/mysql-test/t/count_distinct2.test +++ b/mysql-test/t/count_distinct2.test @@ -51,13 +51,15 @@ drop table t1; # test the conversion from tree to MyISAM create table t1 (n int default NULL); let $1=5000; -disable_query_log; +--disable_query_log +begin; while ($1) { eval insert into t1 values($1); dec $1; } -enable_query_log; +commit; +--enable_query_log flush status; select count(distinct n) from t1; @@ -67,13 +69,15 @@ drop table t1; # Test use of MyISAM tmp tables create table t1 (s text); let $1=5000; -disable_query_log; +--disable_query_log +begin; while ($1) { eval insert into t1 values('$1'); dec $1; } -enable_query_log; +commit; +--enable_query_log flush status; select count(distinct s) from t1; show status like 'Created_tmp_disk_tables'; diff --git a/mysql-test/t/count_distinct3.test b/mysql-test/t/count_distinct3.test index 9de45baf320..8aecd628423 100644 --- a/mysql-test/t/count_distinct3.test +++ b/mysql-test/t/count_distinct3.test @@ -14,6 +14,7 @@ CREATE TABLE t1 (id INTEGER, grp TINYINT, id_rev INTEGER); --disable_query_log SET @rnd_max= 2147483647; let $1 = 1000; +begin; while ($1) { SET @rnd= RAND(); @@ -23,7 +24,7 @@ while ($1) INSERT INTO t1 (id, grp, id_rev) VALUES (@id, @grp, @id_rev); dec $1; } - +commit; # We increase the size of t1 here. SET @orig_myisam_sort_buffer_size = @@session.myisam_sort_buffer_size; SET session myisam_sort_buffer_size=20000000; diff --git a/mysql-test/t/ctype_euckr.test b/mysql-test/t/ctype_euckr.test index fcb94e7b6d1..dcfb980fc37 100644 --- a/mysql-test/t/ctype_euckr.test +++ b/mysql-test/t/ctype_euckr.test @@ -77,11 +77,13 @@ DROP TABLE t1; CREATE TABLE t1 (a binary(1), key(a)); --disable_query_log let $1=255; +begin; while($1) { eval INSERT INTO t1 VALUES (unhex(hex($1))); dec $1; } +commit; --enable_query_log CREATE TABLE t2 (s VARCHAR(4), a VARCHAR(1) CHARACTER SET euckr); diff --git a/mysql-test/t/derived.test b/mysql-test/t/derived.test index d28c19bbd18..a1456246e94 100644 --- a/mysql-test/t/derived.test +++ b/mysql-test/t/derived.test @@ -45,14 +45,16 @@ select * from (select * from t1 where t1.a=(select t2.a from t2 where t2.a=t1.a) explain select * from (select t1.*, t2.a as t2a from t1,t2 where t1.a=t2.a) t1; drop table t1, t2; create table t1(a int not null, t char(8), index(a)); -disable_query_log; +--disable_query_log +begin; let $1 = 10000; while ($1) { eval insert into t1 values ($1,'$1'); dec $1; } -enable_query_log; +commit; +--enable_query_log SELECT * FROM (SELECT * FROM t1) as b ORDER BY a ASC LIMIT 0,20; explain select count(*) from t1 as tt1, (select * from t1) as tt2; drop table t1; diff --git a/mysql-test/t/events_time_zone.test b/mysql-test/t/events_time_zone.test index 03eb78d230e..17260eb0038 100644 --- a/mysql-test/t/events_time_zone.test +++ b/mysql-test/t/events_time_zone.test @@ -118,6 +118,7 @@ INSERT INTO mysql.time_zone_transition_type let $transition_unix_time= `SELECT @unix_time`; let $count= 30; --disable_query_log +begin; while ($count) { eval INSERT INTO mysql.time_zone_transition @@ -126,6 +127,7 @@ while ($count) let $transition_unix_time= `SELECT $transition_unix_time + @step3`; dec $count; } +commit; --enable_query_log let $tz_name = `SELECT CONCAT('b16420_a',UNIX_TIMESTAMP())`; --replace_result $tz_name diff --git a/mysql-test/t/fulltext2.test b/mysql-test/t/fulltext2.test index 88967a5dd04..9635e14d427 100644 --- a/mysql-test/t/fulltext2.test +++ b/mysql-test/t/fulltext2.test @@ -18,6 +18,7 @@ CREATE TABLE t1 ( # two-level entry, second-level tree with depth 2 --disable_query_log +begin; let $1=260; while ($1) { @@ -40,6 +41,7 @@ while ($1) eval insert t1 (a) values ('aaayyy'); dec $1; } +commit; --enable_query_log # converting to two-level @@ -113,6 +115,7 @@ CREATE TABLE t1 ( # two-level entry, second-level tree with depth 2 --disable_query_log let $1=260; +begin; while ($1) { eval insert t1 (a) values ('aaaxxx'); @@ -130,6 +133,7 @@ while ($1) eval insert t1 (a) values ('aaayyy'); dec $1; } +commit; --enable_query_log select count(*) from t1 where match a against ('aaaxxx'); diff --git a/mysql-test/t/func_misc.test b/mysql-test/t/func_misc.test index 6590b43f2dc..98a5ad8d80c 100644 --- a/mysql-test/t/func_misc.test +++ b/mysql-test/t/func_misc.test @@ -213,11 +213,15 @@ start_ts DATETIME, end_ts DATETIME, start_cached INTEGER, end_cached INTEGER); CREATE TABLE t1 (f1 BIGINT); let $num = `SELECT @row_count`; +--disable_query_log +begin; while ($num) { INSERT INTO t1 VALUES (1); dec $num; } +commit; +--enable_query_log let $loops = 4; let $num = $loops; diff --git a/mysql-test/t/gis-rtree.test b/mysql-test/t/gis-rtree.test index 19bbcf19cca..944a00f008f 100644 --- a/mysql-test/t/gis-rtree.test +++ b/mysql-test/t/gis-rtree.test @@ -17,12 +17,16 @@ SHOW CREATE TABLE t1; let $1=150; let $2=150; +--disable_query_log +begin; while ($1) { eval INSERT INTO t1 (g) VALUES (GeomFromText('LineString($1 $1, $2 $2)')); dec $1; inc $2; } +commit; +--enable_query_log SELECT count(*) FROM t1; EXPLAIN SELECT fid, AsText(g) FROM t1 WHERE Within(g, GeomFromText('Polygon((140 140,160 140,160 160,140 160,140 140))')); @@ -35,6 +39,8 @@ CREATE TABLE t2 ( g GEOMETRY NOT NULL ) ENGINE=MyISAM; +--disable_query_log +begin; let $1=10; while ($1) { @@ -46,6 +52,8 @@ while ($1) } dec $1; } +commit; +--enable_query_log ALTER TABLE t2 ADD SPATIAL KEY(g); SHOW CREATE TABLE t2; @@ -55,6 +63,8 @@ EXPLAIN SELECT fid, AsText(g) FROM t2 WHERE Within(g, SELECT fid, AsText(g) FROM t2 WHERE Within(g, GeomFromText('Polygon((40 40,60 40,60 60,40 60,40 40))')); +--disable_query_log +begin; let $1=10; while ($1) { @@ -67,6 +77,8 @@ while ($1) } dec $1; } +commit; +--enable_query_log DROP TABLE t2; diff --git a/mysql-test/t/heap.test b/mysql-test/t/heap.test index 3f91b9966e7..e5700eaeeb8 100644 --- a/mysql-test/t/heap.test +++ b/mysql-test/t/heap.test @@ -234,7 +234,8 @@ drop table t1,t2,t3; # create table t1 (v varchar(10), c char(10), t varchar(50), key(v), key(c), key(t(10))); show create table t1; -disable_query_log; +--disable_query_log +begin; let $1=10; while ($1) { @@ -248,7 +249,9 @@ while ($1) } dec $1; } -enable_query_log; +commit; +--enable_query_log + select count(*) from t1; insert into t1 values(concat('a',char(1)),concat('a',char(1)),concat('a',char(1))); select count(*) from t1 where v='a'; @@ -318,7 +321,8 @@ drop table t1; create table t1 (v varchar(10), c char(10), t varchar(50), key using btree (v), key using btree (c), key using btree (t(10))); show create table t1; -disable_query_log; +--disable_query_log +begin; let $1=10; while ($1) { @@ -332,7 +336,8 @@ while ($1) } dec $1; } -enable_query_log; +commit; +--enable_query_log select count(*) from t1; insert into t1 values(concat('a',char(1)),concat('a',char(1)),concat('a',char(1))); select count(*) from t1 where v='a'; diff --git a/mysql-test/t/innodb_xtradb_bug317074.test b/mysql-test/t/innodb_xtradb_bug317074.test index 33d1dfa8b27..d3f7210d330 100644 --- a/mysql-test/t/innodb_xtradb_bug317074.test +++ b/mysql-test/t/innodb_xtradb_bug317074.test @@ -1,4 +1,3 @@ ---source include/big_test.inc --source include/have_innodb.inc SET @old_innodb_file_format=@@innodb_file_format; @@ -7,16 +6,16 @@ SET @old_innodb_file_format_check=@@innodb_file_format_check; SET GLOBAL innodb_file_format='Barracuda'; SET GLOBAL innodb_file_per_table=ON; --- disable_query_log --- disable_result_log - +--disable_warnings DROP TABLE IF EXISTS `test1`; +--enable_warnings CREATE TABLE IF NOT EXISTS `test1` ( `a` int primary key auto_increment, `b` int default 0, `c` char(100) default 'testtest' ) ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8; +set autocommit=0; delimiter |; CREATE PROCEDURE insert_many(p1 int) BEGIN @@ -26,14 +25,18 @@ REPEAT insert into test1 set b=1; SET @x = @x + 1; SET @y = @y + 1; - IF @y >= 100 THEN + IF @y >= 1000 THEN commit; SET @y = 0; END IF; UNTIL @x >= p1 END REPEAT; END| delimiter ;| +--disable_query_log +--disable_result_log call insert_many(100000); +--enable_query_log +--enable_result_log DROP PROCEDURE insert_many; # The bug is hangup at the following statement diff --git a/mysql-test/t/insert.test b/mysql-test/t/insert.test index 155ae6937ef..5ec0aefe021 100644 --- a/mysql-test/t/insert.test +++ b/mysql-test/t/insert.test @@ -151,7 +151,8 @@ drop table t1; create table t1(id1 int not null auto_increment primary key, t char(12)); create table t2(id2 int not null, t char(12)); create table t3(id3 int not null, t char(12), index(id3)); -disable_query_log; +--disable_query_log +begin; let $1 = 100; while ($1) { @@ -170,7 +171,9 @@ while ($1) } dec $1; } -enable_query_log; +commit; +--enable_query_log + select count(*) from t2; insert into t2 select t1.* from t1, t2 t, t3 where t1.id1 = t.id2 and t.id2 = t3.id3; select count(*) from t2; diff --git a/mysql-test/t/kill.test b/mysql-test/t/kill.test index 8ef668f542b..44d04abf486 100644 --- a/mysql-test/t/kill.test +++ b/mysql-test/t/kill.test @@ -67,12 +67,14 @@ connection conn1; -- disable_result_log -- disable_query_log +begin; let $1 = 4096; while ($1) { eval insert into t1 values ($1); dec $1; } +commit; -- enable_query_log -- enable_result_log @@ -265,6 +267,8 @@ connection con1; let $ID= `select connection_id()`; let $tab_count= 40; +--disable_query_log +begin; let $i= $tab_count; while ($i) { @@ -272,6 +276,8 @@ while ($i) eval INSERT INTO t$i VALUES (1),(2),(3),(4),(5),(6),(7); dec $i ; } +commit; +--enable_query_log set session optimizer_search_depth=0; let $i=$tab_count; diff --git a/mysql-test/t/merge.test b/mysql-test/t/merge.test index 43267870cb7..72cb77a42b0 100644 --- a/mysql-test/t/merge.test +++ b/mysql-test/t/merge.test @@ -1274,6 +1274,8 @@ DROP TABLE t1, t2, t3; CREATE TABLE t1 (id INTEGER, grp TINYINT, id_rev INTEGER); SET @rnd_max= 2147483647; let $1 = 10; +--disable_query_log +begin; while ($1) { SET @rnd= RAND(); @@ -1283,6 +1285,8 @@ while ($1) INSERT INTO t1 (id, grp, id_rev) VALUES (@id, @grp, @id_rev); dec $1; } +commit; +--enable_query_log set @@read_buffer_size=2*1024*1024; CREATE TABLE t2 SELECT * FROM t1; INSERT INTO t1 (id, grp, id_rev) SELECT id, grp, id_rev FROM t2; diff --git a/mysql-test/t/multi_update.test b/mysql-test/t/multi_update.test index fc37fd6a27d..ebf6a6219fc 100644 --- a/mysql-test/t/multi_update.test +++ b/mysql-test/t/multi_update.test @@ -20,7 +20,8 @@ delete from mysql.user where user=_binary'mysqltest_1'; create table t1(id1 int not null auto_increment primary key, t char(12)); create table t2(id2 int not null, t char(12)); create table t3(id3 int not null, t char(12), index(id3)); -disable_query_log; +--disable_query_log +begin; let $1 = 100; while ($1) { @@ -39,7 +40,8 @@ while ($1) } dec $1; } -enable_query_log; +commit; +--enable_query_log select count(*) from t1 where id1 > 95; select count(*) from t2 where id2 > 95; @@ -75,7 +77,8 @@ drop table t1,t2,t3; create table t1(id1 int not null primary key, t varchar(100)) pack_keys = 1; create table t2(id2 int not null, t varchar(100), index(id2)) pack_keys = 1; -disable_query_log; +--disable_query_log +begin; let $1 = 1000; while ($1) { @@ -88,7 +91,8 @@ while ($1) } dec $1; } -enable_query_log; +commit; +--enable_query_log delete t1 from t1,t2 where t1.id1 = t2.id2 and t1.id1 > 500; drop table t1,t2; diff --git a/mysql-test/t/multi_update2.test b/mysql-test/t/multi_update2.test index a04518f4964..9c5078efb6f 100644 --- a/mysql-test/t/multi_update2.test +++ b/mysql-test/t/multi_update2.test @@ -48,13 +48,14 @@ CREATE TABLE t1 ( a INT NOT NULL, b INT NOT NULL) ; INSERT INTO t1 VALUES (1,1),(2,2),(3,3),(4,4); let $1=19; set @d=4; +begin; while ($1) { eval INSERT INTO t1 SELECT a+@d,b+@d FROM t1; eval SET @d=@d*2; dec $1; } - +commit; --enable_query_log ALTER TABLE t1 ADD INDEX i1(a); DELETE FROM t1 WHERE a > 2000000; diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test index 3e9bc69f725..69a0330fd9d 100644 --- a/mysql-test/t/myisam.test +++ b/mysql-test/t/myisam.test @@ -33,7 +33,8 @@ drop table t1; create table t1 (a tinyint not null auto_increment, b blob not null, primary key (a)); let $1=100; -disable_query_log; +--disable_query_log +begin; --disable_warnings SET SQL_WARNINGS=0; while ($1) @@ -41,9 +42,10 @@ while ($1) eval insert into t1 (b) values(repeat(char(65+$1),65550-$1)); dec $1; } +commit; SET SQL_WARNINGS=1; --enable_warnings -enable_query_log; +--enable_query_log check table t1; repair table t1; delete from t1 where (a & 1); @@ -380,14 +382,16 @@ check table t1; # check updating with keys # -disable_query_log; +--disable_query_log +begin; let $1 = 100; while ($1) { eval insert into t1 (b) values (repeat(char(($1 & 32)+65), $1)); dec $1; } -enable_query_log; +commit; +--enable_query_log update t1 set b=repeat(left(b,1),255) where a between 1 and 5; update t1 set b=repeat(left(b,1),10) where a between 32 and 43; update t1 set b=repeat(left(b,1),2) where a between 64 and 66; @@ -551,11 +555,13 @@ create table t2 (a int); let $i=1000; set @@rand_seed1=31415926,@@rand_seed2=2718281828; --disable_query_log +begin; while ($i) { dec $i; insert t2 values (rand()*100000); } +commit; --enable_query_log insert t1 select * from t2; show keys from t1; @@ -1360,11 +1366,13 @@ CREATE TABLE t1 ( --disable_query_log let $count= 100; --echo # Insert $count rows. Query log disabled. +begin; while ($count) { INSERT INTO t1 VALUES ('a', 'b'); dec $count; } +commit; --enable_query_log # # Change most of the rows into long character values with > 127 characters. @@ -1444,11 +1452,13 @@ CREATE TABLE t1 ( --disable_query_log let $count= 100; --echo # Insert $count rows. Query log disabled. +begin; while ($count) { INSERT INTO t1 VALUES ('a', 'b'); dec $count; } +commit; --enable_query_log # # Change most of the rows into long character values with > 42 characters. diff --git a/mysql-test/t/myisam_debug.test b/mysql-test/t/myisam_debug.test index 913668c5f22..43b5143441e 100644 --- a/mysql-test/t/myisam_debug.test +++ b/mysql-test/t/myisam_debug.test @@ -24,11 +24,15 @@ CREATE TABLE `t2` ( INSERT INTO t2 (id) VALUES (123); let $i = 10; +--disable_query_log +begin; while ($i) { INSERT INTO t2 (id) SELECT id FROM t2; dec $i; } +commit; +--enable_query_log --echo # Switch to insert Connection CONNECTION insertConn; diff --git a/mysql-test/t/myisampack.test b/mysql-test/t/myisampack.test index 9d27ed53254..fcd342168c4 100644 --- a/mysql-test/t/myisampack.test +++ b/mysql-test/t/myisampack.test @@ -69,11 +69,13 @@ CREATE TABLE t1(f1 VARCHAR(200), f2 TEXT); INSERT INTO t1 VALUES ('foo', 'foo1'), ('bar', 'bar1'); let $i=9; --disable_query_log +begin; while ($i) { INSERT INTO t1 SELECT * FROM t1; dec $i; } +commit; --enable_query_log FLUSH TABLE t1; --echo # Compress the table using MYISAMPACK tool diff --git a/mysql-test/t/order_by.test b/mysql-test/t/order_by.test index cca1e3209cc..e8887c07612 100644 --- a/mysql-test/t/order_by.test +++ b/mysql-test/t/order_by.test @@ -374,14 +374,16 @@ DROP TABLE t1; # create table t1(id int not null auto_increment primary key, t char(12)); -disable_query_log; +--disable_query_log +begin; let $1 = 1000; while ($1) { eval insert into t1(t) values ('$1'); dec $1; } -enable_query_log; +commit; +--enable_query_log explain select id,t from t1 order by id; explain select id,t from t1 force index (primary) order by id; drop table t1; diff --git a/mysql-test/t/order_fill_sortbuf.test b/mysql-test/t/order_fill_sortbuf.test index f13cf8cf350..7a8779b6e55 100644 --- a/mysql-test/t/order_fill_sortbuf.test +++ b/mysql-test/t/order_fill_sortbuf.test @@ -12,13 +12,15 @@ CREATE TABLE `t1` ( `id2` int(11) NOT NULL default '0', `id3` int(11) NOT NULL default '0'); let $1=4000; -disable_query_log; +--disable_query_log +begin; while ($1) { eval insert into t1 (id,id2,id3) values ($1,$1,$1); dec $1; } -enable_query_log; +commit; +--enable_query_log create table t2 select id2 from t1 order by id3; select count(*) from t2; drop table t1,t2; diff --git a/mysql-test/t/partition.test b/mysql-test/t/partition.test index 0b497d86623..599697a0f44 100644 --- a/mysql-test/t/partition.test +++ b/mysql-test/t/partition.test @@ -1680,6 +1680,7 @@ create table t1 insert into t1 values (null,null); --disable_query_log +begin; let $cnt= 1000; while ($cnt) { @@ -1687,6 +1688,7 @@ while ($cnt) update t1 set s2 = 2; dec $cnt; } +commit; --enable_query_log drop table t1; @@ -1804,11 +1806,13 @@ CREATE TABLE t1(id MEDIUMINT NOT NULL AUTO_INCREMENT, PARTITION pa11 values less than MAXVALUE); --disable_query_log let $n= 15; +begin; while ($n) { insert into t1 (user) values ('mysql'); dec $n; } +commit; --enable_query_log show create table t1; drop table t1; diff --git a/mysql-test/t/partition_archive.test b/mysql-test/t/partition_archive.test index fad57107b7d..9e2377f1bbf 100644 --- a/mysql-test/t/partition_archive.test +++ b/mysql-test/t/partition_archive.test @@ -94,11 +94,13 @@ CREATE TABLE t1(id MEDIUMINT NOT NULL AUTO_INCREMENT, --disable_query_log let $n= 100; +begin; while ($n) { insert into t1 (f1) values (repeat('a',25)); dec $n; } +commit; --enable_query_log show create table t1; diff --git a/mysql-test/t/select_found.test b/mysql-test/t/select_found.test index e4bc54a5538..e043ec4d143 100644 --- a/mysql-test/t/select_found.test +++ b/mysql-test/t/select_found.test @@ -54,7 +54,8 @@ CREATE TABLE t2 ( UNIQUE KEY e_n (email,name) ); -disable_query_log; +--disable_query_log +begin; let $1=200; let $2=0; while ($1) @@ -63,7 +64,8 @@ while ($1) eval INSERT INTO t2 VALUES ($2,'name$2','email$2'); dec $1; } -enable_query_log; +commit; +--enable_query_log EXPLAIN SELECT SQL_CALC_FOUND_ROWS DISTINCT email FROM t2 LEFT JOIN t1 ON kid = t2.id WHERE t1.id IS NULL LIMIT 10; SELECT SQL_CALC_FOUND_ROWS DISTINCT email FROM t2 LEFT JOIN t1 ON kid = t2.id WHERE t1.id IS NULL LIMIT 10; diff --git a/mysql-test/t/sp-big.test b/mysql-test/t/sp-big.test index 90a3a79dd53..6541e546e43 100644 --- a/mysql-test/t/sp-big.test +++ b/mysql-test/t/sp-big.test @@ -43,11 +43,13 @@ create table t2 like t1; let $1=8; --disable_query_log --disable_result_log +begin; while ($1) { eval insert into t1 select * from t1; dec $1; } +commit; --enable_result_log --enable_query_log select count(*) from t1; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index a9edc831fdc..ef5a5e2c0a7 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -811,7 +811,8 @@ create table t1 (a int, b int, index a (a,b)); create table t2 (a int, index a (a)); create table t3 (a int, b int, index a (a)); insert into t1 values (1,10), (2,20), (3,30), (4,40); -disable_query_log; +--disable_query_log +begin; # making table large enough let $1 = 10000; while ($1) @@ -819,7 +820,8 @@ while ($1) eval insert into t1 values (rand()*100000+200,rand()*100000); dec $1; } -enable_query_log; +commit; +--enable_query_log insert into t2 values (2), (3), (4), (5); insert into t3 values (10,3), (20,4), (30,5); select * from t2 where t2.a in (select a from t1); @@ -2607,7 +2609,8 @@ CREATE TABLE t1 (a int, b int auto_increment, PRIMARY KEY (b)); CREATE TABLE t2 (x int auto_increment, y int, z int, PRIMARY KEY (x), FOREIGN KEY (y) REFERENCES t1 (b)); -disable_query_log; +--disable_query_log +begin; let $1=3000; while ($1) { @@ -2621,7 +2624,8 @@ while ($1) } dec $1; } -enable_query_log; +commit; +--enable_query_log SET SESSION sort_buffer_size = 32 * 1024; SELECT SQL_NO_CACHE COUNT(*) @@ -3222,11 +3226,13 @@ insert into t1 values(1,1),(2,2), (3, 3); let $i=10000; --disable_query_log --disable_warnings +begin; while ($i) { eval insert into t2 values (-1 , $i/5000 + 1, '$i'); dec $i; } +commit; --enable_warnings --enable_query_log set session sort_buffer_size= 33*1024; diff --git a/mysql-test/t/warnings.test b/mysql-test/t/warnings.test index 12421170eba..b8235825cf2 100644 --- a/mysql-test/t/warnings.test +++ b/mysql-test/t/warnings.test @@ -82,13 +82,15 @@ drop table t1, t2; create table t1(a char(10)); let $1=50; -disable_query_log; +--disable_query_log +begin; while ($1) { eval insert into t1 values('mysql ab'); dec $1; } -enable_query_log; +commit; +--enable_query_log alter table t1 add b char; set max_error_count=10; update t1 set b=a; From a5637077fbb06d038a4ce5ea2c4209edbdc7ba9e Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Wed, 28 Oct 2009 10:08:54 +0200 Subject: [PATCH 55/69] Added missing 'source' command. --- mysql-test/suite/parts/t/part_supported_sql_func_innodb.test | 2 +- mysql-test/suite/parts/t/partition_alter1_1_2_innodb.test | 2 +- mysql-test/suite/parts/t/partition_alter4_myisam.test | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mysql-test/suite/parts/t/part_supported_sql_func_innodb.test b/mysql-test/suite/parts/t/part_supported_sql_func_innodb.test index eebad5b0d4f..fef41990e28 100644 --- a/mysql-test/suite/parts/t/part_supported_sql_func_innodb.test +++ b/mysql-test/suite/parts/t/part_supported_sql_func_innodb.test @@ -26,7 +26,7 @@ let $debug= 0; let $do_long_tests= 1; # ---include/big_test.inc +--source include/big_test.inc # The server must support partitioning. --source include/have_partition.inc diff --git a/mysql-test/suite/parts/t/partition_alter1_1_2_innodb.test b/mysql-test/suite/parts/t/partition_alter1_1_2_innodb.test index be39f53e93b..240bfb4de1d 100644 --- a/mysql-test/suite/parts/t/partition_alter1_1_2_innodb.test +++ b/mysql-test/suite/parts/t/partition_alter1_1_2_innodb.test @@ -44,7 +44,7 @@ let $more_trigger_tests= 0; let $more_pk_ui_tests= 0; # Slow running test ---include/big_test.inc +--source include/big_test.inc # This test relies on connecting externally from mysqltest, doesn't # work with embedded. --source include/not_embedded.inc diff --git a/mysql-test/suite/parts/t/partition_alter4_myisam.test b/mysql-test/suite/parts/t/partition_alter4_myisam.test index a4fd6d5d70c..652bf8013d5 100644 --- a/mysql-test/suite/parts/t/partition_alter4_myisam.test +++ b/mysql-test/suite/parts/t/partition_alter4_myisam.test @@ -41,7 +41,7 @@ let $more_trigger_tests= 0; let $more_pk_ui_tests= 0; # Slow running test ---include/big_test.inc +--source include/big_test.inc # This test relies on connecting externally from mysqltest, doesn't # work with embedded. --source include/not_embedded.inc From 664fa25e0e40457f2374f4372fca9a631d039c8c Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Thu, 29 Oct 2009 02:04:56 +0200 Subject: [PATCH 56/69] Compile by default MySQL clients with libmysqldclient.a (not .so) This makes them suitable for tar archices right away and also are easier to copy Don't disable federated storage engine by default. Don't allow one to disable the Maria storage engine if it's used for temp tables BUILD/SETUP.sh: Compile by default MySQL clients with libmysqldclient.a (not .so) This makes them suitable for tar archices right away and also are easier to copy scripts/make_binary_distribution.sh: Abort it clients are compiled with the shared libmysqlclient.so library sql/mysqld.cc: Don't call kill_mysql() if signal handler is not setup (causes a core dump). This is only relevant when starting with --gdb. sql/sql_plugin.cc: Don't disable federated storage engine by default. Don't allow one to disable the Maria storage engine if it's used for temp tables --- BUILD/SETUP.sh | 17 +++++++++-------- scripts/make_binary_distribution.sh | 12 ++++++++++++ sql/mysqld.cc | 4 +++- sql/sql_plugin.cc | 14 +++++++++----- 4 files changed, 33 insertions(+), 14 deletions(-) diff --git a/BUILD/SETUP.sh b/BUILD/SETUP.sh index 418ee799a2c..30148cde360 100755 --- a/BUILD/SETUP.sh +++ b/BUILD/SETUP.sh @@ -146,6 +146,13 @@ then debug_cflags="$debug_cflags $debug_extra_cflags" fi +static_link="--with-mysqld-ldflags=-all-static " +static_link="$static_link --with-client-ldflags=-all-static" +# we need local-infile in all binaries for rpl000001 +# if you need to disable local-infile in the client, write a build script +# and unset local_infile_configs +local_infile_configs="--enable-local-infile" + # # Configuration options. # @@ -154,6 +161,8 @@ base_configs="$base_configs --with-extra-charsets=complex " base_configs="$base_configs --enable-thread-safe-client " base_configs="$base_configs --with-big-tables" base_configs="$base_configs --with-plugin-maria --with-maria-tmp-tables --without-plugin-innodb_plugin" +# Compile our client programs with static libraries to allow them to be moved +base_configs="$base_configs --with-mysqld-ldflags=-static --with-client-ldflags=-static" if test -d "$path/../cmd-line-utils/readline" then @@ -163,14 +172,6 @@ then base_configs="$base_configs --with-libedit" fi -static_link="--with-mysqld-ldflags=-all-static " -static_link="$static_link --with-client-ldflags=-all-static" -# we need local-infile in all binaries for rpl000001 -# if you need to disable local-infile in the client, write a build script -# and unset local_infile_configs -local_infile_configs="--enable-local-infile" - - max_no_embedded_configs="$SSL_LIBRARY --with-plugins=max" max_no_qc_configs="$SSL_LIBRARY --with-plugins=max --without-query-cache" max_no_ndb_configs="$SSL_LIBRARY --with-plugins=max-no-ndb --with-embedded-server --with-libevent" diff --git a/scripts/make_binary_distribution.sh b/scripts/make_binary_distribution.sh index 9595a56ef62..3e156dd668d 100644 --- a/scripts/make_binary_distribution.sh +++ b/scripts/make_binary_distribution.sh @@ -231,6 +231,18 @@ if [ x"$BASE_SYSTEM" != x"netware" ] ; then # ---------------------------------------------------------------------- set -e + # + # Check that the client is compiled with libmysqlclient.a + # + if test -f ./client/.libs/mysql + then + echo "" + echo "The MySQL clients are compiled dynamicly, which is not allowed for" + echo "a MySQL binary tar file. Please configure with" + echo "--with-client-ldflags=-all-static and try again" + exit 1; + fi + # ---------------------------------------------------------------------- # Really ugly, one script, "mysql_install_db", needs prefix set to ".", # i.e. makes access relative the current directory. This matches diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 6a7209cd611..497a39b95f8 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1889,7 +1889,9 @@ void close_connection(THD *thd, uint errcode, bool lock) extern "C" sig_handler end_mysqld_signal(int sig __attribute__((unused))) { DBUG_ENTER("end_mysqld_signal"); - kill_mysql(); // Take down mysqld nicely + /* Don't call kill_mysql() if signal thread is not running */ + if (signal_thread_in_use) + kill_mysql(); // Take down mysqld nicely DBUG_VOID_RETURN; /* purecov: deadcode */ } diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index ab7d0a35bc1..a5e65d11304 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -3226,7 +3226,6 @@ static int test_plugin_options(MEM_ROOT *tmp_root, struct st_plugin_int *tmp, my_bool can_disable; bool disable_plugin; enum_plugin_load_policy plugin_load_policy= PLUGIN_ON; - MEM_ROOT *mem_root= alloc_root_inited(&tmp->mem_root) ? &tmp->mem_root : &plugin_mem_root; st_mysql_sys_var **opt; @@ -3240,13 +3239,13 @@ static int test_plugin_options(MEM_ROOT *tmp_root, struct st_plugin_int *tmp, DBUG_ENTER("test_plugin_options"); DBUG_ASSERT(tmp->plugin && tmp->name.str); +#ifdef WITH_NDBCLUSTER_STORAGE_ENGINE /* - The 'federated' and 'ndbcluster' storage engines are always disabled by - default. + The 'ndbcluster' storage engines is always disabled by default. */ - if (!(my_strcasecmp(&my_charset_latin1, tmp->name.str, "federated") && - my_strcasecmp(&my_charset_latin1, tmp->name.str, "ndbcluster"))) + if (!my_strcasecmp(&my_charset_latin1, tmp->name.str, "ndbcluster")) plugin_load_policy= PLUGIN_OFF; +#endif for (opt= tmp->plugin->system_vars; opt && *opt; opt++) count+= 2; /* --{plugin}-{optname} and --plugin-{plugin}-{optname} */ @@ -3295,6 +3294,11 @@ static int test_plugin_options(MEM_ROOT *tmp_root, struct st_plugin_int *tmp, can_disable= my_strcasecmp(&my_charset_latin1, tmp->name.str, "MyISAM") && my_strcasecmp(&my_charset_latin1, tmp->name.str, "MEMORY"); +#ifdef USE_MARIA_FOR_TMP_TABLES + if (!can_disable) + can_disable= (my_strcasecmp(&my_charset_latin1, tmp->name.str, "Maria") + != 0); +#endif tmp->is_mandatory= (plugin_load_policy == PLUGIN_FORCE) || !can_disable; From 1d135003738cee8369b3b4b5427ab46b9f249117 Mon Sep 17 00:00:00 2001 From: Sergey Petrunya Date: Thu, 29 Oct 2009 20:50:33 +0300 Subject: [PATCH 57/69] MWL#17: Table elimination - add debug tests (were accidentally not pushed with the bulk of WL) --- mysql-test/r/table_elim_debug.result | 22 ++++++++++++++++++++++ mysql-test/t/table_elim_debug.test | 27 +++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 mysql-test/r/table_elim_debug.result create mode 100644 mysql-test/t/table_elim_debug.test diff --git a/mysql-test/r/table_elim_debug.result b/mysql-test/r/table_elim_debug.result new file mode 100644 index 00000000000..b059baffa89 --- /dev/null +++ b/mysql-test/r/table_elim_debug.result @@ -0,0 +1,22 @@ +drop table if exists t1, t2; +create table t1 (a int); +insert into t1 values (0),(1),(2),(3); +create table t2 (a int primary key, b int) +as select a, a as b from t1 where a in (1,2); +explain select t1.a from t1 left join t2 on t2.a=t1.a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 4 +set optimizer_switch='table_elimination=off'; +explain select t1.a from t1 left join t2 on t2.a=t1.a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 4 +1 SIMPLE t2 eq_ref PRIMARY PRIMARY 4 test.t1.a 1 Using index +set optimizer_switch='table_elimination=on'; +explain select t1.a from t1 left join t2 on t2.a=t1.a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 4 +set optimizer_switch='table_elimination=default'; +explain select t1.a from t1 left join t2 on t2.a=t1.a; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 4 +drop table t1, t2; diff --git a/mysql-test/t/table_elim_debug.test b/mysql-test/t/table_elim_debug.test new file mode 100644 index 00000000000..9f793169e4f --- /dev/null +++ b/mysql-test/t/table_elim_debug.test @@ -0,0 +1,27 @@ +# +# Table elimination (MWL#17) tests that need debug build +# +--source include/have_debug.inc + +--disable_warnings +drop table if exists t1, t2; +--enable_warnings + +# Check if optimizer_switch works + +create table t1 (a int); +insert into t1 values (0),(1),(2),(3); + +create table t2 (a int primary key, b int) + as select a, a as b from t1 where a in (1,2); + +explain select t1.a from t1 left join t2 on t2.a=t1.a; + +set optimizer_switch='table_elimination=off'; +explain select t1.a from t1 left join t2 on t2.a=t1.a; +set optimizer_switch='table_elimination=on'; +explain select t1.a from t1 left join t2 on t2.a=t1.a; +set optimizer_switch='table_elimination=default'; +explain select t1.a from t1 left join t2 on t2.a=t1.a; + +drop table t1, t2; From 182aa542bccc15c60ff0f897303f4b54910a3b44 Mon Sep 17 00:00:00 2001 From: Sergey Petrunya Date: Fri, 30 Oct 2009 13:50:48 +0300 Subject: [PATCH 58/69] Dummy change to push the release tag. --- win/make_mariadb_win_dist | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/win/make_mariadb_win_dist b/win/make_mariadb_win_dist index 8893159bd20..9d0b3b26af3 100644 --- a/win/make_mariadb_win_dist +++ b/win/make_mariadb_win_dist @@ -66,7 +66,7 @@ ls -lah $ZIPFILE echo "$ZIPFILE is the Windows noinstall binary zip" if [ $RES ] ; then - echo "Archive contents differ from the standard file list, check the diff output above" + echo "Archive contents differ from the standard file list, check the diff output above" else echo "Archive contents match the standard list, OK" fi From 226f0c7601a7bc3d0274d0b7aa6523743856cf11 Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Fri, 30 Oct 2009 20:50:56 +0200 Subject: [PATCH 59/69] Added federatedx storage engine Fixed compiler warnings client/mysqladmin.cc: Fixed compiler warning extra/yassl/taocrypt/src/twofish.cpp: Fixed compiler warning libmysqld/Makefile.am: Use federatedx instead of federated (Should actually be removed) mysql-test/mysql-test-run.pl: Fixed warning mysql-test/valgrind.supp: Removed warning found on 64 bit Linux machine storage/pbxt/src/cache_xt.cc: Fixed compile warning storage/xtradb/include/buf0buf.ic: Fixed compiler warning --- client/mysqladmin.cc | 2 +- extra/yassl/taocrypt/src/twofish.cpp | 2 + libmysqld/Makefile.am | 2 +- mysql-test/mysql-test-run.pl | 1 - mysql-test/suite/federated/disabled.def | 3 +- mysql-test/suite/federated/federated.result | 32 +- mysql-test/suite/federated/federated.test | 14 +- .../suite/federated/federated_archive.result | 4 +- .../federated/federated_bug_13118.result | 4 +- .../federated/federated_bug_25714.result | 4 +- .../suite/federated/federated_cleanup.inc | 4 +- .../suite/federated/federated_innodb.result | 4 +- .../suite/federated/federated_server.result | 4 +- .../suite/federated/federated_server.test | 9 +- .../federated/federated_transactions.result | 9 - mysql-test/valgrind.supp | 14 + storage/federated/README | 7 + .../federated/{plug.in => plug.in.disabled} | 0 storage/federatedx/AUTHORS | 11 + storage/federatedx/CMakeFiles.txt | 3 + storage/federatedx/ChangeLog | 18 + storage/federatedx/FAQ | 40 + storage/federatedx/Makefile.am | 64 + storage/federatedx/README | 33 + storage/federatedx/README.windows | 23 + storage/federatedx/TODO | 30 + storage/federatedx/federatedx_io.cc | 103 + storage/federatedx/federatedx_io_mysql.cc | 592 +++ storage/federatedx/federatedx_io_null.cc | 277 ++ storage/federatedx/federatedx_probes.h | 45 + storage/federatedx/federatedx_txn.cc | 424 ++ storage/federatedx/ha_federatedx.cc | 3487 +++++++++++++++++ storage/federatedx/ha_federatedx.h | 446 +++ storage/federatedx/plug.in | 5 + storage/pbxt/src/cache_xt.cc | 4 +- storage/xtradb/include/buf0buf.ic | 2 +- 36 files changed, 5669 insertions(+), 57 deletions(-) create mode 100644 storage/federated/README rename storage/federated/{plug.in => plug.in.disabled} (100%) create mode 100644 storage/federatedx/AUTHORS create mode 100644 storage/federatedx/CMakeFiles.txt create mode 100644 storage/federatedx/ChangeLog create mode 100644 storage/federatedx/FAQ create mode 100644 storage/federatedx/Makefile.am create mode 100644 storage/federatedx/README create mode 100644 storage/federatedx/README.windows create mode 100644 storage/federatedx/TODO create mode 100644 storage/federatedx/federatedx_io.cc create mode 100644 storage/federatedx/federatedx_io_mysql.cc create mode 100644 storage/federatedx/federatedx_io_null.cc create mode 100644 storage/federatedx/federatedx_probes.h create mode 100644 storage/federatedx/federatedx_txn.cc create mode 100644 storage/federatedx/ha_federatedx.cc create mode 100644 storage/federatedx/ha_federatedx.h create mode 100644 storage/federatedx/plug.in diff --git a/client/mysqladmin.cc b/client/mysqladmin.cc index a746f204df9..4047520b38a 100644 --- a/client/mysqladmin.cc +++ b/client/mysqladmin.cc @@ -1043,7 +1043,7 @@ static int drop_db(MYSQL *mysql, const char *db) printf("Do you really want to drop the '%s' database [y/N] ",db); fflush(stdout); if (fgets(buf,sizeof(buf)-1,stdin) == 0 || - (*buf != 'y') && (*buf != 'Y')) + ((*buf != 'y') && (*buf != 'Y'))) { puts("\nOK, aborting database drop!"); return -1; diff --git a/extra/yassl/taocrypt/src/twofish.cpp b/extra/yassl/taocrypt/src/twofish.cpp index 84dd35f9191..85feaa23280 100644 --- a/extra/yassl/taocrypt/src/twofish.cpp +++ b/extra/yassl/taocrypt/src/twofish.cpp @@ -55,6 +55,7 @@ void Twofish::Process(byte* out, const byte* in, word32 sz) in += BLOCK_SIZE; } else if (mode_ == CBC) + { if (dir_ == ENCRYPTION) while (blocks--) { r_[0] ^= *(word32*)in; @@ -82,6 +83,7 @@ void Twofish::Process(byte* out, const byte* in, word32 sz) out += BLOCK_SIZE; in += BLOCK_SIZE; } + } } #endif // DO_TWOFISH_ASM diff --git a/libmysqld/Makefile.am b/libmysqld/Makefile.am index d1dacbaec0c..ecf45a23399 100644 --- a/libmysqld/Makefile.am +++ b/libmysqld/Makefile.am @@ -124,7 +124,7 @@ handler.o: handler.cc # found to append fileslists that collected by configure # to the sources list -ha_federated.o:ha_federated.cc +ha_federatedx.o:ha_federatedx.cc $(CXXCOMPILE) $(LM_CFLAGS) -c $< ha_heap.o:ha_heap.cc diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 832778aeade..b3cdbfc1e1a 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -127,7 +127,6 @@ my $path_config_file; # The generated config file, var/my.cnf our $opt_vs_config = $ENV{'MTR_VS_CONFIG'}; my $DEFAULT_SUITES= "binlog,federated,main,maria,rpl,innodb,parts"; -my $opt_suites; our $opt_usage; our $opt_list_options; diff --git a/mysql-test/suite/federated/disabled.def b/mysql-test/suite/federated/disabled.def index 9a9149ec80a..f34cda61137 100644 --- a/mysql-test/suite/federated/disabled.def +++ b/mysql-test/suite/federated/disabled.def @@ -9,4 +9,5 @@ # Do not use any TAB characters for whitespace. # ############################################################################## -federated_transactions : Bug#29523 Transactions do not work +federated_server : needs fixup + diff --git a/mysql-test/suite/federated/federated.result b/mysql-test/suite/federated/federated.result index 57f665995a1..13749be9b86 100644 --- a/mysql-test/suite/federated/federated.result +++ b/mysql-test/suite/federated/federated.result @@ -47,9 +47,10 @@ CREATE TABLE federated.t1 ( ) ENGINE="FEDERATED" DEFAULT CHARSET=latin1 CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t3'; -SELECT * FROM federated.t1; -ERROR HY000: The foreign data source you are trying to reference does not exist. Data source error: error: 1146 'Table 'federated.t3' doesn't exist' -DROP TABLE federated.t1; +ERROR HY000: Can't create federated table. Foreign data src error: database: 'federated' username: 'root' hostname: '127.0.0.1' +DROP TABLE IF EXISTS federated.t1; +Warnings: +Note 1051 Unknown table 't1' CREATE TABLE federated.t1 ( `id` int(20) NOT NULL, `group` int NOT NULL default 0, @@ -59,9 +60,10 @@ CREATE TABLE federated.t1 ( ) ENGINE="FEDERATED" DEFAULT CHARSET=latin1 CONNECTION='mysql://user:pass@127.0.0.1:SLAVE_PORT/federated/t1'; -SELECT * FROM federated.t1; -ERROR HY000: Unable to connect to foreign data source: Access denied for user 'user'@'localhost' (using password: YES) -DROP TABLE federated.t1; +ERROR HY000: Can't create federated table. Foreign data src error: database: 'federated' username: 'user' hostname: '127.0.0.1' +DROP TABLE IF EXISTS federated.t1; +Warnings: +Note 1051 Unknown table 't1' CREATE TABLE federated.t1 ( `id` int(20) NOT NULL, `group` int NOT NULL default 0, @@ -1944,15 +1946,7 @@ Bug#18287 create federated table always times out, error 1159 ' ' Test that self-references work -create table federated.t1 (a int primary key); -create table federated.t2 (a int primary key) -ENGINE=FEDERATED -connection='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1'; -insert into federated.t1 (a) values (1); -select * from federated.t2; -a -1 -drop table federated.t1, federated.t2; +fix LOCK_open before reenabling test for Bug#18287 CREATE TABLE federated.t1 (a INT PRIMARY KEY) DEFAULT CHARSET=utf8; CREATE TABLE federated.t1 (a INT PRIMARY KEY) ENGINE=FEDERATED @@ -1960,13 +1954,11 @@ CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1' DEFAULT CHARSET=utf8; SELECT transactions FROM information_schema.engines WHERE engine="FEDERATED"; transactions -NO +YES INSERT INTO federated.t1 VALUES (1); SET autocommit=0; INSERT INTO federated.t1 VALUES (2); ROLLBACK; -Warnings: -Warning 1196 Some non-transactional changed tables couldn't be rolled back SET autocommit=1; SELECT * FROM federated.t1; a @@ -2157,6 +2149,6 @@ End of 5.1 tests SET @@GLOBAL.CONCURRENT_INSERT= @OLD_MASTER_CONCURRENT_INSERT; SET @@GLOBAL.CONCURRENT_INSERT= @OLD_SLAVE_CONCURRENT_INSERT; DROP TABLE IF EXISTS federated.t1; -DROP DATABASE federated; +DROP DATABASE IF EXISTS federated; DROP TABLE IF EXISTS federated.t1; -DROP DATABASE federated; +DROP DATABASE IF EXISTS federated; diff --git a/mysql-test/suite/federated/federated.test b/mysql-test/suite/federated/federated.test index 870bbcb8f71..d45fc50a1bf 100644 --- a/mysql-test/suite/federated/federated.test +++ b/mysql-test/suite/federated/federated.test @@ -57,6 +57,7 @@ CREATE TABLE federated.t1 ( # test non-existant table --replace_result $SLAVE_MYPORT SLAVE_PORT +--error ER_CANT_CREATE_FEDERATED_TABLE eval CREATE TABLE federated.t1 ( `id` int(20) NOT NULL, `group` int NOT NULL default 0, @@ -66,12 +67,11 @@ eval CREATE TABLE federated.t1 ( ) ENGINE="FEDERATED" DEFAULT CHARSET=latin1 CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/t3'; ---error ER_FOREIGN_DATA_SOURCE_DOESNT_EXIST -SELECT * FROM federated.t1; -DROP TABLE federated.t1; +DROP TABLE IF EXISTS federated.t1; # test bad user/password --replace_result $SLAVE_MYPORT SLAVE_PORT +--error ER_CANT_CREATE_FEDERATED_TABLE eval CREATE TABLE federated.t1 ( `id` int(20) NOT NULL, `group` int NOT NULL default 0, @@ -81,9 +81,7 @@ eval CREATE TABLE federated.t1 ( ) ENGINE="FEDERATED" DEFAULT CHARSET=latin1 CONNECTION='mysql://user:pass@127.0.0.1:$SLAVE_MYPORT/federated/t1'; ---error ER_CONNECT_TO_FOREIGN_DATA_SOURCE -SELECT * FROM federated.t1; -DROP TABLE federated.t1; +DROP TABLE IF EXISTS federated.t1; # # correct connection, same named tables --replace_result $SLAVE_MYPORT SLAVE_PORT @@ -1806,6 +1804,8 @@ drop table federated.t1; --echo --echo Test that self-references work --echo +--echo fix LOCK_open before reenabling test for Bug#18287 +--disable_parsing connection slave; create table federated.t1 (a int primary key); --replace_result $SLAVE_MYPORT SLAVE_PORT @@ -1815,7 +1815,7 @@ eval create table federated.t2 (a int primary key) insert into federated.t1 (a) values (1); select * from federated.t2; drop table federated.t1, federated.t2; - +--enable_parsing # # BUG#29875 Disable support for transactions # diff --git a/mysql-test/suite/federated/federated_archive.result b/mysql-test/suite/federated/federated_archive.result index b7960e2a561..d67568ec11c 100644 --- a/mysql-test/suite/federated/federated_archive.result +++ b/mysql-test/suite/federated/federated_archive.result @@ -34,6 +34,6 @@ id name DROP TABLE federated.t1; DROP TABLE federated.archive_table; DROP TABLE IF EXISTS federated.t1; -DROP DATABASE federated; +DROP DATABASE IF EXISTS federated; DROP TABLE IF EXISTS federated.t1; -DROP DATABASE federated; +DROP DATABASE IF EXISTS federated; diff --git a/mysql-test/suite/federated/federated_bug_13118.result b/mysql-test/suite/federated/federated_bug_13118.result index 57175dc8def..a645bc58bc2 100644 --- a/mysql-test/suite/federated/federated_bug_13118.result +++ b/mysql-test/suite/federated/federated_bug_13118.result @@ -25,6 +25,6 @@ foo bar DROP TABLE federated.t1; DROP TABLE federated.bug_13118_table; DROP TABLE IF EXISTS federated.t1; -DROP DATABASE federated; +DROP DATABASE IF EXISTS federated; DROP TABLE IF EXISTS federated.t1; -DROP DATABASE federated; +DROP DATABASE IF EXISTS federated; diff --git a/mysql-test/suite/federated/federated_bug_25714.result b/mysql-test/suite/federated/federated_bug_25714.result index 55d9a0ceb52..ace76b77348 100644 --- a/mysql-test/suite/federated/federated_bug_25714.result +++ b/mysql-test/suite/federated/federated_bug_25714.result @@ -48,6 +48,6 @@ SET @@GLOBAL.CONCURRENT_INSERT= @OLD_MASTER_CONCURRENT_INSERT; DROP TABLE federated.t1; SET @@GLOBAL.CONCURRENT_INSERT= @OLD_SLAVE_CONCURRENT_INSERT; DROP TABLE IF EXISTS federated.t1; -DROP DATABASE federated; +DROP DATABASE IF EXISTS federated; DROP TABLE IF EXISTS federated.t1; -DROP DATABASE federated; +DROP DATABASE IF EXISTS federated; diff --git a/mysql-test/suite/federated/federated_cleanup.inc b/mysql-test/suite/federated/federated_cleanup.inc index e96a7cd2cee..06fd7f6737a 100644 --- a/mysql-test/suite/federated/federated_cleanup.inc +++ b/mysql-test/suite/federated/federated_cleanup.inc @@ -1,9 +1,9 @@ connection master; --disable_warnings DROP TABLE IF EXISTS federated.t1; -DROP DATABASE federated; +DROP DATABASE IF EXISTS federated; connection slave; DROP TABLE IF EXISTS federated.t1; -DROP DATABASE federated; +DROP DATABASE IF EXISTS federated; --enable_warnings diff --git a/mysql-test/suite/federated/federated_innodb.result b/mysql-test/suite/federated/federated_innodb.result index e6cf81bb1a6..526a886f0ce 100644 --- a/mysql-test/suite/federated/federated_innodb.result +++ b/mysql-test/suite/federated/federated_innodb.result @@ -20,6 +20,6 @@ a b drop table federated.t1; drop table federated.t1; DROP TABLE IF EXISTS federated.t1; -DROP DATABASE federated; +DROP DATABASE IF EXISTS federated; DROP TABLE IF EXISTS federated.t1; -DROP DATABASE federated; +DROP DATABASE IF EXISTS federated; diff --git a/mysql-test/suite/federated/federated_server.result b/mysql-test/suite/federated/federated_server.result index 2c20d1c1d57..227dec46ae5 100644 --- a/mysql-test/suite/federated/federated_server.result +++ b/mysql-test/suite/federated/federated_server.result @@ -178,8 +178,8 @@ INSERT INTO db_bogus.t1 VALUES ('2','this is bogus'); create server 's1' foreign data wrapper 'mysql' options (HOST '127.0.0.1', DATABASE 'db_legitimate', -USER 'root', -PASSWORD '', +USER 'test_fed', +PASSWORD 'foo', PORT SLAVE_PORT, SOCKET '', OWNER 'root'); diff --git a/mysql-test/suite/federated/federated_server.test b/mysql-test/suite/federated/federated_server.test index 45b2cbdfd71..5311bf770e1 100644 --- a/mysql-test/suite/federated/federated_server.test +++ b/mysql-test/suite/federated/federated_server.test @@ -3,6 +3,7 @@ # Slow test, don't run during staging part -- source include/not_staging.inc +-- source include/big_test.inc -- source federated.inc connection slave; @@ -182,13 +183,17 @@ CREATE TABLE db_bogus.t1 ( ; INSERT INTO db_bogus.t1 VALUES ('2','this is bogus'); +connection slave; +create user test_fed@localhost identified by 'foo'; +grant all on db_legitimate.* to test_fed@localhost; + connection master; --replace_result $SLAVE_MYPORT SLAVE_PORT eval create server 's1' foreign data wrapper 'mysql' options (HOST '127.0.0.1', DATABASE 'db_legitimate', - USER 'root', - PASSWORD '', + USER 'test_fed', + PASSWORD 'foo', PORT $SLAVE_MYPORT, SOCKET '', OWNER 'root'); diff --git a/mysql-test/suite/federated/federated_transactions.result b/mysql-test/suite/federated/federated_transactions.result index 40644e3535e..2b88f4d0f36 100644 --- a/mysql-test/suite/federated/federated_transactions.result +++ b/mysql-test/suite/federated/federated_transactions.result @@ -1,13 +1,4 @@ -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; -DROP DATABASE IF EXISTS federated; CREATE DATABASE federated; -DROP DATABASE IF EXISTS federated; CREATE DATABASE federated; DROP TABLE IF EXISTS federated.t1; Warnings: diff --git a/mysql-test/valgrind.supp b/mysql-test/valgrind.supp index 57eee78bdaa..5b06273ad6b 100644 --- a/mysql-test/valgrind.supp +++ b/mysql-test/valgrind.supp @@ -880,3 +880,17 @@ fun:nptl_pthread_exit_hack_handler fun:start_thread } + +# +# Problem with glibc and gethostbyaddr_r +# + +{ + libc_res_nsend: Conditional jump or move depends on uninitialised value + Memcheck:Cond + fun: __libc_res_nsend + fun: __libc_res_nquery + obj: /lib64/libnss_dns-*so) + obj: /lib64/libnss_dns-*so) + fun: gethostbyaddr_r +} diff --git a/storage/federated/README b/storage/federated/README new file mode 100644 index 00000000000..1b521cb7859 --- /dev/null +++ b/storage/federated/README @@ -0,0 +1,7 @@ +The files in this directory are not used by MariaDB + +MariaDB uses the new federated storage engine that can be found in the +federatedx directory. + +This directory is only kept around to make it easy to merge code from the +MySQL source repositories that uses the old and disabled federated code. diff --git a/storage/federated/plug.in b/storage/federated/plug.in.disabled similarity index 100% rename from storage/federated/plug.in rename to storage/federated/plug.in.disabled diff --git a/storage/federatedx/AUTHORS b/storage/federatedx/AUTHORS new file mode 100644 index 00000000000..6314d2e4a3d --- /dev/null +++ b/storage/federatedx/AUTHORS @@ -0,0 +1,11 @@ +FederatedX + +Patrick Galbraith - Federated + +Pluggable Storage Engine Skeleton setup + +Brian Aker | - Original Design +Calvin Sun - Windows Support +Brian Miezejewski - Bug fixes +Antony T Curtis - Help in inital development, transactions and various help +Michael Widenius - Bug fixes and some simple early optimizations diff --git a/storage/federatedx/CMakeFiles.txt b/storage/federatedx/CMakeFiles.txt new file mode 100644 index 00000000000..897fc174505 --- /dev/null +++ b/storage/federatedx/CMakeFiles.txt @@ -0,0 +1,3 @@ +INCLUDE("${PROJECT_SOURCE_DIR}/storage/mysql_storage_engine.cmake") +SET(FEDERATED_SOURCES ha_federatedx.cc) +MYSQL_STORAGE_ENGINE(FEDERATED) diff --git a/storage/federatedx/ChangeLog b/storage/federatedx/ChangeLog new file mode 100644 index 00000000000..170321cc0b0 --- /dev/null +++ b/storage/federatedx/ChangeLog @@ -0,0 +1,18 @@ +0.2 - Thu March 8 00:00:00 EST 2008 + + - Fixed bug #30051 "CREATE TABLE does not connect and check existence of remote table" + Modified "real_connect" to take a share and create flag to in order to not rely + on any settings that are later instantiated and/or set by get_share + Also, put logic in the code to not attempt this if a localhost. There's an annoying + functionality that if federated tries to connect to itself during creater table, you + get 1159 error (timeout) - only when local. This prevents having this functionality + and is probably part of the reason it was removed. + +0.1 - Thu Feb 1 00:00:00 EST 2008 + + - This is the FederatedX Storage Engine, + first release. + - Added documentation + - Added simple test and README file to explain + how to run the test + - Added FAQ diff --git a/storage/federatedx/FAQ b/storage/federatedx/FAQ new file mode 100644 index 00000000000..50def432009 --- /dev/null +++ b/storage/federatedx/FAQ @@ -0,0 +1,40 @@ +Q. What is the FederatedX pluggable storage engine? + +A. It is a fork of the Federated Storage Engine that Brian Aker and I +(Patrick Galbraith) developed originally . It is a storage engine that +uses a client connection to a remote MySQL data source as its data +source instead of a local file on disk. + +Q. Why did you fork from Federated? + +A. To enhance the storage engine independently of the +MySQL Server release schedule. Many people have been +mentioning their dissatisfaction with the limitations +of Federated. I think the engine is a great concept and +have a sense of obligation to continue to improve it. +There are some patches already that are in dire need +of being applied and tested. + +Q. What do you plan to do with FederatedX? + +A. Many things need addressing: + +- Outstanding bugs +- How do deal with huge result sets +- Pushdown conditions (being able to pass things like LIMIT + to the remote connection to keep from returning huge + result sets). +- Better transactional support +- Other connection mechanisms (ODBC, JDBC, native drivers + of other RDBMSs) + +Q. What FederatedX is and is not? + +A. FederatedX is not yet a complete "federated" solution in + the sense that other venders have developed (IBM, etc). It + is essentially a networked storage engine. It is my hope + to make it a real federated solution. + +Q. In which MySQL distributions/forks/branches can I find FederateX + +A. MariaDB (http://www.mariadb.com) diff --git a/storage/federatedx/Makefile.am b/storage/federatedx/Makefile.am new file mode 100644 index 00000000000..802f89d2321 --- /dev/null +++ b/storage/federatedx/Makefile.am @@ -0,0 +1,64 @@ +# Used to build Makefile.in + +MYSQLDATAdir = $(localstatedir) +MYSQLSHAREdir = $(pkgdatadir) +MYSQLBASEdir= $(prefix) +MYSQLLIBdir= $(pkglibdir) +pkgplugindir = $(pkglibdir)/plugin +INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include \ + -I$(top_srcdir)/regex \ + -I$(top_srcdir)/sql \ + -I$(srcdir) +WRAPLIBS= + +LDADD = + +DEFS = @DEFS@ + +noinst_HEADERS = ha_federatedx.h federatedx_probes.h + +EXTRA_LTLIBRARIES = ha_federatedx.la +pkgplugin_LTLIBRARIES = @plugin_federated_shared_target@ +ha_federatedx_la_LDFLAGS = -module -rpath $(pkgplugindir) +ha_federatedx_la_CXXFLAGS= $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN +ha_federatedx_la_CFLAGS = $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN +ha_federatedx_la_SOURCES = ha_federatedx.cc + + +EXTRA_LIBRARIES = libfederatedx.a +noinst_LIBRARIES = @plugin_federated_static_target@ +libfederatedx_a_CXXFLAGS = $(AM_CFLAGS) +libfederatedx_a_CFLAGS = $(AM_CFLAGS) +libfederatedx_a_SOURCES= ha_federatedx.cc federatedx_txn.cc \ + federatedx_io.cc federatedx_io_null.cc \ + federatedx_io_mysql.cc + +EXTRA_DIST = CMakeLists.txt plug.in ha_federatedx.h \ + federatedx_probes.d + +ha_federatedx_la_SOURCES = ha_federatedx.cc federatedx_txn.cc \ + federatedx_io.cc federatedx_io_null.cc \ + federatedx_io_mysql.cc $(top_srcdir)/mysys/string.c +ha_federatedx_la_LIBADD = + +#DTRACE = @DTRACE@ +#DTRACEFLAGS = @DTRACEFLAGS@ +#DTRACEFILES = .libs/libfederatedx_engine_la-ha_federatedx.o + +# #if HAVE_DTRACE +# # libfederatedx_engine_la_LIBADD += federatedx_probes.o +# #endif + +# federatedx_probes.h: federatedx_probes.d +# $(DTRACE) $(DTRACEFLAGS) -h -s federatedx_probes.d +# mv federatedx_probes.h federatedx_probes.h.bak +# sed "s/#include //g" federatedx_probes.h.bak > federatedx_probes.h +# rm federatedx_probes.h.bak + +#federatedx_probes.o: +# $(DTRACE) $(DTRACEFLAGS) -G -s federatedx_probes.d $(DTRACEFILES) + +# End + +# Don't update the files from bitkeeper +%::SCCS/s.% diff --git a/storage/federatedx/README b/storage/federatedx/README new file mode 100644 index 00000000000..6618527c08a --- /dev/null +++ b/storage/federatedx/README @@ -0,0 +1,33 @@ +This is the FederatedX Storage Engine, developed as an external storage engine. + +NOTE: + +The following is only relevant if you use it for MySQL. MariaDB already comes +with the latest version of FederatedX. + +To install, grab a copy of the mysql source code and run this: + +./configure --with-mysql=/path/to/src/mysql-5.x --libdir=/usr/local/lib/mysql/ + +make install + +And then inside of MySQL: + +mysql> INSTALL PLUGIN federatedx SONAME 'libfederatedx_engine.so'; + +mysql> CREATE TABLE `d` (`a` varchar(125), b text, primary key(a)) ENGINE=FEDERATEDX CONNECTION="mysql://root@host/schema/table" + +or + +mysql> CREATE TABLE `d` (`a` varchar(125), b text, primary key(a)) ENGINE=FEDERATEDX CONNECTION="server" CHARSET=latin1; + +You will probably need to edit the Makefile.am in the src/ tree if you want +to build on anything other then Linux (and the Makefile assumes that the +server was not compiled for debug). The reason for the two possible +configure lines is that libdir is dependent on where MySQL was installed. If +you run the "INSTALL PLUGIN ..." and you get a file not found, check that +your configured this directory correctly. + +For Solaris you can enable DTrace probes by adding to configure +--enable-dtrace + diff --git a/storage/federatedx/README.windows b/storage/federatedx/README.windows new file mode 100644 index 00000000000..3f1f2a3c79a --- /dev/null +++ b/storage/federatedx/README.windows @@ -0,0 +1,23 @@ +The following files are changed in order to build a new engine on Windows: + +- Update win\configure.js with +case "WITH_FEDERATEDX_STORAGE_ENGINE": +to make sure it will pass WITH_FEDERATEDX_STORAGE_ENGINE in. + +- Update CMakeFiles.txt under mysql root: + IF(WITH_FEDERATEDX_STORAGE_ENGINE) + ADD_DEFINITIONS(-D WITH_FEDERATEDX_STORAGE_ENGINE) + SET (mysql_plugin_defs + "${mysql_plugin_defs},builtin_skeleton_plugin") + ENDIF(WITH_FEDERATEDX_STORAGE_ENGINE) + + and, + + IF(WITH_FEDERATEDX_STORAGE_ENGINE) + ADD_SUBDIRECTORY(storage/skeleton/src) + ENDIF(WITH_FEDERATEDX_STORAGE_ENGINE) + + - Update CMakeFiles.txt under sql: + IF(WITH_FEDERATEDX_STORAGE_ENGINE) + TARGET_LINK_LIBRARIES(mysqld skeleton) + ENDIF(WITH_FEDERATEDX_STORAGE_ENGINE) diff --git a/storage/federatedx/TODO b/storage/federatedx/TODO new file mode 100644 index 00000000000..71330742f4e --- /dev/null +++ b/storage/federatedx/TODO @@ -0,0 +1,30 @@ +Features + +* Add Pushdown conditions +* Add other network driver interfaces +* Handle large result sets +* Auto-discovery of tables on foreign data sources + +Bugs (http://bugs.mysql.com) + +20026 2006-05-23 FEDERATED lacks support for auto_increment_increment and auto_increment_offset +20724 2006-06-27 FEDERATED does not honour SET INSERT_ID +28269 2007-05-06 Any FEDERATED engine fails to quote reserved words for field names +25509 2007-01-10 Federated: Failure with non-ASCII characters +26697 2007-02-27 Every query to a federated table results in a full scan of MyISAM table. +21360 2006-07-31 Microsoft Windows (Windows/Linux) mysqldump error on federated tables +34189 2008-01-31 Any ALTER TABLE t1 ENGINE=FEDERATED CONNECTION='connectionString' on MyISAM fails +31757 2007-10-22 Any Federated tables break replication Antony Curtis +33953 2008-01-21 Any mysqld dies on search federated table using nullable index with < or <= operator +34015 2008-01-23 Linux Problems with float fields using federated tables +21583 2006-08-11 Linux (Linux) Federated table returns broken strings. +33702 2008-01-05 Accessing a federated table with a non existing server returns random error code +25512 2007-01-10 Federated: CREATE failures +32426 2007-11-16 Any FEDERATED query returns corrupt results for ORDER BY on a TEXT field +25510 2007-01-10 Federated: double trigger activation +33250 2007-12-14 SELECT * FROM really_big_federated_table eats lots of virtual memory (OOM) +14874 2005-11-11 Error 2013: Lost connection to MySQL server with Federated table +25508 2007-01-10 Federated: Failure to Remove Partitioning +27180 2007-03-15 #1030 - Got error 1 from storage engine with big tables +33947 2008-01-20 Any Join on Federated tables with Unique index and IS NOT NULL crashes server +30051 (fixed) CREATE TABLE does not connect and check existence of remote table diff --git a/storage/federatedx/federatedx_io.cc b/storage/federatedx/federatedx_io.cc new file mode 100644 index 00000000000..10023bec35b --- /dev/null +++ b/storage/federatedx/federatedx_io.cc @@ -0,0 +1,103 @@ +/* +Copyright (c) 2007, Antony T Curtis +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + + * Neither the name of FederatedX nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +/*#define MYSQL_SERVER 1*/ +#include "mysql_priv.h" +#include + +#include "ha_federatedx.h" + +#include "m_string.h" + +#ifdef USE_PRAGMA_IMPLEMENTATION +#pragma implementation // gcc: Class implementation +#endif + +typedef federatedx_io *(*instantiate_io_type)(MEM_ROOT *server_root, + FEDERATEDX_SERVER *server); +struct io_schemes_st +{ + const char *scheme; + instantiate_io_type instantiate; +}; + + +static const io_schemes_st federated_io_schemes[] = +{ + { "mysql", &instantiate_io_mysql }, + { "null", instantiate_io_null } /* must be last element */ +}; + +const uint federated_io_schemes_count= array_elements(federated_io_schemes); + +federatedx_io::federatedx_io(FEDERATEDX_SERVER *aserver) + : server(aserver), owner_ptr(0), txn_next(0), idle_next(0), + active(FALSE), busy(FALSE), readonly(TRUE) +{ + DBUG_ENTER("federatedx_io::federatedx_io"); + DBUG_ASSERT(server); + + safe_mutex_assert_owner(&server->mutex); + server->io_count++; + + DBUG_VOID_RETURN; +} + + +federatedx_io::~federatedx_io() +{ + DBUG_ENTER("federatedx_io::~federatedx_io"); + + server->io_count--; + + DBUG_VOID_RETURN; +} + + +bool federatedx_io::handles_scheme(const char *scheme) +{ + const io_schemes_st *ptr = federated_io_schemes; + const io_schemes_st *end = ptr + array_elements(federated_io_schemes); + while (ptr != end && strcasecmp(scheme, ptr->scheme)) + ++ptr; + return ptr != end; +} + + +federatedx_io *federatedx_io::construct(MEM_ROOT *server_root, + FEDERATEDX_SERVER *server) +{ + const io_schemes_st *ptr = federated_io_schemes; + const io_schemes_st *end = ptr + (array_elements(federated_io_schemes) - 1); + while (ptr != end && strcasecmp(server->scheme, ptr->scheme)) + ++ptr; + return ptr->instantiate(server_root, server); +} + + diff --git a/storage/federatedx/federatedx_io_mysql.cc b/storage/federatedx/federatedx_io_mysql.cc new file mode 100644 index 00000000000..5245395b060 --- /dev/null +++ b/storage/federatedx/federatedx_io_mysql.cc @@ -0,0 +1,592 @@ +/* +Copyright (c) 2007, Antony T Curtis +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + + * Neither the name of FederatedX nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +/*#define MYSQL_SERVER 1*/ +#include "mysql_priv.h" +#include + +#include "ha_federatedx.h" + +#include "m_string.h" + +#ifdef USE_PRAGMA_IMPLEMENTATION +#pragma implementation // gcc: Class implementation +#endif + + +#define SAVEPOINT_REALIZED 1 +#define SAVEPOINT_RESTRICT 2 +#define SAVEPOINT_EMITTED 4 + + +typedef struct federatedx_savepoint +{ + ulong level; + uint flags; +} SAVEPT; + + +class federatedx_io_mysql :public federatedx_io +{ + MYSQL mysql; /* MySQL connection */ + DYNAMIC_ARRAY savepoints; + bool requested_autocommit; + bool actual_autocommit; + + int actual_query(const char *buffer, uint length); + bool test_all_restrict() const; +public: + federatedx_io_mysql(FEDERATEDX_SERVER *); + ~federatedx_io_mysql(); + + int simple_query(const char *fmt, ...); + int query(const char *buffer, uint length); + virtual FEDERATEDX_IO_RESULT *store_result(); + + virtual size_t max_query_size() const; + + virtual my_ulonglong affected_rows() const; + virtual my_ulonglong last_insert_id() const; + + virtual int error_code(); + virtual const char *error_str(); + + void reset(); + int commit(); + int rollback(); + + int savepoint_set(ulong sp); + ulong savepoint_release(ulong sp); + ulong savepoint_rollback(ulong sp); + void savepoint_restrict(ulong sp); + + ulong last_savepoint() const; + ulong actual_savepoint() const; + bool is_autocommit() const; + + bool table_metadata(ha_statistics *stats, const char *table_name, + uint table_name_length, uint flag); + + /* resultset operations */ + + virtual void free_result(FEDERATEDX_IO_RESULT *io_result); + virtual unsigned int get_num_fields(FEDERATEDX_IO_RESULT *io_result); + virtual my_ulonglong get_num_rows(FEDERATEDX_IO_RESULT *io_result); + virtual FEDERATEDX_IO_ROW *fetch_row(FEDERATEDX_IO_RESULT *io_result); + virtual ulong *fetch_lengths(FEDERATEDX_IO_RESULT *io_result); + virtual const char *get_column_data(FEDERATEDX_IO_ROW *row, + unsigned int column); + virtual bool is_column_null(const FEDERATEDX_IO_ROW *row, + unsigned int column) const; +}; + + +federatedx_io *instantiate_io_mysql(MEM_ROOT *server_root, + FEDERATEDX_SERVER *server) +{ + return new (server_root) federatedx_io_mysql(server); +} + + +federatedx_io_mysql::federatedx_io_mysql(FEDERATEDX_SERVER *aserver) + : federatedx_io(aserver), + requested_autocommit(TRUE), actual_autocommit(TRUE) +{ + DBUG_ENTER("federatedx_io_mysql::federatedx_io_mysql"); + + bzero(&mysql, sizeof(MYSQL)); + bzero(&savepoints, sizeof(DYNAMIC_ARRAY)); + + my_init_dynamic_array(&savepoints, sizeof(SAVEPT), 16, 16); + + DBUG_VOID_RETURN; +} + + +federatedx_io_mysql::~federatedx_io_mysql() +{ + DBUG_ENTER("federatedx_io_mysql::~federatedx_io_mysql"); + + mysql_close(&mysql); + delete_dynamic(&savepoints); + + DBUG_VOID_RETURN; +} + + +void federatedx_io_mysql::reset() +{ + reset_dynamic(&savepoints); + set_active(FALSE); + + requested_autocommit= TRUE; + mysql.reconnect= 1; +} + + +int federatedx_io_mysql::commit() +{ + int error= 0; + DBUG_ENTER("federatedx_io_mysql::commit"); + + if (!actual_autocommit && (error= actual_query("COMMIT", 6))) + rollback(); + + reset(); + + DBUG_RETURN(error); +} + +int federatedx_io_mysql::rollback() +{ + int error= 0; + DBUG_ENTER("federatedx_io_mysql::rollback"); + + if (!actual_autocommit) + error= actual_query("ROLLBACK", 8); + else + error= ER_WARNING_NOT_COMPLETE_ROLLBACK; + + reset(); + + DBUG_RETURN(error); +} + + +ulong federatedx_io_mysql::last_savepoint() const +{ + SAVEPT *savept= NULL; + DBUG_ENTER("federatedx_io_mysql::last_savepoint"); + + if (savepoints.elements) + savept= dynamic_element(&savepoints, savepoints.elements - 1, SAVEPT *); + + DBUG_RETURN(savept ? savept->level : 0); +} + + +ulong federatedx_io_mysql::actual_savepoint() const +{ + SAVEPT *savept= NULL; + uint index= savepoints.elements; + DBUG_ENTER("federatedx_io_mysql::last_savepoint"); + + while (index) + { + savept= dynamic_element(&savepoints, --index, SAVEPT *); + if (savept->flags & SAVEPOINT_REALIZED) + break; + savept= NULL; + } + + DBUG_RETURN(savept ? savept->level : 0); +} + +bool federatedx_io_mysql::is_autocommit() const +{ + return actual_autocommit; +} + + +int federatedx_io_mysql::savepoint_set(ulong sp) +{ + int error; + SAVEPT savept; + DBUG_ENTER("federatedx_io_mysql::savepoint_set"); + DBUG_PRINT("info",("savepoint=%lu", sp)); + DBUG_ASSERT(sp > last_savepoint()); + + savept.level= sp; + savept.flags= 0; + + if ((error= insert_dynamic(&savepoints, (uchar*) &savept) ? -1 : 0)) + goto err; + + set_active(TRUE); + mysql.reconnect= 0; + requested_autocommit= FALSE; + +err: + DBUG_RETURN(error); +} + + +ulong federatedx_io_mysql::savepoint_release(ulong sp) +{ + SAVEPT *savept, *last= NULL; + DBUG_ENTER("federatedx_io_mysql::savepoint_release"); + DBUG_PRINT("info",("savepoint=%lu", sp)); + + while (savepoints.elements) + { + savept= dynamic_element(&savepoints, savepoints.elements - 1, SAVEPT *); + if (savept->level < sp) + break; + if ((savept->flags & (SAVEPOINT_REALIZED | + SAVEPOINT_RESTRICT)) == SAVEPOINT_REALIZED) + last= savept; + savepoints.elements--; + } + + if (last) + { + char buffer[STRING_BUFFER_USUAL_SIZE]; + int length= my_snprintf(buffer, sizeof(buffer), + "RELEASE SAVEPOINT save%lu", last->level); + actual_query(buffer, length); + } + + DBUG_RETURN(last_savepoint()); +} + + +ulong federatedx_io_mysql::savepoint_rollback(ulong sp) +{ + SAVEPT *savept; + uint index; + DBUG_ENTER("federatedx_io_mysql::savepoint_release"); + DBUG_PRINT("info",("savepoint=%lu", sp)); + + while (savepoints.elements) + { + savept= dynamic_element(&savepoints, savepoints.elements - 1, SAVEPT *); + if (savept->level <= sp) + break; + savepoints.elements--; + } + + for (index= savepoints.elements, savept= NULL; index;) + { + savept= dynamic_element(&savepoints, --index, SAVEPT *); + if (savept->flags & SAVEPOINT_REALIZED) + break; + savept= NULL; + } + + if (savept && !(savept->flags & SAVEPOINT_RESTRICT)) + { + char buffer[STRING_BUFFER_USUAL_SIZE]; + int length= my_snprintf(buffer, sizeof(buffer), + "ROLLBACK TO SAVEPOINT save%lu", savept->level); + actual_query(buffer, length); + } + + DBUG_RETURN(last_savepoint()); +} + + +void federatedx_io_mysql::savepoint_restrict(ulong sp) +{ + SAVEPT *savept; + uint index= savepoints.elements; + DBUG_ENTER("federatedx_io_mysql::savepoint_restrict"); + + while (index) + { + savept= dynamic_element(&savepoints, --index, SAVEPT *); + if (savept->level > sp) + continue; + if (savept->level < sp) + break; + savept->flags|= SAVEPOINT_RESTRICT; + break; + } + + DBUG_VOID_RETURN; +} + + +int federatedx_io_mysql::simple_query(const char *fmt, ...) +{ + char buffer[STRING_BUFFER_USUAL_SIZE]; + int length, error; + va_list arg; + DBUG_ENTER("federatedx_io_mysql::simple_query"); + + va_start(arg, fmt); + length= my_vsnprintf(buffer, sizeof(buffer), fmt, arg); + va_end(arg); + + error= query(buffer, length); + + DBUG_RETURN(error); +} + + +bool federatedx_io_mysql::test_all_restrict() const +{ + bool result= FALSE; + SAVEPT *savept; + uint index= savepoints.elements; + DBUG_ENTER("federatedx_io_mysql::test_all_restrict"); + + while (index) + { + savept= dynamic_element(&savepoints, --index, SAVEPT *); + if ((savept->flags & (SAVEPOINT_REALIZED | + SAVEPOINT_RESTRICT)) == SAVEPOINT_REALIZED || + (savept->flags & SAVEPOINT_EMITTED)) + DBUG_RETURN(FALSE); + if (savept->flags & SAVEPOINT_RESTRICT) + result= TRUE; + } + + DBUG_RETURN(result); +} + + +int federatedx_io_mysql::query(const char *buffer, uint length) +{ + int error; + bool wants_autocommit= requested_autocommit | is_readonly(); + DBUG_ENTER("federatedx_io_mysql::query"); + + if (!wants_autocommit && test_all_restrict()) + wants_autocommit= TRUE; + + if (wants_autocommit != actual_autocommit) + { + if ((error= actual_query(wants_autocommit ? "SET AUTOCOMMIT=1" + : "SET AUTOCOMMIT=0", 16))) + DBUG_RETURN(error); + mysql.reconnect= wants_autocommit ? 1 : 0; + actual_autocommit= wants_autocommit; + } + + if (!actual_autocommit && last_savepoint() != actual_savepoint()) + { + SAVEPT *savept= dynamic_element(&savepoints, savepoints.elements - 1, + SAVEPT *); + if (!(savept->flags & SAVEPOINT_RESTRICT)) + { + char buf[STRING_BUFFER_USUAL_SIZE]; + int len= my_snprintf(buf, sizeof(buf), + "SAVEPOINT save%lu", savept->level); + if ((error= actual_query(buf, len))) + DBUG_RETURN(error); + set_active(TRUE); + savept->flags|= SAVEPOINT_EMITTED; + } + savept->flags|= SAVEPOINT_REALIZED; + } + + if (!(error= actual_query(buffer, length))) + set_active(is_active() || !actual_autocommit); + + DBUG_RETURN(error); +} + + +int federatedx_io_mysql::actual_query(const char *buffer, uint length) +{ + int error; + DBUG_ENTER("federatedx_io_mysql::actual_query"); + + if (!mysql.master) + { + if (!(mysql_init(&mysql))) + DBUG_RETURN(-1); + + /* + BUG# 17044 Federated Storage Engine is not UTF8 clean + Add set names to whatever charset the table is at open + of table + */ + /* this sets the csname like 'set names utf8' */ + mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, get_charsetname()); + + if (!mysql_real_connect(&mysql, + get_hostname(), + get_username(), + get_password(), + get_database(), + get_port(), + get_socket(), 0)) + DBUG_RETURN(ER_CONNECT_TO_FOREIGN_DATA_SOURCE); + mysql.reconnect= 1; + } + + error= mysql_real_query(&mysql, buffer, length); + + DBUG_RETURN(error); +} + +size_t federatedx_io_mysql::max_query_size() const +{ + return mysql.net.max_packet_size; +} + + +my_ulonglong federatedx_io_mysql::affected_rows() const +{ + return mysql.affected_rows; +} + + +my_ulonglong federatedx_io_mysql::last_insert_id() const +{ + return mysql.last_used_con->insert_id; +} + + +int federatedx_io_mysql::error_code() +{ + return mysql_errno(&mysql); +} + + +const char *federatedx_io_mysql::error_str() +{ + return mysql_error(&mysql); +} + + +FEDERATEDX_IO_RESULT *federatedx_io_mysql::store_result() +{ + FEDERATEDX_IO_RESULT *result; + DBUG_ENTER("federatedx_io_mysql::store_result"); + + result= (FEDERATEDX_IO_RESULT *) mysql_store_result(&mysql); + + DBUG_RETURN(result); +} + + +void federatedx_io_mysql::free_result(FEDERATEDX_IO_RESULT *io_result) +{ + mysql_free_result((MYSQL_RES *) io_result); +} + + +unsigned int federatedx_io_mysql::get_num_fields(FEDERATEDX_IO_RESULT *io_result) +{ + return mysql_num_fields((MYSQL_RES *) io_result); +} + + +my_ulonglong federatedx_io_mysql::get_num_rows(FEDERATEDX_IO_RESULT *io_result) +{ + return mysql_num_rows((MYSQL_RES *) io_result); +} + + +FEDERATEDX_IO_ROW *federatedx_io_mysql::fetch_row(FEDERATEDX_IO_RESULT *io_result) +{ + return (FEDERATEDX_IO_ROW *) mysql_fetch_row((MYSQL_RES *) io_result); +} + + +ulong *federatedx_io_mysql::fetch_lengths(FEDERATEDX_IO_RESULT *io_result) +{ + return mysql_fetch_lengths((MYSQL_RES *) io_result); +} + + +const char *federatedx_io_mysql::get_column_data(FEDERATEDX_IO_ROW *row, + unsigned int column) +{ + return ((MYSQL_ROW)row)[column]; +} + + +bool federatedx_io_mysql::is_column_null(const FEDERATEDX_IO_ROW *row, + unsigned int column) const +{ + return !((MYSQL_ROW)row)[column]; +} + +bool federatedx_io_mysql::table_metadata(ha_statistics *stats, + const char *table_name, + uint table_name_length, uint flag) +{ + char status_buf[FEDERATEDX_QUERY_BUFFER_SIZE]; + FEDERATEDX_IO_RESULT *result= 0; + FEDERATEDX_IO_ROW *row; + String status_query_string(status_buf, sizeof(status_buf), &my_charset_bin); + int error; + + status_query_string.length(0); + status_query_string.append(STRING_WITH_LEN("SHOW TABLE STATUS LIKE ")); + append_ident(&status_query_string, table_name, + table_name_length, value_quote_char); + + if (query(status_query_string.ptr(), status_query_string.length())) + goto error; + + status_query_string.length(0); + + result= store_result(); + + /* + We're going to use fields num. 4, 12 and 13 of the resultset, + so make sure we have these fields. + */ + if (!result || (get_num_fields(result) < 14)) + goto error; + + if (!get_num_rows(result)) + goto error; + + if (!(row= fetch_row(result))) + goto error; + + /* + deleted is set in ha_federatedx::info + */ + /* + need to figure out what this means as far as federatedx is concerned, + since we don't have a "file" + + data_file_length = ? + index_file_length = ? + delete_length = ? + */ + if (!is_column_null(row, 4)) + stats->records= (ha_rows) my_strtoll10(get_column_data(row, 4), + (char**) 0, &error); + if (!is_column_null(row, 5)) + stats->mean_rec_length= (ulong) my_strtoll10(get_column_data(row, 5), + (char**) 0, &error); + + stats->data_file_length= stats->records * stats->mean_rec_length; + + if (!is_column_null(row, 12)) + stats->update_time= (time_t) my_strtoll10(get_column_data(row, 12), + (char**) 0, &error); + if (!is_column_null(row, 13)) + stats->check_time= (time_t) my_strtoll10(get_column_data(row, 13), + (char**) 0, &error); + + free_result(result); + return 0; + +error: + free_result(result); + return 1; +} diff --git a/storage/federatedx/federatedx_io_null.cc b/storage/federatedx/federatedx_io_null.cc new file mode 100644 index 00000000000..cd8fc3eaf85 --- /dev/null +++ b/storage/federatedx/federatedx_io_null.cc @@ -0,0 +1,277 @@ +/* +Copyright (c) 2007, Antony T Curtis +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + + * Neither the name of FederatedX nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +/*#define MYSQL_SERVER 1*/ +#include "mysql_priv.h" +#include + +#include "ha_federatedx.h" + +#include "m_string.h" + +#ifdef USE_PRAGMA_IMPLEMENTATION +#pragma implementation // gcc: Class implementation +#endif + + +#define SAVEPOINT_REALIZED 1 +#define SAVEPOINT_RESTRICT 2 +#define SAVEPOINT_EMITTED 4 + + +typedef struct federatedx_savepoint +{ + ulong level; + uint flags; +} SAVEPT; + + +class federatedx_io_null :public federatedx_io +{ +public: + federatedx_io_null(FEDERATEDX_SERVER *); + ~federatedx_io_null(); + + int query(const char *buffer, uint length); + virtual FEDERATEDX_IO_RESULT *store_result(); + + virtual size_t max_query_size() const; + + virtual my_ulonglong affected_rows() const; + virtual my_ulonglong last_insert_id() const; + + virtual int error_code(); + virtual const char *error_str(); + + void reset(); + int commit(); + int rollback(); + + int savepoint_set(ulong sp); + ulong savepoint_release(ulong sp); + ulong savepoint_rollback(ulong sp); + void savepoint_restrict(ulong sp); + + ulong last_savepoint() const; + ulong actual_savepoint() const; + bool is_autocommit() const; + + bool table_metadata(ha_statistics *stats, const char *table_name, + uint table_name_length, uint flag); + + /* resultset operations */ + + virtual void free_result(FEDERATEDX_IO_RESULT *io_result); + virtual unsigned int get_num_fields(FEDERATEDX_IO_RESULT *io_result); + virtual my_ulonglong get_num_rows(FEDERATEDX_IO_RESULT *io_result); + virtual FEDERATEDX_IO_ROW *fetch_row(FEDERATEDX_IO_RESULT *io_result); + virtual ulong *fetch_lengths(FEDERATEDX_IO_RESULT *io_result); + virtual const char *get_column_data(FEDERATEDX_IO_ROW *row, + unsigned int column); + virtual bool is_column_null(const FEDERATEDX_IO_ROW *row, + unsigned int column) const; +}; + + +federatedx_io *instantiate_io_null(MEM_ROOT *server_root, + FEDERATEDX_SERVER *server) +{ + return new (server_root) federatedx_io_null(server); +} + + +federatedx_io_null::federatedx_io_null(FEDERATEDX_SERVER *aserver) + : federatedx_io(aserver) +{ +} + + +federatedx_io_null::~federatedx_io_null() +{ +} + + +void federatedx_io_null::reset() +{ +} + + +int federatedx_io_null::commit() +{ + return 0; +} + +int federatedx_io_null::rollback() +{ + return 0; +} + + +ulong federatedx_io_null::last_savepoint() const +{ + return 0; +} + + +ulong federatedx_io_null::actual_savepoint() const +{ + return 0; +} + +bool federatedx_io_null::is_autocommit() const +{ + return 0; +} + + +int federatedx_io_null::savepoint_set(ulong sp) +{ + return 0; +} + + +ulong federatedx_io_null::savepoint_release(ulong sp) +{ + return 0; +} + + +ulong federatedx_io_null::savepoint_rollback(ulong sp) +{ + return 0; +} + + +void federatedx_io_null::savepoint_restrict(ulong sp) +{ +} + + +int federatedx_io_null::query(const char *buffer, uint length) +{ + return 0; +} + + +size_t federatedx_io_null::max_query_size() const +{ + return INT_MAX; +} + + +my_ulonglong federatedx_io_null::affected_rows() const +{ + return 0; +} + + +my_ulonglong federatedx_io_null::last_insert_id() const +{ + return 0; +} + + +int federatedx_io_null::error_code() +{ + return 0; +} + + +const char *federatedx_io_null::error_str() +{ + return ""; +} + + +FEDERATEDX_IO_RESULT *federatedx_io_null::store_result() +{ + FEDERATEDX_IO_RESULT *result; + DBUG_ENTER("federatedx_io_null::store_result"); + + result= NULL; + + DBUG_RETURN(result); +} + + +void federatedx_io_null::free_result(FEDERATEDX_IO_RESULT *) +{ +} + + +unsigned int federatedx_io_null::get_num_fields(FEDERATEDX_IO_RESULT *) +{ + return 0; +} + + +my_ulonglong federatedx_io_null::get_num_rows(FEDERATEDX_IO_RESULT *) +{ + return 0; +} + + +FEDERATEDX_IO_ROW *federatedx_io_null::fetch_row(FEDERATEDX_IO_RESULT *) +{ + return NULL; +} + + +ulong *federatedx_io_null::fetch_lengths(FEDERATEDX_IO_RESULT *) +{ + return NULL; +} + + +const char *federatedx_io_null::get_column_data(FEDERATEDX_IO_ROW *, + unsigned int) +{ + return ""; +} + + +bool federatedx_io_null::is_column_null(const FEDERATEDX_IO_ROW *, + unsigned int) const +{ + return true; +} + +bool federatedx_io_null::table_metadata(ha_statistics *stats, + const char *table_name, + uint table_name_length, uint flag) +{ + stats->records= (ha_rows) 0; + stats->mean_rec_length= (ulong) 0; + stats->data_file_length= 0; + + stats->update_time= (time_t) 0; + stats->check_time= (time_t) 0; + + return 0; +} diff --git a/storage/federatedx/federatedx_probes.h b/storage/federatedx/federatedx_probes.h new file mode 100644 index 00000000000..620419512ce --- /dev/null +++ b/storage/federatedx/federatedx_probes.h @@ -0,0 +1,45 @@ +/* + * Generated by dtrace(1M). + */ + +#ifndef _FEDERATED_PROBES_H +#define _FEDERATED_PROBES_H + + + +#ifdef __cplusplus +extern "C" { +#endif + +#if _DTRACE_VERSION + +#define FEDERATED_CLOSE() \ + __dtrace_federated___close() +#define FEDERATED_CLOSE_ENABLED() \ + __dtraceenabled_federated___close() +#define FEDERATED_OPEN() \ + __dtrace_federated___open() +#define FEDERATED_OPEN_ENABLED() \ + __dtraceenabled_federated___open() + + +extern void __dtrace_federated___close(void); +extern int __dtraceenabled_federated___close(void); +extern void __dtrace_federated___open(void); +extern int __dtraceenabled_federated___open(void); + +#else + +#define FEDERATED_CLOSE() +#define FEDERATED_CLOSE_ENABLED() (0) +#define FEDERATED_OPEN() +#define FEDERATED_OPEN_ENABLED() (0) + +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* _FEDERATED_PROBES_H */ diff --git a/storage/federatedx/federatedx_txn.cc b/storage/federatedx/federatedx_txn.cc new file mode 100644 index 00000000000..a6ca3acc744 --- /dev/null +++ b/storage/federatedx/federatedx_txn.cc @@ -0,0 +1,424 @@ +/* +Copyright (c) 2007, Antony T Curtis +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + + * Neither the name of FederatedX nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +/*#define MYSQL_SERVER 1*/ +#include "mysql_priv.h" +#include + +#include "ha_federatedx.h" + +#include "m_string.h" + +#ifdef USE_PRAGMA_IMPLEMENTATION +#pragma implementation // gcc: Class implementation +#endif + + +federatedx_txn::federatedx_txn() + : txn_list(0), savepoint_level(0), savepoint_stmt(0), savepoint_next(0) +{ + DBUG_ENTER("federatedx_txn::federatedx_txn"); + DBUG_VOID_RETURN; +} + +federatedx_txn::~federatedx_txn() +{ + DBUG_ENTER("federatedx_txn::~federatedx_txn"); + DBUG_ASSERT(!txn_list); + DBUG_VOID_RETURN; +} + + +void federatedx_txn::close(FEDERATEDX_SERVER *server) +{ + uint count= 0; + federatedx_io *io, **iop; + DBUG_ENTER("federatedx_txn::close"); + + DBUG_ASSERT(!server->use_count); + DBUG_PRINT("info",("use count: %u connections: %u", + server->use_count, server->io_count)); + + for (iop= &txn_list; (io= *iop);) + { + if (io->server != server) + iop= &io->txn_next; + else + { + *iop= io->txn_next; + io->txn_next= NULL; + io->busy= FALSE; + + io->idle_next= server->idle_list; + server->idle_list= io; + } + } + + while ((io= server->idle_list)) + { + server->idle_list= io->idle_next; + delete io; + count++; + } + + DBUG_PRINT("info",("closed %u connections, txn_list: %s", count, + txn_list ? "active": "empty")); + DBUG_VOID_RETURN; +} + + +int federatedx_txn::acquire(FEDERATEDX_SHARE *share, bool readonly, + federatedx_io **ioptr) +{ + federatedx_io *io; + FEDERATEDX_SERVER *server= share->s; + DBUG_ENTER("federatedx_txn::acquire"); + DBUG_ASSERT(ioptr && server); + + if (!(io= *ioptr)) + { + /* check to see if we have an available IO connection */ + for (io= txn_list; io; io= io->txn_next) + if (io->server == server) + break; + + if (!io) + { + /* check to see if there are any unowned IO connections */ + pthread_mutex_lock(&server->mutex); + if ((io= server->idle_list)) + { + server->idle_list= io->idle_next; + io->idle_next= NULL; + } + else + io= federatedx_io::construct(&server->mem_root, server); + + io->txn_next= txn_list; + txn_list= io; + + pthread_mutex_unlock(&server->mutex); + } + + if (io->busy) + *io->owner_ptr= NULL; + + io->busy= TRUE; + io->owner_ptr= ioptr; + } + + DBUG_ASSERT(io->busy && io->server == server); + + io->readonly&= readonly; + + DBUG_RETURN((*ioptr= io) ? 0 : -1); +} + + +void federatedx_txn::release(federatedx_io **ioptr) +{ + federatedx_io *io; + DBUG_ENTER("federatedx_txn::release"); + DBUG_ASSERT(ioptr); + + if ((io= *ioptr)) + { + /* mark as available for reuse in this transaction */ + io->busy= FALSE; + *ioptr= NULL; + + DBUG_PRINT("info", ("active: %d autocommit: %d", + io->active, io->is_autocommit())); + + if (io->is_autocommit()) + io->active= FALSE; + } + + release_scan(); + + DBUG_VOID_RETURN; +} + + +void federatedx_txn::release_scan() +{ + uint count= 0, returned= 0; + federatedx_io *io, **pio; + DBUG_ENTER("federatedx_txn::release_scan"); + + /* return any inactive and idle connections to the server */ + for (pio= &txn_list; (io= *pio); count++) + { + if (io->active || io->busy) + pio= &io->txn_next; + else + { + FEDERATEDX_SERVER *server= io->server; + + /* unlink from list of connections bound to the transaction */ + *pio= io->txn_next; + io->txn_next= NULL; + + /* reset some values */ + io->readonly= TRUE; + + pthread_mutex_lock(&server->mutex); + io->idle_next= server->idle_list; + server->idle_list= io; + pthread_mutex_unlock(&server->mutex); + returned++; + } + } + DBUG_PRINT("info",("returned %u of %u connections(s)", returned, count)); + + DBUG_VOID_RETURN; +} + + +bool federatedx_txn::txn_begin() +{ + ulong level= 0; + DBUG_ENTER("federatedx_txn::txn_begin"); + + if (savepoint_next == 0) + { + savepoint_next++; + savepoint_level= savepoint_stmt= 0; + sp_acquire(&level); + } + + DBUG_RETURN(level == 1); +} + + +int federatedx_txn::txn_commit() +{ + int error= 0; + federatedx_io *io; + DBUG_ENTER("federatedx_txn::txn_commit"); + + if (savepoint_next) + { + DBUG_ASSERT(savepoint_stmt != 1); + + for (io= txn_list; io; io= io->txn_next) + { + int rc= 0; + + if (io->active) + rc= io->commit(); + else + io->rollback(); + + if (io->active && rc) + error= -1; + + io->reset(); + } + + release_scan(); + + savepoint_next= savepoint_stmt= savepoint_level= 0; + } + + DBUG_RETURN(error); +} + + +int federatedx_txn::txn_rollback() +{ + int error= 0; + federatedx_io *io; + DBUG_ENTER("federatedx_txn::txn_commit"); + + if (savepoint_next) + { + DBUG_ASSERT(savepoint_stmt != 1); + + for (io= txn_list; io; io= io->txn_next) + { + int rc= io->rollback(); + + if (io->active && rc) + error= -1; + + io->reset(); + } + + release_scan(); + + savepoint_next= savepoint_stmt= savepoint_level= 0; + } + + DBUG_RETURN(error); +} + + +bool federatedx_txn::sp_acquire(ulong *sp) +{ + bool rc= FALSE; + federatedx_io *io; + DBUG_ENTER("federatedx_txn::sp_acquire"); + DBUG_ASSERT(sp && savepoint_next); + + *sp= savepoint_level= savepoint_next++; + + for (io= txn_list; io; io= io->txn_next) + { + if (io->readonly) + continue; + + io->savepoint_set(savepoint_level); + rc= TRUE; + } + + DBUG_RETURN(rc); +} + + +int federatedx_txn::sp_rollback(ulong *sp) +{ + ulong level, new_level= savepoint_level; + federatedx_io *io; + DBUG_ENTER("federatedx_txn::sp_rollback"); + DBUG_ASSERT(sp && savepoint_next && *sp && *sp <= savepoint_level); + + for (io= txn_list; io; io= io->txn_next) + { + if (io->readonly) + continue; + + if ((level= io->savepoint_rollback(*sp)) < new_level) + new_level= level; + } + + savepoint_level= new_level; + + DBUG_RETURN(0); +} + + +int federatedx_txn::sp_release(ulong *sp) +{ + ulong level, new_level= savepoint_level; + federatedx_io *io; + DBUG_ENTER("federatedx_txn::sp_release"); + DBUG_ASSERT(sp && savepoint_next && *sp && *sp <= savepoint_level); + + for (io= txn_list; io; io= io->txn_next) + { + if (io->readonly) + continue; + + if ((level= io->savepoint_release(*sp)) < new_level) + new_level= level; + } + + savepoint_level= new_level; + *sp= 0; + + DBUG_RETURN(0); +} + + +bool federatedx_txn::stmt_begin() +{ + bool result= FALSE; + DBUG_ENTER("federatedx_txn::stmt_begin"); + + if (!savepoint_stmt) + { + if (!savepoint_next) + { + savepoint_next++; + savepoint_level= savepoint_stmt= 0; + } + result= sp_acquire(&savepoint_stmt); + } + + DBUG_RETURN(result); +} + + +int federatedx_txn::stmt_commit() +{ + int result= 0; + DBUG_ENTER("federatedx_txn::stmt_commit"); + + if (savepoint_stmt == 1) + { + savepoint_stmt= 0; + result= txn_commit(); + } + else + if (savepoint_stmt) + result= sp_release(&savepoint_stmt); + + DBUG_RETURN(result); +} + + +int federatedx_txn::stmt_rollback() +{ + int result= 0; + DBUG_ENTER("federated:txn::stmt_rollback"); + + if (savepoint_stmt == 1) + { + savepoint_stmt= 0; + result= txn_rollback(); + } + else + if (savepoint_stmt) + { + result= sp_rollback(&savepoint_stmt); + sp_release(&savepoint_stmt); + } + + DBUG_RETURN(result); +} + + +void federatedx_txn::stmt_autocommit() +{ + federatedx_io *io; + DBUG_ENTER("federatedx_txn::stmt_autocommit"); + + for (io= txn_list; savepoint_stmt && io; io= io->txn_next) + { + if (io->readonly) + continue; + + io->savepoint_restrict(savepoint_stmt); + } + + DBUG_VOID_RETURN; +} + + diff --git a/storage/federatedx/ha_federatedx.cc b/storage/federatedx/ha_federatedx.cc new file mode 100644 index 00000000000..e4ea38c9c42 --- /dev/null +++ b/storage/federatedx/ha_federatedx.cc @@ -0,0 +1,3487 @@ +/* +Copyright (c) 2008, Patrick Galbraith +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + + * Neither the name of Patrick Galbraith nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/* + + FederatedX Pluggable Storage Engine + + ha_federatedx.cc - FederatedX Pluggable Storage Engine + Patrick Galbraith, 2008 + + This is a handler which uses a foreign database as the data file, as + opposed to a handler like MyISAM, which uses .MYD files locally. + + How this handler works + ---------------------------------- + Normal database files are local and as such: You create a table called + 'users', a file such as 'users.MYD' is created. A handler reads, inserts, + deletes, updates data in this file. The data is stored in particular format, + so to read, that data has to be parsed into fields, to write, fields have to + be stored in this format to write to this data file. + + With FederatedX storage engine, there will be no local files + for each table's data (such as .MYD). A foreign database will store + the data that would normally be in this file. This will necessitate + the use of MySQL client API to read, delete, update, insert this + data. The data will have to be retrieve via an SQL call "SELECT * + FROM users". Then, to read this data, it will have to be retrieved + via mysql_fetch_row one row at a time, then converted from the + column in this select into the format that the handler expects. + + The create table will simply create the .frm file, and within the + "CREATE TABLE" SQL, there SHALL be any of the following : + + connection=scheme://username:password@hostname:port/database/tablename + connection=scheme://username@hostname/database/tablename + connection=scheme://username:password@hostname/database/tablename + connection=scheme://username:password@hostname/database/tablename + + - OR - + + As of 5.1 federatedx now allows you to use a non-url + format, taking advantage of mysql.servers: + + connection="connection_one" + connection="connection_one/table_foo" + + An example would be: + + connection=mysql://username:password@hostname:port/database/tablename + + or, if we had: + + create server 'server_one' foreign data wrapper 'mysql' options + (HOST '127.0.0.1', + DATABASE 'db1', + USER 'root', + PASSWORD '', + PORT 3306, + SOCKET '', + OWNER 'root'); + + CREATE TABLE federatedx.t1 ( + `id` int(20) NOT NULL, + `name` varchar(64) NOT NULL default '' + ) + ENGINE="FEDERATEDX" DEFAULT CHARSET=latin1 + CONNECTION='server_one'; + + So, this will have been the equivalent of + + CONNECTION="mysql://root@127.0.0.1:3306/db1/t1" + + Then, we can also change the server to point to a new schema: + + ALTER SERVER 'server_one' options(DATABASE 'db2'); + + All subsequent calls will now be against db2.t1! Guess what? You don't + have to perform an alter table! + + This connecton="connection string" is necessary for the handler to be + able to connect to the foreign server, either by URL, or by server + name. + + + The basic flow is this: + + SQL calls issues locally -> + mysql handler API (data in handler format) -> + mysql client API (data converted to SQL calls) -> + foreign database -> mysql client API -> + convert result sets (if any) to handler format -> + handler API -> results or rows affected to local + + What this handler does and doesn't support + ------------------------------------------ + * Tables MUST be created on the foreign server prior to any action on those + tables via the handler, first version. IMPORTANT: IF you MUST use the + federatedx storage engine type on the REMOTE end, MAKE SURE [ :) ] That + the table you connect to IS NOT a table pointing BACK to your ORIGNAL + table! You know and have heard the screaching of audio feedback? You + know putting two mirror in front of each other how the reflection + continues for eternity? Well, need I say more?! + * There will not be support for transactions. + * There is no way for the handler to know if the foreign database or table + has changed. The reason for this is that this database has to work like a + data file that would never be written to by anything other than the + database. The integrity of the data in the local table could be breached + if there was any change to the foreign database. + * Support for SELECT, INSERT, UPDATE , DELETE, indexes. + * No ALTER TABLE, DROP TABLE or any other Data Definition Language calls. + * Prepared statements will not be used in the first implementation, it + remains to to be seen whether the limited subset of the client API for the + server supports this. + * This uses SELECT, INSERT, UPDATE, DELETE and not HANDLER for its + implementation. + * This will not work with the query cache. + + Method calls + + A two column table, with one record: + + (SELECT) + + "SELECT * FROM foo" + ha_federatedx::info + ha_federatedx::scan_time: + ha_federatedx::rnd_init: share->select_query SELECT * FROM foo + ha_federatedx::extra + + + ha_federatedx::rnd_next + ha_federatedx::convert_row_to_internal_format + ha_federatedx::rnd_next + + + ha_federatedx::rnd_end + ha_federatedx::extra + ha_federatedx::reset + + (INSERT) + + "INSERT INTO foo (id, ts) VALUES (2, now());" + + ha_federatedx::write_row + + ha_federatedx::reset + + (UPDATE) + + "UPDATE foo SET ts = now() WHERE id = 1;" + + ha_federatedx::index_init + ha_federatedx::index_read + ha_federatedx::index_read_idx + ha_federatedx::rnd_next + ha_federatedx::convert_row_to_internal_format + ha_federatedx::update_row + + ha_federatedx::extra + ha_federatedx::extra + ha_federatedx::extra + ha_federatedx::external_lock + ha_federatedx::reset + + + How do I use this handler? + -------------------------- + + + + Next, to use this handler, it's very simple. You must + have two databases running, either both on the same host, or + on different hosts. + + One the server that will be connecting to the foreign + host (client), you create your table as such: + + CREATE TABLE test_table ( + id int(20) NOT NULL auto_increment, + name varchar(32) NOT NULL default '', + other int(20) NOT NULL default '0', + PRIMARY KEY (id), + KEY name (name), + KEY other_key (other)) + ENGINE="FEDERATEDX" + DEFAULT CHARSET=latin1 + CONNECTION='mysql://root@127.0.0.1:9306/federatedx/test_federatedx'; + + Notice the "COMMENT" and "ENGINE" field? This is where you + respectively set the engine type, "FEDERATEDX" and foreign + host information, this being the database your 'client' database + will connect to and use as the "data file". Obviously, the foreign + database is running on port 9306, so you want to start up your other + database so that it is indeed on port 9306, and your federatedx + database on a port other than that. In my setup, I use port 5554 + for federatedx, and port 5555 for the foreign database. + + Then, on the foreign database: + + CREATE TABLE test_table ( + id int(20) NOT NULL auto_increment, + name varchar(32) NOT NULL default '', + other int(20) NOT NULL default '0', + PRIMARY KEY (id), + KEY name (name), + KEY other_key (other)) + ENGINE="" <-- whatever you want, or not specify + DEFAULT CHARSET=latin1 ; + + This table is exactly the same (and must be exactly the same), + except that it is not using the federatedx handler and does + not need the URL. + + + How to see the handler in action + -------------------------------- + + When developing this handler, I compiled the federatedx database with + debugging: + + ./configure --with-federatedx-storage-engine + --prefix=/home/mysql/mysql-build/federatedx/ --with-debug + + Once compiled, I did a 'make install' (not for the purpose of installing + the binary, but to install all the files the binary expects to see in the + diretory I specified in the build with --prefix, + "/home/mysql/mysql-build/federatedx". + + Then, I started the foreign server: + + /usr/local/mysql/bin/mysqld_safe + --user=mysql --log=/tmp/mysqld.5555.log -P 5555 + + Then, I went back to the directory containing the newly compiled mysqld, + /sql/, started up gdb: + + gdb ./mysqld + + Then, withn the (gdb) prompt: + (gdb) run --gdb --port=5554 --socket=/tmp/mysqld.5554 --skip-innodb --debug + + Next, I open several windows for each: + + 1. Tail the debug trace: tail -f /tmp/mysqld.trace|grep ha_fed + 2. Tail the SQL calls to the foreign database: tail -f /tmp/mysqld.5555.log + 3. A window with a client open to the federatedx server on port 5554 + 4. A window with a client open to the federatedx server on port 5555 + + I would create a table on the client to the foreign server on port + 5555, and then to the federatedx server on port 5554. At this point, + I would run whatever queries I wanted to on the federatedx server, + just always remembering that whatever changes I wanted to make on + the table, or if I created new tables, that I would have to do that + on the foreign server. + + Another thing to look for is 'show variables' to show you that you have + support for federatedx handler support: + + show variables like '%federat%' + + and: + + show storage engines; + + Both should display the federatedx storage handler. + + + Testing + ------- + + Testing for FederatedX as a pluggable storage engine for + now is a manual process that I intend to build a test + suite that works for all pluggable storage engines. + + How to test + + 1. cp fed.dat /tmp + (make sure you have access to "test". Use a user that has + super privileges for now) + 2. mysql -f -u root test < federated.test > federated.myresult 2>&1 + 3. diff federated.result federated.myresult (there _should_ be no differences) + + +*/ + + +#define MYSQL_SERVER 1q +#include "mysql_priv.h" +#include + +#ifdef USE_PRAGMA_IMPLEMENTATION +#pragma implementation // gcc: Class implementation +#endif + +#include "ha_federatedx.h" + +#include "m_string.h" + +#include + +/* Variables for federatedx share methods */ +static HASH federatedx_open_tables; // To track open tables +static HASH federatedx_open_servers; // To track open servers +pthread_mutex_t federatedx_mutex; // To init the hash +const char ident_quote_char= '`'; // Character for quoting + // identifiers +const char value_quote_char= '\''; // Character for quoting + // literals +static const int bulk_padding= 64; // bytes "overhead" in packet + +/* Variables used when chopping off trailing characters */ +static const uint sizeof_trailing_comma= sizeof(", ") - 1; +static const uint sizeof_trailing_closeparen= sizeof(") ") - 1; +static const uint sizeof_trailing_and= sizeof(" AND ") - 1; +static const uint sizeof_trailing_where= sizeof(" WHERE ") - 1; + +/* Static declaration for handerton */ +static handler *federatedx_create_handler(handlerton *hton, + TABLE_SHARE *table, + MEM_ROOT *mem_root); + +/* FederatedX storage engine handlerton */ + +static handler *federatedx_create_handler(handlerton *hton, + TABLE_SHARE *table, + MEM_ROOT *mem_root) +{ + return new (mem_root) ha_federatedx(hton, table); +} + + +/* Function we use in the creation of our hash to get key */ + +static uchar * +federatedx_share_get_key(FEDERATEDX_SHARE *share, size_t *length, + my_bool not_used __attribute__ ((unused))) +{ + *length= share->share_key_length; + return (uchar*) share->share_key; +} + + +static uchar * +federatedx_server_get_key(FEDERATEDX_SERVER *server, size_t *length, + my_bool not_used __attribute__ ((unused))) +{ + *length= server->key_length; + return server->key; +} + + +/* + Initialize the federatedx handler. + + SYNOPSIS + federatedx_db_init() + p Handlerton + + RETURN + FALSE OK + TRUE Error +*/ + +int federatedx_db_init(void *p) +{ + DBUG_ENTER("federatedx_db_init"); + handlerton *federatedx_hton= (handlerton *)p; + federatedx_hton->state= SHOW_OPTION_YES; + /* This is no longer needed for plugin storage engines */ + federatedx_hton->db_type= DB_TYPE_DEFAULT; + federatedx_hton->savepoint_offset= sizeof(ulong); + federatedx_hton->close_connection= ha_federatedx::disconnect; + federatedx_hton->savepoint_set= ha_federatedx::savepoint_set; + federatedx_hton->savepoint_rollback= ha_federatedx::savepoint_rollback; + federatedx_hton->savepoint_release= ha_federatedx::savepoint_release; + federatedx_hton->commit= ha_federatedx::commit; + federatedx_hton->rollback= ha_federatedx::rollback; + federatedx_hton->create= federatedx_create_handler; + federatedx_hton->flags= HTON_ALTER_NOT_SUPPORTED | HTON_NO_PARTITION; + + if (pthread_mutex_init(&federatedx_mutex, MY_MUTEX_INIT_FAST)) + goto error; + if (!hash_init(&federatedx_open_tables, &my_charset_bin, 32, 0, 0, + (hash_get_key) federatedx_share_get_key, 0, 0) && + !hash_init(&federatedx_open_servers, &my_charset_bin, 32, 0, 0, + (hash_get_key) federatedx_server_get_key, 0, 0)) + { + DBUG_RETURN(FALSE); + } + + VOID(pthread_mutex_destroy(&federatedx_mutex)); +error: + DBUG_RETURN(TRUE); +} + + +/* + Release the federatedx handler. + + SYNOPSIS + federatedx_db_end() + + RETURN + FALSE OK +*/ + +int federatedx_done(void *p) +{ + hash_free(&federatedx_open_tables); + hash_free(&federatedx_open_servers); + VOID(pthread_mutex_destroy(&federatedx_mutex)); + + return 0; +} + +/** + @brief Append identifiers to the string. + + @param[in,out] string The target string. + @param[in] name Identifier name + @param[in] length Length of identifier name in bytes + @param[in] quote_char Quote char to use for quoting identifier. + + @return Operation Status + @retval FALSE OK + @retval TRUE There was an error appending to the string. + + @note This function is based upon the append_identifier() function + in sql_show.cc except that quoting always occurs. +*/ + +bool append_ident(String *string, const char *name, uint length, + const char quote_char) +{ + bool result; + uint clen; + const char *name_end; + DBUG_ENTER("append_ident"); + + if (quote_char) + { + string->reserve(length * 2 + 2); + if ((result= string->append("e_char, 1, system_charset_info))) + goto err; + + for (name_end= name+length; name < name_end; name+= clen) + { + uchar c= *(uchar *) name; + if (!(clen= my_mbcharlen(system_charset_info, c))) + clen= 1; + if (clen == 1 && c == (uchar) quote_char && + (result= string->append("e_char, 1, system_charset_info))) + goto err; + if ((result= string->append(name, clen, string->charset()))) + goto err; + } + result= string->append("e_char, 1, system_charset_info); + } + else + result= string->append(name, length, system_charset_info); + +err: + DBUG_RETURN(result); +} + + +static int parse_url_error(FEDERATEDX_SHARE *share, TABLE *table, int error_num) +{ + char buf[FEDERATEDX_QUERY_BUFFER_SIZE]; + int buf_len; + DBUG_ENTER("ha_federatedx parse_url_error"); + + buf_len= min(table->s->connect_string.length, + FEDERATEDX_QUERY_BUFFER_SIZE-1); + strmake(buf, table->s->connect_string.str, buf_len); + my_error(error_num, MYF(0), buf); + DBUG_RETURN(error_num); +} + +/* + retrieve server object which contains server meta-data + from the system table given a server's name, set share + connection parameter members +*/ +int get_connection(MEM_ROOT *mem_root, FEDERATEDX_SHARE *share) +{ + int error_num= ER_FOREIGN_SERVER_DOESNT_EXIST; + char error_buffer[FEDERATEDX_QUERY_BUFFER_SIZE]; + FOREIGN_SERVER *server, server_buffer; + DBUG_ENTER("ha_federatedx::get_connection"); + + /* + get_server_by_name() clones the server if exists and allocates + copies of strings in the supplied mem_root + */ + if (!(server= + get_server_by_name(mem_root, share->connection_string, &server_buffer))) + { + DBUG_PRINT("info", ("get_server_by_name returned > 0 error condition!")); + /* need to come up with error handling */ + error_num=1; + goto error; + } + DBUG_PRINT("info", ("get_server_by_name returned server at %lx", + (long unsigned int) server)); + + /* + Most of these should never be empty strings, error handling will + need to be implemented. Also, is this the best way to set the share + members? Is there some allocation needed? In running this code, it works + except there are errors in the trace file of the share being overrun + at the address of the share. + */ + share->server_name_length= server->server_name_length; + share->server_name= server->server_name; + share->username= server->username; + share->password= server->password; + share->database= server->db; +#ifndef I_AM_PARANOID + share->port= server->port > 0 && server->port < 65536 ? +#else + share->port= server->port > 1023 && server->port < 65536 ? +#endif + (ushort) server->port : MYSQL_PORT; + share->hostname= server->host; + if (!(share->socket= server->socket) && + !strcmp(share->hostname, my_localhost)) + share->socket= (char *) MYSQL_UNIX_ADDR; + share->scheme= server->scheme; + + DBUG_PRINT("info", ("share->username: %s", share->username)); + DBUG_PRINT("info", ("share->password: %s", share->password)); + DBUG_PRINT("info", ("share->hostname: %s", share->hostname)); + DBUG_PRINT("info", ("share->database: %s", share->database)); + DBUG_PRINT("info", ("share->port: %d", share->port)); + DBUG_PRINT("info", ("share->socket: %s", share->socket)); + DBUG_RETURN(0); + +error: + my_sprintf(error_buffer, + (error_buffer, "server name: '%s' doesn't exist!", + share->connection_string)); + my_error(error_num, MYF(0), error_buffer); + DBUG_RETURN(error_num); +} + +/* + Parse connection info from table->s->connect_string + + SYNOPSIS + parse_url() + mem_root MEM_ROOT pointer for memory allocation + share pointer to FEDERATEDX share + table pointer to current TABLE class + table_create_flag determines what error to throw + + DESCRIPTION + Populates the share with information about the connection + to the foreign database that will serve as the data source. + This string must be specified (currently) in the "CONNECTION" field, + listed in the CREATE TABLE statement. + + This string MUST be in the format of any of these: + + CONNECTION="scheme://username:password@hostname:port/database/table" + CONNECTION="scheme://username@hostname/database/table" + CONNECTION="scheme://username@hostname:port/database/table" + CONNECTION="scheme://username:password@hostname/database/table" + + _OR_ + + CONNECTION="connection name" + + + + An Example: + + CREATE TABLE t1 (id int(32)) + ENGINE="FEDERATEDX" + CONNECTION="mysql://joe:joespass@192.168.1.111:9308/federatedx/testtable"; + + CREATE TABLE t2 ( + id int(4) NOT NULL auto_increment, + name varchar(32) NOT NULL, + PRIMARY KEY(id) + ) ENGINE="FEDERATEDX" CONNECTION="my_conn"; + + ***IMPORTANT*** + Currently, the FederatedX Storage Engine only supports connecting to another + Database ("scheme" of "mysql"). Connections using JDBC as well as + other connectors are in the planning stage. + + + 'password' and 'port' are both optional. + + RETURN VALUE + 0 success + error_num particular error code + +*/ + +static int parse_url(MEM_ROOT *mem_root, FEDERATEDX_SHARE *share, TABLE *table, + uint table_create_flag) +{ + uint error_num= (table_create_flag ? + ER_FOREIGN_DATA_STRING_INVALID_CANT_CREATE : + ER_FOREIGN_DATA_STRING_INVALID); + DBUG_ENTER("ha_federatedx::parse_url"); + + share->port= 0; + share->socket= 0; + DBUG_PRINT("info", ("share at %lx", (long unsigned int) share)); + DBUG_PRINT("info", ("Length: %u", (uint) table->s->connect_string.length)); + DBUG_PRINT("info", ("String: '%.*s'", (int) table->s->connect_string.length, + table->s->connect_string.str)); + share->connection_string= strmake_root(mem_root, table->s->connect_string.str, + table->s->connect_string.length); + + DBUG_PRINT("info",("parse_url alloced share->connection_string %lx", + (long unsigned int) share->connection_string)); + + DBUG_PRINT("info",("share->connection_string: %s",share->connection_string)); + /* + No :// or @ in connection string. Must be a straight connection name of + either "servername" or "servername/tablename" + */ + if ((!strstr(share->connection_string, "://") && + (!strchr(share->connection_string, '@')))) + { + + DBUG_PRINT("info", + ("share->connection_string: %s internal format " + "share->connection_string: %lx", + share->connection_string, + (ulong) share->connection_string)); + + /* ok, so we do a little parsing, but not completely! */ + share->parsed= FALSE; + /* + If there is a single '/' in the connection string, this means the user is + specifying a table name + */ + + if ((share->table_name= strchr(share->connection_string, '/'))) + { + *share->table_name++= '\0'; + share->table_name_length= strlen(share->table_name); + + DBUG_PRINT("info", + ("internal format, parsed table_name " + "share->connection_string: %s share->table_name: %s", + share->connection_string, share->table_name)); + + /* + there better not be any more '/'s ! + */ + if (strchr(share->table_name, '/')) + goto error; + } + /* + Otherwise, straight server name, use tablename of federatedx table + as remote table name + */ + else + { + /* + Connection specifies everything but, resort to + expecting remote and foreign table names to match + */ + share->table_name= strmake_root(mem_root, table->s->table_name.str, + (share->table_name_length= + table->s->table_name.length)); + DBUG_PRINT("info", + ("internal format, default table_name " + "share->connection_string: %s share->table_name: %s", + share->connection_string, share->table_name)); + } + + if ((error_num= get_connection(mem_root, share))) + goto error; + } + else + { + share->parsed= TRUE; + // Add a null for later termination of table name + share->connection_string[table->s->connect_string.length]= 0; + share->scheme= share->connection_string; + DBUG_PRINT("info",("parse_url alloced share->scheme: %lx", + (ulong) share->scheme)); + + /* + Remove addition of null terminator and store length + for each string in share + */ + if (!(share->username= strstr(share->scheme, "://"))) + goto error; + share->scheme[share->username - share->scheme]= '\0'; + + if (!federatedx_io::handles_scheme(share->scheme)) + goto error; + + share->username+= 3; + + if (!(share->hostname= strchr(share->username, '@'))) + goto error; + *share->hostname++= '\0'; // End username + + if ((share->password= strchr(share->username, ':'))) + { + *share->password++= '\0'; // End username + + /* make sure there isn't an extra / or @ */ + if ((strchr(share->password, '/') || strchr(share->hostname, '@'))) + goto error; + /* + Found that if the string is: + user:@hostname:port/db/table + Then password is a null string, so set to NULL + */ + if ((share->password[0] == '\0')) + share->password= NULL; + } + + /* make sure there isn't an extra / or @ */ + if ((strchr(share->username, '/')) || (strchr(share->hostname, '@'))) + goto error; + + if (!(share->database= strchr(share->hostname, '/'))) + goto error; + *share->database++= '\0'; + + if ((share->sport= strchr(share->hostname, ':'))) + { + *share->sport++= '\0'; + if (share->sport[0] == '\0') + share->sport= NULL; + else + share->port= atoi(share->sport); + } + + if (!(share->table_name= strchr(share->database, '/'))) + goto error; + *share->table_name++= '\0'; + + share->table_name_length= strlen(share->table_name); + + /* make sure there's not an extra / */ + if ((strchr(share->table_name, '/'))) + goto error; + + if (share->hostname[0] == '\0') + share->hostname= NULL; + + } + if (!share->port) + { + if (!share->hostname || strcmp(share->hostname, my_localhost) == 0) + share->socket= (char *) MYSQL_UNIX_ADDR; + else + share->port= MYSQL_PORT; + } + + DBUG_PRINT("info", + ("scheme: %s username: %s password: %s hostname: %s " + "port: %d db: %s tablename: %s", + share->scheme, share->username, share->password, + share->hostname, share->port, share->database, + share->table_name)); + + DBUG_RETURN(0); + +error: + DBUG_RETURN(parse_url_error(share, table, error_num)); +} + +/***************************************************************************** +** FEDERATEDX tables +*****************************************************************************/ + +ha_federatedx::ha_federatedx(handlerton *hton, + TABLE_SHARE *table_arg) + :handler(hton, table_arg), + txn(0), io(0), stored_result(0) +{ + bzero(&bulk_insert, sizeof(bulk_insert)); +} + + +/* + Convert MySQL result set row to handler internal format + + SYNOPSIS + convert_row_to_internal_format() + record Byte pointer to record + row MySQL result set row from fetchrow() + result Result set to use + + DESCRIPTION + This method simply iterates through a row returned via fetchrow with + values from a successful SELECT , and then stores each column's value + in the field object via the field object pointer (pointing to the table's + array of field object pointers). This is how the handler needs the data + to be stored to then return results back to the user + + RETURN VALUE + 0 After fields have had field values stored from record +*/ + +uint ha_federatedx::convert_row_to_internal_format(uchar *record, + FEDERATEDX_IO_ROW *row, + FEDERATEDX_IO_RESULT *result) +{ + ulong *lengths; + Field **field; + int column= 0; + my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->write_set); + DBUG_ENTER("ha_federatedx::convert_row_to_internal_format"); + + lengths= io->fetch_lengths(result); + + for (field= table->field; *field; field++, column++) + { + /* + index variable to move us through the row at the + same iterative step as the field + */ + my_ptrdiff_t old_ptr; + old_ptr= (my_ptrdiff_t) (record - table->record[0]); + (*field)->move_field_offset(old_ptr); + if (io->is_column_null(row, column)) + (*field)->set_null(); + else + { + if (bitmap_is_set(table->read_set, (*field)->field_index)) + { + (*field)->set_notnull(); + (*field)->store(io->get_column_data(row, column), lengths[column], &my_charset_bin); + } + } + (*field)->move_field_offset(-old_ptr); + } + dbug_tmp_restore_column_map(table->write_set, old_map); + DBUG_RETURN(0); +} + +static bool emit_key_part_name(String *to, KEY_PART_INFO *part) +{ + DBUG_ENTER("emit_key_part_name"); + if (append_ident(to, part->field->field_name, + strlen(part->field->field_name), ident_quote_char)) + DBUG_RETURN(1); // Out of memory + DBUG_RETURN(0); +} + +static bool emit_key_part_element(String *to, KEY_PART_INFO *part, + bool needs_quotes, bool is_like, + const uchar *ptr, uint len) +{ + Field *field= part->field; + DBUG_ENTER("emit_key_part_element"); + + if (needs_quotes && to->append(STRING_WITH_LEN("'"))) + DBUG_RETURN(1); + + if (part->type == HA_KEYTYPE_BIT) + { + char buff[STRING_BUFFER_USUAL_SIZE], *buf= buff; + + *buf++= '0'; + *buf++= 'x'; + buf= octet2hex(buf, (char*) ptr, len); + if (to->append((char*) buff, (uint)(buf - buff))) + DBUG_RETURN(1); + } + else if (part->key_part_flag & HA_BLOB_PART) + { + String blob; + uint blob_length= uint2korr(ptr); + blob.set_quick((char*) ptr+HA_KEY_BLOB_LENGTH, + blob_length, &my_charset_bin); + if (append_escaped(to, &blob)) + DBUG_RETURN(1); + } + else if (part->key_part_flag & HA_VAR_LENGTH_PART) + { + String varchar; + uint var_length= uint2korr(ptr); + varchar.set_quick((char*) ptr+HA_KEY_BLOB_LENGTH, + var_length, &my_charset_bin); + if (append_escaped(to, &varchar)) + DBUG_RETURN(1); + } + else + { + char strbuff[MAX_FIELD_WIDTH]; + String str(strbuff, sizeof(strbuff), part->field->charset()), *res; + + res= field->val_str(&str, ptr); + + if (field->result_type() == STRING_RESULT) + { + if (append_escaped(to, res)) + DBUG_RETURN(1); + } + else if (to->append(res->ptr(), res->length())) + DBUG_RETURN(1); + } + + if (is_like && to->append(STRING_WITH_LEN("%"))) + DBUG_RETURN(1); + + if (needs_quotes && to->append(STRING_WITH_LEN("'"))) + DBUG_RETURN(1); + + DBUG_RETURN(0); +} + +/* + Create a WHERE clause based off of values in keys + Note: This code was inspired by key_copy from key.cc + + SYNOPSIS + create_where_from_key () + to String object to store WHERE clause + key_info KEY struct pointer + key byte pointer containing key + key_length length of key + range_type 0 - no range, 1 - min range, 2 - max range + (see enum range_operation) + + DESCRIPTION + Using iteration through all the keys via a KEY_PART_INFO pointer, + This method 'extracts' the value of each key in the byte pointer + *key, and for each key found, constructs an appropriate WHERE clause + + RETURN VALUE + 0 After all keys have been accounted for to create the WHERE clause + 1 No keys found + + Range flags Table per Timour: + + ----------------- + - start_key: + * ">" -> HA_READ_AFTER_KEY + * ">=" -> HA_READ_KEY_OR_NEXT + * "=" -> HA_READ_KEY_EXACT + + - end_key: + * "<" -> HA_READ_BEFORE_KEY + * "<=" -> HA_READ_AFTER_KEY + + records_in_range: + ----------------- + - start_key: + * ">" -> HA_READ_AFTER_KEY + * ">=" -> HA_READ_KEY_EXACT + * "=" -> HA_READ_KEY_EXACT + + - end_key: + * "<" -> HA_READ_BEFORE_KEY + * "<=" -> HA_READ_AFTER_KEY + * "=" -> HA_READ_AFTER_KEY + +0 HA_READ_KEY_EXACT, Find first record else error +1 HA_READ_KEY_OR_NEXT, Record or next record +2 HA_READ_KEY_OR_PREV, Record or previous +3 HA_READ_AFTER_KEY, Find next rec. after key-record +4 HA_READ_BEFORE_KEY, Find next rec. before key-record +5 HA_READ_PREFIX, Key which as same prefix +6 HA_READ_PREFIX_LAST, Last key with the same prefix +7 HA_READ_PREFIX_LAST_OR_PREV, Last or prev key with the same prefix + +Flags that I've found: + +id, primary key, varchar + +id = 'ccccc' +records_in_range: start_key 0 end_key 3 +read_range_first: start_key 0 end_key NULL + +id > 'ccccc' +records_in_range: start_key 3 end_key NULL +read_range_first: start_key 3 end_key NULL + +id < 'ccccc' +records_in_range: start_key NULL end_key 4 +read_range_first: start_key NULL end_key 4 + +id <= 'ccccc' +records_in_range: start_key NULL end_key 3 +read_range_first: start_key NULL end_key 3 + +id >= 'ccccc' +records_in_range: start_key 0 end_key NULL +read_range_first: start_key 1 end_key NULL + +id like 'cc%cc' +records_in_range: start_key 0 end_key 3 +read_range_first: start_key 1 end_key 3 + +id > 'aaaaa' and id < 'ccccc' +records_in_range: start_key 3 end_key 4 +read_range_first: start_key 3 end_key 4 + +id >= 'aaaaa' and id < 'ccccc'; +records_in_range: start_key 0 end_key 4 +read_range_first: start_key 1 end_key 4 + +id >= 'aaaaa' and id <= 'ccccc'; +records_in_range: start_key 0 end_key 3 +read_range_first: start_key 1 end_key 3 + +id > 'aaaaa' and id <= 'ccccc'; +records_in_range: start_key 3 end_key 3 +read_range_first: start_key 3 end_key 3 + +numeric keys: + +id = 4 +index_read_idx: start_key 0 end_key NULL + +id > 4 +records_in_range: start_key 3 end_key NULL +read_range_first: start_key 3 end_key NULL + +id >= 4 +records_in_range: start_key 0 end_key NULL +read_range_first: start_key 1 end_key NULL + +id < 4 +records_in_range: start_key NULL end_key 4 +read_range_first: start_key NULL end_key 4 + +id <= 4 +records_in_range: start_key NULL end_key 3 +read_range_first: start_key NULL end_key 3 + +id like 4 +full table scan, select * from + +id > 2 and id < 8 +records_in_range: start_key 3 end_key 4 +read_range_first: start_key 3 end_key 4 + +id >= 2 and id < 8 +records_in_range: start_key 0 end_key 4 +read_range_first: start_key 1 end_key 4 + +id >= 2 and id <= 8 +records_in_range: start_key 0 end_key 3 +read_range_first: start_key 1 end_key 3 + +id > 2 and id <= 8 +records_in_range: start_key 3 end_key 3 +read_range_first: start_key 3 end_key 3 + +multi keys (id int, name varchar, other varchar) + +id = 1; +records_in_range: start_key 0 end_key 3 +read_range_first: start_key 0 end_key NULL + +id > 4; +id > 2 and name = '333'; remote: id > 2 +id > 2 and name > '333'; remote: id > 2 +id > 2 and name > '333' and other < 'ddd'; remote: id > 2 no results +id > 2 and name >= '333' and other < 'ddd'; remote: id > 2 1 result +id >= 4 and name = 'eric was here' and other > 'eeee'; +records_in_range: start_key 3 end_key NULL +read_range_first: start_key 3 end_key NULL + +id >= 4; +id >= 2 and name = '333' and other < 'ddd'; +remote: `id` >= 2 AND `name` >= '333'; +records_in_range: start_key 0 end_key NULL +read_range_first: start_key 1 end_key NULL + +id < 4; +id < 3 and name = '222' and other <= 'ccc'; remote: id < 3 +records_in_range: start_key NULL end_key 4 +read_range_first: start_key NULL end_key 4 + +id <= 4; +records_in_range: start_key NULL end_key 3 +read_range_first: start_key NULL end_key 3 + +id like 4; +full table scan + +id > 2 and id < 4; +records_in_range: start_key 3 end_key 4 +read_range_first: start_key 3 end_key 4 + +id >= 2 and id < 4; +records_in_range: start_key 0 end_key 4 +read_range_first: start_key 1 end_key 4 + +id >= 2 and id <= 4; +records_in_range: start_key 0 end_key 3 +read_range_first: start_key 1 end_key 3 + +id > 2 and id <= 4; +id = 6 and name = 'eric was here' and other > 'eeee'; +remote: (`id` > 6 AND `name` > 'eric was here' AND `other` > 'eeee') +AND (`id` <= 6) AND ( AND `name` <= 'eric was here') +no results +records_in_range: start_key 3 end_key 3 +read_range_first: start_key 3 end_key 3 + +Summary: + +* If the start key flag is 0 the max key flag shouldn't even be set, + and if it is, the query produced would be invalid. +* Multipart keys, even if containing some or all numeric columns, + are treated the same as non-numeric keys + + If the query is " = " (quotes or not): + - records in range start key flag HA_READ_KEY_EXACT, + end key flag HA_READ_AFTER_KEY (incorrect) + - any other: start key flag HA_READ_KEY_OR_NEXT, + end key flag HA_READ_AFTER_KEY (correct) + +* 'like' queries (of key) + - Numeric, full table scan + - Non-numeric + records_in_range: start_key 0 end_key 3 + other : start_key 1 end_key 3 + +* If the key flag is HA_READ_AFTER_KEY: + if start_key, append > + if end_key, append <= + +* If create_where_key was called by records_in_range: + + - if the key is numeric: + start key flag is 0 when end key is NULL, end key flag is 3 or 4 + - if create_where_key was called by any other function: + start key flag is 1 when end key is NULL, end key flag is 3 or 4 + - if the key is non-numeric, or multipart + When the query is an exact match, the start key flag is 0, + end key flag is 3 for what should be a no-range condition where + you should have 0 and max key NULL, which it is if called by + read_range_first + +Conclusion: + +1. Need logic to determin if a key is min or max when the flag is +HA_READ_AFTER_KEY, and handle appending correct operator accordingly + +2. Need a boolean flag to pass to create_where_from_key, used in the +switch statement. Add 1 to the flag if: + - start key flag is HA_READ_KEY_EXACT and the end key is NULL + +*/ + +bool ha_federatedx::create_where_from_key(String *to, + KEY *key_info, + const key_range *start_key, + const key_range *end_key, + bool from_records_in_range, + bool eq_range) +{ + bool both_not_null= + (start_key != NULL && end_key != NULL) ? TRUE : FALSE; + const uchar *ptr; + uint remainder, length; + char tmpbuff[FEDERATEDX_QUERY_BUFFER_SIZE]; + String tmp(tmpbuff, sizeof(tmpbuff), system_charset_info); + const key_range *ranges[2]= { start_key, end_key }; + my_bitmap_map *old_map; + DBUG_ENTER("ha_federatedx::create_where_from_key"); + + tmp.length(0); + if (start_key == NULL && end_key == NULL) + DBUG_RETURN(1); + + old_map= dbug_tmp_use_all_columns(table, table->write_set); + for (uint i= 0; i <= 1; i++) + { + bool needs_quotes; + KEY_PART_INFO *key_part; + if (ranges[i] == NULL) + continue; + + if (both_not_null) + { + if (i > 0) + tmp.append(STRING_WITH_LEN(") AND (")); + else + tmp.append(STRING_WITH_LEN(" (")); + } + + for (key_part= key_info->key_part, + remainder= key_info->key_parts, + length= ranges[i]->length, + ptr= ranges[i]->key; ; + remainder--, + key_part++) + { + Field *field= key_part->field; + uint store_length= key_part->store_length; + uint part_length= min(store_length, length); + needs_quotes= field->str_needs_quotes(); + DBUG_DUMP("key, start of loop", ptr, length); + + if (key_part->null_bit) + { + if (*ptr++) + { + /* + We got "IS [NOT] NULL" condition against nullable column. We + distinguish between "IS NOT NULL" and "IS NULL" by flag. For + "IS NULL", flag is set to HA_READ_KEY_EXACT. + */ + if (emit_key_part_name(&tmp, key_part) || + tmp.append(ranges[i]->flag == HA_READ_KEY_EXACT ? + " IS NULL " : " IS NOT NULL ")) + goto err; + /* + We need to adjust pointer and length to be prepared for next + key part. As well as check if this was last key part. + */ + goto prepare_for_next_key_part; + } + } + + if (tmp.append(STRING_WITH_LEN(" ("))) + goto err; + + switch (ranges[i]->flag) { + case HA_READ_KEY_EXACT: + DBUG_PRINT("info", ("federatedx HA_READ_KEY_EXACT %d", i)); + if (store_length >= length || + !needs_quotes || + key_part->type == HA_KEYTYPE_BIT || + field->result_type() != STRING_RESULT) + { + if (emit_key_part_name(&tmp, key_part)) + goto err; + + if (from_records_in_range) + { + if (tmp.append(STRING_WITH_LEN(" >= "))) + goto err; + } + else + { + if (tmp.append(STRING_WITH_LEN(" = "))) + goto err; + } + + if (emit_key_part_element(&tmp, key_part, needs_quotes, 0, ptr, + part_length)) + goto err; + } + else + { + /* LIKE */ + if (emit_key_part_name(&tmp, key_part) || + tmp.append(STRING_WITH_LEN(" LIKE ")) || + emit_key_part_element(&tmp, key_part, needs_quotes, 1, ptr, + part_length)) + goto err; + } + break; + case HA_READ_AFTER_KEY: + if (eq_range) + { + if (tmp.append("1=1")) // Dummy + goto err; + break; + } + DBUG_PRINT("info", ("federatedx HA_READ_AFTER_KEY %d", i)); + if (store_length >= length) /* end key */ + { + if (emit_key_part_name(&tmp, key_part)) + goto err; + + if (i > 0) /* end key */ + { + if (tmp.append(STRING_WITH_LEN(" <= "))) + goto err; + } + else /* start key */ + { + if (tmp.append(STRING_WITH_LEN(" > "))) + goto err; + } + + if (emit_key_part_element(&tmp, key_part, needs_quotes, 0, ptr, + part_length)) + { + goto err; + } + break; + } + case HA_READ_KEY_OR_NEXT: + DBUG_PRINT("info", ("federatedx HA_READ_KEY_OR_NEXT %d", i)); + if (emit_key_part_name(&tmp, key_part) || + tmp.append(STRING_WITH_LEN(" >= ")) || + emit_key_part_element(&tmp, key_part, needs_quotes, 0, ptr, + part_length)) + goto err; + break; + case HA_READ_BEFORE_KEY: + DBUG_PRINT("info", ("federatedx HA_READ_BEFORE_KEY %d", i)); + if (store_length >= length) + { + if (emit_key_part_name(&tmp, key_part) || + tmp.append(STRING_WITH_LEN(" < ")) || + emit_key_part_element(&tmp, key_part, needs_quotes, 0, ptr, + part_length)) + goto err; + break; + } + case HA_READ_KEY_OR_PREV: + DBUG_PRINT("info", ("federatedx HA_READ_KEY_OR_PREV %d", i)); + if (emit_key_part_name(&tmp, key_part) || + tmp.append(STRING_WITH_LEN(" <= ")) || + emit_key_part_element(&tmp, key_part, needs_quotes, 0, ptr, + part_length)) + goto err; + break; + default: + DBUG_PRINT("info",("cannot handle flag %d", ranges[i]->flag)); + goto err; + } + if (tmp.append(STRING_WITH_LEN(") "))) + goto err; + +prepare_for_next_key_part: + if (store_length >= length) + break; + DBUG_PRINT("info", ("remainder %d", remainder)); + DBUG_ASSERT(remainder > 1); + length-= store_length; + /* + For nullable columns, null-byte is already skipped before, that is + ptr was incremented by 1. Since store_length still counts null-byte, + we need to subtract 1 from store_length. + */ + ptr+= store_length - test(key_part->null_bit); + if (tmp.append(STRING_WITH_LEN(" AND "))) + goto err; + + DBUG_PRINT("info", + ("create_where_from_key WHERE clause: %s", + tmp.c_ptr_quick())); + } + } + dbug_tmp_restore_column_map(table->write_set, old_map); + + if (both_not_null) + if (tmp.append(STRING_WITH_LEN(") "))) + DBUG_RETURN(1); + + if (to->append(STRING_WITH_LEN(" WHERE "))) + DBUG_RETURN(1); + + if (to->append(tmp)) + DBUG_RETURN(1); + + DBUG_RETURN(0); + +err: + dbug_tmp_restore_column_map(table->write_set, old_map); + DBUG_RETURN(1); +} + +static void fill_server(MEM_ROOT *mem_root, FEDERATEDX_SERVER *server, + FEDERATEDX_SHARE *share, CHARSET_INFO *table_charset) +{ + char buffer[STRING_BUFFER_USUAL_SIZE]; + String key(buffer, sizeof(buffer), &my_charset_bin); + String scheme(share->scheme, &my_charset_latin1); + String hostname(share->hostname, &my_charset_latin1); + String database(share->database, system_charset_info); + String username(share->username, system_charset_info); + String socket(share->socket ? share->socket : "", files_charset_info); + String password(share->password ? share->password : "", &my_charset_bin); + DBUG_ENTER("fill_server"); + + /* Do some case conversions */ + scheme.reserve(scheme.length()); + scheme.length(my_casedn_str(&my_charset_latin1, scheme.c_ptr_safe())); + + hostname.reserve(hostname.length()); + hostname.length(my_casedn_str(&my_charset_latin1, hostname.c_ptr_safe())); + + if (lower_case_table_names) + { + database.reserve(database.length()); + database.length(my_casedn_str(system_charset_info, database.c_ptr_safe())); + } + + if (lower_case_file_system && socket.length()) + { + socket.reserve(socket.length()); + socket.length(my_casedn_str(files_charset_info, socket.c_ptr_safe())); + } + + /* start with all bytes zeroed */ + bzero(server, sizeof(*server)); + + key.length(0); + key.reserve(scheme.length() + hostname.length() + database.length() + + socket.length() + username.length() + password.length() + + sizeof(int) + 8); + key.append(scheme); + key.q_append('\0'); + server->hostname= (const char *) (intptr) key.length(); + key.append(hostname); + key.q_append('\0'); + server->database= (const char *) (intptr) key.length(); + key.append(database); + key.q_append('\0'); + key.q_append((uint32) share->port); + server->socket= (const char *) (intptr) key.length(); + key.append(socket); + key.q_append('\0'); + server->username= (const char *) (intptr) key.length(); + key.append(username); + key.q_append('\0'); + server->password= (const char *) (intptr) key.length(); + key.append(password); + + server->key_length= key.length(); + server->key= (uchar *) memdup_root(mem_root, key.ptr(), key.length()+1); + + /* pointer magic */ + server->scheme+= (intptr) server->key; + server->hostname+= (intptr) server->key; + server->database+= (intptr) server->key; + server->username+= (intptr) server->key; + server->password+= (intptr) server->key; + server->socket+= (intptr) server->key; + server->port= share->port; + + if (!share->socket) + server->socket= NULL; + if (!share->password) + server->password= NULL; + + if (table_charset) + server->csname= strdup_root(mem_root, table_charset->csname); + + DBUG_VOID_RETURN; +} + + +static FEDERATEDX_SERVER *get_server(FEDERATEDX_SHARE *share, TABLE *table) +{ + FEDERATEDX_SERVER *server= NULL, tmp_server; + MEM_ROOT mem_root; + char buffer[STRING_BUFFER_USUAL_SIZE]; + String key(buffer, sizeof(buffer), &my_charset_bin); + String scheme(share->scheme, &my_charset_latin1); + String hostname(share->hostname, &my_charset_latin1); + String database(share->database, system_charset_info); + String username(share->username, system_charset_info); + String socket(share->socket ? share->socket : "", files_charset_info); + String password(share->password ? share->password : "", &my_charset_bin); + DBUG_ENTER("ha_federated.cc::get_server"); + + safe_mutex_assert_owner(&federatedx_mutex); + + init_alloc_root(&mem_root, 4096, 4096); + + fill_server(&mem_root, &tmp_server, share, table ? table->s->table_charset : 0); + + if (!(server= (FEDERATEDX_SERVER *) hash_search(&federatedx_open_servers, + tmp_server.key, + tmp_server.key_length))) + { + if (!table || !tmp_server.csname) + goto error; + + if (!(server= (FEDERATEDX_SERVER *) memdup_root(&mem_root, + (char *) &tmp_server, + sizeof(*server)))) + goto error; + + server->mem_root= mem_root; + + if (my_hash_insert(&federatedx_open_servers, (uchar*) server)) + goto error; + + pthread_mutex_init(&server->mutex, MY_MUTEX_INIT_FAST); + } + else + free_root(&mem_root, MYF(0)); /* prevents memory leak */ + + server->use_count++; + + DBUG_RETURN(server); +error: + free_root(&mem_root, MYF(0)); + DBUG_RETURN(NULL); +} + + +/* + Example of simple lock controls. The "share" it creates is structure we will + pass to each federatedx handler. Do you have to have one of these? Well, you + have pieces that are used for locking, and they are needed to function. +*/ + +static FEDERATEDX_SHARE *get_share(const char *table_name, TABLE *table) +{ + char query_buffer[FEDERATEDX_QUERY_BUFFER_SIZE]; + Field **field; + String query(query_buffer, sizeof(query_buffer), &my_charset_bin); + FEDERATEDX_SHARE *share= NULL, tmp_share; + MEM_ROOT mem_root; + DBUG_ENTER("ha_federatedx.cc::get_share"); + + /* + In order to use this string, we must first zero it's length, + or it will contain garbage + */ + query.length(0); + + bzero(&tmp_share, sizeof(tmp_share)); + init_alloc_root(&mem_root, 256, 0); + + pthread_mutex_lock(&federatedx_mutex); + + tmp_share.share_key= table_name; + tmp_share.share_key_length= strlen(table_name); + if (parse_url(&mem_root, &tmp_share, table, 0)) + goto error; + + /* TODO: change tmp_share.scheme to LEX_STRING object */ + if (!(share= (FEDERATEDX_SHARE *) hash_search(&federatedx_open_tables, + (uchar*) tmp_share.share_key, + tmp_share. + share_key_length))) + { + query.set_charset(system_charset_info); + query.append(STRING_WITH_LEN("SELECT ")); + for (field= table->field; *field; field++) + { + append_ident(&query, (*field)->field_name, + strlen((*field)->field_name), ident_quote_char); + query.append(STRING_WITH_LEN(", ")); + } + /* chops off trailing comma */ + query.length(query.length() - sizeof_trailing_comma); + + query.append(STRING_WITH_LEN(" FROM ")); + + append_ident(&query, tmp_share.table_name, + tmp_share.table_name_length, ident_quote_char); + + if (!(share= (FEDERATEDX_SHARE *) memdup_root(&mem_root, (char*)&tmp_share, sizeof(*share))) || + !(share->select_query= (char*) strmake_root(&mem_root, query.ptr(), query.length() + 1))) + goto error; + + share->mem_root= mem_root; + + DBUG_PRINT("info", + ("share->select_query %s", share->select_query)); + + if (!(share->s= get_server(share, table))) + goto error; + + if (my_hash_insert(&federatedx_open_tables, (uchar*) share)) + goto error; + thr_lock_init(&share->lock); + } + else + free_root(&mem_root, MYF(0)); /* prevents memory leak */ + + share->use_count++; + pthread_mutex_unlock(&federatedx_mutex); + + DBUG_RETURN(share); + +error: + pthread_mutex_unlock(&federatedx_mutex); + free_root(&mem_root, MYF(0)); + DBUG_RETURN(NULL); +} + + +static int free_server(federatedx_txn *txn, FEDERATEDX_SERVER *server) +{ + bool destroy; + DBUG_ENTER("free_server"); + + pthread_mutex_lock(&federatedx_mutex); + if ((destroy= !--server->use_count)) + hash_delete(&federatedx_open_servers, (uchar*) server); + pthread_mutex_unlock(&federatedx_mutex); + + if (destroy) + { + MEM_ROOT mem_root; + + txn->close(server); + + DBUG_ASSERT(server->io_count == 0); + + pthread_mutex_destroy(&server->mutex); + mem_root= server->mem_root; + free_root(&mem_root, MYF(0)); + } + + DBUG_RETURN(0); +} + + +/* + Free lock controls. We call this whenever we close a table. + If the table had the last reference to the share then we + free memory associated with it. +*/ + +static int free_share(federatedx_txn *txn, FEDERATEDX_SHARE *share) +{ + bool destroy; + DBUG_ENTER("free_share"); + + pthread_mutex_lock(&federatedx_mutex); + if ((destroy= !--share->use_count)) + hash_delete(&federatedx_open_tables, (uchar*) share); + pthread_mutex_unlock(&federatedx_mutex); + + if (destroy) + { + MEM_ROOT mem_root; + FEDERATEDX_SERVER *server= share->s; + + thr_lock_delete(&share->lock); + + mem_root= share->mem_root; + free_root(&mem_root, MYF(0)); + + free_server(txn, server); + } + + DBUG_RETURN(0); +} + + +ha_rows ha_federatedx::records_in_range(uint inx, key_range *start_key, + key_range *end_key) +{ + /* + + We really want indexes to be used as often as possible, therefore + we just need to hard-code the return value to a very low number to + force the issue + +*/ + DBUG_ENTER("ha_federatedx::records_in_range"); + DBUG_RETURN(FEDERATEDX_RECORDS_IN_RANGE); +} +/* + If frm_error() is called then we will use this to to find out + what file extentions exist for the storage engine. This is + also used by the default rename_table and delete_table method + in handler.cc. +*/ + +const char **ha_federatedx::bas_ext() const +{ + static const char *ext[]= + { + NullS + }; + return ext; +} + + +federatedx_txn *ha_federatedx::get_txn(THD *thd, bool no_create) +{ + federatedx_txn **txnp= (federatedx_txn **) ha_data(thd); + if (!*txnp && !no_create) + *txnp= new federatedx_txn(); + return *txnp; +} + + +int ha_federatedx::disconnect(handlerton *hton, MYSQL_THD thd) +{ + federatedx_txn *txn= (federatedx_txn *) thd_get_ha_data(thd, hton); + delete txn; + return 0; +} + + +/* + Used for opening tables. The name will be the name of the file. + A table is opened when it needs to be opened. For instance + when a request comes in for a select on the table (tables are not + open and closed for each request, they are cached). + + Called from handler.cc by handler::ha_open(). The server opens + all tables by calling ha_open() which then calls the handler + specific open(). +*/ + +int ha_federatedx::open(const char *name, int mode, uint test_if_locked) +{ + int error; + THD *thd= current_thd; + DBUG_ENTER("ha_federatedx::open"); + + if (!(share= get_share(name, table))) + DBUG_RETURN(1); + thr_lock_data_init(&share->lock, &lock, NULL); + + DBUG_ASSERT(io == NULL); + + txn= get_txn(thd); + + if ((error= txn->acquire(share, TRUE, &io))) + { + free_share(txn, share); + DBUG_RETURN(error); + } + + txn->release(&io); + + ref_length= (table->s->primary_key != MAX_KEY ? + table->key_info[table->s->primary_key].key_length : + table->s->reclength); + DBUG_PRINT("info", ("ref_length: %u", ref_length)); + + reset(); + + DBUG_RETURN(0); +} + + +/* + Closes a table. We call the free_share() function to free any resources + that we have allocated in the "shared" structure. + + Called from sql_base.cc, sql_select.cc, and table.cc. + In sql_select.cc it is only used to close up temporary tables or during + the process where a temporary table is converted over to being a + myisam table. + For sql_base.cc look at close_data_tables(). +*/ + +int ha_federatedx::close(void) +{ + int retval, error; + THD *thd= current_thd; + DBUG_ENTER("ha_federatedx::close"); + + /* free the result set */ + if (stored_result) + retval= free_result(); + + /* Disconnect from mysql */ + if ((txn= get_txn(thd, true))) + txn->release(&io); + + DBUG_ASSERT(io == NULL); + + if ((error= free_share(txn, share))) + retval= error; + DBUG_RETURN(retval); +} + +/* + + Checks if a field in a record is SQL NULL. + + SYNOPSIS + field_in_record_is_null() + table TABLE pointer, MySQL table object + field Field pointer, MySQL field object + record char pointer, contains record + + DESCRIPTION + This method uses the record format information in table to track + the null bit in record. + + RETURN VALUE + 1 if NULL + 0 otherwise +*/ + +static inline uint field_in_record_is_null(TABLE *table, + Field *field, + char *record) +{ + int null_offset; + DBUG_ENTER("ha_federatedx::field_in_record_is_null"); + + if (!field->null_ptr) + DBUG_RETURN(0); + + null_offset= (uint) ((char*)field->null_ptr - (char*)table->record[0]); + + if (record[null_offset] & field->null_bit) + DBUG_RETURN(1); + + DBUG_RETURN(0); +} + + +/** + @brief Construct the INSERT statement. + + @details This method will construct the INSERT statement and appends it to + the supplied query string buffer. + + @return + @retval FALSE No error + @retval TRUE Failure +*/ + +bool ha_federatedx::append_stmt_insert(String *query) +{ + char insert_buffer[FEDERATEDX_QUERY_BUFFER_SIZE]; + Field **field; + uint tmp_length; + bool added_field= FALSE; + + /* The main insert query string */ + String insert_string(insert_buffer, sizeof(insert_buffer), &my_charset_bin); + DBUG_ENTER("ha_federatedx::append_stmt_insert"); + + insert_string.length(0); + + if (replace_duplicates) + insert_string.append(STRING_WITH_LEN("REPLACE INTO ")); + else if (ignore_duplicates && !insert_dup_update) + insert_string.append(STRING_WITH_LEN("INSERT IGNORE INTO ")); + else + insert_string.append(STRING_WITH_LEN("INSERT INTO ")); + append_ident(&insert_string, share->table_name, share->table_name_length, + ident_quote_char); + tmp_length= insert_string.length(); + insert_string.append(STRING_WITH_LEN(" (")); + + /* + loop through the field pointer array, add any fields to both the values + list and the fields list that match the current query id + */ + for (field= table->field; *field; field++) + { + if (bitmap_is_set(table->write_set, (*field)->field_index)) + { + /* append the field name */ + append_ident(&insert_string, (*field)->field_name, + strlen((*field)->field_name), ident_quote_char); + + /* append commas between both fields and fieldnames */ + /* + unfortunately, we can't use the logic if *(fields + 1) to + make the following appends conditional as we don't know if the + next field is in the write set + */ + insert_string.append(STRING_WITH_LEN(", ")); + added_field= TRUE; + } + } + + if (added_field) + { + /* Remove trailing comma. */ + insert_string.length(insert_string.length() - sizeof_trailing_comma); + insert_string.append(STRING_WITH_LEN(") ")); + } + else + { + /* If there were no fields, we don't want to add a closing paren. */ + insert_string.length(tmp_length); + } + + insert_string.append(STRING_WITH_LEN(" VALUES ")); + + DBUG_RETURN(query->append(insert_string)); +} + + +/* + write_row() inserts a row. No extra() hint is given currently if a bulk load + is happeneding. buf() is a byte array of data. You can use the field + information to extract the data from the native byte array type. + Example of this would be: + for (Field **field=table->field ; *field ; field++) + { + ... + } + + Called from item_sum.cc, item_sum.cc, sql_acl.cc, sql_insert.cc, + sql_insert.cc, sql_select.cc, sql_table.cc, sql_udf.cc, and sql_update.cc. +*/ + +int ha_federatedx::write_row(uchar *buf) +{ + char values_buffer[FEDERATEDX_QUERY_BUFFER_SIZE]; + char insert_field_value_buffer[STRING_BUFFER_USUAL_SIZE]; + Field **field; + uint tmp_length; + int error= 0; + bool use_bulk_insert; + bool auto_increment_update_required= (table->next_number_field != NULL); + + /* The string containing the values to be added to the insert */ + String values_string(values_buffer, sizeof(values_buffer), &my_charset_bin); + /* The actual value of the field, to be added to the values_string */ + String insert_field_value_string(insert_field_value_buffer, + sizeof(insert_field_value_buffer), + &my_charset_bin); + my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->read_set); + DBUG_ENTER("ha_federatedx::write_row"); + + values_string.length(0); + insert_field_value_string.length(0); + ha_statistic_increment(&SSV::ha_write_count); + if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT) + table->timestamp_field->set_time(); + + /* + start both our field and field values strings + We must disable multi-row insert for "INSERT...ON DUPLICATE KEY UPDATE" + Ignore duplicates is always true when insert_dup_update is true. + When replace_duplicates == TRUE, we can safely enable multi-row insert. + When performing multi-row insert, we only collect the columns values for + the row. The start of the statement is only created when the first + row is copied in to the bulk_insert string. + */ + if (!(use_bulk_insert= bulk_insert.str && + (!insert_dup_update || replace_duplicates))) + append_stmt_insert(&values_string); + + values_string.append(STRING_WITH_LEN(" (")); + tmp_length= values_string.length(); + + /* + loop through the field pointer array, add any fields to both the values + list and the fields list that is part of the write set + */ + for (field= table->field; *field; field++) + { + if (bitmap_is_set(table->write_set, (*field)->field_index)) + { + if ((*field)->is_null()) + values_string.append(STRING_WITH_LEN(" NULL ")); + else + { + bool needs_quote= (*field)->str_needs_quotes(); + (*field)->val_str(&insert_field_value_string); + if (needs_quote) + values_string.append(value_quote_char); + insert_field_value_string.print(&values_string); + if (needs_quote) + values_string.append(value_quote_char); + + insert_field_value_string.length(0); + } + + /* append commas between both fields and fieldnames */ + /* + unfortunately, we can't use the logic if *(fields + 1) to + make the following appends conditional as we don't know if the + next field is in the write set + */ + values_string.append(STRING_WITH_LEN(", ")); + } + } + dbug_tmp_restore_column_map(table->read_set, old_map); + + /* + if there were no fields, we don't want to add a closing paren + AND, we don't want to chop off the last char '(' + insert will be "INSERT INTO t1 VALUES ();" + */ + if (values_string.length() > tmp_length) + { + /* chops off trailing comma */ + values_string.length(values_string.length() - sizeof_trailing_comma); + } + /* we always want to append this, even if there aren't any fields */ + values_string.append(STRING_WITH_LEN(") ")); + + if ((error= txn->acquire(share, FALSE, &io))) + DBUG_RETURN(error); + + if (use_bulk_insert) + { + /* + Send the current bulk insert out if appending the current row would + cause the statement to overflow the packet size, otherwise set + auto_increment_update_required to FALSE as no query was executed. + */ + if (bulk_insert.length + values_string.length() + bulk_padding > + io->max_query_size() && bulk_insert.length) + { + error= io->query(bulk_insert.str, bulk_insert.length); + bulk_insert.length= 0; + } + else + auto_increment_update_required= FALSE; + + if (bulk_insert.length == 0) + { + char insert_buffer[FEDERATEDX_QUERY_BUFFER_SIZE]; + String insert_string(insert_buffer, sizeof(insert_buffer), + &my_charset_bin); + insert_string.length(0); + append_stmt_insert(&insert_string); + dynstr_append_mem(&bulk_insert, insert_string.ptr(), + insert_string.length()); + } + else + dynstr_append_mem(&bulk_insert, ",", 1); + + dynstr_append_mem(&bulk_insert, values_string.ptr(), + values_string.length()); + } + else + { + error= io->query(values_string.ptr(), values_string.length()); + } + + if (error) + { + DBUG_RETURN(stash_remote_error()); + } + /* + If the table we've just written a record to contains an auto_increment + field, then store the last_insert_id() value from the foreign server + */ + if (auto_increment_update_required) + { + update_auto_increment(); + + /* mysql_insert() uses this for protocol return value */ + table->next_number_field->store(stats.auto_increment_value, 1); + } + + DBUG_RETURN(0); +} + + +/** + @brief Prepares the storage engine for bulk inserts. + + @param[in] rows estimated number of rows in bulk insert + or 0 if unknown. + + @details Initializes memory structures required for bulk insert. +*/ + +void ha_federatedx::start_bulk_insert(ha_rows rows) +{ + uint page_size; + DBUG_ENTER("ha_federatedx::start_bulk_insert"); + + dynstr_free(&bulk_insert); + + /** + We don't bother with bulk-insert semantics when the estimated rows == 1 + The rows value will be 0 if the server does not know how many rows + would be inserted. This can occur when performing INSERT...SELECT + */ + + if (rows == 1) + DBUG_VOID_RETURN; + + /* + Make sure we have an open connection so that we know the + maximum packet size. + */ + if (txn->acquire(share, FALSE, &io)) + DBUG_VOID_RETURN; + + page_size= (uint) my_getpagesize(); + + if (init_dynamic_string(&bulk_insert, NULL, page_size, page_size)) + DBUG_VOID_RETURN; + + bulk_insert.length= 0; + DBUG_VOID_RETURN; +} + + +/** + @brief End bulk insert. + + @details This method will send any remaining rows to the remote server. + Finally, it will deinitialize the bulk insert data structure. + + @return Operation status + @retval 0 No error + @retval != 0 Error occured at remote server. Also sets my_errno. +*/ + +int ha_federatedx::end_bulk_insert(bool abort) +{ + int error= 0; + DBUG_ENTER("ha_federatedx::end_bulk_insert"); + + if (bulk_insert.str && bulk_insert.length && !abort) + { + if ((error= txn->acquire(share, FALSE, &io))) + DBUG_RETURN(error); + if (io->query(bulk_insert.str, bulk_insert.length)) + error= stash_remote_error(); + else + if (table->next_number_field) + update_auto_increment(); + } + + dynstr_free(&bulk_insert); + + DBUG_RETURN(my_errno= error); +} + + +/* + ha_federatedx::update_auto_increment + + This method ensures that last_insert_id() works properly. What it simply does + is calls last_insert_id() on the foreign database immediately after insert + (if the table has an auto_increment field) and sets the insert id via + thd->insert_id(ID)). +*/ +void ha_federatedx::update_auto_increment(void) +{ + THD *thd= current_thd; + DBUG_ENTER("ha_federatedx::update_auto_increment"); + + ha_federatedx::info(HA_STATUS_AUTO); + thd->first_successful_insert_id_in_cur_stmt= + stats.auto_increment_value; + DBUG_PRINT("info",("last_insert_id: %ld", (long) stats.auto_increment_value)); + + DBUG_VOID_RETURN; +} + +int ha_federatedx::optimize(THD* thd, HA_CHECK_OPT* check_opt) +{ + int error= 0; + char query_buffer[STRING_BUFFER_USUAL_SIZE]; + String query(query_buffer, sizeof(query_buffer), &my_charset_bin); + DBUG_ENTER("ha_federatedx::optimize"); + + query.length(0); + + query.set_charset(system_charset_info); + query.append(STRING_WITH_LEN("OPTIMIZE TABLE ")); + append_ident(&query, share->table_name, share->table_name_length, + ident_quote_char); + + DBUG_ASSERT(txn == get_txn(thd)); + + if ((error= txn->acquire(share, FALSE, &io))) + DBUG_RETURN(error); + + if (io->query(query.ptr(), query.length())) + error= stash_remote_error(); + + DBUG_RETURN(error); +} + + +int ha_federatedx::repair(THD* thd, HA_CHECK_OPT* check_opt) +{ + int error= 0; + char query_buffer[STRING_BUFFER_USUAL_SIZE]; + String query(query_buffer, sizeof(query_buffer), &my_charset_bin); + DBUG_ENTER("ha_federatedx::repair"); + + query.length(0); + + query.set_charset(system_charset_info); + query.append(STRING_WITH_LEN("REPAIR TABLE ")); + append_ident(&query, share->table_name, share->table_name_length, + ident_quote_char); + if (check_opt->flags & T_QUICK) + query.append(STRING_WITH_LEN(" QUICK")); + if (check_opt->flags & T_EXTEND) + query.append(STRING_WITH_LEN(" EXTENDED")); + if (check_opt->sql_flags & TT_USEFRM) + query.append(STRING_WITH_LEN(" USE_FRM")); + + DBUG_ASSERT(txn == get_txn(thd)); + + if ((error= txn->acquire(share, FALSE, &io))) + DBUG_RETURN(error); + + if (io->query(query.ptr(), query.length())) + error= stash_remote_error(); + + DBUG_RETURN(error); +} + + +/* + Yes, update_row() does what you expect, it updates a row. old_data will have + the previous row record in it, while new_data will have the newest data in + it. + + Keep in mind that the server can do updates based on ordering if an ORDER BY + clause was used. Consecutive ordering is not guaranteed. + Currently new_data will not have an updated auto_increament record, or + and updated timestamp field. You can do these for federatedx by doing these: + if (table->timestamp_on_update_now) + update_timestamp(new_row+table->timestamp_on_update_now-1); + if (table->next_number_field && record == table->record[0]) + update_auto_increment(); + + Called from sql_select.cc, sql_acl.cc, sql_update.cc, and sql_insert.cc. +*/ + +int ha_federatedx::update_row(const uchar *old_data, uchar *new_data) +{ + /* + This used to control how the query was built. If there was a + primary key, the query would be built such that there was a where + clause with only that column as the condition. This is flawed, + because if we have a multi-part primary key, it would only use the + first part! We don't need to do this anyway, because + read_range_first will retrieve the correct record, which is what + is used to build the WHERE clause. We can however use this to + append a LIMIT to the end if there is NOT a primary key. Why do + this? Because we only are updating one record, and LIMIT enforces + this. + */ + bool has_a_primary_key= test(table->s->primary_key != MAX_KEY); + + /* + buffers for following strings + */ + char field_value_buffer[STRING_BUFFER_USUAL_SIZE]; + char update_buffer[FEDERATEDX_QUERY_BUFFER_SIZE]; + char where_buffer[FEDERATEDX_QUERY_BUFFER_SIZE]; + + /* Work area for field values */ + String field_value(field_value_buffer, sizeof(field_value_buffer), + &my_charset_bin); + /* stores the update query */ + String update_string(update_buffer, + sizeof(update_buffer), + &my_charset_bin); + /* stores the WHERE clause */ + String where_string(where_buffer, + sizeof(where_buffer), + &my_charset_bin); + uchar *record= table->record[0]; + int error; + DBUG_ENTER("ha_federatedx::update_row"); + /* + set string lengths to 0 to avoid misc chars in string + */ + field_value.length(0); + update_string.length(0); + where_string.length(0); + + if (ignore_duplicates) + update_string.append(STRING_WITH_LEN("UPDATE IGNORE ")); + else + update_string.append(STRING_WITH_LEN("UPDATE ")); + append_ident(&update_string, share->table_name, + share->table_name_length, ident_quote_char); + update_string.append(STRING_WITH_LEN(" SET ")); + + /* + In this loop, we want to match column names to values being inserted + (while building INSERT statement). + + Iterate through table->field (new data) and share->old_field (old_data) + using the same index to create an SQL UPDATE statement. New data is + used to create SET field=value and old data is used to create WHERE + field=oldvalue + */ + + for (Field **field= table->field; *field; field++) + { + if (bitmap_is_set(table->write_set, (*field)->field_index)) + { + uint field_name_length= strlen((*field)->field_name); + append_ident(&update_string, (*field)->field_name, field_name_length, + ident_quote_char); + update_string.append(STRING_WITH_LEN(" = ")); + + if ((*field)->is_null()) + update_string.append(STRING_WITH_LEN(" NULL ")); + else + { + /* otherwise = */ + my_bitmap_map *old_map= tmp_use_all_columns(table, table->read_set); + bool needs_quote= (*field)->str_needs_quotes(); + (*field)->val_str(&field_value); + if (needs_quote) + update_string.append(value_quote_char); + field_value.print(&update_string); + if (needs_quote) + update_string.append(value_quote_char); + field_value.length(0); + tmp_restore_column_map(table->read_set, old_map); + } + update_string.append(STRING_WITH_LEN(", ")); + } + + if (bitmap_is_set(table->read_set, (*field)->field_index)) + { + uint field_name_length= strlen((*field)->field_name); + append_ident(&where_string, (*field)->field_name, field_name_length, + ident_quote_char); + if (field_in_record_is_null(table, *field, (char*) old_data)) + where_string.append(STRING_WITH_LEN(" IS NULL ")); + else + { + bool needs_quote= (*field)->str_needs_quotes(); + where_string.append(STRING_WITH_LEN(" = ")); + (*field)->val_str(&field_value, + (old_data + (*field)->offset(record))); + if (needs_quote) + where_string.append(value_quote_char); + field_value.print(&where_string); + if (needs_quote) + where_string.append(value_quote_char); + field_value.length(0); + } + where_string.append(STRING_WITH_LEN(" AND ")); + } + } + + /* Remove last ', '. This works as there must be at least on updated field */ + update_string.length(update_string.length() - sizeof_trailing_comma); + + if (where_string.length()) + { + /* chop off trailing AND */ + where_string.length(where_string.length() - sizeof_trailing_and); + update_string.append(STRING_WITH_LEN(" WHERE ")); + update_string.append(where_string); + } + + /* + If this table has not a primary key, then we could possibly + update multiple rows. We want to make sure to only update one! + */ + if (!has_a_primary_key) + update_string.append(STRING_WITH_LEN(" LIMIT 1")); + + if ((error= txn->acquire(share, FALSE, &io))) + DBUG_RETURN(error); + + if (io->query(update_string.ptr(), update_string.length())) + { + DBUG_RETURN(stash_remote_error()); + } + DBUG_RETURN(0); +} + +/* + This will delete a row. 'buf' will contain a copy of the row to be =deleted. + The server will call this right after the current row has been called (from + either a previous rnd_next() or index call). + If you keep a pointer to the last row or can access a primary key it will + make doing the deletion quite a bit easier. + Keep in mind that the server does no guarentee consecutive deletions. + ORDER BY clauses can be used. + + Called in sql_acl.cc and sql_udf.cc to manage internal table information. + Called in sql_delete.cc, sql_insert.cc, and sql_select.cc. In sql_select + it is used for removing duplicates while in insert it is used for REPLACE + calls. +*/ + +int ha_federatedx::delete_row(const uchar *buf) +{ + char delete_buffer[FEDERATEDX_QUERY_BUFFER_SIZE]; + char data_buffer[FEDERATEDX_QUERY_BUFFER_SIZE]; + String delete_string(delete_buffer, sizeof(delete_buffer), &my_charset_bin); + String data_string(data_buffer, sizeof(data_buffer), &my_charset_bin); + uint found= 0; + int error; + DBUG_ENTER("ha_federatedx::delete_row"); + + delete_string.length(0); + delete_string.append(STRING_WITH_LEN("DELETE FROM ")); + append_ident(&delete_string, share->table_name, + share->table_name_length, ident_quote_char); + delete_string.append(STRING_WITH_LEN(" WHERE ")); + + for (Field **field= table->field; *field; field++) + { + Field *cur_field= *field; + found++; + if (bitmap_is_set(table->read_set, cur_field->field_index)) + { + append_ident(&delete_string, (*field)->field_name, + strlen((*field)->field_name), ident_quote_char); + data_string.length(0); + if (cur_field->is_null()) + { + delete_string.append(STRING_WITH_LEN(" IS NULL ")); + } + else + { + bool needs_quote= cur_field->str_needs_quotes(); + delete_string.append(STRING_WITH_LEN(" = ")); + cur_field->val_str(&data_string); + if (needs_quote) + delete_string.append(value_quote_char); + data_string.print(&delete_string); + if (needs_quote) + delete_string.append(value_quote_char); + } + delete_string.append(STRING_WITH_LEN(" AND ")); + } + } + + // Remove trailing AND + delete_string.length(delete_string.length() - sizeof_trailing_and); + if (!found) + delete_string.length(delete_string.length() - sizeof_trailing_where); + + delete_string.append(STRING_WITH_LEN(" LIMIT 1")); + DBUG_PRINT("info", + ("Delete sql: %s", delete_string.c_ptr_quick())); + + if ((error= txn->acquire(share, FALSE, &io))) + DBUG_RETURN(error); + + if (io->query(delete_string.ptr(), delete_string.length())) + { + DBUG_RETURN(stash_remote_error()); + } + stats.deleted+= (ha_rows) io->affected_rows(); + stats.records-= (ha_rows) io->affected_rows(); + DBUG_PRINT("info", + ("rows deleted %ld rows deleted for all time %ld", + (long) io->affected_rows(), (long) stats.deleted)); + + DBUG_RETURN(0); +} + + +/* + Positions an index cursor to the index specified in the handle. Fetches the + row if available. If the key value is null, begin at the first key of the + index. This method, which is called in the case of an SQL statement having + a WHERE clause on a non-primary key index, simply calls index_read_idx. +*/ + +int ha_federatedx::index_read(uchar *buf, const uchar *key, + uint key_len, ha_rkey_function find_flag) +{ + DBUG_ENTER("ha_federatedx::index_read"); + + if (stored_result) + (void) free_result(); + DBUG_RETURN(index_read_idx_with_result_set(buf, active_index, key, + key_len, find_flag, + &stored_result)); +} + + +/* + Positions an index cursor to the index specified in key. Fetches the + row if any. This is only used to read whole keys. + + This method is called via index_read in the case of a WHERE clause using + a primary key index OR is called DIRECTLY when the WHERE clause + uses a PRIMARY KEY index. + + NOTES + This uses an internal result set that is deleted before function + returns. We need to be able to be callable from ha_rnd_pos() +*/ + +int ha_federatedx::index_read_idx(uchar *buf, uint index, const uchar *key, + uint key_len, enum ha_rkey_function find_flag) +{ + int retval; + FEDERATEDX_IO_RESULT *io_result; + DBUG_ENTER("ha_federatedx::index_read_idx"); + + if ((retval= index_read_idx_with_result_set(buf, index, key, + key_len, find_flag, + &io_result))) + DBUG_RETURN(retval); + /* io is correct, as index_read_idx_with_result_set was ok */ + io->free_result(io_result); + DBUG_RETURN(retval); +} + + +/* + Create result set for rows matching query and return first row + + RESULT + 0 ok In this case *result will contain the result set + table->status == 0 + # error In this case *result will contain 0 + table->status == STATUS_NOT_FOUND +*/ + +int ha_federatedx::index_read_idx_with_result_set(uchar *buf, uint index, + const uchar *key, + uint key_len, + ha_rkey_function find_flag, + FEDERATEDX_IO_RESULT **result) +{ + int retval; + char error_buffer[FEDERATEDX_QUERY_BUFFER_SIZE]; + char index_value[STRING_BUFFER_USUAL_SIZE]; + char sql_query_buffer[FEDERATEDX_QUERY_BUFFER_SIZE]; + String index_string(index_value, + sizeof(index_value), + &my_charset_bin); + String sql_query(sql_query_buffer, + sizeof(sql_query_buffer), + &my_charset_bin); + key_range range; + DBUG_ENTER("ha_federatedx::index_read_idx_with_result_set"); + + *result= 0; // In case of errors + index_string.length(0); + sql_query.length(0); + ha_statistic_increment(&SSV::ha_read_key_count); + + sql_query.append(share->select_query); + + range.key= key; + range.length= key_len; + range.flag= find_flag; + create_where_from_key(&index_string, + &table->key_info[index], + &range, + NULL, 0, 0); + sql_query.append(index_string); + + if ((retval= txn->acquire(share, TRUE, &io))) + DBUG_RETURN(retval); + + if (io->query(sql_query.ptr(), sql_query.length())) + { + my_sprintf(error_buffer, (error_buffer, "error: %d '%s'", + io->error_code(), io->error_str())); + retval= ER_QUERY_ON_FOREIGN_DATA_SOURCE; + goto error; + } + if (!(*result= io->store_result())) + { + retval= HA_ERR_END_OF_FILE; + goto error; + } + if (!(retval= read_next(buf, *result))) + DBUG_RETURN(retval); + + io->free_result(*result); + *result= 0; + table->status= STATUS_NOT_FOUND; + DBUG_RETURN(retval); + +error: + table->status= STATUS_NOT_FOUND; + my_error(retval, MYF(0), error_buffer); + DBUG_RETURN(retval); +} + + +/* + This method is used exlusevely by filesort() to check if we + can create sorting buffers of necessary size. + If the handler returns more records that it declares + here server can just crash on filesort(). + We cannot guarantee that's not going to happen with + the FEDERATEDX engine, as we have records==0 always if the + client is a VIEW, and for the table the number of + records can inpredictably change during execution. + So we return maximum possible value here. +*/ + +ha_rows ha_federatedx::estimate_rows_upper_bound() +{ + return HA_POS_ERROR; +} + + +/* Initialized at each key walk (called multiple times unlike rnd_init()) */ + +int ha_federatedx::index_init(uint keynr, bool sorted) +{ + DBUG_ENTER("ha_federatedx::index_init"); + DBUG_PRINT("info", ("table: '%s' key: %u", table->s->table_name.str, keynr)); + active_index= keynr; + DBUG_RETURN(0); +} + + +/* + Read first range +*/ + +int ha_federatedx::read_range_first(const key_range *start_key, + const key_range *end_key, + bool eq_range_arg, bool sorted) +{ + char sql_query_buffer[FEDERATEDX_QUERY_BUFFER_SIZE]; + int retval; + String sql_query(sql_query_buffer, + sizeof(sql_query_buffer), + &my_charset_bin); + DBUG_ENTER("ha_federatedx::read_range_first"); + + DBUG_ASSERT(!(start_key == NULL && end_key == NULL)); + + sql_query.length(0); + sql_query.append(share->select_query); + create_where_from_key(&sql_query, + &table->key_info[active_index], + start_key, end_key, 0, eq_range_arg); + + if ((retval= txn->acquire(share, TRUE, &io))) + DBUG_RETURN(retval); + + if (stored_result) + { + io->free_result(stored_result); + stored_result= 0; + } + + if (io->query(sql_query.ptr(), sql_query.length())) + { + retval= ER_QUERY_ON_FOREIGN_DATA_SOURCE; + goto error; + } + sql_query.length(0); + + if (!(stored_result= io->store_result())) + { + retval= HA_ERR_END_OF_FILE; + goto error; + } + + retval= read_next(table->record[0], stored_result); + DBUG_RETURN(retval); + +error: + table->status= STATUS_NOT_FOUND; + DBUG_RETURN(retval); +} + + +int ha_federatedx::read_range_next() +{ + int retval; + DBUG_ENTER("ha_federatedx::read_range_next"); + retval= rnd_next(table->record[0]); + DBUG_RETURN(retval); +} + + +/* Used to read forward through the index. */ +int ha_federatedx::index_next(uchar *buf) +{ + DBUG_ENTER("ha_federatedx::index_next"); + ha_statistic_increment(&SSV::ha_read_next_count); + DBUG_RETURN(read_next(buf, stored_result)); +} + + +/* + rnd_init() is called when the system wants the storage engine to do a table + scan. + + This is the method that gets data for the SELECT calls. + + See the federatedx in the introduction at the top of this file to see when + rnd_init() is called. + + Called from filesort.cc, records.cc, sql_handler.cc, sql_select.cc, + sql_table.cc, and sql_update.cc. +*/ + +int ha_federatedx::rnd_init(bool scan) +{ + DBUG_ENTER("ha_federatedx::rnd_init"); + /* + The use of the 'scan' flag is incredibly important for this handler + to work properly, especially with updates containing WHERE clauses + using indexed columns. + + When the initial query contains a WHERE clause of the query using an + indexed column, it's index_read_idx that selects the exact record from + the foreign database. + + When there is NO index in the query, either due to not having a WHERE + clause, or the WHERE clause is using columns that are not indexed, a + 'full table scan' done by rnd_init, which in this situation simply means + a 'select * from ...' on the foreign table. + + In other words, this 'scan' flag gives us the means to ensure that if + there is an index involved in the query, we want index_read_idx to + retrieve the exact record (scan flag is 0), and do not want rnd_init + to do a 'full table scan' and wipe out that result set. + + Prior to using this flag, the problem was most apparent with updates. + + An initial query like 'UPDATE tablename SET anything = whatever WHERE + indexedcol = someval', index_read_idx would get called, using a query + constructed with a WHERE clause built from the values of index ('indexcol' + in this case, having a value of 'someval'). mysql_store_result would + then get called (this would be the result set we want to use). + + After this rnd_init (from sql_update.cc) would be called, it would then + unecessarily call "select * from table" on the foreign table, then call + mysql_store_result, which would wipe out the correct previous result set + from the previous call of index_read_idx's that had the result set + containing the correct record, hence update the wrong row! + + */ + + if (scan) + { + int error; + + if ((error= txn->acquire(share, TRUE, &io))) + DBUG_RETURN(error); + + if (stored_result) + { + io->free_result(stored_result); + stored_result= 0; + } + + if (io->query(share->select_query, + strlen(share->select_query))) + goto error; + + stored_result= io->store_result(); + if (!stored_result) + goto error; + } + DBUG_RETURN(0); + +error: + DBUG_RETURN(stash_remote_error()); +} + + +int ha_federatedx::rnd_end() +{ + DBUG_ENTER("ha_federatedx::rnd_end"); + DBUG_RETURN(index_end()); +} + + +int ha_federatedx::free_result() +{ + int error; + DBUG_ASSERT(stored_result); + if ((error= txn->acquire(share, FALSE, &io))) + { + DBUG_ASSERT(0); // Fail when testing + return error; + } + io->free_result(stored_result); + stored_result= 0; + return 0; +} + +int ha_federatedx::index_end(void) +{ + int error= 0; + DBUG_ENTER("ha_federatedx::index_end"); + if (stored_result) + error= free_result(); + active_index= MAX_KEY; + DBUG_RETURN(error); +} + + +/* + This is called for each row of the table scan. When you run out of records + you should return HA_ERR_END_OF_FILE. Fill buff up with the row information. + The Field structure for the table is the key to getting data into buf + in a manner that will allow the server to understand it. + + Called from filesort.cc, records.cc, sql_handler.cc, sql_select.cc, + sql_table.cc, and sql_update.cc. +*/ + +int ha_federatedx::rnd_next(uchar *buf) +{ + DBUG_ENTER("ha_federatedx::rnd_next"); + + if (stored_result == 0) + { + /* + Return value of rnd_init is not always checked (see records.cc), + so we can get here _even_ if there is _no_ pre-fetched result-set! + TODO: fix it. We can delete this in 5.1 when rnd_init() is checked. + */ + DBUG_RETURN(1); + } + DBUG_RETURN(read_next(buf, stored_result)); +} + + +/* + ha_federatedx::read_next + + reads from a result set and converts to mysql internal + format + + SYNOPSIS + field_in_record_is_null() + buf byte pointer to record + result mysql result set + + DESCRIPTION + This method is a wrapper method that reads one record from a result + set and converts it to the internal table format + + RETURN VALUE + 1 error + 0 no error +*/ + +int ha_federatedx::read_next(uchar *buf, FEDERATEDX_IO_RESULT *result) +{ + int retval; + FEDERATEDX_IO_ROW *row; + DBUG_ENTER("ha_federatedx::read_next"); + + table->status= STATUS_NOT_FOUND; // For easier return + + if ((retval= txn->acquire(share, TRUE, &io))) + DBUG_RETURN(retval); + + /* Fetch a row, insert it back in a row format. */ + if (!(row= io->fetch_row(result))) + DBUG_RETURN(HA_ERR_END_OF_FILE); + + if (!(retval= convert_row_to_internal_format(buf, row, result))) + table->status= 0; + + DBUG_RETURN(retval); +} + + +/* + store reference to current row so that we can later find it for + a re-read, update or delete. + + In case of federatedx, a reference is either a primary key or + the whole record. + + Called from filesort.cc, sql_select.cc, sql_delete.cc and sql_update.cc. +*/ + +void ha_federatedx::position(const uchar *record) +{ + DBUG_ENTER("ha_federatedx::position"); + if (table->s->primary_key != MAX_KEY) + key_copy(ref, (uchar *)record, table->key_info + table->s->primary_key, + ref_length); + else + memcpy(ref, record, ref_length); + DBUG_VOID_RETURN; +} + + +/* + This is like rnd_next, but you are given a position to use to determine the + row. The position will be of the type that you stored in ref. + + This method is required for an ORDER BY + + Called from filesort.cc records.cc sql_insert.cc sql_select.cc sql_update.cc. +*/ + +int ha_federatedx::rnd_pos(uchar *buf, uchar *pos) +{ + int result; + DBUG_ENTER("ha_federatedx::rnd_pos"); + ha_statistic_increment(&SSV::ha_read_rnd_count); + if (table->s->primary_key != MAX_KEY) + { + /* We have a primary key, so use index_read_idx to find row */ + result= index_read_idx(buf, table->s->primary_key, pos, + ref_length, HA_READ_KEY_EXACT); + } + else + { + /* otherwise, get the old record ref as obtained in ::position */ + memcpy(buf, pos, ref_length); + result= 0; + } + table->status= result ? STATUS_NOT_FOUND : 0; + DBUG_RETURN(result); +} + + +/* + ::info() is used to return information to the optimizer. + Currently this table handler doesn't implement most of the fields + really needed. SHOW also makes use of this data + Another note, you will probably want to have the following in your + code: + if (records < 2) + records = 2; + The reason is that the server will optimize for cases of only a single + record. If in a table scan you don't know the number of records + it will probably be better to set records to two so you can return + as many records as you need. + Along with records a few more variables you may wish to set are: + records + deleted + data_file_length + index_file_length + delete_length + check_time + Take a look at the public variables in handler.h for more information. + + Called in: + filesort.cc + ha_heap.cc + item_sum.cc + opt_sum.cc + sql_delete.cc + sql_delete.cc + sql_derived.cc + sql_select.cc + sql_select.cc + sql_select.cc + sql_select.cc + sql_select.cc + sql_show.cc + sql_show.cc + sql_show.cc + sql_show.cc + sql_table.cc + sql_union.cc + sql_update.cc + +*/ + +int ha_federatedx::info(uint flag) +{ + char error_buffer[FEDERATEDX_QUERY_BUFFER_SIZE]; + uint error_code; + federatedx_io *tmp_io= 0; + DBUG_ENTER("ha_federatedx::info"); + + error_code= ER_QUERY_ON_FOREIGN_DATA_SOURCE; + + /* we want not to show table status if not needed to do so */ + if (flag & (HA_STATUS_VARIABLE | HA_STATUS_CONST | HA_STATUS_AUTO)) + { + if ((error_code= txn->acquire(share, TRUE, &tmp_io))) + goto fail; + } + + if (flag & (HA_STATUS_VARIABLE | HA_STATUS_CONST)) + { + /* + size of IO operations (This is based on a good guess, no high science + involved) + */ + if (flag & HA_STATUS_CONST) + stats.block_size= 4096; + + if (tmp_io->table_metadata(&stats, share->table_name, + share->table_name_length, flag)) + goto error; + } + + if (flag & HA_STATUS_AUTO) + stats.auto_increment_value= tmp_io->last_insert_id(); + + /* + If ::info created it's own transaction, close it. This happens in case + of show table status; + */ + txn->release(&tmp_io); + + DBUG_RETURN(0); + +error: + if (tmp_io) + { + my_sprintf(error_buffer, (error_buffer, ": %d : %s", + tmp_io->error_code(), tmp_io->error_str())); + my_error(error_code, MYF(0), error_buffer); + } + else + if (remote_error_number != -1 /* error already reported */) + { + error_code= remote_error_number; + my_error(error_code, MYF(0), ER(error_code)); + } +fail: + txn->release(&tmp_io); + DBUG_RETURN(error_code); +} + + +/** + @brief Handles extra signals from MySQL server + + @param[in] operation Hint for storage engine + + @return Operation Status + @retval 0 OK + */ +int ha_federatedx::extra(ha_extra_function operation) +{ + DBUG_ENTER("ha_federatedx::extra"); + switch (operation) { + case HA_EXTRA_IGNORE_DUP_KEY: + ignore_duplicates= TRUE; + break; + case HA_EXTRA_NO_IGNORE_DUP_KEY: + insert_dup_update= FALSE; + ignore_duplicates= FALSE; + break; + case HA_EXTRA_WRITE_CAN_REPLACE: + replace_duplicates= TRUE; + break; + case HA_EXTRA_WRITE_CANNOT_REPLACE: + /* + We use this flag to ensure that we do not create an "INSERT IGNORE" + statement when inserting new rows into the remote table. + */ + replace_duplicates= FALSE; + break; + case HA_EXTRA_INSERT_WITH_UPDATE: + insert_dup_update= TRUE; + break; + default: + /* do nothing */ + DBUG_PRINT("info",("unhandled operation: %d", (uint) operation)); + } + DBUG_RETURN(0); +} + + +/** + @brief Reset state of file to after 'open'. + + @detail This function is called after every statement for all tables + used by that statement. + + @return Operation status + @retval 0 OK +*/ + +int ha_federatedx::reset(void) +{ + insert_dup_update= FALSE; + ignore_duplicates= FALSE; + replace_duplicates= FALSE; + return 0; +} + + +/* + Used to delete all rows in a table. Both for cases of truncate and + for cases where the optimizer realizes that all rows will be + removed as a result of a SQL statement. + + Called from item_sum.cc by Item_func_group_concat::clear(), + Item_sum_count_distinct::clear(), and Item_func_group_concat::clear(). + Called from sql_delete.cc by mysql_delete(). + Called from sql_select.cc by JOIN::reinit(). + Called from sql_union.cc by st_select_lex_unit::exec(). +*/ + +int ha_federatedx::delete_all_rows() +{ + char query_buffer[FEDERATEDX_QUERY_BUFFER_SIZE]; + String query(query_buffer, sizeof(query_buffer), &my_charset_bin); + int error; + DBUG_ENTER("ha_federatedx::delete_all_rows"); + + query.length(0); + + query.set_charset(system_charset_info); + query.append(STRING_WITH_LEN("TRUNCATE ")); + append_ident(&query, share->table_name, share->table_name_length, + ident_quote_char); + + /* no need for savepoint in autocommit mode */ + if (!(ha_thd()->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) + txn->stmt_autocommit(); + + /* + TRUNCATE won't return anything in mysql_affected_rows + */ + + if ((error= txn->acquire(share, FALSE, &io))) + DBUG_RETURN(error); + + if (io->query(query.ptr(), query.length())) + { + DBUG_RETURN(stash_remote_error()); + } + stats.deleted+= stats.records; + stats.records= 0; + DBUG_RETURN(0); +} + + +/* + The idea with handler::store_lock() is the following: + + The statement decided which locks we should need for the table + for updates/deletes/inserts we get WRITE locks, for SELECT... we get + read locks. + + Before adding the lock into the table lock handler (see thr_lock.c) + mysqld calls store lock with the requested locks. Store lock can now + modify a write lock to a read lock (or some other lock), ignore the + lock (if we don't want to use MySQL table locks at all) or add locks + for many tables (like we do when we are using a MERGE handler). + + Berkeley DB for federatedx changes all WRITE locks to TL_WRITE_ALLOW_WRITE + (which signals that we are doing WRITES, but we are still allowing other + reader's and writer's. + + When releasing locks, store_lock() are also called. In this case one + usually doesn't have to do anything. + + In some exceptional cases MySQL may send a request for a TL_IGNORE; + This means that we are requesting the same lock as last time and this + should also be ignored. (This may happen when someone does a flush + table when we have opened a part of the tables, in which case mysqld + closes and reopens the tables and tries to get the same locks at last + time). In the future we will probably try to remove this. + + Called from lock.cc by get_lock_data(). +*/ + +THR_LOCK_DATA **ha_federatedx::store_lock(THD *thd, + THR_LOCK_DATA **to, + enum thr_lock_type lock_type) +{ + DBUG_ENTER("ha_federatedx::store_lock"); + if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK) + { + /* + Here is where we get into the guts of a row level lock. + If TL_UNLOCK is set + If we are not doing a LOCK TABLE or DISCARD/IMPORT + TABLESPACE, then allow multiple writers + */ + + if ((lock_type >= TL_WRITE_CONCURRENT_INSERT && + lock_type <= TL_WRITE) && !thd->in_lock_tables) + lock_type= TL_WRITE_ALLOW_WRITE; + + /* + In queries of type INSERT INTO t1 SELECT ... FROM t2 ... + MySQL would use the lock TL_READ_NO_INSERT on t2, and that + would conflict with TL_WRITE_ALLOW_WRITE, blocking all inserts + to t2. Convert the lock to a normal read lock to allow + concurrent inserts to t2. + */ + + if (lock_type == TL_READ_NO_INSERT && !thd->in_lock_tables) + lock_type= TL_READ; + + lock.type= lock_type; + } + + *to++= &lock; + + DBUG_RETURN(to); +} + + +static int test_connection(MYSQL_THD thd, federatedx_io *io, + FEDERATEDX_SHARE *share) +{ + char buffer[FEDERATEDX_QUERY_BUFFER_SIZE]; + String str(buffer, sizeof(buffer), &my_charset_bin); + FEDERATEDX_IO_RESULT *resultset= NULL; + int retval; + + str.length(0); + str.append(STRING_WITH_LEN("SELECT * FROM ")); + append_identifier(thd, &str, share->table_name, + share->table_name_length); + str.append(STRING_WITH_LEN(" WHERE 1=0")); + + if ((retval= io->query(str.ptr(), str.length()))) + { + my_sprintf(buffer, (buffer, + "database: '%s' username: '%s' hostname: '%s'", + share->database, share->username, share->hostname)); + DBUG_PRINT("info", ("error-code: %d", io->error_code())); + my_error(ER_CANT_CREATE_FEDERATED_TABLE, MYF(0), buffer); + } + else + resultset= io->store_result(); + + io->free_result(resultset); + + return retval; +} + +/* + create() does nothing, since we have no local setup of our own. + FUTURE: We should potentially connect to the foreign database and +*/ + +int ha_federatedx::create(const char *name, TABLE *table_arg, + HA_CREATE_INFO *create_info) +{ + int retval; + THD *thd= current_thd; + FEDERATEDX_SHARE tmp_share; // Only a temporary share, to test the url + federatedx_txn *tmp_txn; + federatedx_io *tmp_io= NULL; + DBUG_ENTER("ha_federatedx::create"); + + if ((retval= parse_url(thd->mem_root, &tmp_share, table_arg, 1))) + goto error; + + /* loopback socket connections hang due to LOCK_open mutex */ + if ((!tmp_share.hostname || !strcmp(tmp_share.hostname,my_localhost)) && + !tmp_share.port) + goto error; + + /* + If possible, we try to use an existing network connection to + the remote server. To ensure that no new FEDERATEDX_SERVER + instance is created, we pass NULL in get_server() TABLE arg. + */ + pthread_mutex_lock(&federatedx_mutex); + tmp_share.s= get_server(&tmp_share, NULL); + pthread_mutex_unlock(&federatedx_mutex); + + if (tmp_share.s) + { + tmp_txn= get_txn(thd); + if (!(retval= tmp_txn->acquire(&tmp_share, TRUE, &tmp_io))) + { + retval= test_connection(thd, tmp_io, &tmp_share); + tmp_txn->release(&tmp_io); + } + free_server(tmp_txn, tmp_share.s); + } + else + { + FEDERATEDX_SERVER server; + +#ifdef NOT_YET + /* + Bug#25679 + Ensure that we do not hold the LOCK_open mutex while attempting + to establish FederatedX connection to guard against a trivial + Denial of Service scenerio. + */ + safe_mutex_assert_not_owner(&LOCK_open); +#endif + + fill_server(thd->mem_root, &server, &tmp_share, create_info->table_charset); + +#ifndef DBUG_OFF + pthread_mutex_init(&server.mutex, MY_MUTEX_INIT_FAST); + pthread_mutex_lock(&server.mutex); +#endif + + tmp_io= federatedx_io::construct(thd->mem_root, &server); + + retval= test_connection(thd, tmp_io, &tmp_share); + +#ifndef DBUG_OFF + pthread_mutex_unlock(&server.mutex); + pthread_mutex_destroy(&server.mutex); +#endif + + delete tmp_io; + } + +error: + DBUG_RETURN(retval); + +} + + +int ha_federatedx::stash_remote_error() +{ + DBUG_ENTER("ha_federatedx::stash_remote_error()"); + if (!io) + DBUG_RETURN(remote_error_number); + remote_error_number= io->error_code(); + strmake(remote_error_buf, io->error_str(), sizeof(remote_error_buf)-1); + if (remote_error_number == ER_DUP_ENTRY || + remote_error_number == ER_DUP_KEY) + DBUG_RETURN(HA_ERR_FOUND_DUPP_KEY); + DBUG_RETURN(HA_FEDERATEDX_ERROR_WITH_REMOTE_SYSTEM); +} + + +bool ha_federatedx::get_error_message(int error, String* buf) +{ + DBUG_ENTER("ha_federatedx::get_error_message"); + DBUG_PRINT("enter", ("error: %d", error)); + if (error == HA_FEDERATEDX_ERROR_WITH_REMOTE_SYSTEM) + { + buf->append(STRING_WITH_LEN("Error on remote system: ")); + buf->qs_append(remote_error_number); + buf->append(STRING_WITH_LEN(": ")); + buf->append(remote_error_buf); + + remote_error_number= 0; + remote_error_buf[0]= '\0'; + } + DBUG_PRINT("exit", ("message: %s", buf->ptr())); + DBUG_RETURN(FALSE); +} + + +int ha_federatedx::start_stmt(MYSQL_THD thd, thr_lock_type lock_type) +{ + DBUG_ENTER("ha_federatedx::start_stmt"); + DBUG_ASSERT(txn == get_txn(thd)); + + if (!txn->in_transaction()) + { + txn->stmt_begin(); + trans_register_ha(thd, FALSE, ht); + } + DBUG_RETURN(0); +} + + +int ha_federatedx::external_lock(MYSQL_THD thd, int lock_type) +{ + int error= 0; + DBUG_ENTER("ha_federatedx::external_lock"); + + if (lock_type == F_UNLCK) + txn->release(&io); + else + { + txn= get_txn(thd); + if (!(error= txn->acquire(share, lock_type == F_RDLCK, &io)) && + (lock_type == F_WRLCK || !io->is_autocommit())) + { + if (!thd_test_options(thd, (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) + { + txn->stmt_begin(); + trans_register_ha(thd, FALSE, ht); + } + else + { + txn->txn_begin(); + trans_register_ha(thd, TRUE, ht); + } + } + } + + DBUG_RETURN(error); +} + + +int ha_federatedx::savepoint_set(handlerton *hton, MYSQL_THD thd, void *sv) +{ + int error= 0; + federatedx_txn *txn= (federatedx_txn *) thd_get_ha_data(thd, hton); + DBUG_ENTER("ha_federatedx::savepoint_set"); + + if (txn && txn->has_connections()) + { + if (txn->txn_begin()) + trans_register_ha(thd, TRUE, hton); + + txn->sp_acquire((ulong *) sv); + + DBUG_ASSERT(1 < *(ulong *) sv); + } + + DBUG_RETURN(error); +} + + +int ha_federatedx::savepoint_rollback(handlerton *hton, MYSQL_THD thd, void *sv) + { + int error= 0; + federatedx_txn *txn= (federatedx_txn *) thd_get_ha_data(thd, hton); + DBUG_ENTER("ha_federatedx::savepoint_rollback"); + + if (txn) + error= txn->sp_rollback((ulong *) sv); + + DBUG_RETURN(error); +} + + +int ha_federatedx::savepoint_release(handlerton *hton, MYSQL_THD thd, void *sv) +{ + int error= 0; + federatedx_txn *txn= (federatedx_txn *) thd_get_ha_data(thd, hton); + DBUG_ENTER("ha_federatedx::savepoint_release"); + + if (txn) + error= txn->sp_release((ulong *) sv); + + DBUG_RETURN(error); +} + + +int ha_federatedx::commit(handlerton *hton, MYSQL_THD thd, bool all) +{ + int return_val; + federatedx_txn *txn= (federatedx_txn *) thd_get_ha_data(thd, hton); + DBUG_ENTER("ha_federatedx::commit"); + + if (all) + return_val= txn->txn_commit(); + else + return_val= txn->stmt_commit(); + + DBUG_PRINT("info", ("error val: %d", return_val)); + DBUG_RETURN(return_val); +} + + +int ha_federatedx::rollback(handlerton *hton, MYSQL_THD thd, bool all) +{ + int return_val; + federatedx_txn *txn= (federatedx_txn *) thd_get_ha_data(thd, hton); + DBUG_ENTER("ha_federatedx::rollback"); + + if (all) + return_val= txn->txn_rollback(); + else + return_val= txn->stmt_rollback(); + + DBUG_PRINT("info", ("error val: %d", return_val)); + DBUG_RETURN(return_val); +} + +struct st_mysql_storage_engine federatedx_storage_engine= +{ MYSQL_HANDLERTON_INTERFACE_VERSION }; + +mysql_declare_plugin(federated) +{ + MYSQL_STORAGE_ENGINE_PLUGIN, + &federatedx_storage_engine, + "FEDERATED", + "Patrick Galbraith", + "FederatedX pluggable storage engine", + PLUGIN_LICENSE_GPL, + federatedx_db_init, /* Plugin Init */ + federatedx_done, /* Plugin Deinit */ + 0x0100 /* 1.0 */, + NULL, /* status variables */ + NULL, /* system variables */ + NULL /* config options */ +} +mysql_declare_plugin_end; diff --git a/storage/federatedx/ha_federatedx.h b/storage/federatedx/ha_federatedx.h new file mode 100644 index 00000000000..0fa9df25895 --- /dev/null +++ b/storage/federatedx/ha_federatedx.h @@ -0,0 +1,446 @@ +/* +Copyright (c) 2008, Patrick Galbraith +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + + * Neither the name of Patrick Galbraith nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +class federatedx_io; + +/* + FEDERATEDX_SERVER will eventually be a structure that will be shared among + all FEDERATEDX_SHARE instances so that the federated server can minimise + the number of open connections. This will eventually lead to the support + of reliable XA federated tables. +*/ +typedef struct st_fedrated_server { + MEM_ROOT mem_root; + uint use_count, io_count; + + uchar *key; + uint key_length; + + const char *scheme; + const char *hostname; + const char *username; + const char *password; + const char *database; + const char *socket; + ushort port; + + const char *csname; + + pthread_mutex_t mutex; + federatedx_io *idle_list; +} FEDERATEDX_SERVER; + +/* + Please read ha_exmple.cc before reading this file. + Please keep in mind that the federatedx storage engine implements all methods + that are required to be implemented. handler.h has a full list of methods + that you can implement. +*/ + +#ifdef USE_PRAGMA_INTERFACE +#pragma interface /* gcc class implementation */ +#endif + +#include + +/* + handler::print_error has a case statement for error numbers. + This value is (10000) is far out of range and will envoke the + default: case. + (Current error range is 120-159 from include/my_base.h) +*/ +#define HA_FEDERATEDX_ERROR_WITH_REMOTE_SYSTEM 10000 + +#define FEDERATEDX_QUERY_BUFFER_SIZE STRING_BUFFER_USUAL_SIZE * 5 +#define FEDERATEDX_RECORDS_IN_RANGE 2 +#define FEDERATEDX_MAX_KEY_LENGTH 3500 // Same as innodb + +/* + FEDERATEDX_SHARE is a structure that will be shared amoung all open handlers + The example implements the minimum of what you will probably need. +*/ +typedef struct st_federatedx_share { + MEM_ROOT mem_root; + + bool parsed; + /* this key is unique db/tablename */ + const char *share_key; + /* + the primary select query to be used in rnd_init + */ + char *select_query; + /* + remote host info, parse_url supplies + */ + char *server_name; + char *connection_string; + char *scheme; + char *hostname; + char *username; + char *password; + char *database; + char *table_name; + char *table; + char *socket; + char *sport; + int share_key_length; + ushort port; + + uint table_name_length, server_name_length, connect_string_length; + uint use_count; + THR_LOCK lock; + FEDERATEDX_SERVER *s; +} FEDERATEDX_SHARE; + + +typedef struct st_federatedx_result FEDERATEDX_IO_RESULT; +typedef struct st_federatedx_row FEDERATEDX_IO_ROW; +typedef ptrdiff_t FEDERATEDX_IO_OFFSET; + +class federatedx_io +{ + friend class federatedx_txn; + FEDERATEDX_SERVER * const server; + federatedx_io **owner_ptr; + federatedx_io *txn_next; + federatedx_io *idle_next; + bool active; /* currently participating in a transaction */ + bool busy; /* in use by a ha_federated instance */ + bool readonly;/* indicates that no updates have occurred */ + +protected: + void set_active(bool new_active) + { active= new_active; } +public: + federatedx_io(FEDERATEDX_SERVER *); + virtual ~federatedx_io(); + + bool is_readonly() const { return readonly; } + bool is_active() const { return active; } + + const char * get_charsetname() const + { return server->csname ? server->csname : "latin1"; } + + const char * get_hostname() const { return server->hostname; } + const char * get_username() const { return server->username; } + const char * get_password() const { return server->password; } + const char * get_database() const { return server->database; } + ushort get_port() const { return server->port; } + const char * get_socket() const { return server->socket; } + + static bool handles_scheme(const char *scheme); + static federatedx_io *construct(MEM_ROOT *server_root, + FEDERATEDX_SERVER *server); + + static void *operator new(size_t size, MEM_ROOT *mem_root) throw () + { return alloc_root(mem_root, size); } + static void operator delete(void *ptr, size_t size) + { TRASH(ptr, size); } + + virtual int query(const char *buffer, uint length)=0; + virtual FEDERATEDX_IO_RESULT *store_result()=0; + + virtual size_t max_query_size() const=0; + + virtual my_ulonglong affected_rows() const=0; + virtual my_ulonglong last_insert_id() const=0; + + virtual int error_code()=0; + virtual const char *error_str()=0; + + virtual void reset()=0; + virtual int commit()=0; + virtual int rollback()=0; + + virtual int savepoint_set(ulong sp)=0; + virtual ulong savepoint_release(ulong sp)=0; + virtual ulong savepoint_rollback(ulong sp)=0; + virtual void savepoint_restrict(ulong sp)=0; + + virtual ulong last_savepoint() const=0; + virtual ulong actual_savepoint() const=0; + virtual bool is_autocommit() const=0; + + virtual bool table_metadata(ha_statistics *stats, const char *table_name, + uint table_name_length, uint flag) = 0; + + /* resultset operations */ + + virtual void free_result(FEDERATEDX_IO_RESULT *io_result)=0; + virtual unsigned int get_num_fields(FEDERATEDX_IO_RESULT *io_result)=0; + virtual my_ulonglong get_num_rows(FEDERATEDX_IO_RESULT *io_result)=0; + virtual FEDERATEDX_IO_ROW *fetch_row(FEDERATEDX_IO_RESULT *io_result)=0; + virtual ulong *fetch_lengths(FEDERATEDX_IO_RESULT *io_result)=0; + virtual const char *get_column_data(FEDERATEDX_IO_ROW *row, + unsigned int column)=0; + virtual bool is_column_null(const FEDERATEDX_IO_ROW *row, + unsigned int column) const=0; +}; + + +class federatedx_txn +{ + federatedx_io *txn_list; + ulong savepoint_level; + ulong savepoint_stmt; + ulong savepoint_next; + + void release_scan(); +public: + federatedx_txn(); + ~federatedx_txn(); + + bool has_connections() const { return txn_list != NULL; } + bool in_transaction() const { return savepoint_next != 0; } + int acquire(FEDERATEDX_SHARE *share, bool readonly, federatedx_io **io); + void release(federatedx_io **io); + void close(FEDERATEDX_SERVER *); + + bool txn_begin(); + int txn_commit(); + int txn_rollback(); + + bool sp_acquire(ulong *save); + int sp_rollback(ulong *save); + int sp_release(ulong *save); + + bool stmt_begin(); + int stmt_commit(); + int stmt_rollback(); + void stmt_autocommit(); +}; + + +/* + Class definition for the storage engine +*/ +class ha_federatedx: public handler +{ + friend int federatedx_db_init(void *p); + + THR_LOCK_DATA lock; /* MySQL lock */ + FEDERATEDX_SHARE *share; /* Shared lock info */ + federatedx_txn *txn; + federatedx_io *io; + FEDERATEDX_IO_RESULT *stored_result; + uint fetch_num; // stores the fetch num + FEDERATEDX_IO_OFFSET current_position; // Current position used by ::position() + int remote_error_number; + char remote_error_buf[FEDERATEDX_QUERY_BUFFER_SIZE]; + bool ignore_duplicates, replace_duplicates; + bool insert_dup_update; + DYNAMIC_STRING bulk_insert; + +private: + /* + return 0 on success + return errorcode otherwise + */ + uint convert_row_to_internal_format(uchar *buf, FEDERATEDX_IO_ROW *row, + FEDERATEDX_IO_RESULT *result); + bool create_where_from_key(String *to, KEY *key_info, + const key_range *start_key, + const key_range *end_key, + bool records_in_range, bool eq_range); + int stash_remote_error(); + + federatedx_txn *get_txn(THD *thd, bool no_create= FALSE); + + static int disconnect(handlerton *hton, MYSQL_THD thd); + static int savepoint_set(handlerton *hton, MYSQL_THD thd, void *sv); + static int savepoint_rollback(handlerton *hton, MYSQL_THD thd, void *sv); + static int savepoint_release(handlerton *hton, MYSQL_THD thd, void *sv); + static int commit(handlerton *hton, MYSQL_THD thd, bool all); + static int rollback(handlerton *hton, MYSQL_THD thd, bool all); + + bool append_stmt_insert(String *query); + + int read_next(uchar *buf, FEDERATEDX_IO_RESULT *result); + int index_read_idx_with_result_set(uchar *buf, uint index, + const uchar *key, + uint key_len, + ha_rkey_function find_flag, + FEDERATEDX_IO_RESULT **result); + int real_query(const char *query, uint length); + int real_connect(FEDERATEDX_SHARE *my_share, uint create_flag); +public: + ha_federatedx(handlerton *hton, TABLE_SHARE *table_arg); + ~ha_federatedx() {} + /* The name that will be used for display purposes */ + const char *table_type() const { return "FEDERATED"; } + /* + The name of the index type that will be used for display + don't implement this method unless you really have indexes + */ + // perhaps get index type + const char *index_type(uint inx) { return "REMOTE"; } + const char **bas_ext() const; + /* + This is a list of flags that says what the storage engine + implements. The current table flags are documented in + handler.h + */ + ulonglong table_flags() const + { + /* fix server to be able to get remote server table flags */ + return (HA_PRIMARY_KEY_IN_READ_INDEX | HA_FILE_BASED + | HA_REC_NOT_IN_SEQ | HA_AUTO_PART_KEY | HA_CAN_INDEX_BLOBS | + HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE | + HA_NO_PREFIX_CHAR_KEYS | HA_PRIMARY_KEY_REQUIRED_FOR_DELETE | + HA_PARTIAL_COLUMN_READ | HA_NULL_IN_KEY); + } + /* + This is a bitmap of flags that says how the storage engine + implements indexes. The current index flags are documented in + handler.h. If you do not implement indexes, just return zero + here. + + part is the key part to check. First key part is 0 + If all_parts it's set, MySQL want to know the flags for the combined + index up to and including 'part'. + */ + /* fix server to be able to get remote server index flags */ + ulong index_flags(uint inx, uint part, bool all_parts) const + { + return (HA_READ_NEXT | HA_READ_RANGE | HA_READ_AFTER_KEY); + } + uint max_supported_record_length() const { return HA_MAX_REC_LENGTH; } + uint max_supported_keys() const { return MAX_KEY; } + uint max_supported_key_parts() const { return MAX_REF_PARTS; } + uint max_supported_key_length() const { return FEDERATEDX_MAX_KEY_LENGTH; } + uint max_supported_key_part_length() const { return FEDERATEDX_MAX_KEY_LENGTH; } + /* + Called in test_quick_select to determine if indexes should be used. + Normally, we need to know number of blocks . For federatedx we need to + know number of blocks on remote side, and number of packets and blocks + on the network side (?) + Talk to Kostja about this - how to get the + number of rows * ... + disk scan time on other side (block size, size of the row) + network time ... + The reason for "records * 1000" is that such a large number forces + this to use indexes " + */ + double scan_time() + { + DBUG_PRINT("info", ("records %lu", (ulong) stats.records)); + return (double)(stats.records*1000); + } + /* + The next method will never be called if you do not implement indexes. + */ + double read_time(uint index, uint ranges, ha_rows rows) + { + /* + Per Brian, this number is bugus, but this method must be implemented, + and at a later date, he intends to document this issue for handler code + */ + return (double) rows / 20.0+1; + } + + const key_map *keys_to_use_for_scanning() { return &key_map_full; } + /* + Everything below are methods that we implment in ha_federatedx.cc. + + Most of these methods are not obligatory, skip them and + MySQL will treat them as not implemented + */ + int open(const char *name, int mode, uint test_if_locked); // required + int close(void); // required + + void start_bulk_insert(ha_rows rows); + int end_bulk_insert(bool abort); + int write_row(uchar *buf); + int update_row(const uchar *old_data, uchar *new_data); + int delete_row(const uchar *buf); + int index_init(uint keynr, bool sorted); + ha_rows estimate_rows_upper_bound(); + int index_read(uchar *buf, const uchar *key, + uint key_len, enum ha_rkey_function find_flag); + int index_read_idx(uchar *buf, uint idx, const uchar *key, + uint key_len, enum ha_rkey_function find_flag); + int index_next(uchar *buf); + int index_end(); + int read_range_first(const key_range *start_key, + const key_range *end_key, + bool eq_range, bool sorted); + int read_range_next(); + /* + unlike index_init(), rnd_init() can be called two times + without rnd_end() in between (it only makes sense if scan=1). + then the second call should prepare for the new table scan + (e.g if rnd_init allocates the cursor, second call should + position it to the start of the table, no need to deallocate + and allocate it again + */ + int rnd_init(bool scan); //required + int rnd_end(); + int rnd_next(uchar *buf); //required + int rnd_pos(uchar *buf, uchar *pos); //required + void position(const uchar *record); //required + int info(uint); //required + int extra(ha_extra_function operation); + + void update_auto_increment(void); + int repair(THD* thd, HA_CHECK_OPT* check_opt); + int optimize(THD* thd, HA_CHECK_OPT* check_opt); + + int delete_all_rows(void); + int create(const char *name, TABLE *form, + HA_CREATE_INFO *create_info); //required + ha_rows records_in_range(uint inx, key_range *start_key, + key_range *end_key); + uint8 table_cache_type() { return HA_CACHE_TBL_NOCACHE; } + + THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to, + enum thr_lock_type lock_type); //required + bool get_error_message(int error, String *buf); + int start_stmt(THD *thd, thr_lock_type lock_type); + int external_lock(THD *thd, int lock_type); + int reset(void); + int free_result(void); +}; + +extern const char ident_quote_char; // Character for quoting + // identifiers +extern const char value_quote_char; // Character for quoting + // literals + +extern bool append_ident(String *string, const char *name, uint length, + const char quote_char); + + +extern federatedx_io *instantiate_io_mysql(MEM_ROOT *server_root, + FEDERATEDX_SERVER *server); +extern federatedx_io *instantiate_io_null(MEM_ROOT *server_root, + FEDERATEDX_SERVER *server); diff --git a/storage/federatedx/plug.in b/storage/federatedx/plug.in new file mode 100644 index 00000000000..ee2e6af0e94 --- /dev/null +++ b/storage/federatedx/plug.in @@ -0,0 +1,5 @@ +MYSQL_STORAGE_ENGINE(federated,,[FederatedX Storage Engine], + [FederatedX Storage Engine], [max,max-no-ndb]) +MYSQL_PLUGIN_DYNAMIC(federated, [ha_federatedx.la]) +MYSQL_PLUGIN_STATIC(federated, [libfederatedx.a]) +MYSQL_PLUGIN_DEPENDS_ON_MYSQL_INTERNALS(federated, [ha_federatedx.cc]) diff --git a/storage/pbxt/src/cache_xt.cc b/storage/pbxt/src/cache_xt.cc index 89b62c02282..aab8b9de0d0 100644 --- a/storage/pbxt/src/cache_xt.cc +++ b/storage/pbxt/src/cache_xt.cc @@ -374,7 +374,7 @@ xtPublic void xt_ind_release_handle(XTIndHandlePtr handle, xtBool have_lock, XTT { DcHandleSlotPtr hs; XTIndBlockPtr block = NULL; - u_int hash_idx = NULL; + u_int hash_idx = 0; DcSegmentPtr seg = NULL; XTIndBlockPtr xblock; @@ -1379,7 +1379,7 @@ xtPublic xtBool xt_ind_fetch(XTOpenTablePtr ot, XTIndexPtr ind, xtIndexNodeID ad ASSERT_NS(iref->ir_xlock == 2); #endif if (!(block = ind_cac_fetch(ot, ind, address, &seg, TRUE))) - return NULL; + return 0; branch_size = XT_GET_DISK_2(((XTIdxBranchDPtr) block->cb_data)->tb_size_2); if (XT_GET_INDEX_BLOCK_LEN(branch_size) < 2 || XT_GET_INDEX_BLOCK_LEN(branch_size) > XT_INDEX_PAGE_SIZE) { diff --git a/storage/xtradb/include/buf0buf.ic b/storage/xtradb/include/buf0buf.ic index 2b7f643f59b..d7ac80becce 100644 --- a/storage/xtradb/include/buf0buf.ic +++ b/storage/xtradb/include/buf0buf.ic @@ -1056,7 +1056,7 @@ buf_page_release( buf_block_t* block, /* in: buffer block */ ulint rw_latch, /* in: RW_S_LATCH, RW_X_LATCH, RW_NO_LATCH */ - mtr_t* mtr) /* in: mtr */ + mtr_t* mtr __attribute__((unused))) /* in: mtr */ { ut_ad(block); From 60c4f0f87bff0d37388de27970e9cb0e6ed64c4a Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Fri, 30 Oct 2009 20:51:46 +0200 Subject: [PATCH 60/69] Added ignore for symlinked build file --- .bzrignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.bzrignore b/.bzrignore index 258a16fdeca..d2a1ce94f70 100644 --- a/.bzrignore +++ b/.bzrignore @@ -1921,3 +1921,4 @@ sql/share/ukrainian libmysqld/examples/mysqltest.cc extra/libevent/event-config.h libmysqld/opt_table_elimination.cc +libmysqld/ha_federatedx.cc From 0673379006a7352d611ae6c92b0c8799600328a1 Mon Sep 17 00:00:00 2001 From: Arjen Lentz Date: Sat, 31 Oct 2009 15:29:16 +1000 Subject: [PATCH 61/69] libevent fixup required for Debian 4 (Etch) Also missing copyright for copied macros. Fix by Antony Curtis. --- extra/libevent/event-internal.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/extra/libevent/event-internal.h b/extra/libevent/event-internal.h index 19b7a547a84..9dd0c4d7632 100644 --- a/extra/libevent/event-internal.h +++ b/extra/libevent/event-internal.h @@ -70,6 +70,11 @@ struct event_base { /* Internal use only: Functions that might be missing from */ #ifndef HAVE_TAILQFOREACH +/* These following macros are copied from BSD sys/queue.h + Copyright (c) 1991, 1993, The Regents of the University of California. + All rights reserved. +*/ +#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL) #define TAILQ_FIRST(head) ((head)->tqh_first) #define TAILQ_END(head) NULL #define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) From 6cabc7abb8469e6649c68f0608361ba45814fdca Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 31 Oct 2009 21:22:50 +0200 Subject: [PATCH 62/69] Compilation under windows x64 made possible. sql/mysqld.cc: Explicit type casting required by windows x64 compiler. storage/xtradb/include/srv0srv.h: Parameters should be declared as ulong. storage/xtradb/srv/srv0srv.c: Parameters should be declared as ulong. --- sql/mysqld.cc | 2 +- storage/xtradb/include/srv0srv.h | 28 ++++++++++++++-------------- storage/xtradb/srv/srv0srv.c | 28 ++++++++++++++-------------- 3 files changed, 29 insertions(+), 29 deletions(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 497a39b95f8..53b95527a91 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -8084,7 +8084,7 @@ mysqld_get_one_option(int optid, switch(optid) { #ifndef DBUG_OFF case OPT_DEBUG_FLUSH: - argument= IF_WIN(default_dbug_option, (char*) "d:t:i:O,/tmp/mysqld.trace"); + argument= IF_WIN((char*) default_dbug_option, (char*) "d:t:i:O,/tmp/mysqld.trace"); /* fall through */ case '#': if (!argument) diff --git a/storage/xtradb/include/srv0srv.h b/storage/xtradb/include/srv0srv.h index 84fe71595d7..6e5e955f9a5 100644 --- a/storage/xtradb/include/srv0srv.h +++ b/storage/xtradb/include/srv0srv.h @@ -116,8 +116,8 @@ extern ulint srv_log_file_size; extern ulint srv_log_buffer_size; extern ulong srv_flush_log_at_trx_commit; -extern ulint srv_show_locks_held; -extern ulint srv_show_verbose_locks; +extern ulong srv_show_locks_held; +extern ulong srv_show_verbose_locks; /* The sort order table of the MySQL latin1_swedish_ci character set collation */ @@ -166,11 +166,11 @@ extern ulint srv_fast_shutdown; /* If this is 1, do not do a extern ibool srv_innodb_status; extern unsigned long long srv_stats_sample_pages; -extern ulint srv_stats_method; +extern ulong srv_stats_method; #define SRV_STATS_METHOD_NULLS_EQUAL 0 #define SRV_STATS_METHOD_NULLS_NOT_EQUAL 1 #define SRV_STATS_METHOD_IGNORE_NULLS 2 -extern ulint srv_stats_auto_update; +extern ulong srv_stats_auto_update; extern ibool srv_use_doublewrite_buf; extern ibool srv_use_checksums; @@ -183,19 +183,19 @@ extern ulong srv_max_purge_lag; extern ulong srv_replication_delay; -extern ulint srv_io_capacity; +extern ulong srv_io_capacity; extern long long srv_ibuf_max_size; -extern ulint srv_ibuf_active_contract; -extern ulint srv_ibuf_accel_rate; -extern ulint srv_flush_neighbor_pages; -extern ulint srv_enable_unsafe_group_commit; -extern ulint srv_read_ahead; -extern ulint srv_adaptive_checkpoint; +extern ulong srv_ibuf_active_contract; +extern ulong srv_ibuf_accel_rate; +extern ulong srv_flush_neighbor_pages; +extern ulong srv_enable_unsafe_group_commit; +extern ulong srv_read_ahead; +extern ulong srv_adaptive_checkpoint; -extern ulint srv_expand_import; +extern ulong srv_expand_import; -extern ulint srv_extra_rsegments; -extern ulint srv_dict_size_limit; +extern ulong srv_extra_rsegments; +extern ulong srv_dict_size_limit; /*-------------------------------------------*/ extern ulint srv_n_rows_inserted; diff --git a/storage/xtradb/srv/srv0srv.c b/storage/xtradb/srv/srv0srv.c index d261a69991c..35b80d72615 100644 --- a/storage/xtradb/srv/srv0srv.c +++ b/storage/xtradb/srv/srv0srv.c @@ -160,8 +160,8 @@ UNIV_INTERN ulint srv_log_file_size = ULINT_MAX; UNIV_INTERN ulint srv_log_buffer_size = ULINT_MAX; UNIV_INTERN ulong srv_flush_log_at_trx_commit = 1; -UNIV_INTERN ulint srv_show_locks_held = 10; -UNIV_INTERN ulint srv_show_verbose_locks = 0; +UNIV_INTERN ulong srv_show_locks_held = 10; +UNIV_INTERN ulong srv_show_verbose_locks = 0; /* The sort order table of the MySQL latin1_swedish_ci character set @@ -338,8 +338,8 @@ UNIV_INTERN ibool srv_innodb_status = FALSE; /* When estimating number of different key values in an index, sample this many index pages */ UNIV_INTERN unsigned long long srv_stats_sample_pages = 8; -UNIV_INTERN ulint srv_stats_method = 0; -UNIV_INTERN ulint srv_stats_auto_update = 1; +UNIV_INTERN ulong srv_stats_method = 0; +UNIV_INTERN ulong srv_stats_auto_update = 1; UNIV_INTERN ibool srv_use_doublewrite_buf = TRUE; UNIV_INTERN ibool srv_use_checksums = TRUE; @@ -349,7 +349,7 @@ UNIV_INTERN int srv_query_thread_priority = 0; UNIV_INTERN ulong srv_replication_delay = 0; -UNIV_INTERN ulint srv_io_capacity = 100; +UNIV_INTERN ulong srv_io_capacity = 100; /* Returns the number of IO operations that is X percent of the capacity. PCT_IO(5) -> returns the number of IO operations that is 5% of the max @@ -357,20 +357,20 @@ where max is srv_io_capacity. */ #define PCT_IO(pct) ((ulint) (srv_io_capacity * ((double) pct / 100.0))) UNIV_INTERN long long srv_ibuf_max_size = 0; -UNIV_INTERN ulint srv_ibuf_active_contract = 0; /* 0:disable 1:enable */ -UNIV_INTERN ulint srv_ibuf_accel_rate = 100; +UNIV_INTERN ulong srv_ibuf_active_contract = 0; /* 0:disable 1:enable */ +UNIV_INTERN ulong srv_ibuf_accel_rate = 100; #define PCT_IBUF_IO(pct) ((ulint) (srv_io_capacity * srv_ibuf_accel_rate * ((double) pct / 10000.0))) -UNIV_INTERN ulint srv_flush_neighbor_pages = 1; /* 0:disable 1:enable */ +UNIV_INTERN ulong srv_flush_neighbor_pages = 1; /* 0:disable 1:enable */ -UNIV_INTERN ulint srv_enable_unsafe_group_commit = 0; /* 0:disable 1:enable */ -UNIV_INTERN ulint srv_read_ahead = 3; /* 1: random 2: linear 3: Both */ -UNIV_INTERN ulint srv_adaptive_checkpoint = 0; /* 0: none 1: reflex 2: estimate */ +UNIV_INTERN ulong srv_enable_unsafe_group_commit = 0; /* 0:disable 1:enable */ +UNIV_INTERN ulong srv_read_ahead = 3; /* 1: random 2: linear 3: Both */ +UNIV_INTERN ulong srv_adaptive_checkpoint = 0; /* 0: none 1: reflex 2: estimate */ -UNIV_INTERN ulint srv_expand_import = 0; /* 0:disable 1:enable */ +UNIV_INTERN ulong srv_expand_import = 0; /* 0:disable 1:enable */ -UNIV_INTERN ulint srv_extra_rsegments = 0; /* extra rseg for users */ -UNIV_INTERN ulint srv_dict_size_limit = 0; +UNIV_INTERN ulong srv_extra_rsegments = 0; /* extra rseg for users */ +UNIV_INTERN ulong srv_dict_size_limit = 0; /*-------------------------------------------*/ UNIV_INTERN ulong srv_n_spin_wait_rounds = 20; UNIV_INTERN ulong srv_n_free_tickets_to_enter = 500; From 70fbd5561536d4ed2992db6c6e4655ff705f3754 Mon Sep 17 00:00:00 2001 From: Hakan Kuecuekyilmaz Date: Sun, 1 Nov 2009 16:09:55 +0100 Subject: [PATCH 63/69] BUILD/compile-dist && make dist was not working due to typos. Fixed by renaming a file and editing the typo in Makefile.am --- storage/federatedx/{CMakeFiles.txt => CMakeLists.txt} | 0 storage/federatedx/Makefile.am | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename storage/federatedx/{CMakeFiles.txt => CMakeLists.txt} (100%) diff --git a/storage/federatedx/CMakeFiles.txt b/storage/federatedx/CMakeLists.txt similarity index 100% rename from storage/federatedx/CMakeFiles.txt rename to storage/federatedx/CMakeLists.txt diff --git a/storage/federatedx/Makefile.am b/storage/federatedx/Makefile.am index 802f89d2321..6dbeff1207a 100644 --- a/storage/federatedx/Makefile.am +++ b/storage/federatedx/Makefile.am @@ -34,7 +34,7 @@ libfederatedx_a_SOURCES= ha_federatedx.cc federatedx_txn.cc \ federatedx_io_mysql.cc EXTRA_DIST = CMakeLists.txt plug.in ha_federatedx.h \ - federatedx_probes.d + federatedx_probes.h ha_federatedx_la_SOURCES = ha_federatedx.cc federatedx_txn.cc \ federatedx_io.cc federatedx_io_null.cc \ From a6793a48e20c2aebb1391e2f4f916cf147ff1900 Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Mon, 2 Nov 2009 11:30:21 +0200 Subject: [PATCH 64/69] Fixed problem with schema tables and DECIMAL sql/sql_show.cc: Change decimal item to type holder, to be able to define the decimals and max_length for the DECIMAL field from the schema specification instead of the value of the item. --- sql/sql_show.cc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sql/sql_show.cc b/sql/sql_show.cc index bd9e1fb5c72..0601aa976b8 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -5608,6 +5608,12 @@ TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list) { DBUG_RETURN(0); } + /* + Create a type holder, as we want the type of the item to defined + the type of the object, not the value + */ + if (!(item= new Item_type_holder(thd, item))) + DBUG_RETURN(0); item->unsigned_flag= (fields_info->field_flags & MY_I_S_UNSIGNED); item->decimals= fields_info->field_length%10; item->max_length= (fields_info->field_length/100)%100; From 134ac8483ae21c9980b18d8ee498a35fac073b5c Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 2 Nov 2009 21:17:58 +0200 Subject: [PATCH 65/69] Fixed federatedx building under windows storage/federatedx/CMakeLists.txt: removed the same goals for federated and federatedx --- storage/federatedx/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/storage/federatedx/CMakeLists.txt b/storage/federatedx/CMakeLists.txt index 897fc174505..64930c7227c 100644 --- a/storage/federatedx/CMakeLists.txt +++ b/storage/federatedx/CMakeLists.txt @@ -1,3 +1,3 @@ INCLUDE("${PROJECT_SOURCE_DIR}/storage/mysql_storage_engine.cmake") -SET(FEDERATED_SOURCES ha_federatedx.cc) -MYSQL_STORAGE_ENGINE(FEDERATED) +SET(FEDERATEDX_SOURCES ha_federatedx.cc) +MYSQL_STORAGE_ENGINE(FEDERATEDX) From cea82db95cd76b80755e7629a27fd49924bb3e61 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 3 Nov 2009 13:08:09 +0200 Subject: [PATCH 66/69] Make federated compiling under windows storage/federatedx/ha_federatedx.cc: lower_case_file_system do not suported for windows dll --- storage/federatedx/ha_federatedx.cc | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/storage/federatedx/ha_federatedx.cc b/storage/federatedx/ha_federatedx.cc index e4ea38c9c42..4d4b25da058 100644 --- a/storage/federatedx/ha_federatedx.cc +++ b/storage/federatedx/ha_federatedx.cc @@ -1416,12 +1416,18 @@ static void fill_server(MEM_ROOT *mem_root, FEDERATEDX_SERVER *server, database.reserve(database.length()); database.length(my_casedn_str(system_charset_info, database.c_ptr_safe())); } - + +#ifndef __WIN__ + /* + TODO: there is no unix sockets under windows so the engine should be + revised about using sockets in such environment. + */ if (lower_case_file_system && socket.length()) { socket.reserve(socket.length()); socket.length(my_casedn_str(files_charset_info, socket.c_ptr_safe())); } +#endif /* start with all bytes zeroed */ bzero(server, sizeof(*server)); From 716c09936365c9cfeb2304ca54ffdd95c1031c6e Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 3 Nov 2009 16:39:54 +0200 Subject: [PATCH 67/69] Add federatedx files for build storage/federatedx/CMakeLists.txt: Add fedrated files for build --- storage/federatedx/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/federatedx/CMakeLists.txt b/storage/federatedx/CMakeLists.txt index 64930c7227c..1177e3b7b10 100644 --- a/storage/federatedx/CMakeLists.txt +++ b/storage/federatedx/CMakeLists.txt @@ -1,3 +1,3 @@ INCLUDE("${PROJECT_SOURCE_DIR}/storage/mysql_storage_engine.cmake") -SET(FEDERATEDX_SOURCES ha_federatedx.cc) +SET(FEDERATEDX_SOURCES ha_federatedx.cc federatedx_txn.cc federatedx_io.cc federatedx_io_null.cc federatedx_io_mysql.cc) MYSQL_STORAGE_ENGINE(FEDERATEDX) From 3dcbe769fbc54b90e41888c79e6e43125a8f04d3 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 5 Nov 2009 14:40:01 +0100 Subject: [PATCH 68/69] Fix running test suite from installed package. Some files are in different locations in this case. --- mysql-test/lib/mtr_cases.pm | 4 ++++ mysql-test/mysql-test-run.pl | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/mysql-test/lib/mtr_cases.pm b/mysql-test/lib/mtr_cases.pm index 046887c4428..6cdae0d74d8 100644 --- a/mysql-test/lib/mtr_cases.pm +++ b/mysql-test/lib/mtr_cases.pm @@ -249,6 +249,10 @@ sub collect_one_suite($) $suitedir= my_find_dir($::basedir, ["mysql-test/suite", "mysql-test", + "share/mysql-test/suite", + "share/mysql-test", + "share/mysql/mysql-test/suite", + "share/mysql/mysql-test", # Look in storage engine specific suite dirs "storage/*/mysql-test-suites" ], diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 72e49ed01f8..0b849a4ff5a 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -1001,6 +1001,12 @@ sub command_line_setup { { $basedir= dirname($basedir); } + # For .deb, it's like RPM, but installed in /usr/share/mysql/mysql-test. + # So move up one more directory level yet. + if ( ! $source_dist and ! -d "$basedir/bin" ) + { + $basedir= dirname($basedir); + } # Look for the client binaries directory if ($path_client_bindir) From 9b7a0fddbea952372adc04b1c098411b19cb173b Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 7 Nov 2009 07:29:10 +0100 Subject: [PATCH 69/69] Result file update for new FederatedX --- mysql-test/suite/funcs_1/r/is_engines_federated.result | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mysql-test/suite/funcs_1/r/is_engines_federated.result b/mysql-test/suite/funcs_1/r/is_engines_federated.result index f80fbbc7ece..8057a0266c5 100644 --- a/mysql-test/suite/funcs_1/r/is_engines_federated.result +++ b/mysql-test/suite/funcs_1/r/is_engines_federated.result @@ -2,7 +2,7 @@ SELECT * FROM information_schema.engines WHERE ENGINE = 'FEDERATED'; ENGINE FEDERATED SUPPORT YES -COMMENT Federated MySQL storage engine -TRANSACTIONS NO +COMMENT FederatedX pluggable storage engine +TRANSACTIONS YES XA NO -SAVEPOINTS NO +SAVEPOINTS YES