From: Date: February 19 2006 2:38am Subject: bk commit into 5.1 tree (andrey:1.2122) BUG#16992 List-Archive: http://lists.mysql.com/commits/2873 X-Bug: 16992 Message-Id: <20060219013847.5511B3187A@andrey.hristov.com> Below is the list of changes that have just been committed into a local 5.1 repository of andrey. When andrey does a push these changes will be propagated to the main repository and, within 24 hours after the push, to the public repository. For information on how to access the public repository see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html ChangeSet 1.2122 06/02/19 02:38:34 andrey@lmy004. +15 -0 fix for bug#16992 Events: information_schema troubles WL#1034 (the previous CSet was missing one file :( ) EVENT is no more needed, as SHOW PRIVILEGES, to see own events. To see all events one needs SELECT on mysql.event. SHOW EVENTS always shows events from one database. FULL has no effect SELECT I_S gets from all schemas. If user is missing EVENT on a schema but still has events there he will be able to see them but they won't be executed because he misses EVENT on this schema. They will start executing again if she gets again granted EVENT on this schema. mysql-test/t/events_tamper.test 1.1 06/02/19 02:38:24 andrey@lmy004. +100 -0 mysql-test/t/events_tamper.test 1.0 06/02/19 02:38:24 andrey@lmy004. +0 -0 BitKeeper file /work/mysql-5.1-bug16992/mysql-test/t/events_tamper.test mysql-test/r/events_tamper.result 1.1 06/02/19 02:38:22 andrey@lmy004. +126 -0 mysql-test/r/events_tamper.result 1.0 06/02/19 02:38:22 andrey@lmy004. +0 -0 BitKeeper file /work/mysql-5.1-bug16992/mysql-test/r/events_tamper.result mysql-test/r/events_i_s.result 1.1 06/02/19 02:38:21 andrey@lmy004. +125 -0 sql/table.h 1.132 06/02/19 02:38:21 andrey@lmy004. +19 -2 - add index checking typedef sql/table.cc 1.210 06/02/19 02:38:21 andrey@lmy004. +64 -16 - add functionality to table_check_intact() to check also indices, if needed indices on tables with up to 255 fields. The index length is practically unlimited but anyway - 255 fields. - prefix the table->alias with mysql. The code will be used anyway for now only for mysql internal tables. sql/sql_show.cc 1.308 06/02/19 02:38:21 andrey@lmy004. +63 -21 - field 16 of I_S.EVENTS, last_execute_at is declared as maybe_null so only in case it's not null call set_notnull() and set a value - handle in better way SHOW EVENTS / SELECT I_S -- SHOW EVENTS can be executed without having EVENT on the specific schema. All user's events will be presented. If the user has no EVENT but SELECT_ACL on mysql.event the he will see all events in the specific schema (nobody can prevent him from selecting mysql.event anyway) -- SELECT I_S is the same as SHOW EVENTS but on global level. Without SELECT_ACL on mysql.event one does see all events (s)he has. With SELECT_ACL on mysql.event one sees all existing events. mysql-test/r/events_i_s.result 1.0 06/02/19 02:38:21 andrey@lmy004. +0 -0 BitKeeper file /work/mysql-5.1-bug16992/mysql-test/r/events_i_s.result sql/sql_parse.cc 1.523 06/02/19 02:38:20 andrey@lmy004. +5 -6 - handle show events in another way. show events does not require EVENT priv to see your own events. SELECT on mysql.event is required to see all events per db (with SHOW EVENTS) or globally (with SELECT I_S.EVENTS) sql/event_executor.cc 1.31 06/02/19 02:38:20 andrey@lmy004. +6 -6 - additional NULL parameter durin checking of mysql.db, we don't check the indices of mysql.db because we don't care about them. - make "event_scheduler" var OFF when the scheduler finishes. sql/event.cc 1.31 06/02/19 02:38:20 andrey@lmy004. +50 -45 - add information about the indices we expect mysql.event to have - everything else changed in this file is whitespace change scripts/mysql_fix_privilege_tables.sql 1.41 06/02/19 02:38:20 andrey@lmy004. +3 -2 add additional unique index; scripts/mysql_create_system_tables.sh 1.38 06/02/19 02:38:20 andrey@lmy004. +2 -1 add additional unique index mysql-test/t/events.test 1.21 06/02/19 02:38:20 andrey@lmy004. +0 -132 - move information_schema test of EVENTS to a separate test - move tampering test to separate file which has more tests for index checking. mysql-test/r/system_mysql_db.result 1.39 06/02/19 02:38:20 andrey@lmy004. +2 -1 - fix output mysql-test/r/events.result 1.22 06/02/19 02:38:19 andrey@lmy004. +1 -143 -update results file -information_schema test of EVENTS has been moved to a separate file -tampering of mysql.event test has been moved to a separate file mysql-test/lib/init_db.sql 1.25 06/02/19 02:38:19 andrey@lmy004. +2 -1 add a second key, unique to the table mysql.event # This is a BitKeeper patch. What follows are the unified diffs for the # set of deltas contained in the patch. The rest of the patch, the part # that BitKeeper cares about, is below these diffs. # User: andrey # Host: lmy004. # Root: /work/mysql-5.1-bug16992 --- 1.522/sql/sql_parse.cc 2006-02-15 17:12:20 +01:00 +++ 1.523/sql/sql_parse.cc 2006-02-19 02:38:20 +01:00 @@ -2458,15 +2458,11 @@ mysql_execute_command(THD *thd) if (all_tables) { if (lex->orig_sql_command != SQLCOM_SHOW_STATUS_PROC && - lex->orig_sql_command != SQLCOM_SHOW_STATUS_FUNC && - lex->orig_sql_command != SQLCOM_SHOW_EVENTS) + lex->orig_sql_command != SQLCOM_SHOW_STATUS_FUNC) res= check_table_access(thd, lex->exchange ? SELECT_ACL | FILE_ACL : SELECT_ACL, all_tables, 0); - else if (lex->orig_sql_command == SQLCOM_SHOW_EVENTS) - res= check_access(thd, EVENT_ACL, thd->lex->select_lex.db, 0, 0, 0, - is_schema_db(thd->lex->select_lex.db)); } else res= check_access(thd, @@ -3769,9 +3765,12 @@ end_with_restore_list: break; } - if (check_access(thd, EVENT_ACL, lex->et->dbname.str, 0, 0, 0, + if (check_access(thd, EVENT_ACL, lex->et->dbname.str, 0, 0, 1, is_schema_db(lex->et->dbname.str))) + { + my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "EVENT"); break; + } if (end_active_trans(thd)) { --- 1.307/sql/sql_show.cc 2006-02-16 13:12:37 +01:00 +++ 1.308/sql/sql_show.cc 2006-02-19 02:38:21 +01:00 @@ -4013,9 +4013,10 @@ fill_events_copy_to_schema_table(THD *th sch_table->field[15]->store_time(&time, MYSQL_TIMESTAMP_DATETIME); if (et.last_executed.year) + { + sch_table->field[16]->set_notnull(); sch_table->field[16]->store_time(&et.last_executed,MYSQL_TIMESTAMP_DATETIME); - else - sch_table->field[16]->set_null(); + } sch_table->field[17]->store(et.comment.str, et.comment.length, scs); @@ -4035,17 +4036,18 @@ int fill_schema_events(THD *thd, TABLE_L int ret=0; bool verbose= false; char definer[HOSTNAME_LENGTH+USERNAME_LENGTH+2]; - bool use_prefix_scanning= true; uint key_len= 0; byte *key_buf= NULL; LINT_INIT(key_buf); + bool use_prefix_scanning= TRUE; DBUG_ENTER("fill_schema_events"); strxmov(definer, thd->security_ctx->priv_user,"@",thd->security_ctx->priv_host, NullS); - DBUG_PRINT("info",("db=%s current_user=%s", thd->lex->select_lex.db, definer)); + DBUG_PRINT("info",("db=%s current_user=%s", + thd->lex->select_lex.db?thd->lex->select_lex.db:"(null)", definer)); thd->reset_n_backup_open_tables_state(&backup); @@ -4055,33 +4057,68 @@ int fill_schema_events(THD *thd, TABLE_L ret= 1; goto err; } - - event_table->file->ha_index_init(0, 1); - /* - see others' events only if you have PROCESS_ACL !! - thd->lex->verbose is set either if SHOW FULL EVENTS or - in case of SELECT FROM I_S.EVENTS - */ - verbose= (thd->lex->verbose - && (thd->security_ctx->master_access & PROCESS_ACL)); - - if (verbose && thd->security_ctx->user) - { - ret= event_table->file->index_first(event_table->record[0]); - use_prefix_scanning= false; + { + TABLE_LIST tmp_table; + bzero((char*) &tmp_table,sizeof(tmp_table)); + tmp_table.db=(char*) "mysql"; + tmp_table.table_name=(char*) "event"; + verbose= !(check_grant(thd, SELECT_ACL, &tmp_table, 0, 1, 1)); + } + + if (verbose) + { + /* + 1. SELECT I_S => use PK(0) + 2. SHOW EVENTS => second index(1) (db, name, definer) + + */ + if (thd->lex->orig_sql_command == SQLCOM_SHOW_EVENTS) + { + DBUG_PRINT("info",("Using prefix scanning on UNIQUE")); + event_table->file->ha_index_init(1, 1); + DBUG_ASSERT(thd->lex->select_lex.db); + DBUG_PRINT("info",("Using `%s` in the prefix", thd->lex->select_lex.db)); + event_table->field[EVEX_FIELD_DB]-> + store(thd->lex->select_lex.db, strlen(thd->lex->select_lex.db), scs); + key_len= event_table->key_info[1].key_part[0].store_length; + + if (!(key_buf= (byte *)alloc_root(thd->mem_root, key_len))) + { + ret= 1; + goto err; + } + + key_copy(key_buf, event_table->record[0], event_table->key_info + 1, + key_len); + ret= event_table->file->index_read(event_table->record[0], key_buf, + key_len, HA_READ_PREFIX); + } + else + { + DBUG_PRINT("info",("Not using prefix scanning but using PK.")); + event_table->file->ha_index_init(0, 1); + ret= event_table->file->index_first(event_table->record[0]); + use_prefix_scanning= FALSE; + } } else { - event_table->field[EVEX_FIELD_DEFINER]->store(definer, strlen(definer), scs); + DBUG_PRINT("info",("Using prefix scanning on PK")); + + event_table->file->ha_index_init(0, 1); + event_table->field[EVEX_FIELD_DEFINER]->store(definer, strlen(definer), scs); key_len= event_table->key_info->key_part[0].store_length; - if (thd->lex->select_lex.db) + if (thd->lex->orig_sql_command == SQLCOM_SHOW_EVENTS) { + DBUG_PRINT("info",("Using also `%s` in the prefix scanning", + thd->lex->select_lex.db)); event_table->field[EVEX_FIELD_DB]-> store(thd->lex->select_lex.db, strlen(thd->lex->select_lex.db), scs); key_len+= event_table->key_info->key_part[1].store_length; } + if (!(key_buf= (byte *)alloc_root(thd->mem_root, key_len))) { ret= 1; @@ -4098,6 +4135,7 @@ int fill_schema_events(THD *thd, TABLE_L ret= (ret == HA_ERR_END_OF_FILE || ret == HA_ERR_KEY_NOT_FOUND) ? 0 : 1; goto err; } + DBUG_PRINT("info",("Found some rows, let's retrieve them.")); while (!ret) { @@ -4106,20 +4144,24 @@ int fill_schema_events(THD *thd, TABLE_L if (use_prefix_scanning) ret= event_table->file-> - index_next_same(event_table->record[0], key_buf, key_len); + index_next_same(event_table->record[0], key_buf, key_len); else ret= event_table->file->index_next(event_table->record[0]); } + DBUG_PRINT("info",("Scan finished")); // ret is guaranteed to be != 0 ret= (ret != HA_ERR_END_OF_FILE); err: if (event_table) { + DBUG_PRINT("info",("Closing index")); event_table->file->ha_index_end(); close_thread_tables(thd); } thd->restore_backup_open_tables_state(&backup); + + DBUG_PRINT("info",("Return code=%d", ret)); DBUG_RETURN(ret); } --- 1.209/sql/table.cc 2006-02-14 20:10:43 +01:00 +++ 1.210/sql/table.cc 2006-02-19 02:38:21 +01:00 @@ -2299,6 +2299,9 @@ bool check_column_name(const char *name) table - the table to check table_f_count - expected number of columns in the table table_def - expected structure of the table (column name and type) + table_keys - NULL if no index checking, otherwise a pointer to an + array of the type. The last element in the array should + be {NULL, 0} (terminated in this way). last_create_time- the table->file->create_time of the table in memory we have checked last time error_num - ER_XXXX from the error messages file. When 0 no error @@ -2314,8 +2317,9 @@ bool check_column_name(const char *name) my_bool table_check_intact(TABLE *table, uint table_f_count, - TABLE_FIELD_W_TYPE *table_def, time_t *last_create_time, - int error_num) + TABLE_FIELD_W_TYPE *table_def, + TABLE_KEY_FOR_CHECK *table_keys, + time_t *last_create_time, int error_num) { uint i; my_bool error= FALSE; @@ -2323,7 +2327,7 @@ table_check_intact(TABLE *table, uint ta DBUG_ENTER("table_check_intact"); DBUG_PRINT("info",("table=%s expected_count=%d",table->alias, table_f_count)); DBUG_PRINT("info",("last_create_time=%d", *last_create_time)); - + if ((fields_diff_count= (table->s->fields != table_f_count)) || (*last_create_time != table->file->create_time)) { @@ -2363,11 +2367,11 @@ table_check_intact(TABLE *table, uint ta if (strncmp(field->field_name, table_def->name.str, table_def->name.length)) { - sql_print_error("(%s) Expected field %s at position %d, found %s", - table->alias, table_def->name.str, i, + sql_print_error("(mysql.%s) Expected field %s at position %d, " + " found %s", table->alias, table_def->name.str, i, field->field_name); } - + /* IF the type does not match than something is really wrong Check up to length - 1. Why? @@ -2382,22 +2386,23 @@ table_check_intact(TABLE *table, uint ta if (strncmp(sql_type.c_ptr(), table_def->type.str, table_def->type.length - 1)) { - sql_print_error("(%s) Expected field %s at position %d to have type " - "%s, found %s", table->alias, table_def->name.str, - i, table_def->type.str, sql_type.c_ptr()); + sql_print_error("(mysql.%s) Expected field %s at position %d to " + " have type %s, found %s", table->alias, + table_def->name.str, i, table_def->type.str, + sql_type.c_ptr()); error= TRUE; } else if (table_def->cset.str && !field->has_charset()) { - sql_print_error("(%s) Expected field %s at position %d to have " + sql_print_error("(mysql.%s) Expected field %s at position %d to have " "character set '%s' but found no such", table->alias, - table_def->name.str, i, table_def->cset.str); + table_def->name.str, i, table_def->cset.str); error= TRUE; } else if (table_def->cset.str && strcmp(field->charset()->csname, table_def->cset.str)) { - sql_print_error("(%s) Expected field %s at position %d to have " + sql_print_error("(mysql.%s) Expected field %s at position %d to have " "character set '%s' but found '%s'", table->alias, table_def->name.str, i, table_def->cset.str, field->charset()->csname); @@ -2406,12 +2411,54 @@ table_check_intact(TABLE *table, uint ta } else { - sql_print_error("(%s) Expected field %s at position %d to have type %s " - " but no field found.", table_def->name.str, + sql_print_error("(mysql.%s) Expected field %s at position %d to " + " have type %s but no field found.", table_def->name.str, table_def->name.str, i, table_def->type.str); error= TRUE; } } + if (table_keys) + { + KEY *key_info= table->key_info; + uint key_num= 0; + uint missing_keys= 0; + for (; table_keys->key.length; ++key_num, ++table_keys, ++key_info) + { + if (table->s->keys < key_num + 1) + { + ++missing_keys; + continue; + } + KEY_PART_INFO *key_part= key_info->key_part; + if (table_keys->key.length > key_info->key_parts) + { + error= TRUE; + sql_print_error("(mysql.%s) Key %d is shorter than expected. " + "Expected %d key parts, found %d", table->alias, + key_num, table_keys->key.length, key_info->key_parts); + continue; + } + for (uint j=0 ; j < key_info->key_parts ; j++,key_part++) + { + if (j == table_keys->key.length) + break; + + if (key_part->fieldnr != table_keys->key.str[j]) + { + error= TRUE; + sql_print_error("(mysql.%s) Key %d, key part %d expected field %d," + " found %d.", table->alias, key_num, j, + table_keys->key.str[j], key_part->fieldnr); + } + } + } + if (missing_keys) + { + error= TRUE; + sql_print_error("(mysql.%s) Expected %d keys, found %d", table->alias, + table->s->keys + missing_keys, table->s->keys); + } + } if (!error) *last_create_time= table->file->create_time; else if (!fields_diff_count && error_num) @@ -2422,8 +2469,9 @@ table_check_intact(TABLE *table, uint ta DBUG_PRINT("info", ("Table seems ok without thorough checking.")); *last_create_time= table->file->create_time; } - - DBUG_RETURN(error); + + DBUG_PRINT("info", ("return code=%d", error)); + DBUG_RETURN(error); } --- 1.131/sql/table.h 2006-02-16 14:53:27 +01:00 +++ 1.132/sql/table.h 2006-02-19 02:38:21 +01:00 @@ -867,6 +867,7 @@ typedef struct st_open_table_list{ uint32 in_use,locked; } OPEN_TABLE_LIST; + typedef struct st_table_field_w_type { LEX_STRING name; @@ -874,8 +875,24 @@ typedef struct st_table_field_w_type LEX_STRING cset; } TABLE_FIELD_W_TYPE; +/* + Every byte in the string regards a fieldnr + Should work without probles with tables with up to 126 fields. + If char is unsigned by default with up to 255 fields. + Usage: + + STRING_WITH_LEN("\x01\x04\07") + This instructs that the index has 3 parts and includes fields + 1, 4 and 7. For the keys the indexing is 1-based and not 0-based. +*/ +typedef struct st_table_key_for_check +{ + LEX_STRING key; +} TABLE_KEY_FOR_CHECK; + my_bool table_check_intact(TABLE *table, uint table_f_count, - TABLE_FIELD_W_TYPE *table_def, time_t *last_create_time, - int error_num); + TABLE_FIELD_W_TYPE *table_def, + TABLE_KEY_FOR_CHECK *table_keys, + time_t *last_create_time, int error_num); --- 1.21/mysql-test/r/events.result 2006-02-16 13:11:06 +01:00 +++ 1.22/mysql-test/r/events.result 2006-02-19 02:38:19 +01:00 @@ -168,149 +168,6 @@ drop event root19; drop event root20; drop event ðóóò21; set names latin1; -CREATE EVENT intact_check ON SCHEDULE EVERY 10 HOUR DO SELECT "nothing"; -SHOW EVENTS; -Db Name Definer Type Execute at Interval value Interval field Starts Ends Status -events_test intact_check root@localhost RECURRING NULL 10 HOUR # # ENABLED -ALTER TABLE mysql.event ADD dummy INT FIRST; -SHOW EVENTS; -ERROR HY000: Column count of mysql.event is wrong. Expected 16, found 17. Table probably corrupted -ALTER TABLE mysql.event DROP dummy, ADD dummy2 VARCHAR(64) FIRST; -SHOW EVENTS; -ERROR HY000: Column count of mysql.event is wrong. Expected 16, found 17. Table probably corrupted -ALTER TABLE mysql.event DROP dummy2; -SHOW EVENTS; -Db Name Definer Type Execute at Interval value Interval field Starts Ends Status -events_test intact_check root@localhost RECURRING NULL 10 HOUR # # ENABLED -CREATE TABLE event_like LIKE mysql.event; -INSERT INTO event_like SELECT * FROM mysql.event; -ALTER TABLE mysql.event MODIFY db char(20) character set utf8 collate utf8_bin default ''; -SHOW CREATE TABLE mysql.event; -Table Create Table -event CREATE TABLE `event` ( - `db` char(20) character set utf8 collate utf8_bin NOT NULL default '', - `name` char(64) character set utf8 collate utf8_bin NOT NULL default '', - `body` longblob NOT NULL, - `definer` char(77) character set utf8 collate utf8_bin NOT NULL default '', - `execute_at` datetime default NULL, - `interval_value` int(11) default NULL, - `interval_field` enum('YEAR','QUARTER','MONTH','DAY','HOUR','MINUTE','WEEK','SECOND','MICROSECOND','YEAR_MONTH','DAY_HOUR','DAY_MINUTE','DAY_SECOND','HOUR_MINUTE','HOUR_SECOND','MINUTE_SECOND','DAY_MICROSECOND','HOUR_MICROSECOND','MINUTE_MICROSECOND','SECOND_MICROSECOND') default NULL, - `created` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, - `modified` timestamp NOT NULL default '0000-00-00 00:00:00', - `last_executed` datetime default NULL, - `starts` datetime default NULL, - `ends` datetime default NULL, - `status` enum('ENABLED','DISABLED') NOT NULL default 'ENABLED', - `on_completion` enum('DROP','PRESERVE') NOT NULL default 'DROP', - `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE') NOT NULL default '', - `comment` char(64) character set utf8 collate utf8_bin NOT NULL default '', - PRIMARY KEY (`definer`,`db`,`name`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Events' -SELECT event_name FROM INFORMATION_SCHEMA.EVENTS; -ERROR HY000: Cannot load from mysql.event. Table probably corrupted. See error log. -ALTER TABLE mysql.event MODIFY db char(64) character set utf8 collate utf8_bin default ''; -"This should work" -SHOW EVENTS; -Db Name Definer Type Execute at Interval value Interval field Starts Ends Status -events_test intact_check root@localhost RECURRING NULL 10 HOUR # # ENABLED -ALTER TABLE mysql.event MODIFY db char(64) character set cp1251 default ''; -SELECT event_name FROM INFORMATION_SCHEMA.EVENTS; -ERROR HY000: Cannot load from mysql.event. Table probably corrupted. See error log. -ALTER TABLE mysql.event MODIFY db varchar(64) character set utf8 collate utf8_bin default ''; -SELECT event_name FROM INFORMATION_SCHEMA.EVENTS; -ERROR HY000: Cannot load from mysql.event. Table probably corrupted. See error log. -ALTER TABLE mysql.event DROP comment, DROP starts; -SELECT event_name FROM INFORMATION_SCHEMA.EVENTS; -ERROR HY000: Column count of mysql.event is wrong. Expected 16, found 14. Table probably corrupted -DROP TABLE mysql.event; -CREATE TABLE mysql.event like event_like; -INSERT INTO mysql.event SELECT * FROM event_like; -DROP TABLE event_like; -SHOW EVENTS; -Db Name Definer Type Execute at Interval value Interval field Starts Ends Status -events_test intact_check root@localhost RECURRING NULL 10 HOUR # # ENABLED -DROP EVENT intact_check; -create event one_event on schedule every 10 second do select 123; -SHOW EVENTS; -Db Name Definer Type Execute at Interval value Interval field Starts Ends Status -events_test one_event root@localhost RECURRING NULL 10 SECOND # # ENABLED -SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT from information_schema.events; -EVENT_CATALOG EVENT_SCHEMA EVENT_NAME DEFINER EVENT_BODY EVENT_TYPE EXECUTE_AT INTERVAL_VALUE INTERVAL_FIELD STATUS ON_COMPLETION EVENT_COMMENT -NULL events_test one_event root@localhost select 123 RECURRING NULL 10 SECOND ENABLED NOT PRESERVE -CREATE DATABASE events_test2; -CREATE USER ev_test@localhost; -GRANT ALL ON events_test.* to ev_test@localhost; -GRANT ALL on events_test2.* to ev_test@localhost; -REVOKE EVENT ON events_test2.* FROM ev_test@localhost; -REVOKE PROCESS on *.* from ev_test@localhost; -select "NEW CONNECTION"; -NEW CONNECTION -NEW CONNECTION -SELECT USER(), DATABASE(); -USER() DATABASE() -ev_test@localhost events_test2 -SHOW GRANTS; -Grants for ev_test@localhost -GRANT USAGE ON *.* TO 'ev_test'@'localhost' -GRANT ALL PRIVILEGES ON `events_test`.* TO 'ev_test'@'localhost' -GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE, TRIGGER ON `events_test2`.* TO 'ev_test'@'localhost' -"Here comes an error:"; -SHOW EVENTS; -ERROR 42000: Access denied for user 'ev_test'@'localhost' to database 'events_test2' -USE events_test; -"Now the list should be empty:"; -SHOW EVENTS; -Db Name Definer Type Execute at Interval value Interval field Starts Ends Status -select concat("Let's create some new events from the name of ",user()); -concat("Let's create some new events from the name of ",user()) -Let's create some new events from the name of ev_test@localhost -create event one_event on schedule every 20 second do select 123; -create event two_event on schedule every 20 second on completion not preserve comment "two event" do select 123; -create event three_event on schedule every 20 second on completion preserve comment "three event" do select 123; -"Now we should see 3 events:"; -SHOW EVENTS; -Db Name Definer Type Execute at Interval value Interval field Starts Ends Status -events_test one_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED -events_test three_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED -events_test two_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED -"This should show us only 3 events:"; -SHOW FULL EVENTS; -Db Name Definer Type Execute at Interval value Interval field Starts Ends Status -events_test one_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED -events_test three_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED -events_test two_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED -"This should show us only 2 events:"; -SHOW FULL EVENTS LIKE 't%event'; -Db Name Definer Type Execute at Interval value Interval field Starts Ends Status -events_test three_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED -events_test two_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED -"This should show us no events:"; -SHOW FULL EVENTS FROM test LIKE '%'; -Db Name Definer Type Execute at Interval value Interval field Starts Ends Status -DROP DATABASE events_test2; -"should see 1 event:"; -SHOW EVENTS; -Db Name Definer Type Execute at Interval value Interval field Starts Ends Status -events_test one_event root@localhost RECURRING NULL 10 SECOND # # ENABLED -"we should see 4 events now:"; -SHOW FULL EVENTS; -Db Name Definer Type Execute at Interval value Interval field Starts Ends Status -events_test one_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED -events_test three_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED -events_test two_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED -events_test one_event root@localhost RECURRING NULL 10 SECOND # # ENABLED -SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT from information_schema.events; -EVENT_CATALOG EVENT_SCHEMA EVENT_NAME DEFINER EVENT_BODY EVENT_TYPE EXECUTE_AT INTERVAL_VALUE INTERVAL_FIELD STATUS ON_COMPLETION EVENT_COMMENT -NULL events_test one_event ev_test@localhost select 123 RECURRING NULL 20 SECOND ENABLED NOT PRESERVE -NULL events_test three_event ev_test@localhost select 123 RECURRING NULL 20 SECOND ENABLED PRESERVE three event -NULL events_test two_event ev_test@localhost select 123 RECURRING NULL 20 SECOND ENABLED NOT PRESERVE two event -NULL events_test one_event root@localhost select 123 RECURRING NULL 10 SECOND ENABLED NOT PRESERVE -drop event one_event; -drop event two_event; -drop event three_event; -drop user ev_test@localhost; -drop event one_event; -"Sleep a bit so the server closes the second connection" create event e_26 on schedule at '2017-01-01 00:00:00' disable do set @a = 5; select db, name, body, definer, convert_tz(execute_at, 'UTC', 'SYSTEM'), on_completion from mysql.event; db name body definer convert_tz(execute_at, 'UTC', 'SYSTEM') on_completion @@ -343,6 +200,7 @@ root@localhost закачка events_tes 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 select release_lock("test_lock1"); release_lock("test_lock1") 1 --- New file --- +++ mysql-test/r/events_i_s.result 06/02/19 02:38:21 create database if not exists events_test; use events_test; select user(), database(); user() database() root@localhost events_test create event one_event on schedule every 10 second do select 123; SHOW EVENTS; Db Name Definer Type Execute at Interval value Interval field Starts Ends Status events_test one_event root@localhost RECURRING NULL 10 SECOND # # ENABLED SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT from information_schema.events; EVENT_CATALOG EVENT_SCHEMA EVENT_NAME DEFINER EVENT_BODY EVENT_TYPE EXECUTE_AT INTERVAL_VALUE INTERVAL_FIELD STATUS ON_COMPLETION EVENT_COMMENT NULL events_test one_event root@localhost select 123 RECURRING NULL 10 SECOND ENABLED NOT PRESERVE CREATE DATABASE events_test2; CREATE USER ev_test@localhost; GRANT EVENT ON events_test.* to ev_test@localhost; GRANT SELECT on events_test2.* to ev_test@localhost; "Connect as ev_con1, user ev_test, db events_test2" "NEW CONNECTION"; SELECT USER(), DATABASE(); USER() DATABASE() ev_test@localhost events_test2 SHOW GRANTS; Grants for ev_test@localhost GRANT USAGE ON *.* TO 'ev_test'@'localhost' GRANT EVENT ON `events_test`.* TO 'ev_test'@'localhost' GRANT SELECT ON `events_test2`.* TO 'ev_test'@'localhost' "Now the list should be empty:"; SHOW EVENTS; Db Name Definer Type Execute at Interval value Interval field Starts Ends Status "Now create few events as ev_test@localhost in schema events_test" select concat("Let's create some new events from the name of ",user()); concat("Let's create some new events from the name of ",user()) Let's create some new events from the name of ev_test@localhost "ev_test@localhost has no EVENT so error" create event one_event on schedule every 20 second disable do select 123; ERROR 42000: Access denied; you need the EVENT privilege for this operation "Now we will give him EVENT" GRANT EVENT ON events_test2.* to ev_test@localhost; "Change the current schema so the server will read our new privs" use events_test; use events_test2; "Now he has EVENT and will create 3 events" create event one_event on schedule every 20 second disable do select 123; create event two_event on schedule every 20 second on completion not preserve comment "two event" do select 123; create event three_event on schedule every 20 second on completion preserve comment "three event" do select 123; "Now we should see 3 events because ev_test has no SELECT on mysql.event:"; SHOW EVENTS; Db Name Definer Type Execute at Interval value Interval field Starts Ends Status events_test2 one_event ev_test@localhost RECURRING NULL 20 SECOND # # DISABLED events_test2 three_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED events_test2 two_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED "Let's REVOKE his EVENT on events_test2, but he will still see his events" REVOKE EVENT on events_test2.* FROM ev_test@localhost; "Now he has no EVENT on events_test2 but that's not a problem" SHOW EVENTS; Db Name Definer Type Execute at Interval value Interval field Starts Ends Status events_test2 one_event ev_test@localhost RECURRING NULL 20 SECOND # # DISABLED events_test2 three_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED events_test2 two_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED "This should show us only 2 events:"; SHOW EVENTS LIKE 't%event'; Db Name Definer Type Execute at Interval value Interval field Starts Ends Status events_test2 three_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED events_test2 two_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED "This should show us no events:"; SHOW EVENTS FROM test LIKE '%'; Db Name Definer Type Execute at Interval value Interval field Starts Ends Status "This also :"; SHOW EVENTS IN test LIKE '%'; Db Name Definer Type Execute at Interval value Interval field Starts Ends Status "ok, we are back to root@localhost" USE events_test2; create event root_event_1 on schedule every 10 hour do select 12345; create event root_event_2 on schedule every 20 minute do select 4567; "As root@localhost we should see 5 event:"; SHOW EVENTS; Db Name Definer Type Execute at Interval value Interval field Starts Ends Status events_test2 one_event ev_test@localhost RECURRING NULL 20 SECOND # # DISABLED events_test2 three_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED events_test2 two_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED events_test2 root_event_1 root@localhost RECURRING NULL 10 HOUR # # ENABLED events_test2 root_event_2 root@localhost RECURRING NULL 20 MINUTE # # ENABLED "Switching back to ev_con1, should see only his 3 events. Keep in mind he has no EVENT ATM" SHOW EVENTS; Db Name Definer Type Execute at Interval value Interval field Starts Ends Status events_test2 one_event ev_test@localhost RECURRING NULL 20 SECOND # # DISABLED events_test2 three_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED events_test2 two_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED "Back to root@localhost to GRANT SELECT on mysql.event" GRANT SELECT ON mysql.event TO ev_test@localhost; "Back to ev_test@localhost" "Now we should see 5 events, because of SELECT on mysql.event," "even without EVENT on event_test2. 3 of ev_test@localhost and 2 of root@localhost" SHOW EVENTS; Db Name Definer Type Execute at Interval value Interval field Starts Ends Status events_test2 one_event ev_test@localhost RECURRING NULL 20 SECOND # # DISABLED events_test2 three_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED events_test2 two_event ev_test@localhost RECURRING NULL 20 SECOND # # ENABLED events_test2 root_event_1 root@localhost RECURRING NULL 10 HOUR # # ENABLED events_test2 root_event_2 root@localhost RECURRING NULL 20 MINUTE # # ENABLED "we should see 6 events now (additional one from events_test schema:"; SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT from information_schema.events; EVENT_CATALOG EVENT_SCHEMA EVENT_NAME DEFINER EVENT_BODY EVENT_TYPE EXECUTE_AT INTERVAL_VALUE INTERVAL_FIELD STATUS ON_COMPLETION EVENT_COMMENT NULL events_test2 one_event ev_test@localhost select 123 RECURRING NULL 20 SECOND DISABLED NOT PRESERVE NULL events_test2 three_event ev_test@localhost select 123 RECURRING NULL 20 SECOND ENABLED PRESERVE three event NULL events_test2 two_event ev_test@localhost select 123 RECURRING NULL 20 SECOND ENABLED NOT PRESERVE two event NULL events_test one_event root@localhost select 123 RECURRING NULL 10 SECOND ENABLED NOT PRESERVE NULL events_test2 root_event_1 root@localhost select 12345 RECURRING NULL 10 HOUR ENABLED NOT PRESERVE NULL events_test2 root_event_2 root@localhost select 4567 RECURRING NULL 20 MINUTE ENABLED NOT PRESERVE REVOKE SELECT ON mysql.event FROM ev_test@localhost; "we should see only 3 events now, we don't have SELECT on mysql.event anymore:"; SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT from information_schema.events; EVENT_CATALOG EVENT_SCHEMA EVENT_NAME DEFINER EVENT_BODY EVENT_TYPE EXECUTE_AT INTERVAL_VALUE INTERVAL_FIELD STATUS ON_COMPLETION EVENT_COMMENT NULL events_test2 one_event ev_test@localhost select 123 RECURRING NULL 20 SECOND DISABLED NOT PRESERVE NULL events_test2 three_event ev_test@localhost select 123 RECURRING NULL 20 SECOND ENABLED PRESERVE three event NULL events_test2 two_event ev_test@localhost select 123 RECURRING NULL 20 SECOND ENABLED NOT PRESERVE two event DROP DATABASE events_test2; use events_test; "we should see only 2 events now, 3 of ev_test@localhost were dropped with DROP DATABASE"; SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT from information_schema.events; EVENT_CATALOG EVENT_SCHEMA EVENT_NAME DEFINER EVENT_BODY EVENT_TYPE EXECUTE_AT INTERVAL_VALUE INTERVAL_FIELD STATUS ON_COMPLETION EVENT_COMMENT NULL events_test one_event root@localhost select 123 RECURRING NULL 10 SECOND ENABLED NOT PRESERVE drop user ev_test@localhost; drop event one_event; drop database events_test; --- New file --- +++ mysql-test/r/events_tamper.result 06/02/19 02:38:22 create database if not exists events_test; use events_test; CREATE EVENT intact_check ON SCHEDULE EVERY 10 HOUR DO SELECT "nothing"; SHOW EVENTS; Db Name Definer Type Execute at Interval value Interval field Starts Ends Status events_test intact_check root@localhost RECURRING NULL 10 HOUR # # ENABLED ALTER TABLE mysql.event ADD dummy INT FIRST; SHOW EVENTS; ERROR HY000: Column count of mysql.event is wrong. Expected 16, found 17. Table probably corrupted ALTER TABLE mysql.event DROP dummy, ADD dummy2 VARCHAR(64) FIRST; SHOW EVENTS; ERROR HY000: Column count of mysql.event is wrong. Expected 16, found 17. Table probably corrupted ALTER TABLE mysql.event DROP dummy2; SHOW EVENTS; Db Name Definer Type Execute at Interval value Interval field Starts Ends Status events_test intact_check root@localhost RECURRING NULL 10 HOUR # # ENABLED CREATE TABLE event_like LIKE mysql.event; INSERT INTO event_like SELECT * FROM mysql.event; ALTER TABLE mysql.event MODIFY db char(20) character set utf8 collate utf8_bin default ''; SHOW CREATE TABLE mysql.event; Table Create Table event CREATE TABLE `event` ( `db` char(20) character set utf8 collate utf8_bin NOT NULL default '', `name` char(64) character set utf8 collate utf8_bin NOT NULL default '', `body` longblob NOT NULL, `definer` char(77) character set utf8 collate utf8_bin NOT NULL default '', `execute_at` datetime default NULL, `interval_value` int(11) default NULL, `interval_field` enum('YEAR','QUARTER','MONTH','DAY','HOUR','MINUTE','WEEK','SECOND','MICROSECOND','YEAR_MONTH','DAY_HOUR','DAY_MINUTE','DAY_SECOND','HOUR_MINUTE','HOUR_SECOND','MINUTE_SECOND','DAY_MICROSECOND','HOUR_MICROSECOND','MINUTE_MICROSECOND','SECOND_MICROSECOND') default NULL, `created` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, `modified` timestamp NOT NULL default '0000-00-00 00:00:00', `last_executed` datetime default NULL, `starts` datetime default NULL, `ends` datetime default NULL, `status` enum('ENABLED','DISABLED') NOT NULL default 'ENABLED', `on_completion` enum('DROP','PRESERVE') NOT NULL default 'DROP', `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE') NOT NULL default '', `comment` char(64) character set utf8 collate utf8_bin NOT NULL default '', PRIMARY KEY (`definer`,`db`,`name`), UNIQUE KEY `db_definer_name` (`db`,`definer`,`name`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Events' SELECT event_name FROM INFORMATION_SCHEMA.EVENTS; ERROR HY000: Cannot load from mysql.event. Table probably corrupted. See error log. ALTER TABLE mysql.event MODIFY db char(64) character set utf8 collate utf8_bin default ''; "This should work" SHOW EVENTS; Db Name Definer Type Execute at Interval value Interval field Starts Ends Status events_test intact_check root@localhost RECURRING NULL 10 HOUR # # ENABLED ALTER TABLE mysql.event MODIFY db char(64) character set cp1251 default ''; SELECT event_name FROM INFORMATION_SCHEMA.EVENTS; ERROR HY000: Cannot load from mysql.event. Table probably corrupted. See error log. ALTER TABLE mysql.event MODIFY db varchar(64) character set utf8 collate utf8_bin default ''; SELECT event_name FROM INFORMATION_SCHEMA.EVENTS; ERROR HY000: Cannot load from mysql.event. Table probably corrupted. See error log. ALTER TABLE mysql.event DROP comment, DROP starts; SELECT event_name FROM INFORMATION_SCHEMA.EVENTS; ERROR HY000: Column count of mysql.event is wrong. Expected 16, found 14. Table probably corrupted DROP TABLE mysql.event; CREATE TABLE mysql.event like event_like; INSERT INTO mysql.event SELECT * FROM event_like; "Now dropping one index to see whether index tampering check works" ALTER TABLE mysql.event DROP PRIMARY KEY; SELECT event_name FROM INFORMATION_SCHEMA.EVENTS; ERROR HY000: Cannot load from mysql.event. Table probably corrupted. See error log. "Recreating, should work now:" DROP TABLE mysql.event; CREATE TABLE mysql.event like event_like; INSERT INTO mysql.event SELECT * FROM event_like; "Test whether everything is fine" SELECT event_name FROM INFORMATION_SCHEMA.EVENTS; event_name intact_check ALTER TABLE mysql.event DROP INDEX db_definer_name; SHOW CREATE TABLE mysql.event; Table Create Table event CREATE TABLE `event` ( `db` char(64) character set utf8 collate utf8_bin NOT NULL default '', `name` char(64) character set utf8 collate utf8_bin NOT NULL default '', `body` longblob NOT NULL, `definer` char(77) character set utf8 collate utf8_bin NOT NULL default '', `execute_at` datetime default NULL, `interval_value` int(11) default NULL, `interval_field` enum('YEAR','QUARTER','MONTH','DAY','HOUR','MINUTE','WEEK','SECOND','MICROSECOND','YEAR_MONTH','DAY_HOUR','DAY_MINUTE','DAY_SECOND','HOUR_MINUTE','HOUR_SECOND','MINUTE_SECOND','DAY_MICROSECOND','HOUR_MICROSECOND','MINUTE_MICROSECOND','SECOND_MICROSECOND') default NULL, `created` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, `modified` timestamp NOT NULL default '0000-00-00 00:00:00', `last_executed` datetime default NULL, `starts` datetime default NULL, `ends` datetime default NULL, `status` enum('ENABLED','DISABLED') NOT NULL default 'ENABLED', `on_completion` enum('DROP','PRESERVE') NOT NULL default 'DROP', `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE') NOT NULL default '', `comment` char(64) character set utf8 collate utf8_bin NOT NULL default '', PRIMARY KEY (`definer`,`db`,`name`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Events' "Now let's bork the index and see whether we catch it" ALTER TABLE mysql.event ADD UNIQUE db_definer_name(db, name, definer); SELECT event_name FROM INFORMATION_SCHEMA.EVENTS; ERROR HY000: Cannot load from mysql.event. Table probably corrupted. See error log. ALTER TABLE mysql.event DROP KEY db_definer_name; "Make the key shorter" ALTER TABLE mysql.event ADD UNIQUE db_definer_name(db, name); SELECT event_name FROM INFORMATION_SCHEMA.EVENTS; ERROR HY000: Cannot load from mysql.event. Table probably corrupted. See error log. ALTER TABLE mysql.event DROP KEY db_definer_name; "Try with longer index, this should work" ALTER TABLE mysql.event ADD UNIQUE db_definer_name(db, definer, name, execute_at); "No error:" SELECT event_name FROM INFORMATION_SCHEMA.EVENTS; event_name intact_check "Add 1 more index, that should not be a problem - downgrading is ok" ALTER TABLE mysql.event ADD KEY dummy_index(execute_at); "No error:" SELECT event_name FROM INFORMATION_SCHEMA.EVENTS; event_name intact_check "Recreating" DROP TABLE mysql.event; CREATE TABLE mysql.event like event_like; INSERT INTO mysql.event SELECT * FROM event_like; DROP TABLE event_like; SHOW EVENTS; Db Name Definer Type Execute at Interval value Interval field Starts Ends Status events_test intact_check root@localhost RECURRING NULL 10 HOUR # # ENABLED DROP EVENT intact_check; drop database events_test; --- 1.20/mysql-test/t/events.test 2006-02-16 05:20:54 +01:00 +++ 1.21/mysql-test/t/events.test 2006-02-19 02:38:20 +01:00 @@ -149,139 +149,7 @@ set names latin1; # SHOW CREATE EVENT test end # -# -# mysql.event intact checking start -# -# There should be at least 1 second between the ALTERs or we can't catch the change of create_time!! -# -CREATE EVENT intact_check ON SCHEDULE EVERY 10 HOUR DO SELECT "nothing"; ---replace_column 8 # 9 # -SHOW EVENTS; -ALTER TABLE mysql.event ADD dummy INT FIRST; ---error 1525 -SHOW EVENTS; -ALTER TABLE mysql.event DROP dummy, ADD dummy2 VARCHAR(64) FIRST; ---error 1525 -SHOW EVENTS; -ALTER TABLE mysql.event DROP dummy2; ---replace_column 8 # 9 # -SHOW EVENTS; -CREATE TABLE event_like LIKE mysql.event; -INSERT INTO event_like SELECT * FROM mysql.event; -#sleep a bit or we won't catch the change of time ---sleep 1 -ALTER TABLE mysql.event MODIFY db char(20) character set utf8 collate utf8_bin default ''; -#wait a bit or we won't see the difference because of seconds resolution ---sleep 1 -SHOW CREATE TABLE mysql.event; ---error 1526 -SELECT event_name FROM INFORMATION_SCHEMA.EVENTS; ---sleep 1 -ALTER TABLE mysql.event MODIFY db char(64) character set utf8 collate utf8_bin default ''; ---sleep 1 ---echo "This should work" ---replace_column 8 # 9 # -SHOW EVENTS; ---sleep 1 -ALTER TABLE mysql.event MODIFY db char(64) character set cp1251 default ''; ---error 1526 -SELECT event_name FROM INFORMATION_SCHEMA.EVENTS; ---sleep 1 -ALTER TABLE mysql.event MODIFY db varchar(64) character set utf8 collate utf8_bin default ''; ---error 1526 -SELECT event_name FROM INFORMATION_SCHEMA.EVENTS; ---sleep 1 -ALTER TABLE mysql.event DROP comment, DROP starts; ---sleep 1 ---error 1525 -SELECT event_name FROM INFORMATION_SCHEMA.EVENTS; -DROP TABLE mysql.event; -CREATE TABLE mysql.event like event_like; -INSERT INTO mysql.event SELECT * FROM event_like; -DROP TABLE event_like; ---replace_column 8 # 9 # -SHOW EVENTS; -DROP EVENT intact_check; -# -# mysql.event intact checking end -# -# -#INFORMATION_SCHEMA.EVENTS test begin -# -create event one_event on schedule every 10 second do select 123; ---replace_column 8 # 9 # -SHOW EVENTS; -SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT from information_schema.events; -CREATE DATABASE events_test2; -CREATE USER ev_test@localhost; -GRANT ALL ON events_test.* to ev_test@localhost; -GRANT ALL on events_test2.* to ev_test@localhost; -REVOKE EVENT ON events_test2.* FROM ev_test@localhost; -REVOKE PROCESS on *.* from ev_test@localhost; -#now we are on con1 -connect (ev_con1,localhost,ev_test,,events_test2); -select "NEW CONNECTION"; -SELECT USER(), DATABASE(); -SHOW GRANTS; - ---echo "Here comes an error:"; -#NO EVENT_ACL on events_test2 ---error 1044 -SHOW EVENTS; -USE events_test; - ---echo "Now the list should be empty:"; ---replace_column 8 # 9 # -SHOW EVENTS; -#now create an event with the same name but we are different user -select concat("Let's create some new events from the name of ",user()); -create event one_event on schedule every 20 second do select 123; -create event two_event on schedule every 20 second on completion not preserve comment "two event" do select 123; -create event three_event on schedule every 20 second on completion preserve comment "three event" do select 123; - ---echo "Now we should see 3 events:"; ---replace_column 8 # 9 # -SHOW EVENTS; - ---echo "This should show us only 3 events:"; ---replace_column 8 # 9 # -SHOW FULL EVENTS; - ---echo "This should show us only 2 events:"; ---replace_column 8 # 9 # -SHOW FULL EVENTS LIKE 't%event'; - ---echo "This should show us no events:"; ---replace_column 8 # 9 # -SHOW FULL EVENTS FROM test LIKE '%'; -#ok, we are back -connection default; -DROP DATABASE events_test2; - ---echo "should see 1 event:"; ---replace_column 8 # 9 # -SHOW EVENTS; - ---echo "we should see 4 events now:"; ---replace_column 8 # 9 # -SHOW FULL EVENTS; -SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT from information_schema.events; - -connection ev_con1; -drop event one_event; -drop event two_event; -drop event three_event; -disconnect ev_con1; -connection default; -drop user ev_test@localhost; -drop event one_event; -# -##INFORMATION_SCHEMA.EVENTS test end -# - ---echo "Sleep a bit so the server closes the second connection" ---sleep 2 create event e_26 on schedule at '2017-01-01 00:00:00' disable do set @a = 5; select db, name, body, definer, convert_tz(execute_at, 'UTC', 'SYSTEM'), on_completion from mysql.event; drop event e_26; --- New file --- +++ mysql-test/t/events_tamper.test 06/02/19 02:38:24 create database if not exists events_test; use events_test; # # mysql.event intact checking start # # There should be at least 1 second between the ALTERs or we can't catch the change of create_time!! # CREATE EVENT intact_check ON SCHEDULE EVERY 10 HOUR DO SELECT "nothing"; --replace_column 8 # 9 # SHOW EVENTS; ALTER TABLE mysql.event ADD dummy INT FIRST; --error 1525 SHOW EVENTS; ALTER TABLE mysql.event DROP dummy, ADD dummy2 VARCHAR(64) FIRST; --error 1525 SHOW EVENTS; ALTER TABLE mysql.event DROP dummy2; --replace_column 8 # 9 # SHOW EVENTS; CREATE TABLE event_like LIKE mysql.event; INSERT INTO event_like SELECT * FROM mysql.event; #sleep a bit or we won't catch the change of time --sleep 1 ALTER TABLE mysql.event MODIFY db char(20) character set utf8 collate utf8_bin default ''; #wait a bit or we won't see the difference because of seconds resolution --sleep 1 SHOW CREATE TABLE mysql.event; --error 1526 SELECT event_name FROM INFORMATION_SCHEMA.EVENTS; --sleep 1 ALTER TABLE mysql.event MODIFY db char(64) character set utf8 collate utf8_bin default ''; --sleep 1 --echo "This should work" --replace_column 8 # 9 # SHOW EVENTS; ALTER TABLE mysql.event MODIFY db char(64) character set cp1251 default ''; --sleep 2 --error 1526 SELECT event_name FROM INFORMATION_SCHEMA.EVENTS; ALTER TABLE mysql.event MODIFY db varchar(64) character set utf8 collate utf8_bin default ''; --sleep 2 --error 1526 SELECT event_name FROM INFORMATION_SCHEMA.EVENTS; ALTER TABLE mysql.event DROP comment, DROP starts; --sleep 2 --error 1525 SELECT event_name FROM INFORMATION_SCHEMA.EVENTS; DROP TABLE mysql.event; CREATE TABLE mysql.event like event_like; INSERT INTO mysql.event SELECT * FROM event_like; --echo "Now dropping one index to see whether index tampering check works" ALTER TABLE mysql.event DROP PRIMARY KEY; --sleep 2 --error 1526 SELECT event_name FROM INFORMATION_SCHEMA.EVENTS; --echo "Recreating, should work now:" DROP TABLE mysql.event; CREATE TABLE mysql.event like event_like; INSERT INTO mysql.event SELECT * FROM event_like; --echo "Test whether everything is fine" SELECT event_name FROM INFORMATION_SCHEMA.EVENTS; ALTER TABLE mysql.event DROP INDEX db_definer_name; SHOW CREATE TABLE mysql.event; #--sleep 2 #--error 1526 #SELECT event_name FROM INFORMATION_SCHEMA.EVENTS; --echo "Now let's bork the index and see whether we catch it" ALTER TABLE mysql.event ADD UNIQUE db_definer_name(db, name, definer); --sleep 2 --error 1526 SELECT event_name FROM INFORMATION_SCHEMA.EVENTS; ALTER TABLE mysql.event DROP KEY db_definer_name; --echo "Make the key shorter" ALTER TABLE mysql.event ADD UNIQUE db_definer_name(db, name); --sleep 2 --error 1526 SELECT event_name FROM INFORMATION_SCHEMA.EVENTS; ALTER TABLE mysql.event DROP KEY db_definer_name; --echo "Try with longer index, this should work" ALTER TABLE mysql.event ADD UNIQUE db_definer_name(db, definer, name, execute_at); --sleep 2 --echo "No error:" SELECT event_name FROM INFORMATION_SCHEMA.EVENTS; --echo "Add 1 more index, that should not be a problem - downgrading is ok" ALTER TABLE mysql.event ADD KEY dummy_index(execute_at); --sleep 2 --echo "No error:" SELECT event_name FROM INFORMATION_SCHEMA.EVENTS; --echo "Recreating" DROP TABLE mysql.event; CREATE TABLE mysql.event like event_like; INSERT INTO mysql.event SELECT * FROM event_like; DROP TABLE event_like; --replace_column 8 # 9 # SHOW EVENTS; DROP EVENT intact_check; # # mysql.event intact checking end # drop database events_test; --- 1.30/sql/event.cc 2006-02-16 13:11:06 +01:00 +++ 1.31/sql/event.cc 2006-02-19 02:38:20 +01:00 @@ -66,10 +66,15 @@ QUEUE EVEX_EQ_NAME; MEM_ROOT evex_mem_root; time_t mysql_event_last_create_time= 0L; +TABLE_KEY_FOR_CHECK event_table_keys[4]= { + { (char *) STRING_WITH_LEN("\x04\x01\x02") }, + { (char *) STRING_WITH_LEN("\x01\x04\x02") }, + { NULL, 0} +}; -static TABLE_FIELD_W_TYPE event_table_fields[EVEX_FIELD_COUNT] = { +TABLE_FIELD_W_TYPE event_table_fields[EVEX_FIELD_COUNT] = { { - {(char *) STRING_WITH_LEN("db")}, + {(char *) STRING_WITH_LEN("db")}, {(char *) STRING_WITH_LEN("char(64)")}, {(char *) STRING_WITH_LEN("utf8")} }, @@ -162,25 +167,25 @@ static TABLE_FIELD_W_TYPE event_table_fi LEX_STRING interval_type_to_name[] = { - {(char *) STRING_WITH_LEN("YEAR")}, - {(char *) STRING_WITH_LEN("QUARTER")}, - {(char *) STRING_WITH_LEN("MONTH")}, - {(char *) STRING_WITH_LEN("DAY")}, - {(char *) STRING_WITH_LEN("HOUR")}, - {(char *) STRING_WITH_LEN("MINUTE")}, - {(char *) STRING_WITH_LEN("WEEK")}, - {(char *) STRING_WITH_LEN("SECOND")}, - {(char *) STRING_WITH_LEN("MICROSECOND")}, - {(char *) STRING_WITH_LEN("YEAR_MONTH")}, - {(char *) STRING_WITH_LEN("DAY_HOUR")}, - {(char *) STRING_WITH_LEN("DAY_MINUTE")}, - {(char *) STRING_WITH_LEN("DAY_SECOND")}, - {(char *) STRING_WITH_LEN("HOUR_MINUTE")}, - {(char *) STRING_WITH_LEN("HOUR_SECOND")}, - {(char *) STRING_WITH_LEN("MINUTE_SECOND")}, - {(char *) STRING_WITH_LEN("DAY_MICROSECOND")}, - {(char *) STRING_WITH_LEN("HOUR_MICROSECOND")}, - {(char *) STRING_WITH_LEN("MINUTE_MICROSECOND")}, + {(char *) STRING_WITH_LEN("YEAR")}, + {(char *) STRING_WITH_LEN("QUARTER")}, + {(char *) STRING_WITH_LEN("MONTH")}, + {(char *) STRING_WITH_LEN("DAY")}, + {(char *) STRING_WITH_LEN("HOUR")}, + {(char *) STRING_WITH_LEN("MINUTE")}, + {(char *) STRING_WITH_LEN("WEEK")}, + {(char *) STRING_WITH_LEN("SECOND")}, + {(char *) STRING_WITH_LEN("MICROSECOND")}, + {(char *) STRING_WITH_LEN("YEAR_MONTH")}, + {(char *) STRING_WITH_LEN("DAY_HOUR")}, + {(char *) STRING_WITH_LEN("DAY_MINUTE")}, + {(char *) STRING_WITH_LEN("DAY_SECOND")}, + {(char *) STRING_WITH_LEN("HOUR_MINUTE")}, + {(char *) STRING_WITH_LEN("HOUR_SECOND")}, + {(char *) STRING_WITH_LEN("MINUTE_SECOND")}, + {(char *) STRING_WITH_LEN("DAY_MICROSECOND")}, + {(char *) STRING_WITH_LEN("HOUR_MICROSECOND")}, + {(char *) STRING_WITH_LEN("MINUTE_MICROSECOND")}, {(char *) STRING_WITH_LEN("SECOND_MICROSECOND")} }; @@ -369,7 +374,7 @@ event_reconstruct_interval_expression(St goto common_1_lev_code; case INTERVAL_HOUR_MINUTE: case INTERVAL_MINUTE_SECOND: - multipl= 60; + multipl= 60; common_1_lev_code: buf->append('\''); end= longlong10_to_str(expression/multipl, tmp_buff, 10); @@ -410,7 +415,7 @@ common_1_lev_code: expr= tmp_expr - (tmp_expr/60)*60; /* the code after the switch will finish */ } - break; + break; case INTERVAL_DAY_SECOND: { int tmp_expr= expr; @@ -493,7 +498,7 @@ evex_open_event_table(THD *thd, enum thr DBUG_RETURN(1); if (table_check_intact(tables.table, EVEX_FIELD_COUNT, event_table_fields, - &mysql_event_last_create_time, + event_table_keys, &mysql_event_last_create_time, ER_EVENT_CANNOT_LOAD_FROM_TABLE)) { close_thread_tables(thd); @@ -593,7 +598,7 @@ evex_db_find_event_by_name(THD *thd, con Returns 0 - ok EVEX_GENERAL_ERROR - bad data - EVEX_GET_FIELD_FAILED - field count does not match. table corrupted? + EVEX_GET_FIELD_FAILED - field count does not match. table corrupted? DESCRIPTION Used both when an event is created and when it is altered. @@ -641,7 +646,7 @@ evex_fill_row(THD *thd, TABLE *table, ev table->field[EVEX_FIELD_ENDS]-> store_time(&et->ends, MYSQL_TIMESTAMP_DATETIME); } - + if (et->expression) { table->field[EVEX_FIELD_INTERVAL_EXPR]->set_notnull(); @@ -664,8 +669,8 @@ evex_fill_row(THD *thd, TABLE *table, ev table->field[EVEX_FIELD_EXECUTE_AT]->set_notnull(); table->field[EVEX_FIELD_EXECUTE_AT]->store_time(&et->execute_at, - MYSQL_TIMESTAMP_DATETIME); - + MYSQL_TIMESTAMP_DATETIME); + table->field[EVEX_FIELD_TRANSIENT_INTERVAL]->set_null(); } else @@ -674,7 +679,7 @@ evex_fill_row(THD *thd, TABLE *table, ev // it is normal to be here when the action is update // this is an error if the action is create. something is borked } - + ((Field_timestamp *)table->field[EVEX_FIELD_MODIFIED])->set_time(); if (et->comment.length) @@ -698,7 +703,7 @@ trunc_err: et event_timed object containing information for the event create_if_not - if an warning should be generated in case event exists rows_affected - how many rows were affected - + Return value 0 - OK EVEX_GENERAL_ERROR - Failure @@ -726,7 +731,7 @@ db_create_event(THD *thd, event_timed *e my_error(ER_EVENT_OPEN_TABLE_FAILED, MYF(0)); goto err; } - + DBUG_PRINT("info", ("check existance of an event with the same name")); if (!evex_db_find_event_aux(thd, et, table)) { @@ -735,7 +740,7 @@ db_create_event(THD *thd, event_timed *e push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_EVENT_ALREADY_EXISTS, ER(ER_EVENT_ALREADY_EXISTS), et->name.str); - goto ok; + goto ok; } my_error(ER_EVENT_ALREADY_EXISTS, MYF(0), et->name.str); goto err; @@ -747,7 +752,7 @@ db_create_event(THD *thd, event_timed *e my_error(ER_BAD_DB_ERROR, MYF(0)); goto err; } - + restore_record(table, s->default_values); // Get default values for fields if (system_charset_info->cset->numchars(system_charset_info, et->dbname.str, @@ -831,7 +836,7 @@ err: thd THD sp_name the name of the event to alter et event's data - + NOTES sp_name is passed since this is the name of the event to alter in case of RENAME TO. @@ -931,7 +936,7 @@ err: definer who owns the event ett event's data if event is found tbl TABLE object to use when not NULL - + NOTES 1) Use sp_name for look up, return in **ett if found 2) tbl is not closed at exit @@ -967,7 +972,7 @@ db_find_event(THD *thd, sp_name *name, L goto done; } et= new event_timed; - + /* 1)The table should not be closed beforehand. ::load_from_row() only loads and does not compile @@ -1146,7 +1151,7 @@ done: create_options Options specified when in the query. We are interested whether there is IF NOT EXISTS rows_affected How many rows were affected - + NOTES - in case there is an event with the same name (db) and IF NOT EXISTS is specified, an warning is put into the W stack. @@ -1190,7 +1195,7 @@ done: thd THD et event's data new_name set in case of RENAME TO. - + NOTES et contains data about dbname and event name. new_name is the new name of the event, if not null (this means @@ -1312,7 +1317,7 @@ done: et event's name drop_if_exists if set and the event not existing => warning onto the stack rows_affected affected number of rows is returned heres - + */ int @@ -1349,11 +1354,11 @@ evex_drop_event(THD *thd, event_timed *e thd THD spn the name of the event (db, name) definer the definer of the event - + RETURNS 0 - OK 1 - Error during writing to the wire - + */ int @@ -1378,7 +1383,7 @@ evex_show_create_event(THD *thd, sp_name List field_list; const char *sql_mode_str; ulong sql_mode_len=0; - + show_str.length(0); show_str.set_charset(system_charset_info); @@ -1404,19 +1409,19 @@ evex_show_create_event(THD *thd, sp_name protocol->store((char*) sql_mode_str, sql_mode_len, system_charset_info); - + protocol->store(show_str.c_ptr(), show_str.length(), system_charset_info); ret= protocol->write(); send_eof(thd); } - + DBUG_RETURN(ret); } /* evex_drop_db_events - Drops all events in the selected database - + thd - Thread db - ASCIIZ the name of the database --- 1.30/sql/event_executor.cc 2006-02-16 01:27:30 +01:00 +++ 1.31/sql/event_executor.cc 2006-02-19 02:38:20 +01:00 @@ -151,7 +151,8 @@ evex_check_system_tables() else { table_check_intact(tables.table, MYSQL_DB_FIELD_COUNT, mysql_db_table_fields, - &mysql_db_table_last_check,ER_EVENT_CANNOT_LOAD_FROM_TABLE); + NULL, &mysql_db_table_last_check, + ER_EVENT_CANNOT_LOAD_FROM_TABLE); close_thread_tables(thd); } @@ -377,7 +378,6 @@ executor_wait_till_next_event_exec(THD * DBUG_RETURN(ret); } - /* The main scheduler thread. Inits the priority queue on start and destroys it on thread shutdown. Forks child threads for every event @@ -402,12 +402,12 @@ event_executor_main(void *arg) TIME time_now; DBUG_ENTER("event_executor_main"); - DBUG_PRINT("event_executor_main", ("EVEX thread started")); + DBUG_PRINT("event_executor_main", ("EVEX thread started")); + sql_print_information("SCHEDULER: Starting"); // init memory root init_alloc_root(&evex_mem_root, MEM_ROOT_BLOCK_SIZE, MEM_ROOT_PREALLOC); - // needs to call my_thread_init(), otherwise we get a coredump in DBUG_ stuff my_thread_init(); @@ -643,9 +643,9 @@ finish: err_no_thd: VOID(pthread_mutex_lock(&LOCK_evex_running)); - evex_is_running= false; + evex_is_running= false; + event_executor_running_global_var= false; VOID(pthread_mutex_unlock(&LOCK_evex_running)); - free_root(&evex_mem_root, MYF(0)); sql_print_information("SCHEDULER: Stopped."); --- 1.24/mysql-test/lib/init_db.sql 2006-02-01 19:27:04 +01:00 +++ 1.25/mysql-test/lib/init_db.sql 2006-02-19 02:38:19 +01:00 @@ -631,7 +631,8 @@ CREATE TABLE event ( 'HIGH_NOT_PRECEDENCE' ) DEFAULT '' NOT NULL, comment char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', - PRIMARY KEY (definer, db, name) + PRIMARY KEY (definer, db, name), + UNIQUE KEY db_definer_name(db, definer, name) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT 'Events'; CREATE DATABASE IF NOT EXISTS cluster_replication; --- 1.40/scripts/mysql_fix_privilege_tables.sql 2006-02-02 11:35:58 +01:00 +++ 1.41/scripts/mysql_fix_privilege_tables.sql 2006-02-19 02:38:20 +01:00 @@ -622,7 +622,8 @@ CREATE TABLE event ( 'HIGH_NOT_PRECEDENCE' ) DEFAULT '' NOT NULL, comment char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '', - PRIMARY KEY (db,name) + PRIMARY KEY (db,name), + UNIQUE KEY db_definer_name(db, definer, name) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT 'Events'; @@ -666,7 +667,7 @@ ALTER TABLE event ADD sql_mode 'NO_AUTO_CREATE_USER', 'HIGH_NOT_PRECEDENCE' ) DEFAULT '' NOT NULL AFTER on_completion; - +ALTER TABLE event ADD UNIQUE KEY db_definer_name(db, definer, name); -- -- TRIGGER privilege -- --- 1.38/mysql-test/r/system_mysql_db.result 2006-02-02 11:35:57 +01:00 +++ 1.39/mysql-test/r/system_mysql_db.result 2006-02-19 02:38:20 +01:00 @@ -208,7 +208,8 @@ event CREATE TABLE `event` ( `on_completion` enum('DROP','PRESERVE') NOT NULL default 'DROP', `sql_mode` set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES','STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES','ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER','HIGH_NOT_PRECEDENCE') NOT NULL default '', `comment` char(64) character set utf8 collate utf8_bin NOT NULL default '', - PRIMARY KEY (`definer`,`db`,`name`) + PRIMARY KEY (`definer`,`db`,`name`), + UNIQUE KEY `db_definer_name` (`db`,`definer`,`name`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Events' show create table general_log; Table Create Table --- 1.37/scripts/mysql_create_system_tables.sh 2006-02-01 11:28:40 +01:00 +++ 1.38/scripts/mysql_create_system_tables.sh 2006-02-19 02:38:20 +01:00 @@ -827,7 +827,8 @@ then c_ev="$c_ev 'HIGH_NOT_PRECEDENCE'" c_ev="$c_ev ) DEFAULT '' NOT NULL," c_ev="$c_ev comment char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default ''," - c_ev="$c_ev PRIMARY KEY (definer, db, name)" + c_ev="$c_ev PRIMARY KEY (definer, db, name)," + c_ev="$c_ev UNIQUE KEY db_definer_name(db, definer, name)" c_ev="$c_ev ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT 'Events';" fi