List:Commits« Previous MessageNext Message »
From:ahristov Date:March 5 2006 7:37pm
Subject:bk commit into 5.1 tree (andrey:1.2214) BUG#16394
View as plain text  
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.2214 06/03/05 20:36:45 andrey@lmy004. +9 -0
  fix for bug #16394: Events: Crash if schedule contains SELECT

  sql/sql_yacc.yy
    1.472 06/03/05 20:36:23 andrey@lmy004. +18 -75
    use late fix_fields of AT/EVERY/STARTS/ENDS

  sql/event_timed.cc
    1.46 06/03/05 20:36:23 andrey@lmy004. +112 -23
    - late parsing of the AT/EVERY/STARTS/ENDS to support SUBqueries

  sql/event_executor.cc
    1.42 06/03/05 20:36:22 andrey@lmy004. +3 -2
    - 1s is too much time for sleeping, kick in.

  sql/event.h
    1.27 06/03/05 20:36:22 andrey@lmy004. +14 -1
    - add member variables to class Event_timed which are used for the late
      checking of Item* (not in the parser).

  sql/event.cc
    1.38 06/03/05 20:36:21 andrey@lmy004. +103 -11
    - initialization of AT, EVERY, STARTS and ENDS moved from the parser to after parsing
    - tables are opened in one shot, a subquery may open mysql.event again but for read (
      SELECT * FROM information_schema.events) for instance but that's not a problem and is
      tested.
    - check the rights with SELECT before attempting open because if we add mysql.event before
      the check the user has to have always SELECT on mysql.event to be able to use CREATE EVENT

  mysql-test/t/events_bugs.test
    1.2 06/03/05 20:36:21 andrey@lmy004. +64 -0
    add tests

  mysql-test/t/events.test
    1.23 06/03/05 20:36:21 andrey@lmy004. +20 -3
    add more tests

  mysql-test/r/events_bugs.result
    1.3 06/03/05 20:36:20 andrey@lmy004. +72 -0
    update results

  mysql-test/r/events.result
    1.28 06/03/05 20:36:19 andrey@lmy004. +21 -3
    update results

# 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-bug17494

--- 1.471/sql/sql_yacc.yy	2006-03-01 21:39:23 +01:00
+++ 1.472/sql/sql_yacc.yy	2006-03-05 20:36:23 +01:00
@@ -770,7 +770,7 @@ bool my_yyoverflow(short **a, YYSTYPE **
 	signed_literal now_or_signed_literal opt_escape
 	sp_opt_default
 	simple_ident_nospvar simple_ident_q
-        field_or_var limit_option
+        field_or_var limit_option ev_starts ev_ends
         part_func_expr
 
 %type <item_num>
@@ -1317,7 +1317,7 @@ create:
 	    YYTHD->client_capabilities |= $<ulong_num>4;
 	    sp->restore_thd_mem_root(YYTHD);
 	  }
-	| CREATE EVENT_SYM opt_if_not_exists sp_name
+       | CREATE EVENT_SYM opt_if_not_exists sp_name
           /*
              BE CAREFUL when you add a new rule to update the block where
              YYTHD->client_capabilities is set back to original value
@@ -1375,6 +1375,7 @@ create:
               sql_command is set here because some rules in ev_sql_stmt
               can overwrite it
             */
+            Lex->select_lex.db= 0;
             Lex->sql_command= SQLCOM_CREATE_EVENT;
           }
 	| CREATE
@@ -1402,53 +1403,27 @@ create:
 	;
 
 
-ev_schedule_time: EVERY_SYM expr interval
-	  {
-            LEX *lex=Lex;
+ev_schedule_time: EVERY_SYM expr interval ev_starts ev_ends
+          {
+            LEX *lex= Lex;
             if (!lex->et_compile_phase)
             {
-              switch (lex->et->init_interval(YYTHD , $2, $3)) {
-              case EVEX_PARSE_ERROR:
-                yyerror(ER(ER_SYNTAX_ERROR));
-                YYABORT;
-                break;
-              case EVEX_BAD_PARAMS:
-                my_error(ER_EVENT_INTERVAL_NOT_POSITIVE_OR_TOO_BIG, MYF(0));
-              case EVEX_MICROSECOND_UNSUP:
+              if (lex->et->is_valid_interval_type($3))
+              {
                 my_error(ER_NOT_SUPPORTED_YET, MYF(0), "MICROSECOND");
                 YYABORT;
-                break;
               }
+              lex->et->parse_items.interval_expr= $2;
+              lex->et->interval= $3;
+              lex->et->parse_items.starts= $4;
+              lex->et->parse_items.ends= $5;
             }
           }
-          ev_starts
-          ev_ends
         | AT_SYM expr
           {
             LEX *lex=Lex;
             if (!lex->et_compile_phase)
-            {
-              switch (lex->et->init_execute_at(YYTHD, $2)) {
-              case EVEX_PARSE_ERROR:
-                yyerror(ER(ER_SYNTAX_ERROR));
-                YYABORT;  
-                break;
-              case ER_WRONG_VALUE:
-                {
-                  char buff[120];
-                  String str(buff,(uint32) sizeof(buff), system_charset_info);
-                  String *str2= $2->val_str(&str);
-                  my_error(ER_WRONG_VALUE, MYF(0), "AT",
-                           str2? str2->c_ptr():"NULL");
-                  YYABORT;
-                  break;
-                }
-              case EVEX_BAD_PARAMS:
-                my_error(ER_EVENT_EXEC_TIME_IN_THE_PAST, MYF(0));
-                YYABORT;
-                break;
-              }
-            }
+              lex->et->parse_items.execute_at= $2;
           }
       ;
 
@@ -1472,51 +1447,18 @@ opt_ev_status: /* empty */ { $$= 0; }
 
 ev_starts: /* empty */
           {
-            Lex->et->init_starts(YYTHD, new Item_func_now_local());
+            $$= new Item_func_now_local();
           }
         | STARTS_SYM expr
           {
-            LEX *lex= Lex;
-            if (!lex->et_compile_phase)
-            {
-
-              switch (lex->et->init_starts(YYTHD, $2)) {
-              case EVEX_PARSE_ERROR:
-                yyerror(ER(ER_SYNTAX_ERROR));
-                YYABORT;
-                break;
-              case EVEX_BAD_PARAMS:
-                {
-                  char buff[20];
-                  String str(buff,(uint32) sizeof(buff), system_charset_info);
-                  String *str2= $2->val_str(&str);
-                  my_error(ER_WRONG_VALUE, MYF(0), "STARTS", str2? str2->c_ptr():
-                                                                   NULL);
-                  YYABORT;
-                  break;
-                }
-              }
-            }
+            $$= $2;
           }
       ;
 
-ev_ends: /* empty */
+ev_ends: /* empty */ { $$= NULL;}
         | ENDS_SYM expr
           {
-            LEX *lex= Lex;
-            if (!lex->et_compile_phase)
-            {
-              switch (lex->et->init_ends(YYTHD, $2)) {
-              case EVEX_PARSE_ERROR:
-                yyerror(ER(ER_SYNTAX_ERROR));
-                YYABORT;
-                break;
-              case EVEX_BAD_PARAMS:
-                my_error(ER_EVENT_ENDS_BEFORE_STARTS, MYF(0));
-                YYABORT;
-                break;
-              }
-            }
+            $$= $2;
           }
       ;
 
@@ -4878,6 +4820,7 @@ alter:
 	      yyerror(ER(ER_SYNTAX_ERROR));
               YYABORT;
             }
+            Lex->select_lex.db= 0;
             Lex->sql_command= SQLCOM_ALTER_EVENT;
           }
         | ALTER TABLESPACE alter_tablespace_info

--- 1.27/mysql-test/r/events.result	2006-02-28 14:43:41 +01:00
+++ 1.28/mysql-test/r/events.result	2006-03-05 20:36:19 +01:00
@@ -106,7 +106,6 @@ drop event if exists event3;
 Warnings:
 Note	1305	Event event3 does not exist
 create event event3 on schedule every 50 + 10 minute starts date_add("20100101", interval 5 minute) ends date_add("20151010", interval 5 day) comment "portokala_comment" DO insert into t_event3 values (unix_timestamp(), rand());
-set max_allowed_packet=128000000;
 select count(*) from t_event3;
 count(*)
 0
@@ -364,10 +363,28 @@ select db, name, body, definer, convert_
 db	name	body	definer	convert_tz(execute_at, 'UTC', 'SYSTEM')	on_completion
 events_test	e_26	set @a = 5	root@localhost	2017-01-01 00:00:00	DROP
 drop event e_26;
-create event e_26 on schedule at NULL disabled do set @a = 5;
+create event e_26 on schedule at NULL disable do set @a = 5;
 ERROR HY000: Incorrect AT value: 'NULL'
-create event e_26 on schedule at 'definitely not a datetime' disabled do set @a = 5;
+create event e_26 on schedule at 'definitely not a datetime' disable do set @a = 5;
 ERROR HY000: Incorrect AT value: 'definitely not a datetime'
+create event e_26 on schedule every NULL minute do set @a=7;
+ERROR HY000: Incorrect INTERVAL value: 'NULL'
+create event e_26 on schedule every 1 minute starts NULL do set @a=8;
+ERROR HY000: Incorrect STARTS value: 'NULL'
+create event e_26 on schedule every 1 minute ends NULL do set @a=9;
+ERROR HY000: ENDS is either invalid or before STARTS
+create event e_26 on schedule every 1 minute comment NULL do set @a=10;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'NULL do set @a=10' at line 1
+create event e_26 on schedule every -2 minute do set @a=11;
+ERROR HY000: Incorrect INTERVAL value: '-2'
+create event e_26 on schedule every text minute do set @a=12;
+ERROR 42S22: Unknown column 'text' in 'field list'
+create event e_26 on schedule every 'text' minute do set @a=13;
+ERROR HY000: Incorrect INTERVAL value: 'text'
+create event e_26 on schedule every '13' minute do set @a=14;
+DROP EVENT e_26;
+create event e_26 on schedule every 'a13' minute do set @a=14;
+ERROR HY000: Incorrect INTERVAL value: 'a13'
 set names utf8;
 create event задачка on schedule every 123 minute starts now() ends now() + interval 1 month do select 1;
 drop event задачка;
@@ -440,6 +457,7 @@ release_lock("test_lock2_1")
 show processlist;
 Id	User	Host	db	Command	Time	State	Info
 #	root	localhost	events_test	Query	#	NULL	show processlist
+#	event_scheduler	localhost	NULL	Connect	#	Sleeping	NULL
 drop event закачка21;
 create table t_16 (s1 int);
 create trigger t_16_bi before insert on t_16 for each row create event  e_16 on schedule every 1 second do set @a=5;

--- 1.2/mysql-test/r/events_bugs.result	2006-02-21 02:40:15 +01:00
+++ 1.3/mysql-test/r/events_bugs.result	2006-03-05 20:36:20 +01:00
@@ -146,4 +146,76 @@ drop procedure ee_16407_6_pendant;
 set global event_scheduler= 0;
 drop table events_smode_test;
 set sql_mode=@old_sql_mode;
+set global event_scheduler= 0;
+CREATE EVENT e_53 ON SCHEDULE AT (select s1 from ttx)  DO DROP TABLE t;
+ERROR 42S02: Table 'events_test.ttx' doesn't exist
+CREATE EVENT e_53 ON SCHEDULE AT (select s1 from ttx)  DO SELECT 2 FROM DUAL;
+ERROR 42S02: Table 'events_test.ttx' doesn't exist
+CREATE EVENT e_53 ON SCHEDULE AT (select '2020-02-02 20:22:24')  DO SELECT 3 FROM DUAL;
+SHOW EVENTS;
+Db	Name	Definer	Type	Execute at	Interval value	Interval field	Starts	Ends	Status
+events_test	e_53	root@localhost	ONE TIME	2020-02-02 17:22:24	NULL	NULL	NULL	NULL	ENABLED
+DROP EVENT e_53;
+CREATE EVENT e_53 ON SCHEDULE AT (select '2020-02-22 22:11:05')  DO SELECT 4 FROM DUAL;
+SHOW EVENTS;
+Db	Name	Definer	Type	Execute at	Interval value	Interval field	Starts	Ends	Status
+events_test	e_53	root@localhost	ONE TIME	2020-02-22 19:11:05	NULL	NULL	NULL	NULL	ENABLED
+DROP EVENT e_53;
+CREATE EVENT e_53 ON SCHEDULE EVERY (SELECT 5) MINUTE DO SELECT 5 FROM DUAL;
+SHOW EVENTS;
+Db	Name	Definer	Type	Execute at	Interval value	Interval field	Starts	Ends	Status
+events_test	e_53	root@localhost	RECURRING	NULL	5	MINUTE	#	NULL	ENABLED
+DROP EVENT e_53;
+CREATE TABLE t16394 (a int) ENGINE=MYISAM;
+INSERT INTO t16394 VALUES (7);
+CREATE EVENT e_53 ON SCHEDULE EVERY (SELECT * FROM t16394) MINUTE DO SELECT 7 FROM DUAL;
+SHOW EVENTS;
+Db	Name	Definer	Type	Execute at	Interval value	Interval field	Starts	Ends	Status
+events_test	e_53	root@localhost	RECURRING	NULL	7	MINUTE	#	NULL	ENABLED
+DROP EVENT e_53;
+INSERT INTO t16394 VALUES (2);
+CREATE EVENT e_53 ON SCHEDULE EVERY (SELECT * FROM t16394) MINUTE DO SELECT 9 FROM DUAL;
+ERROR 21000: Subquery returns more than 1 row
+SHOW EVENTS;
+Db	Name	Definer	Type	Execute at	Interval value	Interval field	Starts	Ends	Status
+TRUNCATE t16394;
+INSERT INTO t16394 VALUES (11);
+CREATE TABLE t16394_times (dt datetime, typ enum ('STARTS', 'ENDS') default 'STARTS' not null);
+INSERT INTO t16394_times VALUES (DATE_ADD('2020-02-19 20:21:22', INTERVAL 5 SECOND), 'STARTS');
+INSERT INTO t16394_times VALUES (DATE_ADD('2020-02-19 20:21:22', INTERVAL 15 SECOND), 'ENDS');
+CREATE EVENT e_53
+ON SCHEDULE EVERY (SELECT * FROM t16394) MINUTE
+STARTS (SELECT dt FROM t16394_times WHERE typ='STARTS')
+ENDS (SELECT dt FROM t16394_times WHERE typ='ENDS')
+DO
+BEGIN
+SELECT typ FROM t16394_times;
+END|
+SHOW EVENTS|
+Db	Name	Definer	Type	Execute at	Interval value	Interval field	Starts	Ends	Status
+events_test	e_53	root@localhost	RECURRING	NULL	11	MINUTE	2020-02-19 17:21:27	2020-02-19 17:21:37	ENABLED
+SELECT interval_value FROM mysql.event WHERE db=database() and name='e_53'|
+interval_value
+11
+SELECT starts FROM mysql.event WHERE db=database() and name='e_53'|
+starts
+2020-02-19 17:21:27
+SELECT ENDS FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA=database() and EVENT_NAME='e_53'|
+ENDS
+2020-02-19 17:21:37
+CREATE EVENT e_53_clone
+ON SCHEDULE EVERY (SELECT interval_value FROM mysql.event WHERE db=database() and name='e_53') MINUTE
+STARTS (SELECT starts FROM mysql.event WHERE db=database() and name='e_53')
+ENDS (SELECT ENDS FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA=database() and EVENT_NAME='e_53')
+DO
+BEGIN
+SELECT STARTS FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA=database() AND EVENT_NAME='e_53_clone';
+END|
+SHOW EVENTS;
+Db	Name	Definer	Type	Execute at	Interval value	Interval field	Starts	Ends	Status
+events_test	e_53	root@localhost	RECURRING	NULL	11	MINUTE	2020-02-19 17:21:27	2020-02-19 17:21:37	ENABLED
+events_test	e_53_clone	root@localhost	RECURRING	NULL	11	MINUTE	2020-02-19 14:21:27	2020-02-19 14:21:37	ENABLED
+DROP EVENT e_53;
+DROP TABLE t16394;
+DROP TABLE t16394_times;
 drop database events_test;

--- 1.22/mysql-test/t/events.test	2006-02-28 11:46:00 +01:00
+++ 1.23/mysql-test/t/events.test	2006-03-05 20:36:21 +01:00
@@ -101,7 +101,6 @@ set global event_scheduler = 0;
 create table t_event3 (a int, b float);
 drop event if exists event3;
 create event event3 on schedule every 50 + 10 minute starts date_add("20100101", interval 5 minute) ends date_add("20151010", interval 5 day) comment "portokala_comment" DO insert into t_event3 values (unix_timestamp(), rand());
-set max_allowed_packet=128000000;
 select count(*) from t_event3;
 drop event event3;
 drop table t_event3;
@@ -318,9 +317,27 @@ create event e_26 on schedule at '2017-0
 select db, name, body, definer, convert_tz(execute_at, 'UTC', 'SYSTEM'), on_completion from mysql.event;
 drop event e_26;
 --error 1503
-create event e_26 on schedule at NULL disabled do set @a = 5;
+create event e_26 on schedule at NULL disable do set @a = 5;
 --error 1503
-create event e_26 on schedule at 'definitely not a datetime' disabled do set @a = 5;
+create event e_26 on schedule at 'definitely not a datetime' disable do set @a = 5;
+--error 1503
+create event e_26 on schedule every NULL minute do set @a=7;
+--error 1503
+create event e_26 on schedule every 1 minute starts NULL do set @a=8;
+--error 1521
+create event e_26 on schedule every 1 minute ends NULL do set @a=9;
+--error 1064
+create event e_26 on schedule every 1 minute comment NULL do set @a=10;
+--error 1503
+create event e_26 on schedule every -2 minute do set @a=11;
+--error 1054
+create event e_26 on schedule every text minute do set @a=12;
+--error 1503
+create event e_26 on schedule every 'text' minute do set @a=13;
+create event e_26 on schedule every '13' minute do set @a=14;
+DROP EVENT e_26;
+--error 1503
+create event e_26 on schedule every 'a13' minute do set @a=14;
 
 set names utf8;
 create event задачка on schedule every 123 minute starts now() ends now() + interval 1 month do select 1;

--- 1.1/mysql-test/t/events_bugs.test	2006-02-20 23:52:12 +01:00
+++ 1.2/mysql-test/t/events_bugs.test	2006-03-05 20:36:21 +01:00
@@ -118,4 +118,68 @@ set sql_mode=@old_sql_mode;
 #
 # End  - 16407: Events: Changes in sql_mode won't be taken into account  
 #
+
+#
+# Start - 16394: Events: Crash if schedule contains SELECT
+#
+set global event_scheduler= 0;
+--sleep 1
+--error 1146
+CREATE EVENT e_53 ON SCHEDULE AT (select s1 from ttx)  DO DROP TABLE t;
+--error 1146
+CREATE EVENT e_53 ON SCHEDULE AT (select s1 from ttx)  DO SELECT 2 FROM DUAL;
+CREATE EVENT e_53 ON SCHEDULE AT (select '2020-02-02 20:22:24')  DO SELECT 3 FROM DUAL;
+SHOW EVENTS;
+DROP EVENT e_53;
+CREATE EVENT e_53 ON SCHEDULE AT (select '2020-02-22 22:11:05')  DO SELECT 4 FROM DUAL;
+SHOW EVENTS;
+DROP EVENT e_53;
+CREATE EVENT e_53 ON SCHEDULE EVERY (SELECT 5) MINUTE DO SELECT 5 FROM DUAL;
+--replace_column 8 #
+SHOW EVENTS;
+DROP EVENT e_53;
+CREATE TABLE t16394 (a int) ENGINE=MYISAM;
+INSERT INTO t16394 VALUES (7);
+CREATE EVENT e_53 ON SCHEDULE EVERY (SELECT * FROM t16394) MINUTE DO SELECT 7 FROM DUAL;
+--replace_column 8 #
+SHOW EVENTS;
+DROP EVENT e_53;
+INSERT INTO t16394 VALUES (2);
+--error 1242
+CREATE EVENT e_53 ON SCHEDULE EVERY (SELECT * FROM t16394) MINUTE DO SELECT 9 FROM DUAL;
+SHOW EVENTS;
+TRUNCATE t16394;
+INSERT INTO t16394 VALUES (11);
+CREATE TABLE t16394_times (dt datetime, typ enum ('STARTS', 'ENDS') default 'STARTS' not null);
+INSERT INTO t16394_times VALUES (DATE_ADD('2020-02-19 20:21:22', INTERVAL 5 SECOND), 'STARTS');
+INSERT INTO t16394_times VALUES (DATE_ADD('2020-02-19 20:21:22', INTERVAL 15 SECOND), 'ENDS');
+DELIMITER |;
+CREATE EVENT e_53
+  ON SCHEDULE EVERY (SELECT * FROM t16394) MINUTE
+  STARTS (SELECT dt FROM t16394_times WHERE typ='STARTS')
+  ENDS (SELECT dt FROM t16394_times WHERE typ='ENDS')
+DO
+BEGIN
+  SELECT typ FROM t16394_times;
+END|
+SHOW EVENTS|
+SELECT interval_value FROM mysql.event WHERE db=database() and name='e_53'|
+SELECT starts FROM mysql.event WHERE db=database() and name='e_53'|
+SELECT ENDS FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA=database() and EVENT_NAME='e_53'|
+CREATE EVENT e_53_clone
+   ON SCHEDULE EVERY (SELECT interval_value FROM mysql.event WHERE db=database() and name='e_53') MINUTE
+  STARTS (SELECT starts FROM mysql.event WHERE db=database() and name='e_53')
+  ENDS (SELECT ENDS FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA=database() and EVENT_NAME='e_53')
+DO
+BEGIN
+  SELECT STARTS FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA=database() AND EVENT_NAME='e_53_clone';
+END|
+DELIMITER ;|
+SHOW EVENTS;
+DROP EVENT e_53;
+DROP TABLE t16394;
+DROP TABLE t16394_times;
+#
+# End  - 16394: Events: Crash if schedule contains SELECT
+#
 drop database events_test;

--- 1.37/sql/event.cc	2006-02-28 20:32:30 +01:00
+++ 1.38/sql/event.cc	2006-03-05 20:36:21 +01:00
@@ -481,7 +481,7 @@ int
 evex_open_event_table(THD *thd, enum thr_lock_type lock_type, TABLE **table)
 {
   TABLE_LIST tables;
-  DBUG_ENTER("open_proc_table");
+  DBUG_ENTER("evex_open_event_table");
 
   bzero((char*) &tables, sizeof(tables));
   tables.db= (char*) "mysql";
@@ -723,23 +723,26 @@ trunc_err:
 
 static int
 db_create_event(THD *thd, Event_timed *et, my_bool create_if_not,
-                uint *rows_affected)
+                uint *rows_affected, TABLE *table)
 {
   int ret= 0;
-  TABLE *table;
+//  TABLE *table;
   char olddb[128];
   bool dbchanged= false;
+  Open_tables_state backup;
   DBUG_ENTER("db_create_event");
   DBUG_PRINT("enter", ("name: %.*s", et->name.length, et->name.str));
 
   *rows_affected= 0;
   DBUG_PRINT("info", ("open mysql.event for update"));
+/*
+  thd->reset_n_backup_open_tables_state(&backup);
   if (evex_open_event_table(thd, TL_WRITE, &table))
   {
     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))
   {
@@ -830,6 +833,7 @@ ok:
     (void) mysql_change_db(thd, olddb, 1);
   if (table)
     close_thread_tables(thd);
+//  thd->restore_backup_open_tables_state(&backup);
   DBUG_RETURN(EVEX_OK);
 
 err:
@@ -837,6 +841,7 @@ err:
     (void) mysql_change_db(thd, olddb, 1);
   if (table)
     close_thread_tables(thd);
+//  thd->restore_backup_open_tables_state(&backup);
   DBUG_RETURN(EVEX_GENERAL_ERROR);
 }
 
@@ -856,10 +861,12 @@ err:
 */
 
 static int
-db_update_event(THD *thd, Event_timed *et, sp_name *new_name)
+db_update_event(THD *thd, Event_timed *et, sp_name *new_name, TABLE *table)
 {
-  TABLE *table;
+//  TABLE *table;
   int ret= EVEX_OPEN_TABLE_FAILED;
+  Open_tables_state backup;
+
   DBUG_ENTER("db_update_event");
   DBUG_PRINT("enter", ("dbname: %.*s", et->dbname.length, et->dbname.str));
   DBUG_PRINT("enter", ("name: %.*s", et->name.length, et->name.str));
@@ -867,13 +874,14 @@ db_update_event(THD *thd, Event_timed *e
   if (new_name)
     DBUG_PRINT("enter", ("rename to: %.*s", new_name->m_name.length,
                                             new_name->m_name.str));
-
+/*
+  thd->reset_n_backup_open_tables_state(&backup);
   if (evex_open_event_table(thd, TL_WRITE, &table))
   {
     my_error(ER_EVENT_OPEN_TABLE_FAILED, MYF(0));
     goto err;
   }
-  
+*/  
   /* first look whether we overwrite */
   if (new_name)
   {
@@ -928,11 +936,13 @@ db_update_event(THD *thd, Event_timed *e
 
   /* close mysql.event or we crash later when loading the event from disk */
   close_thread_tables(thd);
+//  thd->restore_backup_open_tables_state(&backup);
   DBUG_RETURN(0);
 
 err:
   if (table)
     close_thread_tables(thd);
+//  thd->restore_backup_open_tables_state(&backup);
   DBUG_RETURN(EVEX_GENERAL_ERROR);
 }
 
@@ -1150,6 +1160,61 @@ done:
   DBUG_RETURN(ret);
 }
 
+static
+int evex_check_timing_params(THD *thd, Event_timed *et)
+{
+  const char *pos= NULL;
+  Item *bad_item;
+
+  DBUG_ENTER("evex_check_init_params");
+  DBUG_PRINT("info", ("execute_at=0x%d expr=0x%d starts=0x%d ends=0x%d",
+                      et->parse_items.execute_at, et->parse_items.interval_expr,
+                      et->parse_items.starts, et->parse_items.ends));
+
+  if (et->parse_items.execute_at)
+  {
+    DBUG_PRINT("info", ("ONE TIME"));
+    if (et->init_execute_at(thd, et->parse_items.execute_at))
+    {
+      pos= "AT";
+      bad_item= et->parse_items.execute_at;
+      goto wrong_value;
+    }
+  }
+  else
+  {
+    DBUG_PRINT("info", ("RECURRING"));
+    if (et->parse_items.interval_expr &&
+        et->init_interval(thd, et->parse_items.interval_expr, et->interval))
+    {
+      pos= "INTERVAL";
+      bad_item= et->parse_items.interval_expr;
+      goto wrong_value;
+    }
+
+    if (et->parse_items.starts && et->init_starts(thd, et->parse_items.starts))
+    {
+      pos= "STARTS";
+      bad_item= et->parse_items.starts;
+      goto wrong_value;
+    }
+
+    if (et->parse_items.ends && et->init_ends(thd, et->parse_items.ends))
+    {
+      my_error(ER_EVENT_ENDS_BEFORE_STARTS, MYF(0));
+      DBUG_RETURN(EVEX_BAD_PARAMS);
+    }
+  }
+  DBUG_RETURN(0);
+wrong_value:
+  {
+    char buff[120];
+    String str(buff,(uint32) sizeof(buff), system_charset_info);
+    String *str2= bad_item->fixed? bad_item->val_str(&str):NULL;
+    my_error(ER_WRONG_VALUE, MYF(0), pos, str2? str2->c_ptr():"NULL");
+    DBUG_RETURN(EVEX_BAD_PARAMS);
+  }
+}
 
 /*
    The function exported to the world for creating of events.
@@ -1177,9 +1242,23 @@ evex_create_event(THD *thd, Event_timed 
   DBUG_PRINT("enter", ("name: %*s options:%d", et->name.length,
                 et->name.str, create_options));
 
+  TABLE_LIST *table_list;
+  LEX_STRING dbname={(char*) STRING_WITH_LEN("mysql")};
+  LEX_STRING tname= {(char*) STRING_WITH_LEN("event")};
+  Table_ident *ident= new Table_ident(thd, dbname, tname, 1);
+  if (check_table_access(thd, SELECT_ACL, thd->lex->query_tables, 0) ||
+      !(table_list= thd->lex->select_lex.
+         add_table_to_list(thd, ident, 0, 0, TL_WRITE, (List<String> *) 0,
+                           (List<String> *) 0)) ||
+      open_and_lock_tables(thd, thd->lex->query_tables))
+    DBUG_RETURN(1);
+
+  if ((ret= evex_check_timing_params(thd, et)))
+    goto done;
+
   if ((ret = db_create_event(thd, et,
                              create_options & HA_LEX_CREATE_IF_NOT_EXISTS,
-                             rows_affected)))
+                             rows_affected, table_list->table)))
     goto done;
 
   VOID(pthread_mutex_lock(&LOCK_evex_running));
@@ -1222,12 +1301,26 @@ evex_update_event(THD *thd, Event_timed 
   DBUG_ENTER("evex_update_event");
   DBUG_PRINT("enter", ("name: %*s", et->name.length, et->name.str));
 
+  TABLE_LIST *table_list;
+  LEX_STRING dbname={(char*) STRING_WITH_LEN("mysql")};
+  LEX_STRING tname= {(char*) STRING_WITH_LEN("event")};
+  Table_ident *ident= new Table_ident(thd, dbname, tname, 1);
+  if (check_table_access(thd, SELECT_ACL, thd->lex->query_tables, 0) ||
+      !(table_list= thd->lex->select_lex.
+         add_table_to_list(thd, ident, 0, 0, TL_WRITE, (List<String> *) 0,
+                           (List<String> *) 0)) ||
+      open_and_lock_tables(thd, thd->lex->query_tables))
+    DBUG_RETURN(1);
+
+  if ((ret= evex_check_timing_params(thd, et)))
+    goto done;
+
   /*
     db_update_event() opens & closes the table to prevent
     crash later in the code when loading and compiling the new definition.
     Also on error conditions my_error() is called so no need to handle here
   */
-  if ((ret= db_update_event(thd, et, new_name)))
+  if ((ret= db_update_event(thd, et, new_name, table_list->table)))
     goto done;
 
   VOID(pthread_mutex_lock(&LOCK_evex_running));
@@ -1336,7 +1429,6 @@ evex_drop_event(THD *thd, Event_timed *e
   int ret= 0;
 
   DBUG_ENTER("evex_drop_event");
-
 
   VOID(pthread_mutex_lock(&LOCK_evex_running));
   if (evex_is_running)

--- 1.26/sql/event.h	2006-02-28 18:33:25 +01:00
+++ 1.27/sql/event.h	2006-03-05 20:36:22 +01:00
@@ -87,8 +87,17 @@ class Event_timed
 
   bool status_changed;
   bool last_executed_changed;
+  
 
 public:
+  struct parse_items
+  {
+    Item *execute_at;
+    Item *interval_expr;
+    Item *starts;
+    Item *ends;
+  } parse_items;
+
   TIME last_executed;
 
   LEX_STRING dbname;
@@ -124,7 +133,8 @@ public:
 
   Event_timed():in_spawned_thread(0),locked_by_thread_id(0),
                 running(0), status_changed(false),
-                last_executed_changed(false), expression(0), created(0),
+                last_executed_changed(false),
+                expression(0), created(0),
                 modified(0), on_completion(MYSQL_EVENT_ON_COMPLETION_DROP),
                 status(MYSQL_EVENT_ENABLED), sphead(0), sql_mode(0), 
                 body_begin(0), dropped(false),
@@ -152,6 +162,9 @@ public:
   int
   init_execute_at(THD *thd, Item *expr);
 
+  static int
+  is_valid_interval_type(interval_type new_interval);
+  
   int
   init_interval(THD *thd, Item *expr, interval_type new_interval);
 

--- 1.41/sql/event_executor.cc	2006-03-01 04:21:57 +01:00
+++ 1.42/sql/event_executor.cc	2006-03-05 20:36:22 +01:00
@@ -352,6 +352,7 @@ executor_wait_till_next_event_exec(THD *
   VOID(pthread_mutex_unlock(&LOCK_event_arrays));
 
   DBUG_PRINT("evex main thread",("unlocked LOCK_event_arrays"));
+  t2sleep*=10;
   if (t2sleep > 0)
   {
     ulonglong modified= et->modified;
@@ -366,7 +367,7 @@ executor_wait_till_next_event_exec(THD *
              modified))
     {
       DBUG_PRINT("evex main thread",("will sleep a bit more."));
-      my_sleep(1000000);
+      my_sleep(100000);
     }
     DBUG_PRINT("info",("saved_modified=%llu current=%llu", modified,
                evex_queue_num_elements(EVEX_EQ_NAME)? 
@@ -489,7 +490,7 @@ event_executor_main(void *arg)
 
     if (!evex_queue_num_elements(EVEX_EQ_NAME))
     {
-      my_sleep(1000000);// sleep 1s
+      my_sleep(100000);// sleep 0.1s
       continue;
     }
 

--- 1.45/sql/event_timed.cc	2006-03-02 21:01:56 +01:00
+++ 1.46/sql/event_timed.cc	2006-03-05 20:36:23 +01:00
@@ -47,6 +47,8 @@ Event_timed::init()
   definer_user.length= definer_host.length= 0;
 
   sql_mode= 0;
+  parse_items.execute_at= parse_items.interval_expr= parse_items.starts=
+    parse_items.ends= NULL;
 
   DBUG_VOID_RETURN;
 }
@@ -155,7 +157,10 @@ Event_timed::init_execute_at(THD *thd, I
   DBUG_ENTER("Event_timed::init_execute_at");
 
   if (expr->fix_fields(thd, &expr))
-    DBUG_RETURN(EVEX_PARSE_ERROR);
+  {
+    DBUG_PRINT("error", ("fix_fields failed"));
+    goto wrong_value;
+  }
   
   /* no starts and/or ends in case of execute_at */
   DBUG_PRINT("info", ("starts_null && ends_null should be 1 is %d",
@@ -167,11 +172,14 @@ Event_timed::init_execute_at(THD *thd, I
                                             (my_time_t) thd->query_start());
 
   if ((not_used= expr->get_date(&ltime, TIME_NO_ZERO_DATE)))
-    DBUG_RETURN(ER_WRONG_VALUE);
+    goto wrong_value;
 
   if (TIME_to_ulonglong_datetime(&ltime) <
       TIME_to_ulonglong_datetime(&time_tmp))
+  {
+    my_error(ER_EVENT_EXEC_TIME_IN_THE_PAST, MYF(0));
     DBUG_RETURN(EVEX_BAD_PARAMS);
+  }
 
 
   /*
@@ -183,6 +191,62 @@ Event_timed::init_execute_at(THD *thd, I
   execute_at_null= FALSE;
   execute_at= ltime;
   DBUG_RETURN(0);
+wrong_value:
+  {
+    char buff[120];
+    String str(buff,(uint32) sizeof(buff), system_charset_info);
+    String *str2= expr->val_str(&str);
+    my_error(ER_WRONG_VALUE, MYF(0), "AT", str2? str2->c_ptr():"NULL");
+    DBUG_RETURN(EVEX_BAD_PARAMS);  
+  }
+}
+
+
+/*
+  Checks whether we support the interval type
+
+  SYNOPSIS
+    Event_timed::is_valid_interval_type()
+      new_interval  what is the interval
+
+  RETURNS
+    0                       OK
+    EVEX_MICROSECOND_UNSUP  Microseconds are not supported.
+*/
+
+int
+Event_timed::is_valid_interval_type(interval_type new_interval)
+{
+  DBUG_ENTER("Event_timed::is_valid_interval_type");
+  switch (new_interval) {
+  case INTERVAL_MICROSECOND:
+  case INTERVAL_SECOND_MICROSECOND:
+  case INTERVAL_MINUTE_MICROSECOND:
+  case INTERVAL_HOUR_MICROSECOND:
+  case INTERVAL_DAY_MICROSECOND:
+    DBUG_RETURN(EVEX_MICROSECOND_UNSUP);
+#ifndef DBUG_OFF
+  case INTERVAL_YEAR:
+  case INTERVAL_QUARTER:
+  case INTERVAL_MONTH:
+  case INTERVAL_WEEK:
+  case INTERVAL_DAY:
+  case INTERVAL_HOUR:
+  case INTERVAL_MINUTE:
+  case INTERVAL_SECOND:
+  case INTERVAL_YEAR_MONTH:
+  case INTERVAL_DAY_HOUR:
+  case INTERVAL_DAY_MINUTE:
+  case INTERVAL_HOUR_MINUTE:
+  case INTERVAL_HOUR_SECOND:
+  case INTERVAL_MINUTE_SECOND:
+  case INTERVAL_DAY_SECOND:
+    DBUG_RETURN(0);
+  default:
+    DBUG_PRINT("error", ("type %d is unknown", (int) new_interval));
+    DBUG_ASSERT(0);
+#endif  
+  }
 }
 
 
@@ -210,11 +274,14 @@ Event_timed::init_interval(THD *thd, Ite
   DBUG_ENTER("Event_timed::init_interval");
 
   if (expr->fix_fields(thd, &expr))
-    DBUG_RETURN(EVEX_PARSE_ERROR);
+    DBUG_RETURN(EVEX_BAD_PARAMS);
 
   value.alloc(MAX_DATETIME_FULL_WIDTH*MY_CHARSET_BIN_MB_MAXLEN);
   if (get_interval_value(expr, new_interval, &value, &interval))
-    DBUG_RETURN(EVEX_PARSE_ERROR);
+  {
+    DBUG_PRINT("error", ("fix_fields failed"));
+    DBUG_RETURN(EVEX_BAD_PARAMS);
+  }
 
   expression= 0;
 
@@ -250,17 +317,20 @@ Event_timed::init_interval(THD *thd, Ite
     break;
   case INTERVAL_HOUR_SECOND: /* day is anyway 0 */
   case INTERVAL_DAY_SECOND:
-    /* DAY_SECOND having problems because of leap seconds? */
+    /* QQ: DAY_SECOND having problems because of leap seconds? */
     expression= ((interval.day* 24 + interval.hour) * 60 + interval.minute)*60
                  + interval.second;
     break;
   case INTERVAL_MINUTE_MICROSECOND: /* day and hour are 0 */
   case INTERVAL_HOUR_MICROSECOND:   /* day is anyway 0    */
   case INTERVAL_DAY_MICROSECOND:
-    DBUG_RETURN(EVEX_MICROSECOND_UNSUP);
+    my_error(ER_NOT_SUPPORTED_YET, MYF(0), "MICROSECOND");
+    DBUG_RETURN(EVEX_MICROSECOND_UNSUP);  
+#ifdef WE_SUPPORT_MICROSEC
     expression= ((((interval.day*24) + interval.hour)*60+interval.minute)*60 +
                 interval.second) * 1000000L + interval.second_part;
     break;
+#endif
   case INTERVAL_HOUR_MINUTE:
     expression= interval.hour * 60 + interval.minute;
     break;
@@ -268,13 +338,17 @@ Event_timed::init_interval(THD *thd, Ite
     expression= interval.minute * 60 + interval.second;
     break;
   case INTERVAL_SECOND_MICROSECOND:
-    DBUG_RETURN(EVEX_MICROSECOND_UNSUP);
+    my_error(ER_NOT_SUPPORTED_YET, MYF(0), "MICROSECOND");
+    DBUG_RETURN(EVEX_MICROSECOND_UNSUP);  
+#ifdef WE_SUPPORT_MICROSEC
     expression= interval.second * 1000000L + interval.second_part;
     break;
+#endif
   case INTERVAL_MICROSECOND:
+    my_error(ER_NOT_SUPPORTED_YET, MYF(0), "MICROSECOND");
     DBUG_RETURN(EVEX_MICROSECOND_UNSUP);  
   }
-  if (interval.neg || expression > EVEX_MAX_INTERVAL_VALUE)
+  if (interval.neg || expression > EVEX_MAX_INTERVAL_VALUE || !expression)
     DBUG_RETURN(EVEX_BAD_PARAMS);
 
   this->interval= new_interval;
@@ -307,25 +381,21 @@ int
 Event_timed::init_starts(THD *thd, Item *new_starts)
 {
   my_bool not_used;
-  TIME ltime, time_tmp;
+  TIME ltime, ltime_now;
 
   DBUG_ENTER("Event_timed::init_starts");
 
   if (new_starts->fix_fields(thd, &new_starts))
-    DBUG_RETURN(EVEX_PARSE_ERROR);
+  {
+    DBUG_PRINT("error", ("fix_fields failed"));
+    DBUG_RETURN(EVEX_BAD_PARAMS);
+  }
 
   if ((not_used= new_starts->get_date(&ltime, TIME_NO_ZERO_DATE)))
     DBUG_RETURN(EVEX_BAD_PARAMS);
 
   /* Let's check whether time is in the past */
-  thd->variables.time_zone->gmt_sec_to_TIME(&time_tmp,
-                                            (my_time_t) thd->query_start());
-
-  DBUG_PRINT("info",("now   =%lld", TIME_to_ulonglong_datetime(&time_tmp)));
-  DBUG_PRINT("info",("starts=%lld", TIME_to_ulonglong_datetime(&ltime)));
-  if (TIME_to_ulonglong_datetime(&ltime) <
-      TIME_to_ulonglong_datetime(&time_tmp))
-    DBUG_RETURN(EVEX_BAD_PARAMS);
+  my_tz_UTC->gmt_sec_to_TIME(&ltime_now, (my_time_t) (thd->query_start()));
 
   /*
     This may result in a 1970-01-01 date if ltime is > 2037-xx-xx
@@ -333,6 +403,12 @@ Event_timed::init_starts(THD *thd, Item 
   */
   my_tz_UTC->gmt_sec_to_TIME(&ltime, TIME_to_timestamp(thd, &ltime, &not_used));
 
+  DBUG_PRINT("info",("NOW   =%lld", TIME_to_ulonglong_datetime(&ltime_now)));
+  DBUG_PRINT("info",("STARTS=%lld", TIME_to_ulonglong_datetime(&ltime)));
+  if (TIME_to_ulonglong_datetime(&ltime) <
+      TIME_to_ulonglong_datetime(&ltime_now))
+    DBUG_RETURN(EVEX_BAD_PARAMS);
+
   starts= ltime;
   starts_null= FALSE;
   DBUG_RETURN(0);
@@ -370,22 +446,34 @@ Event_timed::init_ends(THD *thd, Item *n
   DBUG_ENTER("Event_timed::init_ends");
 
   if (new_ends->fix_fields(thd, &new_ends))
+  {
+    DBUG_PRINT("error", ("fix_fields failed"));
     DBUG_RETURN(EVEX_PARSE_ERROR);
+  }
 
   DBUG_PRINT("info", ("convert to TIME"));
-  if ((not_used= new_ends->get_date(&ltime, TIME_NO_ZERO_DATE)))
+  if ((not_used= new_ends->get_date(&ltime, TIME_NO_ZERO_DATE)) && 0)
+  {
+    DBUG_PRINT("error", ("get_date returned error"));
     DBUG_RETURN(EVEX_BAD_PARAMS);
+  }
+
+  DBUG_PRINT("info", ("ENDS  =%lld", TIME_to_ulonglong_datetime(&ltime)));
+
+  DBUG_PRINT("info", ("get the UTC time"));
+  my_tz_UTC->gmt_sec_to_TIME(&ltime, TIME_to_timestamp(thd, &ltime, &not_used));
+
+  DBUG_PRINT("info", ("STARTS=%lld", TIME_to_ulonglong_datetime(&starts)));
+  DBUG_PRINT("info", ("ENDS  =%lld", TIME_to_ulonglong_datetime(&ltime)));
 
   /*
     This may result in a 1970-01-01 date if ltime is > 2037-xx-xx ?
     CONVERT_TZ has similar problem ?
   */
-  DBUG_PRINT("info", ("get the UTC time"));
-  my_tz_UTC->gmt_sec_to_TIME(&ltime, TIME_to_timestamp(thd, &ltime, &not_used));
 
   /* Check whether ends is after starts */
   DBUG_PRINT("info", ("ENDS after STARTS?"));
-  if (!starts_null && my_time_compare(&starts, &ltime) != -1)
+  if (!starts_null && my_time_compare(&starts, &ltime) == 1)
     DBUG_RETURN(EVEX_BAD_PARAMS);
 
   /*
@@ -393,8 +481,9 @@ Event_timed::init_ends(THD *thd, Item *n
     set before NOW() and in this case the following check should be done.
     Check whether ENDS is not in the past.
   */
+  my_tz_UTC->gmt_sec_to_TIME(&ltime_now, (my_time_t) thd->query_start());
   DBUG_PRINT("info", ("ENDS after NOW?"));
-  my_tz_UTC->gmt_sec_to_TIME(&ltime_now, thd->query_start());
+  DBUG_PRINT("info", ("NOW   =%lld", TIME_to_ulonglong_datetime(&ltime_now)));
   if (my_time_compare(&ltime_now, &ltime) == 1)
     DBUG_RETURN(EVEX_BAD_PARAMS);
 
Thread
bk commit into 5.1 tree (andrey:1.2214) BUG#16394ahristov5 Mar