manual merge
mysql-test/r/events.result: Auto merged mysql-test/t/events.test: Auto merged sql/event.h: Auto merged sql/event_executor.cc: Auto merged sql/event_timed.cc: Auto merged sql/sql_acl.cc: Auto merged sql/sql_acl.h: Auto merged sql/sql_parse.cc: Auto merged sql/sql_show.cc: Auto merged sql/sql_yacc.yy: Auto merged sql/table.cc: Auto merged sql/table.h: Auto merged
This commit is contained in:
commit
752cadd453
@ -18,7 +18,7 @@ set global event_scheduler = 1;
|
||||
alter event e_43 do alter event e_43 do set @a = 4;
|
||||
select db, name, body, status, interval_field, interval_value from mysql.event;
|
||||
db name body status interval_field interval_value
|
||||
events_test e_43 set @a = 4 ENABLED SECOND 1
|
||||
events_test e_43 set @a = 4 ENABLED SECOND 1
|
||||
drop event e_43;
|
||||
set global event_scheduler = 0;
|
||||
create table t_event3 (a int, b float);
|
||||
@ -32,13 +32,178 @@ count(*)
|
||||
0
|
||||
drop event event3;
|
||||
drop table t_event3;
|
||||
set names utf8;
|
||||
CREATE EVENT root6 ON SCHEDULE EVERY '10:20' MINUTE_SECOND ON COMPLETION PRESERVE ENABLE COMMENT 'some comment' DO select 1;
|
||||
SHOW CREATE EVENT root6;
|
||||
Event sql_mode Create Event
|
||||
root6 CREATE EVENT `events_test`.`root6` ON SCHEDULE EVERY '10:20' MINUTE_SECOND ON COMPLETION PRESERVE ENABLE COMMENT 'some comment' DO select 1
|
||||
create event root7 on schedule every 2 year do select 1;
|
||||
SHOW CREATE EVENT root7;
|
||||
Event sql_mode Create Event
|
||||
root7 CREATE EVENT `events_test`.`root7` ON SCHEDULE EVERY 2 YEAR ON COMPLETION NOT PRESERVE ENABLE DO select 1
|
||||
create event root8 on schedule every '2:5' year_month do select 1;
|
||||
SHOW CREATE EVENT root8;
|
||||
Event sql_mode Create Event
|
||||
root8 CREATE EVENT `events_test`.`root8` ON SCHEDULE EVERY '2-5' YEAR_MONTH ON COMPLETION NOT PRESERVE ENABLE DO select 1
|
||||
create event root8_1 on schedule every '2:15' year_month do select 1;
|
||||
SHOW CREATE EVENT root8_1;
|
||||
Event sql_mode Create Event
|
||||
root8_1 CREATE EVENT `events_test`.`root8_1` ON SCHEDULE EVERY '3-3' YEAR_MONTH ON COMPLETION NOT PRESERVE ENABLE DO select 1
|
||||
create event root9 on schedule every 2 week ON COMPLETION PRESERVE DISABLE COMMENT 'коментар на кирилица' do select 1;
|
||||
SHOW CREATE EVENT root9;
|
||||
Event sql_mode Create Event
|
||||
root9 CREATE EVENT `events_test`.`root9` ON SCHEDULE EVERY 2 WEEK ON COMPLETION PRESERVE DISABLE COMMENT 'коментар на кирилица' DO select 1
|
||||
create event root10 on schedule every '20:5' day_hour do select 1;
|
||||
SHOW CREATE EVENT root10;
|
||||
Event sql_mode Create Event
|
||||
root10 CREATE EVENT `events_test`.`root10` ON SCHEDULE EVERY '20 5' DAY_HOUR ON COMPLETION NOT PRESERVE ENABLE DO select 1
|
||||
create event root11 on schedule every '20:25' day_hour do select 1;
|
||||
SHOW CREATE EVENT root11;
|
||||
Event sql_mode Create Event
|
||||
root11 CREATE EVENT `events_test`.`root11` ON SCHEDULE EVERY '21 1' DAY_HOUR ON COMPLETION NOT PRESERVE ENABLE DO select 1
|
||||
create event root12 on schedule every '20:25' hour_minute do select 1;
|
||||
SHOW CREATE EVENT root12;
|
||||
Event sql_mode Create Event
|
||||
root12 CREATE EVENT `events_test`.`root12` ON SCHEDULE EVERY '20:25' HOUR_MINUTE ON COMPLETION NOT PRESERVE ENABLE DO select 1
|
||||
create event root13 on schedule every '25:25' hour_minute do select 1;
|
||||
SHOW CREATE EVENT root13;
|
||||
Event sql_mode Create Event
|
||||
root13 CREATE EVENT `events_test`.`root13` ON SCHEDULE EVERY '25:25' HOUR_MINUTE ON COMPLETION NOT PRESERVE ENABLE DO select 1
|
||||
create event root13_1 on schedule every '11:65' hour_minute do select 1;
|
||||
SHOW CREATE EVENT root13_1;
|
||||
Event sql_mode Create Event
|
||||
root13_1 CREATE EVENT `events_test`.`root13_1` ON SCHEDULE EVERY '12:5' HOUR_MINUTE ON COMPLETION NOT PRESERVE ENABLE DO select 1
|
||||
create event root14 on schedule every '35:35' minute_second do select 1;
|
||||
SHOW CREATE EVENT root14;
|
||||
Event sql_mode Create Event
|
||||
root14 CREATE EVENT `events_test`.`root14` ON SCHEDULE EVERY '35:35' MINUTE_SECOND ON COMPLETION NOT PRESERVE ENABLE DO select 1
|
||||
create event root15 on schedule every '35:66' minute_second do select 1;
|
||||
SHOW CREATE EVENT root15;
|
||||
Event sql_mode Create Event
|
||||
root15 CREATE EVENT `events_test`.`root15` ON SCHEDULE EVERY '36:6' MINUTE_SECOND ON COMPLETION NOT PRESERVE ENABLE DO select 1
|
||||
create event root16 on schedule every '35:56' day_minute do select 1;
|
||||
SHOW CREATE EVENT root16;
|
||||
Event sql_mode Create Event
|
||||
root16 CREATE EVENT `events_test`.`root16` ON SCHEDULE EVERY '1 11:56' DAY_MINUTE ON COMPLETION NOT PRESERVE ENABLE DO select 1
|
||||
create event root17 on schedule every '35:12:45' day_minute do select 1;
|
||||
SHOW CREATE EVENT root17;
|
||||
Event sql_mode Create Event
|
||||
root17 CREATE EVENT `events_test`.`root17` ON SCHEDULE EVERY '35 12:45' DAY_MINUTE ON COMPLETION NOT PRESERVE ENABLE DO select 1
|
||||
create event root17_1 on schedule every '35:25:65' day_minute do select 1;
|
||||
SHOW CREATE EVENT root17_1;
|
||||
Event sql_mode Create Event
|
||||
root17_1 CREATE EVENT `events_test`.`root17_1` ON SCHEDULE EVERY '36 2:5' DAY_MINUTE ON COMPLETION NOT PRESERVE ENABLE DO select 1
|
||||
create event root18 on schedule every '35:12:45' hour_second do select 1;
|
||||
SHOW CREATE EVENT root18;
|
||||
Event sql_mode Create Event
|
||||
root18 CREATE EVENT `events_test`.`root18` ON SCHEDULE EVERY '35:12:45' HOUR_SECOND ON COMPLETION NOT PRESERVE ENABLE DO select 1
|
||||
create event root19 on schedule every '15:59:85' hour_second do select 1;
|
||||
SHOW CREATE EVENT root19;
|
||||
Event sql_mode Create Event
|
||||
root19 CREATE EVENT `events_test`.`root19` ON SCHEDULE EVERY '16:0:25' HOUR_SECOND ON COMPLETION NOT PRESERVE ENABLE DO select 1
|
||||
create event root20 on schedule every '50:20:12:45' day_second do select 1;
|
||||
SHOW CREATE EVENT root20;
|
||||
Event sql_mode Create Event
|
||||
root20 CREATE EVENT `events_test`.`root20` ON SCHEDULE EVERY '50 20:12:45' DAY_SECOND ON COMPLETION NOT PRESERVE ENABLE DO select 1
|
||||
set names cp1251;
|
||||
create event ðóóò21 on schedule every '50:23:59:95' day_second COMMENT 'òîâà å 1251 êîìåíòàð' do select 1;
|
||||
SHOW CREATE EVENT ðóóò21;
|
||||
Event sql_mode Create Event
|
||||
ðóóò21 CREATE EVENT `events_test`.`ðóóò21` ON SCHEDULE EVERY '51 0:0:35' DAY_SECOND ON COMPLETION NOT PRESERVE ENABLE COMMENT 'òîâà å 1251 êîìåíòàð' DO select 1
|
||||
insert into mysql.event (db, name, body, definer, interval_value, interval_field) values (database(), "root22", "select 1", user(), 100, "SECOND_MICROSECOND");
|
||||
show create event root22;
|
||||
ERROR HY000: Microseconds intervals are not yet supported
|
||||
SHOW EVENTS;
|
||||
ERROR HY000: Microseconds intervals are not yet supported
|
||||
drop event root22;
|
||||
drop event root6;
|
||||
drop event root7;
|
||||
drop event root8;
|
||||
drop event root8_1;
|
||||
drop event root9;
|
||||
drop event root10;
|
||||
drop event root11;
|
||||
drop event root12;
|
||||
drop event root13;
|
||||
drop event root13_1;
|
||||
drop event root14;
|
||||
drop event root15;
|
||||
drop event root16;
|
||||
drop event root17;
|
||||
drop event root17_1;
|
||||
drop event root18;
|
||||
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 10 HOUR # # ENABLED
|
||||
ALTER TABLE mysql.event ADD dummy INT FIRST;
|
||||
SHOW EVENTS;
|
||||
ERROR HY000: Column count of mysql.event is wrong. Table probably corrupted. Expected 15, found 16.
|
||||
ALTER TABLE mysql.event DROP dummy, ADD dummy2 VARCHAR(64) FIRST;
|
||||
SHOW EVENTS;
|
||||
ERROR HY000: Column count of mysql.event is wrong. Table probably corrupted. Expected 15, found 16.
|
||||
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 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',
|
||||
`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 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. Table probably corrupted. Expected 15, found 13.
|
||||
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 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 INTERVAL_SECOND # # ENABLED
|
||||
events_test one_event root@localhost RECURRING NULL 10 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 INTERVAL_SECOND ENABLED NOT PRESERVE
|
||||
NULL events_test one_event root@localhost select 123 RECURRING NULL 10 10 SECOND ENABLED NOT PRESERVE
|
||||
CREATE DATABASE events_test2;
|
||||
CREATE USER ev_test@localhost;
|
||||
GRANT ALL ON events_test.* to ev_test@localhost;
|
||||
@ -72,20 +237,20 @@ create event three_event on schedule every 20 second on completion preserve comm
|
||||
"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 INTERVAL_SECOND # # ENABLED
|
||||
events_test three_event ev_test@localhost RECURRING NULL 20 INTERVAL_SECOND # # ENABLED
|
||||
events_test two_event ev_test@localhost RECURRING NULL 20 INTERVAL_SECOND # # ENABLED
|
||||
events_test one_event ev_test@localhost RECURRING NULL 20 20 SECOND # # ENABLED
|
||||
events_test three_event ev_test@localhost RECURRING NULL 20 20 SECOND # # ENABLED
|
||||
events_test two_event ev_test@localhost RECURRING NULL 20 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 INTERVAL_SECOND # # ENABLED
|
||||
events_test three_event ev_test@localhost RECURRING NULL 20 INTERVAL_SECOND # # ENABLED
|
||||
events_test two_event ev_test@localhost RECURRING NULL 20 INTERVAL_SECOND # # ENABLED
|
||||
events_test one_event ev_test@localhost RECURRING NULL 20 20 SECOND # # ENABLED
|
||||
events_test three_event ev_test@localhost RECURRING NULL 20 20 SECOND # # ENABLED
|
||||
events_test two_event ev_test@localhost RECURRING NULL 20 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 INTERVAL_SECOND # # ENABLED
|
||||
events_test two_event ev_test@localhost RECURRING NULL 20 INTERVAL_SECOND # # ENABLED
|
||||
events_test three_event ev_test@localhost RECURRING NULL 20 20 SECOND # # ENABLED
|
||||
events_test two_event ev_test@localhost RECURRING NULL 20 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
|
||||
@ -93,20 +258,20 @@ 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 INTERVAL_SECOND # # ENABLED
|
||||
events_test one_event root@localhost RECURRING NULL 10 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 INTERVAL_SECOND # # ENABLED
|
||||
events_test three_event ev_test@localhost RECURRING NULL 20 INTERVAL_SECOND # # ENABLED
|
||||
events_test two_event ev_test@localhost RECURRING NULL 20 INTERVAL_SECOND # # ENABLED
|
||||
events_test one_event root@localhost RECURRING NULL 10 INTERVAL_SECOND # # ENABLED
|
||||
events_test one_event ev_test@localhost RECURRING NULL 20 20 SECOND # # ENABLED
|
||||
events_test three_event ev_test@localhost RECURRING NULL 20 20 SECOND # # ENABLED
|
||||
events_test two_event ev_test@localhost RECURRING NULL 20 20 SECOND # # ENABLED
|
||||
events_test one_event root@localhost RECURRING NULL 10 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 INTERVAL_SECOND ENABLED NOT PRESERVE
|
||||
NULL events_test three_event ev_test@localhost select 123 RECURRING NULL 20 INTERVAL_SECOND ENABLED PRESERVE three event
|
||||
NULL events_test two_event ev_test@localhost select 123 RECURRING NULL 20 INTERVAL_SECOND ENABLED NOT PRESERVE two event
|
||||
NULL events_test one_event root@localhost select 123 RECURRING NULL 10 INTERVAL_SECOND ENABLED NOT PRESERVE
|
||||
NULL events_test one_event ev_test@localhost select 123 RECURRING NULL 20 20 SECOND ENABLED NOT PRESERVE
|
||||
NULL events_test three_event ev_test@localhost select 123 RECURRING NULL 20 20 SECOND ENABLED PRESERVE three event
|
||||
NULL events_test two_event ev_test@localhost select 123 RECURRING NULL 20 20 SECOND ENABLED NOT PRESERVE two event
|
||||
NULL events_test one_event root@localhost select 123 RECURRING NULL 10 10 SECOND ENABLED NOT PRESERVE
|
||||
drop event one_event;
|
||||
drop event two_event;
|
||||
drop event three_event;
|
||||
@ -116,7 +281,7 @@ drop event one_event;
|
||||
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
|
||||
events_test e_26 set @a = 5 root@localhost 2017-01-01 00:00:00 DROP
|
||||
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;
|
||||
ERROR HY000: Incorrect AT value: 'NULL'
|
||||
|
@ -33,6 +33,138 @@ select count(*) from t_event3;
|
||||
drop event event3;
|
||||
drop table t_event3;
|
||||
|
||||
|
||||
set names utf8;
|
||||
#
|
||||
# SHOW CREATE EVENT test begin
|
||||
#
|
||||
CREATE EVENT root6 ON SCHEDULE EVERY '10:20' MINUTE_SECOND ON COMPLETION PRESERVE ENABLE COMMENT 'some comment' DO select 1;
|
||||
SHOW CREATE EVENT root6;
|
||||
create event root7 on schedule every 2 year do select 1;
|
||||
SHOW CREATE EVENT root7;
|
||||
create event root8 on schedule every '2:5' year_month do select 1;
|
||||
SHOW CREATE EVENT root8;
|
||||
create event root8_1 on schedule every '2:15' year_month do select 1;
|
||||
SHOW CREATE EVENT root8_1;
|
||||
create event root9 on schedule every 2 week ON COMPLETION PRESERVE DISABLE COMMENT 'коментар на кирилица' do select 1;
|
||||
SHOW CREATE EVENT root9;
|
||||
create event root10 on schedule every '20:5' day_hour do select 1;
|
||||
SHOW CREATE EVENT root10;
|
||||
create event root11 on schedule every '20:25' day_hour do select 1;
|
||||
SHOW CREATE EVENT root11;
|
||||
create event root12 on schedule every '20:25' hour_minute do select 1;
|
||||
SHOW CREATE EVENT root12;
|
||||
create event root13 on schedule every '25:25' hour_minute do select 1;
|
||||
SHOW CREATE EVENT root13;
|
||||
create event root13_1 on schedule every '11:65' hour_minute do select 1;
|
||||
SHOW CREATE EVENT root13_1;
|
||||
create event root14 on schedule every '35:35' minute_second do select 1;
|
||||
SHOW CREATE EVENT root14;
|
||||
create event root15 on schedule every '35:66' minute_second do select 1;
|
||||
SHOW CREATE EVENT root15;
|
||||
create event root16 on schedule every '35:56' day_minute do select 1;
|
||||
SHOW CREATE EVENT root16;
|
||||
create event root17 on schedule every '35:12:45' day_minute do select 1;
|
||||
SHOW CREATE EVENT root17;
|
||||
create event root17_1 on schedule every '35:25:65' day_minute do select 1;
|
||||
SHOW CREATE EVENT root17_1;
|
||||
create event root18 on schedule every '35:12:45' hour_second do select 1;
|
||||
SHOW CREATE EVENT root18;
|
||||
create event root19 on schedule every '15:59:85' hour_second do select 1;
|
||||
SHOW CREATE EVENT root19;
|
||||
create event root20 on schedule every '50:20:12:45' day_second do select 1;
|
||||
SHOW CREATE EVENT root20;
|
||||
set names cp1251;
|
||||
create event ðóóò21 on schedule every '50:23:59:95' day_second COMMENT 'òîâà å 1251 êîìåíòàð' do select 1;
|
||||
SHOW CREATE EVENT ðóóò21;
|
||||
insert into mysql.event (db, name, body, definer, interval_value, interval_field) values (database(), "root22", "select 1", user(), 100, "SECOND_MICROSECOND");
|
||||
--error 1535
|
||||
show create event root22;
|
||||
--error 1535
|
||||
SHOW EVENTS;
|
||||
drop event root22;
|
||||
drop event root6;
|
||||
drop event root7;
|
||||
drop event root8;
|
||||
drop event root8_1;
|
||||
drop event root9;
|
||||
drop event root10;
|
||||
drop event root11;
|
||||
drop event root12;
|
||||
drop event root13;
|
||||
drop event root13_1;
|
||||
drop event root14;
|
||||
drop event root15;
|
||||
drop event root16;
|
||||
drop event root17;
|
||||
drop event root17_1;
|
||||
drop event root18;
|
||||
drop event root19;
|
||||
drop event root20;
|
||||
drop event ðóóò21;
|
||||
|
||||
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
|
||||
#
|
||||
|
491
sql/event.cc
491
sql/event.cc
@ -51,8 +51,6 @@
|
||||
|
||||
- Make event_timed::get_show_create_event() work
|
||||
|
||||
- Add function documentation whenever needed.
|
||||
|
||||
- Add logging to file
|
||||
|
||||
- Move comparison code to class event_timed
|
||||
@ -66,8 +64,144 @@ Warning:
|
||||
|
||||
QUEUE EVEX_EQ_NAME;
|
||||
MEM_ROOT evex_mem_root;
|
||||
time_t mysql_event_last_create_time= 0L;
|
||||
|
||||
|
||||
static TABLE_FIELD_W_TYPE event_table_fields[EVEX_FIELD_COUNT] = {
|
||||
{
|
||||
{(char *) STRING_WITH_LEN("db")},
|
||||
{(char *) STRING_WITH_LEN("char(64)")},
|
||||
{(char *) STRING_WITH_LEN("utf8")}
|
||||
},
|
||||
{
|
||||
{(char *) STRING_WITH_LEN("name")},
|
||||
{(char *) STRING_WITH_LEN("char(64)")},
|
||||
{(char *) STRING_WITH_LEN("utf8")}
|
||||
},
|
||||
{
|
||||
{(char *) STRING_WITH_LEN("body")},
|
||||
{(char *) STRING_WITH_LEN("longblob")},
|
||||
{NULL, 0}
|
||||
},
|
||||
{
|
||||
{(char *) STRING_WITH_LEN("definer")},
|
||||
{(char *) STRING_WITH_LEN("char(77)")},
|
||||
{(char *) STRING_WITH_LEN("utf8")}
|
||||
},
|
||||
{
|
||||
{(char *) STRING_WITH_LEN("execute_at")},
|
||||
{(char *) STRING_WITH_LEN("datetime")},
|
||||
{NULL, 0}
|
||||
},
|
||||
{
|
||||
{(char *) STRING_WITH_LEN("interval_value")},
|
||||
{(char *) STRING_WITH_LEN("int(11)")},
|
||||
{NULL, 0}
|
||||
},
|
||||
{
|
||||
{(char *) STRING_WITH_LEN("interval_field")},
|
||||
{(char *) STRING_WITH_LEN("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')")},
|
||||
{NULL, 0}
|
||||
},
|
||||
{
|
||||
{(char *) STRING_WITH_LEN("created")},
|
||||
{(char *) STRING_WITH_LEN("timestamp")},
|
||||
{NULL, 0}
|
||||
},
|
||||
{
|
||||
{(char *) STRING_WITH_LEN("modified")},
|
||||
{(char *) STRING_WITH_LEN("timestamp")},
|
||||
{NULL, 0}
|
||||
},
|
||||
{
|
||||
{(char *) STRING_WITH_LEN("last_executed")},
|
||||
{(char *) STRING_WITH_LEN("datetime")},
|
||||
},
|
||||
{
|
||||
{(char *) STRING_WITH_LEN("starts")},
|
||||
{(char *) STRING_WITH_LEN("datetime")},
|
||||
{NULL, 0}
|
||||
},
|
||||
{
|
||||
{(char *) STRING_WITH_LEN("ends")},
|
||||
{(char *) STRING_WITH_LEN("datetime")},
|
||||
{NULL, 0}
|
||||
},
|
||||
{
|
||||
{(char *) STRING_WITH_LEN("status")},
|
||||
{(char *) STRING_WITH_LEN("enum('ENABLED','DISABLED')")},
|
||||
{NULL, 0}
|
||||
},
|
||||
{
|
||||
{(char *) STRING_WITH_LEN("on_completion")},
|
||||
{(char *) STRING_WITH_LEN("enum('DROP','PRESERVE')")},
|
||||
{NULL, 0}
|
||||
},
|
||||
/*
|
||||
{
|
||||
{(char *) STRING_WITH_LEN("sql_mode")},
|
||||
{(char *) STRING_WITH_LEN("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')")},
|
||||
{NULL, 0}
|
||||
},
|
||||
*/
|
||||
{
|
||||
{(char *) STRING_WITH_LEN("comment")},
|
||||
{(char *) STRING_WITH_LEN("char(64)")},
|
||||
{(char *) STRING_WITH_LEN("utf8")}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
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("SECOND_MICROSECOND")}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Inits the scheduler queue - prioritized queue from mysys/queue.c
|
||||
|
||||
Synopsis
|
||||
evex_queue_init()
|
||||
|
||||
queue - pointer the the memory to be initialized as queue. has to be
|
||||
allocated from the caller
|
||||
|
||||
Notes
|
||||
During initialization the queue is sized for 30 events, and when is full
|
||||
will auto extent with 30.
|
||||
*/
|
||||
|
||||
void
|
||||
evex_queue_init(EVEX_QUEUE_TYPE *queue)
|
||||
{
|
||||
@ -77,6 +211,24 @@ evex_queue_init(EVEX_QUEUE_TYPE *queue)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Compares 2 LEX strings regarding case.
|
||||
|
||||
Synopsis
|
||||
my_time_compare()
|
||||
|
||||
s - first LEX_STRING
|
||||
t - second LEX_STRING
|
||||
cs - charset
|
||||
|
||||
RETURNS:
|
||||
-1 - s < t
|
||||
0 - s == t
|
||||
1 - s > t
|
||||
|
||||
Notes
|
||||
TIME.second_part is not considered during comparison
|
||||
*/
|
||||
|
||||
int sortcmp_lex_string(LEX_STRING s, LEX_STRING t, CHARSET_INFO *cs)
|
||||
{
|
||||
@ -85,6 +237,24 @@ int sortcmp_lex_string(LEX_STRING s, LEX_STRING t, CHARSET_INFO *cs)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Compares 2 TIME structures
|
||||
|
||||
Synopsis
|
||||
my_time_compare()
|
||||
|
||||
a - first TIME
|
||||
b - second time
|
||||
|
||||
RETURNS:
|
||||
-1 - a < b
|
||||
0 - a == b
|
||||
1 - a > b
|
||||
|
||||
Notes
|
||||
TIME.second_part is not considered during comparison
|
||||
*/
|
||||
|
||||
int
|
||||
my_time_compare(TIME *a, TIME *b)
|
||||
{
|
||||
@ -106,6 +276,24 @@ my_time_compare(TIME *a, TIME *b)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Compares the execute_at members of 2 event_timed instances
|
||||
|
||||
Synopsis
|
||||
event_timed_compare()
|
||||
|
||||
a - first event_timed object
|
||||
b - second event_timed object
|
||||
|
||||
RETURNS:
|
||||
-1 - a->execute_at < b->execute_at
|
||||
0 - a->execute_at == b->execute_at
|
||||
1 - a->execute_at > b->execute_at
|
||||
|
||||
Notes
|
||||
execute_at.second_part is not considered during comparison
|
||||
*/
|
||||
|
||||
int
|
||||
event_timed_compare(event_timed *a, event_timed *b)
|
||||
{
|
||||
@ -114,7 +302,24 @@ event_timed_compare(event_timed *a, event_timed *b)
|
||||
|
||||
|
||||
/*
|
||||
Callback for the prio queue
|
||||
Compares the execute_at members of 2 event_timed instances.
|
||||
Used as callback for the prioritized queue when shifting
|
||||
elements inside.
|
||||
|
||||
Synopsis
|
||||
event_timed_compare()
|
||||
|
||||
vptr - not used (set it to NULL)
|
||||
a - first event_timed object
|
||||
b - second event_timed object
|
||||
|
||||
RETURNS:
|
||||
-1 - a->execute_at < b->execute_at
|
||||
0 - a->execute_at == b->execute_at
|
||||
1 - a->execute_at > b->execute_at
|
||||
|
||||
Notes
|
||||
execute_at.second_part is not considered during comparison
|
||||
*/
|
||||
|
||||
int
|
||||
@ -124,6 +329,145 @@ event_timed_compare_q(void *vptr, byte* a, byte *b)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Reconstructs interval expression from interval type and expression
|
||||
value that is in form of a value of the smalles entity:
|
||||
For
|
||||
YEAR_MONTH - expression is in months
|
||||
DAY_MINUTE - expression is in minutes
|
||||
|
||||
Synopsis
|
||||
event_reconstruct_interval_expression()
|
||||
buf - preallocated String buffer to add the value to
|
||||
interval - the interval type (for instance YEAR_MONTH)
|
||||
expression - the value in the lowest entity
|
||||
|
||||
RETURNS
|
||||
0 - OK
|
||||
1 - Error
|
||||
|
||||
|
||||
*/
|
||||
|
||||
int
|
||||
event_reconstruct_interval_expression(String *buf,
|
||||
interval_type interval,
|
||||
longlong expression)
|
||||
{
|
||||
ulonglong expr= expression;
|
||||
char tmp_buff[128], *end;
|
||||
bool close_quote= TRUE;
|
||||
int multipl= 0;
|
||||
char separator=':';
|
||||
|
||||
switch (interval) {
|
||||
case INTERVAL_YEAR_MONTH:
|
||||
multipl= 12;
|
||||
separator= '-';
|
||||
goto common_1_lev_code;
|
||||
case INTERVAL_DAY_HOUR:
|
||||
multipl= 24;
|
||||
separator= ' ';
|
||||
goto common_1_lev_code;
|
||||
case INTERVAL_HOUR_MINUTE:
|
||||
case INTERVAL_MINUTE_SECOND:
|
||||
multipl= 60;
|
||||
common_1_lev_code:
|
||||
buf->append('\'');
|
||||
end= longlong10_to_str(expression/multipl, tmp_buff, 10);
|
||||
buf->append(tmp_buff, (uint) (end- tmp_buff));
|
||||
expr= expr - (expr/multipl)*multipl;
|
||||
break;
|
||||
case INTERVAL_DAY_MINUTE:
|
||||
{
|
||||
int tmp_expr= expr;
|
||||
|
||||
tmp_expr/=(24*60);
|
||||
buf->append('\'');
|
||||
end= longlong10_to_str(tmp_expr, tmp_buff, 10);
|
||||
buf->append(tmp_buff, (uint) (end- tmp_buff));// days
|
||||
buf->append(' ');
|
||||
|
||||
tmp_expr= expr - tmp_expr*(24*60);//minutes left
|
||||
end= longlong10_to_str(tmp_expr/60, tmp_buff, 10);
|
||||
buf->append(tmp_buff, (uint) (end- tmp_buff));// hours
|
||||
|
||||
expr= tmp_expr - (tmp_expr/60)*60;
|
||||
/* the code after the switch will finish */
|
||||
}
|
||||
break;
|
||||
case INTERVAL_HOUR_SECOND:
|
||||
{
|
||||
int tmp_expr= expr;
|
||||
|
||||
buf->append('\'');
|
||||
end= longlong10_to_str(tmp_expr/3600, tmp_buff, 10);
|
||||
buf->append(tmp_buff, (uint) (end- tmp_buff));// hours
|
||||
buf->append(':');
|
||||
|
||||
tmp_expr= tmp_expr - (tmp_expr/3600)*3600;
|
||||
end= longlong10_to_str(tmp_expr/60, tmp_buff, 10);
|
||||
buf->append(tmp_buff, (uint) (end- tmp_buff));// minutes
|
||||
|
||||
expr= tmp_expr - (tmp_expr/60)*60;
|
||||
/* the code after the switch will finish */
|
||||
}
|
||||
break;
|
||||
case INTERVAL_DAY_SECOND:
|
||||
{
|
||||
int tmp_expr= expr;
|
||||
|
||||
tmp_expr/=(24*3600);
|
||||
buf->append('\'');
|
||||
end= longlong10_to_str(tmp_expr, tmp_buff, 10);
|
||||
buf->append(tmp_buff, (uint) (end- tmp_buff));// days
|
||||
buf->append(' ');
|
||||
|
||||
tmp_expr= expr - tmp_expr*(24*3600);//seconds left
|
||||
end= longlong10_to_str(tmp_expr/3600, tmp_buff, 10);
|
||||
buf->append(tmp_buff, (uint) (end- tmp_buff));// hours
|
||||
buf->append(':');
|
||||
|
||||
tmp_expr= tmp_expr - (tmp_expr/3600)*3600;
|
||||
end= longlong10_to_str(tmp_expr/60, tmp_buff, 10);
|
||||
buf->append(tmp_buff, (uint) (end- tmp_buff));// minutes
|
||||
|
||||
expr= tmp_expr - (tmp_expr/60)*60;
|
||||
/* the code after the switch will finish */
|
||||
}
|
||||
break;
|
||||
case INTERVAL_DAY_MICROSECOND:
|
||||
case INTERVAL_HOUR_MICROSECOND:
|
||||
case INTERVAL_MINUTE_MICROSECOND:
|
||||
case INTERVAL_SECOND_MICROSECOND:
|
||||
my_error(ER_NOT_SUPPORTED_YET, MYF(0));
|
||||
return 1;
|
||||
break;
|
||||
case INTERVAL_QUARTER:
|
||||
expr/= 3;
|
||||
close_quote= FALSE;
|
||||
break;
|
||||
case INTERVAL_WEEK:
|
||||
expr/= 7;
|
||||
default:
|
||||
close_quote= FALSE;
|
||||
break;
|
||||
}
|
||||
if (close_quote)
|
||||
buf->append(separator);
|
||||
end= longlong10_to_str(expr, tmp_buff, 10);
|
||||
buf->append(tmp_buff, (uint) (end- tmp_buff));
|
||||
if (close_quote)
|
||||
buf->append('\'');
|
||||
|
||||
buf->append(' ');
|
||||
LEX_STRING *ival= &interval_type_to_name[interval];
|
||||
buf->append(ival->str, ival->length);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Open mysql.event table for read
|
||||
|
||||
@ -132,6 +476,7 @@ event_timed_compare_q(void *vptr, byte* a, byte *b)
|
||||
thd Thread context
|
||||
lock_type How to lock the table
|
||||
table The table pointer
|
||||
|
||||
RETURN
|
||||
1 Cannot lock table
|
||||
2 The table is corrupted - different number of fields
|
||||
@ -153,9 +498,10 @@ evex_open_event_table(THD *thd, enum thr_lock_type lock_type, TABLE **table)
|
||||
if (simple_open_n_lock_tables(thd, &tables))
|
||||
DBUG_RETURN(1);
|
||||
|
||||
if (tables.table->s->fields != EVEX_FIELD_COUNT)
|
||||
if (table_check_intact(tables.table, EVEX_FIELD_COUNT, event_table_fields,
|
||||
&mysql_event_last_create_time,
|
||||
ER_EVENT_CANNOT_LOAD_FROM_TABLE))
|
||||
{
|
||||
my_error(ER_EVENT_COL_COUNT_DOESNT_MATCH, MYF(0), "mysql", "event");
|
||||
close_thread_tables(thd);
|
||||
DBUG_RETURN(2);
|
||||
}
|
||||
@ -219,7 +565,6 @@ evex_db_find_event_aux(THD *thd, const LEX_STRING dbname,
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Puts some data common to CREATE and ALTER EVENT into a row.
|
||||
|
||||
@ -245,15 +590,9 @@ evex_fill_row(THD *thd, TABLE *table, event_timed *et, my_bool is_update)
|
||||
|
||||
DBUG_ENTER("evex_fill_row");
|
||||
|
||||
if (table->s->fields != EVEX_FIELD_COUNT)
|
||||
{
|
||||
my_error(ER_EVENT_COL_COUNT_DOESNT_MATCH, MYF(0), "mysql", "event");
|
||||
DBUG_RETURN(EVEX_GET_FIELD_FAILED);
|
||||
}
|
||||
|
||||
DBUG_PRINT("info", ("dbname.len=[%s]",et->dbname.str));
|
||||
DBUG_PRINT("info", ("name.len=[%s]",et->name.str));
|
||||
DBUG_PRINT("info", ("body=[%s]",et->body.str));
|
||||
DBUG_PRINT("info", ("dbname=[%s]", et->dbname.str));
|
||||
DBUG_PRINT("info", ("name =[%s]", et->name.str));
|
||||
DBUG_PRINT("info", ("body =[%s]", et->body.str));
|
||||
|
||||
if (table->field[field_num= EVEX_FIELD_DB]->
|
||||
store(et->dbname.str, et->dbname.length, system_charset_info))
|
||||
@ -584,16 +923,19 @@ err:
|
||||
*/
|
||||
|
||||
static int
|
||||
db_find_event(THD *thd, sp_name *name, LEX_STRING definer, event_timed **ett,
|
||||
TABLE *tbl)
|
||||
db_find_event(THD *thd, sp_name *name, LEX_STRING *definer, event_timed **ett,
|
||||
TABLE *tbl, MEM_ROOT *root)
|
||||
{
|
||||
TABLE *table;
|
||||
int ret;
|
||||
char *ptr;
|
||||
event_timed *et;
|
||||
event_timed *et=NULL;
|
||||
DBUG_ENTER("db_find_event");
|
||||
DBUG_PRINT("enter", ("name: %*s", name->m_name.length, name->m_name.str));
|
||||
|
||||
if (!root)
|
||||
root= &evex_mem_root;
|
||||
|
||||
if (tbl)
|
||||
table= tbl;
|
||||
else if (evex_open_event_table(thd, TL_READ, &table))
|
||||
@ -603,7 +945,7 @@ db_find_event(THD *thd, sp_name *name, LEX_STRING definer, event_timed **ett,
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ((ret= evex_db_find_event_aux(thd, name->m_db, name->m_name, definer,
|
||||
if ((ret= evex_db_find_event_aux(thd, name->m_db, name->m_name, *definer,
|
||||
table)))
|
||||
{
|
||||
my_error(ER_EVENT_DOES_NOT_EXIST, MYF(0), name->m_name.str);
|
||||
@ -617,7 +959,7 @@ db_find_event(THD *thd, sp_name *name, LEX_STRING definer, event_timed **ett,
|
||||
|
||||
2)::load_from_row() is silent on error therefore we emit error msg here
|
||||
*/
|
||||
if ((ret= et->load_from_row(&evex_mem_root, table)))
|
||||
if ((ret= et->load_from_row(root, table)))
|
||||
{
|
||||
my_error(ER_EVENT_CANNOT_LOAD_FROM_TABLE, MYF(0));
|
||||
goto done;
|
||||
@ -671,10 +1013,11 @@ evex_load_and_compile_event(THD * thd, sp_name *spn, LEX_STRING definer,
|
||||
|
||||
thd->reset_n_backup_open_tables_state(&backup);
|
||||
// no need to use my_error() here because db_find_event() has done it
|
||||
if ((ret= db_find_event(thd, spn, definer, &ett, NULL)))
|
||||
ret= db_find_event(thd, spn, &definer, &ett, NULL, NULL);
|
||||
thd->restore_backup_open_tables_state(&backup);
|
||||
if (ret)
|
||||
goto done;
|
||||
|
||||
thd->restore_backup_open_tables_state(&backup);
|
||||
/*
|
||||
allocate on evex_mem_root. if you call without evex_mem_root
|
||||
then sphead will not be cleared!
|
||||
@ -705,16 +1048,31 @@ done:
|
||||
|
||||
|
||||
/*
|
||||
0 - OK can drop from outside
|
||||
1 - Scheduled from dropping, don't drop from outside
|
||||
Removes from queue in memory the event which is identified by the tupple
|
||||
(db, name).
|
||||
|
||||
SYNOPSIS
|
||||
evex_remove_from_cache()
|
||||
|
||||
db - db name
|
||||
name - event name
|
||||
use_lock - whether to lock the mutex LOCK_event_arrays or not in case it
|
||||
has been already locked outside
|
||||
is_drop - if an event is currently being executed then we can also delete
|
||||
the event_timed instance, so we alarm the event that it should
|
||||
drop itself if this parameter is set to TRUE. It's false on
|
||||
ALTER EVENT.
|
||||
|
||||
RETURNS
|
||||
0 - OK (always)
|
||||
*/
|
||||
|
||||
static int
|
||||
evex_remove_from_cache(LEX_STRING *db, LEX_STRING *name, bool use_lock,
|
||||
bool is_drop)
|
||||
{
|
||||
//ToDo : Add definer to the tuple (db, name) to become triple
|
||||
uint i;
|
||||
int ret= 0;
|
||||
|
||||
DBUG_ENTER("evex_remove_from_cache");
|
||||
/*
|
||||
@ -744,8 +1102,7 @@ evex_remove_from_cache(LEX_STRING *db, LEX_STRING *name, bool use_lock,
|
||||
DBUG_PRINT("evex_remove_from_cache",
|
||||
("running.defer mem free. is_drop=%d", is_drop));
|
||||
et->flags|= EVENT_EXEC_NO_MORE;
|
||||
if ((et->dropped= is_drop))
|
||||
ret= 1;
|
||||
et->dropped= is_drop;
|
||||
}
|
||||
DBUG_PRINT("evex_remove_from_cache", ("delete from queue"));
|
||||
evex_queue_delete_element(&EVEX_EQ_NAME, i);
|
||||
@ -758,12 +1115,10 @@ done:
|
||||
if (use_lock)
|
||||
VOID(pthread_mutex_unlock(&LOCK_event_arrays));
|
||||
|
||||
DBUG_RETURN(ret);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
The function exported to the world for creating of events.
|
||||
|
||||
@ -821,8 +1176,8 @@ done:
|
||||
|
||||
NOTES
|
||||
et contains data about dbname and event name.
|
||||
name is the new name of the event, if not null this means
|
||||
that RENAME TO was specified in the query.
|
||||
new_name is the new name of the event, if not null (this means
|
||||
that RENAME TO was specified in the query)
|
||||
*/
|
||||
|
||||
int
|
||||
@ -968,3 +1323,75 @@ evex_drop_event(THD *thd, event_timed *et, bool drop_if_exists,
|
||||
DBUG_RETURN(ret);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
SHOW CREATE EVENT
|
||||
|
||||
SYNOPSIS
|
||||
evex_show_create_event()
|
||||
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
|
||||
evex_show_create_event(THD *thd, sp_name *spn, LEX_STRING definer)
|
||||
{
|
||||
int ret;
|
||||
event_timed *et= NULL;
|
||||
Open_tables_state backup;
|
||||
|
||||
DBUG_ENTER("evex_update_event");
|
||||
DBUG_PRINT("enter", ("name: %*s", spn->m_name.length, spn->m_name.str));
|
||||
|
||||
thd->reset_n_backup_open_tables_state(&backup);
|
||||
ret= db_find_event(thd, spn, &definer, &et, NULL, thd->mem_root);
|
||||
thd->restore_backup_open_tables_state(&backup);
|
||||
|
||||
if (!ret && et)
|
||||
{
|
||||
Protocol *protocol= thd->protocol;
|
||||
char show_str_buf[768];
|
||||
String show_str(show_str_buf, sizeof(show_str_buf), system_charset_info);
|
||||
List<Item> field_list;
|
||||
const char *sql_mode_str;
|
||||
ulong sql_mode_len=0;
|
||||
|
||||
show_str.length(0);
|
||||
show_str.set_charset(system_charset_info);
|
||||
|
||||
if (et->get_create_event(thd, &show_str))
|
||||
DBUG_RETURN(1);
|
||||
|
||||
field_list.push_back(new Item_empty_string("Event", NAME_LEN));
|
||||
|
||||
sql_mode_str=
|
||||
sys_var_thd_sql_mode::symbolic_mode_representation(thd, et->sql_mode,
|
||||
&sql_mode_len);
|
||||
|
||||
field_list.push_back(new Item_empty_string("sql_mode", sql_mode_len));
|
||||
|
||||
field_list.push_back(new Item_empty_string("Create Event",
|
||||
show_str.length()));
|
||||
if (protocol->send_fields(&field_list, Protocol::SEND_NUM_ROWS |
|
||||
Protocol::SEND_EOF))
|
||||
DBUG_RETURN(1);
|
||||
|
||||
protocol->prepare_for_resend();
|
||||
protocol->store(et->name.str, et->name.length, system_charset_info);
|
||||
|
||||
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);
|
||||
}
|
||||
|
18
sql/event.h
18
sql/event.h
@ -109,6 +109,7 @@ public:
|
||||
enum enum_event_on_completion on_completion;
|
||||
enum enum_event_status status;
|
||||
sp_head *sphead;
|
||||
ulong sql_mode;
|
||||
|
||||
const uchar *body_begin;
|
||||
|
||||
@ -119,8 +120,9 @@ public:
|
||||
event_timed():running(0), status_changed(false), last_executed_changed(false),
|
||||
expression(0), created(0), modified(0),
|
||||
on_completion(MYSQL_EVENT_ON_COMPLETION_DROP),
|
||||
status(MYSQL_EVENT_ENABLED), sphead(0), dropped(false),
|
||||
free_sphead_on_delete(true), flags(0)
|
||||
status(MYSQL_EVENT_ENABLED), sphead(0), sql_mode(0),
|
||||
body_begin(0), dropped(false), free_sphead_on_delete(true),
|
||||
flags(0)
|
||||
|
||||
{
|
||||
pthread_mutex_init(&this->LOCK_running, MY_MUTEX_INIT_FAST);
|
||||
@ -177,8 +179,8 @@ public:
|
||||
bool
|
||||
update_fields(THD *thd);
|
||||
|
||||
char *
|
||||
get_show_create_event(THD *thd, uint32 *length);
|
||||
int
|
||||
get_create_event(THD *thd, String *buf);
|
||||
|
||||
int
|
||||
execute(THD *thd, MEM_ROOT *mem_root= NULL);
|
||||
@ -221,8 +223,16 @@ evex_drop_event(THD *thd, event_timed *et, bool drop_if_exists,
|
||||
int
|
||||
evex_open_event_table(THD *thd, enum thr_lock_type lock_type, TABLE **table);
|
||||
|
||||
int
|
||||
evex_show_create_event(THD *thd, sp_name *spn, LEX_STRING definer);
|
||||
|
||||
int sortcmp_lex_string(LEX_STRING s, LEX_STRING t, CHARSET_INFO *cs);
|
||||
|
||||
int
|
||||
event_reconstruct_interval_expression(String *buf,
|
||||
interval_type interval,
|
||||
longlong expression);
|
||||
|
||||
int
|
||||
init_events();
|
||||
|
||||
|
@ -33,9 +33,9 @@ extern ulong thread_created;
|
||||
extern const char *my_localhost;
|
||||
extern pthread_attr_t connection_attrib;
|
||||
|
||||
pthread_mutex_t LOCK_event_arrays,
|
||||
LOCK_workers_count,
|
||||
LOCK_evex_running;
|
||||
pthread_mutex_t LOCK_event_arrays, // mutex for when working with the queue
|
||||
LOCK_workers_count, // mutex for when inc/dec uint workers_count
|
||||
LOCK_evex_running; // mutes for managing bool evex_is_running
|
||||
|
||||
|
||||
bool evex_is_running= false;
|
||||
@ -62,6 +62,19 @@ event_executor_worker(void *arg);
|
||||
pthread_handler_t
|
||||
event_executor_main(void *arg);
|
||||
|
||||
|
||||
/*
|
||||
Returns the seconds difference of 2 TIME structs
|
||||
|
||||
SYNOPSIS
|
||||
evex_time_diff()
|
||||
a - TIME struct 1
|
||||
b - TIME struct 2
|
||||
|
||||
Returns:
|
||||
the seconds difference
|
||||
*/
|
||||
|
||||
static int
|
||||
evex_time_diff(TIME *a, TIME *b)
|
||||
{
|
||||
@ -69,6 +82,19 @@ evex_time_diff(TIME *a, TIME *b)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Inits the mutexes used by the scheduler module
|
||||
|
||||
SYNOPSIS
|
||||
evex_init_mutexes()
|
||||
|
||||
NOTES
|
||||
The mutexes are :
|
||||
LOCK_event_arrays
|
||||
LOCK_workers_count
|
||||
LOCK_evex_running
|
||||
*/
|
||||
|
||||
static void
|
||||
evex_init_mutexes()
|
||||
{
|
||||
@ -84,6 +110,75 @@ evex_init_mutexes()
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Opens mysql.db and mysql.user and checks whether
|
||||
1. mysql.db has column Event_priv at column 20 (0 based);
|
||||
2. mysql.user has column Event_priv at column 29 (0 based);
|
||||
|
||||
Synopsis
|
||||
evex_check_system_tables()
|
||||
*/
|
||||
|
||||
void
|
||||
evex_check_system_tables()
|
||||
{
|
||||
THD *thd= current_thd;
|
||||
TABLE_LIST tables;
|
||||
bool not_used;
|
||||
Open_tables_state backup;
|
||||
|
||||
// thd is 0x0 during boot of the server. Later it's !=0x0
|
||||
if (!thd)
|
||||
return;
|
||||
|
||||
thd->reset_n_backup_open_tables_state(&backup);
|
||||
|
||||
bzero((char*) &tables, sizeof(tables));
|
||||
tables.db= (char*) "mysql";
|
||||
tables.table_name= tables.alias= (char*) "db";
|
||||
tables.lock_type= TL_READ;
|
||||
|
||||
if (simple_open_n_lock_tables(thd, &tables))
|
||||
sql_print_error("Cannot open mysql.db");
|
||||
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);
|
||||
close_thread_tables(thd);
|
||||
}
|
||||
|
||||
bzero((char*) &tables, sizeof(tables));
|
||||
tables.db= (char*) "mysql";
|
||||
tables.table_name= tables.alias= (char*) "user";
|
||||
tables.lock_type= TL_READ;
|
||||
|
||||
if (simple_open_n_lock_tables(thd, &tables))
|
||||
sql_print_error("Cannot open mysql.db");
|
||||
else
|
||||
{
|
||||
if (tables.table->s->fields < 29 ||
|
||||
strncmp(tables.table->field[29]->field_name,
|
||||
STRING_WITH_LEN("Event_priv")))
|
||||
sql_print_error("mysql.user has no `Event_priv` column at position 29");
|
||||
|
||||
close_thread_tables(thd);
|
||||
}
|
||||
|
||||
thd->restore_backup_open_tables_state(&backup);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Inits the scheduler. Called on server start and every time the scheduler
|
||||
is started with switching the event_scheduler global variable to TRUE
|
||||
|
||||
SYNOPSIS
|
||||
init_events()
|
||||
|
||||
NOTES
|
||||
Inits the mutexes used by the scheduler. Done at server start.
|
||||
*/
|
||||
|
||||
int
|
||||
init_events()
|
||||
{
|
||||
@ -92,6 +187,8 @@ init_events()
|
||||
DBUG_ENTER("init_events");
|
||||
|
||||
DBUG_PRINT("info",("Starting events main thread"));
|
||||
|
||||
evex_check_system_tables();
|
||||
|
||||
evex_init_mutexes();
|
||||
|
||||
@ -114,6 +211,16 @@ init_events()
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Cleans up scheduler memory. Called on server shutdown.
|
||||
|
||||
SYNOPSIS
|
||||
shutdown_events()
|
||||
|
||||
NOTES
|
||||
Destroys the mutexes.
|
||||
*/
|
||||
|
||||
void
|
||||
shutdown_events()
|
||||
{
|
||||
@ -130,6 +237,22 @@ shutdown_events()
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Inits an scheduler thread handler, both the main and a worker
|
||||
|
||||
SYNOPSIS
|
||||
init_event_thread()
|
||||
thd - the THD of the thread. Has to be allocated by the caller.
|
||||
|
||||
NOTES
|
||||
1. The host of the thead is my_localhost
|
||||
2. thd->net is initted with NULL - no communication.
|
||||
|
||||
Returns
|
||||
0 - OK
|
||||
-1 - Error
|
||||
*/
|
||||
|
||||
static int
|
||||
init_event_thread(THD* thd)
|
||||
{
|
||||
@ -166,6 +289,22 @@ init_event_thread(THD* thd)
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
The main scheduler thread. Inits the priority queue on start and
|
||||
destroys it on thread shutdown. Forks child threads for every event
|
||||
execution. Sleeps between thread forking and does not do a busy wait.
|
||||
|
||||
SYNOPSIS
|
||||
event_executor_main()
|
||||
arg - unused
|
||||
|
||||
NOTES
|
||||
1. The host of the thead is my_localhost
|
||||
2. thd->net is initted with NULL - no communication.
|
||||
|
||||
*/
|
||||
|
||||
pthread_handler_t
|
||||
event_executor_main(void *arg)
|
||||
{
|
||||
@ -437,6 +576,15 @@ err_no_thd:
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Function that executes an event in a child thread. Setups the
|
||||
environment for the event execution and cleans after that.
|
||||
|
||||
SYNOPSIS
|
||||
event_executor_worker()
|
||||
arg - the event_timed object to be processed
|
||||
*/
|
||||
|
||||
pthread_handler_t
|
||||
event_executor_worker(void *event_void)
|
||||
{
|
||||
@ -562,6 +710,24 @@ err_no_thd:
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Loads all ENABLED events from mysql.event into the prioritized
|
||||
queue. Called during scheduler main thread initialization. Compiles
|
||||
the events. Creates event_timed instances for every ENABLED event
|
||||
from mysql.event.
|
||||
|
||||
SYNOPSIS
|
||||
evex_load_events_from_db()
|
||||
thd - Thread context. Used for memory allocation in some cases.
|
||||
|
||||
RETURNS
|
||||
0 - OK
|
||||
-1 - Error
|
||||
|
||||
NOTES
|
||||
Reports the error to the console
|
||||
*/
|
||||
|
||||
static int
|
||||
evex_load_events_from_db(THD *thd)
|
||||
{
|
||||
@ -648,7 +814,22 @@ end:
|
||||
}
|
||||
|
||||
|
||||
bool sys_var_event_executor::update(THD *thd, set_var *var)
|
||||
/*
|
||||
The update method of the global variable event_scheduler.
|
||||
If event_scheduler is switched from 0 to 1 then the scheduler main
|
||||
thread is started.
|
||||
|
||||
SYNOPSIS
|
||||
event_executor_worker()
|
||||
thd - Thread context (unused)
|
||||
car - the new value
|
||||
|
||||
Returns
|
||||
0 - OK (always)
|
||||
*/
|
||||
|
||||
bool
|
||||
sys_var_event_executor::update(THD *thd, set_var *var)
|
||||
{
|
||||
// here start the thread if not running.
|
||||
DBUG_ENTER("sys_var_event_executor::update");
|
||||
|
@ -116,7 +116,10 @@ event_timed::init_body(THD *thd)
|
||||
while (body.length && body_begin[body.length-1] == '\0')
|
||||
body.length--;
|
||||
|
||||
body.str= strmake_root(root, (char *)body_begin, body.length);
|
||||
//the first is always space which I cannot skip in the parser
|
||||
DBUG_ASSERT(*body_begin == ' ');
|
||||
body.length--;
|
||||
body.str= strmake_root(root, (char *)body_begin + 1, body.length);
|
||||
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
@ -847,6 +850,15 @@ err:
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Set the internal last_executed TIME struct to now. NOW is the
|
||||
time according to thd->query_start(), so the THD's clock.
|
||||
|
||||
Synopsis
|
||||
event_timed::drop()
|
||||
thd - thread context
|
||||
*/
|
||||
|
||||
void
|
||||
event_timed::mark_last_executed(THD *thd)
|
||||
{
|
||||
@ -864,7 +876,13 @@ event_timed::mark_last_executed(THD *thd)
|
||||
|
||||
|
||||
/*
|
||||
Returns :
|
||||
Drops the event
|
||||
|
||||
Synopsis
|
||||
event_timed::drop()
|
||||
thd - thread context
|
||||
|
||||
RETURNS :
|
||||
0 - OK
|
||||
-1 - Cannot open mysql.event
|
||||
-2 - Cannot find the event in mysql.event (already deleted?)
|
||||
@ -884,6 +902,22 @@ event_timed::drop(THD *thd)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Saves status and last_executed_at to the disk if changed.
|
||||
|
||||
Synopsis
|
||||
event_timed::drop()
|
||||
thd - thread context
|
||||
|
||||
Returns :
|
||||
0 - OK
|
||||
SP_OPEN_TABLE_FAILED - Error while opening mysql.event for writing
|
||||
EVEX_WRITE_ROW_FAILED - On error to write to disk
|
||||
|
||||
others - return code from SE in case deletion of the event row
|
||||
failed.
|
||||
*/
|
||||
|
||||
bool
|
||||
event_timed::update_fields(THD *thd)
|
||||
{
|
||||
@ -941,40 +975,75 @@ done:
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
event_timed::get_show_create_event(THD *thd, uint32 *length)
|
||||
/*
|
||||
Get SHOW CREATE EVENT as string
|
||||
|
||||
thd - Thread
|
||||
buf - String*, should be already allocated. CREATE EVENT goes inside.
|
||||
|
||||
Returns:
|
||||
0 - OK
|
||||
1 - Error (for now if mysql.event has been tampered and MICROSECONDS
|
||||
interval or derivative has been put there.
|
||||
*/
|
||||
|
||||
int
|
||||
event_timed::get_create_event(THD *thd, String *buf)
|
||||
{
|
||||
char *dst, *ret;
|
||||
uint len, tmp_len;
|
||||
DBUG_ENTER("get_show_create_event");
|
||||
int multipl= 0;
|
||||
char tmp_buff[128];
|
||||
String expr_buf(tmp_buff, sizeof(tmp_buff), system_charset_info);
|
||||
expr_buf.length(0);
|
||||
|
||||
DBUG_ENTER("get_create_event");
|
||||
DBUG_PRINT("ret_info",("body_len=[%d]body=[%s]", body.length, body.str));
|
||||
|
||||
len = strlen("CREATE EVENT `") + dbname.length + strlen("`.`") + name.length +
|
||||
strlen("` ON SCHEDULE EVERY 5 MINUTE DO ") + body.length;// + strlen(";");
|
||||
|
||||
ret= dst= (char*) alloc_root(thd->mem_root, len + 1);
|
||||
memcpy(dst, "CREATE EVENT `", tmp_len= strlen("CREATE EVENT `"));
|
||||
dst+= tmp_len;
|
||||
memcpy(dst, dbname.str, tmp_len=dbname.length);
|
||||
dst+= tmp_len;
|
||||
memcpy(dst, "`.`", tmp_len= strlen("`.`"));
|
||||
dst+= tmp_len;
|
||||
memcpy(dst, name.str, tmp_len= name.length);
|
||||
dst+= tmp_len;
|
||||
memcpy(dst, "` ON SCHEDULE EVERY 5 MINUTE DO ",
|
||||
tmp_len= strlen("` ON SCHEDULE EVERY 5 MINUTE DO "));
|
||||
dst+= tmp_len;
|
||||
if (expression &&
|
||||
event_reconstruct_interval_expression(&expr_buf, interval, expression))
|
||||
DBUG_RETURN(1);
|
||||
|
||||
memcpy(dst, body.str, tmp_len= body.length);
|
||||
dst+= tmp_len;
|
||||
// memcpy(dst, ";", 1);
|
||||
// ++dst;
|
||||
*dst= '\0';
|
||||
|
||||
*length= len;
|
||||
|
||||
DBUG_PRINT("ret_info",("len=%d",*length));
|
||||
DBUG_RETURN(ret);
|
||||
buf->append(STRING_WITH_LEN("CREATE EVENT "));
|
||||
append_identifier(thd, buf, dbname.str, dbname.length);
|
||||
buf->append(STRING_WITH_LEN("."));
|
||||
append_identifier(thd, buf, name.str, name.length);
|
||||
|
||||
buf->append(STRING_WITH_LEN(" ON SCHEDULE "));
|
||||
if (expression)
|
||||
{
|
||||
buf->append(STRING_WITH_LEN("EVERY "));
|
||||
buf->append(expr_buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
char dtime_buff[20*2+32];// +32 to make my_snprintf_{8bit|ucs2} happy
|
||||
buf->append(STRING_WITH_LEN("AT '"));
|
||||
/*
|
||||
pass the buffer and the second param tells fills the buffer and returns
|
||||
the number of chars to copy
|
||||
*/
|
||||
buf->append(dtime_buff, my_datetime_to_str(&execute_at, dtime_buff));
|
||||
buf->append(STRING_WITH_LEN("'"));
|
||||
}
|
||||
|
||||
if (on_completion == MYSQL_EVENT_ON_COMPLETION_DROP)
|
||||
buf->append(STRING_WITH_LEN(" ON COMPLETION NOT PRESERVE "));
|
||||
else
|
||||
buf->append(STRING_WITH_LEN(" ON COMPLETION PRESERVE "));
|
||||
|
||||
if (status == MYSQL_EVENT_ENABLED)
|
||||
buf->append(STRING_WITH_LEN("ENABLE"));
|
||||
else
|
||||
buf->append(STRING_WITH_LEN("DISABLE"));
|
||||
|
||||
if (comment.length)
|
||||
{
|
||||
buf->append(STRING_WITH_LEN(" COMMENT "));
|
||||
append_unescaped(buf, comment.str, comment.length);
|
||||
}
|
||||
buf->append(STRING_WITH_LEN(" DO "));
|
||||
buf->append(body.str, body.length);
|
||||
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
||||
@ -1035,13 +1104,21 @@ done:
|
||||
|
||||
|
||||
/*
|
||||
Compiles an event before it's execution. Compiles the anonymous
|
||||
sp_head object held by the event
|
||||
|
||||
Synopsis
|
||||
event_timed::compile()
|
||||
thd - thread context, used for memory allocation mostly
|
||||
mem_root - if != NULL then this memory root is used for allocs
|
||||
instead of thd->mem_root
|
||||
|
||||
Returns
|
||||
0 - Success
|
||||
EVEX_COMPILE_ERROR - Error during compilation
|
||||
|
||||
*/
|
||||
|
||||
|
||||
int
|
||||
event_timed::compile(THD *thd, MEM_ROOT *mem_root)
|
||||
{
|
||||
@ -1054,9 +1131,13 @@ event_timed::compile(THD *thd, MEM_ROOT *mem_root)
|
||||
char *old_query;
|
||||
uint old_query_len;
|
||||
st_sp_chistics *p;
|
||||
CHARSET_INFO *old_character_set_client, *old_collation_connection,
|
||||
char create_buf[2048];
|
||||
String show_create(create_buf, sizeof(create_buf), system_charset_info);
|
||||
CHARSET_INFO *old_character_set_client,
|
||||
*old_collation_connection,
|
||||
*old_character_set_results;
|
||||
|
||||
|
||||
show_create.length(0);
|
||||
old_character_set_client= thd->variables.character_set_client;
|
||||
old_character_set_results= thd->variables.character_set_results;
|
||||
old_collation_connection= thd->variables.collation_connection;
|
||||
@ -1079,7 +1160,11 @@ event_timed::compile(THD *thd, MEM_ROOT *mem_root)
|
||||
old_query= thd->query;
|
||||
old_db= thd->db;
|
||||
thd->db= dbname.str;
|
||||
thd->query= get_show_create_event(thd, &thd->query_length);
|
||||
|
||||
get_create_event(thd, &show_create);
|
||||
|
||||
thd->query= show_create.c_ptr();
|
||||
thd->query_length= show_create.length();
|
||||
DBUG_PRINT("event_timed::compile", ("query:%s",thd->query));
|
||||
|
||||
thd->lex= &lex;
|
||||
|
122
sql/sql_acl.cc
122
sql/sql_acl.cc
@ -36,6 +36,122 @@
|
||||
|
||||
#define FIRST_NON_YN_FIELD 26
|
||||
|
||||
time_t mysql_db_table_last_check= 0L;
|
||||
|
||||
TABLE_FIELD_W_TYPE mysql_db_table_fields[MYSQL_DB_FIELD_COUNT] = {
|
||||
{
|
||||
{(char *) STRING_WITH_LEN("Host")},
|
||||
{(char *) STRING_WITH_LEN("char(60)")},
|
||||
{NULL, 0}
|
||||
},
|
||||
{
|
||||
{(char *) STRING_WITH_LEN("Db")},
|
||||
{(char *) STRING_WITH_LEN("char(64)")},
|
||||
{NULL, 0}
|
||||
},
|
||||
{
|
||||
{(char *) STRING_WITH_LEN("User")},
|
||||
{(char *) STRING_WITH_LEN("char(16)")},
|
||||
{NULL, 0}
|
||||
},
|
||||
{
|
||||
{(char *) STRING_WITH_LEN("Select_priv")},
|
||||
{(char *) STRING_WITH_LEN("enum('N','Y')")},
|
||||
{(char *) STRING_WITH_LEN("utf8")}
|
||||
},
|
||||
{
|
||||
{(char *) STRING_WITH_LEN("Insert_priv")},
|
||||
{(char *) STRING_WITH_LEN("enum('N','Y')")},
|
||||
{(char *) STRING_WITH_LEN("utf8")}
|
||||
},
|
||||
{
|
||||
{(char *) STRING_WITH_LEN("Update_priv")},
|
||||
{(char *) STRING_WITH_LEN("enum('N','Y')")},
|
||||
{(char *) STRING_WITH_LEN("utf8")}
|
||||
},
|
||||
{
|
||||
{(char *) STRING_WITH_LEN("Delete_priv")},
|
||||
{(char *) STRING_WITH_LEN("enum('N','Y')")},
|
||||
{(char *) STRING_WITH_LEN("utf8")}
|
||||
},
|
||||
{
|
||||
{(char *) STRING_WITH_LEN("Create_priv")},
|
||||
{(char *) STRING_WITH_LEN("enum('N','Y')")},
|
||||
{(char *) STRING_WITH_LEN("utf8")}
|
||||
},
|
||||
{
|
||||
{(char *) STRING_WITH_LEN("Drop_priv")},
|
||||
{(char *) STRING_WITH_LEN("enum('N','Y')")},
|
||||
{(char *) STRING_WITH_LEN("utf8")}
|
||||
},
|
||||
{
|
||||
{(char *) STRING_WITH_LEN("Grant_priv")},
|
||||
{(char *) STRING_WITH_LEN("enum('N','Y')")},
|
||||
{(char *) STRING_WITH_LEN("utf8")}
|
||||
},
|
||||
{
|
||||
{(char *) STRING_WITH_LEN("References_priv")},
|
||||
{(char *) STRING_WITH_LEN("enum('N','Y')")},
|
||||
{(char *) STRING_WITH_LEN("utf8")}
|
||||
},
|
||||
{
|
||||
{(char *) STRING_WITH_LEN("Index_priv")},
|
||||
{(char *) STRING_WITH_LEN("enum('N','Y')")},
|
||||
{(char *) STRING_WITH_LEN("utf8")}
|
||||
},
|
||||
{
|
||||
{(char *) STRING_WITH_LEN("Alter_priv")},
|
||||
{(char *) STRING_WITH_LEN("enum('N','Y')")},
|
||||
{(char *) STRING_WITH_LEN("utf8")}
|
||||
},
|
||||
{
|
||||
{(char *) STRING_WITH_LEN("Create_tmp_table_priv")},
|
||||
{(char *) STRING_WITH_LEN("enum('N','Y')")},
|
||||
{(char *) STRING_WITH_LEN("utf8")}
|
||||
},
|
||||
{
|
||||
{(char *) STRING_WITH_LEN("Lock_tables_priv")},
|
||||
{(char *) STRING_WITH_LEN("enum('N','Y')")},
|
||||
{(char *) STRING_WITH_LEN("utf8")}
|
||||
},
|
||||
{
|
||||
{(char *) STRING_WITH_LEN("Create_view_priv")},
|
||||
{(char *) STRING_WITH_LEN("enum('N','Y')")},
|
||||
{(char *) STRING_WITH_LEN("utf8")}
|
||||
},
|
||||
{
|
||||
{(char *) STRING_WITH_LEN("Show_view_priv")},
|
||||
{(char *) STRING_WITH_LEN("enum('N','Y')")},
|
||||
{(char *) STRING_WITH_LEN("utf8")}
|
||||
},
|
||||
{
|
||||
{(char *) STRING_WITH_LEN("Create_routine_priv")},
|
||||
{(char *) STRING_WITH_LEN("enum('N','Y')")},
|
||||
{(char *) STRING_WITH_LEN("utf8")}
|
||||
},
|
||||
{
|
||||
{(char *) STRING_WITH_LEN("Alter_routine_priv")},
|
||||
{(char *) STRING_WITH_LEN("enum('N','Y')")},
|
||||
{(char *) STRING_WITH_LEN("utf8")}
|
||||
},
|
||||
{
|
||||
{(char *) STRING_WITH_LEN("Execute_priv")},
|
||||
{(char *) STRING_WITH_LEN("enum('N','Y')")},
|
||||
{(char *) STRING_WITH_LEN("utf8")}
|
||||
},
|
||||
{
|
||||
{(char *) STRING_WITH_LEN("Event_priv")},
|
||||
{(char *) STRING_WITH_LEN("enum('N','Y')")},
|
||||
{(char *) STRING_WITH_LEN("utf8")}
|
||||
},
|
||||
{
|
||||
{(char *) STRING_WITH_LEN("Trigger_priv")},
|
||||
{(char *) STRING_WITH_LEN("enum('N','Y')")},
|
||||
{(char *) STRING_WITH_LEN("utf8")}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class acl_entry :public hash_filo_element
|
||||
{
|
||||
public:
|
||||
@ -441,14 +557,14 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables)
|
||||
while (!(read_record_info.read_record(&read_record_info)))
|
||||
{
|
||||
ACL_DB db;
|
||||
update_hostname(&db.host,get_field(&mem, table->field[0]));
|
||||
db.db=get_field(&mem, table->field[1]);
|
||||
update_hostname(&db.host,get_field(&mem, table->field[MYSQL_DB_FIELD_HOST]));
|
||||
db.db=get_field(&mem, table->field[MYSQL_DB_FIELD_DB]);
|
||||
if (!db.db)
|
||||
{
|
||||
sql_print_warning("Found an entry in the 'db' table with empty database name; Skipped");
|
||||
continue;
|
||||
}
|
||||
db.user=get_field(&mem, table->field[2]);
|
||||
db.user=get_field(&mem, table->field[MYSQL_DB_FIELD_USER]);
|
||||
if (check_no_resolve && hostname_requires_resolving(db.host.hostname))
|
||||
{
|
||||
sql_print_warning("'db' entry '%s %s@%s' "
|
||||
|
@ -134,6 +134,36 @@
|
||||
(((A) & ALTER_PROC_ACL) >> 23) | \
|
||||
(((A) & GRANT_ACL) >> 8))
|
||||
|
||||
enum mysql_db_table_field
|
||||
{
|
||||
MYSQL_DB_FIELD_HOST = 0,
|
||||
MYSQL_DB_FIELD_DB,
|
||||
MYSQL_DB_FIELD_USER,
|
||||
MYSQL_DB_FIELD_SELECT_PRIV,
|
||||
MYSQL_DB_FIELD_INSERT_PRIV,
|
||||
MYSQL_DB_FIELD_UPDATE_PRIV,
|
||||
MYSQL_DB_FIELD_DELETE_PRIV,
|
||||
MYSQL_DB_FIELD_CREATE_PRIV,
|
||||
MYSQL_DB_FIELD_DROP_PRIV,
|
||||
MYSQL_DB_FIELD_GRANT_PRIV,
|
||||
MYSQL_DB_FIELD_REFERENCES_PRIV,
|
||||
MYSQL_DB_FIELD_INDEX_PRIV,
|
||||
MYSQL_DB_FIELD_ALTER_PRIV,
|
||||
MYSQL_DB_FIELD_CREATE_TMP_TABLE_PRIV,
|
||||
MYSQL_DB_FIELD_LOCK_TABLES_PRIV,
|
||||
MYSQL_DB_FIELD_CREATE_VIEW_PRIV,
|
||||
MYSQL_DB_FIELD_SHOW_VIEW_PRIV,
|
||||
MYSQL_DB_FIELD_CREATE_ROUTINE_PRIV,
|
||||
MYSQL_DB_FIELD_ALTER_ROUTINE_PRIV,
|
||||
MYSQL_DB_FIELD_EXECUTE_PRIV,
|
||||
MYSQL_DB_FIELD_EVENT_PRIV,
|
||||
MYSQL_DB_FIELD_TRIGGER_PRIV,
|
||||
MYSQL_DB_FIELD_COUNT
|
||||
};
|
||||
|
||||
extern TABLE_FIELD_W_TYPE mysql_db_table_fields[];
|
||||
extern time_t mysql_db_table_last_check;
|
||||
|
||||
/* Classes */
|
||||
|
||||
struct acl_host_and_ip
|
||||
|
@ -3799,6 +3799,14 @@ end_with_restore_list:
|
||||
}
|
||||
case SQLCOM_SHOW_CREATE_EVENT:
|
||||
{
|
||||
DBUG_ASSERT(lex->spname);
|
||||
DBUG_ASSERT(lex->et);
|
||||
if (! lex->spname->m_db.str)
|
||||
{
|
||||
my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
|
||||
res= true;
|
||||
break;
|
||||
}
|
||||
if (check_access(thd, EVENT_ACL, lex->spname->m_db.str, 0, 0, 0,
|
||||
is_schema_db(lex->spname->m_db.str)))
|
||||
break;
|
||||
@ -3808,8 +3816,7 @@ end_with_restore_list:
|
||||
my_error(ER_TOO_LONG_IDENT, MYF(0), lex->spname->m_name.str);
|
||||
goto error;
|
||||
}
|
||||
/* TODO : Implement it */
|
||||
send_ok(thd, 1);
|
||||
res= evex_show_create_event(thd, lex->spname, lex->et->definer);
|
||||
break;
|
||||
}
|
||||
case SQLCOM_CREATE_FUNCTION: // UDF function
|
||||
|
@ -3766,30 +3766,6 @@ static int get_schema_partitions_record(THD *thd, struct st_table_list *tables,
|
||||
}
|
||||
|
||||
|
||||
static LEX_STRING interval_type_to_name[] = {
|
||||
{(char *) STRING_WITH_LEN("INTERVAL_YEAR")},
|
||||
{(char *) STRING_WITH_LEN("INTERVAL_QUARTER")},
|
||||
{(char *) STRING_WITH_LEN("INTERVAL_MONTH")},
|
||||
{(char *) STRING_WITH_LEN("INTERVAL_DAY")},
|
||||
{(char *) STRING_WITH_LEN("INTERVAL_HOUR")},
|
||||
{(char *) STRING_WITH_LEN("INTERVAL_MINUTE")},
|
||||
{(char *) STRING_WITH_LEN("INTERVAL_WEEK")},
|
||||
{(char *) STRING_WITH_LEN("INTERVAL_SECOND")},
|
||||
{(char *) STRING_WITH_LEN("INTERVAL_MICROSECOND ")},
|
||||
{(char *) STRING_WITH_LEN("INTERVAL_YEAR_MONTH")},
|
||||
{(char *) STRING_WITH_LEN("INTERVAL_DAY_HOUR")},
|
||||
{(char *) STRING_WITH_LEN("INTERVAL_DAY_MINUTE")},
|
||||
{(char *) STRING_WITH_LEN("INTERVAL_DAY_SECOND")},
|
||||
{(char *) STRING_WITH_LEN("INTERVAL_HOUR_MINUTE")},
|
||||
{(char *) STRING_WITH_LEN("INTERVAL_HOUR_SECOND")},
|
||||
{(char *) STRING_WITH_LEN("INTERVAL_MINUTE_SECOND")},
|
||||
{(char *) STRING_WITH_LEN("INTERVAL_DAY_MICROSECOND")},
|
||||
{(char *) STRING_WITH_LEN("INTERVAL_HOUR_MICROSECOND")},
|
||||
{(char *) STRING_WITH_LEN("INTERVAL_MINUTE_MICROSECOND")},
|
||||
{(char *) STRING_WITH_LEN("INTERVAL_SECOND_MICROSECOND")}
|
||||
};
|
||||
|
||||
|
||||
static interval_type get_real_interval_type(interval_type i_type)
|
||||
{
|
||||
switch (i_type) {
|
||||
@ -3863,6 +3839,7 @@ fill_events_copy_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table)
|
||||
sch_table->field[9]->set_null();
|
||||
if (et.expression)
|
||||
{
|
||||
String show_str;
|
||||
//type
|
||||
sch_table->field[5]->store(STRING_WITH_LEN("RECURRING"), scs);
|
||||
//execute_at
|
||||
@ -3871,9 +3848,11 @@ fill_events_copy_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table)
|
||||
sch_table->field[7]->set_notnull();
|
||||
sch_table->field[7]->store((longlong) et.expression);
|
||||
//interval_type
|
||||
LEX_STRING *ival=&interval_type_to_name[get_real_interval_type(et.interval)];
|
||||
if (event_reconstruct_interval_expression(&show_str, et.interval,
|
||||
et.expression))
|
||||
DBUG_RETURN(1);
|
||||
sch_table->field[8]->set_notnull();
|
||||
sch_table->field[8]->store(ival->str, ival->length, scs);
|
||||
sch_table->field[8]->store(show_str.c_ptr(), show_str.length(), scs);
|
||||
//starts & ends
|
||||
sch_table->field[10]->set_notnull();
|
||||
sch_table->field[10]->store_time(&et.starts, MYSQL_TIMESTAMP_DATETIME);
|
||||
|
@ -8431,6 +8431,10 @@ show_param:
|
||||
{
|
||||
Lex->sql_command = SQLCOM_SHOW_CREATE_EVENT;
|
||||
Lex->spname= $3;
|
||||
Lex->et= new event_timed();
|
||||
if (!Lex->et)
|
||||
YYABORT;
|
||||
Lex->et->init_definer(YYTHD);
|
||||
}
|
||||
;
|
||||
|
||||
|
142
sql/table.cc
142
sql/table.cc
@ -343,9 +343,7 @@ int open_table_def(THD *thd, TABLE_SHARE *share, uint db_flags)
|
||||
allow to lock such tables for writing with any other tables (even with
|
||||
other system tables) and some privilege tables need this.
|
||||
*/
|
||||
if (!my_strcasecmp(system_charset_info, share->table_name.str, "proc")
|
||||
|| !my_strcasecmp(system_charset_info, share->table_name.str,
|
||||
"event"))
|
||||
if (!my_strcasecmp(system_charset_info, share->table_name.str, "proc"))
|
||||
share->system_table= 1;
|
||||
else
|
||||
{
|
||||
@ -2291,6 +2289,144 @@ bool check_column_name(const char *name)
|
||||
return last_char_is_space || (uint) (name - start) > NAME_LEN;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Checks whether a table is intact. Should be done *just* after the table has
|
||||
been opened.
|
||||
|
||||
Synopsis
|
||||
table_check_intact()
|
||||
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)
|
||||
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
|
||||
is sent to the client in case types does not match.
|
||||
If different col number either
|
||||
ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE or
|
||||
ER_COL_COUNT_DOESNT_MATCH_CORRUPTED is used
|
||||
|
||||
RETURNS
|
||||
0 - OK
|
||||
1 - There was an error
|
||||
*/
|
||||
|
||||
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)
|
||||
{
|
||||
uint i;
|
||||
my_bool error= FALSE;
|
||||
my_bool fields_diff_count;
|
||||
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))
|
||||
{
|
||||
DBUG_PRINT("info", ("I am suspecting, checking table"));
|
||||
if (fields_diff_count)
|
||||
{
|
||||
// previous MySQL version
|
||||
error= TRUE;
|
||||
if (MYSQL_VERSION_ID > table->s->mysql_version)
|
||||
my_error(ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE, MYF(0), table->alias,
|
||||
table_f_count, table->s->fields, table->s->mysql_version,
|
||||
MYSQL_VERSION_ID);
|
||||
else if (MYSQL_VERSION_ID == table->s->mysql_version)
|
||||
my_error(ER_COL_COUNT_DOESNT_MATCH_CORRUPTED,MYF(0), table->alias,
|
||||
table_f_count, table->s->fields);
|
||||
else
|
||||
/*
|
||||
moving from newer mysql to older one -> let's say not an error but
|
||||
will check the definition afterwards. If a column was added at the end
|
||||
then we don't care much since it's not in the middle.
|
||||
*/
|
||||
error= FALSE;
|
||||
}
|
||||
//definitely something has changed
|
||||
char buffer[255];
|
||||
for (i=0 ;i < table_f_count; ++i, ++table_def)
|
||||
{
|
||||
Field *field= table->field[i];
|
||||
String sql_type(buffer, sizeof(buffer), system_charset_info);
|
||||
sql_type.length(0);
|
||||
/*
|
||||
name changes are not fatal, we use sequence numbers => no prob for us
|
||||
but this can show tampered table or broken table.
|
||||
*/
|
||||
if (!fields_diff_count || i < table->s->fields)
|
||||
{
|
||||
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,
|
||||
field->field_name);
|
||||
}
|
||||
|
||||
/*
|
||||
IF the type does not match than something is really wrong
|
||||
Check up to length - 1. Why?
|
||||
1. datetime -> datetim -> the same
|
||||
2. int(11) -> int(11 -> the same
|
||||
3. set('one','two') -> set('one','two'
|
||||
so for sets if the same prefix is there it's ok if more are
|
||||
added as part of the set. The same is valid for enum. So a new
|
||||
table running on a old server will be valid.
|
||||
*/
|
||||
field->sql_type(sql_type);
|
||||
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());
|
||||
error= TRUE;
|
||||
}
|
||||
else if (table_def->cset.str && !field->has_charset())
|
||||
{
|
||||
sql_print_error("(%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);
|
||||
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 "
|
||||
"character set '%s' but found '%s'", table->alias,
|
||||
table_def->name.str, i, table_def->cset.str,
|
||||
field->charset()->csname);
|
||||
error= TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sql_print_error("(%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 (!error)
|
||||
*last_create_time= table->file->create_time;
|
||||
else if (!fields_diff_count && error_num)
|
||||
my_error(error_num,MYF(0), table->alias, table_f_count, table->s->fields);
|
||||
}
|
||||
else
|
||||
{
|
||||
DBUG_PRINT("info", ("Table seems ok without through checking."));
|
||||
*last_create_time= table->file->create_time;
|
||||
}
|
||||
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Create Item_field for each column in the table.
|
||||
|
||||
|
11
sql/table.h
11
sql/table.h
@ -866,4 +866,15 @@ typedef struct st_open_table_list{
|
||||
uint32 in_use,locked;
|
||||
} OPEN_TABLE_LIST;
|
||||
|
||||
typedef struct st_table_field_w_type
|
||||
{
|
||||
LEX_STRING name;
|
||||
LEX_STRING type;
|
||||
LEX_STRING cset;
|
||||
} TABLE_FIELD_W_TYPE;
|
||||
|
||||
|
||||
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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user