diff --git a/myisam/myisampack.c b/myisam/myisampack.c index b4b4169965d..eae75b07760 100644 --- a/myisam/myisampack.c +++ b/myisam/myisampack.c @@ -2050,7 +2050,7 @@ static int save_state(MI_INFO *isam_file,PACK_MRG_INFO *mrg,my_off_t new_length, share->state.dellink= HA_OFFSET_ERROR; share->state.split=(ha_rows) mrg->records; share->state.version=(ulong) time((time_t*) 0); - if (share->state.key_map != (1ULL << share->base.keys) - 1) + if (share->state.key_map != (ULL(1) << share->base.keys) - 1) { /* Some indexes are disabled, cannot use current key_file_length value diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index a416ba5c482..e1391a496c6 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -413,14 +413,40 @@ deallocate prepare stmt; create table t1 (a int); insert into t1 values (1),(2),(3); create table t2 select * from t1; -PREPARE my_stmt FROM 'create table t2 select * from t1'; +prepare stmt FROM 'create table t2 select * from t1'; drop table t2; -execute my_stmt; +execute stmt; drop table t2; -execute my_stmt; -execute my_stmt; +execute stmt; +execute stmt; ERROR 42S01: Table 't2' already exists drop table t2; -execute my_stmt; +execute stmt; drop table t1,t2; -deallocate prepare my_stmt; +deallocate prepare stmt; +create table t1 (a int); +insert into t1 (a) values (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); +prepare stmt from "select sql_calc_found_rows * from t1 limit 2"; +execute stmt; +a +1 +2 +select found_rows(); +found_rows() +10 +execute stmt; +a +1 +2 +select found_rows(); +found_rows() +10 +execute stmt; +a +1 +2 +select found_rows(); +found_rows() +10 +deallocate prepare stmt; +drop table t1; diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 8bcf7f9bff2..04c5f685f58 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -176,17 +176,17 @@ a b a b 1 7 2 7 -3 8 4 8 +3 8 explain extended (select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) union (select * from t4 where t4.b=(select max(t2.a)*4 from t2) order by a); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where 2 SUBQUERY t3 ALL NULL NULL NULL NULL 3 Using filesort -3 UNION t4 ALL NULL NULL NULL NULL 3 Using where; Using filesort +3 UNION t4 ALL NULL NULL NULL NULL 3 Using where 4 SUBQUERY t2 ALL NULL NULL NULL NULL 2 NULL UNION RESULT ALL NULL NULL NULL NULL NULL Warnings: -Note 1003 (select test.t2.a AS `a`,test.t2.b AS `b` from test.t2 where (test.t2.b = (select test.t3.a AS `a` from test.t3 order by test.t3.a desc limit 1))) union (select test.t4.a AS `a`,test.t4.b AS `b` from test.t4 where (test.t4.b = (select (max(test.t2.a) * 4) AS `max(t2.a)*4` from test.t2)) order by test.t4.a) +Note 1003 (select test.t2.a AS `a`,test.t2.b AS `b` from test.t2 where (test.t2.b = (select test.t3.a AS `a` from test.t3 order by test.t3.a desc limit 1))) union (select test.t4.a AS `a`,test.t4.b AS `b` from test.t4 where (test.t4.b = (select (max(test.t2.a) * 4) AS `max(t2.a)*4` from test.t2)) order by a) select (select a from t3 where a &list) int mysql_revoke_all(THD *thd, List &list) { - uint counter; + uint counter, revoked; int result; ACL_DB *acl_db; TABLE_LIST tables[4]; @@ -3624,83 +3624,96 @@ int mysql_revoke_all(THD *thd, List &list) } /* Remove db access privileges */ - for (counter= 0 ; counter < acl_dbs.elements ; ) + /* + Because acl_dbs and column_priv_hash shrink and may re-order + as privileges are removed, removal occurs in a repeated loop + until no more privileges are revoked. + */ + do { - const char *user,*host; - - acl_db=dynamic_element(&acl_dbs,counter,ACL_DB*); - if (!(user=acl_db->user)) - user= ""; - if (!(host=acl_db->host.hostname)) - host= ""; - - if (!strcmp(lex_user->user.str,user) && - !my_strcasecmp(system_charset_info, lex_user->host.str, host)) + for (counter= 0, revoked= 0 ; counter < acl_dbs.elements ; ) { - if (!replace_db_table(tables[1].table, acl_db->db, *lex_user, ~0, 1)) - { - /* - Don't increment counter as replace_db_table deleted the - current element in acl_db's and shifted the higher elements down - */ - continue; - } - result= -1; // Something went wrong + const char *user,*host; + + acl_db=dynamic_element(&acl_dbs,counter,ACL_DB*); + if (!(user=acl_db->user)) + user= ""; + if (!(host=acl_db->host.hostname)) + host= ""; + + if (!strcmp(lex_user->user.str,user) && + !my_strcasecmp(system_charset_info, lex_user->host.str, host)) + { + if (!replace_db_table(tables[1].table, acl_db->db, *lex_user, ~0, 1)) + { + /* + Don't increment counter as replace_db_table deleted the + current element in acl_dbs. + */ + revoked= 1; + continue; + } + result= -1; // Something went wrong + } + counter++; } - counter++; - } + } while (revoked); /* Remove column access */ - for (counter= 0 ; counter < column_priv_hash.records ; ) + do { - const char *user,*host; - GRANT_TABLE *grant_table= (GRANT_TABLE*) hash_element(&column_priv_hash, - counter); - if (!(user=grant_table->user)) - user= ""; - if (!(host=grant_table->host)) - host= ""; - - if (!strcmp(lex_user->user.str,user) && - !my_strcasecmp(system_charset_info, lex_user->host.str, host)) + for (counter= 0, revoked= 0 ; counter < column_priv_hash.records ; ) { - if (replace_table_table(thd,grant_table,tables[2].table,*lex_user, - grant_table->db, - grant_table->tname, - ~0, 0, 1)) + const char *user,*host; + GRANT_TABLE *grant_table= (GRANT_TABLE*)hash_element(&column_priv_hash, + counter); + if (!(user=grant_table->user)) + user= ""; + if (!(host=grant_table->host)) + host= ""; + + if (!strcmp(lex_user->user.str,user) && + !my_strcasecmp(system_charset_info, lex_user->host.str, host)) { - result= -1; - continue; - } - else - { - if (!grant_table->cols) - continue; - List columns; - if (replace_column_table(grant_table,tables[3].table, *lex_user, - columns, - grant_table->db, - grant_table->tname, - ~0, 1)) - result= -1; - /* - Safer to do continue here as replace_table_table changed - column_priv_hash and we want to test the current element - */ - continue; + if (replace_table_table(thd,grant_table,tables[2].table,*lex_user, + grant_table->db, + grant_table->tname, + ~0, 0, 1)) + { + result= -1; + } + else + { + if (!grant_table->cols) + { + revoked= 1; + continue; + } + List columns; + if (!replace_column_table(grant_table,tables[3].table, *lex_user, + columns, + grant_table->db, + grant_table->tname, + ~0, 1)) + { + revoked= 1; + continue; + } + result= -1; + } } + counter++; } - counter++; - } + } while (revoked); } - + VOID(pthread_mutex_unlock(&acl_cache->lock)); rw_unlock(&LOCK_grant); close_thread_tables(thd); - + if (result) my_error(ER_REVOKE_GRANTS, MYF(0)); - + DBUG_RETURN(result); } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 28c5c9e0069..a01b8c895c3 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1563,6 +1563,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, case COM_CREATE_DB: // QQ: To be removed { char *db=thd->strdup(packet), *alias; + HA_CREATE_INFO create_info; statistic_increment(com_stat[SQLCOM_CREATE_DB],&LOCK_status); // null test to handle EOM @@ -1574,8 +1575,9 @@ bool dispatch_command(enum enum_server_command command, THD *thd, if (check_access(thd,CREATE_ACL,db,0,1,0)) break; mysql_log.write(thd,command,packet); + bzero(&create_info, sizeof(create_info)); if (mysql_create_db(thd, (lower_case_table_names == 2 ? alias : db), - 0, 0) < 0) + &create_info, 0) < 0) send_error(thd, thd->killed ? ER_SERVER_SHUTDOWN : 0); break; } diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 44004e1238d..f9a1908355b 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -147,6 +147,7 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, SELECT_LEX *lex_select_save= thd_arg->lex->current_select; SELECT_LEX *sl, *first_select; select_result *tmp_result; + bool is_union; DBUG_ENTER("st_select_lex_unit::prepare"); describe= test(additional_options & SELECT_DESCRIBE); @@ -183,10 +184,11 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, thd_arg->lex->current_select= sl= first_select= first_select_in_union(); found_rows_for_union= first_select->options & OPTION_FOUND_ROWS; + is_union= test(first_select->next_select()); /* Global option */ - if (first_select->next_select()) + if (is_union) { if (!(tmp_result= union_result= new select_union(0))) goto err; @@ -195,14 +197,11 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, tmp_result= sel_result; } else - { tmp_result= sel_result; - // single select should be processed like select in p[arantses - first_select->braces= 1; - } for (;sl; sl= sl->next_select()) { + bool can_skip_order_by; sl->options|= SELECT_NO_UNLOCK; JOIN *join= new JOIN(thd_arg, sl->item_list, sl->options | thd_arg->options | additional_options, @@ -217,14 +216,17 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, select_limit_cnt= HA_POS_ERROR; // no limit if (select_limit_cnt == HA_POS_ERROR || sl->braces) sl->options&= ~OPTION_FOUND_ROWS; - + + can_skip_order_by= is_union && + (!sl->braces || select_limit_cnt == HA_POS_ERROR); + res= join->prepare(&sl->ref_pointer_array, (TABLE_LIST*) sl->table_list.first, sl->with_wild, sl->where, - ((sl->braces) ? sl->order_list.elements : 0) + - sl->group_list.elements, - (sl->braces) ? - (ORDER *)sl->order_list.first : (ORDER *) 0, + (can_skip_order_by ? 0 : sl->order_list.elements) + + sl->group_list.elements, + can_skip_order_by ? + (ORDER*) 0 : (ORDER *)sl->order_list.first, (ORDER*) sl->group_list.first, sl->having, (ORDER*) NULL, @@ -264,10 +266,8 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, } } - if (first_select->next_select()) + if (is_union) { - /* This is not a single select */ - /* Check that it was possible to aggregate all collations together for UNION. @@ -364,8 +364,6 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, } } } - else - first_select->braces= 0; // remove our changes thd_arg->lex->current_select= lex_select_save; diff --git a/tests/client_test.c b/tests/client_test.c index 130e0bc3b4f..31244395132 100644 --- a/tests/client_test.c +++ b/tests/client_test.c @@ -10688,6 +10688,31 @@ static void test_bug6046() } +/* + Altough mysql_create_db(), mysql_rm_db() are deprecated since 4.0 they + should not crash server and should not hang in case of errors. + + Since those functions can't be seen in modern API (unless client library + was compiled with USE_OLD_FUNCTIONS define) we use simple_command() macro. +*/ +static void test_bug6081() +{ + int rc; + myheader("test_bug6081"); + + rc= simple_command(mysql, COM_DROP_DB, current_db, + (ulong)strlen(current_db), 0); + myquery(rc); + rc= simple_command(mysql, COM_DROP_DB, current_db, + (ulong)strlen(current_db), 0); + myquery_r(rc); + rc= simple_command(mysql, COM_CREATE_DB, current_db, + (ulong)strlen(current_db), 0); + myquery(rc); + rc= simple_command(mysql, COM_CREATE_DB, current_db, + (ulong)strlen(current_db), 0); + myquery_r(rc); +} /* @@ -11004,6 +11029,7 @@ int main(int argc, char **argv) test_bug6058(); /* check support for 0000-00-00 dates */ test_bug6059(); /* correct metadata for SELECT ... INTO OUTFILE */ test_bug6046(); /* NATURAL JOIN transformation works in PS */ + test_bug6081(); /* test of mysql_create_db()/mysql_rm_db() */ /* XXX: PLEASE RUN THIS PROGRAM UNDER VALGRIND AND VERIFY THAT YOUR TEST DOESN'T CONTAIN WARNINGS/ERRORS BEFORE YOU PUSH.