diff --git a/client/mysqltest.c b/client/mysqltest.c index ca28419fa4f..6f212f784ef 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -3028,6 +3028,59 @@ static void replace_dynstr_append(DYNAMIC_STRING *ds, const char *val) } +/* + Append the result for one field to the dynamic string ds +*/ + +static void append_field(DYNAMIC_STRING *ds, uint col_idx, MYSQL_FIELD* field, + const char* val, ulonglong len, bool is_null) +{ + + char buf[256]; + if (col_idx < max_replace_column && replace_column[col_idx]) + { + val= replace_column[col_idx]; + len= strlen(val); + } + else if (is_null) + { + val= "NULL"; + len= 4; + } +#ifdef __WIN__ + else if ((field->type == MYSQL_TYPE_DOUBLE || + field->type == MYSQL_TYPE_FLOAT ) && + field->decimals >= 31) + { + /* Convert 1.2e+018 to 1.2e+18 and 1.2e-018 to 1.2e-18 */ + char *start= strchr(val, 'e'); + if (start && strlen(start) >= 5 && + (start[1] == '-' || start[1] == '+') && start[2] == '0') + { + start+=2; /* Now points at first '0' */ + /* Move all chars after the first '0' one step left */ + memmove(start, start + 1, strlen(start)); + len--; + } + } +#endif + + if (!display_result_vertically) + { + if (col_idx) + dynstr_append_mem(ds, "\t", 1); + replace_dynstr_append_mem(ds, val, (int)len); + } + else + { + dynstr_append(ds, field->name); + dynstr_append_mem(ds, "\t", 1); + replace_dynstr_append_mem(ds, val, (int)len); + dynstr_append_mem(ds, "\n", 1); + } +} + + /* Append all results to the dynamic string separated with '\t' Values may be converted with 'replace_column' @@ -3037,41 +3090,16 @@ static void append_result(DYNAMIC_STRING *ds, MYSQL_RES *res) { MYSQL_ROW row; uint num_fields= mysql_num_fields(res); - MYSQL_FIELD *fields= !display_result_vertically ? 0 : mysql_fetch_fields(res); + MYSQL_FIELD *fields= mysql_fetch_fields(res); ulong *lengths; + while ((row = mysql_fetch_row(res))) { uint i; lengths = mysql_fetch_lengths(res); for (i = 0; i < num_fields; i++) - { - const char *val= row[i]; - ulonglong len= lengths[i]; - - if (i < max_replace_column && replace_column[i]) - { - val= replace_column[i]; - len= strlen(val); - } - if (!val) - { - val= "NULL"; - len= 4; - } - if (!display_result_vertically) - { - if (i) - dynstr_append_mem(ds, "\t", 1); - replace_dynstr_append_mem(ds, val, (int)len); - } - else - { - dynstr_append(ds, fields[i].name); - dynstr_append_mem(ds, "\t", 1); - replace_dynstr_append_mem(ds, val, (int)len); - dynstr_append_mem(ds, "\n", 1); - } - } + append_field(ds, i, &fields[i], + (const char*)row[i], lengths[i], !row[i]); if (!display_result_vertically) dynstr_append_mem(ds, "\n", 1); } @@ -3085,13 +3113,12 @@ static void append_result(DYNAMIC_STRING *ds, MYSQL_RES *res) */ static void append_stmt_result(DYNAMIC_STRING *ds, MYSQL_STMT *stmt, - MYSQL_FIELD *field, uint num_fields) + MYSQL_FIELD *fields, uint num_fields) { MYSQL_BIND *bind; my_bool *is_null; ulong *length; - ulonglong num_rows; - uint col_idx, row_idx; + uint i; /* Allocate array with bind structs, lengths and NULL flags */ bind= (MYSQL_BIND*) my_malloc(num_fields * sizeof(MYSQL_BIND), @@ -3101,71 +3128,29 @@ static void append_stmt_result(DYNAMIC_STRING *ds, MYSQL_STMT *stmt, is_null= (my_bool*) my_malloc(num_fields * sizeof(my_bool), MYF(MY_WME | MY_FAE)); - for (col_idx= 0; col_idx < num_fields; col_idx++) + /* Allocate data for the result of each field */ + for (i= 0; i < num_fields; i++) { - /* Allocate data for output */ - uint max_length= field[col_idx].max_length + 1; - char *str_data= (char *) my_malloc(max_length, MYF(MY_WME | MY_FAE)); - - bind[col_idx].buffer_type= MYSQL_TYPE_STRING; - bind[col_idx].buffer= (char *)str_data; - bind[col_idx].buffer_length= max_length; - bind[col_idx].is_null= &is_null[col_idx]; - bind[col_idx].length= &length[col_idx]; + uint max_length= fields[i].max_length + 1; + bind[i].buffer_type= MYSQL_TYPE_STRING; + bind[i].buffer= (char *)my_malloc(max_length, MYF(MY_WME | MY_FAE)); + bind[i].buffer_length= max_length; + bind[i].is_null= &is_null[i]; + bind[i].length= &length[i]; DBUG_PRINT("bind", ("col[%d]: buffer_type: %d, buffer_length: %d", - col_idx, - bind[col_idx].buffer_type, - bind[col_idx].buffer_length)); + i, bind[i].buffer_type, bind[i].buffer_length)); } - /* Fill in the data into the structures created above */ if (mysql_stmt_bind_result(stmt, bind)) die("mysql_stmt_bind_result failed: %d: %s", mysql_stmt_errno(stmt), mysql_stmt_error(stmt)); - /* Read result from each row */ - num_rows= mysql_stmt_num_rows(stmt); - for (row_idx= 0; row_idx < num_rows; row_idx++) + while (mysql_stmt_fetch(stmt) == 0) { - if (mysql_stmt_fetch(stmt)) - die("mysql_stmt_fetch failed: %d %s", - mysql_stmt_errno(stmt), mysql_stmt_error(stmt)); - - /* Read result from each column */ - for (col_idx= 0; col_idx < num_fields; col_idx++) - { - const char *val; - ulonglong len; - if (col_idx < max_replace_column && replace_column[col_idx]) - { - val= replace_column[col_idx]; - len= strlen(val); - } - else if (*bind[col_idx].is_null) - { - val= "NULL"; - len= 4; - } - else - { - val= (const char *) bind[col_idx].buffer; - len= *bind[col_idx].length; - } - if (!display_result_vertically) - { - if (col_idx) /* No tab before first col */ - dynstr_append_mem(ds, "\t", 1); - replace_dynstr_append_mem(ds, val, (int)len); - } - else - { - dynstr_append(ds, field[col_idx].name); - dynstr_append_mem(ds, "\t", 1); - replace_dynstr_append_mem(ds, val, (int)len); - dynstr_append_mem(ds, "\n", 1); - } - } + for (i= 0; i < num_fields; i++) + append_field(ds, i, &fields[i], (const char *) bind[i].buffer, + *bind[i].length, *bind[i].is_null); if (!display_result_vertically) dynstr_append_mem(ds, "\n", 1); } @@ -3176,10 +3161,10 @@ static void append_stmt_result(DYNAMIC_STRING *ds, MYSQL_STMT *stmt, free_replace_column(); - for (col_idx= 0; col_idx < num_fields; col_idx++) + for (i= 0; i < num_fields; i++) { /* Free data for output */ - my_free((gptr)bind[col_idx].buffer, MYF(MY_WME | MY_FAE)); + my_free((gptr)bind[i].buffer, MYF(MY_WME | MY_FAE)); } /* Free array with bind structs, lengths and NULL flags */ my_free((gptr)bind , MYF(MY_WME | MY_FAE)); diff --git a/configure.in b/configure.in index c171badb8e7..2ba832d4e2b 100644 --- a/configure.in +++ b/configure.in @@ -365,7 +365,7 @@ MYSQL_PROG_AR # libmysqlclient versioning when linked with GNU ld. if $LD --version 2>/dev/null|grep -q GNU; then - LD_VERSION_SCRIPT="-Wl,--version-script=\$(top_srcdir)/libmysql/libmysql.ver" + LD_VERSION_SCRIPT="-Wl,--version-script=\$(top_builddir)/libmysql/libmysql.ver" AC_CONFIG_FILES(libmysql/libmysql.ver) fi AC_SUBST(LD_VERSION_SCRIPT) diff --git a/heap/hp_create.c b/heap/hp_create.c index 47dcb00278a..9ffa4e33108 100644 --- a/heap/hp_create.c +++ b/heap/hp_create.c @@ -135,6 +135,7 @@ int heap_create(const char *name, uint keys, HP_KEYDEF *keydef, DBUG_RETURN(1); } share->keydef= (HP_KEYDEF*) (share + 1); + share->key_stat_version= 1; keyseg= (HA_KEYSEG*) (share->keydef + keys); init_block(&share->block, reclength + 1, min_records, max_records); /* Fix keys */ diff --git a/include/heap.h b/include/heap.h index badec9ce2ef..cfbb6113f86 100644 --- a/include/heap.h +++ b/include/heap.h @@ -136,6 +136,7 @@ typedef struct st_heap_share HP_KEYDEF *keydef; ulong min_records,max_records; /* Params to open */ ulong data_length,index_length,max_table_size; + uint key_stat_version; /* version to indicate insert/delete */ uint records; /* records */ uint blength; /* records rounded up to 2^n */ uint deleted; /* Deleted records in database */ diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index be1a3a1fe5f..9825f1ecdfa 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -5036,6 +5036,12 @@ my_bool STDCALL mysql_stmt_reset(MYSQL_STMT *stmt) { DBUG_ENTER("mysql_stmt_reset"); DBUG_ASSERT(stmt != 0); + if (!stmt->mysql) + { + /* mysql can be reset in mysql_close called from mysql_reconnect */ + set_stmt_error(stmt, CR_SERVER_LOST, unknown_sqlstate); + DBUG_RETURN(1); + } /* Reset the client and server sides of the prepared statement */ DBUG_RETURN(reset_stmt_handle(stmt, RESET_SERVER_SIDE | RESET_LONG_DATA)); } diff --git a/mysql-test/r/date_formats.result b/mysql-test/r/date_formats.result index f8189266e50..39e3aa0ca8e 100644 --- a/mysql-test/r/date_formats.result +++ b/mysql-test/r/date_formats.result @@ -503,3 +503,12 @@ d1 d2 02 February 01 January drop table t1; +select str_to_date( 1, NULL ); +str_to_date( 1, NULL ) +NULL +select str_to_date( NULL, 1 ); +str_to_date( NULL, 1 ) +NULL +select str_to_date( 1, IF(1=1,NULL,NULL) ); +str_to_date( 1, IF(1=1,NULL,NULL) ) +NULL diff --git a/mysql-test/r/heap.result b/mysql-test/r/heap.result index 7f40dfa3a36..fda4886f1af 100644 --- a/mysql-test/r/heap.result +++ b/mysql-test/r/heap.result @@ -169,7 +169,7 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL btn NULL NULL NULL 11 Using where explain select * from t1 where btn="a" and new_col="a"; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref btn btn 11 const,const 1 Using where +1 SIMPLE t1 ref btn btn 11 const,const 2 Using where drop table t1; CREATE TABLE t1 ( a int default NULL, @@ -182,7 +182,7 @@ SELECT * FROM t1 WHERE a=NULL; a b explain SELECT * FROM t1 WHERE a IS NULL; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref a a 5 const 1 Using where +1 SIMPLE t1 ref a a 5 const 2 Using where SELECT * FROM t1 WHERE a<=>NULL; a b NULL 99 @@ -701,6 +701,15 @@ insert into t1 values ("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd insert into t1 values ("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"); ERROR 23000: Duplicate entry 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl' for key 1 drop table t1; +CREATE TABLE t1 (a int, key(a)) engine=heap; +insert delayed into t1 values (0); +delete from t1; +select * from t1; +a +insert delayed into t1 values (0), (1); +select * from t1 where a = 0; +a +drop table t1; create table t1 (c char(10)) engine=memory; create table t2 (c varchar(10)) engine=memory; show table status like 't_'; diff --git a/mysql-test/r/heap_hash.result b/mysql-test/r/heap_hash.result index d8d89b786b5..e0835bbf8d6 100644 --- a/mysql-test/r/heap_hash.result +++ b/mysql-test/r/heap_hash.result @@ -169,7 +169,7 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 ALL btn NULL NULL NULL 11 Using where explain select * from t1 where btn="a" and new_col="a"; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref btn btn 11 const,const 1 Using where +1 SIMPLE t1 ref btn btn 11 const,const 2 Using where drop table t1; CREATE TABLE t1 ( a int default NULL, @@ -182,7 +182,7 @@ SELECT * FROM t1 WHERE a=NULL; a b explain SELECT * FROM t1 WHERE a IS NULL; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref a a 5 const 1 Using where +1 SIMPLE t1 ref a a 5 const 2 Using where SELECT * FROM t1 WHERE a<=>NULL; a b NULL 99 @@ -220,16 +220,16 @@ insert into t1 values ('aaag', 'prefill-hash=3',0); insert into t1 values ('aaah', 'prefill-hash=6',0); explain select * from t1 where a='aaaa'; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref a a 8 const 1 Using where +1 SIMPLE t1 ref a a 8 const 2 Using where explain select * from t1 where a='aaab'; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref a a 8 const 1 Using where +1 SIMPLE t1 ref a a 8 const 2 Using where explain select * from t1 where a='aaac'; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref a a 8 const 1 Using where +1 SIMPLE t1 ref a a 8 const 2 Using where explain select * from t1 where a='aaad'; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref a a 8 const 1 Using where +1 SIMPLE t1 ref a a 8 const 2 Using where insert into t1 select * from t1; flush tables; explain select * from t1 where a='aaaa'; @@ -291,25 +291,25 @@ insert into t1 (name) values ('Matt'), ('Lilu'), ('Corbin'), ('Carly'), insert into t2 select * from t1; explain select * from t1 where name='matt'; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref heap_idx,btree_idx heap_idx 22 const 1 Using where +1 SIMPLE t1 ref heap_idx,btree_idx btree_idx 22 const 1 Using where explain select * from t2 where name='matt'; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ref btree_idx,heap_idx btree_idx 22 const 1 Using where explain select * from t1 where name='Lilu'; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref heap_idx,btree_idx heap_idx 22 const 1 Using where +1 SIMPLE t1 ref heap_idx,btree_idx btree_idx 22 const 1 Using where explain select * from t2 where name='Lilu'; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ref btree_idx,heap_idx btree_idx 22 const 1 Using where explain select * from t1 where name='Phil'; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref heap_idx,btree_idx heap_idx 22 const 1 Using where +1 SIMPLE t1 ref heap_idx,btree_idx btree_idx 22 const 1 Using where explain select * from t2 where name='Phil'; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ref btree_idx,heap_idx btree_idx 22 const 1 Using where explain select * from t1 where name='Lilu'; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ref heap_idx,btree_idx heap_idx 22 const 1 Using where +1 SIMPLE t1 ref heap_idx,btree_idx btree_idx 22 const 1 Using where explain select * from t2 where name='Lilu'; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ref btree_idx,heap_idx btree_idx 22 const 1 Using where @@ -364,5 +364,5 @@ a 3 explain select a from t1 where a in (1,3); id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 range a a 5 NULL 2 Using where +1 SIMPLE t1 range a a 5 NULL 4 Using where drop table t1; diff --git a/mysql-test/r/kill.result b/mysql-test/r/kill.result index 2413834be4f..2cb90679aed 100644 --- a/mysql-test/r/kill.result +++ b/mysql-test/r/kill.result @@ -1,4 +1,4 @@ -drop table if exists t1; +drop table if exists t1, t2, t3; create table t1 (kill_id int); insert into t1 values(connection_id()); select ((@id := kill_id) - kill_id) from t1; @@ -15,6 +15,18 @@ select 4; 4 4 drop table t1; +create table t1 (id int primary key); +create table t2 (id int unsigned not null); +insert into t2 select id from t1; +create table t3 (kill_id int); +insert into t3 values(connection_id()); + select id from t1 where id in (select distinct id from t2); +select ((@id := kill_id) - kill_id) from t3; +((@id := kill_id) - kill_id) +0 +kill @id; +ERROR 08S01: Server shutdown in progress +drop table t1, t2, t3; select get_lock("a", 10); get_lock("a", 10) 1 diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result index e000cfd9c11..f60996ba31f 100644 --- a/mysql-test/r/myisam.result +++ b/mysql-test/r/myisam.result @@ -567,7 +567,7 @@ Warnings: Note 1031 Table storage engine for 't1' doesn't have this option show keys from t1; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment -t1 1 a 1 a NULL 1000 NULL NULL YES HASH +t1 1 a 1 a NULL 500 NULL NULL YES HASH drop table t1,t2; create table t1 ( a tinytext, b char(1), index idx (a(1),b) ); insert into t1 values (null,''), (null,''); diff --git a/mysql-test/r/type_float.result b/mysql-test/r/type_float.result index fb8d0515c18..e941e740fcb 100644 --- a/mysql-test/r/type_float.result +++ b/mysql-test/r/type_float.result @@ -31,14 +31,14 @@ select * from t1; f1 f2 10 10 100000 100000 -1.23457e+9 1234567890 +1.23457e+09 1234567890 1e+10 10000000000 1e+15 1e+15 1e+20 1e+20 3.40282e+38 1e+50 3.40282e+38 1e+150 -10 -10 -1e-5 1e-5 +1e-05 1e-05 1e-10 1e-10 1e-15 1e-15 1e-20 1e-20 diff --git a/mysql-test/r/update.result b/mysql-test/r/update.result index abeade5df0c..4b7dbb3dbe9 100644 --- a/mysql-test/r/update.result +++ b/mysql-test/r/update.result @@ -358,3 +358,22 @@ update t2,t1 set f1=3,f2=3 where f1=f2 and f1=1; affected rows: 3 info: Rows matched: 3 Changed: 3 Warnings: 0 drop table t1,t2; +create table t1 (a int); +insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +create table t2 (a int, filler1 char(200), filler2 char(200), key(a)); +insert into t2 select A.a + 10*B.a, 'filler','filler' from t1 A, t1 B; +flush status; +update t2 set a=3 where a=2; +show status like 'handler_read%'; +Variable_name Value +Handler_read_first 0 +Handler_read_key 1 +Handler_read_next 1 +Handler_read_prev 0 +Handler_read_rnd 1 +Handler_read_rnd_next 0 +drop table t1, t2; +create table t1(f1 int, `*f2` int); +insert into t1 values (1,1); +update t1 set `*f2`=1; +drop table t1; diff --git a/mysql-test/t/date_formats.test b/mysql-test/t/date_formats.test index c007c2f5205..b4c6cf0d72a 100644 --- a/mysql-test/t/date_formats.test +++ b/mysql-test/t/date_formats.test @@ -269,4 +269,11 @@ insert into t1 (f1) values ("2005-01-01"); insert into t1 (f1) values ("2005-02-01"); select date_format(f1, "%m") as d1, date_format(f1, "%M") as d2 from t1 order by date_format(f1, "%M"); drop table t1; + +# +# Bug #15828 +# +select str_to_date( 1, NULL ); +select str_to_date( NULL, 1 ); +select str_to_date( 1, IF(1=1,NULL,NULL) ); # End of 4.1 tests diff --git a/mysql-test/t/heap.test b/mysql-test/t/heap.test index fcaa4c41ece..6a8abdeea26 100644 --- a/mysql-test/t/heap.test +++ b/mysql-test/t/heap.test @@ -436,6 +436,17 @@ insert into t1 values ("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd insert into t1 values ("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"); drop table t1; +# +# Bug 12796: Record doesn't show when selecting through index +# +CREATE TABLE t1 (a int, key(a)) engine=heap; +insert delayed into t1 values (0); +delete from t1; +select * from t1; +insert delayed into t1 values (0), (1); +select * from t1 where a = 0; +drop table t1; + # End of 4.1 tests # diff --git a/mysql-test/t/insert.test b/mysql-test/t/insert.test index 51d936f5b4f..ddde6cfa5d3 100644 --- a/mysql-test/t/insert.test +++ b/mysql-test/t/insert.test @@ -99,27 +99,22 @@ create table t1(number int auto_increment primary key, original_value varchar(50 set @value= "aa"; insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value); ---replace_result e-0 e- e+0 e+ --query_vertical select * from t1 where number =last_insert_id() set @value= "1aa"; insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value); ---replace_result e-0 e- e+0 e+ --query_vertical select * from t1 where number =last_insert_id() set @value= "aa1"; insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value); ---replace_result e-0 e- e+0 e+ --query_vertical select * from t1 where number =last_insert_id() set @value= "1e+1111111111a"; insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value); ---replace_result e-0 e- e+0 e+ --query_vertical select * from t1 where number =last_insert_id() set @value= "-1e+1111111111a"; insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value); ---replace_result e-0 e- e+0 e+ --query_vertical select * from t1 where number =last_insert_id() --error 1367 @@ -130,22 +125,18 @@ set @value= -1e+1111111111; set @value= 1e+111; insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value); ---replace_result e-0 e- e+0 e+ --query_vertical select * from t1 where number =last_insert_id() set @value= -1e+111; insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value); ---replace_result e-0 e- e+0 e+ --query_vertical select * from t1 where number =last_insert_id() set @value= 1; insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value); ---replace_result e-0 e- e+0 e+ --query_vertical select * from t1 where number =last_insert_id() set @value= -1; insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value); ---replace_result e-0 e- e+0 e+ --query_vertical select * from t1 where number =last_insert_id() drop table t1; diff --git a/mysql-test/t/kill.test b/mysql-test/t/kill.test index c50c35825fc..9a8f61b1052 100644 --- a/mysql-test/t/kill.test +++ b/mysql-test/t/kill.test @@ -12,7 +12,7 @@ connect (con2, localhost, root,,); #remember id of con1 connection con1; --disable_warnings -drop table if exists t1; +drop table if exists t1, t2, t3; --enable_warnings --disable_reconnect @@ -47,6 +47,50 @@ connection con2; select 4; drop table t1; +connection default; +# +# BUG#14851: killing long running subquery processed via a temporary table. +# +create table t1 (id int primary key); +create table t2 (id int unsigned not null); + +connect (conn1, localhost, root,,); +connection conn1; + +-- disable_result_log +-- disable_query_log +let $1 = 4096; +while ($1) +{ + eval insert into t1 values ($1); + dec $1; +} +-- enable_query_log +-- enable_result_log + +insert into t2 select id from t1; + +create table t3 (kill_id int); +insert into t3 values(connection_id()); + +-- disable_result_log +send select id from t1 where id in (select distinct id from t2); +-- enable_result_log + +connect (conn2, localhost, root,,); +connection conn2; +select ((@id := kill_id) - kill_id) from t3; +-- sleep 1 +kill @id; + +connection conn1; +-- error 1053 +reap; + +connection default; + +drop table t1, t2, t3; + # End of 4.1 tests # diff --git a/mysql-test/t/type_float.test b/mysql-test/t/type_float.test index 79f29624e89..d223c315735 100644 --- a/mysql-test/t/type_float.test +++ b/mysql-test/t/type_float.test @@ -6,9 +6,7 @@ drop table if exists t1,t2; --enable_warnings ---replace_result e-0 e- e+0 e+ SELECT 10,10.0,10.,.1e+2,100.0e-1; ---replace_result e-00 e-0 SELECT 6e-05, -6e-05, --6e-05, -6e-05+1.000000; SELECT 1e1,1.e1,1.0e1,1e+1,1.e+1,1.0e+1,1e-1,1.e-1,1.0e-1; SELECT 0.001e+1,0.001e-1, -0.001e+01,-0.001e-01; @@ -21,7 +19,6 @@ create table t1 (f1 float(24),f2 float(52)); show full columns from t1; insert into t1 values(10,10),(1e+5,1e+5),(1234567890,1234567890),(1e+10,1e+10),(1e+15,1e+15),(1e+20,1e+20),(1e+50,1e+50),(1e+150,1e+150); insert into t1 values(-10,-10),(1e-5,1e-5),(1e-10,1e-10),(1e-15,1e-15),(1e-20,1e-20),(1e-50,1e-50),(1e-150,1e-150); ---replace_result e-0 e- e+0 e+ select * from t1; drop table t1; diff --git a/mysql-test/t/update.test b/mysql-test/t/update.test index d0496b48c7a..5a49de248b1 100644 --- a/mysql-test/t/update.test +++ b/mysql-test/t/update.test @@ -287,4 +287,23 @@ update t1 set f1=1 where f1=3; update t2,t1 set f1=3,f2=3 where f1=f2 and f1=1; --disable_info drop table t1,t2; + + +# BUG#15935 +create table t1 (a int); +insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); +create table t2 (a int, filler1 char(200), filler2 char(200), key(a)); +insert into t2 select A.a + 10*B.a, 'filler','filler' from t1 A, t1 B; +flush status; +update t2 set a=3 where a=2; +show status like 'handler_read%'; +drop table t1, t2; + +# +# Bug #16510 Updating field named like '*name' caused server crash +# +create table t1(f1 int, `*f2` int); +insert into t1 values (1,1); +update t1 set `*f2`=1; +drop table t1; # End of 4.1 tests diff --git a/mysql-test/t/variables.test b/mysql-test/t/variables.test index df0c90ea563..9fc7f79d364 100644 --- a/mysql-test/t/variables.test +++ b/mysql-test/t/variables.test @@ -20,7 +20,6 @@ select @test, @`test`, @TEST, @`TEST`, @"teSt"; set @select=2,@t5=1.23456; select @`select`,@not_used; set @test_int=10,@test_double=1e-10,@test_string="abcdeghi",@test_string2="abcdefghij",@select=NULL; ---replace_result e-0 e- e+0 e+ select @test_int,@test_double,@test_string,@test_string2,@select; set @test_int="hello",@test_double="hello",@test_string="hello",@test_string2="hello"; select @test_int,@test_double,@test_string,@test_string2; diff --git a/ndb/include/mgmapi/mgmapi_config_parameters.h b/ndb/include/mgmapi/mgmapi_config_parameters.h index 41516b1c3e4..7c24c5d698d 100644 --- a/ndb/include/mgmapi/mgmapi_config_parameters.h +++ b/ndb/include/mgmapi/mgmapi_config_parameters.h @@ -85,6 +85,11 @@ #define CFG_DB_BACKUP_DATADIR 158 #define CFG_DB_MAX_OPEN_FILES 159 +#define CFG_DB_DISK_PAGE_BUFFER_MEMORY 160 /* used from 5.1 */ +#define CFG_DB_STRING_MEMORY 161 /* used from 5.1 */ +#define CFG_DB_INITIAL_OPEN_FILES 162 /* used from 5.1 */ + +#define CFG_DB_DATA_MEM_2 199 /* used in special build in 5.1 */ #define CFG_NODE_ARBIT_RANK 200 #define CFG_NODE_ARBIT_DELAY 201 diff --git a/ndb/test/ndbapi/testBlobs.cpp b/ndb/test/ndbapi/testBlobs.cpp index a88d7d21820..506ff188ff6 100644 --- a/ndb/test/ndbapi/testBlobs.cpp +++ b/ndb/test/ndbapi/testBlobs.cpp @@ -1483,13 +1483,16 @@ testperf() // insert char (one trans) { DBG("--- insert char ---"); + char b[20]; t1.on(); CHK((g_con = g_ndb->startTransaction()) != 0); for (Uint32 k = 0; k < g_opt.m_rowsperf; k++) { CHK((g_opr = g_con->getNdbOperation(tab.getName())) != 0); CHK(g_opr->insertTuple() == 0); CHK(g_opr->equal(cA, (char*)&k) == 0); - CHK(g_opr->setValue(cB, "b") == 0); + memset(b, 0x20, sizeof(b)); + b[0] = 'b'; + CHK(g_opr->setValue(cB, b) == 0); CHK(g_con->execute(NoCommit) == 0); } t1.off(g_opt.m_rowsperf); @@ -1526,12 +1529,15 @@ testperf() { DBG("--- insert for read test ---"); unsigned n = 0; + char b[20]; CHK((g_con = g_ndb->startTransaction()) != 0); for (Uint32 k = 0; k < g_opt.m_rowsperf; k++) { CHK((g_opr = g_con->getNdbOperation(tab.getName())) != 0); CHK(g_opr->insertTuple() == 0); CHK(g_opr->equal(cA, (char*)&k) == 0); - CHK(g_opr->setValue(cB, "b") == 0); + memset(b, 0x20, sizeof(b)); + b[0] = 'b'; + CHK(g_opr->setValue(cB, b) == 0); CHK((g_bh1 = g_opr->getBlobHandle(cC)) != 0); CHK((g_bh1->setValue("c", 1) == 0)); if (++n == g_opt.m_batch) { @@ -1565,7 +1571,7 @@ testperf() a = (Uint32)-1; b[0] = 0; CHK(g_con->execute(NoCommit) == 0); - CHK(a == k && strcmp(b, "b") == 0); + CHK(a == k && b[0] == 'b'); } CHK(g_con->execute(Commit) == 0); t1.off(g_opt.m_rowsperf); @@ -1591,7 +1597,7 @@ testperf() CHK(g_con->execute(NoCommit) == 0); Uint32 m = 20; CHK(g_bh1->readData(c, m) == 0); - CHK(a == k && m == 1 && strcmp(c, "c") == 0); + CHK(a == k && m == 1 && c[0] == 'c'); } CHK(g_con->execute(Commit) == 0); t2.off(g_opt.m_rowsperf); @@ -1623,7 +1629,7 @@ testperf() CHK((ret = g_ops->nextResult(true)) == 0 || ret == 1); if (ret == 1) break; - CHK(a < g_opt.m_rowsperf && strcmp(b, "b") == 0); + CHK(a < g_opt.m_rowsperf && b[0] == 'b'); n++; } CHK(n == g_opt.m_rowsperf); @@ -1654,7 +1660,7 @@ testperf() break; Uint32 m = 20; CHK(g_bh1->readData(c, m) == 0); - CHK(a < g_opt.m_rowsperf && m == 1 && strcmp(c, "c") == 0); + CHK(a < g_opt.m_rowsperf && m == 1 && c[0] == 'c'); n++; } CHK(n == g_opt.m_rowsperf); diff --git a/sql/ha_heap.cc b/sql/ha_heap.cc index 98cc96db707..739569e305a 100644 --- a/sql/ha_heap.cc +++ b/sql/ha_heap.cc @@ -53,7 +53,7 @@ handlerton heap_hton= { ha_heap::ha_heap(TABLE *table_arg) :handler(&heap_hton, table_arg), file(0), records_changed(0), - key_stats_ok(0) + key_stat_version(0) {} @@ -104,7 +104,7 @@ int ha_heap::open(const char *name, int mode, uint test_if_locked) ha_heap::info(), which is always called before key statistics are used. */ - key_stats_ok= FALSE; + key_stat_version= file->s->key_stat_version-1; } return (file ? 0 : 1); } @@ -151,14 +151,21 @@ void ha_heap::update_key_stats() continue; if (key->algorithm != HA_KEY_ALG_BTREE) { - ha_rows hash_buckets= file->s->keydef[i].hash_buckets; - key->rec_per_key[key->key_parts-1]= - hash_buckets ? file->s->records/hash_buckets : 0; + if (key->flags & HA_NOSAME) + key->rec_per_key[key->key_parts-1]= 1; + else + { + ha_rows hash_buckets= file->s->keydef[i].hash_buckets; + uint no_records= hash_buckets ? file->s->records/hash_buckets : 2; + if (no_records < 2) + no_records= 2; + key->rec_per_key[key->key_parts-1]= no_records; + } } } records_changed= 0; /* At the end of update_key_stats() we can proudly claim they are OK. */ - key_stats_ok= TRUE; + key_stat_version= file->s->key_stat_version; } @@ -173,7 +180,13 @@ int ha_heap::write_row(byte * buf) res= heap_write(file,buf); if (!res && (++records_changed*HEAP_STATS_UPDATE_THRESHOLD > file->s->records)) - key_stats_ok= FALSE; + { + /* + We can perform this safely since only one writer at the time is + allowed on the table. + */ + file->s->key_stat_version++; + } return res; } @@ -186,7 +199,13 @@ int ha_heap::update_row(const byte * old_data, byte * new_data) res= heap_update(file,old_data,new_data); if (!res && ++records_changed*HEAP_STATS_UPDATE_THRESHOLD > file->s->records) - key_stats_ok= FALSE; + { + /* + We can perform this safely since only one writer at the time is + allowed on the table. + */ + file->s->key_stat_version++; + } return res; } @@ -197,7 +216,13 @@ int ha_heap::delete_row(const byte * buf) res= heap_delete(file,buf); if (!res && table->s->tmp_table == NO_TMP_TABLE && ++records_changed*HEAP_STATS_UPDATE_THRESHOLD > file->s->records) - key_stats_ok= FALSE; + { + /* + We can perform this safely since only one writer at the time is + allowed on the table. + */ + file->s->key_stat_version++; + } return res; } @@ -324,7 +349,7 @@ void ha_heap::info(uint flag) have to update the key statistics. Hoping that a table lock is now in place. */ - if (! key_stats_ok) + if (key_stat_version != file->s->key_stat_version) update_key_stats(); } @@ -337,7 +362,13 @@ int ha_heap::delete_all_rows() { heap_clear(file); if (table->s->tmp_table == NO_TMP_TABLE) - key_stats_ok= FALSE; + { + /* + We can perform this safely since only one writer at the time is + allowed on the table. + */ + file->s->key_stat_version++; + } return 0; } @@ -497,8 +528,11 @@ ha_rows ha_heap::records_in_range(uint inx, key_range *min_key, max_key->flag != HA_READ_AFTER_KEY) return HA_POS_ERROR; // Can only use exact keys + if (records <= 1) + return records; + /* Assert that info() did run. We need current statistics here. */ - DBUG_ASSERT(key_stats_ok); + DBUG_ASSERT(key_stat_version); return key->rec_per_key[key->key_parts-1]; } diff --git a/sql/ha_heap.h b/sql/ha_heap.h index 7c4227e952c..e2816abf0b6 100644 --- a/sql/ha_heap.h +++ b/sql/ha_heap.h @@ -29,7 +29,7 @@ class ha_heap: public handler key_map btree_keys; /* number of records changed since last statistics update */ uint records_changed; - bool key_stats_ok; + uint key_stat_version; public: ha_heap(TABLE *table); ~ha_heap() {} diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 61449d3c671..17f25b49bcc 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -3023,9 +3023,9 @@ void Item_func_str_to_date::fix_length_and_dec() cached_field_type= MYSQL_TYPE_STRING; max_length= MAX_DATETIME_FULL_WIDTH*MY_CHARSET_BIN_MB_MAXLEN; cached_timestamp_type= MYSQL_TIMESTAMP_NONE; - if ((const_item= args[1]->const_item())) + format= args[1]->val_str(&format_str); + if (!args[1]->null_value && (const_item= args[1]->const_item())) { - format= args[1]->val_str(&format_str); cached_format_type= get_date_time_result_type(format->ptr(), format->length()); switch (cached_format_type) { diff --git a/sql/sql_class.cc b/sql/sql_class.cc index ca86c077a3a..b3709235d8b 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1816,11 +1816,14 @@ bool select_dumpvar::send_eof() void TMP_TABLE_PARAM::init() { + DBUG_ENTER("TMP_TABLE_PARAM::init"); + DBUG_PRINT("enter", ("this: 0x%lx", (ulong)this)); field_count= sum_func_count= func_count= hidden_field_count= 0; group_parts= group_length= group_null_parts= 0; quick_group= 1; table_charset= 0; precomputed_group_by= 0; + DBUG_VOID_RETURN; } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index f23260e6bf8..4ac2bb91af5 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -6016,6 +6016,20 @@ void JOIN::cleanup(bool full) problems in free_elements() as some of the elements are then deleted. */ tmp_table_param.copy_funcs.empty(); + /* + If we have tmp_join and 'this' JOIN is not tmp_join and + tmp_table_param.copy_field's of them are equal then we have to remove + pointer to tmp_table_param.copy_field from tmp_join, because it qill + be removed in tmp_table_param.cleanup(). + */ + if (tmp_join && + tmp_join != this && + tmp_join->tmp_table_param.copy_field == + tmp_table_param.copy_field) + { + tmp_join->tmp_table_param.copy_field= + tmp_join->tmp_table_param.save_copy_field= 0; + } tmp_table_param.cleanup(); } DBUG_VOID_RETURN; diff --git a/sql/sql_select.h b/sql/sql_select.h index 4aa238641e5..9046398faaf 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -285,7 +285,14 @@ class JOIN :public Sql_alloc { init(thd_arg, fields_arg, select_options_arg, result_arg); } - + + JOIN(JOIN &join) + :fields_list(join.fields_list) + { + init(join.thd, join.fields_list, join.select_options, + join.result); + } + void init(THD *thd_arg, List &fields_arg, ulonglong select_options_arg, select_result *result_arg) { @@ -332,7 +339,7 @@ class JOIN :public Sql_alloc all_fields= fields_arg; fields_list= fields_arg; bzero((char*) &keyuse,sizeof(keyuse)); - tmp_table_param.copy_field=0; + tmp_table_param.init(); tmp_table_param.end_write_records= HA_POS_ERROR; rollup.state= ROLLUP::STATE_NONE; } diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 2ff8a4bc244..d319167b61d 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -308,7 +308,6 @@ int mysql_update(THD *thd, SORT_FIELD *sortorder; ha_rows examined_rows; - used_index= MAX_KEY; // For call to init_read_record() table->sort.io_cache = (IO_CACHE *) my_malloc(sizeof(IO_CACHE), MYF(MY_FAE | MY_ZEROFILL)); if (!(sortorder=make_unireg_sortorder(order, &length)) || @@ -339,10 +338,21 @@ int mysql_update(THD *thd, if (open_cached_file(&tempfile, mysql_tmpdir,TEMP_PREFIX, DISK_BUFFER_SIZE, MYF(MY_WME))) goto err; - + /* If quick select is used, initialize it before retrieving rows. */ if (select && select->quick && select->quick->reset()) goto err; + + /* + When we get here, we have one of the following options: + A. used_index == MAX_KEY + This means we should use full table scan, and start it with + init_read_record call + B. used_index != MAX_KEY + B.1 quick select is used, start the scan with init_read_record + B.2 quick select is not used, this is full index scan (with LIMIT) + Full index scan must be started with init_read_record_idx + */ if (used_index == MAX_KEY || (select && select->quick)) init_read_record(&info,thd,table,select,0,1); else diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index e68e9c61000..f32fd752d77 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -14697,6 +14697,38 @@ static void test_opt_reconnect() mysql_close(lmysql); } + +static void test_bug12744() +{ + MYSQL_STMT *prep_stmt = NULL; + int rc; + myheader("test_bug12744"); + + prep_stmt= mysql_stmt_init(mysql); + rc= mysql_stmt_prepare(prep_stmt, "SELECT 1", 8); + DIE_UNLESS(rc==0); + + rc= mysql_kill(mysql, mysql_thread_id(mysql)); + DIE_UNLESS(rc==0); + + if (rc= mysql_stmt_execute(prep_stmt)) + { + if (rc= mysql_stmt_reset(prep_stmt)) + printf("OK!\n"); + else + { + printf("Error!"); + DIE_UNLESS(1==0); + } + } + else + { + fprintf(stderr, "expected error but no error occured\n"); + DIE_UNLESS(1==0); + } + rc= mysql_stmt_close(prep_stmt); +} + /* Bug #16144: mysql_stmt_attr_get type error */ static void test_bug16144() @@ -14711,6 +14743,7 @@ static void test_bug16144() mysql_stmt_attr_set(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, (const void*) &flag); mysql_stmt_attr_get(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, (void*) &flag); DIE_UNLESS(flag == flag_orig); + mysql_stmt_close(stmt); } @@ -15039,7 +15072,7 @@ static struct my_tests_st my_tests[]= { { "test_bug14845", test_bug14845 }, { "test_bug15510", test_bug15510 }, { "test_opt_reconnect", test_opt_reconnect }, - + { "test_bug12744", test_bug12744 }, { "test_bug16144", test_bug16144 }, { "test_bug15613", test_bug15613 }, { 0, 0 }