diff --git a/mysql-test/r/func_default.result b/mysql-test/r/func_default.result index c7483027322..5742ddd102b 100644 --- a/mysql-test/r/func_default.result +++ b/mysql-test/r/func_default.result @@ -16,3 +16,8 @@ explain select * from t1 where str <> default(str); id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 system NULL NULL NULL NULL 1 drop table t1; +CREATE TABLE t1 (id int(11), s varchar(20)); +INSERT INTO t1 VALUES (1, 'one'), (2, 'two'), (3, 'three'); +SELECT s, 32 AS mi FROM t1 GROUP BY s HAVING DEFAULT(mi) IS NULL; +ERROR HY000: Field 'mi' doesn't have a default value +DROP TABLE t1; diff --git a/mysql-test/r/group_min_max.result b/mysql-test/r/group_min_max.result index a43f1ee88a6..13eb2690e86 100644 --- a/mysql-test/r/group_min_max.result +++ b/mysql-test/r/group_min_max.result @@ -1954,6 +1954,24 @@ id select_type table type possible_keys key key_len ref rows Extra explain select sum(ord(a1)) from t1 where (a1 > 'a') group by a1,a2,b; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 index idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 163 NULL 128 Using where; Using index +explain select a1 from t1 where a2 = 'b' group by a1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range NULL idx_t1_1 130 NULL 5 Using where; Using index for group-by +select a1 from t1 where a2 = 'b' group by a1; +a1 +a +b +c +d +explain select distinct a1 from t1 where a2 = 'b'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range NULL idx_t1_1 130 NULL 5 Using where; Using index for group-by +select distinct a1 from t1 where a2 = 'b'; +a1 +a +b +c +d drop table t1; drop table t2; drop table t3; diff --git a/mysql-test/r/lock_multi.result b/mysql-test/r/lock_multi.result index 9eedbf50064..73e3a9d32e3 100644 --- a/mysql-test/r/lock_multi.result +++ b/mysql-test/r/lock_multi.result @@ -36,3 +36,10 @@ lock table t1 write, t2 write; drop table t2; ERROR 42S02: Table 'test.t2' doesn't exist drop table t1; +create table t1(a int); +lock tables t1 write; +show columns from t1; +Field Type Null Key Default Extra +a int(11) YES NULL +unlock tables; +drop table t1; diff --git a/mysql-test/r/mysql.result b/mysql-test/r/mysql.result index feb0b2348cd..dbb47152926 100644 --- a/mysql-test/r/mysql.result +++ b/mysql-test/r/mysql.result @@ -48,3 +48,9 @@ Test 'go' command g a 1 drop table t1; +create table t1(a int); +lock tables t1 write; +database() +test +unlock tables; +drop table t1; diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result index f73c9b223fd..080bc4d1e0f 100644 --- a/mysql-test/r/mysqldump.result +++ b/mysql-test/r/mysqldump.result @@ -1,6 +1,7 @@ DROP TABLE IF EXISTS t1, `"t"1`, t1aa, t2, t2aa; drop database if exists mysqldump_test_db; -drop view if exists v1; +drop database if exists db1; +drop view if exists v1, v2; CREATE TABLE t1(a int); INSERT INTO t1 VALUES (1), (2); @@ -1422,3 +1423,51 @@ UNLOCK TABLES; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; DROP TABLE t1; +create database db1; +use db1; +CREATE TABLE t2 ( +a varchar(30) default NULL, +KEY a (a(5)) +); +INSERT INTO t2 VALUES ('alfred'); +INSERT INTO t2 VALUES ('angie'); +INSERT INTO t2 VALUES ('bingo'); +INSERT INTO t2 VALUES ('waffle'); +INSERT INTO t2 VALUES ('lemon'); +create view v2 as select * from t2 where a like 'a%' with check option; + +/*!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 */; +/*!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 `t2`; +CREATE TABLE `t2` ( + `a` varchar(30) default NULL, + KEY `a` (`a`(5)) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; + + +/*!40000 ALTER TABLE `t2` DISABLE KEYS */; +LOCK TABLES `t2` WRITE; +INSERT INTO `t2` VALUES ('alfred'),('angie'),('bingo'),('waffle'),('lemon'); +UNLOCK TABLES; +/*!40000 ALTER TABLE `t2` ENABLE KEYS */; +DROP TABLE IF EXISTS `v2`; +DROP VIEW IF EXISTS `v2`; +CREATE ALGORITHM=UNDEFINED VIEW `db1`.`v2` AS select `db1`.`t2`.`a` AS `a` from `db1`.`t2` where (`db1`.`t2`.`a` like _latin1'a%') WITH CASCADED CHECK OPTION; + +/*!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 t2; +drop view v2; +drop database db1; diff --git a/mysql-test/t/func_default.test b/mysql-test/t/func_default.test index 6ae9f088f92..af7ebcf588b 100644 --- a/mysql-test/t/func_default.test +++ b/mysql-test/t/func_default.test @@ -16,4 +16,14 @@ explain select * from t1 where str <> default(str); #show create table from t1; #insert into t2 select select default(str), default(strnull), default(intg), default(rel) from t1; -drop table t1; \ No newline at end of file +drop table t1; + +# +# Bug #11314 (HAVING DEFAULT() hangs) +# +CREATE TABLE t1 (id int(11), s varchar(20)); +INSERT INTO t1 VALUES (1, 'one'), (2, 'two'), (3, 'three'); +--error 1364 +SELECT s, 32 AS mi FROM t1 GROUP BY s HAVING DEFAULT(mi) IS NULL; +DROP TABLE t1; + diff --git a/mysql-test/t/group_min_max.test b/mysql-test/t/group_min_max.test index 76f959b983b..6731be615fd 100644 --- a/mysql-test/t/group_min_max.test +++ b/mysql-test/t/group_min_max.test @@ -482,7 +482,6 @@ select a1,a2,b from t2 where (a2 >= 'b') and (b = 'a') group by a1,a2,b; select a1,a2,b,c from t2 where (a2 >= 'b') and (b = 'a') and (c = 'i121') group by a1,a2,b; select a1,a2,b from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b; - -- -- DISTINCT queries -- @@ -526,6 +525,7 @@ select distinct a1,a1 from t1; select distinct a2,a1,a2,a1 from t1; select distinct t1.a1,t2.a1 from t1,t2; + -- -- DISTINCT queries with GROUP-BY -- @@ -641,6 +641,17 @@ explain select a1,a2,count(a2) from t1 group by a1,a2,b; explain select a1,a2,count(a2) from t1 where (a1 > 'a') group by a1,a2,b; explain select sum(ord(a1)) from t1 where (a1 > 'a') group by a1,a2,b; +# +# BUG#11044: DISTINCT or GROUP BY queries with equality predicates instead of MIN/MAX. +# + +explain select a1 from t1 where a2 = 'b' group by a1; +select a1 from t1 where a2 = 'b' group by a1; + +explain select distinct a1 from t1 where a2 = 'b'; +select distinct a1 from t1 where a2 = 'b'; + + drop table t1; drop table t2; drop table t3; diff --git a/mysql-test/t/lock_multi.test b/mysql-test/t/lock_multi.test index cbda47ac864..43cff90332b 100644 --- a/mysql-test/t/lock_multi.test +++ b/mysql-test/t/lock_multi.test @@ -94,3 +94,15 @@ connection reader; reap; connection locker; drop table t1; + + +# +# BUG#9998 - MySQL client hangs on USE "database" + +create table t1(a int); +lock tables t1 write; +connection reader; +show columns from t1; +connection locker; +unlock tables; +drop table t1; diff --git a/mysql-test/t/mysql.test b/mysql-test/t/mysql.test index d30e5b65d8e..c1d9813ea39 100644 --- a/mysql-test/t/mysql.test +++ b/mysql-test/t/mysql.test @@ -30,5 +30,14 @@ select "Test 'go' command(vertical output) \G" as " "; select "Test 'go' command \g" as " "; --exec $MYSQL test -e 'select * from t1\g' --enable_query_log - drop table t1; + +# +# BUG9998 - MySQL client hangs on USE "database" +# +create table t1(a int); +lock tables t1 write; +--exec $MYSQL -e 'use test; select database();' +unlock tables; +drop table t1; + diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test index 7a39fbdf5f6..f842b8f4d0b 100644 --- a/mysql-test/t/mysqldump.test +++ b/mysql-test/t/mysqldump.test @@ -4,7 +4,8 @@ --disable_warnings DROP TABLE IF EXISTS t1, `"t"1`, t1aa, t2, t2aa; drop database if exists mysqldump_test_db; -drop view if exists v1; +drop database if exists db1; +drop view if exists v1, v2; --enable_warnings # XML output @@ -563,3 +564,27 @@ 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) +# + +create database db1; +use db1; + +CREATE TABLE t2 ( + a varchar(30) default NULL, + KEY a (a(5)) +); + +INSERT INTO t2 VALUES ('alfred'); +INSERT INTO t2 VALUES ('angie'); +INSERT INTO t2 VALUES ('bingo'); +INSERT INTO t2 VALUES ('waffle'); +INSERT INTO t2 VALUES ('lemon'); +create view v2 as select * from t2 where a like 'a%' with check option; +--exec $MYSQL_DUMP --skip-comments db1 +drop table t2; +drop view v2; +drop database db1; diff --git a/sql/item.cc b/sql/item.cc index 0e68ba48118..8f893b5572c 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -4448,6 +4448,7 @@ bool Item_default_value::fix_fields(THD *thd, struct st_table_list *table_list, Item **items) { + Item *real_arg; Item_field *field_arg; Field *def_field; DBUG_ASSERT(fixed == 0); @@ -4459,17 +4460,15 @@ bool Item_default_value::fix_fields(THD *thd, } if (!arg->fixed && arg->fix_fields(thd, table_list, &arg)) return TRUE; - - if (arg->type() == REF_ITEM) + + real_arg= arg->real_item(); + if (real_arg->type() != FIELD_ITEM) { - Item_ref *ref= (Item_ref *)arg; - if (ref->ref[0]->type() != FIELD_ITEM) - { - return TRUE; - } - arg= ref->ref[0]; + my_error(ER_NO_DEFAULT_FOR_FIELD, MYF(0), arg->name); + return TRUE; } - field_arg= (Item_field *)arg; + + field_arg= (Item_field *)real_arg; if (field_arg->field->flags & NO_DEFAULT_VALUE_FLAG) { my_error(ER_NO_DEFAULT_FOR_FIELD, MYF(0), field_arg->field->field_name); diff --git a/sql/item.h b/sql/item.h index 1fe90a41e3a..2629f94a903 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1352,7 +1352,13 @@ public: { (*ref)->save_in_field(result_field, no_conversions); } - Item *real_item() { return *ref; } + Item *real_item() { + Item *item= this; + do + item= *((Item_ref *)item)->ref; + while (item->type() == Item::REF_ITEM); + return item; + } bool walk(Item_processor processor, byte *arg) { return (*ref)->walk(processor, arg); } void print(String *str); diff --git a/sql/item_func.cc b/sql/item_func.cc index 91defd7f0ee..e9f35f5a2e8 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -879,11 +879,11 @@ longlong Item_func_numhybrid::val_int() return (longlong)real_op(); case STRING_RESULT: { - char *end_not_used; int err_not_used; String *res= str_op(&str_value); + char *end= (char*) res->ptr() + res->length(); CHARSET_INFO *cs= str_value.charset(); - return (res ? (*(cs->cset->strtoll10))(cs, res->ptr(), &end_not_used, + return (res ? (*(cs->cset->strtoll10))(cs, res->ptr(), &end, &err_not_used) : 0); } default: diff --git a/sql/opt_range.cc b/sql/opt_range.cc index da359b0aebd..0a9f117a97b 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -7617,8 +7617,8 @@ void cost_group_min_max(TABLE* table, KEY *index_info, uint used_key_parts, *records= num_groups; DBUG_PRINT("info", - ("records=%u, keys/block=%u, keys/group=%u, records=%u, blocks=%u", - table_records, keys_per_block, keys_per_group, records, + ("table rows=%u, keys/block=%u, keys/group=%u, result rows=%u, blocks=%u", + table_records, keys_per_block, keys_per_group, *records, num_blocks)); DBUG_VOID_RETURN; } @@ -8125,6 +8125,15 @@ int QUICK_GROUP_MIN_MAX_SELECT::get_next() DBUG_ASSERT((have_max && !have_min) || (have_max && have_min && (max_res == 0))); } + /* + If this is a just a GROUP BY or DISTINCT without MIN or MAX and there + are equality predicates for the key parts after the group, find the + first sub-group with the extended prefix. + */ + if (!have_min && !have_max && key_infix_len > 0) + result= file->index_read(record, group_prefix, real_prefix_len, + HA_READ_KEY_EXACT); + result= have_min ? min_res : have_max ? max_res : result; } while (result == HA_ERR_KEY_NOT_FOUND && is_last_prefix != 0); @@ -8151,9 +8160,8 @@ int QUICK_GROUP_MIN_MAX_SELECT::get_next() QUICK_GROUP_MIN_MAX_SELECT::next_min() DESCRIPTION - Load the prefix of the next group into group_prefix and find the minimal - key within this group such that the key satisfies the query conditions and - NULL semantics. The found key is loaded into this->record. + Find the minimal key within this group such that the key satisfies the query + conditions and NULL semantics. The found key is loaded into this->record. IMPLEMENTATION Depending on the values of min_max_ranges.elements, key_infix_len, and @@ -8237,9 +8245,7 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_min() QUICK_GROUP_MIN_MAX_SELECT::next_max() DESCRIPTION - If there was no previous next_min call to determine the next group prefix, - then load the next prefix into group_prefix, then lookup the maximal key of - the group, and store it into this->record. + Lookup the maximal key of the group, and store it into this->record. RETURN 0 on success diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 4f0776d42a9..ddbc2908d56 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -7953,6 +7953,19 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, modify_item ? (Item_field*) item : NULL, convert_blob_length); } + case Item::REF_ITEM: + if ( ((Item_ref*)item)->real_item()->type() == Item::FIELD_ITEM) + { + Item_field *field= (Item_field*) *((Item_ref*)item)->ref; + Field *new_field= create_tmp_field_from_field(thd, + (*from_field= field->field), + item->name, table, + NULL, + convert_blob_length); + if (modify_item) + item->set_result_field(new_field); + return new_field; + } case Item::FUNC_ITEM: case Item::COND_ITEM: case Item::FIELD_AVG_ITEM: @@ -7964,7 +7977,6 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, case Item::REAL_ITEM: case Item::DECIMAL_ITEM: case Item::STRING_ITEM: - case Item::REF_ITEM: case Item::NULL_ITEM: case Item::VARBIN_ITEM: return create_tmp_field_from_item(thd, item, table, copy_func, modify_item, diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 1e34f32184a..68c6d1a8030 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -348,7 +348,7 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list) table_list->table_name)); /* Only one table for now, but VIEW can involve several tables */ - if (open_and_lock_tables(thd, table_list)) + if (open_normal_and_derived_tables(thd, table_list)) { DBUG_RETURN(TRUE); } @@ -540,8 +540,7 @@ mysqld_list_fields(THD *thd, TABLE_LIST *table_list, const char *wild) DBUG_ENTER("mysqld_list_fields"); DBUG_PRINT("enter",("table: %s",table_list->table_name)); - table_list->lock_type= TL_UNLOCK; - if (open_and_lock_tables(thd, table_list)) + if (open_normal_and_derived_tables(thd, table_list)) DBUG_VOID_RETURN; table= table_list->table; @@ -1945,7 +1944,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) bool res; lex->all_selects_list= lsel; - res= open_and_lock_tables(thd, show_table_list); + res= open_normal_and_derived_tables(thd, show_table_list); if (schema_table->process_table(thd, show_table_list, table, res, show_table_list->db, show_table_list->alias)) @@ -2050,7 +2049,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) show_table_list->lock_type= lock_type; lex->all_selects_list= &sel; lex->derived_tables= 0; - res= open_and_lock_tables(thd, show_table_list); + res= open_normal_and_derived_tables(thd, show_table_list); if (schema_table->process_table(thd, show_table_list, table, res, base_name, show_table_list->alias)) diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index b6ca4996c70..fb18c83b30e 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -13145,6 +13145,48 @@ static void test_bug9643() myquery(rc); } +/* + Bug#11111: fetch from view returns wrong data +*/ + +static void test_bug11111() +{ + MYSQL_STMT *stmt; + MYSQL_BIND bind[2]; + char buf[2][20]; + long len[2]; + int i; + const char * query = "SELECT DISTINCT f1,ff2 FROM v1"; + + mysql_query(mysql, "drop table if exists t1, t2, v1"); + mysql_query(mysql, "create table t1 (f1 int, f2 int)"); + mysql_query(mysql, "create table t2 (ff1 int, ff2 int)"); + mysql_query(mysql, "create view v1 as select * from t1, t2 where f1=ff1"); + mysql_query(mysql, "insert into t1 values (1,1), (2,2), (3,3)"); + mysql_query(mysql, "insert into t2 values (1,1), (2,2), (3,3)"); + + stmt = mysql_stmt_init(mysql); + + mysql_stmt_prepare(stmt, query, strlen(query)); + mysql_stmt_execute(stmt); + + for (i=0; i < 2; i++) { + memset(&bind[i], '\0', sizeof(MYSQL_BIND)); + bind[i].buffer_type= MYSQL_TYPE_STRING; + bind[i].buffer= (gptr *)&buf[i]; + bind[i].buffer_length= 20; + bind[i].length= &len[i]; + } + + if (mysql_stmt_bind_result(stmt, bind)) + printf("Error: %s\n", mysql_stmt_error(stmt)); + + mysql_stmt_fetch(stmt); + DIE_UNLESS(!strcmp(buf[1],"1")); + mysql_stmt_close(stmt); + mysql_query(mysql, "drop table t1, t2, v1"); +} + /* Check that proper cleanups are done for prepared statement when fetching thorugh a cursor. @@ -13439,6 +13481,7 @@ static struct my_tests_st my_tests[]= { { "test_bug9478", test_bug9478 }, { "test_bug9643", test_bug9643 }, { "test_bug10729", test_bug10729 }, + { "test_bug11111", test_bug11111 }, { 0, 0 } };