diff --git a/mysql-test/r/events.result b/mysql-test/r/events.result index f7b28056c1a..2ab2dd0076c 100644 --- a/mysql-test/r/events.result +++ b/mysql-test/r/events.result @@ -23,6 +23,7 @@ DROP EVENT e_x2; DROP DATABASE db_x; DROP USER pauline@localhost; USE events_test; +SET GLOBAL event_scheduler=0; drop event if exists event1; Warnings: Note 1305 Event event1 does not exist @@ -43,6 +44,14 @@ select db, name, body, status, interval_field, interval_value from mysql.event; db name body status interval_field interval_value events_test e_43 set @a = 4 ENABLED SECOND 1 drop event e_43; +"Let's check whether we can use non-qualified names" +create table non_qualif(a int); +create event non_qualif_ev on schedule every 10 minute do insert into non_qualif values (800219); +select * from non_qualif; +a +800219 +drop event non_qualif_ev; +drop table non_qualif; set global event_scheduler = 0; create table t_event3 (a int, b float); drop event if exists event3; @@ -374,7 +383,6 @@ show processlist; Id User Host db Command Time State Info # root localhost events_test Query # NULL show processlist # event_scheduler connecting host NULL Connect # Sleeping NULL -# root localhost events_test Connect # User lock select get_lock("test_lock2_1", 20) "Release the lock so the child process should finish. Hence the scheduler also" select release_lock("test_lock2_1"); release_lock("test_lock2_1") diff --git a/mysql-test/t/events.test b/mysql-test/t/events.test index 2755d4ec02e..6cad9991c44 100644 --- a/mysql-test/t/events.test +++ b/mysql-test/t/events.test @@ -28,11 +28,11 @@ connection default; DROP DATABASE db_x; DROP USER pauline@localhost; USE events_test; ---sleep 1 # # END: BUG #17289 Events: missing privilege check for drop database # - +SET GLOBAL event_scheduler=0; +--sleep 1 drop event if exists event1; create event event1 on schedule every 15 minute starts now() ends date_add(now(), interval 5 hour) DO begin end; alter event event1 rename to event2 enable; @@ -56,6 +56,14 @@ alter event e_43 do alter event e_43 do set @a = 4; select db, name, body, status, interval_field, interval_value from mysql.event; drop event e_43; --sleep 1 + +--echo "Let's check whether we can use non-qualified names" +create table non_qualif(a int); +create event non_qualif_ev on schedule every 10 minute do insert into non_qualif values (800219); +--sleep 2 +select * from non_qualif; +drop event non_qualif_ev; +drop table non_qualif; set global event_scheduler = 0; create table t_event3 (a int, b float); diff --git a/sql/event.cc b/sql/event.cc index 76d802b9ac0..d9e71a263b8 100644 --- a/sql/event.cc +++ b/sql/event.cc @@ -1272,7 +1272,7 @@ int db_drop_event(THD *thd, event_timed *et, bool drop_if_exists, goto done; } - if (!(ret= evex_db_find_event_aux(thd, et->dbname,et->name,et->definer,table))) + if (!(ret= evex_db_find_event_aux(thd, et, table))) { if ((ret= table->file->ha_delete_row(table->record[0]))) { @@ -1452,7 +1452,7 @@ evex_drop_db_events(THD *thd, char *db) READ_RECORD read_record_info; MYSQL_LOCK *lock; int ret= 0; - int i; + uint i; LEX_STRING db_lex= {db, strlen(db)}; DBUG_ENTER("evex_drop_db_events"); diff --git a/sql/event.h b/sql/event.h index f6e1ecd3188..6df6267abc4 100644 --- a/sql/event.h +++ b/sql/event.h @@ -247,7 +247,8 @@ public: } protected: bool - change_security_context(THD *thd, Security_context **backup); + change_security_context(THD *thd, Security_context *s_ctx, + Security_context **backup); void restore_security_context(THD *thd, Security_context *backup); diff --git a/sql/event_timed.cc b/sql/event_timed.cc index d76a9777d4a..cb0c0167a54 100644 --- a/sql/event_timed.cc +++ b/sql/event_timed.cc @@ -412,21 +412,30 @@ event_timed::init_definer(THD *thd) { DBUG_ENTER("event_timed::init_definer"); + DBUG_PRINT("info",("init definer_user thd->mem_root=0x%lx " + "thd->sec_ctx->priv_user=0x%lx", thd->mem_root, + thd->security_ctx->priv_user)); definer_user.str= strdup_root(thd->mem_root, thd->security_ctx->priv_user); definer_user.length= strlen(thd->security_ctx->priv_user); + DBUG_PRINT("info",("init definer_host thd->s_c->priv_host=0x%lx", + thd->security_ctx->priv_host)); definer_host.str= strdup_root(thd->mem_root, thd->security_ctx->priv_host); definer_host.length= strlen(thd->security_ctx->priv_host); + DBUG_PRINT("info",("init definer as whole")); definer.length= definer_user.length + definer_host.length + 1; definer.str= alloc_root(thd->mem_root, definer.length + 1); + DBUG_PRINT("info",("copy the user")); memcpy(definer.str, definer_user.str, definer_user.length); definer.str[definer_user.length]= '@'; + DBUG_PRINT("info",("copy the host")); memcpy(definer.str + definer_user.length + 1, definer_host.str, definer_host.length); definer.str[definer.length]= '\0'; + DBUG_PRINT("info",("definer initted")); DBUG_RETURN(0); } @@ -1070,6 +1079,8 @@ int event_timed::execute(THD *thd, MEM_ROOT *mem_root) { Security_context *save_ctx; + /* this one is local and not needed after exec */ + Security_context security_ctx; int ret= 0; DBUG_ENTER("event_timed::execute"); @@ -1085,18 +1096,19 @@ event_timed::execute(THD *thd, MEM_ROOT *mem_root) running= true; VOID(pthread_mutex_unlock(&this->LOCK_running)); - // TODO Andrey : make this as member variable and delete in destructor - + DBUG_PRINT("info", ("master_access=%d db_access=%d", + thd->security_ctx->master_access, thd->security_ctx->db_access)); + change_security_context(thd, &security_ctx, &save_ctx); + DBUG_PRINT("info", ("master_access=%d db_access=%d", + thd->security_ctx->master_access, thd->security_ctx->db_access)); + if (!sphead && (ret= compile(thd, mem_root))) goto done; - - DBUG_PRINT("info", ("master_access=%d db_access=%d", - thd->security_ctx->master_access, thd->security_ctx->db_access)); - change_security_context(thd, &save_ctx); - - DBUG_PRINT("info", ("master_access=%d db_access=%d", - thd->security_ctx->master_access, thd->security_ctx->db_access)); - if (mysql_change_db(thd, dbname.str, 0)) + /* Now we are sure we have valid this->sphead so we can copy the context */ + sphead->m_security_ctx= security_ctx; + thd->db= dbname.str; + thd->db_length= dbname.length; + if (!check_access(thd, EVENT_ACL,dbname.str, 0, 0, 0,is_schema_db(dbname.str))) { List empty_item_list; empty_item_list.empty(); @@ -1109,16 +1121,20 @@ event_timed::execute(THD *thd, MEM_ROOT *mem_root) ret= -99; } restore_security_context(thd, save_ctx); - DBUG_PRINT("info", ("master_access=%d db_access=%d", thd->security_ctx->master_access, thd->security_ctx->db_access)); + thd->db= 0; VOID(pthread_mutex_lock(&this->LOCK_running)); running= false; VOID(pthread_mutex_unlock(&this->LOCK_running)); done: - // Don't cache sphead if allocated on another mem_root + /* + 1. Don't cache sphead if allocated on another mem_root + 2. Don't call security_ctx.destroy() because this will free our dbname.str + name.str and definer.str + */ if (mem_root && sphead) { delete sphead; @@ -1143,20 +1159,22 @@ done: 1 - Error (generates error too) */ bool -event_timed::change_security_context(THD *thd, Security_context **backup) +event_timed::change_security_context(THD *thd, Security_context *s_ctx, + Security_context **backup) { DBUG_ENTER("event_timed::change_security_context"); DBUG_PRINT("info",("%s@%s@%s",definer_user.str,definer_host.str, dbname.str)); #ifndef NO_EMBEDDED_ACCESS_CHECKS + s_ctx->init(); *backup= 0; - if (acl_getroot_no_password(&sphead->m_security_ctx, definer_user.str, - definer_host.str, definer_host.str, dbname.str)) + if (acl_getroot_no_password(s_ctx, definer_user.str, definer_host.str, + definer_host.str, dbname.str)) { my_error(ER_NO_SUCH_USER, MYF(0), definer_user.str, definer_host.str); DBUG_RETURN(TRUE); } *backup= thd->security_ctx; - thd->security_ctx= &sphead->m_security_ctx; + thd->security_ctx= s_ctx; #endif DBUG_RETURN(FALSE); }