Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
MariaDB
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
MariaDB
Commits
0a0304b5
Commit
0a0304b5
authored
Jan 30, 2006
by
andrey@lmy004
Browse files
Options
Browse Files
Download
Plain Diff
Merge ahristov@bk-internal.mysql.com:/home/bk/mysql-5.1-new
into lmy004.:/work/mysql-5.1-events_i_s
parents
94e65a83
08892be3
Changes
19
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
598 additions
and
75 deletions
+598
-75
mysql-test/lib/init_db.sql
mysql-test/lib/init_db.sql
+1
-1
mysql-test/r/events.result
mysql-test/r/events.result
+81
-1
mysql-test/r/information_schema.result
mysql-test/r/information_schema.result
+11
-2
mysql-test/r/information_schema_db.result
mysql-test/r/information_schema_db.result
+1
-0
mysql-test/r/system_mysql_db.result
mysql-test/r/system_mysql_db.result
+1
-1
mysql-test/t/events.test
mysql-test/t/events.test
+77
-1
scripts/mysql_create_system_tables.sh
scripts/mysql_create_system_tables.sh
+1
-1
scripts/mysql_fix_privilege_tables.sql
scripts/mysql_fix_privilege_tables.sql
+2
-0
sql/event.cc
sql/event.cc
+41
-22
sql/event.h
sql/event.h
+29
-4
sql/event_executor.cc
sql/event_executor.cc
+3
-2
sql/event_priv.h
sql/event_priv.h
+3
-24
sql/event_timed.cc
sql/event_timed.cc
+21
-8
sql/mysqld.cc
sql/mysqld.cc
+1
-0
sql/sql_lex.h
sql/sql_lex.h
+1
-1
sql/sql_parse.cc
sql/sql_parse.cc
+6
-1
sql/sql_show.cc
sql/sql_show.cc
+292
-0
sql/sql_yacc.yy
sql/sql_yacc.yy
+25
-6
sql/table.h
sql/table.h
+1
-0
No files found.
mysql-test/lib/init_db.sql
View file @
0a0304b5
...
...
@@ -596,7 +596,7 @@ CREATE TABLE event (
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
(
d
b
,
name
)
PRIMARY
KEY
(
d
efiner
,
db
,
name
)
)
ENGINE
=
MyISAM
DEFAULT
CHARSET
=
utf8
COMMENT
'Events'
;
CREATE
DATABASE
IF
NOT
EXISTS
cluster_replication
;
...
...
mysql-test/r/events.result
View file @
0a0304b5
...
...
@@ -34,13 +34,93 @@ create table t_event3 (a int, b float);
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("20
01
0101", interval 5 minute) ends date_add("20151010", interval 5 day) comment "portokala_comment" DO insert into t_event3 values (unix_timestamp(), rand());
create event event3 on schedule every 50 + 10 minute starts date_add("20
10
0101", 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
drop event event3;
drop table t_event3;
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
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
CREATE DATABASE events_test2;
CREATE USER ev_test@localhost;
GRANT ALL ON events_test.* to ev_test@localhost;
GRANT ALL on events_test2.* to ev_test@localhost;
REVOKE EVENT ON events_test2.* FROM ev_test@localhost;
REVOKE PROCESS on *.* from ev_test@localhost;
select "NEW CONNECTION";
NEW CONNECTION
NEW CONNECTION
SELECT USER(), DATABASE();
USER() DATABASE()
ev_test@localhost events_test2
SHOW GRANTS;
Grants for ev_test@localhost
GRANT USAGE ON *.* TO 'ev_test'@'localhost'
GRANT ALL PRIVILEGES ON `events_test`.* TO 'ev_test'@'localhost'
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, ALTER, CREATE TEMPORARY TABLES, LOCK TABLES, EXECUTE, CREATE VIEW, SHOW VIEW, CREATE ROUTINE, ALTER ROUTINE ON `events_test2`.* TO 'ev_test'@'localhost'
"Here comes an error:";
SHOW EVENTS;
ERROR 42000: Access denied for user 'ev_test'@'localhost' to database 'events_test2'
USE events_test;
"Now the list should be empty:";
SHOW EVENTS;
Db Name Definer Type Execute at Interval value Interval field Starts Ends Status
select concat("Let's create some new events from the name of ",user());
concat("Let's create some new events from the name of ",user())
Let's create some new events from the name of ev_test@localhost
create event one_event on schedule every 20 second do select 123;
create event two_event on schedule every 20 second on completion not preserve comment "two event" do select 123;
create event three_event on schedule every 20 second on completion preserve comment "three event" do select 123;
"Now we should see 3 events:";
SHOW EVENTS;
Db Name Definer Type Execute at Interval value Interval field Starts Ends Status
events_test one_event ev_test@localhost RECURRING NULL 20 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
"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
"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
"This should show us no events:";
SHOW FULL EVENTS FROM test LIKE '%';
Db Name Definer Type Execute at Interval value Interval field Starts Ends Status
DROP DATABASE events_test2;
"should see 1 event:";
SHOW EVENTS;
Db Name Definer Type Execute at Interval value Interval field Starts Ends Status
events_test one_event root@localhost RECURRING NULL 10 INTERVAL_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
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
drop event one_event;
drop event two_event;
drop event three_event;
drop user ev_test@localhost;
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
...
...
mysql-test/r/information_schema.result
View file @
0a0304b5
...
...
@@ -44,6 +44,7 @@ COLLATION_CHARACTER_SET_APPLICABILITY
COLUMNS
COLUMN_PRIVILEGES
ENGINES
EVENTS
KEY_COLUMN_USAGE
PARTITIONS
PLUGINS
...
...
@@ -734,7 +735,7 @@ CREATE TABLE t_crashme ( f1 BIGINT);
CREATE VIEW a1 (t_CRASHME) AS SELECT f1 FROM t_crashme GROUP BY f1;
CREATE VIEW a2 AS SELECT t_CRASHME FROM a1;
count(*)
1
09
1
10
drop view a2, a1;
drop table t_crashme;
select table_schema,table_name, column_name from
...
...
@@ -742,6 +743,8 @@ information_schema.columns
where data_type = 'longtext';
table_schema table_name column_name
information_schema COLUMNS COLUMN_TYPE
information_schema EVENTS EVENT_BODY
information_schema EVENTS SQL_MODE
information_schema PARTITIONS PARTITION_EXPRESSION
information_schema PARTITIONS SUBPARTITION_EXPRESSION
information_schema PARTITIONS PARTITION_DESCRIPTION
...
...
@@ -756,6 +759,12 @@ information_schema VIEWS VIEW_DEFINITION
select table_name, column_name, data_type from information_schema.columns
where data_type = 'datetime';
table_name column_name data_type
EVENTS EXECUTE_AT datetime
EVENTS STARTS datetime
EVENTS ENDS datetime
EVENTS CREATED datetime
EVENTS LAST_ALTERED datetime
EVENTS LAST_EXECUTED datetime
PARTITIONS CREATE_TIME datetime
PARTITIONS UPDATE_TIME datetime
PARTITIONS CHECK_TIME datetime
...
...
@@ -817,7 +826,7 @@ flush privileges;
SELECT table_schema, count(*) FROM information_schema.TABLES GROUP BY TABLE_SCHEMA;
table_schema count(*)
cluster_replication 1
information_schema
19
information_schema
20
mysql 21
create table t1 (i int, j int);
create trigger trg1 before insert on t1 for each row
...
...
mysql-test/r/information_schema_db.result
View file @
0a0304b5
...
...
@@ -7,6 +7,7 @@ COLLATION_CHARACTER_SET_APPLICABILITY
COLUMNS
COLUMN_PRIVILEGES
ENGINES
EVENTS
KEY_COLUMN_USAGE
PARTITIONS
PLUGINS
...
...
mysql-test/r/system_mysql_db.result
View file @
0a0304b5
...
...
@@ -204,7 +204,7 @@ event CREATE TABLE `event` (
`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 (`db`,`name`)
PRIMARY KEY (`d
efiner`,`d
b`,`name`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Events'
show create table general_log;
Table Create Table
...
...
mysql-test/t/events.test
View file @
0a0304b5
...
...
@@ -27,12 +27,88 @@ 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
(
"20
01
0101"
,
interval
5
minute
)
ends
date_add
(
"20151010"
,
interval
5
day
)
comment
"portokala_comment"
DO
insert
into
t_event3
values
(
unix_timestamp
(),
rand
());
create
event
event3
on
schedule
every
50
+
10
minute
starts
date_add
(
"20
10
0101"
,
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
;
#
#INFORMATION_SCHEMA.EVENTS test begin
#
create
event
one_event
on
schedule
every
10
second
do
select
123
;
--
replace_column
8
# 9 #
SHOW
EVENTS
;
SELECT
EVENT_CATALOG
,
EVENT_SCHEMA
,
EVENT_NAME
,
DEFINER
,
EVENT_BODY
,
EVENT_TYPE
,
EXECUTE_AT
,
INTERVAL_VALUE
,
INTERVAL_FIELD
,
STATUS
,
ON_COMPLETION
,
EVENT_COMMENT
from
information_schema
.
events
;
CREATE
DATABASE
events_test2
;
CREATE
USER
ev_test
@
localhost
;
GRANT
ALL
ON
events_test
.*
to
ev_test
@
localhost
;
GRANT
ALL
on
events_test2
.*
to
ev_test
@
localhost
;
REVOKE
EVENT
ON
events_test2
.*
FROM
ev_test
@
localhost
;
REVOKE
PROCESS
on
*.*
from
ev_test
@
localhost
;
#now we are on con1
connect
(
ev_con1
,
localhost
,
ev_test
,,
events_test2
);
select
"NEW CONNECTION"
;
SELECT
USER
(),
DATABASE
();
SHOW
GRANTS
;
--
echo
"Here comes an error:"
;
#NO EVENT_ACL on events_test2
--
error
1044
SHOW
EVENTS
;
USE
events_test
;
--
echo
"Now the list should be empty:"
;
--
replace_column
8
# 9 #
SHOW
EVENTS
;
#now create an event with the same name but we are different user
select
concat
(
"Let's create some new events from the name of "
,
user
());
create
event
one_event
on
schedule
every
20
second
do
select
123
;
create
event
two_event
on
schedule
every
20
second
on
completion
not
preserve
comment
"two event"
do
select
123
;
create
event
three_event
on
schedule
every
20
second
on
completion
preserve
comment
"three event"
do
select
123
;
--
echo
"Now we should see 3 events:"
;
--
replace_column
8
# 9 #
SHOW
EVENTS
;
--
echo
"This should show us only 3 events:"
;
--
replace_column
8
# 9 #
SHOW
FULL
EVENTS
;
--
echo
"This should show us only 2 events:"
;
--
replace_column
8
# 9 #
SHOW
FULL
EVENTS
LIKE
't%event'
;
--
echo
"This should show us no events:"
;
--
replace_column
8
# 9 #
SHOW
FULL
EVENTS
FROM
test
LIKE
'%'
;
#ok, we are back
connection
default
;
DROP
DATABASE
events_test2
;
--
echo
"should see 1 event:"
;
--
replace_column
8
# 9 #
SHOW
EVENTS
;
--
echo
"we should see 4 events now:"
;
--
replace_column
8
# 9 #
SHOW
FULL
EVENTS
;
SELECT
EVENT_CATALOG
,
EVENT_SCHEMA
,
EVENT_NAME
,
DEFINER
,
EVENT_BODY
,
EVENT_TYPE
,
EXECUTE_AT
,
INTERVAL_VALUE
,
INTERVAL_FIELD
,
STATUS
,
ON_COMPLETION
,
EVENT_COMMENT
from
information_schema
.
events
;
connection
ev_con1
;
drop
event
one_event
;
drop
event
two_event
;
drop
event
three_event
;
disconnect
ev_con1
;
connection
default
;
drop
user
ev_test
@
localhost
;
drop
event
one_event
;
#
##INFORMATION_SCHEMA.EVENTS test end
#
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
;
...
...
scripts/mysql_create_system_tables.sh
View file @
0a0304b5
...
...
@@ -792,7 +792,7 @@ then
c_ev
=
"
$c_ev
status ENUM('ENABLED','DISABLED') NOT NULL default 'ENABLED',"
c_ev
=
"
$c_ev
on_completion ENUM('DROP','PRESERVE') NOT NULL default 'DROP',"
c_ev
=
"
$c_ev
comment char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '',"
c_ev
=
"
$c_ev
PRIMARY KEY (d
b,
name)"
c_ev
=
"
$c_ev
PRIMARY KEY (d
efiner, db,
name)"
c_ev
=
"
$c_ev
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT 'Events';"
fi
...
...
scripts/mysql_fix_privilege_tables.sql
View file @
0a0304b5
...
...
@@ -600,4 +600,6 @@ CREATE TABLE event (
ALTER TABLE user add Event_priv enum('
N
','
Y
') character set utf8 DEFAULT '
N
' NOT NULL AFTER Create_user_priv;
ALTER TABLE db add Event_priv enum('
N
','
Y
') character set utf8 DEFAULT '
N
' NOT NULL;
ALTER TABLE event DROP PRIMARY KEY;
ALTER TABLE event ADD PRIMARY KEY(definer, db, name);
sql/event.cc
View file @
0a0304b5
...
...
@@ -77,7 +77,7 @@ evex_queue_init(EVEX_QUEUE_TYPE *queue)
}
static
int
sortcmp_lex_string
(
LEX_STRING
s
,
LEX_STRING
t
,
CHARSET_INFO
*
cs
)
{
return
cs
->
coll
->
strnncollsp
(
cs
,
(
unsigned
char
*
)
s
.
str
,
s
.
length
,
...
...
@@ -182,7 +182,9 @@ evex_open_event_table(THD *thd, enum thr_lock_type lock_type, TABLE **table)
int
evex_db_find_event_aux
(
THD
*
thd
,
const
LEX_STRING
dbname
,
const
LEX_STRING
ev_name
,
TABLE
*
table
)
const
LEX_STRING
ev_name
,
const
LEX_STRING
user_name
,
TABLE
*
table
)
{
byte
key
[
MAX_KEY_LENGTH
];
DBUG_ENTER
(
"evex_db_find_event_aux"
);
...
...
@@ -196,11 +198,17 @@ evex_db_find_event_aux(THD *thd, const LEX_STRING dbname,
same fields.
*/
if
(
dbname
.
length
>
table
->
field
[
EVEX_FIELD_DB
]
->
field_length
||
ev_name
.
length
>
table
->
field
[
EVEX_FIELD_NAME
]
->
field_length
)
ev_name
.
length
>
table
->
field
[
EVEX_FIELD_NAME
]
->
field_length
||
user_name
.
length
>
table
->
field
[
EVEX_FIELD_DEFINER
]
->
field_length
)
DBUG_RETURN
(
EVEX_KEY_NOT_FOUND
);
table
->
field
[
0
]
->
store
(
dbname
.
str
,
dbname
.
length
,
&
my_charset_bin
);
table
->
field
[
1
]
->
store
(
ev_name
.
str
,
ev_name
.
length
,
&
my_charset_bin
);
table
->
field
[
EVEX_FIELD_DB
]
->
store
(
dbname
.
str
,
dbname
.
length
,
&
my_charset_bin
);
table
->
field
[
EVEX_FIELD_NAME
]
->
store
(
ev_name
.
str
,
ev_name
.
length
,
&
my_charset_bin
);
table
->
field
[
EVEX_FIELD_DEFINER
]
->
store
(
user_name
.
str
,
user_name
.
length
,
&
my_charset_bin
);
key_copy
(
key
,
table
->
record
[
0
],
table
->
key_info
,
table
->
key_info
->
key_length
);
if
(
table
->
file
->
index_read_idx
(
table
->
record
[
0
],
0
,
key
,
...
...
@@ -290,10 +298,15 @@ evex_fill_row(THD *thd, TABLE *table, event_timed *et, my_bool is_update)
from 1. Thus +1 offset is needed!
*/
table
->
field
[
EVEX_FIELD_TRANSIENT_INTERVAL
]
->
store
((
longlong
)
et
->
interval
+
1
);
table
->
field
[
EVEX_FIELD_EXECUTE_AT
]
->
set_null
();
}
else
if
(
et
->
execute_at
.
year
)
{
// fix_fields already called in init_execute_at
table
->
field
[
EVEX_FIELD_INTERVAL_EXPR
]
->
set_null
();
table
->
field
[
EVEX_FIELD_TRANSIENT_INTERVAL
]
->
set_null
();
table
->
field
[
EVEX_FIELD_EXECUTE_AT
]
->
set_notnull
();
table
->
field
[
EVEX_FIELD_EXECUTE_AT
]
->
store_time
(
&
et
->
execute_at
,
MYSQL_TIMESTAMP_DATETIME
);
...
...
@@ -358,9 +371,9 @@ db_create_event(THD *thd, event_timed *et, my_bool create_if_not,
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
->
dbname
,
et
->
name
,
table
))
if
(
!
evex_db_find_event_aux
(
thd
,
et
->
dbname
,
et
->
name
,
et
->
definer
,
table
))
{
if
(
create_if_not
)
{
...
...
@@ -410,10 +423,9 @@ db_create_event(THD *thd, event_timed *et, my_bool create_if_not,
goto
err
;
}
strxmov
(
definer
,
et
->
definer_user
.
str
,
"@"
,
et
->
definer_host
.
str
,
NullS
);
if
((
ret
=
table
->
field
[
EVEX_FIELD_DEFINER
]
->
store
(
definer
,
et
->
definer_user
.
length
+
1
+
et
->
definer_host
.
length
,
system_charset_info
)))
if
((
ret
=
table
->
field
[
EVEX_FIELD_DEFINER
]
->
store
(
et
->
definer
.
str
,
et
->
definer
.
length
,
system_charset_info
)))
{
my_error
(
ER_EVENT_STORE_FAILED
,
MYF
(
0
),
et
->
name
.
str
,
ret
);
goto
err
;
...
...
@@ -476,7 +488,9 @@ db_update_event(THD *thd, event_timed *et, sp_name *new_name)
TABLE
*
table
;
int
ret
=
EVEX_OPEN_TABLE_FAILED
;
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
));
DBUG_PRINT
(
"enter"
,
(
"user: %.*s"
,
et
->
name
.
length
,
et
->
name
.
str
));
if
(
new_name
)
DBUG_PRINT
(
"enter"
,
(
"rename to: %.*s"
,
new_name
->
m_name
.
length
,
new_name
->
m_name
.
str
));
...
...
@@ -497,7 +511,8 @@ db_update_event(THD *thd, event_timed *et, sp_name *new_name)
goto
err
;
}
if
(
!
evex_db_find_event_aux
(
thd
,
new_name
->
m_db
,
new_name
->
m_name
,
table
))
if
(
!
evex_db_find_event_aux
(
thd
,
new_name
->
m_db
,
new_name
->
m_name
,
et
->
definer
,
table
))
{
my_error
(
ER_EVENT_ALREADY_EXISTS
,
MYF
(
0
),
new_name
->
m_name
.
str
);
goto
err
;
...
...
@@ -510,7 +525,7 @@ db_update_event(THD *thd, event_timed *et, sp_name *new_name)
row (copied into record[1] later
*/
if
(
EVEX_KEY_NOT_FOUND
==
evex_db_find_event_aux
(
thd
,
et
->
dbname
,
et
->
name
,
table
))
et
->
definer
,
table
))
{
my_error
(
ER_EVENT_DOES_NOT_EXIST
,
MYF
(
0
),
et
->
name
.
str
);
goto
err
;
...
...
@@ -559,6 +574,7 @@ db_update_event(THD *thd, event_timed *et, sp_name *new_name)
db_find_event()
thd THD
name the name of the event to find
definer who owns the event
ett event's data if event is found
tbl TABLE object to use when not NULL
...
...
@@ -568,11 +584,11 @@ db_update_event(THD *thd, event_timed *et, sp_name *new_name)
*/
static
int
db_find_event
(
THD
*
thd
,
sp_name
*
name
,
event_timed
**
ett
,
TABLE
*
tbl
)
db_find_event
(
THD
*
thd
,
sp_name
*
name
,
LEX_STRING
definer
,
event_timed
**
ett
,
TABLE
*
tbl
)
{
TABLE
*
table
;
int
ret
;
const
char
*
definer
;
char
*
ptr
;
event_timed
*
et
;
DBUG_ENTER
(
"db_find_event"
);
...
...
@@ -587,7 +603,8 @@ db_find_event(THD *thd, sp_name *name, event_timed **ett, TABLE *tbl)
goto
done
;
}
if
((
ret
=
evex_db_find_event_aux
(
thd
,
name
->
m_db
,
name
->
m_name
,
table
)))
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
);
goto
done
;
...
...
@@ -628,6 +645,7 @@ db_find_event(THD *thd, sp_name *name, event_timed **ett, TABLE *tbl)
evex_load_and_compile_event()
thd THD
spn the name of the event to alter
definer who is the owner
use_lock whether to obtain a lock on LOCK_event_arrays or not
RETURN VALUE
...
...
@@ -637,7 +655,8 @@ db_find_event(THD *thd, sp_name *name, event_timed **ett, TABLE *tbl)
*/
static
int
evex_load_and_compile_event
(
THD
*
thd
,
sp_name
*
spn
,
bool
use_lock
)
evex_load_and_compile_event
(
THD
*
thd
,
sp_name
*
spn
,
LEX_STRING
definer
,
bool
use_lock
)
{
int
ret
=
0
;
MEM_ROOT
*
tmp_mem_root
;
...
...
@@ -652,7 +671,7 @@ evex_load_and_compile_event(THD * thd, sp_name *spn, bool use_lock)
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
,
&
ett
,
NULL
)))
if
((
ret
=
db_find_event
(
thd
,
spn
,
definer
,
&
ett
,
NULL
)))
goto
done
;
thd
->
restore_backup_open_tables_state
(
&
backup
);
...
...
@@ -773,7 +792,7 @@ evex_create_event(THD *thd, event_timed *et, uint create_options,
if
(
evex_is_running
&&
et
->
status
==
MYSQL_EVENT_ENABLED
)
{
sp_name
spn
(
et
->
dbname
,
et
->
name
);
ret
=
evex_load_and_compile_event
(
thd
,
&
spn
,
true
);
ret
=
evex_load_and_compile_event
(
thd
,
&
spn
,
et
->
definer
,
true
);
}
VOID
(
pthread_mutex_unlock
(
&
LOCK_evex_running
));
...
...
@@ -826,11 +845,11 @@ evex_update_event(THD *thd, event_timed *et, sp_name *new_name,
if
(
et
->
status
==
MYSQL_EVENT_ENABLED
)
{
if
(
new_name
)
ret
=
evex_load_and_compile_event
(
thd
,
new_name
,
false
);
ret
=
evex_load_and_compile_event
(
thd
,
new_name
,
et
->
definer
,
false
);
else
{
sp_name
spn
(
et
->
dbname
,
et
->
name
);
ret
=
evex_load_and_compile_event
(
thd
,
&
spn
,
false
);
ret
=
evex_load_and_compile_event
(
thd
,
&
spn
,
et
->
definer
,
false
);
}
if
(
ret
==
EVEX_COMPILE_ERROR
)
my_error
(
ER_EVENT_COMPILE_ERROR
,
MYF
(
0
));
...
...
@@ -868,7 +887,7 @@ evex_drop_event(THD *thd, event_timed *et, bool drop_if_exists,
goto
done
;
}
if
(
!
(
ret
=
evex_db_find_event_aux
(
thd
,
et
->
dbname
,
et
->
name
,
table
)))
if
(
!
(
ret
=
evex_db_find_event_aux
(
thd
,
et
->
dbname
,
et
->
name
,
et
->
definer
,
table
)))
{
if
((
ret
=
table
->
file
->
ha_delete_row
(
table
->
record
[
0
])))
{
...
...
sql/event.h
View file @
0a0304b5
...
...
@@ -54,6 +54,25 @@ enum enum_event_status
MYSQL_EVENT_DISABLED
};
enum
evex_table_field
{
EVEX_FIELD_DB
=
0
,
EVEX_FIELD_NAME
,
EVEX_FIELD_BODY
,
EVEX_FIELD_DEFINER
,
EVEX_FIELD_EXECUTE_AT
,
EVEX_FIELD_INTERVAL_EXPR
,
EVEX_FIELD_TRANSIENT_INTERVAL
,
EVEX_FIELD_CREATED
,
EVEX_FIELD_MODIFIED
,
EVEX_FIELD_LAST_EXECUTED
,
EVEX_FIELD_STARTS
,
EVEX_FIELD_ENDS
,
EVEX_FIELD_STATUS
,
EVEX_FIELD_ON_COMPLETION
,
EVEX_FIELD_COMMENT
,
EVEX_FIELD_COUNT
/* a cool trick to count the number of fields :) */
}
;
class
event_timed
{
...
...
@@ -64,9 +83,10 @@ class event_timed
bool
status_changed
;
bool
last_executed_changed
;
TIME
last_executed
;
public:
TIME
last_executed
;
LEX_STRING
dbname
;
LEX_STRING
name
;
LEX_STRING
body
;
...
...
@@ -83,8 +103,8 @@ class event_timed
longlong
expression
;
interval_type
interval
;
longlong
created
;
longlong
modified
;
u
longlong
created
;
u
longlong
modified
;
enum
enum_event_on_completion
on_completion
;
enum
enum_event_status
status
;
sp_head
*
sphead
;
...
...
@@ -197,6 +217,10 @@ int
evex_drop_event
(
THD
*
thd
,
event_timed
*
et
,
bool
drop_if_exists
,
uint
*
rows_affected
);
int
evex_open_event_table
(
THD
*
thd
,
enum
thr_lock_type
lock_type
,
TABLE
**
table
);
int
sortcmp_lex_string
(
LEX_STRING
s
,
LEX_STRING
t
,
CHARSET_INFO
*
cs
);
int
init_events
();
...
...
@@ -210,6 +234,7 @@ int
event_timed_compare
(
event_timed
**
a
,
event_timed
**
b
);
/*
CREATE TABLE event (
db char(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '',
...
...
@@ -233,7 +258,7 @@ CREATE TABLE event (
status ENUM('ENABLED','DISABLED') NOT NULL default 'ENABLED',
on_completion ENUM('DROP','PRESERVE') NOT NULL default 'DROP',
comment varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '',
PRIMARY KEY (db,name)
PRIMARY KEY (d
efiner,d
b,name)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT 'Events';
*/
...
...
sql/event_executor.cc
View file @
0a0304b5
...
...
@@ -348,7 +348,8 @@ event_executor_main(void *arg)
TIME_to_ulonglong_datetime
(
&
et
->
execute_at
)));
et
->
update_fields
(
thd
);
DBUG_PRINT
(
"info"
,
(
" Spawning a thread %d"
,
++
iter_num
));
++
iter_num
;
DBUG_PRINT
(
"info"
,
(
" Spawning a thread %d"
,
iter_num
));
#ifndef DBUG_FAULTY_THR
if
(
pthread_create
(
&
th
,
NULL
,
event_executor_worker
,
(
void
*
)
et
))
{
...
...
@@ -461,7 +462,7 @@ event_executor_worker(void *event_void)
thd
->
mem_root
=
&
worker_mem_root
;
pthread_detach
(
pthread_self
());
if
(
init_event_thread
(
thd
))
goto
err
;
...
...
sql/event_priv.h
View file @
0a0304b5
...
...
@@ -24,26 +24,6 @@
#define UNLOCK_MUTEX_AND_BAIL_OUT(__mutex, __label) \
{ VOID(pthread_mutex_unlock(&__mutex)); goto __label; }
enum
evex_table_field
{
EVEX_FIELD_DB
=
0
,
EVEX_FIELD_NAME
,
EVEX_FIELD_BODY
,
EVEX_FIELD_DEFINER
,
EVEX_FIELD_EXECUTE_AT
,
EVEX_FIELD_INTERVAL_EXPR
,
EVEX_FIELD_TRANSIENT_INTERVAL
,
EVEX_FIELD_CREATED
,
EVEX_FIELD_MODIFIED
,
EVEX_FIELD_LAST_EXECUTED
,
EVEX_FIELD_STARTS
,
EVEX_FIELD_ENDS
,
EVEX_FIELD_STATUS
,
EVEX_FIELD_ON_COMPLETION
,
EVEX_FIELD_COMMENT
,
EVEX_FIELD_COUNT
/* a cool trick to count the number of fields :) */
}
;
#define EVEX_DB_FIELD_LEN 64
#define EVEX_NAME_FIELD_LEN 64
#define EVEX_MAX_INTERVAL_VALUE 2147483647L
...
...
@@ -53,11 +33,10 @@ my_time_compare(TIME *a, TIME *b);
int
evex_db_find_event_aux
(
THD
*
thd
,
const
LEX_STRING
dbname
,
const
LEX_STRING
rname
,
TABLE
*
table
);
const
LEX_STRING
rname
,
const
LEX_STRING
definer
,
TABLE
*
table
);
int
evex_open_event_table
(
THD
*
thd
,
enum
thr_lock_type
lock_type
,
TABLE
**
table
);
int
event_timed_compare_q
(
void
*
vptr
,
byte
*
a
,
byte
*
b
);
...
...
sql/event_timed.cc
View file @
0a0304b5
...
...
@@ -307,6 +307,8 @@ event_timed::init_starts(THD *thd, Item *new_starts)
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
);
...
...
@@ -413,6 +415,16 @@ event_timed::init_definer(THD *thd)
definer_host
.
str
=
strdup_root
(
thd
->
mem_root
,
thd
->
security_ctx
->
priv_host
);
definer_host
.
length
=
strlen
(
thd
->
security_ctx
->
priv_host
);
definer
.
length
=
definer_user
.
length
+
definer_host
.
length
+
1
;
definer
.
str
=
alloc_root
(
thd
->
mem_root
,
definer
.
length
+
1
);
memcpy
(
definer
.
str
,
definer_user
.
str
,
definer_user
.
length
);
definer
.
str
[
definer_user
.
length
]
=
'@'
;
memcpy
(
definer
.
str
+
definer_user
.
length
+
1
,
definer_host
.
str
,
definer_host
.
length
);
definer
.
str
[
definer
.
length
]
=
'\0'
;
DBUG_RETURN
(
0
);
}
...
...
@@ -486,7 +498,6 @@ event_timed::load_from_row(MEM_ROOT *mem_root, TABLE *table)
et
->
definer_host
.
str
=
strmake_root
(
mem_root
,
ptr
+
1
,
len
);
//1: because of @
et
->
definer_host
.
length
=
len
;
res1
=
table
->
field
[
EVEX_FIELD_STARTS
]
->
get_date
(
&
et
->
starts
,
TIME_NO_ZERO_DATE
);
...
...
@@ -542,8 +553,7 @@ event_timed::load_from_row(MEM_ROOT *mem_root, TABLE *table)
goto
error
;
DBUG_PRINT
(
"load_from_row"
,
(
"Event [%s] is [%s]"
,
et
->
name
.
str
,
ptr
));
et
->
status
=
(
ptr
[
0
]
==
'E'
?
MYSQL_EVENT_ENABLED
:
MYSQL_EVENT_DISABLED
);
et
->
status
=
(
ptr
[
0
]
==
'E'
?
MYSQL_EVENT_ENABLED
:
MYSQL_EVENT_DISABLED
);
// ToDo : Andrey . Find a way not to allocate ptr on event_mem_root
if
((
ptr
=
get_field
(
mem_root
,
...
...
@@ -681,7 +691,8 @@ event_timed::compute_next_execution_time()
}
time
((
time_t
*
)
&
now
);
my_tz_UTC
->
gmt_sec_to_TIME
(
&
time_now
,
now
);
/*
#ifdef ANDREY_0
sql_print_information
(
"[%s.%s]"
,
dbname
.
str
,
name
.
str
);
sql_print_information
(
"time_now : [%d-%d-%d %d:%d:%d ]"
,
time_now
.
year
,
time_now
.
month
,
time_now
.
day
,
...
...
@@ -696,7 +707,8 @@ event_timed::compute_next_execution_time()
last_executed
.
month
,
last_executed
.
day
,
last_executed
.
hour
,
last_executed
.
minute
,
last_executed
.
second
);
*/
#endif
//if time_now is after ends don't execute anymore
if
(
ends
.
year
&&
(
tmp
=
my_time_compare
(
&
ends
,
&
time_now
))
==
-
1
)
{
...
...
@@ -871,7 +883,7 @@ event_timed::drop(THD *thd)
if
(
evex_open_event_table
(
thd
,
TL_WRITE
,
&
table
))
DBUG_RETURN
(
-
1
);
if
(
evex_db_find_event_aux
(
thd
,
dbname
,
name
,
table
))
if
(
evex_db_find_event_aux
(
thd
,
dbname
,
name
,
definer
,
table
))
DBUG_RETURN
(
-
2
);
if
((
ret
=
table
->
file
->
ha_delete_row
(
table
->
record
[
0
])))
...
...
@@ -907,11 +919,12 @@ event_timed::update_fields(THD *thd)
}
if
((
ret
=
evex_db_find_event_aux
(
thd
,
dbname
,
name
,
table
)))
if
((
ret
=
evex_db_find_event_aux
(
thd
,
dbname
,
name
,
definer
,
table
)))
goto
done
;
store_record
(
table
,
record
[
1
]);
table
->
timestamp_field_type
=
TIMESTAMP_NO_AUTO_SET
;
// Don't update create on row update.
// Don't update create on row update.
table
->
timestamp_field_type
=
TIMESTAMP_NO_AUTO_SET
;
if
(
last_executed_changed
)
{
...
...
sql/mysqld.cc
View file @
0a0304b5
...
...
@@ -6718,6 +6718,7 @@ SHOW_VAR status_vars[]= {
{
"Com_show_engine_logs"
,
(
char
*
)
offsetof
(
STATUS_VAR
,
com_stat
[(
uint
)
SQLCOM_SHOW_ENGINE_LOGS
]),
SHOW_LONG_STATUS
},
{
"Com_show_engine_mutex"
,
(
char
*
)
offsetof
(
STATUS_VAR
,
com_stat
[(
uint
)
SQLCOM_SHOW_ENGINE_MUTEX
]),
SHOW_LONG_STATUS
},
{
"Com_show_engine_status"
,
(
char
*
)
offsetof
(
STATUS_VAR
,
com_stat
[(
uint
)
SQLCOM_SHOW_ENGINE_STATUS
]),
SHOW_LONG_STATUS
},
{
"Com_show_events"
,
(
char
*
)
offsetof
(
STATUS_VAR
,
com_stat
[(
uint
)
SQLCOM_SHOW_EVENTS
]),
SHOW_LONG_STATUS
},
{
"Com_show_errors"
,
(
char
*
)
offsetof
(
STATUS_VAR
,
com_stat
[(
uint
)
SQLCOM_SHOW_ERRORS
]),
SHOW_LONG_STATUS
},
{
"Com_show_fields"
,
(
char
*
)
offsetof
(
STATUS_VAR
,
com_stat
[(
uint
)
SQLCOM_SHOW_FIELDS
]),
SHOW_LONG_STATUS
},
{
"Com_show_grants"
,
(
char
*
)
offsetof
(
STATUS_VAR
,
com_stat
[(
uint
)
SQLCOM_SHOW_GRANTS
]),
SHOW_LONG_STATUS
},
...
...
sql/sql_lex.h
View file @
0a0304b5
...
...
@@ -101,7 +101,7 @@ enum enum_sql_command {
SQLCOM_SHOW_AUTHORS
,
SQLCOM_BINLOG_BASE64_EVENT
,
SQLCOM_SHOW_PLUGINS
,
SQLCOM_CREATE_EVENT
,
SQLCOM_ALTER_EVENT
,
SQLCOM_DROP_EVENT
,
SQLCOM_SHOW_CREATE_EVENT
,
SQLCOM_SHOW_CREATE_EVENT
,
SQLCOM_SHOW_EVENTS
,
/* This should be the last !!! */
...
...
sql/sql_parse.cc
View file @
0a0304b5
...
...
@@ -2161,6 +2161,7 @@ int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident,
case
SCH_TABLES
:
case
SCH_VIEWS
:
case
SCH_TRIGGERS
:
case
SCH_EVENTS
:
#ifdef DONT_ALLOW_SHOW_COMMANDS
my_message
(
ER_NOT_ALLOWED_COMMAND
,
ER
(
ER_NOT_ALLOWED_COMMAND
),
MYF
(
0
));
/* purecov: inspected */
...
...
@@ -2449,11 +2450,15 @@ mysql_execute_command(THD *thd)
if
(
all_tables
)
{
if
(
lex
->
orig_sql_command
!=
SQLCOM_SHOW_STATUS_PROC
&&
lex
->
orig_sql_command
!=
SQLCOM_SHOW_STATUS_FUNC
)
lex
->
orig_sql_command
!=
SQLCOM_SHOW_STATUS_FUNC
&&
lex
->
orig_sql_command
!=
SQLCOM_SHOW_EVENTS
)
res
=
check_table_access
(
thd
,
lex
->
exchange
?
SELECT_ACL
|
FILE_ACL
:
SELECT_ACL
,
all_tables
,
0
);
else
if
(
lex
->
orig_sql_command
==
SQLCOM_SHOW_EVENTS
)
res
=
check_access
(
thd
,
EVENT_ACL
,
thd
->
lex
->
select_lex
.
db
,
0
,
0
,
0
,
is_schema_db
(
thd
->
lex
->
select_lex
.
db
));
}
else
res
=
check_access
(
thd
,
...
...
sql/sql_show.cc
View file @
0a0304b5
This diff is collapsed.
Click to expand it.
sql/sql_yacc.yy
View file @
0a0304b5
...
...
@@ -1355,8 +1355,11 @@ create:
$<ulong_num>$= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES;
YYTHD->client_capabilities &= (~CLIENT_MULTI_QUERIES);
if (!lex->et_compile_phase)
if (!lex->et_compile_phase)
{
lex->et->init_name(YYTHD, $4);
lex->et->init_definer(YYTHD);
}
}
ON SCHEDULE_SYM ev_schedule_time
opt_ev_on_completion
...
...
@@ -1599,7 +1602,6 @@ ev_sql_stmt:
if (!lex->et_compile_phase)
{
lex->et->init_body(YYTHD);
lex->et->init_definer(YYTHD);
}
}
;
...
...
@@ -4816,8 +4818,13 @@ alter:
if (!(et= new event_timed()))// implicitly calls event_timed::init()
YYABORT;
lex->et = et;
et->init_name(YYTHD, $3);
if (!lex->et_compile_phase)
{
et->init_definer(YYTHD);
et->init_name(YYTHD, $3);
}
/*
We have to turn of CLIENT_MULTI_QUERIES while parsing a
stored procedure, otherwise yylex will chop it into pieces
...
...
@@ -4825,7 +4832,6 @@ alter:
*/
$<ulong_num>$= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES;
YYTHD->client_capabilities &= ~CLIENT_MULTI_QUERIES;
}
ev_alter_on_schedule_completion
opt_ev_rename_to
...
...
@@ -7664,7 +7670,6 @@ drop:
if (lex->et)
{
// ToDo Andrey : Change the error message
/*
Recursive events are not possible because recursive SPs
are not also possible. lex->sp_head is not stacked.
...
...
@@ -7675,8 +7680,13 @@ drop:
if (!(lex->et= new event_timed()))
YYABORT;
lex->et->init_name(YYTHD, $4);
if (!lex->et_compile_phase)
{
lex->et->init_name(YYTHD, $4);
lex->et->init_definer(YYTHD);
}
lex->sql_command = SQLCOM_DROP_EVENT;
lex->drop_if_exists= $3;
}
...
...
@@ -8068,6 +8078,15 @@ show_param:
if (prepare_schema_table(YYTHD, lex, 0, SCH_TRIGGERS))
YYABORT;
}
| opt_full EVENTS_SYM opt_db wild_and_where
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_SELECT;
lex->orig_sql_command= SQLCOM_SHOW_EVENTS;
lex->select_lex.db= $3;
if (prepare_schema_table(YYTHD, lex, 0, SCH_EVENTS))
YYABORT;
}
| TABLE_SYM STATUS_SYM opt_db wild_and_where
{
LEX *lex= Lex;
...
...
sql/table.h
View file @
0a0304b5
...
...
@@ -338,6 +338,7 @@ enum enum_schema_tables
SCH_COLUMNS
,
SCH_COLUMN_PRIVILEGES
,
SCH_ENGINES
,
SCH_EVENTS
,
SCH_KEY_COLUMN_USAGE
,
SCH_OPEN_TABLES
,
SCH_PARTITIONS
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment