From 8597ebaed00e5ba789d8387877e67f0d0fd3e6ef Mon Sep 17 00:00:00 2001 From: "grog@eucla.lemis.com" <> Date: Wed, 2 Aug 2006 10:48:47 +0930 Subject: [PATCH 01/39] mysqldump.c: Tidy up style: no space before = or +=. --- client/mysqldump.c | 94 +++++++++++++++++++++++----------------------- 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/client/mysqldump.c b/client/mysqldump.c index 4318e4b9528..5b197499776 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -617,13 +617,13 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), tty_password=1; break; case 'r': - if (!(md_result_file = my_fopen(argument, O_WRONLY | FILE_BINARY, + if (!(md_result_file= my_fopen(argument, O_WRONLY | FILE_BINARY, MYF(MY_WME)))) exit(1); break; case 'W': #ifdef __WIN__ - opt_protocol = MYSQL_PROTOCOL_PIPE; + opt_protocol= MYSQL_PROTOCOL_PIPE; #endif break; case 'N': @@ -638,7 +638,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), #include case 'V': print_version(); exit(0); case 'X': - opt_xml = 1; + opt_xml= 1; extended_insert= opt_drop= opt_lock= opt_disable_keys= opt_autocommit= opt_create_db= 0; break; @@ -1404,7 +1404,7 @@ static uint get_table_structure(char *table, char *db, char *table_type, const char *insert_option; char name_buff[NAME_LEN+3],table_buff[NAME_LEN*2+3]; char table_buff2[NAME_LEN*2+3], query_buff[512]; - FILE *sql_file = md_result_file; + FILE *sql_file= md_result_file; int len; MYSQL_RES *result; MYSQL_ROW row; @@ -1451,7 +1451,7 @@ static uint get_table_structure(char *table, char *db, char *table_type, opt_quoted_table= quote_name(table, table_buff2, 0); if (opt_order_by_primary) - order_by = primary_key_fields(result_table); + order_by= primary_key_fields(result_table); if (!opt_xml && !mysql_query_with_error_report(sock, 0, query_buff)) { @@ -1503,7 +1503,7 @@ static uint get_table_structure(char *table, char *db, char *table_type, field= mysql_fetch_field_direct(result, 0); if (strcmp(field->name, "View") == 0) { - char *scv_buff = NULL; + char *scv_buff= NULL; if (verbose) fprintf(stderr, "-- It's a view, create dummy table for view\n"); @@ -1541,7 +1541,7 @@ static uint get_table_structure(char *table, char *db, char *table_type, my_free(scv_buff, MYF(MY_ALLOW_ZERO_PTR)); safe_exit(EX_MYSQLERR); - DBUG_RETURN(0); + DBUG_RETURN(0); } else my_free(scv_buff, MYF(MY_ALLOW_ZERO_PTR)); @@ -1909,7 +1909,7 @@ static void dump_triggers_for_table (char *table, char *db) char name_buff[NAME_LEN*4+3], table_buff[NAME_LEN*2+3]; char query_buff[512]; uint old_opt_compatible_mode=opt_compatible_mode; - FILE *sql_file = md_result_file; + FILE *sql_file= md_result_file; MYSQL_RES *result; MYSQL_ROW row; @@ -2160,15 +2160,15 @@ static void dump_table(char *table, char *db) end= strmov(end,buff); if (where || order_by) { - query = alloc_query_str((ulong) ((end - query) + 1 + + query= alloc_query_str((ulong) ((end - query) + 1 + (where ? strlen(where) + 7 : 0) + (order_by ? strlen(order_by) + 10 : 0))); - end = strmov(query, query_buf); + end= strmov(query, query_buf); if (where) - end = strxmov(end, " WHERE ", where, NullS); + end= strxmov(end, " WHERE ", where, NullS); if (order_by) - end = strxmov(end, " ORDER BY ", order_by, NullS); + end= strxmov(end, " ORDER BY ", order_by, NullS); } if (mysql_real_query(sock, query, (uint) (end - query))) { @@ -2189,10 +2189,10 @@ static void dump_table(char *table, char *db) result_table); if (where || order_by) { - query = alloc_query_str((ulong) (strlen(query) + 1 + + query= alloc_query_str((ulong) (strlen(query) + 1 + (where ? strlen(where) + 7 : 0) + (order_by ? strlen(order_by) + 10 : 0))); - end = strmov(query, query_buf); + end= strmov(query, query_buf); if (where) { @@ -2201,7 +2201,7 @@ static void dump_table(char *table, char *db) fprintf(md_result_file, "-- WHERE: %s\n", where); check_io(md_result_file); } - end = strxmov(end, " WHERE ", where, NullS); + end= strxmov(end, " WHERE ", where, NullS); } if (order_by) { @@ -2210,7 +2210,7 @@ static void dump_table(char *table, char *db) fprintf(md_result_file, "-- ORDER BY: %s\n", order_by); check_io(md_result_file); } - end = strxmov(end, " ORDER BY ", order_by, NullS); + end= strxmov(end, " ORDER BY ", order_by, NullS); } } if (!opt_xml && !opt_compact) @@ -2283,12 +2283,12 @@ static void dump_table(char *table, char *db) check_io(md_result_file); } - for (i = 0; i < mysql_num_fields(res); i++) + for (i= 0; i < mysql_num_fields(res); i++) { int is_blob; ulong length= lengths[i]; - if (!(field = mysql_fetch_field(res))) + if (!(field= mysql_fetch_field(res))) { my_snprintf(query, QUERY_LENGTH, "%s: Not enough fields from table %s! Aborting.\n", @@ -2360,7 +2360,7 @@ static void dump_table(char *table, char *db) else { /* change any strings ("inf", "-inf", "nan") into NULL */ - char *ptr = row[i]; + char *ptr= row[i]; if (my_isalpha(charset_info, *ptr) || (*ptr == '-' && my_isalpha(charset_info, ptr[1]))) dynstr_append(&extended_row, "NULL"); @@ -2420,7 +2420,7 @@ static void dump_table(char *table, char *db) else { /* change any strings ("inf", "-inf", "nan") into NULL */ - char *ptr = row[i]; + char *ptr= row[i]; if (opt_xml) { print_xml_tag1(md_result_file, "\t\t", "field name=", @@ -2466,10 +2466,10 @@ static void dump_table(char *table, char *db) { ulong row_length; dynstr_append(&extended_row,")"); - row_length = 2 + extended_row.length; + row_length= 2 + extended_row.length; if (total_length + row_length < opt_net_buffer_length) { - total_length += row_length; + total_length+= row_length; fputc(',',md_result_file); /* Always row break */ fputs(extended_row.str,md_result_file); } @@ -2481,7 +2481,7 @@ static void dump_table(char *table, char *db) fputs(insert_pat.str,md_result_file); fputs(extended_row.str,md_result_file); - total_length = row_length+init_length; + total_length= row_length+init_length; } check_io(md_result_file); } @@ -2546,15 +2546,15 @@ err: static char *getTableName(int reset) { - static MYSQL_RES *res = NULL; + static MYSQL_RES *res= NULL; MYSQL_ROW row; if (!res) { - if (!(res = mysql_list_tables(sock,NullS))) + if (!(res= mysql_list_tables(sock,NullS))) return(NULL); } - if ((row = mysql_fetch_row(res))) + if ((row= mysql_fetch_row(res))) return((char*) row[0]); if (reset) @@ -2562,7 +2562,7 @@ static char *getTableName(int reset) else { mysql_free_result(res); - res = NULL; + res= NULL; } return(NULL); } /* getTableName */ @@ -2576,7 +2576,7 @@ static int dump_all_databases() if (mysql_query_with_error_report(sock, &tableres, "SHOW DATABASES")) return 1; - while ((row = mysql_fetch_row(tableres))) + while ((row= mysql_fetch_row(tableres))) { if (dump_all_tables_in_db(row[0])) result=1; @@ -2584,13 +2584,13 @@ static int dump_all_databases() if (seen_views) { if (mysql_query(sock, "SHOW DATABASES") || - !(tableres = mysql_store_result(sock))) + !(tableres= mysql_store_result(sock))) { my_printf_error(0, "Error: Couldn't execute 'SHOW DATABASES': %s", MYF(0), mysql_error(sock)); return 1; } - while ((row = mysql_fetch_row(tableres))) + while ((row= mysql_fetch_row(tableres))) { if (dump_all_views_in_db(row[0])) result=1; @@ -2657,7 +2657,7 @@ static int init_dumping(char *database) "SHOW CREATE DATABASE IF NOT EXISTS %s", qdatabase); - if (mysql_query(sock, qbuf) || !(dbinfo = mysql_store_result(sock))) + if (mysql_query(sock, qbuf) || !(dbinfo= mysql_store_result(sock))) { /* Old server version, dump generic CREATE DATABASE */ if (opt_drop_database) @@ -2674,7 +2674,7 @@ static int init_dumping(char *database) fprintf(md_result_file, "\n/*!40000 DROP DATABASE IF EXISTS %s*/;\n", qdatabase); - row = mysql_fetch_row(dbinfo); + row= mysql_fetch_row(dbinfo); if (row[1]) { fprintf(md_result_file,"\n%s;\n",row[1]); @@ -2983,7 +2983,7 @@ static int do_show_master_status(MYSQL *mysql_con) } else { - row = mysql_fetch_row(master); + row= mysql_fetch_row(master); if (row && row[0] && row[1]) { /* SHOW MASTER STATUS reports file and position */ @@ -3110,7 +3110,7 @@ static void print_value(FILE *file, MYSQL_RES *result, MYSQL_ROW row, MYSQL_FIELD *field; mysql_field_seek(result, 0); - for ( ; (field = mysql_fetch_field(result)) ; row++) + for ( ; (field= mysql_fetch_field(result)) ; row++) { if (!strcmp(field->name,name)) { @@ -3239,17 +3239,17 @@ char check_if_ignore_table(const char *table_name, char *table_type) static char *primary_key_fields(const char *table_name) { - MYSQL_RES *res = NULL; + MYSQL_RES *res= NULL; MYSQL_ROW row; /* SHOW KEYS FROM + table name * 2 (escaped) + 2 quotes + \0 */ char show_keys_buff[15 + 64 * 2 + 3]; - uint result_length = 0; - char *result = 0; + uint result_length= 0; + char *result= 0; my_snprintf(show_keys_buff, sizeof(show_keys_buff), "SHOW KEYS FROM %s", table_name); if (mysql_query(sock, show_keys_buff) || - !(res = mysql_store_result(sock))) + !(res= mysql_store_result(sock))) { fprintf(stderr, "Warning: Couldn't read keys from table %s;" " records are NOT sorted (%s)\n", @@ -3264,12 +3264,12 @@ static char *primary_key_fields(const char *table_name) * row, and UNIQUE keys come before others. So we only need to check * the first key, not all keys. */ - if ((row = mysql_fetch_row(res)) && atoi(row[1]) == 0) + if ((row= mysql_fetch_row(res)) && atoi(row[1]) == 0) { /* Key is unique */ do - result_length += strlen(row[4]) + 1; /* + 1 for ',' or \0 */ - while ((row = mysql_fetch_row(res)) && atoi(row[3]) > 1); + result_length+= strlen(row[4]) + 1; /* + 1 for ',' or \0 */ + while ((row= mysql_fetch_row(res)) && atoi(row[3]) > 1); } /* Build the ORDER BY clause result */ @@ -3277,17 +3277,17 @@ static char *primary_key_fields(const char *table_name) { char *end; /* result (terminating \0 is already in result_length) */ - result = my_malloc(result_length + 10, MYF(MY_WME)); + result= my_malloc(result_length + 10, MYF(MY_WME)); if (!result) { fprintf(stderr, "Error: Not enough memory to store ORDER BY clause\n"); goto cleanup; } mysql_data_seek(res, 0); - row = mysql_fetch_row(res); - end = strmov(result, row[4]); - while ((row = mysql_fetch_row(res)) && atoi(row[3]) > 1) - end = strxmov(end, ",", row[4], NullS); + row= mysql_fetch_row(res); + end= strmov(result, row[4]); + while ((row= mysql_fetch_row(res)) && atoi(row[3]) > 1) + end= strxmov(end, ",", row[4], NullS); } cleanup: @@ -3355,7 +3355,7 @@ static my_bool get_view_structure(char *table, char* db) char table_buff[NAME_LEN*2+3]; char table_buff2[NAME_LEN*2+3]; char query[QUERY_LENGTH]; - FILE *sql_file = md_result_file; + FILE *sql_file= md_result_file; DBUG_ENTER("get_view_structure"); if (tFlag) /* Don't write table creation info */ From 90c9c72605c561fb0ef2b040f7660b8bcc5d28e1 Mon Sep 17 00:00:00 2001 From: "grog@eucla.lemis.com" <> Date: Wed, 2 Aug 2006 11:26:08 +0930 Subject: [PATCH 02/39] BUG#13926: --order-by-primary fails if PKEY contains quote character. Quote PKEY. --- client/mysqldump.c | 16 ++++++-- mysql-test/r/mysqldump.result | 71 +++++++++++++++++++++++++++++++++++ mysql-test/t/mysqldump.test | 20 ++++++++++ 3 files changed, 103 insertions(+), 4 deletions(-) diff --git a/client/mysqldump.c b/client/mysqldump.c index 5b197499776..f8f95ca7fd8 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -3245,6 +3245,8 @@ static char *primary_key_fields(const char *table_name) char show_keys_buff[15 + 64 * 2 + 3]; uint result_length= 0; char *result= 0; + char buff[NAME_LEN * 2 + 3]; + char *quoted_field; my_snprintf(show_keys_buff, sizeof(show_keys_buff), "SHOW KEYS FROM %s", table_name); @@ -3268,8 +3270,10 @@ static char *primary_key_fields(const char *table_name) { /* Key is unique */ do - result_length+= strlen(row[4]) + 1; /* + 1 for ',' or \0 */ - while ((row= mysql_fetch_row(res)) && atoi(row[3]) > 1); + { + quoted_field= quote_name(row[4], buff, 0); + result_length+= strlen(quoted_field) + 1; /* + 1 for ',' or \0 */ + } while ((row= mysql_fetch_row(res)) && atoi(row[3]) > 1); } /* Build the ORDER BY clause result */ @@ -3285,9 +3289,13 @@ static char *primary_key_fields(const char *table_name) } mysql_data_seek(res, 0); row= mysql_fetch_row(res); - end= strmov(result, row[4]); + quoted_field= quote_name(row[4], buff, 0); + end= strmov(result, quoted_field); while ((row= mysql_fetch_row(res)) && atoi(row[3]) > 1) - end= strxmov(end, ",", row[4], NullS); + { + quoted_field= quote_name(row[4], buff, 0); + end= strxmov(end, ",", quoted_field, NullS); + } } cleanup: diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result index 118079906bf..b2a01bde10f 100644 --- a/mysql-test/r/mysqldump.result +++ b/mysql-test/r/mysqldump.result @@ -2867,3 +2867,74 @@ drop view nasishnasifu; drop database mysqldump_views; drop table mysqldump_tables.basetable; drop database mysqldump_tables; +USE test; +DROP TABLE IF EXISTS `t1`; +CREATE TABLE `t1` ( +`a b` INT, +`c"d` INT, +`e``f` INT, +PRIMARY KEY (`a b`, `c"d`, `e``f`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +insert into t1 values (0815, 4711, 2006); +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO,ANSI' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; +DROP TABLE IF EXISTS "t1"; +CREATE TABLE "t1" ( + "a b" int(11) NOT NULL default '0', + "c""d" int(11) NOT NULL default '0', + "e`f" int(11) NOT NULL default '0', + PRIMARY KEY ("a b","c""d","e`f") +); + +LOCK TABLES "t1" WRITE; +/*!40000 ALTER TABLE "t1" DISABLE KEYS */; +INSERT INTO "t1" VALUES (815,4711,2006); +/*!40000 ALTER TABLE "t1" ENABLE KEYS */; +UNLOCK TABLES; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; +DROP TABLE IF EXISTS `t1`; +CREATE TABLE `t1` ( + `a b` int(11) NOT NULL default '0', + `c"d` int(11) NOT NULL default '0', + `e``f` int(11) NOT NULL default '0', + PRIMARY KEY (`a b`,`c"d`,`e``f`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; + +LOCK TABLES `t1` WRITE; +/*!40000 ALTER TABLE `t1` DISABLE KEYS */; +INSERT INTO `t1` VALUES (815,4711,2006); +/*!40000 ALTER TABLE `t1` ENABLE KEYS */; +UNLOCK TABLES; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +DROP TABLE `t1`; +End of 5.0 tests diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test index 858d8910781..a0060863959 100644 --- a/mysql-test/t/mysqldump.test +++ b/mysql-test/t/mysqldump.test @@ -1228,3 +1228,23 @@ drop view nasishnasifu; drop database mysqldump_views; drop table mysqldump_tables.basetable; drop database mysqldump_tables; +USE test; + +# +# BUG#13926: --order-by-primary fails if PKEY contains quote character +# +--disable_warnings +DROP TABLE IF EXISTS `t1`; +CREATE TABLE `t1` ( + `a b` INT, + `c"d` INT, + `e``f` INT, + PRIMARY KEY (`a b`, `c"d`, `e``f`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +insert into t1 values (0815, 4711, 2006); + +--exec $MYSQL_DUMP --skip-comments --compatible=ansi --order-by-primary test t1 +--exec $MYSQL_DUMP --skip-comments --order-by-primary test t1 +DROP TABLE `t1`; +--enable_warnings +--echo End of 5.0 tests From 3183f73601e70a4d07f34780bf933a46e08da05a Mon Sep 17 00:00:00 2001 From: "gkodinov/kgeorge@macbook.gmz" <> Date: Thu, 3 Aug 2006 19:20:30 +0300 Subject: [PATCH 03/39] Bug #21180: Subselect with index for both WHERE and ORDER BY produces empty result Reseting subqueries with "quick" access methods was incomplete. Partially backported the correct reseting of QUICK_SELECTs from 5.x. --- mysql-test/r/subselect.result | 29 +++++++++++++++++++++++++++++ mysql-test/t/subselect.test | 26 ++++++++++++++++++++++++++ sql/opt_range.cc | 14 +++++++++++++- sql/opt_range.h | 4 ++-- 4 files changed, 70 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 983ad628425..e92d9d83d3f 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -2895,3 +2895,32 @@ select * from t1 where NOT(s1 = ALL (select s1/s1 from t1)); s1 2 drop table t1; +create table t1(a int, primary key (a)); +insert into t1 values (10); +create table t2 (a int primary key, b varchar(32), c int, unique key b(c, b)); +insert into t2(a, c, b) values (1,10,'359'), (2,10,'35988'), (3,10,'35989'); +explain SELECT sql_no_cache t1.a, r.a, r.b FROM t1 LEFT JOIN t2 r +ON r.a = (SELECT t2.a FROM t2 WHERE t2.c = t1.a AND t2.b <= '359899' +ORDER BY t2.c DESC, t2.b DESC LIMIT 1) WHERE t1.a = 10; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 system PRIMARY NULL NULL NULL 1 +1 PRIMARY r const PRIMARY PRIMARY 4 const 1 +2 DEPENDENT SUBQUERY t2 range b b 38 NULL 2 Using where +SELECT sql_no_cache t1.a, r.a, r.b FROM t1 LEFT JOIN t2 r +ON r.a = (SELECT t2.a FROM t2 WHERE t2.c = t1.a AND t2.b <= '359899' +ORDER BY t2.c DESC, t2.b DESC LIMIT 1) WHERE t1.a = 10; +a a b +10 3 35989 +explain SELECT sql_no_cache t1.a, r.a, r.b FROM t1 LEFT JOIN t2 r +ON r.a = (SELECT t2.a FROM t2 WHERE t2.c = t1.a AND t2.b <= '359899' +ORDER BY t2.c, t2.b LIMIT 1) WHERE t1.a = 10; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 system PRIMARY NULL NULL NULL 1 +1 PRIMARY r const PRIMARY PRIMARY 4 const 1 +2 DEPENDENT SUBQUERY t2 range b b 38 NULL 2 Using where +SELECT sql_no_cache t1.a, r.a, r.b FROM t1 LEFT JOIN t2 r +ON r.a = (SELECT t2.a FROM t2 WHERE t2.c = t1.a AND t2.b <= '359899' +ORDER BY t2.c, t2.b LIMIT 1) WHERE t1.a = 10; +a a b +10 1 359 +drop table t1,t2; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index fc97d22cbb1..ca3854833f4 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -1861,4 +1861,30 @@ select * from t1 where NOT(s1+1 = ANY (select s1 from t1)); select * from t1 where (s1 = ALL (select s1/s1 from t1)); select * from t1 where NOT(s1 = ALL (select s1/s1 from t1)); drop table t1; + +# +# Bug #21180: Subselect with index for both WHERE and ORDER BY +# produces empty result +# +create table t1(a int, primary key (a)); +insert into t1 values (10); + +create table t2 (a int primary key, b varchar(32), c int, unique key b(c, b)); +insert into t2(a, c, b) values (1,10,'359'), (2,10,'35988'), (3,10,'35989'); + +explain SELECT sql_no_cache t1.a, r.a, r.b FROM t1 LEFT JOIN t2 r + ON r.a = (SELECT t2.a FROM t2 WHERE t2.c = t1.a AND t2.b <= '359899' + ORDER BY t2.c DESC, t2.b DESC LIMIT 1) WHERE t1.a = 10; +SELECT sql_no_cache t1.a, r.a, r.b FROM t1 LEFT JOIN t2 r + ON r.a = (SELECT t2.a FROM t2 WHERE t2.c = t1.a AND t2.b <= '359899' + ORDER BY t2.c DESC, t2.b DESC LIMIT 1) WHERE t1.a = 10; + +explain SELECT sql_no_cache t1.a, r.a, r.b FROM t1 LEFT JOIN t2 r + ON r.a = (SELECT t2.a FROM t2 WHERE t2.c = t1.a AND t2.b <= '359899' + ORDER BY t2.c, t2.b LIMIT 1) WHERE t1.a = 10; +SELECT sql_no_cache t1.a, r.a, r.b FROM t1 LEFT JOIN t2 r + ON r.a = (SELECT t2.a FROM t2 WHERE t2.c = t1.a AND t2.b <= '359899' + ORDER BY t2.c, t2.b LIMIT 1) WHERE t1.a = 10; + +drop table t1,t2; # End of 4.1 tests diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 57903ffe7b9..85125a4521a 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -2980,6 +2980,14 @@ int QUICK_SELECT::get_next() } } +void QUICK_SELECT::reset(void) +{ + next= 0; + it.rewind(); + range= 0; + if (file->inited == handler::NONE) + file->ha_index_init(index); +} /* Get next for geometrical indexes */ @@ -3201,7 +3209,11 @@ bool QUICK_SELECT_DESC::test_if_null_range(QUICK_RANGE *range_arg, return 0; } #endif - +void QUICK_SELECT_DESC::reset(void) +{ + rev_it.rewind(); + QUICK_SELECT::reset(); +} /***************************************************************************** ** Print a quick range for debugging diff --git a/sql/opt_range.h b/sql/opt_range.h index 15f0bf02b34..367a85dc6f2 100644 --- a/sql/opt_range.h +++ b/sql/opt_range.h @@ -86,7 +86,7 @@ public: QUICK_SELECT(THD *thd, TABLE *table,uint index_arg,bool no_alloc=0); virtual ~QUICK_SELECT(); - void reset(void) { next=0; it.rewind(); } + virtual void reset(void); int init() { key_part_info= head->key_info[index].key_part; @@ -120,7 +120,7 @@ private: #ifdef NOT_USED bool test_if_null_range(QUICK_RANGE *range, uint used_key_parts); #endif - void reset(void) { next=0; rev_it.rewind(); } + void reset(void); List rev_ranges; List_iterator rev_it; }; From 9ff33b5d93b64fa26470099b7c96414542e67f78 Mon Sep 17 00:00:00 2001 From: "gkodinov/kgeorge@macbook.gmz" <> Date: Thu, 10 Aug 2006 16:45:02 +0300 Subject: [PATCH 04/39] Bug #16792 query with subselect, join, and group not returning proper values Treat queries with no FROM and aggregate functions as normal queries, so the aggregate function get correctly calculated as if there is 1 row. This means that they will be considered to have one row, so COUNT(*) will return 1 instead of 0. Other aggregates will behave in compatible manner. --- mysql-test/r/func_gconcat.result | 4 ++-- mysql-test/r/func_group.result | 24 ++++++++++++++++++++---- mysql-test/r/subselect.result | 4 ++-- mysql-test/t/func_group.test | 14 ++++++++++++++ sql/opt_sum.cc | 4 ++-- sql/sql_select.cc | 20 +++++++++++++++----- 6 files changed, 55 insertions(+), 15 deletions(-) diff --git a/mysql-test/r/func_gconcat.result b/mysql-test/r/func_gconcat.result index 2c79b8f8ab1..db0125b7d4f 100644 --- a/mysql-test/r/func_gconcat.result +++ b/mysql-test/r/func_gconcat.result @@ -559,14 +559,14 @@ COUNT(*) GROUP_CONCAT(DISTINCT t2.somename SEPARATOR ' |') DROP TABLE t1,t2; select * from (select group_concat('c') from DUAL) t; group_concat('c') -NULL +c create table t1 ( a int not null default 0); select * from (select group_concat(a) from t1) t2; group_concat(a) NULL select group_concat('x') UNION ALL select 1; group_concat('x') -NULL +x 1 drop table t1; CREATE TABLE t1 (id int, a varchar(9)); diff --git a/mysql-test/r/func_group.result b/mysql-test/r/func_group.result index 932ef133087..04f6ebe6398 100644 --- a/mysql-test/r/func_group.result +++ b/mysql-test/r/func_group.result @@ -794,7 +794,7 @@ min(7) NULL select min(7) from DUAL; min(7) -NULL +7 explain select min(7) from t2m join t1m; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away @@ -809,7 +809,7 @@ max(7) NULL select max(7) from DUAL; max(7) -NULL +7 explain select max(7) from t2m join t1m; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away @@ -848,7 +848,7 @@ min(7) NULL select min(7) from DUAL; min(7) -NULL +7 explain select min(7) from t2i join t1i; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2i ALL NULL NULL NULL NULL 1 @@ -864,7 +864,7 @@ max(7) NULL select max(7) from DUAL; max(7) -NULL +7 explain select max(7) from t2i join t1i; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2i ALL NULL NULL NULL NULL 1 @@ -942,3 +942,19 @@ EXPLAIN SELECT MAX(b) FROM t1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 DROP TABLE t1; +CREATE TABLE t1 (a INT, b INT); +INSERT INTO t1 VALUES (1,1),(1,2),(2,3); +SELECT (SELECT COUNT(DISTINCT t1.b)) FROM t1 GROUP BY t1.a; +(SELECT COUNT(DISTINCT t1.b)) +1 +1 +SELECT (SELECT COUNT(DISTINCT 12)) FROM t1 GROUP BY t1.a; +(SELECT COUNT(DISTINCT 12)) +1 +1 +SELECT AVG(2), BIT_AND(2), BIT_OR(2), BIT_XOR(2), COUNT(*), COUNT(12), +COUNT(DISTINCT 12), MIN(2),MAX(2),STD(2), VARIANCE(2),SUM(2), +GROUP_CONCAT(2),GROUP_CONCAT(DISTINCT 2); +AVG(2) BIT_AND(2) BIT_OR(2) BIT_XOR(2) COUNT(*) COUNT(12) COUNT(DISTINCT 12) MIN(2) MAX(2) STD(2) VARIANCE(2) SUM(2) GROUP_CONCAT(2) GROUP_CONCAT(DISTINCT 2) +2.0000 2 2 2 1 1 1 2 2 0.0000 0.0000 2 2 2 +DROP TABLE t1; diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 983ad628425..e6b86980fbb 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -1001,7 +1001,7 @@ INSERT INTO t1 VALUES (1); UPDATE t1 SET i=i+1 WHERE i=(SELECT MAX(i)); select * from t1; i -1 +2 drop table t1; CREATE TABLE t1 (a int(1)); EXPLAIN EXTENDED SELECT (SELECT RAND() FROM t1) FROM t1; @@ -1193,7 +1193,7 @@ UPDATE t1 SET t.i=i+(SELECT MAX(i) FROM (SELECT 1) t); ERROR 42S02: Unknown table 't' in field list select * from t1; i -1 +3 drop table t1; CREATE TABLE t1 ( id int(11) default NULL diff --git a/mysql-test/t/func_group.test b/mysql-test/t/func_group.test index f8a3ed0f25e..18cb5d0a430 100644 --- a/mysql-test/t/func_group.test +++ b/mysql-test/t/func_group.test @@ -617,4 +617,18 @@ SELECT MAX(b) FROM t1; EXPLAIN SELECT MAX(b) FROM t1; DROP TABLE t1; +# +# Bug #16792 query with subselect, join, and group not returning proper values +# +CREATE TABLE t1 (a INT, b INT); +INSERT INTO t1 VALUES (1,1),(1,2),(2,3); + +SELECT (SELECT COUNT(DISTINCT t1.b)) FROM t1 GROUP BY t1.a; +SELECT (SELECT COUNT(DISTINCT 12)) FROM t1 GROUP BY t1.a; +# an attempt to test all aggregate function with no table. +SELECT AVG(2), BIT_AND(2), BIT_OR(2), BIT_XOR(2), COUNT(*), COUNT(12), + COUNT(DISTINCT 12), MIN(2),MAX(2),STD(2), VARIANCE(2),SUM(2), + GROUP_CONCAT(2),GROUP_CONCAT(DISTINCT 2); +DROP TABLE t1; + # End of 4.1 tests diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc index b53fbfd3f80..bc98c96b5a8 100644 --- a/sql/opt_sum.cc +++ b/sql/opt_sum.cc @@ -182,7 +182,7 @@ int opt_sum_query(TABLE_LIST *tables, List &all_fields,COND *conds) Type of range for the key part for this field will be returned in range_fl. */ - if ((outer_tables & table->map) || + if (table->file->inited || (outer_tables & table->map) || !find_key_for_maxmin(0, &ref, item_field->field, conds, &range_fl, &prefix_len)) { @@ -269,7 +269,7 @@ int opt_sum_query(TABLE_LIST *tables, List &all_fields,COND *conds) Type of range for the key part for this field will be returned in range_fl. */ - if ((outer_tables & table->map) || + if (table->file->inited || (outer_tables & table->map) || !find_key_for_maxmin(1, &ref, item_field->field, conds, &range_fl, &prefix_len)) { diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 605ef49bb07..6a3b9fe54cf 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1131,7 +1131,7 @@ JOIN::exec() DBUG_VOID_RETURN; } - if (!tables_list) + if (!tables_list && (tables || !select_lex->with_sum_func)) { // Only test of functions if (select_options & SELECT_DESCRIBE) select_describe(this, FALSE, FALSE, FALSE, @@ -1170,7 +1170,12 @@ JOIN::exec() thd->examined_row_count= 0; DBUG_VOID_RETURN; } - thd->limit_found_rows= thd->examined_row_count= 0; + /* + don't reset the found rows count if there're no tables + as FOUND_ROWS() may be called. + */ + if (tables) + thd->limit_found_rows= thd->examined_row_count= 0; if (zero_result_cause) { @@ -1209,7 +1214,8 @@ JOIN::exec() having= tmp_having; select_describe(this, need_tmp, order != 0 && !skip_sort_order, - select_distinct); + select_distinct, + !tables ? "No tables used" : NullS); DBUG_VOID_RETURN; } @@ -6028,9 +6034,12 @@ do_select(JOIN *join,List *fields,TABLE *table,Procedure *procedure) else end_select=end_send; } - join->join_tab[join->tables-1].next_select=end_select; + if (join->tables) + { + join->join_tab[join->tables-1].next_select=end_select; - join_tab=join->join_tab+join->const_tables; + join_tab=join->join_tab+join->const_tables; + } join->send_records=0; if (join->tables == join->const_tables) { @@ -6048,6 +6057,7 @@ do_select(JOIN *join,List *fields,TABLE *table,Procedure *procedure) } else { + DBUG_ASSERT(join_tab); error= sub_select(join,join_tab,0); if (error >= 0) error= sub_select(join,join_tab,1); From 7d0b042ec5437485e6db72ae846be1432fee524d Mon Sep 17 00:00:00 2001 From: "monty@mysql.com/narttu.mysql.fi" <> Date: Thu, 10 Aug 2006 22:41:19 +0300 Subject: [PATCH 05/39] Better bug fix for #14400 "Query joins wrong rows from table which is subject of "concurrent insert"" The previous bug fix didn't work when using partial keys. Don't use GNUC min/max operations are they are depricated. Fixed valgrind warning --- .bzrignore | 4 +++ include/my_global.h | 5 +-- myisam/mi_rkey.c | 53 ++++++++++++++++------------- myisam/mi_test_all.res | 70 +++++++++++++++++++------------------- myisam/mi_test_all.sh | 3 +- mysql-test/r/myisam.result | 15 ++++++++ mysql-test/t/myisam.test | 17 +++++++++ sql/sql_select.cc | 14 ++++++-- 8 files changed, 116 insertions(+), 65 deletions(-) diff --git a/.bzrignore b/.bzrignore index 1d5a2dcebdb..f37b74c9fc9 100644 --- a/.bzrignore +++ b/.bzrignore @@ -549,3 +549,7 @@ support-files/my-innodb-heavy-4G.cnf ac_available_languages_fragment support-files/MacOSX/postflight support-files/MacOSX/preflight +*/.deps +*.Po +*.Plo +*/.libs/* diff --git a/include/my_global.h b/include/my_global.h index aed4ee4fa01..37e53c65dec 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -348,10 +348,7 @@ int __void__; #endif /* Define some useful general macros */ -#if defined(__cplusplus) && defined(__GNUC__) -#define max(a, b) ((a) >? (b)) -#define min(a, b) ((a) (b) ? (a) : (b)) #define min(a, b) ((a) < (b) ? (a) : (b)) #endif diff --git a/myisam/mi_rkey.c b/myisam/mi_rkey.c index 41c2e173b70..f051558cae5 100644 --- a/myisam/mi_rkey.c +++ b/myisam/mi_rkey.c @@ -78,32 +78,39 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len, if (!_mi_search(info,keyinfo, key_buff, use_key_length, myisam_read_vec[search_flag], info->s->state.key_root[inx])) { - /* - If we are searching for an exact key (including the data pointer) - and this was added by an concurrent insert, - then the result is "key not found". - */ - if ((search_flag == HA_READ_KEY_EXACT) && - (info->lastpos >= info->state->data_file_length)) + if (info->lastpos >= info->state->data_file_length) { - my_errno= HA_ERR_KEY_NOT_FOUND; - info->lastpos= HA_OFFSET_ERROR; - } - else while (info->lastpos >= info->state->data_file_length) - { - /* - Skip rows that are inserted by other threads since we got a lock - Note that this can only happen if we are not searching after an - exact key, because the keys are sorted according to position - */ - if (_mi_search_next(info, keyinfo, info->lastkey, - info->lastkey_length, - myisam_readnext_vec[search_flag], - info->s->state.key_root[inx])) - break; + do + { + uint not_used; + /* + If we are searching for an exact key, abort if we find a bigger + key. + */ + if (search_flag == HA_READ_KEY_EXACT && + (use_key_length == USE_WHOLE_KEY || + _mi_key_cmp(keyinfo->seg, key_buff, info->lastkey, use_key_length, + SEARCH_FIND, ¬_used))) + { + my_errno= HA_ERR_END_OF_FILE; + info->lastpos= HA_OFFSET_ERROR; + break; + } + /* + Skip rows that are inserted by other threads since we got a lock + Note that this can only happen if we are not searching after an + full length exact key, because the keys are sorted + according to position + */ + if (_mi_search_next(info, keyinfo, info->lastkey, + info->lastkey_length, + myisam_readnext_vec[search_flag], + info->s->state.key_root[inx])) + break; + } + while (info->lastpos >= info->state->data_file_length); } } - if (share->concurrent_insert) rw_unlock(&share->key_root_lock[inx]); diff --git a/myisam/mi_test_all.res b/myisam/mi_test_all.res index 94355bf1aa2..5c0d05cc977 100644 --- a/myisam/mi_test_all.res +++ b/myisam/mi_test_all.res @@ -5,46 +5,46 @@ myisamchk: MyISAM file test2 myisamchk: warning: Datafile is almost full, 65532 of 65534 used MyISAM-table 'test2' is usable but should be fixed Commands Used count Errors Recover errors -open 17 0 0 -write 850 0 0 -update 85 0 0 -delete 850 0 0 -close 17 0 0 -extra 102 0 0 -Total 1921 0 0 +open 7 0 0 +write 350 0 0 +update 35 0 0 +delete 350 0 0 +close 7 0 0 +extra 42 0 0 +Total 791 0 0 Commands Used count Errors Recover errors -open 18 0 0 -write 900 0 0 -update 90 0 0 -delete 900 0 0 -close 18 0 0 -extra 108 0 0 -Total 2034 0 0 +open 8 0 0 +write 400 0 0 +update 40 0 0 +delete 400 0 0 +close 8 0 0 +extra 48 0 0 +Total 904 0 0 -real 0m1.054s -user 0m0.410s -sys 0m0.640s +real 0m0.221s +user 0m0.120s +sys 0m0.100s -real 0m1.077s -user 0m0.550s -sys 0m0.530s +real 0m0.222s +user 0m0.140s +sys 0m0.084s -real 0m1.100s -user 0m0.420s -sys 0m0.680s +real 0m0.232s +user 0m0.112s +sys 0m0.120s -real 0m0.783s -user 0m0.590s -sys 0m0.200s +real 0m0.163s +user 0m0.116s +sys 0m0.036s -real 0m0.764s -user 0m0.560s -sys 0m0.210s +real 0m0.159s +user 0m0.136s +sys 0m0.020s -real 0m0.699s -user 0m0.570s -sys 0m0.130s +real 0m0.147s +user 0m0.132s +sys 0m0.016s -real 0m0.991s -user 0m0.630s -sys 0m0.350s +real 0m0.211s +user 0m0.124s +sys 0m0.088s diff --git a/myisam/mi_test_all.sh b/myisam/mi_test_all.sh index 07e71d65675..c1fb12d7c3b 100755 --- a/myisam/mi_test_all.sh +++ b/myisam/mi_test_all.sh @@ -79,7 +79,8 @@ myisamchk$suffix -se test1 # check of myisampack / myisamchk myisampack$suffix --force -s test1 -myisamchk$suffix -es test1 +# Ignore error for index file +myisamchk$suffix -es test1 2>&1 >& /dev/null myisamchk$suffix -rqs test1 myisamchk$suffix -es test1 myisamchk$suffix -rs test1 diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result index e6df3499eb5..e7c1ad7e344 100644 --- a/mysql-test/r/myisam.result +++ b/mysql-test/r/myisam.result @@ -472,3 +472,18 @@ select c1 from t1 order by c1 limit 1; c1 a drop table t1; +create table t1 (a int not null, primary key(a)); +create table t2 (a int not null, b int not null, primary key(a,b)); +insert into t1 values (1),(2),(3),(4),(5),(6); +insert into t2 values (1,1),(2,1); +lock tables t1 read local, t2 read local; +select straight_join * from t1,t2 force index (primary) where t1.a=t2.a; +a a b +1 1 1 +2 2 1 +insert into t2 values(2,0); +select straight_join * from t1,t2 force index (primary) where t1.a=t2.a; +a a b +1 1 1 +2 2 1 +drop table t1,t2; diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test index a502002d30e..bb8dc30395b 100644 --- a/mysql-test/t/myisam.test +++ b/mysql-test/t/myisam.test @@ -458,3 +458,20 @@ insert into t1 values ('a'), ('b'); select c1 from t1 order by c1 limit 1; drop table t1; +# +# Bug #14400 Join could miss concurrently inserted row +# +create table t1 (a int not null, primary key(a)); +create table t2 (a int not null, b int not null, primary key(a,b)); +insert into t1 values (1),(2),(3),(4),(5),(6); +insert into t2 values (1,1),(2,1); +lock tables t1 read local, t2 read local; +select straight_join * from t1,t2 force index (primary) where t1.a=t2.a; +connect (root,localhost,root,,test,$MASTER_MYPORT,master.sock); +insert into t2 values(2,0); +disconnect root; +connection default; +select straight_join * from t1,t2 force index (primary) where t1.a=t2.a; +drop table t1,t2; + +# end of 4.0 tests diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 32658f92416..e28bc81753d 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -7222,6 +7222,8 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param, List &fields) param->copy_funcs.empty(); while ((pos=li++)) { + Field *field; + char *tmp; if (pos->type() == Item::FIELD_ITEM) { Item_field *item=(Item_field*) pos; @@ -7245,13 +7247,21 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param, List &fields) } /* set up save buffer and change result_field to point at saved value */ - Field *field= item->field; + field= item->field; item->result_field=field->new_field(&thd->mem_root,field->table); - char *tmp=(char*) sql_alloc(field->pack_length()+1); + /* + We need to allocate one extra byte for null handling and + another extra byte to not get warnings from purify in + Field_string::val_int + */ + tmp= (char*) sql_alloc(field->pack_length()+2); if (!tmp) goto err; copy->set(tmp, item->result_field); item->result_field->move_field(copy->to_ptr,copy->to_null_ptr,1); +#ifdef HAVE_purify + copy->to_ptr[copy->from_length]= 0; +#endif copy++; } else if ((pos->type() == Item::FUNC_ITEM || From eccd9969c752c06a89d93fd295796a58601136f8 Mon Sep 17 00:00:00 2001 From: "svoj@may.pils.ru" <> Date: Thu, 17 Aug 2006 21:23:00 +0500 Subject: [PATCH 06/39] BUG#19702 - Using myisampack/myisamchk on a FULLTEXT indexed table results in table corrupt Fulltext key has always two keysegs, thus we need to update FT_SEGS (last) element from seg array in case of compressed table. Also we must update ft2_keyinfo. --- myisam/mi_packrec.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/myisam/mi_packrec.c b/myisam/mi_packrec.c index bd2d162d100..0edb3ac1d5d 100644 --- a/myisam/mi_packrec.c +++ b/myisam/mi_packrec.c @@ -16,7 +16,7 @@ /* Functions to compressed records */ -#include "myisamdef.h" +#include "fulltext.h" #define IS_CHAR ((uint) 32768) /* Bit if char (not offset) in tree */ @@ -228,11 +228,19 @@ my_bool _mi_read_pack_info(MI_INFO *info, pbool fix_keys) { for (i=0 ; i < share->base.keys ; i++) { - share->keyinfo[i].keylength+=(uint16) diff_length; - share->keyinfo[i].minlength+=(uint16) diff_length; - share->keyinfo[i].maxlength+=(uint16) diff_length; - share->keyinfo[i].seg[share->keyinfo[i].keysegs].length= - (uint16) rec_reflength; + MI_KEYDEF *keyinfo= &share->keyinfo[i]; + keyinfo->keylength+= (uint16) diff_length; + keyinfo->minlength+= (uint16) diff_length; + keyinfo->maxlength+= (uint16) diff_length; + keyinfo->seg[keyinfo->flag & HA_FULLTEXT ? + FT_SEGS : keyinfo->keysegs].length= (uint16) rec_reflength; + } + if (share->ft2_keyinfo.seg) + { + MI_KEYDEF *ft2_keyinfo= &share->ft2_keyinfo; + ft2_keyinfo->keylength+= (uint16) diff_length; + ft2_keyinfo->minlength+= (uint16) diff_length; + ft2_keyinfo->maxlength+= (uint16) diff_length; } } From 0b2a9d01ed78c3bb51b95f7d5cb1c8359a865986 Mon Sep 17 00:00:00 2001 From: "istruewing@chilla.local" <> Date: Tue, 29 Aug 2006 20:45:04 +0200 Subject: [PATCH 07/39] Bug#14400 - Query joins wrong rows from table which is subject of "concurrent insert" Better fix by Monty: "The previous bug fix didn't work when using partial keys." --- myisam/mi_rkey.c | 43 +++++++++++++++++++++++++++----------- mysql-test/r/myisam.result | 15 +++++++++++++ mysql-test/t/myisam.test | 17 +++++++++++++++ 3 files changed, 63 insertions(+), 12 deletions(-) diff --git a/myisam/mi_rkey.c b/myisam/mi_rkey.c index 70122288d6c..f051558cae5 100644 --- a/myisam/mi_rkey.c +++ b/myisam/mi_rkey.c @@ -66,6 +66,7 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len, if (fast_mi_readinfo(info)) goto err; + if (share->concurrent_insert) rw_rdlock(&share->key_root_lock[inx]); @@ -77,19 +78,37 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len, if (!_mi_search(info,keyinfo, key_buff, use_key_length, myisam_read_vec[search_flag], info->s->state.key_root[inx])) { - while (info->lastpos >= info->state->data_file_length) + if (info->lastpos >= info->state->data_file_length) { - /* - Skip rows that are inserted by other threads since we got a lock - Note that this can only happen if we are not searching after an - exact key, because the keys are sorted according to position - */ - - if (_mi_search_next(info, keyinfo, info->lastkey, - info->lastkey_length, - myisam_readnext_vec[search_flag], - info->s->state.key_root[inx])) - break; + do + { + uint not_used; + /* + If we are searching for an exact key, abort if we find a bigger + key. + */ + if (search_flag == HA_READ_KEY_EXACT && + (use_key_length == USE_WHOLE_KEY || + _mi_key_cmp(keyinfo->seg, key_buff, info->lastkey, use_key_length, + SEARCH_FIND, ¬_used))) + { + my_errno= HA_ERR_END_OF_FILE; + info->lastpos= HA_OFFSET_ERROR; + break; + } + /* + Skip rows that are inserted by other threads since we got a lock + Note that this can only happen if we are not searching after an + full length exact key, because the keys are sorted + according to position + */ + if (_mi_search_next(info, keyinfo, info->lastkey, + info->lastkey_length, + myisam_readnext_vec[search_flag], + info->s->state.key_root[inx])) + break; + } + while (info->lastpos >= info->state->data_file_length); } } if (share->concurrent_insert) diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result index e6df3499eb5..e7c1ad7e344 100644 --- a/mysql-test/r/myisam.result +++ b/mysql-test/r/myisam.result @@ -472,3 +472,18 @@ select c1 from t1 order by c1 limit 1; c1 a drop table t1; +create table t1 (a int not null, primary key(a)); +create table t2 (a int not null, b int not null, primary key(a,b)); +insert into t1 values (1),(2),(3),(4),(5),(6); +insert into t2 values (1,1),(2,1); +lock tables t1 read local, t2 read local; +select straight_join * from t1,t2 force index (primary) where t1.a=t2.a; +a a b +1 1 1 +2 2 1 +insert into t2 values(2,0); +select straight_join * from t1,t2 force index (primary) where t1.a=t2.a; +a a b +1 1 1 +2 2 1 +drop table t1,t2; diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test index a502002d30e..bb8dc30395b 100644 --- a/mysql-test/t/myisam.test +++ b/mysql-test/t/myisam.test @@ -458,3 +458,20 @@ insert into t1 values ('a'), ('b'); select c1 from t1 order by c1 limit 1; drop table t1; +# +# Bug #14400 Join could miss concurrently inserted row +# +create table t1 (a int not null, primary key(a)); +create table t2 (a int not null, b int not null, primary key(a,b)); +insert into t1 values (1),(2),(3),(4),(5),(6); +insert into t2 values (1,1),(2,1); +lock tables t1 read local, t2 read local; +select straight_join * from t1,t2 force index (primary) where t1.a=t2.a; +connect (root,localhost,root,,test,$MASTER_MYPORT,master.sock); +insert into t2 values(2,0); +disconnect root; +connection default; +select straight_join * from t1,t2 force index (primary) where t1.a=t2.a; +drop table t1,t2; + +# end of 4.0 tests From 678e15174eacc04306c09175781e68a462fcc4f7 Mon Sep 17 00:00:00 2001 From: "acurtis/antony@xiphis.org/ltantony.xiphis.org" <> Date: Wed, 30 Aug 2006 13:20:39 -0700 Subject: [PATCH 08/39] Bug#20573 "strict mode: inserts autogenerated auto_increment value bigger than max" Strict mode should fail if autoincrement value is out of range --- include/my_base.h | 4 +++- mysql-test/include/strict_autoinc.inc | 28 ++++++++++++++++++++++ mysql-test/r/strict_autoinc_1myisam.result | 27 +++++++++++++++++++++ mysql-test/r/strict_autoinc_2innodb.result | 27 +++++++++++++++++++++ mysql-test/r/strict_autoinc_3heap.result | 27 +++++++++++++++++++++ mysql-test/r/strict_autoinc_4bdb.result | 27 +++++++++++++++++++++ mysql-test/r/strict_autoinc_5ndb.result | 27 +++++++++++++++++++++ mysql-test/t/strict_autoinc_1myisam.test | 8 +++++++ mysql-test/t/strict_autoinc_2innodb.test | 10 ++++++++ mysql-test/t/strict_autoinc_3heap.test | 8 +++++++ mysql-test/t/strict_autoinc_4bdb.test | 10 ++++++++ mysql-test/t/strict_autoinc_5ndb.test | 10 ++++++++ sql/ha_berkeley.cc | 5 +++- sql/ha_heap.cc | 5 +++- sql/ha_innodb.cc | 3 ++- sql/ha_myisam.cc | 6 ++++- sql/ha_myisammrg.cc | 6 ++++- sql/ha_ndbcluster.cc | 4 +++- sql/handler.cc | 23 ++++++++++++++---- sql/handler.h | 2 +- sql/share/errmsg.txt | 2 ++ 21 files changed, 256 insertions(+), 13 deletions(-) create mode 100644 mysql-test/include/strict_autoinc.inc create mode 100644 mysql-test/r/strict_autoinc_1myisam.result create mode 100644 mysql-test/r/strict_autoinc_2innodb.result create mode 100644 mysql-test/r/strict_autoinc_3heap.result create mode 100644 mysql-test/r/strict_autoinc_4bdb.result create mode 100644 mysql-test/r/strict_autoinc_5ndb.result create mode 100644 mysql-test/t/strict_autoinc_1myisam.test create mode 100644 mysql-test/t/strict_autoinc_2innodb.test create mode 100644 mysql-test/t/strict_autoinc_3heap.test create mode 100644 mysql-test/t/strict_autoinc_4bdb.test create mode 100644 mysql-test/t/strict_autoinc_5ndb.test diff --git a/include/my_base.h b/include/my_base.h index d8a0e15ccbe..cffe1c3caf4 100644 --- a/include/my_base.h +++ b/include/my_base.h @@ -357,8 +357,10 @@ enum ha_base_keytype { #define HA_ERR_TABLE_DEF_CHANGED 159 /* The table changed in storage engine */ #define HA_ERR_TABLE_NEEDS_UPGRADE 160 /* The table changed in storage engine */ #define HA_ERR_TABLE_READONLY 161 /* The table is not writable */ +#define HA_ERR_AUTOINC_READ_FAILED 162/* Failed to get the next autoinc value */ +#define HA_ERR_AUTOINC_ERANGE 163 /* Failed to set the row autoinc value */ -#define HA_ERR_LAST 161 /*Copy last error nr.*/ +#define HA_ERR_LAST 163 /*Copy last error nr.*/ /* Add error numbers before HA_ERR_LAST and change it accordingly. */ #define HA_ERR_ERRORS (HA_ERR_LAST - HA_ERR_FIRST + 1) diff --git a/mysql-test/include/strict_autoinc.inc b/mysql-test/include/strict_autoinc.inc new file mode 100644 index 00000000000..6960440f3a7 --- /dev/null +++ b/mysql-test/include/strict_autoinc.inc @@ -0,0 +1,28 @@ +# +# Test for strict-mode autoincrement +# + +set @org_mode=@@sql_mode; +eval create table t1 +( + `a` tinyint(4) NOT NULL auto_increment, + primary key (`a`) +) engine = $type ; +set @@sql_mode='strict_all_tables'; +--error ER_WARN_DATA_OUT_OF_RANGE +insert into t1 values(1000); +select count(*) from t1; + +set auto_increment_increment=1000; +set auto_increment_offset=700; +--error ER_WARN_DATA_OUT_OF_RANGE +insert into t1 values(null); +select count(*) from t1; + +set @@sql_mode=@org_mode; +insert into t1 values(null); +select * from t1; + +drop table t1; + +# End of test diff --git a/mysql-test/r/strict_autoinc_1myisam.result b/mysql-test/r/strict_autoinc_1myisam.result new file mode 100644 index 00000000000..5d3c2698cda --- /dev/null +++ b/mysql-test/r/strict_autoinc_1myisam.result @@ -0,0 +1,27 @@ +set @org_mode=@@sql_mode; +create table t1 +( +`a` tinyint(4) NOT NULL auto_increment, +primary key (`a`) +) engine = 'MYISAM' ; +set @@sql_mode='strict_all_tables'; +insert into t1 values(1000); +ERROR 22003: Out of range value adjusted for column 'a' at row 1 +select count(*) from t1; +count(*) +0 +set auto_increment_increment=1000; +set auto_increment_offset=700; +insert into t1 values(null); +ERROR 22003: Out of range value adjusted for column 'a' at row 1 +select count(*) from t1; +count(*) +0 +set @@sql_mode=@org_mode; +insert into t1 values(null); +Warnings: +Warning 1264 Out of range value adjusted for column 'a' at row 1 +select * from t1; +a +127 +drop table t1; diff --git a/mysql-test/r/strict_autoinc_2innodb.result b/mysql-test/r/strict_autoinc_2innodb.result new file mode 100644 index 00000000000..f1936ff4de3 --- /dev/null +++ b/mysql-test/r/strict_autoinc_2innodb.result @@ -0,0 +1,27 @@ +set @org_mode=@@sql_mode; +create table t1 +( +`a` tinyint(4) NOT NULL auto_increment, +primary key (`a`) +) engine = 'InnoDB' ; +set @@sql_mode='strict_all_tables'; +insert into t1 values(1000); +ERROR 22003: Out of range value adjusted for column 'a' at row 1 +select count(*) from t1; +count(*) +0 +set auto_increment_increment=1000; +set auto_increment_offset=700; +insert into t1 values(null); +ERROR 22003: Out of range value adjusted for column 'a' at row 1 +select count(*) from t1; +count(*) +0 +set @@sql_mode=@org_mode; +insert into t1 values(null); +Warnings: +Warning 1264 Out of range value adjusted for column 'a' at row 1 +select * from t1; +a +127 +drop table t1; diff --git a/mysql-test/r/strict_autoinc_3heap.result b/mysql-test/r/strict_autoinc_3heap.result new file mode 100644 index 00000000000..aa0be270ac5 --- /dev/null +++ b/mysql-test/r/strict_autoinc_3heap.result @@ -0,0 +1,27 @@ +set @org_mode=@@sql_mode; +create table t1 +( +`a` tinyint(4) NOT NULL auto_increment, +primary key (`a`) +) engine = 'MEMORY' ; +set @@sql_mode='strict_all_tables'; +insert into t1 values(1000); +ERROR 22003: Out of range value adjusted for column 'a' at row 1 +select count(*) from t1; +count(*) +0 +set auto_increment_increment=1000; +set auto_increment_offset=700; +insert into t1 values(null); +ERROR 22003: Out of range value adjusted for column 'a' at row 1 +select count(*) from t1; +count(*) +0 +set @@sql_mode=@org_mode; +insert into t1 values(null); +Warnings: +Warning 1264 Out of range value adjusted for column 'a' at row 1 +select * from t1; +a +127 +drop table t1; diff --git a/mysql-test/r/strict_autoinc_4bdb.result b/mysql-test/r/strict_autoinc_4bdb.result new file mode 100644 index 00000000000..73683b645e2 --- /dev/null +++ b/mysql-test/r/strict_autoinc_4bdb.result @@ -0,0 +1,27 @@ +set @org_mode=@@sql_mode; +create table t1 +( +`a` tinyint(4) NOT NULL auto_increment, +primary key (`a`) +) engine = 'BDB' ; +set @@sql_mode='strict_all_tables'; +insert into t1 values(1000); +ERROR 22003: Out of range value adjusted for column 'a' at row 1 +select count(*) from t1; +count(*) +0 +set auto_increment_increment=1000; +set auto_increment_offset=700; +insert into t1 values(null); +ERROR 22003: Out of range value adjusted for column 'a' at row 1 +select count(*) from t1; +count(*) +0 +set @@sql_mode=@org_mode; +insert into t1 values(null); +Warnings: +Warning 1264 Out of range value adjusted for column 'a' at row 1 +select * from t1; +a +127 +drop table t1; diff --git a/mysql-test/r/strict_autoinc_5ndb.result b/mysql-test/r/strict_autoinc_5ndb.result new file mode 100644 index 00000000000..d0d62d05b32 --- /dev/null +++ b/mysql-test/r/strict_autoinc_5ndb.result @@ -0,0 +1,27 @@ +set @org_mode=@@sql_mode; +create table t1 +( +`a` tinyint(4) NOT NULL auto_increment, +primary key (`a`) +) engine = 'NDB' ; +set @@sql_mode='strict_all_tables'; +insert into t1 values(1000); +ERROR 22003: Out of range value adjusted for column 'a' at row 1 +select count(*) from t1; +count(*) +0 +set auto_increment_increment=1000; +set auto_increment_offset=700; +insert into t1 values(null); +ERROR 22003: Out of range value adjusted for column 'a' at row 1 +select count(*) from t1; +count(*) +0 +set @@sql_mode=@org_mode; +insert into t1 values(null); +Warnings: +Warning 1264 Out of range value adjusted for column 'a' at row 1 +select * from t1; +a +127 +drop table t1; diff --git a/mysql-test/t/strict_autoinc_1myisam.test b/mysql-test/t/strict_autoinc_1myisam.test new file mode 100644 index 00000000000..d9ecce30974 --- /dev/null +++ b/mysql-test/t/strict_autoinc_1myisam.test @@ -0,0 +1,8 @@ +# +# Bug#20573 Strict mode auto-increment +# + +let $type= 'MYISAM' ; +--source include/strict_autoinc.inc + +# end of test diff --git a/mysql-test/t/strict_autoinc_2innodb.test b/mysql-test/t/strict_autoinc_2innodb.test new file mode 100644 index 00000000000..83dfe950938 --- /dev/null +++ b/mysql-test/t/strict_autoinc_2innodb.test @@ -0,0 +1,10 @@ +-- source include/have_innodb.inc + +# +# Bug#20573 Strict mode auto-increment +# + +let $type= 'InnoDB' ; +--source include/strict_autoinc.inc + +# end of test diff --git a/mysql-test/t/strict_autoinc_3heap.test b/mysql-test/t/strict_autoinc_3heap.test new file mode 100644 index 00000000000..f266ecdfda2 --- /dev/null +++ b/mysql-test/t/strict_autoinc_3heap.test @@ -0,0 +1,8 @@ +# +# Bug#20573 Strict mode auto-increment +# + +let $type= 'MEMORY' ; +--source include/strict_autoinc.inc + +# end of test diff --git a/mysql-test/t/strict_autoinc_4bdb.test b/mysql-test/t/strict_autoinc_4bdb.test new file mode 100644 index 00000000000..10d6bfd41e7 --- /dev/null +++ b/mysql-test/t/strict_autoinc_4bdb.test @@ -0,0 +1,10 @@ +-- source include/have_bdb.inc + +# +# Bug#20573 Strict mode auto-increment +# + +let $type= 'BDB' ; +--source include/strict_autoinc.inc + +# end of test diff --git a/mysql-test/t/strict_autoinc_5ndb.test b/mysql-test/t/strict_autoinc_5ndb.test new file mode 100644 index 00000000000..9e2090fddef --- /dev/null +++ b/mysql-test/t/strict_autoinc_5ndb.test @@ -0,0 +1,10 @@ +-- source include/have_ndb.inc + +# +# Bug#20573 Strict mode auto-increment +# + +let $type= 'NDB' ; +--source include/strict_autoinc.inc + +# end of test diff --git a/sql/ha_berkeley.cc b/sql/ha_berkeley.cc index 72af402a0dc..4209bc93d30 100644 --- a/sql/ha_berkeley.cc +++ b/sql/ha_berkeley.cc @@ -953,7 +953,10 @@ int ha_berkeley::write_row(byte * record) if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT) table->timestamp_field->set_time(); if (table->next_number_field && record == table->record[0]) - update_auto_increment(); + { + if ((error= update_auto_increment())) + DBUG_RETURN(error); + } if ((error=pack_row(&row, record,1))) DBUG_RETURN(error); /* purecov: inspected */ diff --git a/sql/ha_heap.cc b/sql/ha_heap.cc index 79d4575ff1b..3aaa0287098 100644 --- a/sql/ha_heap.cc +++ b/sql/ha_heap.cc @@ -176,7 +176,10 @@ int ha_heap::write_row(byte * buf) if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT) table->timestamp_field->set_time(); if (table->next_number_field && buf == table->record[0]) - update_auto_increment(); + { + if ((res= update_auto_increment())) + return res; + } res= heap_write(file,buf); if (!res && (++records_changed*HEAP_STATS_UPDATE_THRESHOLD > file->s->records)) diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index c56be6376d0..4e73d4fb285 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -3252,7 +3252,8 @@ no_commit: /* We must use the handler code to update the auto-increment value to be sure that we increment it correctly. */ - update_auto_increment(); + if ((error= update_auto_increment())) + goto func_exit; auto_inc_used = 1; } diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc index 128cc191434..f35d7efce0b 100644 --- a/sql/ha_myisam.cc +++ b/sql/ha_myisam.cc @@ -316,7 +316,11 @@ int ha_myisam::write_row(byte * buf) or a new row, then update the auto_increment value in the record. */ if (table->next_number_field && buf == table->record[0]) - update_auto_increment(); + { + int error; + if ((error= update_auto_increment())) + return error; + } return mi_write(file,buf); } diff --git a/sql/ha_myisammrg.cc b/sql/ha_myisammrg.cc index 0b6e05fcbd4..cb11d9b0452 100644 --- a/sql/ha_myisammrg.cc +++ b/sql/ha_myisammrg.cc @@ -139,7 +139,11 @@ int ha_myisammrg::write_row(byte * buf) if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT) table->timestamp_field->set_time(); if (table->next_number_field && buf == table->record[0]) - update_auto_increment(); + { + int error; + if ((error= update_auto_increment())) + return error; + } return myrg_write(file,buf); } diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 5d6fe5f984f..d8f33394e1a 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -2130,9 +2130,11 @@ int ha_ndbcluster::write_row(byte *record) if (has_auto_increment) { THD *thd= table->in_use; + int error; m_skip_auto_increment= FALSE; - update_auto_increment(); + if ((error= update_auto_increment())) + DBUG_RETURN(error); /* Ensure that handler is always called for auto_increment values */ thd->next_insert_id= 0; m_skip_auto_increment= !auto_increment_column_changed; diff --git a/sql/handler.cc b/sql/handler.cc index b0051b02d91..d29ae5e4026 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -429,6 +429,8 @@ static int ha_init_errors(void) SETMSG(HA_ERR_TABLE_DEF_CHANGED, ER(ER_TABLE_DEF_CHANGED)); SETMSG(HA_ERR_TABLE_NEEDS_UPGRADE, ER(ER_TABLE_NEEDS_UPGRADE)); SETMSG(HA_ERR_TABLE_READONLY, ER(ER_OPEN_AS_READONLY)); + SETMSG(HA_ERR_AUTOINC_READ_FAILED, ER(ER_AUTOINC_READ_FAILED)); + SETMSG(HA_ERR_AUTOINC_ERANGE, ER(ER_WARN_DATA_OUT_OF_RANGE)); /* Register the error messages for use with my_error(). */ return my_error_register(errmsgs, HA_ERR_FIRST, HA_ERR_LAST); @@ -1542,7 +1544,10 @@ prev_insert_id(ulonglong nr, struct system_variables *variables) RETURN 0 ok - 1 get_auto_increment() was called and returned ~(ulonglong) 0 + HA_ERR_AUTOINC_READ_FAILED + get_auto_increment() was called and returned ~(ulonglong) 0 + HA_ERR_AUTOINC_ERANGE + storing value in field caused strict mode failure. IMPLEMENTATION @@ -1586,13 +1591,12 @@ prev_insert_id(ulonglong nr, struct system_variables *variables) thd->next_insert_id is cleared after it's been used for a statement. */ -bool handler::update_auto_increment() +int handler::update_auto_increment() { ulonglong nr; THD *thd= table->in_use; struct system_variables *variables= &thd->variables; bool auto_increment_field_not_null; - bool result= 0; DBUG_ENTER("handler::update_auto_increment"); /* @@ -1616,7 +1620,7 @@ bool handler::update_auto_increment() if (!(nr= thd->next_insert_id)) { if ((nr= get_auto_increment()) == ~(ulonglong) 0) - result= 1; // Mark failure + DBUG_RETURN(HA_ERR_AUTOINC_READ_FAILED); // Mark failure if (variables->auto_increment_increment != 1) nr= next_insert_id(nr-1, variables); @@ -1636,6 +1640,7 @@ bool handler::update_auto_increment() if (likely(!table->next_number_field->store((longlong) nr, TRUE))) thd->insert_id((ulonglong) nr); else + if (thd->killed != THD::KILL_BAD_DATA) /* did we fail strict mode? */ { /* overflow of the field; we'll use the max value, however we try to @@ -1646,6 +1651,8 @@ bool handler::update_auto_increment() if (unlikely(table->next_number_field->store((longlong) nr, TRUE))) thd->insert_id(nr= table->next_number_field->val_int()); } + else + DBUG_RETURN(HA_ERR_AUTOINC_ERANGE); /* We can't set next_insert_id if the auto-increment key is not the @@ -1666,7 +1673,7 @@ bool handler::update_auto_increment() /* Mark that we generated a new value */ auto_increment_column_changed=1; - DBUG_RETURN(result); + DBUG_RETURN(0); } /* @@ -1864,6 +1871,12 @@ void handler::print_error(int error, myf errflag) case HA_ERR_TABLE_READONLY: textno= ER_OPEN_AS_READONLY; break; + case HA_ERR_AUTOINC_READ_FAILED: + textno= ER_AUTOINC_READ_FAILED; + break; + case HA_ERR_AUTOINC_ERANGE: + textno= ER_WARN_DATA_OUT_OF_RANGE; + break; default: { /* The error was "unknown" to this function. diff --git a/sql/handler.h b/sql/handler.h index 44de0cc715a..051f5bd31bf 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -565,7 +565,7 @@ public: virtual ~handler(void) { /* TODO: DBUG_ASSERT(inited == NONE); */ } int ha_open(const char *name, int mode, int test_if_locked); void adjust_next_insert_id_after_explicit_value(ulonglong nr); - bool update_auto_increment(); + int update_auto_increment(); virtual void print_error(int error, myf errflag); virtual bool get_error_message(int error, String *buf); uint get_dup_key(int error); diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index e90f54608e1..94e0d6e0db5 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -5623,3 +5623,5 @@ ER_NO_TRIGGERS_ON_SYSTEM_SCHEMA eng "Triggers can not be created on system tables" ER_REMOVED_SPACES eng "Leading spaces are removed from name '%s'" +ER_AUTOINC_READ_FAILED + eng "Failed to read auto-increment value from storage engine" From 45568bbe11c225aacf87b48ac1d856c1092f0fb6 Mon Sep 17 00:00:00 2001 From: "aelkin/elkin@dsl-hkigw8-feaaf900-177.dhcp.inet.fi" <> Date: Thu, 31 Aug 2006 02:00:40 +0300 Subject: [PATCH 09/39] BUG#18822 LOAD DATA FROM MASTER corrupts data there is a bunch of dups. It has been decided to declare this feature as deprecated. --- sql/sql_yacc.yy | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 162b4183c84..bce9aed79fc 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -4800,14 +4800,16 @@ load: LOAD DATA_SYM load_data_lock opt_local INFILE TEXT_STRING_sys LOAD TABLE_SYM table_ident FROM MASTER_SYM { Lex->sql_command = SQLCOM_LOAD_MASTER_TABLE; + WARN_DEPRECATED("LOAD TABLE FROM MASTER", "mysqldump or future BACKUP/RESTORE DATABASE facility"); if (!Select->add_table_to_list(YYTHD, $3, NULL, TL_OPTION_UPDATING)) YYABORT; - + } | LOAD DATA_SYM FROM MASTER_SYM { Lex->sql_command = SQLCOM_LOAD_MASTER_DATA; + WARN_DEPRECATED("LOAD DATA FROM MASTER", "mysqldump or future BACKUP/RESTORE DATABASE facility"); }; opt_local: From e5bc4c7e779e81fe089e33a6207c907860f4b60d Mon Sep 17 00:00:00 2001 From: "gkodinov/kgeorge@macbook.gmz" <> Date: Thu, 31 Aug 2006 18:00:25 +0300 Subject: [PATCH 10/39] Bug#14654 : Cannot select from the same table twice within a UNION statement Made the parser to support parenthesis around UNION branches. This is done by amending the rules of the parser so it generates the correct structure. Currently it supports arbitrary subquery/join/parenthesis operations in the EXISTS clause. In the IN/scalar subquery case it will allow adding nested parenthesis only if there is an UNION clause after the parenthesis. Otherwise it will just treat the multiple nested parenthesis as a scalar expression. It adds extra lex level for ((SELECT ...) UNION ...) to accommodate for the UNION clause. --- mysql-test/r/subselect.result | 25 ++++++ mysql-test/t/subselect.test | 26 ++++++ sql/sql_yacc.yy | 146 +++++++++++++++++----------------- 3 files changed, 125 insertions(+), 72 deletions(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index b7f0866019c..ef11f1063e4 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -3346,3 +3346,28 @@ ORDER BY t1.t DESC LIMIT 1); i1 i2 t i1 i2 t 24 1 2005-05-27 12:40:30 24 1 2006-06-20 12:29:40 DROP TABLE t1, t2; +CREATE TABLE t1 (i INT); +(SELECT i FROM t1) UNION (SELECT i FROM t1); +i +SELECT sql_no_cache * FROM t1 WHERE NOT EXISTS +( +(SELECT i FROM t1) UNION +(SELECT i FROM t1) +); +i +SELECT * FROM t1 +WHERE NOT EXISTS (((SELECT i FROM t1) UNION (SELECT i FROM t1))); +i +explain select ((select t11.i from t1 t11) union (select t12.i from t1 t12)) +from t1; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'union (select t12.i from t1 t12)) +from t1' at line 1 +explain select * from t1 where not exists +((select t11.i from t1 t11) union (select t12.i from t1 t12)); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 system NULL NULL NULL NULL 0 const row not found +2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL No tables used +3 SUBQUERY NULL NULL NULL NULL NULL NULL NULL no matching row in const table +4 UNION t12 system NULL NULL NULL NULL 0 const row not found +NULL UNION RESULT ALL NULL NULL NULL NULL NULL +DROP TABLE t1; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index c9ed62f0e54..a47221dbd02 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -2257,3 +2257,29 @@ SELECT * FROM t1,t2 ORDER BY t1.t DESC LIMIT 1); DROP TABLE t1, t2; + +# +# Bug#14654 : Cannot select from the same table twice within a UNION +# statement +# +CREATE TABLE t1 (i INT); + +(SELECT i FROM t1) UNION (SELECT i FROM t1); +SELECT sql_no_cache * FROM t1 WHERE NOT EXISTS + ( + (SELECT i FROM t1) UNION + (SELECT i FROM t1) + ); + +SELECT * FROM t1 +WHERE NOT EXISTS (((SELECT i FROM t1) UNION (SELECT i FROM t1))); + +#TODO:not supported +--error 1064 +explain select ((select t11.i from t1 t11) union (select t12.i from t1 t12)) + from t1; +#supported +explain select * from t1 where not exists + ((select t11.i from t1 t11) union (select t12.i from t1 t12)); + +DROP TABLE t1; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 5d0a583f7d1..fd7e9fa1ab4 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -725,8 +725,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); predicate bit_expr bit_term bit_factor value_expr term factor table_wild simple_expr udf_expr expr_or_default set_expr_or_default interval_expr - param_marker singlerow_subselect singlerow_subselect_init - exists_subselect exists_subselect_init geometry_function + param_marker geometry_function signed_literal now_or_signed_literal opt_escape sp_opt_default simple_ident_nospvar simple_ident_q @@ -791,7 +790,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %type internal_variable_name -%type in_subselect in_subselect_init +%type subselect subselect_init get_select_lex %type comp_op @@ -3914,12 +3913,14 @@ select_paren: yyerror(ER(ER_SYNTAX_ERROR)); YYABORT; } - if (sel->linkage == UNION_TYPE && - !sel->master_unit()->first_select()->braces) - { - yyerror(ER(ER_SYNTAX_ERROR)); - YYABORT; - } + if (sel->linkage == UNION_TYPE && + !sel->master_unit()->first_select()->braces && + sel->master_unit()->first_select()->linkage == + UNION_TYPE) + { + yyerror(ER(ER_SYNTAX_ERROR)); + YYABORT; + } /* select in braces, can't contain global parameters */ if (sel->master_unit()->fake_select_lex) sel->master_unit()->global_parameters= @@ -4177,37 +4178,37 @@ bool_pri: | bool_pri EQUAL_SYM predicate { $$= new Item_func_equal($1,$3); } | bool_pri comp_op predicate %prec EQ { $$= (*$2)(0)->create($1,$3); } - | bool_pri comp_op all_or_any in_subselect %prec EQ - { $$= all_any_subquery_creator($1, $2, $3, $4); } + | bool_pri comp_op all_or_any '(' subselect ')' %prec EQ + { $$= all_any_subquery_creator($1, $2, $3, $5); } | predicate ; predicate: - bit_expr IN_SYM '(' expr_list ')' - { - if ($4->elements == 1) - $$= new Item_func_eq($1, $4->head()); - else - { - $4->push_front($1); - $$= new Item_func_in(*$4); - } - } - | bit_expr not IN_SYM '(' expr_list ')' + bit_expr IN_SYM '(' subselect ')' + { $$= new Item_in_subselect($1, $4); } + | bit_expr not IN_SYM '(' subselect ')' + { $$= negate_expression(YYTHD, new Item_in_subselect($1, $5)); } + | bit_expr IN_SYM '(' expr ')' { - if ($5->elements == 1) - $$= new Item_func_ne($1, $5->head()); - else - { - $5->push_front($1); - Item_func_in *item = new Item_func_in(*$5); + $$= new Item_func_eq($1, $4); + } + | bit_expr IN_SYM '(' expr ',' expr_list ')' + { + $6->push_front($4); + $6->push_front($1); + $$= new Item_func_in(*$6); + } + | bit_expr not IN_SYM '(' expr ')' + { + $$= new Item_func_ne($1, $5); + } + | bit_expr not IN_SYM '(' expr ',' expr_list ')' + { + $7->push_front($5); + $7->push_front($1); + Item_func_in *item = new Item_func_in(*$7); item->negate(); $$= item; - } } - | bit_expr IN_SYM in_subselect - { $$= new Item_in_subselect($1, $3); } - | bit_expr not IN_SYM in_subselect - { $$= negate_expression(YYTHD, new Item_in_subselect($1, $4)); } | bit_expr BETWEEN_SYM bit_expr AND_SYM predicate { $$= new Item_func_between($1,$3,$5); } | bit_expr not BETWEEN_SYM bit_expr AND_SYM predicate @@ -4329,6 +4330,10 @@ simple_expr: | '-' simple_expr %prec NEG { $$= new Item_func_neg($2); } | '~' simple_expr %prec NEG { $$= new Item_func_bit_neg($2); } | not2 simple_expr %prec NEG { $$= negate_expression(YYTHD, $2); } + | '(' subselect ')' + { + $$= new Item_singlerow_subselect($2); + } | '(' expr ')' { $$= $2; } | '(' expr ',' expr_list ')' { @@ -4340,8 +4345,10 @@ simple_expr: $5->push_front($3); $$= new Item_row(*$5); } - | EXISTS exists_subselect { $$= $2; } - | singlerow_subselect { $$= $1; } + | EXISTS '(' subselect ')' + { + $$= new Item_exists_subselect($3); + } | '{' ident expr '}' { $$= $3; } | MATCH ident_list_arg AGAINST '(' bit_expr fulltext_options ')' { $2->push_front($5); @@ -8863,49 +8870,38 @@ union_option: | ALL { $$=0; } ; -singlerow_subselect: - subselect_start singlerow_subselect_init - subselect_end - { - $$= $2; - }; +subselect: + SELECT_SYM subselect_start subselect_init subselect_end + { + $$= $3; + } + | '(' subselect_start subselect ')' + { + LEX *lex= Lex; + THD *thd= YYTHD; + /* + note that a local variable can't be used for + $3 as it's used in local variable construction + and some compilers can't guarnatee the order + in which the local variables are initialized. + */ + List_iterator it($3->item_list); + Item *item; + /* + we must fill the items list for the "derived table". + */ + while ((item= it++)) + add_item_to_list(thd, item); + } + union_clause subselect_end { $$= $3; }; -singlerow_subselect_init: - select_init2 - { - $$= new Item_singlerow_subselect(Lex->current_select-> - master_unit()->first_select()); - }; - -exists_subselect: - subselect_start exists_subselect_init - subselect_end - { - $$= $2; - }; - -exists_subselect_init: - select_init2 - { - $$= new Item_exists_subselect(Lex->current_select->master_unit()-> - first_select()); - }; - -in_subselect: - subselect_start in_subselect_init - subselect_end - { - $$= $2; - }; - -in_subselect_init: +subselect_init: select_init2 { $$= Lex->current_select->master_unit()->first_select(); }; subselect_start: - '(' SELECT_SYM { LEX *lex=Lex; if (lex->sql_command == (int)SQLCOM_HA_READ || @@ -8914,12 +8910,18 @@ subselect_start: yyerror(ER(ER_SYNTAX_ERROR)); YYABORT; } + /* + we are making a "derived table" for the parenthesis + as we need to have a lex level to fit the union + after the parenthesis, e.g. + (SELECT .. ) UNION ... becomes + SELECT * FROM ((SELECT ...) UNION ...) + */ if (mysql_new_select(Lex, 1)) YYABORT; }; subselect_end: - ')' { LEX *lex=Lex; lex->pop_context(); From 0e96978cf63a4e1668291a049ecebcc011e7c2ae Mon Sep 17 00:00:00 2001 From: "igor@rurik.mysql.com" <> Date: Fri, 1 Sep 2006 04:23:04 -0700 Subject: [PATCH 11/39] Fixed bug #16081: row equalities were not taken into account by the optimizer. Now all row equalities are converted into conjunctions of equalities between row elements. They are taken into account by the optimizer together with the original regular equality predicates. --- mysql-test/r/join_outer.result | 2 +- mysql-test/r/row.result | 125 +++++++++ mysql-test/t/row.test | 47 ++++ sql/sql_list.h | 6 +- sql/sql_select.cc | 496 +++++++++++++++++++++------------ 5 files changed, 500 insertions(+), 176 deletions(-) diff --git a/mysql-test/r/join_outer.result b/mysql-test/r/join_outer.result index 2d9652ff0e3..89bb26c4b3f 100644 --- a/mysql-test/r/join_outer.result +++ b/mysql-test/r/join_outer.result @@ -1126,7 +1126,7 @@ a b a b 7 8 7 5 EXPLAIN SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a = t2.a OR t1.a = t2.b; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t2 ALL PRIMARY NULL NULL NULL 4 Using where +1 SIMPLE t2 ALL PRIMARY NULL NULL NULL 4 1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 test.t2.a 1 EXPLAIN SELECT * FROM t1 LEFT JOIN t2 ON t1.a = t2.a WHERE t1.a IN(t2.a, t2.b); id select_type table type possible_keys key key_len ref rows Extra diff --git a/mysql-test/r/row.result b/mysql-test/r/row.result index 1762587415d..5b5f8b7b954 100644 --- a/mysql-test/r/row.result +++ b/mysql-test/r/row.result @@ -181,3 +181,128 @@ SELECT ROW(1,1,1) = ROW(1,1,1) as `1`, ROW(1,1,1) = ROW(1,2,1) as `0`, ROW(1,NUL select row(NULL,1)=(2,0); row(NULL,1)=(2,0) 0 +CREATE TABLE t1 (a int, b int, PRIMARY KEY (a,b)); +INSERT INTO t1 VALUES (1,1), (2,1), (3,1), (1,2), (3,2), (3,3); +EXPLAIN SELECT * FROM t1 WHERE a=3 AND b=2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 const PRIMARY PRIMARY 8 const,const 1 Using index +EXPLAIN SELECT * FROM t1 WHERE (a,b)=(3,2); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 const PRIMARY PRIMARY 8 const,const 1 Using index +SELECT * FROM t1 WHERE a=3 and b=2; +a b +3 2 +SELECT * FROM t1 WHERE (a,b)=(3,2); +a b +3 2 +CREATE TABLE t2 (a int, b int, c int, PRIMARY KEY (a,b,c)); +INSERT INTO t2 VALUES +(1,1,2), (3,1,3), (1,2,2), (4,4,2), +(1,1,1), (3,1,1), (1,2,1); +EXPLAIN SELECT * FROM t1,t2 WHERE t1.a=t2.a AND t1.b=t2.b; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index PRIMARY PRIMARY 8 NULL 6 Using index +1 SIMPLE t2 ref PRIMARY PRIMARY 8 test.t1.a,test.t1.b 1 Using index +EXPLAIN SELECT * FROM t1,t2 WHERE (t1.a,t1.b)=(t2.a,t2.b); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index PRIMARY PRIMARY 8 NULL 6 Using index +1 SIMPLE t2 ref PRIMARY PRIMARY 8 test.t1.a,test.t1.b 1 Using index +SELECT * FROM t1,t2 WHERE t1.a=t2.a and t1.b=t2.b; +a b a b c +1 1 1 1 1 +1 1 1 1 2 +1 2 1 2 1 +1 2 1 2 2 +3 1 3 1 1 +3 1 3 1 3 +SELECT * FROM t1,t2 WHERE (t1.a,t1.b)=(t2.a,t2.b); +a b a b c +1 1 1 1 1 +1 1 1 1 2 +1 2 1 2 1 +1 2 1 2 2 +3 1 3 1 1 +3 1 3 1 3 +EXPLAIN SELECT * FROM t1,t2 WHERE t1.a=t2.a AND t1.b=2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index PRIMARY PRIMARY 8 NULL 5 Using where; Using index +1 SIMPLE t2 ref PRIMARY PRIMARY 4 test.t1.a 1 Using index +EXPLAIN SELECT * FROM t1,t2 WHERE (t1.a,t1.b)=(t2.a,2); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index PRIMARY PRIMARY 8 NULL 5 Using where; Using index +1 SIMPLE t2 ref PRIMARY PRIMARY 4 test.t1.a 1 Using index +SELECT * FROM t1,t2 WHERE t1.a=1 and t1.b=t2.b; +a b a b c +1 1 1 1 2 +1 1 3 1 3 +1 2 1 2 2 +1 1 1 1 1 +1 1 3 1 1 +1 2 1 2 1 +SELECT * FROM t1,t2 WHERE (t1.a,t1.b)=(t2.a,2); +a b a b c +1 2 1 1 1 +1 2 1 1 2 +1 2 1 2 1 +1 2 1 2 2 +3 2 3 1 1 +3 2 3 1 3 +EXPLAIN EXTENDED SELECT * FROM t1,t2 WHERE (t1.a,t1.b)=(t2.a,t2.b+1); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index PRIMARY PRIMARY 8 NULL 6 Using index +1 SIMPLE t2 ref PRIMARY PRIMARY 4 test.t1.a 1 Using where; Using index +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t1` join `test`.`t2` where ((`test`.`t2`.`a` = `test`.`t1`.`a`) and (`test`.`t1`.`b` = (`test`.`t2`.`b` + 1))) +SELECT * FROM t1,t2 WHERE (t1.a,t1.b)=(t2.a,t2.b+1); +a b a b c +1 2 1 1 1 +1 2 1 1 2 +3 2 3 1 1 +3 2 3 1 3 +EXPLAIN EXTENDED SELECT * FROM t1,t2 WHERE (t1.a-1,t1.b)=(t2.a-1,t2.b+1); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index NULL PRIMARY 8 NULL 6 Using index +1 SIMPLE t2 index NULL PRIMARY 12 NULL 7 Using where; Using index +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t1` join `test`.`t2` where (((`test`.`t1`.`a` - 1) = (`test`.`t2`.`a` - 1)) and (`test`.`t1`.`b` = (`test`.`t2`.`b` + 1))) +SELECT * FROM t1,t2 WHERE (t1.a-1,t1.b)=(t2.a-1,t2.b+1); +a b a b c +1 2 1 1 2 +3 2 3 1 3 +1 2 1 1 1 +3 2 3 1 1 +EXPLAIN SELECT * FROM t2 WHERE a=3 AND b=2; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ref PRIMARY PRIMARY 8 const,const 1 Using index +EXPLAIN SELECT * FROM t2 WHERE (a,b)=(3,2); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 ref PRIMARY PRIMARY 8 const,const 1 Using index +SELECT * FROM t2 WHERE a=3 and b=2; +a b c +SELECT * FROM t2 WHERE (a,b)=(3,2); +a b c +EXPLAIN SELECT * FROM t1,t2 WHERE t2.a=t1.a AND t2.b=2 AND t2.c=1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index PRIMARY PRIMARY 8 NULL 6 Using index +1 SIMPLE t2 eq_ref PRIMARY PRIMARY 12 test.t1.a,const,const 1 Using index +EXPLAIN EXTENDED SELECT * FROM t1,t2 WHERE (t2.a,(t2.b,t2.c))=(t1.a,(2,1)); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index PRIMARY PRIMARY 8 NULL 6 Using index +1 SIMPLE t2 eq_ref PRIMARY PRIMARY 12 test.t1.a,const,const 1 Using index +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t1` join `test`.`t2` where ((`test`.`t2`.`c` = 1) and (`test`.`t2`.`b` = 2) and (`test`.`t2`.`a` = `test`.`t1`.`a`)) +SELECT * FROM t1,t2 WHERE (t2.a,(t2.b,t2.c))=(t1.a,(2,1)); +a b a b c +1 1 1 2 1 +1 2 1 2 1 +EXPLAIN EXTENDED SELECT * FROM t1,t2 WHERE t2.a=t1.a AND (t2.b,t2.c)=(2,1); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index PRIMARY PRIMARY 8 NULL 6 Using index +1 SIMPLE t2 eq_ref PRIMARY PRIMARY 12 test.t1.a,const,const 1 Using index +Warnings: +Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t2`.`a` AS `a`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t1` join `test`.`t2` where ((`test`.`t2`.`c` = 1) and (`test`.`t2`.`b` = 2) and (`test`.`t2`.`a` = `test`.`t1`.`a`)) +SELECT * FROM t1,t2 WHERE t2.a=t1.a AND (t2.b,t2.c)=(2,1); +a b a b c +1 1 1 2 1 +1 2 1 2 1 +DROP TABLE t1,t2; diff --git a/mysql-test/t/row.test b/mysql-test/t/row.test index 6301cc0f584..63c611e6be6 100644 --- a/mysql-test/t/row.test +++ b/mysql-test/t/row.test @@ -92,3 +92,50 @@ SELECT ROW(NULL,10) <=> ROW(3,NULL); # SELECT ROW(1,1,1) = ROW(1,1,1) as `1`, ROW(1,1,1) = ROW(1,2,1) as `0`, ROW(1,NULL,1) = ROW(2,2,1) as `0`, ROW(1,NULL,1) = ROW(1,2,2) as `0`, ROW(1,NULL,1) = ROW(1,2,1) as `null` ; select row(NULL,1)=(2,0); + +# +# Bug #16081: row equalities are to be used for query optimizations +# + +CREATE TABLE t1 (a int, b int, PRIMARY KEY (a,b)); +INSERT INTO t1 VALUES (1,1), (2,1), (3,1), (1,2), (3,2), (3,3); + +EXPLAIN SELECT * FROM t1 WHERE a=3 AND b=2; +EXPLAIN SELECT * FROM t1 WHERE (a,b)=(3,2); +SELECT * FROM t1 WHERE a=3 and b=2; +SELECT * FROM t1 WHERE (a,b)=(3,2); + +CREATE TABLE t2 (a int, b int, c int, PRIMARY KEY (a,b,c)); +INSERT INTO t2 VALUES + (1,1,2), (3,1,3), (1,2,2), (4,4,2), + (1,1,1), (3,1,1), (1,2,1); + +EXPLAIN SELECT * FROM t1,t2 WHERE t1.a=t2.a AND t1.b=t2.b; +EXPLAIN SELECT * FROM t1,t2 WHERE (t1.a,t1.b)=(t2.a,t2.b); +SELECT * FROM t1,t2 WHERE t1.a=t2.a and t1.b=t2.b; +SELECT * FROM t1,t2 WHERE (t1.a,t1.b)=(t2.a,t2.b); + +EXPLAIN SELECT * FROM t1,t2 WHERE t1.a=t2.a AND t1.b=2; +EXPLAIN SELECT * FROM t1,t2 WHERE (t1.a,t1.b)=(t2.a,2); +SELECT * FROM t1,t2 WHERE t1.a=1 and t1.b=t2.b; +SELECT * FROM t1,t2 WHERE (t1.a,t1.b)=(t2.a,2); + +EXPLAIN EXTENDED SELECT * FROM t1,t2 WHERE (t1.a,t1.b)=(t2.a,t2.b+1); +SELECT * FROM t1,t2 WHERE (t1.a,t1.b)=(t2.a,t2.b+1); + +EXPLAIN EXTENDED SELECT * FROM t1,t2 WHERE (t1.a-1,t1.b)=(t2.a-1,t2.b+1); +SELECT * FROM t1,t2 WHERE (t1.a-1,t1.b)=(t2.a-1,t2.b+1); + +EXPLAIN SELECT * FROM t2 WHERE a=3 AND b=2; +EXPLAIN SELECT * FROM t2 WHERE (a,b)=(3,2); +SELECT * FROM t2 WHERE a=3 and b=2; +SELECT * FROM t2 WHERE (a,b)=(3,2); + +EXPLAIN SELECT * FROM t1,t2 WHERE t2.a=t1.a AND t2.b=2 AND t2.c=1; +EXPLAIN EXTENDED SELECT * FROM t1,t2 WHERE (t2.a,(t2.b,t2.c))=(t1.a,(2,1)); +SELECT * FROM t1,t2 WHERE (t2.a,(t2.b,t2.c))=(t1.a,(2,1)); + +EXPLAIN EXTENDED SELECT * FROM t1,t2 WHERE t2.a=t1.a AND (t2.b,t2.c)=(2,1); +SELECT * FROM t1,t2 WHERE t2.a=t1.a AND (t2.b,t2.c)=(2,1); + +DROP TABLE t1,t2; diff --git a/sql/sql_list.h b/sql/sql_list.h index b2bcc4ea401..afad6d0f6ac 100644 --- a/sql/sql_list.h +++ b/sql/sql_list.h @@ -94,9 +94,9 @@ public: inline base_list() { empty(); } inline base_list(const base_list &tmp) :Sql_alloc() { - elements=tmp.elements; - first=tmp.first; - last=tmp.last; + elements= tmp.elements; + first= tmp.first; + last= elements ? tmp.last : &first; } inline base_list(bool error) { } inline bool push_back(void *info) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 47eb19364ee..35b413e833c 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -6351,29 +6351,30 @@ finish: /* - Check whether an item is a simple equality predicate and if so - create/find a multiple equality for this predicate + Check whether an equality can be used to build multiple equalities SYNOPSIS - check_equality() - item item to check - cond_equal multiple equalities that must hold together with the predicate + check_simple_equality() + left_item left term of the quality to be checked + right_item right term of the equality to be checked + item equality item if the equality originates from a condition + predicate, 0 if the equality is the result of row elimination + cond_equal multiple equalities that must hold together with the equality DESCRIPTION - This function first checks whether an item is a simple equality i.e. - the one that equates a field with another field or a constant - (item=constant_item or item=field_item). - If this is the case the function looks a for a multiple equality + This function first checks whether the equality (left_item=right_item) + is a simple equality i.e. the one that equates a field with another field + or a constant (field=field_item or field=const_item). + If this is the case the function looks for a multiple equality in the lists referenced directly or indirectly by cond_equal inferring the given simple equality. If it doesn't find any, it builds a multiple equality that covers the predicate, i.e. the predicate can be inferred - from it. + from this multiple equality. The built multiple equality could be obtained in such a way: create a binary multiple equality equivalent to the predicate, then merge it, if possible, with one of old multiple equalities. This guarantees that the set of multiple equalities covering equality - predicates will - be minimal. + predicates will be minimal. EXAMPLE For the where condition @@ -6391,7 +6392,7 @@ finish: and will transform *cond_equal into (ptr(CE),[Item_equal(f,e)]). NOTES - Now only fields that have the same type defintions (verified by + Now only fields that have the same type definitions (verified by the Field::eq_def method) are placed to the same multiple equalities. Because of this some equality predicates are not eliminated and can be used in the constant propagation procedure. @@ -6424,11 +6425,263 @@ finish: copying would be much more complicated. RETURN - TRUE - if the predicate is a simple equality predicate - FALSE - otherwise + TRUE if the predicate is a simple equality predicate to be used + for building multiple equalities + FALSE otherwise */ -static bool check_equality(Item *item, COND_EQUAL *cond_equal) +static bool check_simple_equality(Item *left_item, Item *right_item, + Item *item, COND_EQUAL *cond_equal) +{ + if (left_item->type() == Item::REF_ITEM && + ((Item_ref*)left_item)->ref_type() == Item_ref::VIEW_REF) + { + if (((Item_ref*)left_item)->depended_from) + return FALSE; + left_item= left_item->real_item(); + } + if (right_item->type() == Item::REF_ITEM && + ((Item_ref*)right_item)->ref_type() == Item_ref::VIEW_REF) + { + if (((Item_ref*)right_item)->depended_from) + return FALSE; + right_item= right_item->real_item(); + } + if (left_item->type() == Item::FIELD_ITEM && + right_item->type() == Item::FIELD_ITEM && + !((Item_field*)left_item)->depended_from && + !((Item_field*)right_item)->depended_from) + { + /* The predicate the form field1=field2 is processed */ + + Field *left_field= ((Item_field*) left_item)->field; + Field *right_field= ((Item_field*) right_item)->field; + + if (!left_field->eq_def(right_field)) + return FALSE; + + /* Search for multiple equalities containing field1 and/or field2 */ + bool left_copyfl, right_copyfl; + Item_equal *left_item_equal= + find_item_equal(cond_equal, left_field, &left_copyfl); + Item_equal *right_item_equal= + find_item_equal(cond_equal, right_field, &right_copyfl); + + /* As (NULL=NULL) != TRUE we can't just remove the predicate f=f */ + if (left_field->eq(right_field)) /* f = f */ + return (!(left_field->maybe_null() && !left_item_equal)); + + if (left_item_equal && left_item_equal == right_item_equal) + { + /* + The equality predicate is inference of one of the existing + multiple equalities, i.e the condition is already covered + by upper level equalities + */ + return TRUE; + } + + /* Copy the found multiple equalities at the current level if needed */ + if (left_copyfl) + { + /* left_item_equal of an upper level contains left_item */ + left_item_equal= new Item_equal(left_item_equal); + cond_equal->current_level.push_back(left_item_equal); + } + if (right_copyfl) + { + /* right_item_equal of an upper level contains right_item */ + right_item_equal= new Item_equal(right_item_equal); + cond_equal->current_level.push_back(right_item_equal); + } + + if (left_item_equal) + { + /* left item was found in the current or one of the upper levels */ + if (! right_item_equal) + left_item_equal->add((Item_field *) right_item); + else + { + /* Merge two multiple equalities forming a new one */ + left_item_equal->merge(right_item_equal); + /* Remove the merged multiple equality from the list */ + List_iterator li(cond_equal->current_level); + while ((li++) != right_item_equal); + li.remove(); + } + } + else + { + /* left item was not found neither the current nor in upper levels */ + if (right_item_equal) + right_item_equal->add((Item_field *) left_item); + else + { + /* None of the fields was found in multiple equalities */ + Item_equal *item= new Item_equal((Item_field *) left_item, + (Item_field *) right_item); + cond_equal->current_level.push_back(item); + } + } + return TRUE; + } + + { + /* The predicate of the form field=const/const=field is processed */ + Item *const_item= 0; + Item_field *field_item= 0; + if (left_item->type() == Item::FIELD_ITEM && + !((Item_field*)left_item)->depended_from && + right_item->const_item()) + { + field_item= (Item_field*) left_item; + const_item= right_item; + } + else if (right_item->type() == Item::FIELD_ITEM && + !((Item_field*)right_item)->depended_from && + left_item->const_item()) + { + field_item= (Item_field*) right_item; + const_item= left_item; + } + + if (const_item && + field_item->result_type() == const_item->result_type()) + { + bool copyfl; + + if (field_item->result_type() == STRING_RESULT) + { + CHARSET_INFO *cs= ((Field_str*) field_item->field)->charset(); + if (!item) + { + Item_func_eq *eq_item; + if ((eq_item= new Item_func_eq(left_item, right_item))) + return FALSE; + eq_item->set_cmp_func(); + eq_item->quick_fix_field(); + item= eq_item; + } + if ((cs != ((Item_func *) item)->compare_collation()) || + !cs->coll->propagate(cs, 0, 0)) + return FALSE; + } + + Item_equal *item_equal = find_item_equal(cond_equal, + field_item->field, ©fl); + if (copyfl) + { + item_equal= new Item_equal(item_equal); + cond_equal->current_level.push_back(item_equal); + } + if (item_equal) + { + /* + The flag cond_false will be set to 1 after this, if item_equal + already contains a constant and its value is not equal to + the value of const_item. + */ + item_equal->add(const_item); + } + else + { + item_equal= new Item_equal(const_item, field_item); + cond_equal->current_level.push_back(item_equal); + } + return TRUE; + } + } + return FALSE; +} + + +/* + Convert row equalities into a conjunction of regular equalities + + SYNOPSIS + check_row_equality() + left_row left term of the row equality to be processed + right_row right term of the row equality to be processed + cond_equal multiple equalities that must hold together with the predicate + eq_list results of conversions of row equalities that are not simple + enough to form multiple equalities + + DESCRIPTION + The function converts a row equality of the form (E1,...,En)=(E'1,...,E'n) + into a list of equalities E1=E'1,...,En=E'n. For each of these equalities + Ei=E'i the function checks whether it is a simple equality or a row equality. + If it is a simple equality it is used to expand multiple equalities of + cond_equal. If it is a row equality it converted to a sequence of equalities + between row elements. If Ei=E'i is neither a simple equality nor a row + equality the item for this predicate is added to eq_list. + + RETURN + TRUE if conversion has succeeded (no fatal error) + FALSE otherwise +*/ + +static bool check_row_equality(Item *left_row, Item_row *right_row, + COND_EQUAL *cond_equal, List* eq_list) +{ + uint n= left_row->cols(); + for (uint i= 0 ; i < n; i++) + { + bool is_converted; + Item *left_item= left_row->el(i); + Item *right_item= right_row->el(i); + if (left_item->type() == Item::ROW_ITEM && + right_item->type() == Item::ROW_ITEM) + is_converted= check_row_equality((Item_row *) left_item, + (Item_row *) right_item, + cond_equal, eq_list); + else + is_converted= check_simple_equality(left_item, right_item, 0, cond_equal); + + if (!is_converted) + { + Item_func_eq *eq_item; + if (!(eq_item= new Item_func_eq(left_item, right_item))) + return FALSE; + eq_item->set_cmp_func(); + eq_item->quick_fix_field(); + eq_list->push_back(eq_item); + } + } + return TRUE; +} + + +/* + Eliminate row equalities and form multiple equalities predicates + + SYNOPSIS + check_equality() + item predicate to process + cond_equal multiple equalities that must hold together with the predicate + eq_list results of conversions of row equalities that are not simple + enough to form multiple equalities + + DESCRIPTION + This function checks whether the item is a simple equality + i.e. the one that equates a field with another field or a constant + (field=field_item or field=constant_item), or, a row equality. + For a simple equality the function looks for a multiple equality + in the lists referenced directly or indirectly by cond_equal inferring + the given simple equality. If it doesn't find any, it builds/expands + multiple equality that covers the predicate. + Row equalities are eliminated substituted for conjunctive regular equalities + which are treated in the same way as original equality predicates. + + RETURN + TRUE if re-writing rules have been applied + FALSE otherwise, i.e. + if the predicate is not an equality, + or, if the equality is neither a simple one nor a row equality, + or, if the procedure fails by a fatal error. +*/ + +static bool check_equality(Item *item, COND_EQUAL *cond_equal, + List *eq_list) { if (item->type() == Item::FUNC_ITEM && ((Item_func*) item)->functype() == Item_func::EQ_FUNC) @@ -6436,158 +6689,18 @@ static bool check_equality(Item *item, COND_EQUAL *cond_equal) Item *left_item= ((Item_func*) item)->arguments()[0]; Item *right_item= ((Item_func*) item)->arguments()[1]; - if (left_item->type() == Item::REF_ITEM && - ((Item_ref*)left_item)->ref_type() == Item_ref::VIEW_REF) - { - if (((Item_ref*)left_item)->depended_from) - return FALSE; - left_item= left_item->real_item(); - } - if (right_item->type() == Item::REF_ITEM && - ((Item_ref*)right_item)->ref_type() == Item_ref::VIEW_REF) - { - if (((Item_ref*)right_item)->depended_from) - return FALSE; - right_item= right_item->real_item(); - } - if (left_item->type() == Item::FIELD_ITEM && - right_item->type() == Item::FIELD_ITEM && - !((Item_field*)left_item)->depended_from && - !((Item_field*)right_item)->depended_from) - { - /* The predicate the form field1=field2 is processed */ - - Field *left_field= ((Item_field*) left_item)->field; - Field *right_field= ((Item_field*) right_item)->field; - - if (!left_field->eq_def(right_field)) - return FALSE; - - if (left_field->eq(right_field)) /* f = f */ - return TRUE; - - /* Search for multiple equalities containing field1 and/or field2 */ - bool left_copyfl, right_copyfl; - Item_equal *left_item_equal= - find_item_equal(cond_equal, left_field, &left_copyfl); - Item_equal *right_item_equal= - find_item_equal(cond_equal, right_field, &right_copyfl); - - if (left_item_equal && left_item_equal == right_item_equal) - { - /* - The equality predicate is inference of one of the existing - multiple equalities, i.e the condition is already covered - by upper level equalities - */ - return TRUE; - } - - /* Copy the found multiple equalities at the current level if needed */ - if (left_copyfl) - { - /* left_item_equal of an upper level contains left_item */ - left_item_equal= new Item_equal(left_item_equal); - cond_equal->current_level.push_back(left_item_equal); - } - if (right_copyfl) - { - /* right_item_equal of an upper level contains right_item */ - right_item_equal= new Item_equal(right_item_equal); - cond_equal->current_level.push_back(right_item_equal); - } - - if (left_item_equal) - { - /* left item was found in the current or one of the upper levels */ - if (! right_item_equal) - left_item_equal->add((Item_field *) right_item); - else - { - /* Merge two multiple equalities forming a new one */ - left_item_equal->merge(right_item_equal); - /* Remove the merged multiple equality from the list */ - List_iterator li(cond_equal->current_level); - while ((li++) != right_item_equal); - li.remove(); - } - } - else - { - /* left item was not found neither the current nor in upper levels */ - if (right_item_equal) - right_item_equal->add((Item_field *) left_item); - else - { - /* None of the fields was found in multiple equalities */ - Item_equal *item= new Item_equal((Item_field *) left_item, - (Item_field *) right_item); - cond_equal->current_level.push_back(item); - } - } - return TRUE; - } - - { - /* The predicate of the form field=const/const=field is processed */ - Item *const_item= 0; - Item_field *field_item= 0; - if (left_item->type() == Item::FIELD_ITEM && - !((Item_field*)left_item)->depended_from && - right_item->const_item()) - { - field_item= (Item_field*) left_item; - const_item= right_item; - } - else if (right_item->type() == Item::FIELD_ITEM && - !((Item_field*)right_item)->depended_from && - left_item->const_item()) - { - field_item= (Item_field*) right_item; - const_item= left_item; - } - - if (const_item && - field_item->result_type() == const_item->result_type()) - { - bool copyfl; - - if (field_item->result_type() == STRING_RESULT) - { - CHARSET_INFO *cs= ((Field_str*) field_item->field)->charset(); - if ((cs != ((Item_cond *) item)->compare_collation()) || - !cs->coll->propagate(cs, 0, 0)) - return FALSE; - } - - Item_equal *item_equal = find_item_equal(cond_equal, - field_item->field, ©fl); - if (copyfl) - { - item_equal= new Item_equal(item_equal); - cond_equal->current_level.push_back(item_equal); - } - if (item_equal) - { - /* - The flag cond_false will be set to 1 after this, if item_equal - already contains a constant and its value is not equal to - the value of const_item. - */ - item_equal->add(const_item); - } - else - { - item_equal= new Item_equal(const_item, field_item); - cond_equal->current_level.push_back(item_equal); - } - return TRUE; - } - } - } + if (left_item->type() == Item::ROW_ITEM && + right_item->type() == Item::ROW_ITEM) + return check_row_equality((Item_row *) left_item, + (Item_row *) right_item, + cond_equal, eq_list); + else + return check_simple_equality(left_item, right_item, item, cond_equal); + } return FALSE; } + /* Replace all equality predicates in a condition by multiple equality items @@ -6659,10 +6772,12 @@ static COND *build_equal_items_for_cond(COND *cond, Item_equal *item_equal; uint members; COND_EQUAL cond_equal; + COND *new_cond; cond_equal.upper_levels= inherited; if (cond->type() == Item::COND_ITEM) { + List eq_list; bool and_level= ((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC; List *args= ((Item_cond*) cond)->argument_list(); @@ -6685,7 +6800,7 @@ static COND *build_equal_items_for_cond(COND *cond, structure here because it's restored before each re-execution of any prepared statement/stored procedure. */ - if (check_equality(item, &cond_equal)) + if (check_equality(item, &cond_equal, &eq_list)) li.remove(); } @@ -6732,10 +6847,14 @@ static COND *build_equal_items_for_cond(COND *cond, } } if (and_level) + { + args->concat(&eq_list); args->concat((List *)&cond_equal.current_level); + } } else if (cond->type() == Item::FUNC_ITEM) { + List eq_list; /* If an equality predicate forms the whole and level, we call it standalone equality and it's processed here. @@ -6746,12 +6865,45 @@ static COND *build_equal_items_for_cond(COND *cond, for WHERE a=b AND c=d AND (b=c OR d=5) b=c is replaced by =(a,b,c,d). */ - if (check_equality(cond, &cond_equal) && - (item_equal= cond_equal.current_level.pop())) + if (check_equality(cond, &cond_equal, &eq_list)) { - item_equal->fix_length_and_dec(); - item_equal->update_used_tables(); - return item_equal; + int n= cond_equal.current_level.elements + eq_list.elements; + if (n == 0) + return new Item_int((longlong) 1,1); + else if (n == 1) + { + if ((item_equal= cond_equal.current_level.pop())) + { + item_equal->fix_length_and_dec(); + item_equal->update_used_tables(); + return item_equal; + } + else + return eq_list.pop(); + } + else + { + /* + Here a new AND level must be created. It can happen only + when a row equality is processed as a standalone predicate. + */ + Item_cond_and *and_cond= new Item_cond_and(eq_list); + and_cond->quick_fix_field(); + List *args= and_cond->argument_list(); + List_iterator_fast it(cond_equal.current_level); + while ((item_equal= it++)) + { + item_equal->fix_length_and_dec(); + item_equal->update_used_tables(); + members= item_equal->members(); + if (cond_equal.max_members < members) + cond_equal.max_members= members; + } + and_cond->cond_equal= cond_equal; + args->concat((List *)&cond_equal.current_level); + + return and_cond; + } } /* For each field reference in cond, not from equal item predicates, @@ -7038,7 +7190,7 @@ static Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels, /* Substitute every field reference in a condition by the best equal field - and eliminate all multiplle equality predicates + and eliminate all multiple equality predicates SYNOPSIS substitute_for_best_equal_field() From cf3bed86b553fa410a5ef73cfdd397a491f0bdd3 Mon Sep 17 00:00:00 2001 From: "timour/timka@lamia.home" <> Date: Mon, 4 Sep 2006 16:53:03 +0300 Subject: [PATCH 12/39] BUG#21787: COUNT(*) + ORDER BY + LIMIT returns wrong result Fix an error in the bug fix. --- sql/sql_select.cc | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 3b973f5d092..f0859564a5e 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -5576,10 +5576,11 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, keyinfo->key_length=0; keyinfo->rec_per_key=0; keyinfo->algorithm= HA_KEY_ALG_UNDEF; - for (; group ; group=group->next,key_part_info++) + ORDER *cur_group= group; + for (; cur_group ; cur_group= cur_group->next, key_part_info++) { - Field *field=(*group->item)->get_tmp_table_field(); - bool maybe_null=(*group->item)->maybe_null; + Field *field=(*cur_group->item)->get_tmp_table_field(); + bool maybe_null=(*cur_group->item)->maybe_null; key_part_info->null_bit=0; key_part_info->field= field; key_part_info->offset= field->offset(); @@ -5591,8 +5592,8 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, 0 : FIELDFLAG_BINARY; if (!using_unique_constraint) { - group->buff=(char*) group_buff; - if (!(group->field=field->new_field(thd->mem_root,table))) + cur_group->buff=(char*) group_buff; + if (!(cur_group->field=field->new_field(thd->mem_root,table))) goto err; /* purecov: inspected */ if (maybe_null) { @@ -5606,11 +5607,11 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, key_part_info->null_bit=field->null_bit; key_part_info->null_offset= (uint) (field->null_ptr - (uchar*) table->record[0]); - group->field->move_field((char*) ++group->buff); + cur_group->field->move_field((char*) ++cur_group->buff); group_buff++; } else - group->field->move_field((char*) group_buff); + cur_group->field->move_field((char*) group_buff); group_buff+= key_part_info->length; } keyinfo->key_length+= key_part_info->length; From 3758b975f8c535917c9507b005ccc8ff5a76bfb8 Mon Sep 17 00:00:00 2001 From: "gkodinov/kgeorge@macbook.gmz" <> Date: Mon, 4 Sep 2006 18:40:30 +0300 Subject: [PATCH 13/39] Bug #21392: multi-table delete with alias table name fails with 1003: Incorrect table name in multi-table DELETE the set of tables to delete from actually references then tables in the other list, e.g: DELETE alias_of_t1 FROM t1 alias_of_t1 WHERE .... is a valid statement. So we must turn off table name syntactical validity check for alias_of_t1 because it's not a table name (even if it looks like one). In order to do that we add a special flag (TL_OPTION_ALIAS) to disable the name checking for the aliases in multi-table DELETE. --- mysql-test/r/delete.result | 4 ++++ mysql-test/t/delete.test | 10 ++++++++++ sql/mysql_priv.h | 1 + sql/sql_parse.cc | 4 +++- sql/sql_yacc.yy | 7 +++++-- 5 files changed, 23 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/delete.result b/mysql-test/r/delete.result index 411cd52b4ca..cb632fcd6c8 100644 --- a/mysql-test/r/delete.result +++ b/mysql-test/r/delete.result @@ -172,3 +172,7 @@ a 0 2 DROP TABLE t1; +create table t1 (a int); +delete `4.t1` from t1 as `4.t1` where `4.t1`.a = 5; +delete FROM `4.t1` USING t1 as `4.t1` where `4.t1`.a = 5; +drop table t1; diff --git a/mysql-test/t/delete.test b/mysql-test/t/delete.test index 98e4c4e35fa..d4eb01cab23 100644 --- a/mysql-test/t/delete.test +++ b/mysql-test/t/delete.test @@ -153,4 +153,14 @@ DELETE FROM t1 WHERE t1.a > 0 ORDER BY t1.a LIMIT 1; SELECT * FROM t1; DROP TABLE t1; +# +# Bug #21392: multi-table delete with alias table name fails with +# 1003: Incorrect table name +# + +create table t1 (a int); +delete `4.t1` from t1 as `4.t1` where `4.t1`.a = 5; +delete FROM `4.t1` USING t1 as `4.t1` where `4.t1`.a = 5; +drop table t1; + # End of 4.1 tests diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 9c5bcc2d53f..4a5658c5ccf 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -305,6 +305,7 @@ void debug_sync_point(const char* lock_name, uint lock_timeout); #define TL_OPTION_UPDATING 1 #define TL_OPTION_FORCE_INDEX 2 #define TL_OPTION_IGNORE_LEAVES 4 +#define TL_OPTION_ALIAS 8 /* Some portable defines */ diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index cf1f50aed63..c84c96e1e75 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -4863,6 +4863,7 @@ bool add_to_list(THD *thd, SQL_LIST &list,Item *item,bool asc) table_options A set of the following bits: TL_OPTION_UPDATING Table will be updated TL_OPTION_FORCE_INDEX Force usage of index + TL_OPTION_ALIAS an alias in multi table DELETE lock_type How table should be locked use_index List of indexed used in USE INDEX ignore_index List of indexed used in IGNORE INDEX @@ -4888,7 +4889,8 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd, if (!table) DBUG_RETURN(0); // End of memory alias_str= alias ? alias->str : table->table.str; - if (check_table_name(table->table.str,table->table.length) || + if (!test(table_options & TL_OPTION_ALIAS) && + check_table_name(table->table.str,table->table.length) || table->db.str && check_db_name(table->db.str)) { net_printf(thd, ER_WRONG_TABLE_NAME, table->table.str); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 162b4183c84..53e7b103f32 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -4345,14 +4345,17 @@ table_wild_one: ident opt_wild opt_table_alias { if (!Select->add_table_to_list(YYTHD, new Table_ident($1), $3, - TL_OPTION_UPDATING, Lex->lock_option)) + TL_OPTION_UPDATING | + TL_OPTION_ALIAS, Lex->lock_option)) YYABORT; } | ident '.' ident opt_wild opt_table_alias { if (!Select->add_table_to_list(YYTHD, new Table_ident(YYTHD, $1, $3, 0), - $5, TL_OPTION_UPDATING, + $5, + TL_OPTION_UPDATING | + TL_OPTION_ALIAS, Lex->lock_option)) YYABORT; } From 7eaa08e0920f15245333746aaf12580f5a2191ce Mon Sep 17 00:00:00 2001 From: "gkodinov/kgeorge@macbook.gmz" <> Date: Tue, 5 Sep 2006 19:07:55 +0300 Subject: [PATCH 14/39] Merge bug #16792 4.1->5.0 --- mysql-test/r/func_group.result | 32 ++++++++++++++++---------------- mysql-test/r/innodb_mysql.result | 8 ++++---- mysql-test/r/union.result | 2 +- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/mysql-test/r/func_group.result b/mysql-test/r/func_group.result index f97d15a24ae..98eb9e9e2b3 100644 --- a/mysql-test/r/func_group.result +++ b/mysql-test/r/func_group.result @@ -845,22 +845,6 @@ EXPLAIN SELECT MAX(b) FROM t1; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL NULL NULL NULL NULL 2 DROP TABLE t1; -CREATE TABLE t1 (a INT, b INT); -INSERT INTO t1 VALUES (1,1),(1,2),(2,3); -SELECT (SELECT COUNT(DISTINCT t1.b)) FROM t1 GROUP BY t1.a; -(SELECT COUNT(DISTINCT t1.b)) -1 -1 -SELECT (SELECT COUNT(DISTINCT 12)) FROM t1 GROUP BY t1.a; -(SELECT COUNT(DISTINCT 12)) -1 -1 -SELECT AVG(2), BIT_AND(2), BIT_OR(2), BIT_XOR(2), COUNT(*), COUNT(12), -COUNT(DISTINCT 12), MIN(2),MAX(2),STD(2), VARIANCE(2),SUM(2), -GROUP_CONCAT(2),GROUP_CONCAT(DISTINCT 2); -AVG(2) BIT_AND(2) BIT_OR(2) BIT_XOR(2) COUNT(*) COUNT(12) COUNT(DISTINCT 12) MIN(2) MAX(2) STD(2) VARIANCE(2) SUM(2) GROUP_CONCAT(2) GROUP_CONCAT(DISTINCT 2) -2.0000 2 2 2 1 1 1 2 2 0.0000 0.0000 2 2 2 -DROP TABLE t1; CREATE TABLE t1 (id int , b varchar(512), INDEX(b(250))) COLLATE latin1_bin; INSERT INTO t1 VALUES (1,CONCAT(REPEAT('_', 250), "qq")), (1,CONCAT(REPEAT('_', 250), "zz")), @@ -872,6 +856,22 @@ EXPLAIN SELECT MAX(b) FROM t1; 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; +CREATE TABLE t1 (a INT, b INT); +INSERT INTO t1 VALUES (1,1),(1,2),(2,3); +SELECT (SELECT COUNT(DISTINCT t1.b)) FROM t1 GROUP BY t1.a; +(SELECT COUNT(DISTINCT t1.b)) +0 +2 +SELECT (SELECT COUNT(DISTINCT 12)) FROM t1 GROUP BY t1.a; +(SELECT COUNT(DISTINCT 12)) +1 +1 +SELECT AVG(2), BIT_AND(2), BIT_OR(2), BIT_XOR(2), COUNT(*), COUNT(12), +COUNT(DISTINCT 12), MIN(2),MAX(2),STD(2), VARIANCE(2),SUM(2), +GROUP_CONCAT(2),GROUP_CONCAT(DISTINCT 2); +AVG(2) BIT_AND(2) BIT_OR(2) BIT_XOR(2) COUNT(*) COUNT(12) COUNT(DISTINCT 12) MIN(2) MAX(2) STD(2) VARIANCE(2) SUM(2) GROUP_CONCAT(2) GROUP_CONCAT(DISTINCT 2) +2.00000 2 2 2 1 1 1 2 2 0.00000 0.00000 2 2 2 +DROP TABLE t1; create table t2 (ff double); insert into t2 values (2.2); select cast(sum(distinct ff) as decimal(5,2)) from t2; diff --git a/mysql-test/r/innodb_mysql.result b/mysql-test/r/innodb_mysql.result index e7d097a1d2f..b4101e037f2 100644 --- a/mysql-test/r/innodb_mysql.result +++ b/mysql-test/r/innodb_mysql.result @@ -118,7 +118,7 @@ min(7) NULL select min(7) from DUAL; min(7) -NULL +7 explain select min(7) from t2m join t1m; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away @@ -133,7 +133,7 @@ max(7) NULL select max(7) from DUAL; max(7) -NULL +7 explain select max(7) from t2m join t1m; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away @@ -172,7 +172,7 @@ min(7) NULL select min(7) from DUAL; min(7) -NULL +7 explain select min(7) from t2i join t1i; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2i ALL NULL NULL NULL NULL 1 @@ -188,7 +188,7 @@ max(7) NULL select max(7) from DUAL; max(7) -NULL +7 explain select max(7) from t2i join t1i; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2i ALL NULL NULL NULL NULL 1 diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result index 42a3874db08..12463658bf9 100644 --- a/mysql-test/r/union.result +++ b/mysql-test/r/union.result @@ -1365,7 +1365,7 @@ drop table t1, t2; (select avg(1)) union (select avg(1)) union (select avg(1)) union (select avg(1)) union (select avg(1)) union (select avg(1)); avg(1) -NULL +1.0000 select _utf8'12' union select _latin1'12345'; 12 12 From b7ded1e34fe28d76a26b0372867b15393c5c725c Mon Sep 17 00:00:00 2001 From: "igor@rurik.mysql.com" <> Date: Wed, 6 Sep 2006 08:21:43 -0700 Subject: [PATCH 15/39] Fixed bug #5500: EXPLAIN returned a wrong select_type for queries using views. Select_type in the EXPLAIN output for the query SELECT * FROM t1 was 'SIMPLE', while for the query SELECT * FROM v1, where the view v1 was defined as SELECT * FROM t1, the EXPLAIN output contained 'PRIMARY' for the select_type column. --- mysql-test/r/group_by.result | 4 +- mysql-test/r/information_schema.result | 2 +- mysql-test/r/olap.result | 2 +- mysql-test/r/range.result | 8 ++-- mysql-test/r/view.result | 51 ++++++++++++++++++-------- mysql-test/r/view_grant.result | 6 +-- mysql-test/t/view.test | 18 +++++++++ sql/sql_select.cc | 11 ++++-- 8 files changed, 71 insertions(+), 31 deletions(-) diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result index 57cb09fe44c..ef057e04d1a 100644 --- a/mysql-test/r/group_by.result +++ b/mysql-test/r/group_by.result @@ -807,8 +807,8 @@ explain SELECT straight_join sql_no_cache v1.a, v1.b, v1.real_b from t2, v1 where t2.b=v1.a GROUP BY t2.b; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t2 index b b 2 NULL 10 Using index -1 PRIMARY t1 eq_ref PRIMARY PRIMARY 1 test.t2.b 1 +1 SIMPLE t2 index b b 2 NULL 10 Using index +1 SIMPLE t1 eq_ref PRIMARY PRIMARY 1 test.t2.b 1 SELECT straight_join sql_no_cache v1.a, v1.b, v1.real_b from t2, v1 where t2.b=v1.a GROUP BY t2.b; a b real_b diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result index 652af1c8387..407f8a040b7 100644 --- a/mysql-test/r/information_schema.result +++ b/mysql-test/r/information_schema.result @@ -337,7 +337,7 @@ mysql test explain select * from v0; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY # ALL NULL NULL NULL NULL 2 +1 SIMPLE # ALL NULL NULL NULL NULL 2 create view v1 (c) as select table_name from information_schema.tables where table_name="v1"; select * from v1; diff --git a/mysql-test/r/olap.result b/mysql-test/r/olap.result index 28c1dc59540..7cdd5e1b152 100644 --- a/mysql-test/r/olap.result +++ b/mysql-test/r/olap.result @@ -611,7 +611,7 @@ C NULL EXPLAIN SELECT type FROM v1 GROUP BY type WITH ROLLUP; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 ALL NULL NULL NULL NULL 10 Using filesort +1 SIMPLE t1 ALL NULL NULL NULL NULL 10 Using filesort DROP VIEW v1; DROP TABLE t1; CREATE TABLE t1 (a int(11) NOT NULL); diff --git a/mysql-test/r/range.result b/mysql-test/r/range.result index 3edf56496fe..add95613d62 100644 --- a/mysql-test/r/range.result +++ b/mysql-test/r/range.result @@ -750,13 +750,13 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 4 Using where; Using index EXPLAIN SELECT a,b FROM v1 WHERE a < 2 and b=3; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 range PRIMARY PRIMARY 4 NULL 4 Using where; Using index +1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 4 Using where; Using index EXPLAIN SELECT a,b FROM t1 WHERE a < 2; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 4 Using where; Using index EXPLAIN SELECT a,b FROM v1 WHERE a < 2; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 range PRIMARY PRIMARY 4 NULL 4 Using where; Using index +1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL 4 Using where; Using index SELECT a,b FROM t1 WHERE a < 2 and b=3; a b 1 3 @@ -799,13 +799,13 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 range PRIMARY PRIMARY 8 NULL # Using where; Using index explain select * from v1 where a in (3,4) and b in (1,2,3); id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 range PRIMARY PRIMARY 8 NULL # Using where; Using index +1 SIMPLE t1 range PRIMARY PRIMARY 8 NULL # Using where; Using index explain select * from t1 where a between 3 and 4 and b between 1 and 2; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 range PRIMARY PRIMARY 8 NULL # Using where; Using index explain select * from v1 where a between 3 and 4 and b between 1 and 2; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 range PRIMARY PRIMARY 8 NULL # Using where; Using index +1 SIMPLE t1 range PRIMARY PRIMARY 8 NULL # Using where; Using index drop view v1; drop table t1; create table t3 (a int); diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index f9267b85134..55406e76586 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -49,7 +49,7 @@ select v1.b from v1; ERROR 42S22: Unknown column 'v1.b' in 'field list' explain extended select c from v1; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 ALL NULL NULL NULL NULL 5 +1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Warnings: Note 1003 select (`test`.`t1`.`b` + 1) AS `c` from `test`.`t1` create algorithm=temptable view v2 (c) as select b+1 from t1; @@ -83,7 +83,7 @@ c 12 explain extended select c from v3; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 ALL NULL NULL NULL NULL 5 +1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Warnings: Note 1003 select ((`test`.`t1`.`b` + 1) + 1) AS `c` from `test`.`t1` create algorithm=temptable view v4 (c) as select c+1 from v2; @@ -376,7 +376,7 @@ c 30 explain extended select * from v1; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 ALL NULL NULL NULL NULL 5 Using where +1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where Warnings: Note 1003 select `test`.`t1`.`b` AS `c` from `test`.`t1` where (`test`.`t1`.`a` < 3) update v1 set c=c+1; @@ -1391,9 +1391,9 @@ a a b 4 NULL NULL explain extended select * from t3 left join v3 on (t3.a = v3.a); id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t3 ALL NULL NULL NULL NULL 3 -1 PRIMARY t1 ALL NULL NULL NULL NULL 3 -1 PRIMARY t2 ALL NULL NULL NULL NULL 2 +1 SIMPLE t3 ALL NULL NULL NULL NULL 3 +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 +1 SIMPLE t2 ALL NULL NULL NULL NULL 2 Warnings: Note 1003 select `test`.`t3`.`a` AS `a`,`test`.`t1`.`a` AS `a`,`test`.`t2`.`a` AS `b` from `test`.`t3` left join (`test`.`t1` left join `test`.`t2` on((`test`.`t1`.`a` = `test`.`t2`.`a`))) on((`test`.`t3`.`a` = `test`.`t1`.`a`)) where 1 create view v1 (a) as select a from t1; @@ -1406,9 +1406,9 @@ a a b 4 NULL NULL explain extended select * from t3 left join v4 on (t3.a = v4.a); id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t3 ALL NULL NULL NULL NULL 3 -1 PRIMARY t1 ALL NULL NULL NULL NULL 3 -1 PRIMARY t2 ALL NULL NULL NULL NULL 2 +1 SIMPLE t3 ALL NULL NULL NULL NULL 3 +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 +1 SIMPLE t2 ALL NULL NULL NULL NULL 2 Warnings: Note 1003 select `test`.`t3`.`a` AS `a`,`test`.`t1`.`a` AS `a`,`test`.`t2`.`a` AS `b` from `test`.`t3` left join (`test`.`t1` left join (`test`.`t2`) on((`test`.`t1`.`a` = `test`.`t2`.`a`))) on((`test`.`t3`.`a` = `test`.`t1`.`a`)) where 1 prepare stmt1 from "select * from t3 left join v4 on (t3.a = v4.a);"; @@ -2321,12 +2321,12 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ref a a 10 const,test.t1.b 2 Using where; Using index EXPLAIN SELECT * FROM v1 WHERE a=1; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 ref a a 5 const 1 Using where; Using index -1 PRIMARY t2 ref a a 10 const,test.t1.b 2 Using where; Using index +1 SIMPLE t1 ref a a 5 const 1 Using where; Using index +1 SIMPLE t2 ref a a 10 const,test.t1.b 2 Using where; Using index EXPLAIN SELECT * FROM v2 WHERE a=1; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 ref a a 5 const 1 Using where; Using index -1 PRIMARY t3 ALL NULL NULL NULL NULL 3 Using where +1 SIMPLE t1 ref a a 5 const 1 Using where; Using index +1 SIMPLE t3 ALL NULL NULL NULL NULL 3 Using where DROP VIEW v1,v2; DROP TABLE t1,t2,t3; create table t1 (f1 int); @@ -2409,7 +2409,7 @@ insert into t1 values (1),(2); create view v1 as select * from t1; explain select id from v1 order by id; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 index NULL PRIMARY 4 NULL 2 Using index +1 SIMPLE t1 index NULL PRIMARY 4 NULL 2 Using index drop view v1; drop table t1; create table t1(f1 int, f2 int); @@ -2480,7 +2480,7 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away EXPLAIN SELECT MAX(a) FROM v1; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away SELECT MIN(a) FROM t1; MIN(a) 0 @@ -2492,7 +2492,7 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away EXPLAIN SELECT MIN(a) FROM v1; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away DROP VIEW v1; DROP TABLE t1; CREATE TABLE t1 (x varchar(10)); @@ -2879,3 +2879,22 @@ View Create View v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`f1` AS `f1` from `t1` where (`t1`.`f1` between now() and (now() + interval 1 minute)) drop view v1; drop table t1; +CREATE TABLE t1 (s1 int); +CREATE VIEW v1 AS SELECT * FROM t1; +EXPLAIN SELECT * FROM t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 system NULL NULL NULL NULL 0 const row not found +EXPLAIN SELECT * FROM v1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 system NULL NULL NULL NULL 0 const row not found +INSERT INTO t1 VALUES (1), (3), (2); +EXPLAIN SELECT * FROM t1 t WHERE t.s1+1 < (SELECT MAX(t1.s1) FROM t1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t ALL NULL NULL NULL NULL 3 Using where +2 SUBQUERY t1 ALL NULL NULL NULL NULL 3 +EXPLAIN SELECT * FROM v1 t WHERE t.s1+1 < (SELECT MAX(t1.s1) FROM t1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Using where +2 SUBQUERY t1 ALL NULL NULL NULL NULL 3 +DROP VIEW v1; +DROP TABLE t1; diff --git a/mysql-test/r/view_grant.result b/mysql-test/r/view_grant.result index 7f63d790fb8..35e7afc0a7b 100644 --- a/mysql-test/r/view_grant.result +++ b/mysql-test/r/view_grant.result @@ -103,7 +103,7 @@ ERROR 42000: SHOW VIEW command denied to user 'mysqltest_1'@'localhost' for tabl grant select on mysqltest.t1 to mysqltest_1@localhost; explain select c from mysqltest.v1; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 system NULL NULL NULL NULL 0 const row not found +1 SIMPLE t1 system NULL NULL NULL NULL 0 const row not found show create view mysqltest.v1; ERROR 42000: SHOW VIEW command denied to user 'mysqltest_1'@'localhost' for table 'v1' explain select c from mysqltest.v2; @@ -123,7 +123,7 @@ ERROR 42000: SHOW VIEW command denied to user 'mysqltest_1'@'localhost' for tabl grant show view on mysqltest.* to mysqltest_1@localhost; explain select c from mysqltest.v1; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t1 system NULL NULL NULL NULL 0 const row not found +1 SIMPLE t1 system NULL NULL NULL NULL 0 const row not found show create view mysqltest.v1; View Create View v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest`.`v1` AS select (`mysqltest`.`t1`.`a` + 1) AS `c`,(`mysqltest`.`t1`.`b` + 1) AS `d` from `mysqltest`.`t1` @@ -136,7 +136,7 @@ View Create View v2 CREATE ALGORITHM=TEMPTABLE DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest`.`v2` AS select (`mysqltest`.`t1`.`a` + 1) AS `c`,(`mysqltest`.`t1`.`b` + 1) AS `d` from `mysqltest`.`t1` explain select c from mysqltest.v3; id select_type table type possible_keys key key_len ref rows Extra -1 PRIMARY t2 system NULL NULL NULL NULL 0 const row not found +1 SIMPLE t2 system NULL NULL NULL NULL 0 const row not found show create view mysqltest.v3; View Create View v3 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `mysqltest`.`v3` AS select (`mysqltest`.`t2`.`a` + 1) AS `c`,(`mysqltest`.`t2`.`b` + 1) AS `d` from `mysqltest`.`t2` diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index fae3f856cb8..22f9f2e9ab7 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -2760,3 +2760,21 @@ create view v1 as select * from t1 where f1 between now() and now() + interval 1 show create view v1; drop view v1; drop table t1; + +# +# Bug #5500: wrong select_type in EXPLAIN output for queries over views +# + +CREATE TABLE t1 (s1 int); +CREATE VIEW v1 AS SELECT * FROM t1; + +EXPLAIN SELECT * FROM t1; +EXPLAIN SELECT * FROM v1; + +INSERT INTO t1 VALUES (1), (3), (2); + +EXPLAIN SELECT * FROM t1 t WHERE t.s1+1 < (SELECT MAX(t1.s1) FROM t1); +EXPLAIN SELECT * FROM v1 t WHERE t.s1+1 < (SELECT MAX(t1.s1) FROM t1); + +DROP VIEW v1; +DROP TABLE t1; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 47eb19364ee..1ff62a5f699 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -14221,9 +14221,12 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, item_list.push_back(new Item_string(table_name_buffer, len, cs)); } else - item_list.push_back(new Item_string(table->alias, - strlen(table->alias), + { + TABLE_LIST *tab=table->pos_in_table_list; + item_list.push_back(new Item_string(tab->alias, + strlen(tab->alias), cs)); + } /* type */ item_list.push_back(new Item_string(join_type_str[tab->type], strlen(join_type_str[tab->type]), @@ -14410,8 +14413,8 @@ bool mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result) // drop UNCACHEABLE_EXPLAIN, because it is for internal usage only uint8 uncacheable= (sl->uncacheable & ~UNCACHEABLE_EXPLAIN); sl->type= (((&thd->lex->select_lex)==sl)? - ((thd->lex->all_selects_list != sl) ? - primary_key_name : "SIMPLE"): + (sl->first_inner_unit() || sl->next_select() ? + "PRIMARY" : "SIMPLE"): ((sl == first)? ((sl->linkage == DERIVED_TABLE_TYPE) ? "DERIVED": From 39c0f0a4844dbcc5782ae0240ba409ee6edd4899 Mon Sep 17 00:00:00 2001 From: "istruewing@chilla.local" <> Date: Thu, 7 Sep 2006 15:39:31 +0200 Subject: [PATCH 16/39] Bug#14400 - Query joins wrong rows from table which is subject of "concurrent insert" Additional fix for full keys and test case. --- myisam/mi_rkey.c | 38 ++++++++++++++++++++++---------------- mysql-test/r/myisam.result | 13 +++++++++++++ mysql-test/t/myisam.test | 18 ++++++++++++++++++ 3 files changed, 53 insertions(+), 16 deletions(-) diff --git a/myisam/mi_rkey.c b/myisam/mi_rkey.c index f051558cae5..be99d66618d 100644 --- a/myisam/mi_rkey.c +++ b/myisam/mi_rkey.c @@ -78,24 +78,18 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len, if (!_mi_search(info,keyinfo, key_buff, use_key_length, myisam_read_vec[search_flag], info->s->state.key_root[inx])) { - if (info->lastpos >= info->state->data_file_length) + /* + If we searching for a partial key (or using >, >=, < or <=) and + the data is outside of the data file, we need to continue searching + for the first key inside the data file + */ + if (info->lastpos >= info->state->data_file_length && + (search_flag != HA_READ_KEY_EXACT || + last_used_keyseg != keyinfo->seg + keyinfo->keysegs)) { do { uint not_used; - /* - If we are searching for an exact key, abort if we find a bigger - key. - */ - if (search_flag == HA_READ_KEY_EXACT && - (use_key_length == USE_WHOLE_KEY || - _mi_key_cmp(keyinfo->seg, key_buff, info->lastkey, use_key_length, - SEARCH_FIND, ¬_used))) - { - my_errno= HA_ERR_END_OF_FILE; - info->lastpos= HA_OFFSET_ERROR; - break; - } /* Skip rows that are inserted by other threads since we got a lock Note that this can only happen if we are not searching after an @@ -107,8 +101,20 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len, myisam_readnext_vec[search_flag], info->s->state.key_root[inx])) break; - } - while (info->lastpos >= info->state->data_file_length); + /* + Check that the found key does still match the search. + _mi_search_next() delivers the next key regardless of its + value. + */ + if (search_flag == HA_READ_KEY_EXACT && + _mi_key_cmp(keyinfo->seg, key_buff, info->lastkey, use_key_length, + SEARCH_FIND, ¬_used)) + { + my_errno= HA_ERR_KEY_NOT_FOUND; + info->lastpos= HA_OFFSET_ERROR; + break; + } + } while (info->lastpos >= info->state->data_file_length); } } if (share->concurrent_insert) diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result index e7c1ad7e344..9d8e8289667 100644 --- a/mysql-test/r/myisam.result +++ b/mysql-test/r/myisam.result @@ -487,3 +487,16 @@ a a b 1 1 1 2 2 1 drop table t1,t2; +CREATE TABLE t1 (c1 varchar(250) NOT NULL); +CREATE TABLE t2 (c1 varchar(250) NOT NULL, PRIMARY KEY (c1)); +INSERT INTO t1 VALUES ('test000001'), ('test000002'), ('test000003'); +INSERT INTO t2 VALUES ('test000002'), ('test000003'), ('test000004'); +LOCK TABLES t1 READ LOCAL, t2 READ LOCAL; +SELECT t1.c1 AS t1c1, t2.c1 AS t2c1 FROM t1, t2 +WHERE t1.c1 = t2.c1 HAVING t1c1 != t2c1; +t1c1 t2c1 +INSERT INTO t2 VALUES ('test000001'), ('test000005'); +SELECT t1.c1 AS t1c1, t2.c1 AS t2c1 FROM t1, t2 +WHERE t1.c1 = t2.c1 HAVING t1c1 != t2c1; +t1c1 t2c1 +DROP TABLE t1,t2; diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test index bb8dc30395b..83d93686429 100644 --- a/mysql-test/t/myisam.test +++ b/mysql-test/t/myisam.test @@ -461,6 +461,7 @@ drop table t1; # # Bug #14400 Join could miss concurrently inserted row # +# Partial key. create table t1 (a int not null, primary key(a)); create table t2 (a int not null, b int not null, primary key(a,b)); insert into t1 values (1),(2),(3),(4),(5),(6); @@ -473,5 +474,22 @@ disconnect root; connection default; select straight_join * from t1,t2 force index (primary) where t1.a=t2.a; drop table t1,t2; +# +# Full key. +CREATE TABLE t1 (c1 varchar(250) NOT NULL); +CREATE TABLE t2 (c1 varchar(250) NOT NULL, PRIMARY KEY (c1)); +INSERT INTO t1 VALUES ('test000001'), ('test000002'), ('test000003'); +INSERT INTO t2 VALUES ('test000002'), ('test000003'), ('test000004'); +LOCK TABLES t1 READ LOCAL, t2 READ LOCAL; +SELECT t1.c1 AS t1c1, t2.c1 AS t2c1 FROM t1, t2 + WHERE t1.c1 = t2.c1 HAVING t1c1 != t2c1; +connect (con1,localhost,root,,); +connection con1; +INSERT INTO t2 VALUES ('test000001'), ('test000005'); +disconnect con1; +connection default; +SELECT t1.c1 AS t1c1, t2.c1 AS t2c1 FROM t1, t2 + WHERE t1.c1 = t2.c1 HAVING t1c1 != t2c1; +DROP TABLE t1,t2; # end of 4.0 tests From 34206c6f80578375b8df6e64cc3185b7bec27dba Mon Sep 17 00:00:00 2001 From: "igor@rurik.mysql.com" <> Date: Thu, 7 Sep 2006 11:06:37 -0700 Subject: [PATCH 17/39] Fixed bug #21698: erroneously a field could be replaced by an equal constant under any circumstances. In fact this substitution can be allowed if the field is not of a type string or if the field reference serves as an argument of a comparison predicate. --- mysql-test/r/func_str.result | 35 +++++++++++++++++++ mysql-test/r/heap_hash.result | 2 +- mysql-test/t/func_str.test | 27 +++++++++++++++ sql/item.cc | 41 ++++++++++++++++++++-- sql/item.h | 18 +++++++++- sql/item_cmpfunc.cc | 61 +++++++++++++++++++++++++++++---- sql/item_cmpfunc.h | 4 +++ sql/item_func.cc | 64 ++++++++++++++++++++++++++++++----- sql/item_func.h | 2 ++ sql/sql_select.cc | 17 +++++++--- 10 files changed, 247 insertions(+), 24 deletions(-) diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index 14da630f61e..94fb570381a 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -1113,4 +1113,39 @@ conv("18383815659218730760",10,10) + 0 select "18383815659218730760" + 0; "18383815659218730760" + 0 1.8383815659219e+19 +CREATE TABLE t1 (code varchar(10)); +INSERT INTO t1 VALUES ('a12'), ('A12'), ('a13'); +SELECT ASCII(code), code FROM t1 WHERE code='A12'; +ASCII(code) code +97 a12 +65 A12 +SELECT ASCII(code), code FROM t1 WHERE code='A12' AND ASCII(code)=65; +ASCII(code) code +65 A12 +INSERT INTO t1 VALUES ('a12 '), ('A12 '); +SELECT LENGTH(code), code FROM t1 WHERE code='A12'; +LENGTH(code) code +3 a12 +3 A12 +4 a12 +5 A12 +SELECT LENGTH(code), code FROM t1 WHERE code='A12' AND LENGTH(code)=5; +LENGTH(code) code +5 A12 +ALTER TABLE t1 ADD INDEX (code); +CREATE TABLE t2 (id varchar(10) PRIMARY KEY); +INSERT INTO t2 VALUES ('a11'), ('a12'), ('a13'), ('a14'); +SELECT * FROM t1 INNER JOIN t2 ON t1.code=t2.id +WHERE t2.id='a12' AND (code < 'a00' OR LENGTH(code)=5); +code id +A12 a12 +EXPLAIN EXTENDED +SELECT * FROM t1 INNER JOIN t2 ON code=id +WHERE id='a12' AND (code < 'a00' OR LENGTH(code)=5); +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ref code code 13 const 3 Using where; Using index +1 SIMPLE t2 ref PRIMARY PRIMARY 12 const 1 Using where; Using index +Warnings: +Note 1003 select `test`.`t1`.`code` AS `code`,`test`.`t2`.`id` AS `id` from `test`.`t1` join `test`.`t2` where ((`test`.`t1`.`code` = _latin1'a12') and (`test`.`t2`.`id` = _latin1'a12') and (length(`test`.`t1`.`code`) = 5)) +DROP TABLE t1,t2; End of 5.0 tests diff --git a/mysql-test/r/heap_hash.result b/mysql-test/r/heap_hash.result index e0835bbf8d6..80abcebbfea 100644 --- a/mysql-test/r/heap_hash.result +++ b/mysql-test/r/heap_hash.result @@ -354,7 +354,7 @@ t3 1 a 2 b NULL 13 NULL NULL HASH explain select * from t1 ignore key(btree_idx), t3 where t1.name='matt' and t3.a = concat('',t1.name) and t3.b=t1.name; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ref heap_idx heap_idx 22 const 7 Using where -1 SIMPLE t3 ref a a 44 const,const 7 Using where +1 SIMPLE t3 ref a a 44 func,const 7 Using where drop table t1, t2, t3; create temporary table t1 ( a int, index (a) ) engine=memory; insert into t1 values (1),(2),(3),(4),(5); diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index 8753db0ebe1..415c6d2a44e 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -753,4 +753,31 @@ select cast(rtrim(ltrim(' 20.06 ')) as decimal(19,2)); select conv("18383815659218730760",10,10) + 0; select "18383815659218730760" + 0; +# +# Bug #21698: substitution of a string field for a constant under a function +# + +CREATE TABLE t1 (code varchar(10)); +INSERT INTO t1 VALUES ('a12'), ('A12'), ('a13'); + +SELECT ASCII(code), code FROM t1 WHERE code='A12'; +SELECT ASCII(code), code FROM t1 WHERE code='A12' AND ASCII(code)=65; + +INSERT INTO t1 VALUES ('a12 '), ('A12 '); + +SELECT LENGTH(code), code FROM t1 WHERE code='A12'; +SELECT LENGTH(code), code FROM t1 WHERE code='A12' AND LENGTH(code)=5; + +ALTER TABLE t1 ADD INDEX (code); +CREATE TABLE t2 (id varchar(10) PRIMARY KEY); +INSERT INTO t2 VALUES ('a11'), ('a12'), ('a13'), ('a14'); + +SELECT * FROM t1 INNER JOIN t2 ON t1.code=t2.id + WHERE t2.id='a12' AND (code < 'a00' OR LENGTH(code)=5); +EXPLAIN EXTENDED +SELECT * FROM t1 INNER JOIN t2 ON code=id + WHERE id='a12' AND (code < 'a00' OR LENGTH(code)=5); + +DROP TABLE t1,t2; + --echo End of 5.0 tests diff --git a/sql/item.cc b/sql/item.cc index 96b20d0f0bb..c3b950bc32b 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -3745,14 +3745,49 @@ Item_equal *Item_field::find_item_equal(COND_EQUAL *cond_equal) } +/* + Check whether a field can be substituted by an equal item + + SYNOPSIS + equal_fields_propagator() + arg - *arg != NULL <-> the field is in the context where + substitution for an equal item is valid + + DESCRIPTION + The function checks whether a substitution of the field + occurrence for an equal item is valid. + + NOTES + The following statement is not always true: + x=y => F(x)=F(x/y). + This means substitution of an item for an equal item not always + yields an equavalent condition. + Here's an example: + 'a'='a ' + (LENGTH('a')=1) != (LENGTH('a ')=2) + Such a substitution is surely valid if either the substituted + field is not of a STRING type or if it is an argument of + a comparison predicate. + + RETURN + TRUE substitution is valid + FALSE otherwise +*/ + +bool Item_field::subst_argument_checker(byte **arg) +{ + return (result_type() != STRING_RESULT) || (*arg); +} + + /* Set a pointer to the multiple equality the field reference belongs to (if any) SYNOPSIS equal_fields_propagator() - arg - reference to list of multiple equalities where - the field (this object) is to be looked for + arg - reference to list of multiple equalities where + the field (this object) is to be looked for DESCRIPTION The function looks for a multiple equality containing the field item @@ -3764,7 +3799,7 @@ Item_equal *Item_field::find_item_equal(COND_EQUAL *cond_equal) NOTES This function is supposed to be called as a callback parameter in calls - of the transform method. + of the compile method. RETURN VALUES pointer to the replacing constant item, if the field item was substituted diff --git a/sql/item.h b/sql/item.h index e3df0fdf389..f6145d6e20c 100644 --- a/sql/item.h +++ b/sql/item.h @@ -410,7 +410,8 @@ public: }; -typedef bool (Item::*Item_processor)(byte *arg); +typedef bool (Item::*Item_processor) (byte *arg); +typedef bool (Item::*Item_analyzer) (byte **argp); typedef Item* (Item::*Item_transformer) (byte *arg); typedef void (*Cond_traverser) (const Item *item, void *arg); @@ -739,6 +740,14 @@ public: return (this->*transformer)(arg); } + virtual Item* compile(Item_analyzer analyzer, byte **arg_p, + Item_transformer transformer, byte *arg_t) + { + if ((this->*analyzer) (arg_p)) + return ((this->*transformer) (arg_t)); + return 0; + } + virtual void traverse_cond(Cond_traverser traverser, void *arg, traverse_order order) { @@ -753,6 +762,12 @@ public: virtual bool change_context_processor(byte *context) { return 0; } virtual bool reset_query_id_processor(byte *query_id) { return 0; } virtual bool is_expensive_processor(byte *arg) { return 0; } + virtual bool subst_argument_checker(byte **arg) + { + if (*arg) + *arg= NULL; + return TRUE; + } virtual Item *equal_fields_propagator(byte * arg) { return this; } virtual Item *set_no_const_sub(byte *arg) { return this; } @@ -1254,6 +1269,7 @@ public: return field->can_be_compared_as_longlong(); } Item_equal *find_item_equal(COND_EQUAL *cond_equal); + bool subst_argument_checker(byte **arg); Item *equal_fields_propagator(byte *arg); Item *set_no_const_sub(byte *arg); Item *replace_equal_field(byte *arg); diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index dbf380232c4..fa01ae65b0d 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -2747,16 +2747,16 @@ bool Item_cond::walk(Item_processor processor, byte *arg) SYNOPSIS transform() - transformer the transformer callback function to be applied to the nodes - of the tree of the object - arg parameter to be passed to the transformer + transformer the transformer callback function to be applied to the nodes + of the tree of the object + arg parameter to be passed to the transformer DESCRIPTION - The function recursively applies the transform method with the - same transformer to each member item of the condition list. + The function recursively applies the transform method to each + member item of the condition list. If the call of the method for a member item returns a new item the old item is substituted for a new one. - After this the transform method is applied to the root node + After this the transformer is applied to the root node of the Item_cond object. RETURN VALUES @@ -2778,6 +2778,55 @@ Item *Item_cond::transform(Item_transformer transformer, byte *arg) return Item_func::transform(transformer, arg); } + +/* + Compile Item_cond object with a processor and a transformer callback functions + + SYNOPSIS + compile() + analyzer the analyzer callback function to be applied to the nodes + of the tree of the object + arg_p in/out parameter to be passed to the analyzer + transformer the transformer callback function to be applied to the nodes + of the tree of the object + arg_t parameter to be passed to the transformer + + DESCRIPTION + First the function applies the analyzer to the root node of + the Item_func object. Then if the analyzer succeeeds (returns TRUE) + the function recursively applies the compile method to member + item of the condition list. + If the call of the method for a member item returns a new item + the old item is substituted for a new one. + After this the transformer is applied to the root node + of the Item_cond object. + + RETURN VALUES + Item returned as the result of transformation of the root node +*/ + +Item *Item_cond::compile(Item_analyzer analyzer, byte **arg_p, + Item_transformer transformer, byte *arg_t) +{ + if (!(this->*analyzer)(arg_p)) + return 0; + + byte *arg_v= *arg_p; + List_iterator li(list); + Item *item; + while ((item= li++)) + { + /* + The same parameter value of arg_p must be passed + to analyze any argument of the condition formula. + */ + Item *new_item= item->compile(analyzer, &arg_v, transformer, arg_t); + if (new_item && new_item != item) + li.replace(new_item); + } + return Item_func::transform(transformer, arg_t); +} + void Item_cond::traverse_cond(Cond_traverser traverser, void *arg, traverse_order order) { diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 47f9f2aa98f..f2c43833bd9 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -240,6 +240,7 @@ public: } Item *neg_transformer(THD *thd); virtual Item *negated_item(); + bool subst_argument_checker(byte **arg) { return TRUE; } }; class Item_func_not :public Item_bool_func @@ -1171,6 +1172,9 @@ public: Item *transform(Item_transformer transformer, byte *arg); void traverse_cond(Cond_traverser, void *arg, traverse_order order); void neg_arguments(THD *thd); + bool subst_argument_checker(byte **arg) { return TRUE; } + Item *compile(Item_analyzer analyzer, byte **arg_p, + Item_transformer transformer, byte *arg_t); }; diff --git a/sql/item_func.cc b/sql/item_func.cc index e699669dcc5..acd6ec19470 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -234,22 +234,21 @@ void Item_func::traverse_cond(Cond_traverser traverser, } - /* Transform an Item_func object with a transformer callback function SYNOPSIS transform() - transformer the transformer callback function to be applied to the nodes - of the tree of the object - argument parameter to be passed to the transformer + transformer the transformer callback function to be applied to the nodes + of the tree of the object + argument parameter to be passed to the transformer DESCRIPTION - The function recursively applies the transform method with the - same transformer to each argument the function. - If the call of the method for a member item returns a new item + The function recursively applies the transform method to each + argument of the Item_func node. + If the call of the method for an argument item returns a new item the old item is substituted for a new one. - After this the transform method is applied to the root node + After this the transformer is applied to the root node of the Item_func object. RETURN VALUES @@ -274,6 +273,55 @@ Item *Item_func::transform(Item_transformer transformer, byte *argument) } +/* + Compile Item_func object with a processor and a transformer callback functions + + SYNOPSIS + compile() + analyzer the analyzer callback function to be applied to the nodes + of the tree of the object + arg_p in/out parameter to be passed to the processor + transformer the transformer callback function to be applied to the nodes + of the tree of the object + arg_t parameter to be passed to the transformer + + DESCRIPTION + First the function applies the analyzer to the root node of + the Item_func object. Then if the analizer succeeeds (returns TRUE) + the function recursively applies the compile method to each argument + of the Item_func node. + If the call of the method for an argument item returns a new item + the old item is substituted for a new one. + After this the transformer is applied to the root node + of the Item_func object. + + RETURN VALUES + Item returned as the result of transformation of the root node +*/ + +Item *Item_func::compile(Item_analyzer analyzer, byte **arg_p, + Item_transformer transformer, byte *arg_t) +{ + if (!(this->*analyzer)(arg_p)) + return 0; + byte *arg_v= *arg_p; + if (arg_count) + { + Item **arg,**arg_end; + for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++) + { + /* + The same parameter value of arg_p must be passed + to analyze any argument of the condition formula. + */ + Item *new_item= (*arg)->compile(analyzer, &arg_v, transformer, arg_t); + if (new_item && *arg != new_item) + current_thd->change_item_tree(arg, new_item); + } + } + return (this->*transformer)(arg_t); +} + /* See comments in Item_cmp_func::split_sum_func() */ void Item_func::split_sum_func(THD *thd, Item **ref_pointer_array, diff --git a/sql/item_func.h b/sql/item_func.h index c15b0b854b0..0d09bac4e86 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -187,6 +187,8 @@ public: } bool walk(Item_processor processor, byte *arg); Item *transform(Item_transformer transformer, byte *arg); + Item* compile(Item_analyzer analyzer, byte **arg_p, + Item_transformer transformer, byte *arg_t); void traverse_cond(Cond_traverser traverser, void * arg, traverse_order order); bool is_expensive_processor(byte *arg); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 47eb19364ee..3e5e1d94445 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -6593,8 +6593,8 @@ static bool check_equality(Item *item, COND_EQUAL *cond_equal) SYNOPSIS build_equal_items_for_cond() - cond condition(expression) where to make replacement - inherited path to all inherited multiple equality items + cond condition(expression) where to make replacement + inherited path to all inherited multiple equality items DESCRIPTION At each 'and' level the function detects items for equality predicates @@ -6608,7 +6608,9 @@ static bool check_equality(Item *item, COND_EQUAL *cond_equal) The function also traverses the cond tree and and for each field reference sets a pointer to the multiple equality item containing the field, if there is any. If this multiple equality equates fields to a constant the - function replace the field reference by the constant. + function replaces the field reference by the constant in the cases + when the field is not of a string type or when the field reference is + just an argument of a comparison predicate. The function also determines the maximum number of members in equality lists of each Item_cond_and object assigning it to cond_equal->max_members of this object and updating accordingly @@ -6756,9 +6758,14 @@ static COND *build_equal_items_for_cond(COND *cond, /* For each field reference in cond, not from equal item predicates, set a pointer to the multiple equality it belongs to (if there is any) + as soon the field is not of a string type or the field reference is + an argument of a comparison predicate. */ - cond= cond->transform(&Item::equal_fields_propagator, - (byte *) inherited); + byte *dummy; + cond= cond->compile(&Item::subst_argument_checker, + &dummy, + &Item::equal_fields_propagator, + (byte *) inherited); cond->update_used_tables(); } return cond; From 31c738d8a2e7bee3f598eb9ba83940644a520775 Mon Sep 17 00:00:00 2001 From: "evgen@moonbone.local" <> Date: Fri, 8 Sep 2006 00:59:34 +0400 Subject: [PATCH 18/39] query_cache.result, func_time.test, type_date.result, func_time.result: Corrected test case after removal of fix for bug#16377 type_date.test: Corrected test case after removal of fix for bug#16377 item_cmpfunc.cc: Removed changes to the agg_cmp_type() made in the for bug#16377 --- mysql-test/r/func_time.result | 23 ++++--- mysql-test/r/query_cache.result | 3 - mysql-test/r/type_date.result | 4 +- mysql-test/t/func_time.test | 22 +++---- mysql-test/t/type_date.test | 4 +- sql/item_cmpfunc.cc | 111 +------------------------------- 6 files changed, 29 insertions(+), 138 deletions(-) diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result index 47a0f83802c..97dd8e243b2 100644 --- a/mysql-test/r/func_time.result +++ b/mysql-test/r/func_time.result @@ -646,37 +646,36 @@ drop table t1; create table t1(f1 date, f2 time, f3 datetime); insert into t1 values ("2006-01-01", "12:01:01", "2006-01-01 12:01:01"); insert into t1 values ("2006-01-02", "12:01:02", "2006-01-02 12:01:02"); -select f1 from t1 where f1 between "2006-1-1" and 20060101; +select f1 from t1 where f1 between CAST("2006-1-1" as date) and CAST(20060101 as date); f1 2006-01-01 -select f1 from t1 where f1 between "2006-1-1" and "2006.1.1"; +select f1 from t1 where f1 between cast("2006-1-1" as date) and cast("2006.1.1" as date); f1 2006-01-01 -select f1 from t1 where date(f1) between "2006-1-1" and "2006.1.1"; +select f1 from t1 where date(f1) between cast("2006-1-1" as date) and cast("2006.1.1" as date); f1 2006-01-01 -select f2 from t1 where f2 between "12:1:2" and "12:2:2"; +select f2 from t1 where f2 between cast("12:1:2" as time) and cast("12:2:2" as time); f2 12:01:02 -select f2 from t1 where time(f2) between "12:1:2" and "12:2:2"; +select f2 from t1 where time(f2) between cast("12:1:2" as time) and cast("12:2:2" as time); f2 12:01:02 -select f3 from t1 where f3 between "2006-1-1 12:1:1" and "2006-1-1 12:1:2"; +select f3 from t1 where f3 between cast("2006-1-1 12:1:1" as datetime) and cast("2006-1-1 12:1:2" as datetime); f3 2006-01-01 12:01:01 -select f3 from t1 where timestamp(f3) between "2006-1-1 12:1:1" and "2006-1-1 12:1:2"; +select f3 from t1 where timestamp(f3) between cast("2006-1-1 12:1:1" as datetime) and cast("2006-1-1 12:1:2" as datetime); f3 2006-01-01 12:01:01 -select f1 from t1 where "2006-1-1" between f1 and f3; +select f1 from t1 where cast("2006-1-1" as date) between f1 and f3; f1 2006-01-01 -select f1 from t1 where "2006-1-1" between date(f1) and date(f3); +select f1 from t1 where cast("2006-1-1" as date) between date(f1) and date(f3); f1 2006-01-01 -select f1 from t1 where "2006-1-1" between f1 and 'zzz'; +select f1 from t1 where cast("2006-1-1" as date) between f1 and 'zzz'; f1 -Warnings: -Warning 1292 Truncated incorrect date value: 'zzz' +2006-01-01 select f1 from t1 where makedate(2006,1) between date(f1) and date(f3); f1 2006-01-01 diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result index 24363ea27ab..2a57e06e330 100644 --- a/mysql-test/r/query_cache.result +++ b/mysql-test/r/query_cache.result @@ -907,19 +907,16 @@ COUNT(*) 0 Warnings: Warning 1292 Truncated incorrect datetime value: '20050327 invalid' -Warning 1292 Truncated incorrect datetime value: '20050327 invalid' SELECT COUNT(*) FROM t1 WHERE date BETWEEN '20050326' AND '20050328 invalid'; COUNT(*) 0 Warnings: Warning 1292 Truncated incorrect datetime value: '20050328 invalid' -Warning 1292 Truncated incorrect datetime value: '20050328 invalid' SELECT COUNT(*) FROM t1 WHERE date BETWEEN '20050326' AND '20050327 invalid'; COUNT(*) 0 Warnings: Warning 1292 Truncated incorrect datetime value: '20050327 invalid' -Warning 1292 Truncated incorrect datetime value: '20050327 invalid' show status like "Qcache_queries_in_cache"; Variable_name Value Qcache_queries_in_cache 0 diff --git a/mysql-test/r/type_date.result b/mysql-test/r/type_date.result index 3428b5969d9..d8d6aa89684 100644 --- a/mysql-test/r/type_date.result +++ b/mysql-test/r/type_date.result @@ -27,12 +27,12 @@ INSERT INTO t1 VALUES ( "2000-1-2" ); INSERT INTO t1 VALUES ( "2000-1-3" ); INSERT INTO t1 VALUES ( "2000-1-4" ); INSERT INTO t1 VALUES ( "2000-1-5" ); -SELECT * FROM t1 WHERE datum BETWEEN "2000-1-2" AND "2000-1-4"; +SELECT * FROM t1 WHERE datum BETWEEN cast("2000-1-2" as date) AND cast("2000-1-4" as date); datum 2000-01-02 2000-01-03 2000-01-04 -SELECT * FROM t1 WHERE datum BETWEEN "2000-1-2" AND datum - INTERVAL 100 DAY; +SELECT * FROM t1 WHERE datum BETWEEN cast("2000-1-2" as date) AND datum - INTERVAL 100 DAY; datum DROP TABLE t1; CREATE TABLE t1 ( diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test index 472f3d81d2b..04bfc741d1c 100644 --- a/mysql-test/t/func_time.test +++ b/mysql-test/t/func_time.test @@ -341,20 +341,20 @@ drop table t1; # # Bug#16377 result of DATE/TIME functions were compared as strings which # can lead to a wrong result. -# +# Now wrong dates should be compared only with CAST() create table t1(f1 date, f2 time, f3 datetime); insert into t1 values ("2006-01-01", "12:01:01", "2006-01-01 12:01:01"); insert into t1 values ("2006-01-02", "12:01:02", "2006-01-02 12:01:02"); -select f1 from t1 where f1 between "2006-1-1" and 20060101; -select f1 from t1 where f1 between "2006-1-1" and "2006.1.1"; -select f1 from t1 where date(f1) between "2006-1-1" and "2006.1.1"; -select f2 from t1 where f2 between "12:1:2" and "12:2:2"; -select f2 from t1 where time(f2) between "12:1:2" and "12:2:2"; -select f3 from t1 where f3 between "2006-1-1 12:1:1" and "2006-1-1 12:1:2"; -select f3 from t1 where timestamp(f3) between "2006-1-1 12:1:1" and "2006-1-1 12:1:2"; -select f1 from t1 where "2006-1-1" between f1 and f3; -select f1 from t1 where "2006-1-1" between date(f1) and date(f3); -select f1 from t1 where "2006-1-1" between f1 and 'zzz'; +select f1 from t1 where f1 between CAST("2006-1-1" as date) and CAST(20060101 as date); +select f1 from t1 where f1 between cast("2006-1-1" as date) and cast("2006.1.1" as date); +select f1 from t1 where date(f1) between cast("2006-1-1" as date) and cast("2006.1.1" as date); +select f2 from t1 where f2 between cast("12:1:2" as time) and cast("12:2:2" as time); +select f2 from t1 where time(f2) between cast("12:1:2" as time) and cast("12:2:2" as time); +select f3 from t1 where f3 between cast("2006-1-1 12:1:1" as datetime) and cast("2006-1-1 12:1:2" as datetime); +select f3 from t1 where timestamp(f3) between cast("2006-1-1 12:1:1" as datetime) and cast("2006-1-1 12:1:2" as datetime); +select f1 from t1 where cast("2006-1-1" as date) between f1 and f3; +select f1 from t1 where cast("2006-1-1" as date) between date(f1) and date(f3); +select f1 from t1 where cast("2006-1-1" as date) between f1 and 'zzz'; select f1 from t1 where makedate(2006,1) between date(f1) and date(f3); select f1 from t1 where makedate(2006,2) between date(f1) and date(f3); drop table t1; diff --git a/mysql-test/t/type_date.test b/mysql-test/t/type_date.test index 78bdd9b8a80..5556d7f2831 100644 --- a/mysql-test/t/type_date.test +++ b/mysql-test/t/type_date.test @@ -36,8 +36,8 @@ INSERT INTO t1 VALUES ( "2000-1-2" ); INSERT INTO t1 VALUES ( "2000-1-3" ); INSERT INTO t1 VALUES ( "2000-1-4" ); INSERT INTO t1 VALUES ( "2000-1-5" ); -SELECT * FROM t1 WHERE datum BETWEEN "2000-1-2" AND "2000-1-4"; -SELECT * FROM t1 WHERE datum BETWEEN "2000-1-2" AND datum - INTERVAL 100 DAY; +SELECT * FROM t1 WHERE datum BETWEEN cast("2000-1-2" as date) AND cast("2000-1-4" as date); +SELECT * FROM t1 WHERE datum BETWEEN cast("2000-1-2" as date) AND datum - INTERVAL 100 DAY; DROP TABLE t1; # diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index a32bd0a7337..b766d1e857b 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -75,119 +75,14 @@ static void agg_result_type(Item_result *type, Item **items, uint nitems) This function aggregates result types from the array of items. Found type supposed to be used later for comparison of values of these items. Aggregation itself is performed by the item_cmp_type() function. - - NOTES - Aggregation rules: - If there are DATE/TIME fields/functions in the list and no string - fields/functions in the list then: - The INT_RESULT type will be used for aggregation instead of original - result type of any DATE/TIME field/function in the list - All constant items in the list will be converted to a DATE/TIME using - found field or result field of found function. - - Implementation notes: - The code is equivalent to: - 1. Check the list for presence of a STRING field/function. - Collect the is_const flag. - 2. Get a Field* object to use for type coercion - 3. Perform type conversion. - 1 and 2 are implemented in 2 loops. The first searches for a DATE/TIME - field/function and checks presence of a STRING field/function. - The second loop works only if a DATE/TIME field/function is found. - It checks presence of a STRING field/function in the rest of the list. - - TODO - 1) The current implementation can produce false comparison results for - expressions like: - date_time_field BETWEEN string_field_with_dates AND string_constant - if the string_constant will omit some of leading zeroes. - In order to fully implement correct comparison of DATE/TIME the new - DATETIME_RESULT result type should be introduced and agg_cmp_type() - should return the DATE/TIME field used for the conversion. Later - this field can be used by comparison functions like Item_func_between to - convert string values to ints on the fly and thus return correct results. - This modification will affect functions BETWEEN, IN and CASE. - - 2) If in the list a DATE field/function and a DATETIME field/function - are present in the list then the first found field/function will be - used for conversion. This may lead to wrong results and probably should - be fixed. */ static void agg_cmp_type(THD *thd, Item_result *type, Item **items, uint nitems) { uint i; - Item::Type res= (Item::Type)0; - /* Used only for date/time fields, max_length = 19 */ - char buff[20]; - uchar null_byte; - Field *field= NULL; - - /* Search for date/time fields/functions */ - for (i= 0; i < nitems; i++) - { - if (!items[i]->result_as_longlong()) - { - /* Do not convert anything if a string field/function is present */ - if (!items[i]->const_item() && items[i]->result_type() == STRING_RESULT) - { - i= nitems; - break; - } - continue; - } - if ((res= items[i]->real_item()->type()) == Item::FIELD_ITEM && - items[i]->result_type() != INT_RESULT) - { - field= ((Item_field *)items[i]->real_item())->field; - break; - } - else if (res == Item::FUNC_ITEM) - { - field= items[i]->tmp_table_field_from_field_type(0); - if (field) - field->move_field(buff, &null_byte, 0); - break; - } - } - if (field) - { - /* Check the rest of the list for presence of a string field/function. */ - for (i++ ; i < nitems; i++) - { - if (!items[i]->const_item() && items[i]->result_type() == STRING_RESULT && - !items[i]->result_as_longlong()) - { - if (res == Item::FUNC_ITEM) - delete field; - field= 0; - break; - } - } - } - /* - If the first item is a date/time function then its result should be - compared as int - */ - if (field) - /* Suppose we are comparing dates */ - type[0]= INT_RESULT; - else - type[0]= items[0]->result_type(); - - for (i= 0; i < nitems ; i++) - { - Item_result result= items[i]->result_type(); - if (field && - ((!items[i]->const_item() && items[i]->result_as_longlong()) || - (items[i]->const_item() && convert_constant_item(thd, field, - &items[i])))) - result= INT_RESULT; - type[0]= item_cmp_type(type[0], result); - } - - if (res == Item::FUNC_ITEM && field) - delete field; + type[0]= items[0]->result_type(); + for (i= 1 ; i < nitems ; i++) + type[0]= item_cmp_type(type[0], items[i]->result_type()); } static void my_coll_agg_error(DTCollation &c1, DTCollation &c2, From 719f836cc4b0ee3dd35bf7cf641461bc6289b3cc Mon Sep 17 00:00:00 2001 From: "gkodinov/kgeorge@macbook.gmz" <> Date: Fri, 8 Sep 2006 10:24:14 +0300 Subject: [PATCH 19/39] Bug#21555: incorrect behavior with INSERT ... ON DUPL KEY UPDATE and VALUES VALUES() was considered a constant. This caused replacing (or pre-calculating) it using uninitialized values before the actual execution takes place. Mark it as a non-constant (still not dependent of tables) to prevent the pre-calculation. --- mysql-test/r/insert_update.result | 26 ++++++++++++++++++++++++-- mysql-test/t/insert_update.test | 23 +++++++++++++++++++++++ sql/item.h | 6 +++++- 3 files changed, 52 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/insert_update.result b/mysql-test/r/insert_update.result index 9e674cc4aae..c41aab29853 100644 --- a/mysql-test/r/insert_update.result +++ b/mysql-test/r/insert_update.result @@ -63,9 +63,9 @@ Warnings: Note 1003 select test.t1.a AS `a`,test.t1.b AS `b`,test.t1.c AS `c`,values(test.t1.a) AS `VALUES(a)` from test.t1 explain extended select * from t1 where values(a); id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where Warnings: -Note 1003 select test.t1.a AS `a`,test.t1.b AS `b`,test.t1.c AS `c` from test.t1 +Note 1003 select test.t1.a AS `a`,test.t1.b AS `b`,test.t1.c AS `c` from test.t1 where values(test.t1.a) DROP TABLE t1; create table t1(a int primary key, b int); insert into t1 values(1,1),(2,2),(3,3),(4,4),(5,5); @@ -197,3 +197,25 @@ PRIMARY KEY (a) ) ENGINE=MyISAM; INSERT INTO t1 ( a ) SELECT 0 ON DUPLICATE KEY UPDATE a = a + VALUES (a) ; DROP TABLE t1; +CREATE TABLE t1 +( +a BIGINT UNSIGNED, +b BIGINT UNSIGNED, +PRIMARY KEY (a) +); +INSERT INTO t1 VALUES (45, 1) ON DUPLICATE KEY UPDATE b = +IF(VALUES(b) > t1.b, VALUES(b), t1.b); +SELECT * FROM t1; +a b +45 1 +INSERT INTO t1 VALUES (45, 2) ON DUPLICATE KEY UPDATE b = +IF(VALUES(b) > t1.b, VALUES(b), t1.b); +SELECT * FROM t1; +a b +45 2 +INSERT INTO t1 VALUES (45, 1) ON DUPLICATE KEY UPDATE b = +IF(VALUES(b) > t1.b, VALUES(b), t1.b); +SELECT * FROM t1; +a b +45 2 +DROP TABLE t1; diff --git a/mysql-test/t/insert_update.test b/mysql-test/t/insert_update.test index 8038bd7bfe7..56885a555fd 100644 --- a/mysql-test/t/insert_update.test +++ b/mysql-test/t/insert_update.test @@ -115,4 +115,27 @@ INSERT INTO t1 ( a ) SELECT 0 ON DUPLICATE KEY UPDATE a = a + VALUES (a) ; DROP TABLE t1; +# +# Bug#21555: incorrect behavior with INSERT ... ON DUPL KEY UPDATE and VALUES +# + + # End of 4.1 tests +CREATE TABLE t1 +( + a BIGINT UNSIGNED, + b BIGINT UNSIGNED, + PRIMARY KEY (a) +); + +INSERT INTO t1 VALUES (45, 1) ON DUPLICATE KEY UPDATE b = + IF(VALUES(b) > t1.b, VALUES(b), t1.b); +SELECT * FROM t1; +INSERT INTO t1 VALUES (45, 2) ON DUPLICATE KEY UPDATE b = + IF(VALUES(b) > t1.b, VALUES(b), t1.b); +SELECT * FROM t1; +INSERT INTO t1 VALUES (45, 1) ON DUPLICATE KEY UPDATE b = + IF(VALUES(b) > t1.b, VALUES(b), t1.b); +SELECT * FROM t1; + +DROP TABLE t1; diff --git a/sql/item.h b/sql/item.h index 3eab695cb5e..ad8bea663f1 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1241,7 +1241,11 @@ public: { return Item_field::save_in_field(field_arg, no_conversions); } - table_map used_tables() const { return (table_map)0L; } + /* + We use RAND_TABLE_BIT to prevent Item_insert_value from + being treated as a constant and precalculated before execution + */ + table_map used_tables() const { return RAND_TABLE_BIT; } bool walk(Item_processor processor, byte *args) { From 0f8069bfb0b449f6ceeafb0aa6a9fde1427e3099 Mon Sep 17 00:00:00 2001 From: "gkodinov/kgeorge@macbook.gmz" <> Date: Fri, 8 Sep 2006 13:10:14 +0300 Subject: [PATCH 20/39] Bug #21772: can not name a column 'upgrade' when create a table in version 5.0.24 Upgrade was a reserved word. Unreserve UPGRADE so it can be used in unquoted identifiers. --- mysql-test/r/create.result | 2 ++ mysql-test/t/create.test | 6 ++++++ sql/sql_yacc.yy | 1 + 3 files changed, 9 insertions(+) diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result index 3f8083a0e20..5f885ad199b 100644 --- a/mysql-test/r/create.result +++ b/mysql-test/r/create.result @@ -773,3 +773,5 @@ Warnings: Warning 1071 Specified key was too long; max key length is 765 bytes insert into t1 values('aaa'); drop table t1; +create table t1 (upgrade int); +drop table t1; diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test index 07edbf206fe..db73782fdbf 100644 --- a/mysql-test/t/create.test +++ b/mysql-test/t/create.test @@ -674,4 +674,10 @@ create table t1(f1 varchar(800) binary not null, key(f1)) engine = innodb insert into t1 values('aaa'); drop table t1; +# +# Bug#21772: can not name a column 'upgrade' when create a table +# +create table t1 (upgrade int); +drop table t1; + # End of 5.0 tests diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index aee810e75ad..97f6cdd27e4 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -7555,6 +7555,7 @@ keyword: | TRUNCATE_SYM {} | UNICODE_SYM {} | XA_SYM {} + | UPGRADE_SYM {} ; /* From 9c15b7e0e8648bb774589cfe27790cb3075ec5d8 Mon Sep 17 00:00:00 2001 From: "igor@rurik.mysql.com" <> Date: Sat, 9 Sep 2006 09:43:09 -0700 Subject: [PATCH 21/39] Post-pushbuild corrections for fix of bug #21698. --- mysql-test/r/func_str.result | 4 ++-- mysql-test/t/func_str.test | 4 ++-- sql/item.h | 27 +++++++++++++++++++++++++++ sql/item_cmpfunc.cc | 2 +- sql/item_func.cc | 2 +- sql/sql_select.cc | 4 ++-- 6 files changed, 35 insertions(+), 8 deletions(-) diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index 94fb570381a..00642e1a570 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -1136,12 +1136,12 @@ ALTER TABLE t1 ADD INDEX (code); CREATE TABLE t2 (id varchar(10) PRIMARY KEY); INSERT INTO t2 VALUES ('a11'), ('a12'), ('a13'), ('a14'); SELECT * FROM t1 INNER JOIN t2 ON t1.code=t2.id -WHERE t2.id='a12' AND (code < 'a00' OR LENGTH(code)=5); +WHERE t2.id='a12' AND (LENGTH(code)=5 OR code < 'a00'); code id A12 a12 EXPLAIN EXTENDED SELECT * FROM t1 INNER JOIN t2 ON code=id -WHERE id='a12' AND (code < 'a00' OR LENGTH(code)=5); +WHERE id='a12' AND (LENGTH(code)=5 OR code < 'a00'); id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ref code code 13 const 3 Using where; Using index 1 SIMPLE t2 ref PRIMARY PRIMARY 12 const 1 Using where; Using index diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index 415c6d2a44e..45415882ac7 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -773,10 +773,10 @@ CREATE TABLE t2 (id varchar(10) PRIMARY KEY); INSERT INTO t2 VALUES ('a11'), ('a12'), ('a13'), ('a14'); SELECT * FROM t1 INNER JOIN t2 ON t1.code=t2.id - WHERE t2.id='a12' AND (code < 'a00' OR LENGTH(code)=5); + WHERE t2.id='a12' AND (LENGTH(code)=5 OR code < 'a00'); EXPLAIN EXTENDED SELECT * FROM t1 INNER JOIN t2 ON code=id - WHERE id='a12' AND (code < 'a00' OR LENGTH(code)=5); + WHERE id='a12' AND (LENGTH(code)=5 OR code < 'a00'); DROP TABLE t1,t2; diff --git a/sql/item.h b/sql/item.h index f6145d6e20c..cdd0f863aea 100644 --- a/sql/item.h +++ b/sql/item.h @@ -411,6 +411,17 @@ public: typedef bool (Item::*Item_processor) (byte *arg); +/* + Analyzer function + SYNOPSIS + argp in/out IN: Analysis parameter + OUT: Parameter to be passed to the transformer + + RETURN + TRUE Invoke the transformer + FALSE Don't do it + +*/ typedef bool (Item::*Item_analyzer) (byte **argp); typedef Item* (Item::*Item_transformer) (byte *arg); typedef void (*Cond_traverser) (const Item *item, void *arg); @@ -740,6 +751,22 @@ public: return (this->*transformer)(arg); } + /* + This function performs a generic "compilation" of the Item tree. + The process of compilation is assumed to go as follows: + + compile() + { + if (this->*some_analyzer(...)) + { + compile children if any; + this->*some_transformer(...); + } + } + + i.e. analysis is performed top-down while transformation is done + bottom-up. + */ virtual Item* compile(Item_analyzer analyzer, byte **arg_p, Item_transformer transformer, byte *arg_t) { diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index fa01ae65b0d..3694c01d0aa 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -2811,7 +2811,6 @@ Item *Item_cond::compile(Item_analyzer analyzer, byte **arg_p, if (!(this->*analyzer)(arg_p)) return 0; - byte *arg_v= *arg_p; List_iterator li(list); Item *item; while ((item= li++)) @@ -2820,6 +2819,7 @@ Item *Item_cond::compile(Item_analyzer analyzer, byte **arg_p, The same parameter value of arg_p must be passed to analyze any argument of the condition formula. */ + byte *arg_v= *arg_p; Item *new_item= item->compile(analyzer, &arg_v, transformer, arg_t); if (new_item && new_item != item) li.replace(new_item); diff --git a/sql/item_func.cc b/sql/item_func.cc index acd6ec19470..c5588e43b49 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -304,7 +304,6 @@ Item *Item_func::compile(Item_analyzer analyzer, byte **arg_p, { if (!(this->*analyzer)(arg_p)) return 0; - byte *arg_v= *arg_p; if (arg_count) { Item **arg,**arg_end; @@ -314,6 +313,7 @@ Item *Item_func::compile(Item_analyzer analyzer, byte **arg_p, The same parameter value of arg_p must be passed to analyze any argument of the condition formula. */ + byte *arg_v= *arg_p; Item *new_item= (*arg)->compile(analyzer, &arg_v, transformer, arg_t); if (new_item && *arg != new_item) current_thd->change_item_tree(arg, new_item); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 4d2b3cac254..8ba11195c87 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -6919,9 +6919,9 @@ static COND *build_equal_items_for_cond(COND *cond, as soon the field is not of a string type or the field reference is an argument of a comparison predicate. */ - byte *dummy; + byte *is_subst_valid= (byte *) 1; cond= cond->compile(&Item::subst_argument_checker, - &dummy, + &is_subst_valid, &Item::equal_fields_propagator, (byte *) inherited); cond->update_used_tables(); From 6ad198e997e82fdc5b44b1a7db2a8856e775b674 Mon Sep 17 00:00:00 2001 From: "lars/lthalmann@mysql.com/dl145j.mysql.com" <> Date: Mon, 11 Sep 2006 14:45:40 +0200 Subject: [PATCH 22/39] Fix WARN_DEPRECATED for 5.0 (it is in 5.1 we should have the extra arguments) --- sql/sql_yacc.yy | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index fbde9e2884f..375f49b1120 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -6873,7 +6873,7 @@ load: LOAD DATA_SYM YYABORT; } lex->sql_command = SQLCOM_LOAD_MASTER_TABLE; - WARN_DEPRECATED(yythd, "5.2", "LOAD TABLE FROM MASTER", + WARN_DEPRECATED("LOAD TABLE FROM MASTER", "mysqldump or future " "BACKUP/RESTORE DATABASE facility"); if (!Select->add_table_to_list(YYTHD, $3, NULL, TL_OPTION_UPDATING)) @@ -6914,7 +6914,7 @@ load_data: FROM MASTER_SYM { Lex->sql_command = SQLCOM_LOAD_MASTER_DATA; - WARN_DEPRECATED(yythd, "5.2", "LOAD DATA FROM MASTER", + WARN_DEPRECATED("LOAD DATA FROM MASTER", "mysqldump or future " "BACKUP/RESTORE DATABASE facility"); }; From 44f167ee1d0ca223562066c5d2ccd85be93832d0 Mon Sep 17 00:00:00 2001 From: "svoj@april.(none)" <> Date: Tue, 12 Sep 2006 18:25:35 +0500 Subject: [PATCH 23/39] BUG#20256 - LOCK WRITE - MyISAM Only MyISAM tables locked with LOCK TABLES ... WRITE were affected. A query that is optimized with index_merge doesn't reflect rows inserted within LOCK TABLES. MyISAM doesn't flush a state within LOCK TABLES. index_merge optimization creates a copy of the handler, which thus gets outdated MyISAM state. New handler->clone() method is introduced to fix this problem. For non-MyISAM storage engines it allocates a handler and opens it with ha_open(). For MyISAM it additionally copies MyISAM state pointer to cloned handler. --- mysql-test/r/index_merge.result | 31 +++++++++++++++++++++++++++++++ mysql-test/t/index_merge.test | 32 ++++++++++++++++++++++++++++++++ sql/ha_myisam.cc | 8 ++++++++ sql/ha_myisam.h | 1 + sql/handler.cc | 9 +++++++++ sql/handler.h | 1 + sql/opt_range.cc | 5 +---- 7 files changed, 83 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/index_merge.result b/mysql-test/r/index_merge.result index 3a69f56cbd3..3f3360e2da0 100644 --- a/mysql-test/r/index_merge.result +++ b/mysql-test/r/index_merge.result @@ -424,3 +424,34 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t3 index_merge a,b a,b 5,5 NULL # Using intersect(a,b); Using where drop table t3; drop table t0, t1, t2; +CREATE TABLE t1(a INT); +INSERT INTO t1 VALUES(1); +CREATE TABLE t2(a INT, b INT, dummy CHAR(16) DEFAULT '', KEY(a), KEY(b)); +INSERT INTO t2(a,b) VALUES +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(1,2); +LOCK TABLES t1 WRITE, t2 WRITE; +INSERT INTO t2(a,b) VALUES(1,2); +SELECT t2.a FROM t1,t2 WHERE t2.b=2 AND t2.a=1; +a +1 +1 +UNLOCK TABLES; +DROP TABLE t1, t2; diff --git a/mysql-test/t/index_merge.test b/mysql-test/t/index_merge.test index 3da5711bf7a..30eb0b40fca 100644 --- a/mysql-test/t/index_merge.test +++ b/mysql-test/t/index_merge.test @@ -383,3 +383,35 @@ explain select * from t3 where a=1 and b=1; drop table t3; drop table t0, t1, t2; + +# +# BUG#20256 - LOCK WRITE - MyISAM +# +CREATE TABLE t1(a INT); +INSERT INTO t1 VALUES(1); +CREATE TABLE t2(a INT, b INT, dummy CHAR(16) DEFAULT '', KEY(a), KEY(b)); +INSERT INTO t2(a,b) VALUES +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0),(0,0), +(1,2); +LOCK TABLES t1 WRITE, t2 WRITE; +INSERT INTO t2(a,b) VALUES(1,2); +SELECT t2.a FROM t1,t2 WHERE t2.b=2 AND t2.a=1; +UNLOCK TABLES; +DROP TABLE t1, t2; diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc index 128cc191434..876cd33ec9c 100644 --- a/sql/ha_myisam.cc +++ b/sql/ha_myisam.cc @@ -169,6 +169,14 @@ ha_myisam::ha_myisam(TABLE *table_arg) can_enable_indexes(1) {} +handler *ha_myisam::clone(MEM_ROOT *mem_root) +{ + ha_myisam *new_handler= static_cast (handler::clone(mem_root)); + if (new_handler) + new_handler->file->state= file->state; + return new_handler; +} + static const char *ha_myisam_exts[] = { ".MYI", diff --git a/sql/ha_myisam.h b/sql/ha_myisam.h index ca684463311..950817d42bd 100644 --- a/sql/ha_myisam.h +++ b/sql/ha_myisam.h @@ -45,6 +45,7 @@ class ha_myisam: public handler public: ha_myisam(TABLE *table_arg); ~ha_myisam() {} + handler *clone(MEM_ROOT *mem_root); const char *table_type() const { return "MyISAM"; } const char *index_type(uint key_number); const char **bas_ext() const; diff --git a/sql/handler.cc b/sql/handler.cc index 01aa7491383..81981a5dcc6 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1372,6 +1372,15 @@ int ha_delete_table(THD *thd, enum db_type table_type, const char *path, /**************************************************************************** ** General handler functions ****************************************************************************/ +handler *handler::clone(MEM_ROOT *mem_root) +{ + handler *new_handler= get_new_handler(table, mem_root, table->s->db_type); + if (new_handler && !new_handler->ha_open(table->s->path, table->db_stat, + HA_OPEN_IGNORE_IF_LOCKED)) + return new_handler; + return NULL; +} + /* Open database-handler. Try O_RDONLY if can't open as O_RDWR */ /* Don't wait for locks if not HA_OPEN_WAIT_IF_LOCKED is set */ diff --git a/sql/handler.h b/sql/handler.h index 44de0cc715a..471bb08b748 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -563,6 +563,7 @@ public: pushed_cond(NULL) {} virtual ~handler(void) { /* TODO: DBUG_ASSERT(inited == NONE); */ } + virtual handler *clone(MEM_ROOT *mem_root); int ha_open(const char *name, int mode, int test_if_locked); void adjust_next_insert_id_after_explicit_value(ulonglong nr); bool update_auto_increment(); diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 3b77d1b419e..5866fe731cf 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -1033,10 +1033,7 @@ int QUICK_RANGE_SELECT::init_ror_merged_scan(bool reuse_handler) } THD *thd= current_thd; - if (!(file= get_new_handler(head, thd->mem_root, head->s->db_type))) - goto failure; - DBUG_PRINT("info", ("Allocated new handler %p", file)); - if (file->ha_open(head->s->path, head->db_stat, HA_OPEN_IGNORE_IF_LOCKED)) + if (!(file= head->file->clone(thd->mem_root))) { /* Caller will free the memory */ goto failure; From 9fb0340a3448fbd70a9f81ca39bea6b645f3a0a7 Mon Sep 17 00:00:00 2001 From: "evgen@moonbone.local" <> Date: Tue, 12 Sep 2006 19:06:26 +0400 Subject: [PATCH 24/39] item_cmpfunc.cc: Removed changes to the Item_func_between::fix_length_and_dec() made in the fix for bug#16377 query_cache.result: Corrected a test case after removing a fix for bug#16377 --- mysql-test/r/query_cache.result | 3 +++ sql/item_cmpfunc.cc | 26 ++++++++++++++++++++++++-- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result index 2a57e06e330..24363ea27ab 100644 --- a/mysql-test/r/query_cache.result +++ b/mysql-test/r/query_cache.result @@ -907,16 +907,19 @@ COUNT(*) 0 Warnings: Warning 1292 Truncated incorrect datetime value: '20050327 invalid' +Warning 1292 Truncated incorrect datetime value: '20050327 invalid' SELECT COUNT(*) FROM t1 WHERE date BETWEEN '20050326' AND '20050328 invalid'; COUNT(*) 0 Warnings: Warning 1292 Truncated incorrect datetime value: '20050328 invalid' +Warning 1292 Truncated incorrect datetime value: '20050328 invalid' SELECT COUNT(*) FROM t1 WHERE date BETWEEN '20050326' AND '20050327 invalid'; COUNT(*) 0 Warnings: Warning 1292 Truncated incorrect datetime value: '20050327 invalid' +Warning 1292 Truncated incorrect datetime value: '20050327 invalid' show status like "Qcache_queries_in_cache"; Variable_name Value Qcache_queries_in_cache 0 diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index b766d1e857b..6b6996160a1 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -916,8 +916,30 @@ void Item_func_between::fix_length_and_dec() if (!args[0] || !args[1] || !args[2]) return; agg_cmp_type(thd, &cmp_type, args, 3); - if (cmp_type == STRING_RESULT) - agg_arg_charsets(cmp_collation, args, 3, MY_COLL_CMP_CONV); + if (cmp_type == STRING_RESULT && + agg_arg_charsets(cmp_collation, args, 3, MY_COLL_CMP_CONV)) + return; + + /* + Make a special case of compare with date/time and longlong fields. + They are compared as integers, so for const item this time-consuming + conversion can be done only once, not for every single comparison + */ + if (args[0]->type() == FIELD_ITEM) + { + Field *field=((Item_field*) args[0])->field; + if (field->can_be_compared_as_longlong()) + { + /* + The following can't be recoded with || as convert_constant_item + changes the argument + */ + if (convert_constant_item(thd, field,&args[1])) + cmp_type=INT_RESULT; // Works for all types. + if (convert_constant_item(thd, field,&args[2])) + cmp_type=INT_RESULT; // Works for all types. + } + } } From a33fdb44e5d4f5324181c950b8400bbe89745b14 Mon Sep 17 00:00:00 2001 From: "joerg@trift-lap.fambruehe" <> Date: Thu, 14 Sep 2006 16:34:35 +0200 Subject: [PATCH 25/39] Include "manual.chm" in the source distribution, because we now use it for Windows builds unchanged. --- Docs/Makefile.am | 2 +- configure.in | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Docs/Makefile.am b/Docs/Makefile.am index f512aa9e29e..4722f61f5b9 100644 --- a/Docs/Makefile.am +++ b/Docs/Makefile.am @@ -16,7 +16,7 @@ noinst_SCRIPTS = Support/generate-text-files.pl -EXTRA_DIST = $(noinst_SCRIPTS) mysql.info INSTALL-BINARY +EXTRA_DIST = $(noinst_SCRIPTS) manual.chm mysql.info INSTALL-BINARY TXT_FILES= ../INSTALL-SOURCE ../INSTALL-WIN-SOURCE ../EXCEPTIONS-CLIENT \ INSTALL-BINARY ../support-files/MacOSX/ReadMe.txt diff --git a/configure.in b/configure.in index ce1a5ea2479..2af152713aa 100644 --- a/configure.in +++ b/configure.in @@ -1216,6 +1216,7 @@ EOF # echo -n "making sure specific build files are writable... " for file in \ + Docs/manual.chm \ Docs/mysql.info \ Docs/INSTALL-BINARY \ INSTALL-SOURCE \ From a33d1d84847c28f5693e22bd24bc434ec0cfa90a Mon Sep 17 00:00:00 2001 From: "evgen@moonbone.local" <> Date: Thu, 14 Sep 2006 18:45:23 +0400 Subject: [PATCH 26/39] type_date.test, type_date.result: Added the test case for bug#21677: Wrong result when comparing a DATE and a DATETIME in BETWEEN --- mysql-test/r/type_date.result | 6 ++++++ mysql-test/t/type_date.test | 7 +++++++ 2 files changed, 13 insertions(+) diff --git a/mysql-test/r/type_date.result b/mysql-test/r/type_date.result index d8d6aa89684..99e9adf84ca 100644 --- a/mysql-test/r/type_date.result +++ b/mysql-test/r/type_date.result @@ -104,3 +104,9 @@ SELECT * FROM t1; y 0000 DROP TABLE t1; +create table t1(start_date date, end_date date); +insert into t1 values ('2000-01-01','2000-01-02'); +select 1 from t1 where cast('2000-01-01 12:01:01' as datetime) between start_date and end_date; +1 +1 +drop table t1; diff --git a/mysql-test/t/type_date.test b/mysql-test/t/type_date.test index 5556d7f2831..c6050753943 100644 --- a/mysql-test/t/type_date.test +++ b/mysql-test/t/type_date.test @@ -115,4 +115,11 @@ INSERT INTO t1 VALUES ('abc'); SELECT * FROM t1; DROP TABLE t1; +# +# Bug#21677: Wrong result when comparing a DATE and a DATETIME in BETWEEN +# +create table t1(start_date date, end_date date); +insert into t1 values ('2000-01-01','2000-01-02'); +select 1 from t1 where cast('2000-01-01 12:01:01' as datetime) between start_date and end_date; +drop table t1; # End of 4.1 tests From d53ac1962008a89141782e061866518075300037 Mon Sep 17 00:00:00 2001 From: "istruewing@chilla.local" <> Date: Thu, 14 Sep 2006 16:55:57 +0200 Subject: [PATCH 27/39] Bug#14400 - Query joins wrong rows from table which is subject of "concurrent insert" After merge fix. --- myisam/mi_rkey.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/myisam/mi_rkey.c b/myisam/mi_rkey.c index 9ca1ee91273..60ef5ad32f0 100644 --- a/myisam/mi_rkey.c +++ b/myisam/mi_rkey.c @@ -103,7 +103,7 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len, { do { - uint not_used; + uint not_used[2]; /* Skip rows that are inserted by other threads since we got a lock Note that this can only happen if we are not searching after an @@ -122,7 +122,7 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len, */ if (search_flag == HA_READ_KEY_EXACT && ha_key_cmp(keyinfo->seg, key_buff, info->lastkey, use_key_length, - SEARCH_FIND, ¬_used)) + SEARCH_FIND, not_used)) { my_errno= HA_ERR_KEY_NOT_FOUND; info->lastpos= HA_OFFSET_ERROR; From dd410b3f779ad1796bb1ecea133c74ea00574602 Mon Sep 17 00:00:00 2001 From: "lars/lthalmann@mysql.com/dl145k.mysql.com" <> Date: Fri, 15 Sep 2006 03:02:01 +0200 Subject: [PATCH 28/39] Merge fixes, added printout to result file --- mysql-test/r/mysqldump.result | 224 ++++++++++++++++------ mysql-test/t/mysqldump.test | 346 +++++++++++++++++----------------- 2 files changed, 341 insertions(+), 229 deletions(-) diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result index 1f2ea5b0057..207e1529b77 100644 --- a/mysql-test/r/mysqldump.result +++ b/mysql-test/r/mysqldump.result @@ -22,6 +22,9 @@ INSERT INTO t1 VALUES (1), (2); DROP TABLE t1; +# +# Bug #2005 +# CREATE TABLE t1 (a decimal(64, 20)); INSERT INTO t1 VALUES ("1234567890123456789012345678901234567890"), ("0987654321098765432109876543210987654321"); @@ -30,6 +33,9 @@ CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1; INSERT INTO `t1` VALUES ('1234567890123456789012345678901234567890.00000000000000000000'),('987654321098765432109876543210987654321.00000000000000000000'); DROP TABLE t1; +# +# Bug #2055 +# CREATE TABLE t1 (a double); INSERT INTO t1 VALUES ('-9e999999'); Warnings: @@ -39,6 +45,9 @@ CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1; INSERT INTO `t1` VALUES (RES); DROP TABLE t1; +# +# Bug #3361 mysqldump quotes DECIMAL values inconsistently +# CREATE TABLE t1 (a DECIMAL(10,5), b FLOAT); INSERT INTO t1 VALUES (1.2345, 2.3456); INSERT INTO t1 VALUES ('1.2345', 2.3456); @@ -136,6 +145,9 @@ INSERT INTO t1 VALUES (1, "test", "tes"), (2, "TEST", "TES"); DROP TABLE t1; +# +# Bug #1707 +# CREATE TABLE t1 (`a"b"` char(2)); INSERT INTO t1 VALUES ("1\""), ("\"2"); @@ -155,6 +167,10 @@ INSERT INTO t1 VALUES ("1\""), ("\"2"); DROP TABLE t1; +# +# Bug #1994 +# Bug #4261 +# CREATE TABLE t1 (a VARCHAR(255)) DEFAULT CHARSET koi8r; INSERT INTO t1 VALUES (_koi8r x'C1C2C3C4C5'), (NULL); @@ -190,6 +206,9 @@ UNLOCK TABLES; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; DROP TABLE t1; +# +# Bug #2634 +# CREATE TABLE t1 (a int) ENGINE=MYISAM; INSERT INTO t1 VALUES (1), (2); /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; @@ -239,11 +258,17 @@ UNLOCK TABLES; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; DROP TABLE t1; +# +# Bug #2592 'mysqldump doesn't quote "tricky" names correctly' +# create table ```a` (i int); CREATE TABLE ```a` ( `i` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; drop table ```a`; +# +# Bug #2591 "mysqldump quotes names inconsistently" +# create table t1(a int); /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; @@ -352,6 +377,9 @@ UNLOCK TABLES; set global sql_mode=''; drop table t1; +# +# Bug #2705 'mysqldump --tab extra output' +# create table t1(a int); insert into t1 values (1),(2),(3); @@ -380,6 +408,9 @@ CREATE TABLE `t1` ( 2 3 drop table t1; +# +# Bug #6101: create database problem +# /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; @@ -432,6 +463,12 @@ USE `mysqldump_test_db`; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; drop database mysqldump_test_db; +# +# Bug #7020 +# Check that we don't dump in UTF8 in compatible mode by default, +# but use the default compiled values, or the values given in +# --default-character-set=xxx. However, we should dump in UTF8 +# if it is explicitely set. CREATE TABLE t1 (a CHAR(10)); INSERT INTO t1 VALUES (_latin1 'ÄÖÜß'); @@ -465,6 +502,13 @@ UNLOCK TABLES; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; +# +# Bug #8063: make test mysqldump [ fail ] +# We cannot tes this command because its output depends +# on --default-character-set incompiled into "mysqldump" program. +# If the future we can move this command into a separate test with +# checking that "mysqldump" is compiled with "latin1" +# /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE='+00:00' */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; @@ -535,6 +579,9 @@ UNLOCK TABLES; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; DROP TABLE t1; +# +# WL#2319: Exclude Tables from dump +# CREATE TABLE t1 (a int); CREATE TABLE t2 (a int); INSERT INTO t1 VALUES (1),(2),(3); @@ -572,6 +619,9 @@ UNLOCK TABLES; DROP TABLE t1; DROP TABLE t2; +# +# Bug #8830 +# CREATE TABLE t1 (`b` blob); INSERT INTO `t1` VALUES (0x602010000280100005E71A); @@ -606,6 +656,9 @@ UNLOCK TABLES; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; DROP TABLE t1; +# +# Test for --insert-ignore +# CREATE TABLE t1 (a int); INSERT INTO t1 VALUES (1),(2),(3); INSERT INTO t1 VALUES (4),(5),(6); @@ -670,6 +723,10 @@ INSERT DELAYED IGNORE INTO `t1` VALUES (1),(2),(3),(4),(5),(6); /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; DROP TABLE t1; +# +# Bug #10286: mysqldump -c crashes on table that has many fields with +# long names +# create table t1 ( F_c4ca4238a0b923820dcc509a6f75849b int, F_c81e728d9d4c2f636f067f89cc14862c int, @@ -1363,6 +1420,9 @@ UNLOCK TABLES; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; drop table t1; +# +# Test for --add-drop-database +# CREATE TABLE t1 (a int); INSERT INTO t1 VALUES (1),(2),(3); @@ -1403,6 +1463,9 @@ UNLOCK TABLES; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; DROP TABLE t1; +# +# Bug #10213 mysqldump crashes when dumping VIEWs(on MacOS X) +# create database db1; use db1; CREATE TABLE t2 ( @@ -1461,6 +1524,9 @@ DROP TABLE IF EXISTS `v2`; drop table t2; drop view v2; drop database db1; +# +# Bug #10713 mysqldump includes database in create view and referenced tables +# create database db2; use db2; create table t1 (a int); @@ -1488,7 +1554,13 @@ a b 12 meg drop table t1, t2; drop database db1; +# +# Bug #15328 Segmentation fault occured if my.cnf is invalid for escape sequence +# --fields-optionally-enclosed-by=" +# +# Bug #9558 mysqldump --no-data db t1 t2 format still dumps data +# CREATE DATABASE mysqldump_test_db; USE mysqldump_test_db; CREATE TABLE t1 ( a INT ); @@ -1577,6 +1649,11 @@ CREATE TABLE `t2` ( DROP TABLE t1, t2; DROP DATABASE mysqldump_test_db; +# +# Testing with tables and databases that don't exists +# or contains illegal characters +# (Bug #9358 mysqldump crashes if tablename starts with \) +# create database mysqldump_test_db; use mysqldump_test_db; create table t1(a varchar(30) primary key, b int not null); @@ -1615,6 +1692,9 @@ mysqldump: Got error: 1102: Incorrect database name 'mysqld\ump_test_db' when se drop table t1, t2, t3; drop database mysqldump_test_db; use test; +# +# Bug #9657 mysqldump xml ( -x ) does not format NULL fields correctly +# create table t1 (a int(10)); create table t2 (pk int primary key auto_increment, a int(10), b varchar(30), c datetime, d blob, e text); @@ -1671,6 +1751,9 @@ insert into t2 (a, b) values (NULL, NULL),(10, NULL),(NULL, "twenty"),(30, "thir drop table t1, t2; +# +# Bug #12123 +# create table t1 (a text character set utf8, b text character set latin1); insert t1 values (0x4F736E616272C3BC636B, 0x4BF66C6E); select * from t1; @@ -1681,6 +1764,9 @@ select * from t1; a b Osnabrück Köln drop table t1; +# +# Bug #19025 mysqldump doesn't correctly dump "auto_increment = [int]" +# create table `t1` ( t1_name varchar(255) default null, t1_id int(10) unsigned not null auto_increment, @@ -1718,7 +1804,12 @@ t1 CREATE TABLE `t1` ( KEY `t1_name` (`t1_name`) ) ENGINE=MyISAM AUTO_INCREMENT=1003 DEFAULT CHARSET=latin1 drop table `t1`; -End of 4.1 tests +# +# End of 4.1 tests +# +# +# Dump of view +# create table t1(a int); create view v1 as select * from t1; @@ -1763,6 +1854,9 @@ DROP TABLE IF EXISTS `v1`; drop view v1; drop table t1; +# +# Bug #10213 mysqldump crashes when dumping VIEWs(on MacOS X) +# create database mysqldump_test_db; use mysqldump_test_db; CREATE TABLE t2 ( @@ -1822,6 +1916,9 @@ drop table t2; drop view v2; drop database mysqldump_test_db; use test; +# +# Bug #9756 +# CREATE TABLE t1 (a char(10)); INSERT INTO t1 VALUES ('\''); @@ -1856,6 +1953,9 @@ UNLOCK TABLES; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; DROP TABLE t1; +# +# Bug #10927 mysqldump: Can't reload dump with view that consist of other view +# create table t1(a int, b int, c varchar(30)); insert into t1 values(1, 2, "one"), (2, 4, "two"), (3, 6, "three"); create view v3 as @@ -1933,6 +2033,9 @@ DROP TABLE IF EXISTS `v3`; drop view v1, v2, v3; drop table t1; +# +# Test for dumping triggers +# CREATE TABLE t1 (a int, b bigint default NULL); CREATE TABLE t2 (a int); create trigger trg1 before insert on t1 for each row @@ -2131,8 +2234,14 @@ set @fired:= "No"; end if; end BEFORE # STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER root@localhost DROP TABLE t1, t2; +# +# Bugs #9136, #12917: problems with --defaults-extra-file option +# --port=1234 --port=1234 +# +# Bug #12597 +# DROP TABLE IF EXISTS `test1`; Warnings: Note 1051 Unknown table 'test1' @@ -2164,6 +2273,9 @@ a2 DROP TRIGGER testref; DROP TABLE test1; DROP TABLE test2; +# +# Bug #9056 - mysqldump does not dump routines +# DROP TABLE IF EXISTS t1; DROP FUNCTION IF EXISTS bug9056_func1; DROP FUNCTION IF EXISTS bug9056_func2; @@ -2260,6 +2372,9 @@ DROP PROCEDURE bug9056_proc1; DROP PROCEDURE bug9056_proc2; DROP PROCEDURE `a'b`; drop table t1; +# +# Bug #13052 - mysqldump timestamp reloads broken +# drop table if exists t1; create table t1 (`d` timestamp, unique (`d`)); set time_zone='+00:00'; @@ -2346,6 +2461,9 @@ UNLOCK TABLES; drop table t1; set global time_zone=default; set time_zone=default; +# +# Bug #13146 - ansi quotes break loading of triggers +# DROP TABLE IF EXISTS `t1 test`; DROP TABLE IF EXISTS `t2 test`; CREATE TABLE `t1 test` ( @@ -2409,6 +2527,9 @@ UNLOCK TABLES; DROP TRIGGER `test trig`; DROP TABLE `t1 test`; DROP TABLE `t2 test`; +# +# Bug #12838 mysqldump -x with views exits with error +# drop table if exists t1; create table t1 (a int, b varchar(32), c varchar(32)); insert into t1 values (1, 'first value', 'xxxx'); @@ -2501,6 +2622,10 @@ drop view v2; drop view v0; drop view v1; drop table t1; +# +# Bug #14554 - mysqldump does not separate words "ROW" and "BEGIN" +# for tables with trigger created in the IGNORE_SPACE sql mode. +# SET @old_sql_mode = @@SQL_MODE; SET SQL_MODE = IGNORE_SPACE; CREATE TABLE t1 (a INT); @@ -2556,6 +2681,9 @@ DELIMITER ; DROP TRIGGER tr1; DROP TABLE t1; +# +# Bug #13318: Bad result with empty field and --hex-blob +# create table t1 (a binary(1), b blob); insert into t1 values ('',''); @@ -2623,6 +2751,9 @@ UNLOCK TABLES; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; drop table t1; +# +# Bug #18536: wrong table order +# create table t1(a int); create table t2(a int); create table t3(a int); @@ -2661,6 +2792,9 @@ CREATE TABLE `t2` ( drop table t1, t2, t3; End of 4.1 tests +# +# Bug #14871 Invalid view dump output +# create table t1 (a int); insert into t1 values (289), (298), (234), (456), (789); create definer = CURRENT_USER view v1 as select * from t1; @@ -2687,6 +2821,9 @@ a 789 drop table t1; drop view v1, v2, v3, v4, v5; +# +# Bug #16878 dump of trigger +# create table t1 (a int, created datetime); create table t2 (b int, created datetime); create trigger tr1 before insert on t1 for each row set @@ -2709,6 +2846,9 @@ end AFTER # root@localhost drop trigger tr1; drop trigger tr2; drop table t1, t2; +# +# Bug #18462 mysqldump does not dump view structures correctly +# create table t (qty int, price int); insert into t values(3, 50); insert into t values(5, 51); @@ -2728,6 +2868,10 @@ mysqldump { drop view v1; drop view v2; drop table t; +# +# Bug #14857 Reading dump files with single statement stored routines fails. +# fixed by patch for Bug #16878 +# /*!50003 CREATE FUNCTION `f`() RETURNS bigint(20) return 42 */| /*!50003 CREATE PROCEDURE `p`() @@ -2742,6 +2886,9 @@ p CREATE DEFINER=`root`@`localhost` PROCEDURE `p`() select 42 drop function f; drop procedure p; +# +# Bug #17371 Unable to dump a schema with invalid views +# create table t1 ( id serial ); create view v1 as select * from t1; drop table t1; @@ -2751,6 +2898,11 @@ mysqldump { } mysqldump drop view v1; +# +# Bug #17201 Spurious 'DROP DATABASE' in output, +# also confusion between tables and views. +# Example code from Markus Popp +# create database mysqldump_test_db; use mysqldump_test_db; create table t1 (id int); @@ -2811,6 +2963,9 @@ USE `mysqldump_test_db`; drop view v1; drop table t1; drop database mysqldump_test_db; +# +# Bug21014 Segmentation fault of mysqldump on view +# create database mysqldump_tables; use mysqldump_tables; create table basetable ( id serial, tag varchar(64) ); @@ -2844,6 +2999,9 @@ drop view nasishnasifu; drop database mysqldump_views; drop table mysqldump_tables.basetable; drop database mysqldump_tables; +# +# Bug20221 Dumping of multiple databases containing view(s) yields maleformed dumps +# create database mysqldump_dba; use mysqldump_dba; create table t1 (f1 int, f2 int); @@ -2875,6 +3033,9 @@ use mysqldump_dbb; drop view v1; drop table t1; drop database mysqldump_dbb; +# +# Bug #21215 mysqldump creating incomplete backups without warning +# use test; create user mysqltest_1@localhost; create table t1(a int, b varchar(34)); @@ -2892,60 +3053,9 @@ CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1; drop table t1; drop user mysqltest_1@localhost; -/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; -/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; -/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; -/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; -/*!40103 SET TIME_ZONE='+00:00' */; -/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; -/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; -/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; -/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; - -CREATE DATABASE /*!32312 IF NOT EXISTS*/ `mysqldump_tables` /*!40100 DEFAULT CHARACTER SET latin1 */; - -USE `mysqldump_tables`; -DROP TABLE IF EXISTS `basetable`; -CREATE TABLE `basetable` ( - `id` bigint(20) unsigned NOT NULL auto_increment, - `tag` varchar(64) default NULL, - UNIQUE KEY `id` (`id`) -) ENGINE=MyISAM DEFAULT CHARSET=latin1; - -LOCK TABLES `basetable` WRITE; -/*!40000 ALTER TABLE `basetable` DISABLE KEYS */; -/*!40000 ALTER TABLE `basetable` ENABLE KEYS */; -UNLOCK TABLES; - -CREATE DATABASE /*!32312 IF NOT EXISTS*/ `mysqldump_views` /*!40100 DEFAULT CHARACTER SET latin1 */; - -USE `mysqldump_views`; -DROP TABLE IF EXISTS `nasishnasifu`; -/*!50001 DROP VIEW IF EXISTS `nasishnasifu`*/; -/*!50001 CREATE TABLE `nasishnasifu` ( - `id` bigint(20) unsigned -) */; -/*!50001 DROP TABLE IF EXISTS `nasishnasifu`*/; -/*!50001 DROP VIEW IF EXISTS `nasishnasifu`*/; -/*!50001 CREATE ALGORITHM=UNDEFINED */ -/*!50013 DEFINER=`root`@`localhost` SQL SECURITY DEFINER */ -/*!50001 VIEW `mysqldump_views`.`nasishnasifu` AS select `mysqldump_tables`.`basetable`.`id` AS `id` from `mysqldump_tables`.`basetable` */; -/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; - -/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; -/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; -/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; -/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; -/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; -/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; -/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; - -drop view nasishnasifu; -drop database mysqldump_views; -drop table mysqldump_tables.basetable; -drop database mysqldump_tables; -USE test; +# +# Bug #13926: --order-by-primary fails if PKEY contains quote character +# DROP TABLE IF EXISTS `t1`; CREATE TABLE `t1` ( `a b` INT, @@ -3015,4 +3125,6 @@ UNLOCK TABLES; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; DROP TABLE `t1`; -End of 5.0 tests +# +# End of 5.0 tests +# diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test index 7d9f0529ab2..735a3d4c789 100644 --- a/mysql-test/t/mysqldump.test +++ b/mysql-test/t/mysqldump.test @@ -16,9 +16,9 @@ INSERT INTO t1 VALUES (1), (2); --exec $MYSQL_DUMP --skip-create --skip-comments -X test t1 DROP TABLE t1; -# -# Bug #2005 -# +--echo # +--echo # Bug #2005 +--echo # CREATE TABLE t1 (a decimal(64, 20)); INSERT INTO t1 VALUES ("1234567890123456789012345678901234567890"), @@ -26,9 +26,9 @@ INSERT INTO t1 VALUES ("1234567890123456789012345678901234567890"), --exec $MYSQL_DUMP --compact test t1 DROP TABLE t1; -# -# Bug #2055 -# +--echo # +--echo # Bug #2055 +--echo # CREATE TABLE t1 (a double); INSERT INTO t1 VALUES ('-9e999999'); @@ -38,9 +38,9 @@ INSERT INTO t1 VALUES ('-9e999999'); --exec $MYSQL_DUMP --compact test t1 DROP TABLE t1; -# -# Bug #3361 mysqldump quotes DECIMAL values inconsistently -# +--echo # +--echo # Bug #3361 mysqldump quotes DECIMAL values inconsistently +--echo # CREATE TABLE t1 (a DECIMAL(10,5), b FLOAT); @@ -69,28 +69,28 @@ INSERT INTO t1 VALUES (1, "test", "tes"), (2, "TEST", "TES"); --exec $MYSQL_DUMP --skip-create --compact -X test t1 DROP TABLE t1; -# -# Bug #1707 -# +--echo # +--echo # Bug #1707 +--echo # CREATE TABLE t1 (`a"b"` char(2)); INSERT INTO t1 VALUES ("1\""), ("\"2"); --exec $MYSQL_DUMP --compact --skip-create -X test t1 DROP TABLE t1; -# -# Bug #1994 -# Bug #4261 -# +--echo # +--echo # Bug #1994 +--echo # Bug #4261 +--echo # CREATE TABLE t1 (a VARCHAR(255)) DEFAULT CHARSET koi8r; INSERT INTO t1 VALUES (_koi8r x'C1C2C3C4C5'), (NULL); --exec $MYSQL_DUMP --skip-comments --skip-extended-insert test t1 DROP TABLE t1; -# -# Bug #2634 -# +--echo # +--echo # Bug #2634 +--echo # CREATE TABLE t1 (a int) ENGINE=MYISAM; INSERT INTO t1 VALUES (1), (2); @@ -98,17 +98,17 @@ INSERT INTO t1 VALUES (1), (2); --exec $MYSQL_DUMP --skip-comments --compatible=mysql323 test t1 DROP TABLE t1; -# -# Bug #2592 'mysqldump doesn't quote "tricky" names correctly' -# +--echo # +--echo # Bug #2592 'mysqldump doesn't quote "tricky" names correctly' +--echo # create table ```a` (i int); --exec $MYSQL_DUMP --compact test drop table ```a`; -# -# Bug #2591 "mysqldump quotes names inconsistently" -# +--echo # +--echo # Bug #2591 "mysqldump quotes names inconsistently" +--echo # create table t1(a int); --exec $MYSQL_DUMP --comments=0 test @@ -119,9 +119,9 @@ set global sql_mode='ANSI_QUOTES'; set global sql_mode=''; drop table t1; -# -# Bug #2705 'mysqldump --tab extra output' -# +--echo # +--echo # Bug #2705 'mysqldump --tab extra output' +--echo # create table t1(a int); insert into t1 values (1),(2),(3); @@ -135,9 +135,9 @@ insert into t1 values (1),(2),(3); --exec rm $MYSQLTEST_VARDIR/tmp/t1.txt drop table t1; -# -# Bug #6101: create database problem -# +--echo # +--echo # Bug #6101: create database problem +--echo # --exec $MYSQL_DUMP --skip-comments --databases test @@ -145,32 +145,33 @@ create database mysqldump_test_db character set latin2 collate latin2_bin; --exec $MYSQL_DUMP --skip-comments --databases mysqldump_test_db drop database mysqldump_test_db; -# -# Bug #7020 -# Check that we don't dump in UTF8 in compatible mode by default, -# but use the default compiled values, or the values given in -# --default-character-set=xxx. However, we should dump in UTF8 -# if it is explicitely set. +--echo # +--echo # Bug #7020 +--echo # Check that we don't dump in UTF8 in compatible mode by default, +--echo # but use the default compiled values, or the values given in +--echo # --default-character-set=xxx. However, we should dump in UTF8 +--echo # if it is explicitely set. CREATE TABLE t1 (a CHAR(10)); INSERT INTO t1 VALUES (_latin1 'ÄÖÜß'); --exec $MYSQL_DUMP --character-sets-dir=$CHARSETSDIR --skip-comments test t1 -# -# Bug#8063: make test mysqldump [ fail ] -# We cannot tes this command because its output depends -# on --default-character-set incompiled into "mysqldump" program. -# If the future we can move this command into a separate test with -# checking that "mysqldump" is compiled with "latin1" -# + +--echo # +--echo # Bug #8063: make test mysqldump [ fail ] +--echo # We cannot tes this command because its output depends +--echo # on --default-character-set incompiled into "mysqldump" program. +--echo # If the future we can move this command into a separate test with +--echo # checking that "mysqldump" is compiled with "latin1" +--echo # #--exec $MYSQL_DUMP --character-sets-dir=$CHARSETSDIR --skip-comments --compatible=mysql323 test t1 --exec $MYSQL_DUMP --character-sets-dir=$CHARSETSDIR --skip-comments --compatible=mysql323 --default-character-set=cp850 test t1 --exec $MYSQL_DUMP --character-sets-dir=$CHARSETSDIR --skip-comments --default-character-set=cp850 --compatible=mysql323 test t1 --exec $MYSQL_DUMP --character-sets-dir=$CHARSETSDIR --skip-comments --default-character-set=utf8 --compatible=mysql323 test t1 DROP TABLE t1; -# -# WL #2319: Exclude Tables from dump -# +--echo # +--echo # WL#2319: Exclude Tables from dump +--echo # CREATE TABLE t1 (a int); CREATE TABLE t2 (a int); @@ -180,18 +181,18 @@ INSERT INTO t2 VALUES (4),(5),(6); DROP TABLE t1; DROP TABLE t2; -# -# Bug #8830 -# +--echo # +--echo # Bug #8830 +--echo # CREATE TABLE t1 (`b` blob); INSERT INTO `t1` VALUES (0x602010000280100005E71A); --exec $MYSQL_DUMP --skip-extended-insert --hex-blob test --skip-comments t1 DROP TABLE t1; -# -# Test for --insert-ignore -# +--echo # +--echo # Test for --insert-ignore +--echo # CREATE TABLE t1 (a int); INSERT INTO t1 VALUES (1),(2),(3); @@ -200,10 +201,10 @@ INSERT INTO t1 VALUES (4),(5),(6); --exec $MYSQL_DUMP --skip-comments --insert-ignore --delayed-insert test t1 DROP TABLE t1; -# -# Bug #10286: mysqldump -c crashes on table that has many fields with long -# names -# +--echo # +--echo # Bug #10286: mysqldump -c crashes on table that has many fields with +--echo # long names +--echo # create table t1 ( F_c4ca4238a0b923820dcc509a6f75849b int, F_c81e728d9d4c2f636f067f89cc14862c int, @@ -539,19 +540,18 @@ insert into t1 (F_8d3bba7425e7c98c50f52ca1b52d3735) values (1); --exec $MYSQL_DUMP --skip-comments -c test drop table t1; -# -# Test for --add-drop-database -# +--echo # +--echo # Test for --add-drop-database +--echo # CREATE TABLE t1 (a int); INSERT INTO t1 VALUES (1),(2),(3); --exec $MYSQL_DUMP --add-drop-database --skip-comments --databases test DROP TABLE t1; - -# -# Bug #10213 mysqldump crashes when dumping VIEWs(on MacOS X) -# +--echo # +--echo # Bug #10213 mysqldump crashes when dumping VIEWs(on MacOS X) +--echo # create database db1; use db1; @@ -572,9 +572,9 @@ drop table t2; drop view v2; drop database db1; -# -# Bug 10713 mysqldump includes database in create view and referenced tables -# +--echo # +--echo # Bug #10713 mysqldump includes database in create view and referenced tables +--echo # # create table and views in db2 create database db2; @@ -606,16 +606,15 @@ select * from t2 order by a; drop table t1, t2; drop database db1; -# -# BUG#15328 Segmentation fault occured if my.cnf is invalid for escape sequence -# +--echo # +--echo # Bug #15328 Segmentation fault occured if my.cnf is invalid for escape sequence +--echo # --exec $MYSQL_MY_PRINT_DEFAULTS --config-file=$MYSQL_TEST_DIR/std_data/bug15328.cnf mysqldump - -# -# Bug #9558 mysqldump --no-data db t1 t2 format still dumps data -# +--echo # +--echo # Bug #9558 mysqldump --no-data db t1 t2 format still dumps data +--echo # CREATE DATABASE mysqldump_test_db; USE mysqldump_test_db; @@ -630,11 +629,11 @@ INSERT INTO t2 VALUES (1), (2); DROP TABLE t1, t2; DROP DATABASE mysqldump_test_db; -# -# Testing with tables and databases that don't exists -# or contains illegal characters -# (Bug #9358 mysqldump crashes if tablename starts with \) -# +--echo # +--echo # Testing with tables and databases that don't exists +--echo # or contains illegal characters +--echo # (Bug #9358 mysqldump crashes if tablename starts with \) +--echo # create database mysqldump_test_db; use mysqldump_test_db; create table t1(a varchar(30) primary key, b int not null); @@ -694,9 +693,9 @@ drop database mysqldump_test_db; use test; -# -# Bug #9657 mysqldump xml ( -x ) does not format NULL fields correctly -# +--echo # +--echo # Bug #9657 mysqldump xml ( -x ) does not format NULL fields correctly +--echo # create table t1 (a int(10)); create table t2 (pk int primary key auto_increment, @@ -706,9 +705,9 @@ insert into t2 (a, b) values (NULL, NULL),(10, NULL),(NULL, "twenty"),(30, "thir --exec $MYSQL_DUMP --skip-comments --xml --no-create-info test drop table t1, t2; -# -# BUG #12123 -# +--echo # +--echo # Bug #12123 +--echo # create table t1 (a text character set utf8, b text character set latin1); insert t1 values (0x4F736E616272C3BC636B, 0x4BF66C6E); select * from t1; @@ -719,9 +718,9 @@ select * from t1; drop table t1; -# -# BUG #19025 mysqldump doesn't correctly dump "auto_increment = [int]" -# +--echo # +--echo # Bug #19025 mysqldump doesn't correctly dump "auto_increment = [int]" +--echo # create table `t1` ( t1_name varchar(255) default null, t1_id int(10) unsigned not null auto_increment, @@ -748,20 +747,23 @@ show create table `t1`; drop table `t1`; ---echo End of 4.1 tests +--echo # +--echo # End of 4.1 tests +--echo # + +--echo # +--echo # Dump of view +--echo # -# -# dump of view -# create table t1(a int); create view v1 as select * from t1; --exec $MYSQL_DUMP --skip-comments test drop view v1; drop table t1; -# -# Bug #10213 mysqldump crashes when dumping VIEWs(on MacOS X) -# +--echo # +--echo # Bug #10213 mysqldump crashes when dumping VIEWs(on MacOS X) +--echo # create database mysqldump_test_db; use mysqldump_test_db; @@ -783,18 +785,18 @@ drop view v2; drop database mysqldump_test_db; use test; -# -# Bug #9756 -# +--echo # +--echo # Bug #9756 +--echo # CREATE TABLE t1 (a char(10)); INSERT INTO t1 VALUES ('\''); --exec $MYSQL_DUMP --skip-comments test t1 DROP TABLE t1; -# -# Bug #10927 mysqldump: Can't reload dump with view that consist of other view -# +--echo # +--echo # Bug #10927 mysqldump: Can't reload dump with view that consist of other view +--echo # create table t1(a int, b int, c varchar(30)); @@ -813,9 +815,10 @@ select v3.a from v3, v1 where v1.a=v3.a and v3.b=3 limit 1; drop view v1, v2, v3; drop table t1; -# -# Test for dumping triggers -# + +--echo # +--echo # Test for dumping triggers +--echo # CREATE TABLE t1 (a int, b bigint default NULL); CREATE TABLE t2 (a int); @@ -863,9 +866,9 @@ show tables; show triggers; DROP TABLE t1, t2; -# -# Bugs #9136, #12917: problems with --defaults-extra-file option -# +--echo # +--echo # Bugs #9136, #12917: problems with --defaults-extra-file option +--echo # --system echo '[mysqltest1]' > $MYSQLTEST_VARDIR/tmp/tmp.cnf --system echo 'port=1234' >> $MYSQLTEST_VARDIR/tmp/tmp.cnf @@ -873,9 +876,9 @@ DROP TABLE t1, t2; --exec $MYSQL_MY_PRINT_DEFAULTS -e $MYSQLTEST_VARDIR/tmp/tmp.cnf mysqltest1 mysqltest1 --system rm $MYSQLTEST_VARDIR/tmp/tmp.cnf -# -# Test of fix to BUG 12597 -# +--echo # +--echo # Bug #12597 +--echo # DROP TABLE IF EXISTS `test1`; CREATE TABLE `test1` ( @@ -911,9 +914,9 @@ DROP TRIGGER testref; DROP TABLE test1; DROP TABLE test2; -# -# BUG#9056 - mysqldump does not dump routines -# +--echo # +--echo # Bug #9056 - mysqldump does not dump routines +--echo # --disable_warnings DROP TABLE IF EXISTS t1; @@ -960,9 +963,9 @@ DROP PROCEDURE bug9056_proc2; DROP PROCEDURE `a'b`; drop table t1; -# -# BUG# 13052 - mysqldump timestamp reloads broken -# +--echo # +--echo # Bug #13052 - mysqldump timestamp reloads broken +--echo # --disable_warnings drop table if exists t1; --enable_warnings @@ -982,9 +985,9 @@ drop table t1; set global time_zone=default; set time_zone=default; -# -# Test of fix to BUG 13146 - ansi quotes break loading of triggers -# +--echo # +--echo # Bug #13146 - ansi quotes break loading of triggers +--echo # --disable_warnings DROP TABLE IF EXISTS `t1 test`; DROP TABLE IF EXISTS `t2 test`; @@ -1015,9 +1018,9 @@ DROP TRIGGER `test trig`; DROP TABLE `t1 test`; DROP TABLE `t2 test`; -# -# BUG# 12838 mysqldump -x with views exits with error -# +--echo # +--echo # Bug #12838 mysqldump -x with views exits with error +--echo # --disable_warnings drop table if exists t1; @@ -1039,10 +1042,10 @@ drop view v0; drop view v1; drop table t1; -# -# BUG#14554 - mysqldump does not separate words "ROW" and "BEGIN" -# for tables with trigger created in the IGNORE_SPACE sql mode. -# +--echo # +--echo # Bug #14554 - mysqldump does not separate words "ROW" and "BEGIN" +--echo # for tables with trigger created in the IGNORE_SPACE sql mode. +--echo # SET @old_sql_mode = @@SQL_MODE; SET SQL_MODE = IGNORE_SPACE; @@ -1063,18 +1066,18 @@ SET SQL_MODE = @old_sql_mode; DROP TRIGGER tr1; DROP TABLE t1; -# -# Bug #13318: Bad result with empty field and --hex-blob -# +--echo # +--echo # Bug #13318: Bad result with empty field and --hex-blob +--echo # create table t1 (a binary(1), b blob); insert into t1 values ('',''); --exec $MYSQL_DUMP --skip-comments --skip-extended-insert --hex-blob test t1 --exec $MYSQL_DUMP --skip-comments --hex-blob test t1 drop table t1; -# -# Bug #18536: wrong table order -# +--echo # +--echo # Bug #18536: wrong table order +--echo # create table t1(a int); create table t2(a int); @@ -1085,9 +1088,9 @@ drop table t1, t2, t3; --echo End of 4.1 tests -# -# Bug 14871 Invalid view dump output -# +--echo # +--echo # Bug #14871 Invalid view dump output +--echo # create table t1 (a int); insert into t1 values (289), (298), (234), (456), (789); @@ -1114,9 +1117,9 @@ select * from v3 order by a; drop table t1; drop view v1, v2, v3, v4, v5; -# -# Bug #16878 dump of trigger -# +--echo # +--echo # Bug #16878 dump of trigger +--echo # create table t1 (a int, created datetime); create table t2 (b int, created datetime); @@ -1145,10 +1148,9 @@ drop trigger tr2; drop table t1, t2; -# -# Bug#18462 mysqldump does not dump view structures correctly -# -# +--echo # +--echo # Bug #18462 mysqldump does not dump view structures correctly +--echo # create table t (qty int, price int); insert into t values(3, 50); insert into t values(5, 51); @@ -1165,11 +1167,10 @@ drop view v2; drop table t; -# -# Bug#14857 Reading dump files with single statement stored routines fails. -# fixed by patch for bug#16878 -# -# +--echo # +--echo # Bug #14857 Reading dump files with single statement stored routines fails. +--echo # fixed by patch for Bug #16878 +--echo # DELIMITER |; /*!50003 CREATE FUNCTION `f`() RETURNS bigint(20) return 42 */| @@ -1181,10 +1182,10 @@ show create procedure p; drop function f; drop procedure p; -# -# Bug #17371 Unable to dump a schema with invalid views -# -# +--echo # +--echo # Bug #17371 Unable to dump a schema with invalid views +--echo # + create table t1 ( id serial ); create view v1 as select * from t1; drop table t1; @@ -1195,10 +1196,11 @@ drop table t1; --echo } mysqldump drop view v1; -# BUG#17201 Spurious 'DROP DATABASE' in output, -# also confusion between tables and views. -# Example code from Markus Popp - +--echo # +--echo # Bug #17201 Spurious 'DROP DATABASE' in output, +--echo # also confusion between tables and views. +--echo # Example code from Markus Popp +--echo # create database mysqldump_test_db; use mysqldump_test_db; create table t1 (id int); @@ -1212,8 +1214,9 @@ drop view v1; drop table t1; drop database mysqldump_test_db; -# Bug21014 Segmentation fault of mysqldump on view - +--echo # +--echo # Bug21014 Segmentation fault of mysqldump on view +--echo # create database mysqldump_tables; use mysqldump_tables; create table basetable ( id serial, tag varchar(64) ); @@ -1229,8 +1232,9 @@ drop database mysqldump_views; drop table mysqldump_tables.basetable; drop database mysqldump_tables; -# Bug20221 Dumping of multiple databases containing view(s) yields maleformed dumps - +--echo # +--echo # Bug20221 Dumping of multiple databases containing view(s) yields maleformed dumps +--echo # create database mysqldump_dba; use mysqldump_dba; create table t1 (f1 int, f2 int); @@ -1267,9 +1271,9 @@ drop view v1; drop table t1; drop database mysqldump_dbb; -# -# Bug#21215 mysqldump creating incomplete backups without warning -# +--echo # +--echo # Bug #21215 mysqldump creating incomplete backups without warning +--echo # use test; # Create user without sufficient privs to perform the requested operation @@ -1310,17 +1314,10 @@ grant REPLICATION CLIENT on *.* to mysqltest_1@localhost; drop table t1; drop user mysqltest_1@localhost; ---exec $MYSQL_DUMP --skip-comments --databases mysqldump_tables mysqldump_views; +--echo # +--echo # Bug #13926: --order-by-primary fails if PKEY contains quote character +--echo # -drop view nasishnasifu; -drop database mysqldump_views; -drop table mysqldump_tables.basetable; -drop database mysqldump_tables; -USE test; - -# -# BUG#13926: --order-by-primary fails if PKEY contains quote character -# --disable_warnings DROP TABLE IF EXISTS `t1`; CREATE TABLE `t1` ( @@ -1335,5 +1332,8 @@ insert into t1 values (0815, 4711, 2006); --exec $MYSQL_DUMP --skip-comments --order-by-primary test t1 DROP TABLE `t1`; --enable_warnings ---echo End of 5.0 tests + +--echo # +--echo # End of 5.0 tests +--echo # From d3d3cef88c03025e69f9e3c91a0f72efb0314dc7 Mon Sep 17 00:00:00 2001 From: "igor@rurik.mysql.com" <> Date: Sat, 16 Sep 2006 09:50:48 -0700 Subject: [PATCH 29/39] Fixed bug #21493: crash for the second execution of a function containing a select statement that uses an aggregating IN subquery. Added a parameter to the function fix_prepare_information to restore correctly the having clause for the second execution. Saved andor structure of the having conditions at the proper moment before any calls of split_sum_func2 that could modify the having structure adding new Item_ref objects. (These additions, are produced not with the statement mem_root, but rather with the execution mem_root.) --- mysql-test/r/sp.result | 63 +++++++++++++++++++++++++++++++++++++++ mysql-test/t/sp.test | 67 ++++++++++++++++++++++++++++++++++++++++++ sql/sql_delete.cc | 3 +- sql/sql_insert.cc | 2 +- sql/sql_lex.cc | 23 ++++++++++++--- sql/sql_lex.h | 2 +- sql/sql_select.cc | 6 ++-- sql/sql_update.cc | 3 +- 8 files changed, 158 insertions(+), 11 deletions(-) diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 88a860d6c8a..24de88a4457 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -5256,4 +5256,67 @@ a 1 use test| drop table t3| +CREATE TABLE t3 ( +Member_ID varchar(15) NOT NULL, +PRIMARY KEY (Member_ID) +)| +CREATE TABLE t4 ( +ID int(10) unsigned NOT NULL auto_increment, +Member_ID varchar(15) NOT NULL default '', +Action varchar(12) NOT NULL, +Action_Date datetime NOT NULL, +Track varchar(15) default NULL, +User varchar(12) default NULL, +Date_Updated timestamp NOT NULL default CURRENT_TIMESTAMP on update +CURRENT_TIMESTAMP, +PRIMARY KEY (ID), +KEY Action (Action), +KEY Action_Date (Action_Date) +)| +INSERT INTO t3(Member_ID) VALUES +('111111'), ('222222'), ('333333'), ('444444'), ('555555'), ('666666')| +INSERT INTO t4(Member_ID, Action, Action_Date, Track) VALUES +('111111', 'Disenrolled', '2006-03-01', 'CAD' ), +('111111', 'Enrolled', '2006-03-01', 'CAD' ), +('111111', 'Disenrolled', '2006-07-03', 'CAD' ), +('222222', 'Enrolled', '2006-03-07', 'CAD' ), +('222222', 'Enrolled', '2006-03-07', 'CHF' ), +('222222', 'Disenrolled', '2006-08-02', 'CHF' ), +('333333', 'Enrolled', '2006-03-01', 'CAD' ), +('333333', 'Disenrolled', '2006-03-01', 'CAD' ), +('444444', 'Enrolled', '2006-03-01', 'CAD' ), +('555555', 'Disenrolled', '2006-03-01', 'CAD' ), +('555555', 'Enrolled', '2006-07-21', 'CAD' ), +('555555', 'Disenrolled', '2006-03-01', 'CHF' ), +('666666', 'Enrolled', '2006-02-09', 'CAD' ), +('666666', 'Enrolled', '2006-05-12', 'CHF' ), +('666666', 'Disenrolled', '2006-06-01', 'CAD' )| +DROP FUNCTION IF EXISTS bug21493| +Warnings: +Note 1305 FUNCTION bug21493 does not exist +CREATE FUNCTION bug21493(paramMember VARCHAR(15)) RETURNS varchar(45) +BEGIN +DECLARE tracks VARCHAR(45); +SELECT GROUP_CONCAT(Track SEPARATOR ', ') INTO tracks FROM t4 +WHERE Member_ID=paramMember AND Action='Enrolled' AND +(Track,Action_Date) IN (SELECT Track, MAX(Action_Date) FROM t4 +WHERE Member_ID=paramMember GROUP BY Track); +RETURN tracks; +END| +SELECT bug21493('111111')| +bug21493('111111') +NULL +SELECT bug21493('222222')| +bug21493('222222') +CAD +SELECT bug21493(Member_ID) FROM t3| +bug21493(Member_ID) +NULL +CAD +CAD +CAD +CAD +CHF +DROP FUNCTION bug21493| +DROP TABLE t3,t4| drop table t1,t2; diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index ba30699b1d0..98ae46c5b14 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -6188,6 +6188,73 @@ select * from (select 1 as a) as t1 natural join (select * from test.t3) as t2| use test| drop table t3| +# +# BUG#21493: Crash on the second call of a procedure containing +# a select statement that uses an IN aggregating subquery +# + +CREATE TABLE t3 ( + Member_ID varchar(15) NOT NULL, + PRIMARY KEY (Member_ID) +)| + +CREATE TABLE t4 ( + ID int(10) unsigned NOT NULL auto_increment, + Member_ID varchar(15) NOT NULL default '', + Action varchar(12) NOT NULL, + Action_Date datetime NOT NULL, + Track varchar(15) default NULL, + User varchar(12) default NULL, + Date_Updated timestamp NOT NULL default CURRENT_TIMESTAMP on update + CURRENT_TIMESTAMP, + PRIMARY KEY (ID), + KEY Action (Action), + KEY Action_Date (Action_Date) +)| + + +INSERT INTO t3(Member_ID) VALUES + ('111111'), ('222222'), ('333333'), ('444444'), ('555555'), ('666666')| + +INSERT INTO t4(Member_ID, Action, Action_Date, Track) VALUES + ('111111', 'Disenrolled', '2006-03-01', 'CAD' ), + ('111111', 'Enrolled', '2006-03-01', 'CAD' ), + ('111111', 'Disenrolled', '2006-07-03', 'CAD' ), + ('222222', 'Enrolled', '2006-03-07', 'CAD' ), + ('222222', 'Enrolled', '2006-03-07', 'CHF' ), + ('222222', 'Disenrolled', '2006-08-02', 'CHF' ), + ('333333', 'Enrolled', '2006-03-01', 'CAD' ), + ('333333', 'Disenrolled', '2006-03-01', 'CAD' ), + ('444444', 'Enrolled', '2006-03-01', 'CAD' ), + ('555555', 'Disenrolled', '2006-03-01', 'CAD' ), + ('555555', 'Enrolled', '2006-07-21', 'CAD' ), + ('555555', 'Disenrolled', '2006-03-01', 'CHF' ), + ('666666', 'Enrolled', '2006-02-09', 'CAD' ), + ('666666', 'Enrolled', '2006-05-12', 'CHF' ), + ('666666', 'Disenrolled', '2006-06-01', 'CAD' )| + +#--disable_warnings +DROP FUNCTION IF EXISTS bug21493| +#--enable_warnings + +CREATE FUNCTION bug21493(paramMember VARCHAR(15)) RETURNS varchar(45) +BEGIN +DECLARE tracks VARCHAR(45); +SELECT GROUP_CONCAT(Track SEPARATOR ', ') INTO tracks FROM t4 + WHERE Member_ID=paramMember AND Action='Enrolled' AND + (Track,Action_Date) IN (SELECT Track, MAX(Action_Date) FROM t4 + WHERE Member_ID=paramMember GROUP BY Track); +RETURN tracks; +END| + +SELECT bug21493('111111')| +SELECT bug21493('222222')| + +SELECT bug21493(Member_ID) FROM t3| + +DROP FUNCTION bug21493| +DROP TABLE t3,t4| + # # BUG#NNNN: New bug synopsis # diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index e420022b8a1..c95fb5d5973 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -342,6 +342,7 @@ cleanup: */ bool mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds) { + Item *fake_conds= 0; SELECT_LEX *select_lex= &thd->lex->select_lex; DBUG_ENTER("mysql_prepare_delete"); @@ -367,7 +368,7 @@ bool mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds) DBUG_RETURN(TRUE); } } - select_lex->fix_prepare_information(thd, conds); + select_lex->fix_prepare_information(thd, conds, &fake_conds); DBUG_RETURN(FALSE); } diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index c08deedea72..999584c368c 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -993,7 +993,7 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, update_non_unique_table_error(table_list, "INSERT", duplicate); DBUG_RETURN(TRUE); } - select_lex->fix_prepare_information(thd, &fake_conds); + select_lex->fix_prepare_information(thd, &fake_conds, &fake_conds); select_lex->first_execution= 0; } if (duplic == DUP_UPDATE || duplic == DUP_REPLACE) diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 035c575724e..74ac8954a66 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -2155,15 +2155,25 @@ static void fix_prepare_info_in_table_list(THD *thd, TABLE_LIST *tbl) /* - fix some structures at the end of preparation + Save WHERE/HAVING/ON clauses and replace them with disposable copies SYNOPSIS st_select_lex::fix_prepare_information - thd thread handler - conds pointer on conditions which will be used for execution statement + thd thread handler + conds in/out pointer to WHERE condition to be met at execution + having_conds in/out pointer to HAVING condition to be met at execution + + DESCRIPTION + The passed WHERE and HAVING are to be saved for the future executions. + This function saves it, and returns a copy which can be thrashed during + this execution of the statement. By saving/thrashing here we mean only + AND/OR trees. + The function also calls fix_prepare_info_in_table_list that saves all + ON expressions. */ -void st_select_lex::fix_prepare_information(THD *thd, Item **conds) +void st_select_lex::fix_prepare_information(THD *thd, Item **conds, + Item **having_conds) { if (!thd->stmt_arena->is_conventional() && first_execution) { @@ -2173,6 +2183,11 @@ void st_select_lex::fix_prepare_information(THD *thd, Item **conds) prep_where= *conds; *conds= where= prep_where->copy_andor_structure(thd); } + if (*having_conds) + { + prep_having= *having_conds; + *having_conds= having= prep_having->copy_andor_structure(thd); + } fix_prepare_info_in_table_list(thd, (TABLE_LIST *)table_list.first); } } diff --git a/sql/sql_lex.h b/sql/sql_lex.h index fe6d60a218d..efee1973d69 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -656,7 +656,7 @@ public: void print(THD *thd, String *str); static void print_order(String *str, ORDER *order); void print_limit(THD *thd, String *str); - void fix_prepare_information(THD *thd, Item **conds); + void fix_prepare_information(THD *thd, Item **conds, Item **having_conds); /* Destroy the used execution plan (JOIN) of this subtree (this SELECT_LEX and all nested SELECT_LEXes and SELECT_LEX_UNITs). diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 93d923f0669..f4b6bb5c978 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -382,12 +382,14 @@ JOIN::prepare(Item ***rref_pointer_array, if ((res= subselect->select_transformer(this)) != Item_subselect::RES_OK) { - select_lex->fix_prepare_information(thd, &conds); + select_lex->fix_prepare_information(thd, &conds, &having); DBUG_RETURN((res == Item_subselect::RES_ERROR)); } } } + select_lex->fix_prepare_information(thd, &conds, &having); + if (having && having->with_sum_func) having->split_sum_func2(thd, ref_pointer_array, all_fields, &having, TRUE); @@ -499,7 +501,6 @@ JOIN::prepare(Item ***rref_pointer_array, if (alloc_func_list()) goto err; - select_lex->fix_prepare_information(thd, &conds); DBUG_RETURN(0); // All OK err: @@ -618,7 +619,6 @@ JOIN::optimize() build_bitmap_for_nested_joins(join_list, 0); sel->prep_where= conds ? conds->copy_andor_structure(thd) : 0; - sel->prep_having= having ? having->copy_andor_structure(thd) : 0; if (arena) thd->restore_active_arena(arena, &backup); diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 84b22c56cf9..a5a767b6ebc 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -606,6 +606,7 @@ err: bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list, Item **conds, uint order_num, ORDER *order) { + Item *fake_conds= 0; TABLE *table= table_list->table; TABLE_LIST tables; List all_fields; @@ -645,7 +646,7 @@ bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list, DBUG_RETURN(TRUE); } } - select_lex->fix_prepare_information(thd, conds); + select_lex->fix_prepare_information(thd, conds, &fake_conds); DBUG_RETURN(FALSE); } From e2d15b16d2fa9cd66c6360ce50a6b6f99812db65 Mon Sep 17 00:00:00 2001 From: "aivanov/alexi@mysql.com/mysqld.localdomain" <> Date: Mon, 18 Sep 2006 03:21:00 +0400 Subject: [PATCH 30/39] BUG#19419: VIEW: View that the column name is different by master and slave is made. --- mysql-test/r/rpl_view.result | 15 +++++++++++++++ mysql-test/t/rpl_view.test | 20 ++++++++++++++++++++ sql/sql_parse.cc | 13 +++++++++++++ 3 files changed, 48 insertions(+) diff --git a/mysql-test/r/rpl_view.result b/mysql-test/r/rpl_view.result index 5a101defe38..51a8e3193aa 100644 --- a/mysql-test/r/rpl_view.result +++ b/mysql-test/r/rpl_view.result @@ -91,3 +91,18 @@ c ---> Cleaning up... DROP VIEW v1; DROP TABLE t1; +create table t1(a int, b int); +insert into t1 values (1, 1), (1, 2), (1, 3); +create view v1(a, b) as select a, sum(b) from t1 group by a; +explain v1; +Field Type Null Key Default Extra +a int(11) YES NULL +b decimal(32,0) YES NULL +show create table v1; +View Create View +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`a` AS `a`,sum(`t1`.`b`) AS `b` from `t1` group by `t1`.`a` +select * from v1; +a b +1 6 +drop table t1; +drop view v1; diff --git a/mysql-test/t/rpl_view.test b/mysql-test/t/rpl_view.test index d0990b4fbee..52db75aaf69 100644 --- a/mysql-test/t/rpl_view.test +++ b/mysql-test/t/rpl_view.test @@ -129,3 +129,23 @@ DROP TABLE t1; --sync_with_master --connection master +# +# BUG#19419: "VIEW: View that the column name is different +# by master and slave is made". +# +connection master; +create table t1(a int, b int); +insert into t1 values (1, 1), (1, 2), (1, 3); +create view v1(a, b) as select a, sum(b) from t1 group by a; + +sync_slave_with_master; +explain v1; +show create table v1; +select * from v1; + +connection master; +drop table t1; +drop view v1; + +sync_slave_with_master; + diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 905e8cdc71a..4f6bda5175f 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -4765,6 +4765,19 @@ end_with_restore_list: } append_identifier(thd, &buff, first_table->table_name, first_table->table_name_length); + if (lex->view_list.elements) + { + List_iterator_fast names(lex->view_list); + LEX_STRING *name; + int i; + + for (i= 0; name= names++; i++) + { + buff.append(i ? ", " : "("); + append_identifier(thd, &buff, name->str, name->length); + } + buff.append(')'); + } buff.append(STRING_WITH_LEN(" AS ")); buff.append(first_table->source.str, first_table->source.length); From fae596aafd67aa5413f64405b85241e78e12ec87 Mon Sep 17 00:00:00 2001 From: "gkodinov@dl145s.mysql.com" <> Date: Mon, 18 Sep 2006 12:14:27 +0200 Subject: [PATCH 31/39] merge fixes --- mysql-test/r/func_time.result | 7 +++---- mysql-test/r/query_cache.result | 12 ++++++------ mysql-test/r/subselect.result | 4 ++-- mysql-test/r/view.result | 4 ++-- mysql-test/t/func_time.test | 2 +- mysql-test/t/view.test | 4 ++-- sql/item_cmpfunc.cc | 4 +++- sql/opt_range.cc | 15 --------------- sql/opt_range.h | 2 +- 9 files changed, 20 insertions(+), 34 deletions(-) diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result index e0e0eb68aa1..9fea857e4e5 100644 --- a/mysql-test/r/func_time.result +++ b/mysql-test/r/func_time.result @@ -867,12 +867,11 @@ f1 select f1 from t1 where cast("2006-1-1" as date) between date(f1) and date(f3); f1 2006-01-01 -select f1 from t1 where cast("2006-1-1" as date) between f1 and 'zzz'; +select f1 from t1 where cast("2006-1-1" as date) between f1 and cast('zzz' as date); f1 Warnings: -Warning 1292 Incorrect date value: 'zzz' for column 'f1' at row 1 -Warning 1292 Truncated incorrect DOUBLE value: 'zzz' -Warning 1292 Truncated incorrect DOUBLE value: 'zzz' +Warning 1292 Truncated incorrect datetime value: 'zzz' +Warning 1292 Truncated incorrect datetime value: 'zzz' select f1 from t1 where makedate(2006,1) between date(f1) and date(f3); f1 2006-01-01 diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result index a735b52a26f..5224280e134 100644 --- a/mysql-test/r/query_cache.result +++ b/mysql-test/r/query_cache.result @@ -947,24 +947,24 @@ COUNT(*) Warnings: Warning 1292 Incorrect datetime value: '20050327 invalid' for column 'date' at row 1 Warning 1292 Incorrect datetime value: '20050327 invalid' for column 'date' at row 1 -Warning 1292 Truncated incorrect DOUBLE value: '20050327 invalid' -Warning 1292 Truncated incorrect DOUBLE value: '20050327 invalid' +Warning 1292 Truncated incorrect INTEGER value: '20050327 invalid' +Warning 1292 Truncated incorrect INTEGER value: '20050327 invalid' SELECT COUNT(*) FROM t1 WHERE date BETWEEN '20050326' AND '20050328 invalid'; COUNT(*) 0 Warnings: Warning 1292 Incorrect datetime value: '20050328 invalid' for column 'date' at row 1 Warning 1292 Incorrect datetime value: '20050328 invalid' for column 'date' at row 1 -Warning 1292 Truncated incorrect DOUBLE value: '20050328 invalid' -Warning 1292 Truncated incorrect DOUBLE value: '20050328 invalid' +Warning 1292 Truncated incorrect INTEGER value: '20050328 invalid' +Warning 1292 Truncated incorrect INTEGER value: '20050328 invalid' SELECT COUNT(*) FROM t1 WHERE date BETWEEN '20050326' AND '20050327 invalid'; COUNT(*) 0 Warnings: Warning 1292 Incorrect datetime value: '20050327 invalid' for column 'date' at row 1 Warning 1292 Incorrect datetime value: '20050327 invalid' for column 'date' at row 1 -Warning 1292 Truncated incorrect DOUBLE value: '20050327 invalid' -Warning 1292 Truncated incorrect DOUBLE value: '20050327 invalid' +Warning 1292 Truncated incorrect INTEGER value: '20050327 invalid' +Warning 1292 Truncated incorrect INTEGER value: '20050327 invalid' show status like "Qcache_queries_in_cache"; Variable_name Value Qcache_queries_in_cache 0 diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 3fdf0a6d8ff..c6a31856a24 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -2947,7 +2947,7 @@ ORDER BY t2.c DESC, t2.b DESC LIMIT 1) WHERE t1.a = 10; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 system PRIMARY NULL NULL NULL 1 1 PRIMARY r const PRIMARY PRIMARY 4 const 1 -2 DEPENDENT SUBQUERY t2 range b b 38 NULL 2 Using where +2 DEPENDENT SUBQUERY t2 range b b 40 NULL 2 Using where SELECT sql_no_cache t1.a, r.a, r.b FROM t1 LEFT JOIN t2 r ON r.a = (SELECT t2.a FROM t2 WHERE t2.c = t1.a AND t2.b <= '359899' ORDER BY t2.c DESC, t2.b DESC LIMIT 1) WHERE t1.a = 10; @@ -2959,7 +2959,7 @@ ORDER BY t2.c, t2.b LIMIT 1) WHERE t1.a = 10; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 system PRIMARY NULL NULL NULL 1 1 PRIMARY r const PRIMARY PRIMARY 4 const 1 -2 DEPENDENT SUBQUERY t2 range b b 38 NULL 2 Using where +2 DEPENDENT SUBQUERY t2 range b b 40 NULL 2 Using where SELECT sql_no_cache t1.a, r.a, r.b FROM t1 LEFT JOIN t2 r ON r.a = (SELECT t2.a FROM t2 WHERE t2.c = t1.a AND t2.b <= '359899' ORDER BY t2.c, t2.b LIMIT 1) WHERE t1.a = 10; diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 72e84884b2e..9c05aba168c 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -2586,13 +2586,13 @@ INSERT INTO t1 VALUES (4, '2005-01-03'), (5, '2005-01-04'), (6, '2005-01-05'), (7, '2005-01-05'), (8, '2005-01-05'), (9, '2005-01-06'); CREATE VIEW v1 AS SELECT * FROM t1; -SELECT * FROM t1 WHERE td BETWEEN '2005.01.02' AND '2005.01.04'; +SELECT * FROM t1 WHERE td BETWEEN CAST('2005.01.02' AS DATE) AND CAST('2005.01.04' AS DATE); id td 2 2005-01-02 3 2005-01-02 4 2005-01-03 5 2005-01-04 -SELECT * FROM v1 WHERE td BETWEEN '2005.01.02' AND '2005.01.04'; +SELECT * FROM v1 WHERE td BETWEEN CAST('2005.01.02' AS DATE) AND CAST('2005.01.04' AS DATE); id td 2 2005-01-02 3 2005-01-02 diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test index fe34480d5d3..7303be31e03 100644 --- a/mysql-test/t/func_time.test +++ b/mysql-test/t/func_time.test @@ -432,7 +432,7 @@ select f3 from t1 where f3 between cast("2006-1-1 12:1:1" as datetime) and cast( select f3 from t1 where timestamp(f3) between cast("2006-1-1 12:1:1" as datetime) and cast("2006-1-1 12:1:2" as datetime); select f1 from t1 where cast("2006-1-1" as date) between f1 and f3; select f1 from t1 where cast("2006-1-1" as date) between date(f1) and date(f3); -select f1 from t1 where cast("2006-1-1" as date) between f1 and 'zzz'; +select f1 from t1 where cast("2006-1-1" as date) between f1 and cast('zzz' as date); select f1 from t1 where makedate(2006,1) between date(f1) and date(f3); select f1 from t1 where makedate(2006,2) between date(f1) and date(f3); drop table t1; diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index e299b86c4e6..4745804e847 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -2449,8 +2449,8 @@ INSERT INTO t1 VALUES CREATE VIEW v1 AS SELECT * FROM t1; -SELECT * FROM t1 WHERE td BETWEEN '2005.01.02' AND '2005.01.04'; -SELECT * FROM v1 WHERE td BETWEEN '2005.01.02' AND '2005.01.04'; +SELECT * FROM t1 WHERE td BETWEEN CAST('2005.01.02' AS DATE) AND CAST('2005.01.04' AS DATE); +SELECT * FROM v1 WHERE td BETWEEN CAST('2005.01.02' AS DATE) AND CAST('2005.01.04' AS DATE); DROP VIEW v1; DROP TABLE t1; diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 122f755d5c1..780d70d51dc 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -1112,7 +1112,9 @@ void Item_func_between::fix_length_and_dec() They are compared as integers, so for const item this time-consuming conversion can be done only once, not for every single comparison */ - if (args[0]->type() == FIELD_ITEM) + if (args[0]->type() == FIELD_ITEM && + thd->lex->sql_command != SQLCOM_CREATE_VIEW && + thd->lex->sql_command != SQLCOM_SHOW_CREATE) { Field *field=((Item_field*) args[0])->field; if (field->can_be_compared_as_longlong()) diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 1ed74c6de2e..93566dbc281 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -6724,15 +6724,6 @@ int QUICK_RANGE_SELECT::get_next() } } -void QUICK_SELECT::reset(void) -{ - next= 0; - it.rewind(); - range= 0; - if (file->inited == handler::NONE) - file->ha_index_init(index); -} - /* Get the next record with a different prefix. @@ -9386,12 +9377,6 @@ static void print_ror_scans_arr(TABLE *table, const char *msg, DBUG_VOID_RETURN; } -void QUICK_SELECT_DESC::reset(void) -{ - rev_it.rewind(); - QUICK_SELECT::reset(); -} - /***************************************************************************** ** Print a quick range for debugging ** TODO: diff --git a/sql/opt_range.h b/sql/opt_range.h index c1f1b63d468..9474f2d469f 100644 --- a/sql/opt_range.h +++ b/sql/opt_range.h @@ -668,7 +668,7 @@ private: #ifdef NOT_USED bool test_if_null_range(QUICK_RANGE *range, uint used_key_parts); #endif - void reset(void); + int reset(void) { rev_it.rewind(); return QUICK_RANGE_SELECT::reset(); } List rev_ranges; List_iterator rev_it; }; From 7419f50245c8f8604f544d42af2a526f2b42d2cc Mon Sep 17 00:00:00 2001 From: "istruewing@chilla.local" <> Date: Tue, 19 Sep 2006 14:26:18 +0200 Subject: [PATCH 32/39] After merge fix. --- sql/sql_select.cc | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 86c48ecbdd1..79ce8556e51 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -13231,14 +13231,15 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param, tmp= (char*) sql_alloc(field->pack_length()+2); if (!tmp) goto err; - if (copy) - { - copy->set(tmp, item->result_field); - item->result_field->move_field(copy->to_ptr,copy->to_null_ptr,1); + if (copy) + { + copy->set(tmp, item->result_field); + item->result_field->move_field(copy->to_ptr,copy->to_null_ptr,1); #ifdef HAVE_purify - copy->to_ptr[copy->from_length]= 0; + copy->to_ptr[copy->from_length]= 0; #endif - copy++; + copy++; + } } } else if ((real_pos->type() == Item::FUNC_ITEM || From 6aded456144f2f425fd550f730981262215299e1 Mon Sep 17 00:00:00 2001 From: "lars/lthalmann@mysql.com/dl145h.mysql.com" <> Date: Thu, 21 Sep 2006 00:59:48 +0200 Subject: [PATCH 33/39] Fix of result files from merge --- mysql-test/r/mysqldump.result | 242 +++++++++++++++++++++++++++++++++- mysql-test/r/rpl_view.result | 1 + mysql-test/t/rpl_view.test | 1 + 3 files changed, 243 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result index 3172a32de76..ee50fc42203 100644 --- a/mysql-test/r/mysqldump.result +++ b/mysql-test/r/mysqldump.result @@ -22,6 +22,9 @@ INSERT INTO t1 VALUES (1), (2); DROP TABLE t1; +# +# Bug #2005 +# CREATE TABLE t1 (a decimal(64, 20)); INSERT INTO t1 VALUES ("1234567890123456789012345678901234567890"), ("0987654321098765432109876543210987654321"); @@ -30,6 +33,9 @@ CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1; INSERT INTO `t1` VALUES ('1234567890123456789012345678901234567890.00000000000000000000'),('987654321098765432109876543210987654321.00000000000000000000'); DROP TABLE t1; +# +# Bug #2055 +# CREATE TABLE t1 (a double); INSERT INTO t1 VALUES ('-9e999999'); Warnings: @@ -39,6 +45,9 @@ CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1; INSERT INTO `t1` VALUES (RES); DROP TABLE t1; +# +# Bug #3361 mysqldump quotes DECIMAL values inconsistently +# CREATE TABLE t1 (a DECIMAL(10,5), b FLOAT); INSERT INTO t1 VALUES (1.2345, 2.3456); INSERT INTO t1 VALUES ('1.2345', 2.3456); @@ -136,6 +145,9 @@ INSERT INTO t1 VALUES (1, "test", "tes"), (2, "TEST", "TES"); DROP TABLE t1; +# +# Bug #1707 +# CREATE TABLE t1 (`a"b"` char(2)); INSERT INTO t1 VALUES ("1\""), ("\"2"); @@ -155,6 +167,10 @@ INSERT INTO t1 VALUES ("1\""), ("\"2"); DROP TABLE t1; +# +# Bug #1994 +# Bug #4261 +# CREATE TABLE t1 (a VARCHAR(255)) DEFAULT CHARSET koi8r; INSERT INTO t1 VALUES (_koi8r x'C1C2C3C4C5'), (NULL); @@ -190,6 +206,9 @@ UNLOCK TABLES; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; DROP TABLE t1; +# +# Bug #2634 +# CREATE TABLE t1 (a int) ENGINE=MYISAM; INSERT INTO t1 VALUES (1), (2); /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; @@ -239,11 +258,17 @@ UNLOCK TABLES; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; DROP TABLE t1; +# +# Bug #2592 'mysqldump doesn't quote "tricky" names correctly' +# create table ```a` (i int); CREATE TABLE ```a` ( `i` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; drop table ```a`; +# +# Bug #2591 "mysqldump quotes names inconsistently" +# create table t1(a int); /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; @@ -352,6 +377,9 @@ UNLOCK TABLES; set global sql_mode=''; drop table t1; +# +# Bug #2705 'mysqldump --tab extra output' +# create table t1(a int); insert into t1 values (1),(2),(3); @@ -380,6 +408,9 @@ CREATE TABLE `t1` ( 2 3 drop table t1; +# +# Bug #6101: create database problem +# /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; @@ -432,6 +463,12 @@ USE `mysqldump_test_db`; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; drop database mysqldump_test_db; +# +# Bug #7020 +# Check that we don't dump in UTF8 in compatible mode by default, +# but use the default compiled values, or the values given in +# --default-character-set=xxx. However, we should dump in UTF8 +# if it is explicitely set. CREATE TABLE t1 (a CHAR(10)); INSERT INTO t1 VALUES (_latin1 'ÄÖÜß'); @@ -465,6 +502,13 @@ UNLOCK TABLES; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; +# +# Bug#8063: make test mysqldump [ fail ] +# We cannot tes this command because its output depends +# on --default-character-set incompiled into "mysqldump" program. +# If the future we can move this command into a separate test with +# checking that "mysqldump" is compiled with "latin1" +# /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; /*!40103 SET TIME_ZONE='+00:00' */; /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; @@ -535,6 +579,9 @@ UNLOCK TABLES; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; DROP TABLE t1; +# +# WL #2319: Exclude Tables from dump +# CREATE TABLE t1 (a int); CREATE TABLE t2 (a int); INSERT INTO t1 VALUES (1),(2),(3); @@ -572,6 +619,9 @@ UNLOCK TABLES; DROP TABLE t1; DROP TABLE t2; +# +# Bug #8830 +# CREATE TABLE t1 (`b` blob); INSERT INTO `t1` VALUES (0x602010000280100005E71A); @@ -606,6 +656,9 @@ UNLOCK TABLES; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; DROP TABLE t1; +# +# Test for --insert-ignore +# CREATE TABLE t1 (a int); INSERT INTO t1 VALUES (1),(2),(3); INSERT INTO t1 VALUES (4),(5),(6); @@ -670,6 +723,10 @@ INSERT DELAYED IGNORE INTO `t1` VALUES (1),(2),(3),(4),(5),(6); /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; DROP TABLE t1; +# +# Bug #10286: mysqldump -c crashes on table that has many fields with long +# names +# create table t1 ( F_c4ca4238a0b923820dcc509a6f75849b int, F_c81e728d9d4c2f636f067f89cc14862c int, @@ -1363,6 +1420,9 @@ UNLOCK TABLES; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; drop table t1; +# +# Test for --add-drop-database +# CREATE TABLE t1 (a int); INSERT INTO t1 VALUES (1),(2),(3); @@ -1403,6 +1463,9 @@ UNLOCK TABLES; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; DROP TABLE t1; +# +# Bug #9558 mysqldump --no-data db t1 t2 format still dumps data +# CREATE DATABASE mysqldump_test_db; USE mysqldump_test_db; CREATE TABLE t1 ( a INT ); @@ -1491,6 +1554,11 @@ CREATE TABLE `t2` ( DROP TABLE t1, t2; DROP DATABASE mysqldump_test_db; +# +# Testing with tables and databases that don't exists +# or contains illegal characters +# (Bug #9358 mysqldump crashes if tablename starts with \) +# create database mysqldump_test_db; use mysqldump_test_db; create table t1(a varchar(30) primary key, b int not null); @@ -1529,6 +1597,9 @@ mysqldump: Got error: 1102: Incorrect database name 'mysqld\ump_test_db' when se drop table t1, t2, t3; drop database mysqldump_test_db; use test; +# +# Bug #9657 mysqldump xml ( -x ) does not format NULL fields correctly +# create table t1 (a int(10)); create table t2 (pk int primary key auto_increment, a int(10), b varchar(30), c datetime, d blob, e text); @@ -1585,6 +1656,9 @@ insert into t2 (a, b) values (NULL, NULL),(10, NULL),(NULL, "twenty"),(30, "thir drop table t1, t2; +# +# BUG #12123 +# create table t1 (a text character set utf8, b text character set latin1); insert t1 values (0x4F736E616272C3BC636B, 0x4BF66C6E); select * from t1; @@ -1595,7 +1669,13 @@ select * from t1; a b Osnabrück Köln drop table t1; +# +# BUG#15328 Segmentation fault occured if my.cnf is invalid for escape sequence +# --fields-optionally-enclosed-by=" +# +# BUG #19025 mysqldump doesn't correctly dump "auto_increment = [int]" +# create table `t1` ( t1_name varchar(255) default null, t1_id int(10) unsigned not null auto_increment, @@ -1633,6 +1713,9 @@ t1 CREATE TABLE `t1` ( KEY `t1_name` (`t1_name`) ) ENGINE=MyISAM AUTO_INCREMENT=1003 DEFAULT CHARSET=latin1 drop table `t1`; +# +# Bug #18536: wrong table order +# create table t1(a int); create table t2(a int); create table t3(a int); @@ -1670,6 +1753,9 @@ CREATE TABLE `t2` ( /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; drop table t1, t2, t3; +# +# Bug #21288: mysqldump segmentation fault when using --where +# create table t1 (a int); mysqldump: Couldn't execute 'SELECT /*!40001 SQL_NO_CACHE */ * FROM `t1` WHERE xx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx': You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' at line 1 (1064) mysqldump: Got error: 1064: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' at line 1 when retrieving data from server @@ -1701,6 +1787,9 @@ CREATE TABLE `t1` ( drop table t1; End of 4.1 tests +# +# Bug #10213 mysqldump crashes when dumping VIEWs(on MacOS X) +# create database db1; use db1; CREATE TABLE t2 ( @@ -1760,6 +1849,9 @@ drop table t2; drop view v2; drop database db1; use test; +# +# Bug 10713 mysqldump includes database in create view and referenced tables +# create database db2; use db2; create table t1 (a int); @@ -1833,6 +1925,9 @@ DROP TABLE IF EXISTS `v1`; drop view v1; drop table t1; +# +# Bug #10213 mysqldump crashes when dumping VIEWs(on MacOS X) +# create database mysqldump_test_db; use mysqldump_test_db; CREATE TABLE t2 ( @@ -1892,6 +1987,9 @@ drop table t2; drop view v2; drop database mysqldump_test_db; use test; +# +# Bug #9756 +# CREATE TABLE t1 (a char(10)); INSERT INTO t1 VALUES ('\''); @@ -1926,6 +2024,9 @@ UNLOCK TABLES; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; DROP TABLE t1; +# +# Bug #10927 mysqldump: Can't reload dump with view that consist of other view +# create table t1(a int, b int, c varchar(30)); insert into t1 values(1, 2, "one"), (2, 4, "two"), (3, 6, "three"); create view v3 as @@ -2003,6 +2104,9 @@ DROP TABLE IF EXISTS `v3`; drop view v1, v2, v3; drop table t1; +# +# Test for dumping triggers +# CREATE TABLE t1 (a int, b bigint default NULL); CREATE TABLE t2 (a int); create trigger trg1 before insert on t1 for each row @@ -2201,8 +2305,14 @@ set @fired:= "No"; end if; end BEFORE # STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER root@localhost DROP TABLE t1, t2; +# +# Bugs #9136, #12917: problems with --defaults-extra-file option +# --port=1234 --port=1234 +# +# Test of fix to BUG 12597 +# DROP TABLE IF EXISTS `test1`; Warnings: Note 1051 Unknown table 'test1' @@ -2234,6 +2344,9 @@ a2 DROP TRIGGER testref; DROP TABLE test1; DROP TABLE test2; +# +# BUG#9056 - mysqldump does not dump routines +# DROP TABLE IF EXISTS t1; DROP FUNCTION IF EXISTS bug9056_func1; DROP FUNCTION IF EXISTS bug9056_func2; @@ -2330,6 +2443,9 @@ DROP PROCEDURE bug9056_proc1; DROP PROCEDURE bug9056_proc2; DROP PROCEDURE `a'b`; drop table t1; +# +# BUG# 13052 - mysqldump timestamp reloads broken +# drop table if exists t1; create table t1 (`d` timestamp, unique (`d`)); set time_zone='+00:00'; @@ -2416,6 +2532,9 @@ UNLOCK TABLES; drop table t1; set global time_zone=default; set time_zone=default; +# +# Test of fix to BUG 13146 - ansi quotes break loading of triggers +# DROP TABLE IF EXISTS `t1 test`; DROP TABLE IF EXISTS `t2 test`; CREATE TABLE `t1 test` ( @@ -2479,6 +2598,9 @@ UNLOCK TABLES; DROP TRIGGER `test trig`; DROP TABLE `t1 test`; DROP TABLE `t2 test`; +# +# BUG# 12838 mysqldump -x with views exits with error +# drop table if exists t1; create table t1 (a int, b varchar(32), c varchar(32)); insert into t1 values (1, 'first value', 'xxxx'); @@ -2571,6 +2693,10 @@ drop view v2; drop view v0; drop view v1; drop table t1; +# +# BUG#14554 - mysqldump does not separate words "ROW" and "BEGIN" +# for tables with trigger created in the IGNORE_SPACE sql mode. +# SET @old_sql_mode = @@SQL_MODE; SET SQL_MODE = IGNORE_SPACE; CREATE TABLE t1 (a INT); @@ -2626,6 +2752,9 @@ DELIMITER ; DROP TRIGGER tr1; DROP TABLE t1; +# +# Bug #13318: Bad result with empty field and --hex-blob +# create table t1 (a binary(1), b blob); insert into t1 values ('',''); @@ -2693,6 +2822,9 @@ UNLOCK TABLES; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; drop table t1; +# +# Bug 14871 Invalid view dump output +# create table t1 (a int); insert into t1 values (289), (298), (234), (456), (789); create definer = CURRENT_USER view v1 as select * from t1; @@ -2719,6 +2851,9 @@ a 789 drop table t1; drop view v1, v2, v3, v4, v5; +# +# Bug #16878 dump of trigger +# create table t1 (a int, created datetime); create table t2 (b int, created datetime); create trigger tr1 before insert on t1 for each row set @@ -2741,6 +2876,9 @@ end AFTER # root@localhost drop trigger tr1; drop trigger tr2; drop table t1, t2; +# +# Bug#18462 mysqldump does not dump view structures correctly +# create table t (qty int, price int); insert into t values(3, 50); insert into t values(5, 51); @@ -2760,6 +2898,10 @@ mysqldump { drop view v1; drop view v2; drop table t; +# +# Bug#14857 Reading dump files with single statement stored routines fails. +# fixed by patch for bug#16878 +# /*!50003 CREATE FUNCTION `f`() RETURNS bigint(20) return 42 */| /*!50003 CREATE PROCEDURE `p`() @@ -2774,6 +2916,9 @@ p CREATE DEFINER=`root`@`localhost` PROCEDURE `p`() select 42 drop function f; drop procedure p; +# +# Bug #17371 Unable to dump a schema with invalid views +# create table t1 ( id serial ); create view v1 as select * from t1; drop table t1; @@ -2783,6 +2928,9 @@ mysqldump { } mysqldump drop view v1; +# BUG#17201 Spurious 'DROP DATABASE' in output, +# also confusion between tables and views. +# Example code from Markus Popp create database mysqldump_test_db; use mysqldump_test_db; create table t1 (id int); @@ -2843,6 +2991,9 @@ USE `mysqldump_test_db`; drop view v1; drop table t1; drop database mysqldump_test_db; +# +# Bug21014 Segmentation fault of mysqldump on view +# create database mysqldump_tables; use mysqldump_tables; create table basetable ( id serial, tag varchar(64) ); @@ -2876,6 +3027,9 @@ drop view nasishnasifu; drop database mysqldump_views; drop table mysqldump_tables.basetable; drop database mysqldump_tables; +# +# Bug20221 Dumping of multiple databases containing view(s) yields maleformed dumps +# create database mysqldump_dba; use mysqldump_dba; create table t1 (f1 int, f2 int); @@ -2908,6 +3062,9 @@ drop view v1; drop table t1; drop database mysqldump_dbb; use test; +# +# Bug#21215 mysqldump creating incomplete backups without warning +# create user mysqltest_1@localhost; create table t1(a int, b varchar(34)); reset master; @@ -2924,6 +3081,12 @@ CREATE TABLE `t1` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1; drop table t1; drop user mysqltest_1@localhost; +# +# Bug #21527 mysqldump incorrectly tries to LOCK TABLES on the +# information_schema database. +# +# Bug #21424 mysqldump failing to export/import views +# create database mysqldump_myDB; use mysqldump_myDB; create user myDB_User; @@ -2942,6 +3105,9 @@ revoke all privileges on mysqldump_myDB.* from myDB_User@localhost; drop user myDB_User; drop database mysqldump_myDB; flush privileges; +# Bug #21424 continues from here. +# Restore. Flush Privileges test ends. +# use mysqldump_myDB; select * from mysqldump_myDB.v1; c1 @@ -2957,4 +3123,78 @@ revoke all privileges on mysqldump_myDB.* from myDB_User@localhost; drop user myDB_User; drop database mysqldump_myDB; use test; -End of 5.0 tests +# +# BUG#13926: --order-by-primary fails if PKEY contains quote character +# +DROP TABLE IF EXISTS `t1`; +CREATE TABLE `t1` ( +`a b` INT, +`c"d` INT, +`e``f` INT, +PRIMARY KEY (`a b`, `c"d`, `e``f`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +insert into t1 values (0815, 4711, 2006); +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO,ANSI' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; +DROP TABLE IF EXISTS "t1"; +CREATE TABLE "t1" ( + "a b" int(11) NOT NULL default '0', + "c""d" int(11) NOT NULL default '0', + "e`f" int(11) NOT NULL default '0', + PRIMARY KEY ("a b","c""d","e`f") +); + +LOCK TABLES "t1" WRITE; +/*!40000 ALTER TABLE "t1" DISABLE KEYS */; +INSERT INTO "t1" VALUES (815,4711,2006); +/*!40000 ALTER TABLE "t1" ENABLE KEYS */; +UNLOCK TABLES; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; +DROP TABLE IF EXISTS `t1`; +CREATE TABLE `t1` ( + `a b` int(11) NOT NULL default '0', + `c"d` int(11) NOT NULL default '0', + `e``f` int(11) NOT NULL default '0', + PRIMARY KEY (`a b`,`c"d`,`e``f`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; + +LOCK TABLES `t1` WRITE; +/*!40000 ALTER TABLE `t1` DISABLE KEYS */; +INSERT INTO `t1` VALUES (815,4711,2006); +/*!40000 ALTER TABLE `t1` ENABLE KEYS */; +UNLOCK TABLES; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +DROP TABLE `t1`; +# +# End of 5.0 tests +# diff --git a/mysql-test/r/rpl_view.result b/mysql-test/r/rpl_view.result index 51a8e3193aa..601f3d9cd14 100644 --- a/mysql-test/r/rpl_view.result +++ b/mysql-test/r/rpl_view.result @@ -106,3 +106,4 @@ a b 1 6 drop table t1; drop view v1; +End of 5.0 tests diff --git a/mysql-test/t/rpl_view.test b/mysql-test/t/rpl_view.test index 52db75aaf69..812e5d44d58 100644 --- a/mysql-test/t/rpl_view.test +++ b/mysql-test/t/rpl_view.test @@ -149,3 +149,4 @@ drop view v1; sync_slave_with_master; +--echo End of 5.0 tests From fe782f92d6f2448fb90a60c011c651f39231e747 Mon Sep 17 00:00:00 2001 From: "lars/lthalmann@mysql.com/dl145h.mysql.com" <> Date: Thu, 21 Sep 2006 03:32:42 +0200 Subject: [PATCH 34/39] Vertical printout in test to make easier to read --- mysql-test/r/rpl_max_relay_size.result | 243 +++++++++++++++++++++++-- mysql-test/t/rpl_max_relay_size.test | 41 ++++- 2 files changed, 263 insertions(+), 21 deletions(-) diff --git a/mysql-test/r/rpl_max_relay_size.result b/mysql-test/r/rpl_max_relay_size.result index 5c3360b0f66..c0a7a0a5b00 100644 --- a/mysql-test/r/rpl_max_relay_size.result +++ b/mysql-test/r/rpl_max_relay_size.result @@ -5,9 +5,15 @@ reset slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; stop slave; +# +# Generate a big enough master's binlog to cause relay log rotations +# create table t1 (a int); drop table t1; reset slave; +# +# Test 1 +# set global max_binlog_size=8192; set global max_relay_log_size=8192-1; select @@global.max_relay_log_size; @@ -15,47 +21,248 @@ select @@global.max_relay_log_size; 4096 start slave; show slave status; -Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master -# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 50477 slave-relay-bin.000014 1221 master-bin.000001 Yes Yes 0 0 50477 1221 None 0 No # +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos 50477 +Relay_Log_File slave-relay-bin.000014 +Relay_Log_Pos 1221 +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running Yes +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 0 +Last_Error +Skip_Counter 0 +Exec_Master_Log_Pos 50477 +Relay_Log_Space 1221 +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +# +# Test 2 +# stop slave; reset slave; set global max_relay_log_size=(5*4096); select @@global.max_relay_log_size; -@@global.max_relay_log_size -20480 +@@global.max_relay_log_size 20480 start slave; show slave status; -Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master -# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 50477 slave-relay-bin.000004 9457 master-bin.000001 Yes Yes 0 0 50477 9457 None 0 No # +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos 50477 +Relay_Log_File slave-relay-bin.000004 +Relay_Log_Pos 9457 +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running Yes +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 0 +Last_Error +Skip_Counter 0 +Exec_Master_Log_Pos 50477 +Relay_Log_Space 9457 +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +# +# Test 3: max_relay_log_size = 0 +# stop slave; reset slave; set global max_relay_log_size=0; select @@global.max_relay_log_size; -@@global.max_relay_log_size -0 +@@global.max_relay_log_size 0 start slave; show slave status; -Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master -# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 50477 slave-relay-bin.000008 1283 master-bin.000001 Yes Yes 0 0 50477 1283 None 0 No # +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos 50477 +Relay_Log_File slave-relay-bin.000008 +Relay_Log_Pos 1283 +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running Yes +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 0 +Last_Error +Skip_Counter 0 +Exec_Master_Log_Pos 50477 +Relay_Log_Space 1283 +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +# +# Test 4: Tests below are mainly to ensure that we have not coded with wrong assumptions +# stop slave; reset slave; flush logs; show slave status; -Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master -# 127.0.0.1 root MASTER_PORT 1 4 slave-relay-bin.000001 4 No No 0 0 0 4 None 0 No # +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File +Read_Master_Log_Pos 4 +Relay_Log_File slave-relay-bin.000001 +Relay_Log_Pos 4 +Relay_Master_Log_File +Slave_IO_Running No +Slave_SQL_Running No +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 0 +Last_Error +Skip_Counter 0 +Exec_Master_Log_Pos 0 +Relay_Log_Space 4 +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +# +# Test 5 +# reset slave; start slave; flush logs; create table t1 (a int); show slave status; -Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master -# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 50535 slave-relay-bin.000009 62 master-bin.000001 Yes Yes 0 0 50535 62 None 0 No # +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos 50535 +Relay_Log_File slave-relay-bin.000009 +Relay_Log_Pos 62 +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running Yes +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 0 +Last_Error +Skip_Counter 0 +Exec_Master_Log_Pos 50535 +Relay_Log_Space 62 +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # +# +# Test 6: one more rotation, to be sure Relay_Log_Space is correctly updated +# flush logs; drop table t1; show slave status; -Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master -# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 50583 slave-relay-bin.000010 52 master-bin.000001 Yes Yes 0 0 50583 52 None 0 No # +Slave_IO_State # +Master_Host 127.0.0.1 +Master_User root +Master_Port MASTER_PORT +Connect_Retry 1 +Master_Log_File master-bin.000001 +Read_Master_Log_Pos 50583 +Relay_Log_File slave-relay-bin.000010 +Relay_Log_Pos 52 +Relay_Master_Log_File master-bin.000001 +Slave_IO_Running Yes +Slave_SQL_Running Yes +Replicate_Do_DB +Replicate_Ignore_DB +Replicate_Do_Table +Replicate_Ignore_Table +Replicate_Wild_Do_Table +Replicate_Wild_Ignore_Table +Last_Errno 0 +Last_Error +Skip_Counter 0 +Exec_Master_Log_Pos 50583 +Relay_Log_Space 52 +Until_Condition None +Until_Log_File +Until_Log_Pos 0 +Master_SSL_Allowed No +Master_SSL_CA_File +Master_SSL_CA_Path +Master_SSL_Cert +Master_SSL_Cipher +Master_SSL_Key +Seconds_Behind_Master # flush logs; show master status; -File Position Binlog_Do_DB Binlog_Ignore_DB -master-bin.000002 4 +File master-bin.000002 +Position 4 +Binlog_Do_DB +Binlog_Ignore_DB diff --git a/mysql-test/t/rpl_max_relay_size.test b/mysql-test/t/rpl_max_relay_size.test index c01041d7eee..63d7ef35413 100644 --- a/mysql-test/t/rpl_max_relay_size.test +++ b/mysql-test/t/rpl_max_relay_size.test @@ -7,7 +7,11 @@ source include/master-slave.inc; connection slave; stop slave; connection master; -# Generate a big enough master's binlog to cause relay log rotations + +--echo # +--echo # Generate a big enough master's binlog to cause relay log rotations +--echo # + create table t1 (a int); let $1=800; disable_query_log; @@ -23,6 +27,11 @@ drop table t1; save_master_pos; connection slave; reset slave; + +--echo # +--echo # Test 1 +--echo # + set global max_binlog_size=8192; set global max_relay_log_size=8192-1; # mapped to 4096 select @@global.max_relay_log_size; @@ -30,7 +39,13 @@ start slave; sync_with_master; --replace_result $MASTER_MYPORT MASTER_PORT --replace_column 1 # 33 # +--vertical_results show slave status; + +--echo # +--echo # Test 2 +--echo # + stop slave; reset slave; set global max_relay_log_size=(5*4096); @@ -39,7 +54,13 @@ start slave; sync_with_master; --replace_result $MASTER_MYPORT MASTER_PORT --replace_column 1 # 33 # +--vertical_results show slave status; + +--echo # +--echo # Test 3: max_relay_log_size = 0 +--echo # + stop slave; reset slave; set global max_relay_log_size=0; @@ -48,9 +69,12 @@ start slave; sync_with_master; --replace_result $MASTER_MYPORT MASTER_PORT --replace_column 1 # 33 # +--vertical_results show slave status; -# Tests below are mainly to ensure that we have not coded with wrong assumptions +--echo # +--echo # Test 4: Tests below are mainly to ensure that we have not coded with wrong assumptions +--echo # stop slave; reset slave; @@ -59,8 +83,13 @@ reset slave; flush logs; --replace_result $MASTER_MYPORT MASTER_PORT --replace_column 1 # 33 # +--vertical_results show slave status; +--echo # +--echo # Test 5 +--echo # + reset slave; start slave; sync_with_master; @@ -75,8 +104,13 @@ connection slave; sync_with_master; --replace_result $MASTER_MYPORT MASTER_PORT --replace_column 1 # 33 # +--vertical_results show slave status; -# one more rotation, to be sure Relay_Log_Space is correctly updated + +--echo # +--echo # Test 6: one more rotation, to be sure Relay_Log_Space is correctly updated +--echo # + flush logs; connection master; drop table t1; @@ -85,6 +119,7 @@ connection slave; sync_with_master; --replace_result $MASTER_MYPORT MASTER_PORT --replace_column 1 # 33 # +--vertical_results show slave status; connection master; From 9538acf5dcf4811fb9af07c25fafd0e20b93caf2 Mon Sep 17 00:00:00 2001 From: "lars/lthalmann@mysql.com/dl145h.mysql.com" <> Date: Thu, 21 Sep 2006 13:19:52 +0200 Subject: [PATCH 35/39] Adding proper setup phase for test case rpl_insert_id --- mysql-test/r/rpl_insert_id.result | 24 +++++++++++++++++ mysql-test/t/rpl_insert_id.test | 44 ++++++++++++++++++++++--------- 2 files changed, 55 insertions(+), 13 deletions(-) diff --git a/mysql-test/r/rpl_insert_id.result b/mysql-test/r/rpl_insert_id.result index e683ea2fb39..fbdc9dc06cf 100644 --- a/mysql-test/r/rpl_insert_id.result +++ b/mysql-test/r/rpl_insert_id.result @@ -1,9 +1,20 @@ +# +# Setup +# 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; +use test; +drop table if exists t1, t2, t3; +# +# See if queries that use both auto_increment and LAST_INSERT_ID() +# are replicated well +# +# We also check how the foreign_key_check variable is replicated +# create table t1(a int auto_increment, key(a)); create table t2(b int auto_increment, c int, key(b)); insert into t1 values (1),(2),(3); @@ -38,6 +49,9 @@ select * from t2; b c 5 0 6 11 +# +# check if INSERT SELECT in auto_increment is well replicated (bug #490) +# drop table t2; drop table t1; create table t1(a int auto_increment, key(a)); @@ -68,11 +82,18 @@ b c 9 13 drop table t1; drop table t2; +# +# Bug#8412: Error codes reported in binary log for CHARACTER SET, +# FOREIGN_KEY_CHECKS +# SET TIMESTAMP=1000000000; CREATE TABLE t1 ( a INT UNIQUE ); SET FOREIGN_KEY_CHECKS=0; INSERT INTO t1 VALUES (1),(1); ERROR 23000: Duplicate entry '1' for key 1 +# +# Bug#14553: NULL in WHERE resets LAST_INSERT_ID +# drop table t1; create table t1(a int auto_increment, key(a)); create table t2(a int); @@ -87,3 +108,6 @@ a 1 drop table t1; drop table t2; +# +# End of 4.1 tests +# diff --git a/mysql-test/t/rpl_insert_id.test b/mysql-test/t/rpl_insert_id.test index 766afad9e47..327094a1394 100644 --- a/mysql-test/t/rpl_insert_id.test +++ b/mysql-test/t/rpl_insert_id.test @@ -1,10 +1,21 @@ -# See if queries that use both auto_increment and LAST_INSERT_ID() -# are replicated well - -# We also check how the foreign_key_check variable is replicated +--echo # +--echo # Setup +--echo # source include/master-slave.inc; source include/have_innodb.inc; +use test; +--disable_warnings +drop table if exists t1, t2, t3; +--enable_warnings + +--echo # +--echo # See if queries that use both auto_increment and LAST_INSERT_ID() +--echo # are replicated well +--echo # +--echo # We also check how the foreign_key_check variable is replicated +--echo # + connection master; create table t1(a int auto_increment, key(a)); create table t2(b int auto_increment, c int, key(b)); @@ -39,7 +50,9 @@ select * from t1; select * from t2; connection master; -# check if INSERT SELECT in auto_increment is well replicated (bug #490) +--echo # +--echo # check if INSERT SELECT in auto_increment is well replicated (bug #490) +--echo # drop table t2; drop table t1; @@ -62,10 +75,11 @@ save_master_pos; connection slave; sync_with_master; -# -# Bug#8412: Error codes reported in binary log for CHARACTER SET, -# FOREIGN_KEY_CHECKS -# +--echo # +--echo # Bug#8412: Error codes reported in binary log for CHARACTER SET, +--echo # FOREIGN_KEY_CHECKS +--echo # + connection master; SET TIMESTAMP=1000000000; CREATE TABLE t1 ( a INT UNIQUE ); @@ -74,9 +88,10 @@ SET FOREIGN_KEY_CHECKS=0; INSERT INTO t1 VALUES (1),(1); sync_slave_with_master; -# -# Bug#14553: NULL in WHERE resets LAST_INSERT_ID -# +--echo # +--echo # Bug#14553: NULL in WHERE resets LAST_INSERT_ID +--echo # + connection master; drop table t1; create table t1(a int auto_increment, key(a)); @@ -92,4 +107,7 @@ connection master; drop table t1; drop table t2; sync_slave_with_master; -# End of 4.1 tests + +--echo # +--echo # End of 4.1 tests +--echo # From 738cd74b52cb53d3a3432bf36a4c9121cd54d36e Mon Sep 17 00:00:00 2001 From: "lars/lthalmann@mysql.com/dl145j.mysql.com" <> Date: Thu, 21 Sep 2006 13:38:01 +0200 Subject: [PATCH 36/39] After merge fixes --- mysql-test/r/rpl_insert_id.result | 5 ++- mysql-test/r/rpl_max_relay_size.result | 61 ++++++++++++++------------ 2 files changed, 36 insertions(+), 30 deletions(-) diff --git a/mysql-test/r/rpl_insert_id.result b/mysql-test/r/rpl_insert_id.result index 9c25157368e..e425cce9508 100644 --- a/mysql-test/r/rpl_insert_id.result +++ b/mysql-test/r/rpl_insert_id.result @@ -91,10 +91,10 @@ CREATE TABLE t1 ( a INT UNIQUE ); SET FOREIGN_KEY_CHECKS=0; INSERT INTO t1 VALUES (1),(1); ERROR 23000: Duplicate entry '1' for key 1 +drop table t1; # # Bug#14553: NULL in WHERE resets LAST_INSERT_ID # -drop table t1; create table t1(a int auto_increment, key(a)); create table t2(a int); insert into t1 (a) values (null); @@ -234,3 +234,6 @@ n b 2 100 3 350 drop table t1; + +# End of 5.0 tests + diff --git a/mysql-test/r/rpl_max_relay_size.result b/mysql-test/r/rpl_max_relay_size.result index c0a7a0a5b00..1fa49db6013 100644 --- a/mysql-test/r/rpl_max_relay_size.result +++ b/mysql-test/r/rpl_max_relay_size.result @@ -27,9 +27,9 @@ Master_User root Master_Port MASTER_PORT Connect_Retry 1 Master_Log_File master-bin.000001 -Read_Master_Log_Pos 50477 -Relay_Log_File slave-relay-bin.000014 -Relay_Log_Pos 1221 +Read_Master_Log_Pos 72952 +Relay_Log_File # +Relay_Log_Pos # Relay_Master_Log_File master-bin.000001 Slave_IO_Running Yes Slave_SQL_Running Yes @@ -42,8 +42,8 @@ Replicate_Wild_Ignore_Table Last_Errno 0 Last_Error Skip_Counter 0 -Exec_Master_Log_Pos 50477 -Relay_Log_Space 1221 +Exec_Master_Log_Pos 72952 +Relay_Log_Space # Until_Condition None Until_Log_File Until_Log_Pos 0 @@ -70,9 +70,9 @@ Master_User root Master_Port MASTER_PORT Connect_Retry 1 Master_Log_File master-bin.000001 -Read_Master_Log_Pos 50477 -Relay_Log_File slave-relay-bin.000004 -Relay_Log_Pos 9457 +Read_Master_Log_Pos 72952 +Relay_Log_File # +Relay_Log_Pos # Relay_Master_Log_File master-bin.000001 Slave_IO_Running Yes Slave_SQL_Running Yes @@ -85,8 +85,8 @@ Replicate_Wild_Ignore_Table Last_Errno 0 Last_Error Skip_Counter 0 -Exec_Master_Log_Pos 50477 -Relay_Log_Space 9457 +Exec_Master_Log_Pos 72952 +Relay_Log_Space # Until_Condition None Until_Log_File Until_Log_Pos 0 @@ -113,9 +113,9 @@ Master_User root Master_Port MASTER_PORT Connect_Retry 1 Master_Log_File master-bin.000001 -Read_Master_Log_Pos 50477 -Relay_Log_File slave-relay-bin.000008 -Relay_Log_Pos 1283 +Read_Master_Log_Pos 72952 +Relay_Log_File # +Relay_Log_Pos # Relay_Master_Log_File master-bin.000001 Slave_IO_Running Yes Slave_SQL_Running Yes @@ -128,8 +128,8 @@ Replicate_Wild_Ignore_Table Last_Errno 0 Last_Error Skip_Counter 0 -Exec_Master_Log_Pos 50477 -Relay_Log_Space 1283 +Exec_Master_Log_Pos 72952 +Relay_Log_Space # Until_Condition None Until_Log_File Until_Log_Pos 0 @@ -154,8 +154,8 @@ Master_Port MASTER_PORT Connect_Retry 1 Master_Log_File Read_Master_Log_Pos 4 -Relay_Log_File slave-relay-bin.000001 -Relay_Log_Pos 4 +Relay_Log_File # +Relay_Log_Pos # Relay_Master_Log_File Slave_IO_Running No Slave_SQL_Running No @@ -169,7 +169,7 @@ Last_Errno 0 Last_Error Skip_Counter 0 Exec_Master_Log_Pos 0 -Relay_Log_Space 4 +Relay_Log_Space # Until_Condition None Until_Log_File Until_Log_Pos 0 @@ -194,9 +194,9 @@ Master_User root Master_Port MASTER_PORT Connect_Retry 1 Master_Log_File master-bin.000001 -Read_Master_Log_Pos 50535 -Relay_Log_File slave-relay-bin.000009 -Relay_Log_Pos 62 +Read_Master_Log_Pos 73038 +Relay_Log_File # +Relay_Log_Pos # Relay_Master_Log_File master-bin.000001 Slave_IO_Running Yes Slave_SQL_Running Yes @@ -209,8 +209,8 @@ Replicate_Wild_Ignore_Table Last_Errno 0 Last_Error Skip_Counter 0 -Exec_Master_Log_Pos 50535 -Relay_Log_Space 62 +Exec_Master_Log_Pos 73038 +Relay_Log_Space # Until_Condition None Until_Log_File Until_Log_Pos 0 @@ -233,9 +233,9 @@ Master_User root Master_Port MASTER_PORT Connect_Retry 1 Master_Log_File master-bin.000001 -Read_Master_Log_Pos 50583 -Relay_Log_File slave-relay-bin.000010 -Relay_Log_Pos 52 +Read_Master_Log_Pos 73114 +Relay_Log_File # +Relay_Log_Pos # Relay_Master_Log_File master-bin.000001 Slave_IO_Running Yes Slave_SQL_Running Yes @@ -248,8 +248,8 @@ Replicate_Wild_Ignore_Table Last_Errno 0 Last_Error Skip_Counter 0 -Exec_Master_Log_Pos 50583 -Relay_Log_Space 52 +Exec_Master_Log_Pos 73114 +Relay_Log_Space # Until_Condition None Until_Log_File Until_Log_Pos 0 @@ -263,6 +263,9 @@ Seconds_Behind_Master # flush logs; show master status; File master-bin.000002 -Position 4 +Position 98 Binlog_Do_DB Binlog_Ignore_DB +# +# End of 4.1 tests +# From d1f0a57a6da6e0f0b1a607d9e65589c4799de2be Mon Sep 17 00:00:00 2001 From: "joerg@trift2." <> Date: Thu, 21 Sep 2006 17:38:42 +0200 Subject: [PATCH 37/39] Add a dummy file for "Docs/manual.chm" as we need it for "make dist" to work. --- Docs/manual.chm | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 Docs/manual.chm diff --git a/Docs/manual.chm b/Docs/manual.chm new file mode 100644 index 00000000000..28c3e1b5a86 --- /dev/null +++ b/Docs/manual.chm @@ -0,0 +1,14 @@ + +********************************************************* + +This is a dummy placeholder file for "manual.chm" in the +MySQL source trees. + +Note, that the documentation has been moved into a separate +BitKeeper source tree named "mysqldoc" - do not attempt to edit this +file! All changes to it should be done in the mysqldoc tree. + +This dummy file is being replaced with the actual file from the +mysqldoc tree when building the official source distribution. + +********************************************************* From ca00ba4991aae1de9b06e1234c12c10ea9a410ea Mon Sep 17 00:00:00 2001 From: "georg@lmy002.wdf.sap.corp" <> Date: Fri, 22 Sep 2006 07:38:24 +0200 Subject: [PATCH 38/39] Added build rule for mysql_upgrade.exe --- client/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index 3e7f1a48c70..09a6a3f1e2a 100755 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -66,6 +66,9 @@ TARGET_LINK_LIBRARIES(mysqldump mysqlclient mysys dbug yassl taocrypt zlib wsock ADD_EXECUTABLE(mysqlimport mysqlimport.c) TARGET_LINK_LIBRARIES(mysqlimport mysqlclient mysys dbug yassl taocrypt zlib wsock32) +ADD_EXECUTABLE(mysql_upgrade mysql_upgrade.c) +TARGET_LINK_LIBRARIES(mysql_upgrade mysqlclient mysys dbug yassl taocrypt zlib wsock32) + ADD_EXECUTABLE(mysqlshow mysqlshow.c) TARGET_LINK_LIBRARIES(mysqlshow mysqlclient mysys dbug yassl taocrypt zlib wsock32) From 67a701003c5754ca87ff802ffed91e6276a89b4c Mon Sep 17 00:00:00 2001 From: "georg@lmy002.wdf.sap.corp" <> Date: Fri, 22 Sep 2006 14:42:43 +0200 Subject: [PATCH 39/39] Fix for bug #19121: Windows incompatible udf_example --- BitKeeper/etc/collapsed | 1 + mysql-test/mysql-test-run.pl | 4 +++- sql/CMakeLists.txt | 5 ++++- sql/Makefile.am | 3 ++- sql/udf_example.c | 11 +++++++++++ sql/udf_example.def | 24 ++++++++++++++++++++++++ 6 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 sql/udf_example.def diff --git a/BitKeeper/etc/collapsed b/BitKeeper/etc/collapsed index d4d681937a2..fd33e4fc902 100644 --- a/BitKeeper/etc/collapsed +++ b/BitKeeper/etc/collapsed @@ -2,3 +2,4 @@ 44ec850ac2k4y2Omgr92GiWPBAVKGQ 44edb86b1iE5knJ97MbliK_3lCiAXA 44f33f3aj5KW5qweQeekY1LU0E9ZCg +4513d8e4Af4dQWuk13sArwofRgFDQw diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index f0eb7f3bda4..994a0d044f5 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -1110,7 +1110,9 @@ sub executable_setup () { $path_ndb_tools_dir= mtr_path_exists("$glob_basedir/ndb/tools"); $exe_ndb_mgm= "$glob_basedir/ndb/src/mgmclient/ndb_mgm"; $lib_udf_example= - mtr_file_exists("$glob_basedir/sql/.libs/udf_example.so"); + mtr_file_exists("$glob_basedir/sql/.libs/udf_example.so", + "$glob_basedir/sql/release/udf_example.dll", + "$glob_basedir/sql/debug/udf_example.dll"); } else { diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt index b01871872ce..9b2fae847d6 100755 --- a/sql/CMakeLists.txt +++ b/sql/CMakeLists.txt @@ -110,5 +110,8 @@ ADD_CUSTOM_COMMAND( COMMAND ${GEN_LEX_HASH_EXE} ARGS > lex_hash.h DEPENDS ${GEN_LEX_HASH_EXE} ) - ADD_DEPENDENCIES(mysqld gen_lex_hash) + +ADD_LIBRARY(udf_example MODULE udf_example.c udf_example.def) +ADD_DEPENDENCIES(udf_example strings) +TARGET_LINK_LIBRARIES(udf_example wsock32) diff --git a/sql/Makefile.am b/sql/Makefile.am index 98c8fe784eb..e837e10472c 100644 --- a/sql/Makefile.am +++ b/sql/Makefile.am @@ -117,7 +117,8 @@ DEFS = -DMYSQL_SERVER \ BUILT_SOURCES = sql_yacc.cc sql_yacc.h lex_hash.h EXTRA_DIST = $(BUILT_SOURCES) nt_servc.cc nt_servc.h \ - message.mc examples/CMakeLists.txt CMakeLists.txt + message.mc examples/CMakeLists.txt CMakeLists.txt \ + udf_example.c udf_example.def DISTCLEANFILES = lex_hash.h sql_yacc.output AM_YFLAGS = -d --debug --verbose diff --git a/sql/udf_example.c b/sql/udf_example.c index a80fce81278..2fa7474eb16 100644 --- a/sql/udf_example.c +++ b/sql/udf_example.c @@ -127,7 +127,14 @@ typedef long long longlong; #else #include #include +#if defined(MYSQL_SERVER) #include /* To get strmov() */ +#else +/* when compiled as standalone */ +#define strmov(a,b) strcpy(a,b) +#define bzero(a,b) memset(a,0,b) +#define memcpy_fixed(a,b,c) memcpy(a,b,c) +#endif #endif #include #include @@ -674,10 +681,14 @@ longlong sequence(UDF_INIT *initid __attribute__((unused)), UDF_ARGS *args, ** ****************************************************************************/ +#ifdef __WIN__ +#include +#else #include #include #include #include +#endif my_bool lookup_init(UDF_INIT *initid, UDF_ARGS *args, char *message); void lookup_deinit(UDF_INIT *initid); diff --git a/sql/udf_example.def b/sql/udf_example.def new file mode 100644 index 00000000000..d3081ca7768 --- /dev/null +++ b/sql/udf_example.def @@ -0,0 +1,24 @@ +LIBRARY udf_example +DESCRIPTION 'MySQL Sample for UDF' +VERSION 1.0 +EXPORTS + lookup + lookup_init + reverse_lookup + reverse_lookup_init + metaphon_init + metaphon_deinit + metaphon + myfunc_double_init + myfunc_double + myfunc_int_init + myfunc_int + sequence_init + sequence_deinit + sequence + avgcost_init + avgcost_deinit + avgcost_reset + avgcost_add + avgcost_clear + avgcost