Merge maint1.mysql.com:/data/localhome/tsmith/bk/51
into maint1.mysql.com:/data/localhome/tsmith/bk/maint/51
This commit is contained in:
commit
3ae37d30de
@ -904,6 +904,14 @@ extern CHARSET_INFO *get_charset(uint cs_number, myf flags);
|
|||||||
extern CHARSET_INFO *get_charset_by_name(const char *cs_name, myf flags);
|
extern CHARSET_INFO *get_charset_by_name(const char *cs_name, myf flags);
|
||||||
extern CHARSET_INFO *get_charset_by_csname(const char *cs_name,
|
extern CHARSET_INFO *get_charset_by_csname(const char *cs_name,
|
||||||
uint cs_flags, myf my_flags);
|
uint cs_flags, myf my_flags);
|
||||||
|
|
||||||
|
extern bool resolve_charset(CHARSET_INFO **cs,
|
||||||
|
const char *cs_name,
|
||||||
|
CHARSET_INFO *default_cs);
|
||||||
|
extern bool resolve_collation(CHARSET_INFO **cl,
|
||||||
|
const char *cl_name,
|
||||||
|
CHARSET_INFO *default_cl);
|
||||||
|
|
||||||
extern void free_charsets(void);
|
extern void free_charsets(void);
|
||||||
extern char *get_charsets_dir(char *buf);
|
extern char *get_charsets_dir(char *buf);
|
||||||
extern my_bool my_charset_same(CHARSET_INFO *cs1, CHARSET_INFO *cs2);
|
extern my_bool my_charset_same(CHARSET_INFO *cs1, CHARSET_INFO *cs2);
|
||||||
|
@ -8,7 +8,7 @@ multi line comment */;
|
|||||||
;
|
;
|
||||||
ERROR 42000: Query was empty
|
ERROR 42000: Query was empty
|
||||||
select 1 /*!32301 +1 */;
|
select 1 /*!32301 +1 */;
|
||||||
1 /*!32301 +1
|
1 +1
|
||||||
2
|
2
|
||||||
select 1 /*!52301 +1 */;
|
select 1 /*!52301 +1 */;
|
||||||
1
|
1
|
||||||
@ -26,3 +26,13 @@ select 1 # The rest of the row will be ignored
|
|||||||
1
|
1
|
||||||
1
|
1
|
||||||
/* line with only comment */;
|
/* line with only comment */;
|
||||||
|
select 1/*!2*/;
|
||||||
|
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '2*/' at line 1
|
||||||
|
select 1/*!000002*/;
|
||||||
|
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '2*/' at line 1
|
||||||
|
select 1/*!999992*/;
|
||||||
|
1
|
||||||
|
1
|
||||||
|
select 1 + /*!00000 2 */ + 3 /*!99999 noise*/ + 4;
|
||||||
|
1 + 2 + 3 + 4
|
||||||
|
10
|
||||||
|
@ -287,3 +287,71 @@ slow_log
|
|||||||
slow_log_new
|
slow_log_new
|
||||||
drop table slow_log_new, general_log_new;
|
drop table slow_log_new, general_log_new;
|
||||||
use test;
|
use test;
|
||||||
|
SET GLOBAL LOG_OUTPUT = 'TABLE';
|
||||||
|
SET GLOBAL general_log = 0;
|
||||||
|
FLUSH LOGS;
|
||||||
|
TRUNCATE TABLE mysql.general_log;
|
||||||
|
ALTER TABLE mysql.general_log ENGINE = MyISAM;
|
||||||
|
ALTER TABLE mysql.general_log
|
||||||
|
ADD COLUMN seq BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY;
|
||||||
|
SET GLOBAL general_log = 1;
|
||||||
|
FLUSH LOGS;
|
||||||
|
SELECT * FROM mysql.general_log;
|
||||||
|
event_time user_host thread_id server_id command_type argument seq
|
||||||
|
EVENT_TIME USER_HOST THREAD_ID SERVER_ID Query FLUSH LOGS 1
|
||||||
|
EVENT_TIME USER_HOST THREAD_ID SERVER_ID Query SELECT * FROM mysql.general_log 2
|
||||||
|
SELECT * FROM mysql.general_log;
|
||||||
|
event_time user_host thread_id server_id command_type argument seq
|
||||||
|
EVENT_TIME USER_HOST THREAD_ID SERVER_ID Query FLUSH LOGS 1
|
||||||
|
EVENT_TIME USER_HOST THREAD_ID SERVER_ID Query SELECT * FROM mysql.general_log 2
|
||||||
|
EVENT_TIME USER_HOST THREAD_ID SERVER_ID Query SELECT * FROM mysql.general_log 3
|
||||||
|
SELECT "My own query 1";
|
||||||
|
My own query 1
|
||||||
|
My own query 1
|
||||||
|
SELECT "My own query 2";
|
||||||
|
My own query 2
|
||||||
|
My own query 2
|
||||||
|
SELECT * FROM mysql.general_log;
|
||||||
|
event_time user_host thread_id server_id command_type argument seq
|
||||||
|
EVENT_TIME USER_HOST THREAD_ID SERVER_ID Query FLUSH LOGS 1
|
||||||
|
EVENT_TIME USER_HOST THREAD_ID SERVER_ID Query SELECT * FROM mysql.general_log 2
|
||||||
|
EVENT_TIME USER_HOST THREAD_ID SERVER_ID Query SELECT * FROM mysql.general_log 3
|
||||||
|
EVENT_TIME USER_HOST THREAD_ID SERVER_ID Query SELECT "My own query 1" 4
|
||||||
|
EVENT_TIME USER_HOST THREAD_ID SERVER_ID Query SELECT "My own query 2" 5
|
||||||
|
EVENT_TIME USER_HOST THREAD_ID SERVER_ID Query SELECT * FROM mysql.general_log 6
|
||||||
|
SET GLOBAL general_log = 0;
|
||||||
|
FLUSH LOGS;
|
||||||
|
ALTER TABLE mysql.general_log DROP COLUMN seq;
|
||||||
|
ALTER TABLE mysql.general_log ENGINE = CSV;
|
||||||
|
SET @old_long_query_time:=@@long_query_time;
|
||||||
|
SET GLOBAL slow_query_log = 0;
|
||||||
|
FLUSH LOGS;
|
||||||
|
TRUNCATE TABLE mysql.slow_log;
|
||||||
|
ALTER TABLE mysql.slow_log ENGINE = MyISAM;
|
||||||
|
ALTER TABLE mysql.slow_log
|
||||||
|
ADD COLUMN seq BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY;
|
||||||
|
SET SESSION long_query_time = 1;
|
||||||
|
SET GLOBAL slow_query_log = 1;
|
||||||
|
FLUSH LOGS;
|
||||||
|
SELECT "My own slow query", sleep(2);
|
||||||
|
My own slow query sleep(2)
|
||||||
|
My own slow query 0
|
||||||
|
SELECT "My own slow query", sleep(2);
|
||||||
|
My own slow query sleep(2)
|
||||||
|
My own slow query 0
|
||||||
|
SELECT "My own slow query", sleep(2);
|
||||||
|
My own slow query sleep(2)
|
||||||
|
My own slow query 0
|
||||||
|
SELECT "My own slow query", sleep(2);
|
||||||
|
My own slow query sleep(2)
|
||||||
|
My own slow query 0
|
||||||
|
SELECT * FROM mysql.slow_log WHERE seq >= 2 LIMIT 3;
|
||||||
|
start_time user_host query_time lock_time rows_sent rows_examined db last_insert_id insert_id server_id sql_text seq
|
||||||
|
START_TIME USER_HOST QUERY_TIME 00:00:00 1 0 test NULL NULL 1 SELECT "My own slow query", sleep(2) 2
|
||||||
|
START_TIME USER_HOST QUERY_TIME 00:00:00 1 0 test NULL NULL 1 SELECT "My own slow query", sleep(2) 3
|
||||||
|
START_TIME USER_HOST QUERY_TIME 00:00:00 1 0 test NULL NULL 1 SELECT "My own slow query", sleep(2) 4
|
||||||
|
SET GLOBAL slow_query_log = 0;
|
||||||
|
SET SESSION long_query_time =@old_long_query_time;
|
||||||
|
FLUSH LOGS;
|
||||||
|
ALTER TABLE mysql.slow_log DROP COLUMN seq;
|
||||||
|
ALTER TABLE mysql.slow_log ENGINE = CSV;
|
||||||
|
@ -1495,3 +1495,51 @@ insert into t1 values ('c');
|
|||||||
a
|
a
|
||||||
drop table t1;
|
drop table t1;
|
||||||
set GLOBAL query_cache_size= default;
|
set GLOBAL query_cache_size= default;
|
||||||
|
drop database if exists db1;
|
||||||
|
drop database if exists db2;
|
||||||
|
set GLOBAL query_cache_size=15*1024*1024;
|
||||||
|
create database db1;
|
||||||
|
use db1;
|
||||||
|
create table t1(c1 int)engine=myisam;
|
||||||
|
insert into t1(c1) values (1);
|
||||||
|
select * from db1.t1 f;
|
||||||
|
c1
|
||||||
|
1
|
||||||
|
show status like 'Qcache_queries_in_cache';
|
||||||
|
Variable_name Value
|
||||||
|
Qcache_queries_in_cache 1
|
||||||
|
rename schema db1 to db2;
|
||||||
|
show status like 'Qcache_queries_in_cache';
|
||||||
|
Variable_name Value
|
||||||
|
Qcache_queries_in_cache 0
|
||||||
|
drop database db2;
|
||||||
|
set global query_cache_size=default;
|
||||||
|
drop database if exists db1;
|
||||||
|
drop database if exists db3;
|
||||||
|
set GLOBAL query_cache_size=15*1024*1024;
|
||||||
|
create database db1;
|
||||||
|
create database db3;
|
||||||
|
use db1;
|
||||||
|
create table t1(c1 int) engine=myisam;
|
||||||
|
use db3;
|
||||||
|
create table t1(c1 int) engine=myisam;
|
||||||
|
use db1;
|
||||||
|
insert into t1(c1) values (1);
|
||||||
|
use mysql;
|
||||||
|
select * from db1.t1;
|
||||||
|
c1
|
||||||
|
1
|
||||||
|
select c1+1 from db1.t1;
|
||||||
|
c1+1
|
||||||
|
2
|
||||||
|
select * from db3.t1;
|
||||||
|
c1
|
||||||
|
show status like 'Qcache_queries_in_cache';
|
||||||
|
Variable_name Value
|
||||||
|
Qcache_queries_in_cache 3
|
||||||
|
rename schema db1 to db2;
|
||||||
|
show status like 'Qcache_queries_in_cache';
|
||||||
|
Variable_name Value
|
||||||
|
Qcache_queries_in_cache 1
|
||||||
|
drop database db2;
|
||||||
|
drop database db3;
|
||||||
|
@ -6281,4 +6281,130 @@ v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VI
|
|||||||
DROP VIEW v1;
|
DROP VIEW v1;
|
||||||
DROP FUNCTION metered;
|
DROP FUNCTION metered;
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
End of 5.0 tests
|
drop procedure if exists proc_25411_a;
|
||||||
|
drop procedure if exists proc_25411_b;
|
||||||
|
drop procedure if exists proc_25411_c;
|
||||||
|
create procedure proc_25411_a()
|
||||||
|
begin
|
||||||
|
/* real comment */
|
||||||
|
select 1;
|
||||||
|
/*! select 2; */
|
||||||
|
select 3;
|
||||||
|
/*!00000 select 4; */
|
||||||
|
/*!99999 select 5; */
|
||||||
|
end
|
||||||
|
$$
|
||||||
|
create procedure proc_25411_b(
|
||||||
|
/* real comment */
|
||||||
|
/*! p1 int, */
|
||||||
|
/*!00000 p2 int */
|
||||||
|
/*!99999 ,p3 int */
|
||||||
|
)
|
||||||
|
begin
|
||||||
|
select p1, p2;
|
||||||
|
end
|
||||||
|
$$
|
||||||
|
create procedure proc_25411_c()
|
||||||
|
begin
|
||||||
|
select 1/*!,2*//*!00000,3*//*!99999,4*/;
|
||||||
|
select 1/*! ,2*//*!00000 ,3*//*!99999 ,4*/;
|
||||||
|
select 1/*!,2 *//*!00000,3 *//*!99999,4 */;
|
||||||
|
select 1/*! ,2 *//*!00000 ,3 *//*!99999 ,4 */;
|
||||||
|
select 1 /*!,2*/ /*!00000,3*/ /*!99999,4*/ ;
|
||||||
|
end
|
||||||
|
$$
|
||||||
|
show create procedure proc_25411_a;
|
||||||
|
Procedure sql_mode Create Procedure
|
||||||
|
proc_25411_a CREATE DEFINER=`root`@`localhost` PROCEDURE `proc_25411_a`()
|
||||||
|
begin
|
||||||
|
/* real comment */
|
||||||
|
select 1;
|
||||||
|
select 2;
|
||||||
|
select 3;
|
||||||
|
select 4;
|
||||||
|
|
||||||
|
end
|
||||||
|
call proc_25411_a();
|
||||||
|
1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
2
|
||||||
|
3
|
||||||
|
3
|
||||||
|
4
|
||||||
|
4
|
||||||
|
show create procedure proc_25411_b;
|
||||||
|
Procedure sql_mode Create Procedure
|
||||||
|
proc_25411_b CREATE DEFINER=`root`@`localhost` PROCEDURE `proc_25411_b`(
|
||||||
|
/* real comment */
|
||||||
|
p1 int,
|
||||||
|
p2 int
|
||||||
|
|
||||||
|
)
|
||||||
|
begin
|
||||||
|
select p1, p2;
|
||||||
|
end
|
||||||
|
select name, param_list, body from mysql.proc where name like "%25411%";
|
||||||
|
name param_list body
|
||||||
|
proc_25411_a begin
|
||||||
|
/* real comment */
|
||||||
|
select 1;
|
||||||
|
select 2;
|
||||||
|
select 3;
|
||||||
|
select 4;
|
||||||
|
|
||||||
|
end
|
||||||
|
proc_25411_b
|
||||||
|
/* real comment */
|
||||||
|
p1 int,
|
||||||
|
p2 int
|
||||||
|
|
||||||
|
begin
|
||||||
|
select p1, p2;
|
||||||
|
end
|
||||||
|
proc_25411_c begin
|
||||||
|
select 1,2,3;
|
||||||
|
select 1 ,2 ,3;
|
||||||
|
select 1,2 ,3 ;
|
||||||
|
select 1 ,2 ,3 ;
|
||||||
|
select 1 ,2 ,3 ;
|
||||||
|
end
|
||||||
|
call proc_25411_b(10, 20);
|
||||||
|
p1 p2
|
||||||
|
10 20
|
||||||
|
show create procedure proc_25411_c;
|
||||||
|
Procedure sql_mode Create Procedure
|
||||||
|
proc_25411_c CREATE DEFINER=`root`@`localhost` PROCEDURE `proc_25411_c`()
|
||||||
|
begin
|
||||||
|
select 1,2,3;
|
||||||
|
select 1 ,2 ,3;
|
||||||
|
select 1,2 ,3 ;
|
||||||
|
select 1 ,2 ,3 ;
|
||||||
|
select 1 ,2 ,3 ;
|
||||||
|
end
|
||||||
|
call proc_25411_c();
|
||||||
|
1 2 3
|
||||||
|
1 2 3
|
||||||
|
1 2 3
|
||||||
|
1 2 3
|
||||||
|
1 2 3
|
||||||
|
1 2 3
|
||||||
|
1 2 3
|
||||||
|
1 2 3
|
||||||
|
1 2 3
|
||||||
|
1 2 3
|
||||||
|
drop procedure proc_25411_a;
|
||||||
|
drop procedure proc_25411_b;
|
||||||
|
drop procedure proc_25411_c;
|
||||||
|
drop procedure if exists proc_26302;
|
||||||
|
create procedure proc_26302()
|
||||||
|
select 1 /* testing */;
|
||||||
|
show create procedure proc_26302;
|
||||||
|
Procedure sql_mode Create Procedure
|
||||||
|
proc_26302 CREATE DEFINER=`root`@`localhost` PROCEDURE `proc_26302`()
|
||||||
|
select 1 /* testing */
|
||||||
|
select ROUTINE_NAME, ROUTINE_DEFINITION from information_schema.ROUTINES
|
||||||
|
where ROUTINE_NAME = "proc_26302";
|
||||||
|
ROUTINE_NAME ROUTINE_DEFINITION
|
||||||
|
proc_26302 select 1 /* testing */
|
||||||
|
drop procedure proc_26302;
|
||||||
|
@ -1477,3 +1477,19 @@ DROP TABLE t1,t2;
|
|||||||
SET SESSION LOW_PRIORITY_UPDATES=DEFAULT;
|
SET SESSION LOW_PRIORITY_UPDATES=DEFAULT;
|
||||||
SET GLOBAL LOW_PRIORITY_UPDATES=DEFAULT;
|
SET GLOBAL LOW_PRIORITY_UPDATES=DEFAULT;
|
||||||
End of 5.0 tests
|
End of 5.0 tests
|
||||||
|
drop table if exists table_25411_a;
|
||||||
|
drop table if exists table_25411_b;
|
||||||
|
create table table_25411_a(a int);
|
||||||
|
create table table_25411_b(b int);
|
||||||
|
create trigger trg_25411a_ai after insert on table_25411_a
|
||||||
|
for each row
|
||||||
|
insert into table_25411_b select new.*;
|
||||||
|
select * from table_25411_a;
|
||||||
|
a
|
||||||
|
insert into table_25411_a values (1);
|
||||||
|
ERROR 42S02: Unknown table 'new'
|
||||||
|
select * from table_25411_a;
|
||||||
|
a
|
||||||
|
1
|
||||||
|
drop table table_25411_a;
|
||||||
|
drop table table_25411_b;
|
||||||
|
@ -79,3 +79,19 @@ select length(a) from t1;
|
|||||||
length(a)
|
length(a)
|
||||||
6
|
6
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
drop table if exists table_28127_a;
|
||||||
|
drop table if exists table_28127_b;
|
||||||
|
create table table_28127_a(0b02 int);
|
||||||
|
show create table table_28127_a;
|
||||||
|
Table Create Table
|
||||||
|
table_28127_a CREATE TABLE `table_28127_a` (
|
||||||
|
`0b02` int(11) DEFAULT NULL
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||||
|
create table table_28127_b(0b2 int);
|
||||||
|
show create table table_28127_b;
|
||||||
|
Table Create Table
|
||||||
|
table_28127_b CREATE TABLE `table_28127_b` (
|
||||||
|
`0b2` int(11) DEFAULT NULL
|
||||||
|
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||||
|
drop table table_28127_a;
|
||||||
|
drop table table_28127_b;
|
||||||
|
@ -19,3 +19,18 @@ select 1 # The rest of the row will be ignored
|
|||||||
/* line with only comment */;
|
/* line with only comment */;
|
||||||
|
|
||||||
# End of 4.1 tests
|
# End of 4.1 tests
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug#25411 (trigger code truncated)
|
||||||
|
#
|
||||||
|
|
||||||
|
--error ER_PARSE_ERROR
|
||||||
|
select 1/*!2*/;
|
||||||
|
|
||||||
|
--error ER_PARSE_ERROR
|
||||||
|
select 1/*!000002*/;
|
||||||
|
|
||||||
|
select 1/*!999992*/;
|
||||||
|
|
||||||
|
select 1 + /*!00000 2 */ + 3 /*!99999 noise*/ + 4;
|
||||||
|
|
||||||
|
@ -48,3 +48,6 @@ ndb_partition_error2 : HF is not sure if the test can work as internded on all
|
|||||||
im_options_set : Bug#20294: Instance manager tests fail randomly
|
im_options_set : Bug#20294: Instance manager tests fail randomly
|
||||||
im_options_unset : Bug#20294: Instance manager tests fail randomly
|
im_options_unset : Bug#20294: Instance manager tests fail randomly
|
||||||
mysql_upgrade : Bug#28560 test links to /usr/local/mysql/lib libraries, causes non-determinism and failures on ABI breakage
|
mysql_upgrade : Bug#28560 test links to /usr/local/mysql/lib libraries, causes non-determinism and failures on ABI breakage
|
||||||
|
rpl_udf : Bug#28993 rpl_udf test causes server crash and valgrind warning in pushbuild
|
||||||
|
rpl_ndb_circular : Bug#29233 rpl_ndb_circular fails randomly
|
||||||
|
ndb_dd_sql_features : Bug#29102 ndb_dd_sql_features fails in pushbuild
|
||||||
|
@ -18,3 +18,4 @@ drop database events_test;
|
|||||||
let $wait_condition=
|
let $wait_condition=
|
||||||
select count(*) = 0 from information_schema.processlist
|
select count(*) = 0 from information_schema.processlist
|
||||||
where db='events_test' and command = 'Connect' and user=current_user();
|
where db='events_test' and command = 'Connect' and user=current_user();
|
||||||
|
--source include/wait_condition.inc
|
||||||
|
@ -145,11 +145,11 @@ select @@optimizer_prune_level;
|
|||||||
#
|
#
|
||||||
# These are the values for the parameters that control the greedy optimizer
|
# These are the values for the parameters that control the greedy optimizer
|
||||||
# (total 6 combinations - 3 for optimizer_search_depth, 2 for optimizer_prune_level):
|
# (total 6 combinations - 3 for optimizer_search_depth, 2 for optimizer_prune_level):
|
||||||
#
|
# 3:
|
||||||
# set optimizer_search_depth=0; - automatic
|
# set optimizer_search_depth=0; - automatic
|
||||||
# set optimizer_search_depth=1; - min
|
# set optimizer_search_depth=1; - min
|
||||||
# set optimizer_search_depth=62; - max (default)
|
# set optimizer_search_depth=62; - max (default)
|
||||||
#
|
# 2:
|
||||||
# set optimizer_prune_level=0 - exhaustive;
|
# set optimizer_prune_level=0 - exhaustive;
|
||||||
# set optimizer_prune_level=1 - heuristic; # default
|
# set optimizer_prune_level=1 - heuristic; # default
|
||||||
|
|
||||||
|
@ -512,10 +512,12 @@ select * from v1a join (t3 natural join t4) on a = y;
|
|||||||
#--------------------------------------------------------------------
|
#--------------------------------------------------------------------
|
||||||
# Negative tests (tests for errors)
|
# Negative tests (tests for errors)
|
||||||
#--------------------------------------------------------------------
|
#--------------------------------------------------------------------
|
||||||
|
# works in Oracle - bug
|
||||||
-- error 1052
|
-- error 1052
|
||||||
select * from t1 natural join (t3 cross join t4); # works in Oracle - bug
|
select * from t1 natural join (t3 cross join t4);
|
||||||
|
# works in Oracle - bug
|
||||||
-- error 1052
|
-- error 1052
|
||||||
select * from (t3 cross join t4) natural join t1; # works in Oracle - bug
|
select * from (t3 cross join t4) natural join t1;
|
||||||
-- error 1052
|
-- error 1052
|
||||||
select * from t1 join (t2, t3) using (b);
|
select * from t1 join (t2, t3) using (b);
|
||||||
-- error 1052
|
-- error 1052
|
||||||
|
@ -400,6 +400,76 @@ show tables like "%log%";
|
|||||||
drop table slow_log_new, general_log_new;
|
drop table slow_log_new, general_log_new;
|
||||||
use test;
|
use test;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug#27857 (Log tables supplies the wrong value for generating
|
||||||
|
# AUTO_INCREMENT numbers)
|
||||||
|
#
|
||||||
|
|
||||||
|
SET GLOBAL LOG_OUTPUT = 'TABLE';
|
||||||
|
|
||||||
|
## test the general log
|
||||||
|
|
||||||
|
SET GLOBAL general_log = 0;
|
||||||
|
FLUSH LOGS;
|
||||||
|
|
||||||
|
TRUNCATE TABLE mysql.general_log;
|
||||||
|
ALTER TABLE mysql.general_log ENGINE = MyISAM;
|
||||||
|
ALTER TABLE mysql.general_log
|
||||||
|
ADD COLUMN seq BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY;
|
||||||
|
|
||||||
|
SET GLOBAL general_log = 1;
|
||||||
|
FLUSH LOGS;
|
||||||
|
|
||||||
|
--replace_column 1 EVENT_TIME 2 USER_HOST 3 THREAD_ID 4 SERVER_ID
|
||||||
|
SELECT * FROM mysql.general_log;
|
||||||
|
--replace_column 1 EVENT_TIME 2 USER_HOST 3 THREAD_ID 4 SERVER_ID
|
||||||
|
SELECT * FROM mysql.general_log;
|
||||||
|
SELECT "My own query 1";
|
||||||
|
SELECT "My own query 2";
|
||||||
|
--replace_column 1 EVENT_TIME 2 USER_HOST 3 THREAD_ID 4 SERVER_ID
|
||||||
|
SELECT * FROM mysql.general_log;
|
||||||
|
|
||||||
|
SET GLOBAL general_log = 0;
|
||||||
|
FLUSH LOGS;
|
||||||
|
|
||||||
|
ALTER TABLE mysql.general_log DROP COLUMN seq;
|
||||||
|
ALTER TABLE mysql.general_log ENGINE = CSV;
|
||||||
|
|
||||||
|
## test the slow query log
|
||||||
|
|
||||||
|
SET @old_long_query_time:=@@long_query_time;
|
||||||
|
|
||||||
|
SET GLOBAL slow_query_log = 0;
|
||||||
|
FLUSH LOGS;
|
||||||
|
|
||||||
|
TRUNCATE TABLE mysql.slow_log;
|
||||||
|
ALTER TABLE mysql.slow_log ENGINE = MyISAM;
|
||||||
|
|
||||||
|
ALTER TABLE mysql.slow_log
|
||||||
|
ADD COLUMN seq BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY;
|
||||||
|
|
||||||
|
SET SESSION long_query_time = 1;
|
||||||
|
SET GLOBAL slow_query_log = 1;
|
||||||
|
FLUSH LOGS;
|
||||||
|
|
||||||
|
## FLUSH LOGS above might be slow, so the following is
|
||||||
|
## logged as either seq 1-4 or seq 2-5
|
||||||
|
SELECT "My own slow query", sleep(2);
|
||||||
|
SELECT "My own slow query", sleep(2);
|
||||||
|
SELECT "My own slow query", sleep(2);
|
||||||
|
SELECT "My own slow query", sleep(2);
|
||||||
|
|
||||||
|
## So we look for seq 2-4
|
||||||
|
--replace_column 1 START_TIME 2 USER_HOST 3 QUERY_TIME
|
||||||
|
SELECT * FROM mysql.slow_log WHERE seq >= 2 LIMIT 3;
|
||||||
|
|
||||||
|
SET GLOBAL slow_query_log = 0;
|
||||||
|
SET SESSION long_query_time =@old_long_query_time;
|
||||||
|
FLUSH LOGS;
|
||||||
|
|
||||||
|
ALTER TABLE mysql.slow_log DROP COLUMN seq;
|
||||||
|
ALTER TABLE mysql.slow_log ENGINE = CSV;
|
||||||
|
|
||||||
# kill all connections
|
# kill all connections
|
||||||
disconnect con1;
|
disconnect con1;
|
||||||
disconnect con2;
|
disconnect con2;
|
||||||
|
@ -1058,3 +1058,48 @@ drop table t1;
|
|||||||
set GLOBAL query_cache_size= default;
|
set GLOBAL query_cache_size= default;
|
||||||
|
|
||||||
# End of 5.0 tests
|
# End of 5.0 tests
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug #28211 RENAME DATABASE and query cache don't play nicely together
|
||||||
|
#
|
||||||
|
--disable_warnings
|
||||||
|
drop database if exists db1;
|
||||||
|
drop database if exists db2;
|
||||||
|
--enable_warnings
|
||||||
|
set GLOBAL query_cache_size=15*1024*1024;
|
||||||
|
create database db1;
|
||||||
|
use db1;
|
||||||
|
create table t1(c1 int)engine=myisam;
|
||||||
|
insert into t1(c1) values (1);
|
||||||
|
select * from db1.t1 f;
|
||||||
|
show status like 'Qcache_queries_in_cache';
|
||||||
|
rename schema db1 to db2;
|
||||||
|
show status like 'Qcache_queries_in_cache';
|
||||||
|
drop database db2;
|
||||||
|
set global query_cache_size=default;
|
||||||
|
|
||||||
|
--disable_warnings
|
||||||
|
drop database if exists db1;
|
||||||
|
drop database if exists db3;
|
||||||
|
--enable_warnings
|
||||||
|
set GLOBAL query_cache_size=15*1024*1024;
|
||||||
|
create database db1;
|
||||||
|
create database db3;
|
||||||
|
use db1;
|
||||||
|
create table t1(c1 int) engine=myisam;
|
||||||
|
use db3;
|
||||||
|
create table t1(c1 int) engine=myisam;
|
||||||
|
use db1;
|
||||||
|
insert into t1(c1) values (1);
|
||||||
|
use mysql;
|
||||||
|
select * from db1.t1;
|
||||||
|
select c1+1 from db1.t1;
|
||||||
|
select * from db3.t1;
|
||||||
|
show status like 'Qcache_queries_in_cache';
|
||||||
|
rename schema db1 to db2;
|
||||||
|
show status like 'Qcache_queries_in_cache';
|
||||||
|
drop database db2;
|
||||||
|
drop database db3;
|
||||||
|
|
||||||
|
# End of 5.1 tests
|
||||||
|
@ -7251,4 +7251,83 @@ DROP FUNCTION metered;
|
|||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
|
||||||
--echo End of 5.0 tests
|
#
|
||||||
|
# Bug#25411 (trigger code truncated)
|
||||||
|
#
|
||||||
|
|
||||||
|
--disable_warnings
|
||||||
|
drop procedure if exists proc_25411_a;
|
||||||
|
drop procedure if exists proc_25411_b;
|
||||||
|
drop procedure if exists proc_25411_c;
|
||||||
|
--enable_warnings
|
||||||
|
|
||||||
|
delimiter $$;
|
||||||
|
|
||||||
|
create procedure proc_25411_a()
|
||||||
|
begin
|
||||||
|
/* real comment */
|
||||||
|
select 1;
|
||||||
|
/*! select 2; */
|
||||||
|
select 3;
|
||||||
|
/*!00000 select 4; */
|
||||||
|
/*!99999 select 5; */
|
||||||
|
end
|
||||||
|
$$
|
||||||
|
|
||||||
|
create procedure proc_25411_b(
|
||||||
|
/* real comment */
|
||||||
|
/*! p1 int, */
|
||||||
|
/*!00000 p2 int */
|
||||||
|
/*!99999 ,p3 int */
|
||||||
|
)
|
||||||
|
begin
|
||||||
|
select p1, p2;
|
||||||
|
end
|
||||||
|
$$
|
||||||
|
|
||||||
|
create procedure proc_25411_c()
|
||||||
|
begin
|
||||||
|
select 1/*!,2*//*!00000,3*//*!99999,4*/;
|
||||||
|
select 1/*! ,2*//*!00000 ,3*//*!99999 ,4*/;
|
||||||
|
select 1/*!,2 *//*!00000,3 *//*!99999,4 */;
|
||||||
|
select 1/*! ,2 *//*!00000 ,3 *//*!99999 ,4 */;
|
||||||
|
select 1 /*!,2*/ /*!00000,3*/ /*!99999,4*/ ;
|
||||||
|
end
|
||||||
|
$$
|
||||||
|
|
||||||
|
delimiter ;$$
|
||||||
|
|
||||||
|
show create procedure proc_25411_a;
|
||||||
|
call proc_25411_a();
|
||||||
|
|
||||||
|
show create procedure proc_25411_b;
|
||||||
|
select name, param_list, body from mysql.proc where name like "%25411%";
|
||||||
|
call proc_25411_b(10, 20);
|
||||||
|
|
||||||
|
show create procedure proc_25411_c;
|
||||||
|
call proc_25411_c();
|
||||||
|
|
||||||
|
drop procedure proc_25411_a;
|
||||||
|
drop procedure proc_25411_b;
|
||||||
|
drop procedure proc_25411_c;
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug#26302 (MySQL server cuts off trailing "*/" from comments in SP/func)
|
||||||
|
#
|
||||||
|
|
||||||
|
--disable_warnings
|
||||||
|
drop procedure if exists proc_26302;
|
||||||
|
--enable_warnings
|
||||||
|
|
||||||
|
create procedure proc_26302()
|
||||||
|
select 1 /* testing */;
|
||||||
|
|
||||||
|
show create procedure proc_26302;
|
||||||
|
|
||||||
|
select ROUTINE_NAME, ROUTINE_DEFINITION from information_schema.ROUTINES
|
||||||
|
where ROUTINE_NAME = "proc_26302";
|
||||||
|
|
||||||
|
drop procedure proc_26302;
|
||||||
|
|
||||||
|
|
||||||
|
@ -1830,3 +1830,30 @@ SET SESSION LOW_PRIORITY_UPDATES=DEFAULT;
|
|||||||
SET GLOBAL LOW_PRIORITY_UPDATES=DEFAULT;
|
SET GLOBAL LOW_PRIORITY_UPDATES=DEFAULT;
|
||||||
|
|
||||||
--echo End of 5.0 tests
|
--echo End of 5.0 tests
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug#25411 (trigger code truncated)
|
||||||
|
#
|
||||||
|
|
||||||
|
--disable_warnings
|
||||||
|
drop table if exists table_25411_a;
|
||||||
|
drop table if exists table_25411_b;
|
||||||
|
--enable_warnings
|
||||||
|
|
||||||
|
create table table_25411_a(a int);
|
||||||
|
create table table_25411_b(b int);
|
||||||
|
|
||||||
|
create trigger trg_25411a_ai after insert on table_25411_a
|
||||||
|
for each row
|
||||||
|
insert into table_25411_b select new.*;
|
||||||
|
|
||||||
|
select * from table_25411_a;
|
||||||
|
|
||||||
|
--error ER_BAD_TABLE_ERROR
|
||||||
|
insert into table_25411_a values (1);
|
||||||
|
|
||||||
|
select * from table_25411_a;
|
||||||
|
|
||||||
|
drop table table_25411_a;
|
||||||
|
drop table table_25411_b;
|
||||||
|
|
||||||
|
@ -85,3 +85,22 @@ alter table t1 modify a varchar(255);
|
|||||||
select length(a) from t1;
|
select length(a) from t1;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug#28127 (Some valid identifiers names are not parsed correctly)
|
||||||
|
#
|
||||||
|
|
||||||
|
--disable_warnings
|
||||||
|
drop table if exists table_28127_a;
|
||||||
|
drop table if exists table_28127_b;
|
||||||
|
--enable_warnings
|
||||||
|
|
||||||
|
create table table_28127_a(0b02 int);
|
||||||
|
show create table table_28127_a;
|
||||||
|
|
||||||
|
create table table_28127_b(0b2 int);
|
||||||
|
show create table table_28127_b;
|
||||||
|
|
||||||
|
drop table table_28127_a;
|
||||||
|
drop table table_28127_b;
|
||||||
|
|
||||||
|
@ -573,6 +573,70 @@ CHARSET_INFO *get_charset_by_csname(const char *cs_name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Resolve character set by the character set name (utf8, latin1, ...).
|
||||||
|
|
||||||
|
The function tries to resolve character set by the specified name. If
|
||||||
|
there is character set with the given name, it is assigned to the "cs"
|
||||||
|
parameter and FALSE is returned. If there is no such character set,
|
||||||
|
"default_cs" is assigned to the "cs" and TRUE is returned.
|
||||||
|
|
||||||
|
@param[out] cs Variable to store character set.
|
||||||
|
@param[in] cs_name Character set name.
|
||||||
|
@param[in] default_cs Default character set.
|
||||||
|
|
||||||
|
@return FALSE if character set was resolved successfully; TRUE if there
|
||||||
|
is no character set with given name.
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool resolve_charset(CHARSET_INFO **cs,
|
||||||
|
const char *cs_name,
|
||||||
|
CHARSET_INFO *default_cs)
|
||||||
|
{
|
||||||
|
*cs= get_charset_by_csname(cs_name, MY_CS_PRIMARY, MYF(0));
|
||||||
|
|
||||||
|
if (*cs == NULL)
|
||||||
|
{
|
||||||
|
*cs= default_cs;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Resolve collation by the collation name (utf8_general_ci, ...).
|
||||||
|
|
||||||
|
The function tries to resolve collation by the specified name. If there
|
||||||
|
is collation with the given name, it is assigned to the "cl" parameter
|
||||||
|
and FALSE is returned. If there is no such collation, "default_cl" is
|
||||||
|
assigned to the "cl" and TRUE is returned.
|
||||||
|
|
||||||
|
@param[out] cl Variable to store collation.
|
||||||
|
@param[in] cl_name Collation name.
|
||||||
|
@param[in] default_cl Default collation.
|
||||||
|
|
||||||
|
@return FALSE if collation was resolved successfully; TRUE if there is no
|
||||||
|
collation with given name.
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool resolve_collation(CHARSET_INFO **cl,
|
||||||
|
const char *cl_name,
|
||||||
|
CHARSET_INFO *default_cl)
|
||||||
|
{
|
||||||
|
*cl= get_charset_by_name(cl_name, MYF(0));
|
||||||
|
|
||||||
|
if (*cl == NULL)
|
||||||
|
{
|
||||||
|
*cl= default_cl;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Escape string with backslashes (\)
|
Escape string with backslashes (\)
|
||||||
|
|
||||||
|
@ -94,6 +94,7 @@ Event_parse_data::Event_parse_data()
|
|||||||
:on_completion(Event_basic::ON_COMPLETION_DROP),
|
:on_completion(Event_basic::ON_COMPLETION_DROP),
|
||||||
status(Event_basic::ENABLED),
|
status(Event_basic::ENABLED),
|
||||||
do_not_create(FALSE),
|
do_not_create(FALSE),
|
||||||
|
body_changed(FALSE),
|
||||||
item_starts(NULL), item_ends(NULL), item_execute_at(NULL),
|
item_starts(NULL), item_ends(NULL), item_execute_at(NULL),
|
||||||
starts_null(TRUE), ends_null(TRUE), execute_at_null(TRUE),
|
starts_null(TRUE), ends_null(TRUE), execute_at_null(TRUE),
|
||||||
item_expression(NULL), expression(0)
|
item_expression(NULL), expression(0)
|
||||||
@ -103,8 +104,8 @@ Event_parse_data::Event_parse_data()
|
|||||||
/* Actually in the parser STARTS is always set */
|
/* Actually in the parser STARTS is always set */
|
||||||
starts= ends= execute_at= 0;
|
starts= ends= execute_at= 0;
|
||||||
|
|
||||||
body.str= comment.str= NULL;
|
comment.str= NULL;
|
||||||
body.length= comment.length= 0;
|
comment.length= 0;
|
||||||
|
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
@ -137,86 +138,6 @@ Event_parse_data::init_name(THD *thd, sp_name *spn)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
Set body of the event - what should be executed.
|
|
||||||
|
|
||||||
SYNOPSIS
|
|
||||||
Event_parse_data::init_body()
|
|
||||||
thd THD
|
|
||||||
|
|
||||||
NOTE
|
|
||||||
The body is extracted by copying all data between the
|
|
||||||
start of the body set by another method and the current pointer in Lex.
|
|
||||||
|
|
||||||
Some questionable removal of characters is done in here, and that part
|
|
||||||
should be refactored when the parser is smarter.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
Event_parse_data::init_body(THD *thd)
|
|
||||||
{
|
|
||||||
DBUG_ENTER("Event_parse_data::init_body");
|
|
||||||
|
|
||||||
/* This method is called from within the parser, from sql_yacc.yy */
|
|
||||||
DBUG_ASSERT(thd->m_lip != NULL);
|
|
||||||
|
|
||||||
DBUG_PRINT("info", ("body: '%s' body_begin: 0x%lx end: 0x%lx", body_begin,
|
|
||||||
(long) body_begin, (long) thd->m_lip->ptr));
|
|
||||||
|
|
||||||
body.length= thd->m_lip->ptr - body_begin;
|
|
||||||
const char *body_end= body_begin + body.length - 1;
|
|
||||||
|
|
||||||
/* Trim nuls or close-comments ('*'+'/') or spaces at the end */
|
|
||||||
while (body_begin < body_end)
|
|
||||||
{
|
|
||||||
|
|
||||||
if ((*body_end == '\0') ||
|
|
||||||
(my_isspace(thd->variables.character_set_client, *body_end)))
|
|
||||||
{ /* consume NULs and meaningless whitespace */
|
|
||||||
--body.length;
|
|
||||||
--body_end;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
consume closing comments
|
|
||||||
|
|
||||||
This is arguably wrong, but it's the best we have until the parser is
|
|
||||||
changed to be smarter. FIXME PARSER
|
|
||||||
|
|
||||||
See also the sp_head code, where something like this is done also.
|
|
||||||
|
|
||||||
One idea is to keep in the lexer structure the count of the number of
|
|
||||||
open-comments we've entered, and scan left-to-right looking for a
|
|
||||||
closing comment IFF the count is greater than zero.
|
|
||||||
|
|
||||||
Another idea is to remove the closing comment-characters wholly in the
|
|
||||||
parser, since that's where it "removes" the opening characters.
|
|
||||||
*/
|
|
||||||
if ((*(body_end - 1) == '*') && (*body_end == '/'))
|
|
||||||
{
|
|
||||||
DBUG_PRINT("info", ("consumend one '*" "/' comment in the query '%s'",
|
|
||||||
body_begin));
|
|
||||||
body.length-= 2;
|
|
||||||
body_end-= 2;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
break; /* none were found, so we have excised all we can. */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* the first is always whitespace which I cannot skip in the parser */
|
|
||||||
while (my_isspace(thd->variables.character_set_client, *body_begin))
|
|
||||||
{
|
|
||||||
++body_begin;
|
|
||||||
--body.length;
|
|
||||||
}
|
|
||||||
body.str= thd->strmake(body_begin, body.length);
|
|
||||||
|
|
||||||
DBUG_VOID_RETURN;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This function is called on CREATE EVENT or ALTER EVENT. When either
|
This function is called on CREATE EVENT or ALTER EVENT. When either
|
||||||
ENDS or AT is in the past, we are trying to create an event that
|
ENDS or AT is in the past, we are trying to create an event that
|
||||||
@ -838,36 +759,32 @@ Event_timed::init()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/**
|
||||||
Loads an event's body from a row from mysql.event
|
Load an event's body from a row from mysql.event.
|
||||||
|
@details This method is silent on errors and should behave like that.
|
||||||
|
Callers should handle throwing of error messages. The reason is that the
|
||||||
|
class should not know about how to deal with communication.
|
||||||
|
|
||||||
SYNOPSIS
|
@return Operation status
|
||||||
Event_job_data::load_from_row(THD *thd, TABLE *table)
|
@retval FALSE OK
|
||||||
|
@retval TRUE Error
|
||||||
RETURN VALUE
|
|
||||||
0 OK
|
|
||||||
EVEX_GET_FIELD_FAILED Error
|
|
||||||
|
|
||||||
NOTES
|
|
||||||
This method is silent on errors and should behave like that. Callers
|
|
||||||
should handle throwing of error messages. The reason is that the class
|
|
||||||
should not know about how to deal with communication.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
bool
|
||||||
Event_job_data::load_from_row(THD *thd, TABLE *table)
|
Event_job_data::load_from_row(THD *thd, TABLE *table)
|
||||||
{
|
{
|
||||||
char *ptr;
|
char *ptr;
|
||||||
uint len;
|
uint len;
|
||||||
|
LEX_STRING tz_name;
|
||||||
|
|
||||||
DBUG_ENTER("Event_job_data::load_from_row");
|
DBUG_ENTER("Event_job_data::load_from_row");
|
||||||
|
|
||||||
if (!table)
|
if (!table)
|
||||||
goto error;
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
if (table->s->fields < ET_FIELD_COUNT)
|
if (table->s->fields < ET_FIELD_COUNT)
|
||||||
goto error;
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
LEX_STRING tz_name;
|
|
||||||
if (load_string_fields(table->field,
|
if (load_string_fields(table->field,
|
||||||
ET_FIELD_DB, &dbname,
|
ET_FIELD_DB, &dbname,
|
||||||
ET_FIELD_NAME, &name,
|
ET_FIELD_NAME, &name,
|
||||||
@ -875,10 +792,10 @@ Event_job_data::load_from_row(THD *thd, TABLE *table)
|
|||||||
ET_FIELD_DEFINER, &definer,
|
ET_FIELD_DEFINER, &definer,
|
||||||
ET_FIELD_TIME_ZONE, &tz_name,
|
ET_FIELD_TIME_ZONE, &tz_name,
|
||||||
ET_FIELD_COUNT))
|
ET_FIELD_COUNT))
|
||||||
goto error;
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
if (load_time_zone(thd, tz_name))
|
if (load_time_zone(thd, tz_name))
|
||||||
goto error;
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
ptr= strchr(definer.str, '@');
|
ptr= strchr(definer.str, '@');
|
||||||
|
|
||||||
@ -895,29 +812,23 @@ Event_job_data::load_from_row(THD *thd, TABLE *table)
|
|||||||
|
|
||||||
sql_mode= (ulong) table->field[ET_FIELD_SQL_MODE]->val_int();
|
sql_mode= (ulong) table->field[ET_FIELD_SQL_MODE]->val_int();
|
||||||
|
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(FALSE);
|
||||||
error:
|
|
||||||
DBUG_RETURN(EVEX_GET_FIELD_FAILED);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/**
|
||||||
Loads an event from a row from mysql.event
|
Load an event's body from a row from mysql.event.
|
||||||
|
|
||||||
SYNOPSIS
|
@details This method is silent on errors and should behave like that.
|
||||||
Event_queue_element::load_from_row(THD *thd, TABLE *table)
|
Callers should handle throwing of error messages. The reason is that the
|
||||||
|
class should not know about how to deal with communication.
|
||||||
|
|
||||||
RETURN VALUE
|
@return Operation status
|
||||||
0 OK
|
@retval FALSE OK
|
||||||
EVEX_GET_FIELD_FAILED Error
|
@retval TRUE Error
|
||||||
|
|
||||||
NOTES
|
|
||||||
This method is silent on errors and should behave like that. Callers
|
|
||||||
should handle throwing of error messages. The reason is that the class
|
|
||||||
should not know about how to deal with communication.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
bool
|
||||||
Event_queue_element::load_from_row(THD *thd, TABLE *table)
|
Event_queue_element::load_from_row(THD *thd, TABLE *table)
|
||||||
{
|
{
|
||||||
char *ptr;
|
char *ptr;
|
||||||
@ -927,10 +838,10 @@ Event_queue_element::load_from_row(THD *thd, TABLE *table)
|
|||||||
DBUG_ENTER("Event_queue_element::load_from_row");
|
DBUG_ENTER("Event_queue_element::load_from_row");
|
||||||
|
|
||||||
if (!table)
|
if (!table)
|
||||||
goto error;
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
if (table->s->fields < ET_FIELD_COUNT)
|
if (table->s->fields < ET_FIELD_COUNT)
|
||||||
goto error;
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
if (load_string_fields(table->field,
|
if (load_string_fields(table->field,
|
||||||
ET_FIELD_DB, &dbname,
|
ET_FIELD_DB, &dbname,
|
||||||
@ -938,10 +849,10 @@ Event_queue_element::load_from_row(THD *thd, TABLE *table)
|
|||||||
ET_FIELD_DEFINER, &definer,
|
ET_FIELD_DEFINER, &definer,
|
||||||
ET_FIELD_TIME_ZONE, &tz_name,
|
ET_FIELD_TIME_ZONE, &tz_name,
|
||||||
ET_FIELD_COUNT))
|
ET_FIELD_COUNT))
|
||||||
goto error;
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
if (load_time_zone(thd, tz_name))
|
if (load_time_zone(thd, tz_name))
|
||||||
goto error;
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
starts_null= table->field[ET_FIELD_STARTS]->is_null();
|
starts_null= table->field[ET_FIELD_STARTS]->is_null();
|
||||||
if (!starts_null)
|
if (!starts_null)
|
||||||
@ -971,7 +882,7 @@ Event_queue_element::load_from_row(THD *thd, TABLE *table)
|
|||||||
{
|
{
|
||||||
if (table->field[ET_FIELD_EXECUTE_AT]->get_date(&time,
|
if (table->field[ET_FIELD_EXECUTE_AT]->get_date(&time,
|
||||||
TIME_NO_ZERO_DATE))
|
TIME_NO_ZERO_DATE))
|
||||||
goto error;
|
DBUG_RETURN(TRUE);
|
||||||
execute_at= sec_since_epoch_TIME(&time);
|
execute_at= sec_since_epoch_TIME(&time);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -990,13 +901,13 @@ Event_queue_element::load_from_row(THD *thd, TABLE *table)
|
|||||||
|
|
||||||
table->field[ET_FIELD_TRANSIENT_INTERVAL]->val_str(&str);
|
table->field[ET_FIELD_TRANSIENT_INTERVAL]->val_str(&str);
|
||||||
if (!(tmp.length= str.length()))
|
if (!(tmp.length= str.length()))
|
||||||
goto error;
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
tmp.str= str.c_ptr_safe();
|
tmp.str= str.c_ptr_safe();
|
||||||
|
|
||||||
i= find_string_in_array(interval_type_to_name, &tmp, system_charset_info);
|
i= find_string_in_array(interval_type_to_name, &tmp, system_charset_info);
|
||||||
if (i < 0)
|
if (i < 0)
|
||||||
goto error;
|
DBUG_RETURN(TRUE);
|
||||||
interval= (interval_type) i;
|
interval= (interval_type) i;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1009,7 +920,7 @@ Event_queue_element::load_from_row(THD *thd, TABLE *table)
|
|||||||
last_executed_changed= FALSE;
|
last_executed_changed= FALSE;
|
||||||
|
|
||||||
if ((ptr= get_field(&mem_root, table->field[ET_FIELD_STATUS])) == NullS)
|
if ((ptr= get_field(&mem_root, table->field[ET_FIELD_STATUS])) == NullS)
|
||||||
goto error;
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
DBUG_PRINT("load_from_row", ("Event [%s] is [%s]", name.str, ptr));
|
DBUG_PRINT("load_from_row", ("Event [%s] is [%s]", name.str, ptr));
|
||||||
|
|
||||||
@ -1028,40 +939,34 @@ Event_queue_element::load_from_row(THD *thd, TABLE *table)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if ((ptr= get_field(&mem_root, table->field[ET_FIELD_ORIGINATOR])) == NullS)
|
if ((ptr= get_field(&mem_root, table->field[ET_FIELD_ORIGINATOR])) == NullS)
|
||||||
goto error;
|
DBUG_RETURN(TRUE);
|
||||||
originator = table->field[ET_FIELD_ORIGINATOR]->val_int();
|
originator = table->field[ET_FIELD_ORIGINATOR]->val_int();
|
||||||
|
|
||||||
/* ToDo : Andrey . Find a way not to allocate ptr on event_mem_root */
|
/* ToDo : Andrey . Find a way not to allocate ptr on event_mem_root */
|
||||||
if ((ptr= get_field(&mem_root,
|
if ((ptr= get_field(&mem_root,
|
||||||
table->field[ET_FIELD_ON_COMPLETION])) == NullS)
|
table->field[ET_FIELD_ON_COMPLETION])) == NullS)
|
||||||
goto error;
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
on_completion= (ptr[0]=='D'? Event_queue_element::ON_COMPLETION_DROP:
|
on_completion= (ptr[0]=='D'? Event_queue_element::ON_COMPLETION_DROP:
|
||||||
Event_queue_element::ON_COMPLETION_PRESERVE);
|
Event_queue_element::ON_COMPLETION_PRESERVE);
|
||||||
|
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(FALSE);
|
||||||
error:
|
|
||||||
DBUG_RETURN(EVEX_GET_FIELD_FAILED);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/**
|
||||||
Loads an event from a row from mysql.event
|
Load an event's body from a row from mysql.event.
|
||||||
|
|
||||||
SYNOPSIS
|
@details This method is silent on errors and should behave like that.
|
||||||
Event_timed::load_from_row(THD *thd, TABLE *table)
|
Callers should handle throwing of error messages. The reason is that the
|
||||||
|
class should not know about how to deal with communication.
|
||||||
|
|
||||||
RETURN VALUE
|
@return Operation status
|
||||||
0 OK
|
@retval FALSE OK
|
||||||
EVEX_GET_FIELD_FAILED Error
|
@retval TRUE Error
|
||||||
|
|
||||||
NOTES
|
|
||||||
This method is silent on errors and should behave like that. Callers
|
|
||||||
should handle throwing of error messages. The reason is that the class
|
|
||||||
should not know about how to deal with communication.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
bool
|
||||||
Event_timed::load_from_row(THD *thd, TABLE *table)
|
Event_timed::load_from_row(THD *thd, TABLE *table)
|
||||||
{
|
{
|
||||||
char *ptr;
|
char *ptr;
|
||||||
@ -1070,12 +975,12 @@ Event_timed::load_from_row(THD *thd, TABLE *table)
|
|||||||
DBUG_ENTER("Event_timed::load_from_row");
|
DBUG_ENTER("Event_timed::load_from_row");
|
||||||
|
|
||||||
if (Event_queue_element::load_from_row(thd, table))
|
if (Event_queue_element::load_from_row(thd, table))
|
||||||
goto error;
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
if (load_string_fields(table->field,
|
if (load_string_fields(table->field,
|
||||||
ET_FIELD_BODY, &body,
|
ET_FIELD_BODY, &body,
|
||||||
ET_FIELD_COUNT))
|
ET_FIELD_COUNT))
|
||||||
goto error;
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
|
|
||||||
ptr= strchr(definer.str, '@');
|
ptr= strchr(definer.str, '@');
|
||||||
@ -1102,9 +1007,7 @@ Event_timed::load_from_row(THD *thd, TABLE *table)
|
|||||||
|
|
||||||
sql_mode= (ulong) table->field[ET_FIELD_SQL_MODE]->val_int();
|
sql_mode= (ulong) table->field[ET_FIELD_SQL_MODE]->val_int();
|
||||||
|
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(FALSE);
|
||||||
error:
|
|
||||||
DBUG_RETURN(EVEX_GET_FIELD_FAILED);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1925,11 +1828,9 @@ Event_job_data::execute(THD *thd, bool drop)
|
|||||||
|
|
||||||
{
|
{
|
||||||
Lex_input_stream lip(thd, thd->query, thd->query_length);
|
Lex_input_stream lip(thd, thd->query, thd->query_length);
|
||||||
thd->m_lip= &lip;
|
|
||||||
lex_start(thd);
|
lex_start(thd);
|
||||||
int err= MYSQLparse(thd);
|
|
||||||
|
|
||||||
if (err || thd->is_fatal_error)
|
if (parse_sql(thd, &lip))
|
||||||
{
|
{
|
||||||
sql_print_error("Event Scheduler: "
|
sql_print_error("Event Scheduler: "
|
||||||
"%serror during compilation of %s.%s",
|
"%serror during compilation of %s.%s",
|
||||||
@ -1999,6 +1900,9 @@ end:
|
|||||||
thd->lex->unit.cleanup();
|
thd->lex->unit.cleanup();
|
||||||
thd->end_statement();
|
thd->end_statement();
|
||||||
thd->cleanup_after_query();
|
thd->cleanup_after_query();
|
||||||
|
/* Avoid races with SHOW PROCESSLIST */
|
||||||
|
thd->query_length= 0;
|
||||||
|
thd->query= NULL;
|
||||||
|
|
||||||
DBUG_PRINT("info", ("EXECUTED %s.%s ret: %d", dbname.str, name.str, ret));
|
DBUG_PRINT("info", ("EXECUTED %s.%s ret: %d", dbname.str, name.str, ret));
|
||||||
|
|
||||||
|
@ -77,7 +77,7 @@ public:
|
|||||||
Event_basic();
|
Event_basic();
|
||||||
virtual ~Event_basic();
|
virtual ~Event_basic();
|
||||||
|
|
||||||
virtual int
|
virtual bool
|
||||||
load_from_row(THD *thd, TABLE *table) = 0;
|
load_from_row(THD *thd, TABLE *table) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -119,7 +119,7 @@ public:
|
|||||||
Event_queue_element();
|
Event_queue_element();
|
||||||
virtual ~Event_queue_element();
|
virtual ~Event_queue_element();
|
||||||
|
|
||||||
virtual int
|
virtual bool
|
||||||
load_from_row(THD *thd, TABLE *table);
|
load_from_row(THD *thd, TABLE *table);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -157,7 +157,7 @@ public:
|
|||||||
void
|
void
|
||||||
init();
|
init();
|
||||||
|
|
||||||
virtual int
|
virtual bool
|
||||||
load_from_row(THD *thd, TABLE *table);
|
load_from_row(THD *thd, TABLE *table);
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -176,7 +176,7 @@ public:
|
|||||||
|
|
||||||
Event_job_data();
|
Event_job_data();
|
||||||
|
|
||||||
virtual int
|
virtual bool
|
||||||
load_from_row(THD *thd, TABLE *table);
|
load_from_row(THD *thd, TABLE *table);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -205,12 +205,11 @@ public:
|
|||||||
*/
|
*/
|
||||||
bool do_not_create;
|
bool do_not_create;
|
||||||
|
|
||||||
const char *body_begin;
|
bool body_changed;
|
||||||
|
|
||||||
LEX_STRING dbname;
|
LEX_STRING dbname;
|
||||||
LEX_STRING name;
|
LEX_STRING name;
|
||||||
LEX_STRING definer;// combination of user and host
|
LEX_STRING definer;// combination of user and host
|
||||||
LEX_STRING body;
|
|
||||||
LEX_STRING comment;
|
LEX_STRING comment;
|
||||||
|
|
||||||
Item* item_starts;
|
Item* item_starts;
|
||||||
@ -235,9 +234,6 @@ public:
|
|||||||
bool
|
bool
|
||||||
check_parse_data(THD *thd);
|
check_parse_data(THD *thd);
|
||||||
|
|
||||||
void
|
|
||||||
init_body(THD *thd);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
#include "mysql_priv.h"
|
#include "mysql_priv.h"
|
||||||
#include "event_db_repository.h"
|
#include "event_db_repository.h"
|
||||||
|
#include "sp_head.h"
|
||||||
#include "event_data_objects.h"
|
#include "event_data_objects.h"
|
||||||
#include "events.h"
|
#include "events.h"
|
||||||
#include "sql_show.h"
|
#include "sql_show.h"
|
||||||
@ -141,7 +142,10 @@ const TABLE_FIELD_W_TYPE event_table_fields[ET_FIELD_COUNT] =
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
mysql_event_fill_row(THD *thd, TABLE *table, Event_parse_data *et,
|
mysql_event_fill_row(THD *thd,
|
||||||
|
TABLE *table,
|
||||||
|
Event_parse_data *et,
|
||||||
|
sp_head *sp,
|
||||||
my_bool is_update)
|
my_bool is_update)
|
||||||
{
|
{
|
||||||
CHARSET_INFO *scs= system_charset_info;
|
CHARSET_INFO *scs= system_charset_info;
|
||||||
@ -152,7 +156,6 @@ mysql_event_fill_row(THD *thd, TABLE *table, Event_parse_data *et,
|
|||||||
|
|
||||||
DBUG_PRINT("info", ("dbname=[%s]", et->dbname.str));
|
DBUG_PRINT("info", ("dbname=[%s]", et->dbname.str));
|
||||||
DBUG_PRINT("info", ("name =[%s]", et->name.str));
|
DBUG_PRINT("info", ("name =[%s]", et->name.str));
|
||||||
DBUG_PRINT("info", ("body =[%s]", et->body.str));
|
|
||||||
|
|
||||||
if (table->s->fields < ET_FIELD_COUNT)
|
if (table->s->fields < ET_FIELD_COUNT)
|
||||||
{
|
{
|
||||||
@ -187,12 +190,19 @@ mysql_event_fill_row(THD *thd, TABLE *table, Event_parse_data *et,
|
|||||||
Change the SQL_MODE only if body was present in an ALTER EVENT and of course
|
Change the SQL_MODE only if body was present in an ALTER EVENT and of course
|
||||||
always during CREATE EVENT.
|
always during CREATE EVENT.
|
||||||
*/
|
*/
|
||||||
if (et->body.str)
|
if (et->body_changed)
|
||||||
{
|
{
|
||||||
|
DBUG_ASSERT(sp->m_body.str);
|
||||||
|
|
||||||
fields[ET_FIELD_SQL_MODE]->store((longlong)thd->variables.sql_mode, TRUE);
|
fields[ET_FIELD_SQL_MODE]->store((longlong)thd->variables.sql_mode, TRUE);
|
||||||
if (fields[f_num= ET_FIELD_BODY]->store(et->body.str, et->body.length, scs))
|
|
||||||
|
if (fields[f_num= ET_FIELD_BODY]->store(sp->m_body.str,
|
||||||
|
sp->m_body.length,
|
||||||
|
scs))
|
||||||
|
{
|
||||||
goto err_truncate;
|
goto err_truncate;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (et->expression)
|
if (et->expression)
|
||||||
{
|
{
|
||||||
@ -513,10 +523,12 @@ Event_db_repository::create_event(THD *thd, Event_parse_data *parse_data,
|
|||||||
{
|
{
|
||||||
int ret= 1;
|
int ret= 1;
|
||||||
TABLE *table= NULL;
|
TABLE *table= NULL;
|
||||||
|
sp_head *sp= thd->lex->sphead;
|
||||||
|
|
||||||
DBUG_ENTER("Event_db_repository::create_event");
|
DBUG_ENTER("Event_db_repository::create_event");
|
||||||
|
|
||||||
DBUG_PRINT("info", ("open mysql.event for update"));
|
DBUG_PRINT("info", ("open mysql.event for update"));
|
||||||
|
DBUG_ASSERT(sp);
|
||||||
|
|
||||||
if (open_event_table(thd, TL_WRITE, &table))
|
if (open_event_table(thd, TL_WRITE, &table))
|
||||||
goto end;
|
goto end;
|
||||||
@ -561,7 +573,7 @@ Event_db_repository::create_event(THD *thd, Event_parse_data *parse_data,
|
|||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parse_data->body.length > table->field[ET_FIELD_BODY]->field_length)
|
if (sp->m_body.length > table->field[ET_FIELD_BODY]->field_length)
|
||||||
{
|
{
|
||||||
my_error(ER_TOO_LONG_BODY, MYF(0), parse_data->name.str);
|
my_error(ER_TOO_LONG_BODY, MYF(0), parse_data->name.str);
|
||||||
goto end;
|
goto end;
|
||||||
@ -573,7 +585,7 @@ Event_db_repository::create_event(THD *thd, Event_parse_data *parse_data,
|
|||||||
mysql_event_fill_row() calls my_error() in case of error so no need to
|
mysql_event_fill_row() calls my_error() in case of error so no need to
|
||||||
handle it here
|
handle it here
|
||||||
*/
|
*/
|
||||||
if (mysql_event_fill_row(thd, table, parse_data, FALSE))
|
if (mysql_event_fill_row(thd, table, parse_data, sp, FALSE))
|
||||||
goto end;
|
goto end;
|
||||||
|
|
||||||
table->field[ET_FIELD_STATUS]->store((longlong)parse_data->status, TRUE);
|
table->field[ET_FIELD_STATUS]->store((longlong)parse_data->status, TRUE);
|
||||||
@ -617,7 +629,9 @@ Event_db_repository::update_event(THD *thd, Event_parse_data *parse_data,
|
|||||||
{
|
{
|
||||||
CHARSET_INFO *scs= system_charset_info;
|
CHARSET_INFO *scs= system_charset_info;
|
||||||
TABLE *table= NULL;
|
TABLE *table= NULL;
|
||||||
|
sp_head *sp= thd->lex->sphead;
|
||||||
int ret= 1;
|
int ret= 1;
|
||||||
|
|
||||||
DBUG_ENTER("Event_db_repository::update_event");
|
DBUG_ENTER("Event_db_repository::update_event");
|
||||||
|
|
||||||
/* None or both must be set */
|
/* None or both must be set */
|
||||||
@ -661,7 +675,7 @@ Event_db_repository::update_event(THD *thd, Event_parse_data *parse_data,
|
|||||||
mysql_event_fill_row() calls my_error() in case of error so no need to
|
mysql_event_fill_row() calls my_error() in case of error so no need to
|
||||||
handle it here
|
handle it here
|
||||||
*/
|
*/
|
||||||
if (mysql_event_fill_row(thd, table, parse_data, TRUE))
|
if (mysql_event_fill_row(thd, table, parse_data, sp, TRUE))
|
||||||
goto end;
|
goto end;
|
||||||
|
|
||||||
if (new_dbname)
|
if (new_dbname)
|
||||||
|
@ -326,6 +326,8 @@ end:
|
|||||||
|
|
||||||
delete event;
|
delete event;
|
||||||
deinit_event_thread(thd);
|
deinit_event_thread(thd);
|
||||||
|
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
62
sql/field.cc
62
sql/field.cc
@ -38,8 +38,8 @@
|
|||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
|
#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
|
||||||
template class List<create_field>;
|
template class List<Create_field>;
|
||||||
template class List_iterator<create_field>;
|
template class List_iterator<Create_field>;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
uchar Field_null::null[1]={1};
|
uchar Field_null::null[1]={1};
|
||||||
@ -2631,7 +2631,7 @@ void Field_new_decimal::sql_type(String &str) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint Field_new_decimal::is_equal(create_field *new_field)
|
uint Field_new_decimal::is_equal(Create_field *new_field)
|
||||||
{
|
{
|
||||||
return ((new_field->sql_type == real_type()) &&
|
return ((new_field->sql_type == real_type()) &&
|
||||||
((new_field->flags & UNSIGNED_FLAG) ==
|
((new_field->flags & UNSIGNED_FLAG) ==
|
||||||
@ -4366,7 +4366,7 @@ Field_timestamp::Field_timestamp(uchar *ptr_arg, uint32 len_arg,
|
|||||||
const char *field_name_arg,
|
const char *field_name_arg,
|
||||||
TABLE_SHARE *share,
|
TABLE_SHARE *share,
|
||||||
CHARSET_INFO *cs)
|
CHARSET_INFO *cs)
|
||||||
:Field_str(ptr_arg, 19, null_ptr_arg, null_bit_arg,
|
:Field_str(ptr_arg, MAX_DATETIME_WIDTH, null_ptr_arg, null_bit_arg,
|
||||||
unireg_check_arg, field_name_arg, cs)
|
unireg_check_arg, field_name_arg, cs)
|
||||||
{
|
{
|
||||||
/* For 4.0 MYD and 4.0 InnoDB compatibility */
|
/* For 4.0 MYD and 4.0 InnoDB compatibility */
|
||||||
@ -4383,7 +4383,8 @@ Field_timestamp::Field_timestamp(uchar *ptr_arg, uint32 len_arg,
|
|||||||
Field_timestamp::Field_timestamp(bool maybe_null_arg,
|
Field_timestamp::Field_timestamp(bool maybe_null_arg,
|
||||||
const char *field_name_arg,
|
const char *field_name_arg,
|
||||||
CHARSET_INFO *cs)
|
CHARSET_INFO *cs)
|
||||||
:Field_str((uchar*) 0, 19, maybe_null_arg ? (uchar*) "": 0, 0,
|
:Field_str((uchar*) 0, MAX_DATETIME_WIDTH,
|
||||||
|
maybe_null_arg ? (uchar*) "": 0, 0,
|
||||||
NONE, field_name_arg, cs)
|
NONE, field_name_arg, cs)
|
||||||
{
|
{
|
||||||
/* For 4.0 MYD and 4.0 InnoDB compatibility */
|
/* For 4.0 MYD and 4.0 InnoDB compatibility */
|
||||||
@ -4916,7 +4917,7 @@ String *Field_time::val_str(String *val_buffer,
|
|||||||
{
|
{
|
||||||
ASSERT_COLUMN_MARKED_FOR_READ;
|
ASSERT_COLUMN_MARKED_FOR_READ;
|
||||||
MYSQL_TIME ltime;
|
MYSQL_TIME ltime;
|
||||||
val_buffer->alloc(19);
|
val_buffer->alloc(MAX_DATE_STRING_REP_LENGTH);
|
||||||
long tmp=(long) sint3korr(ptr);
|
long tmp=(long) sint3korr(ptr);
|
||||||
ltime.neg= 0;
|
ltime.neg= 0;
|
||||||
if (tmp < 0)
|
if (tmp < 0)
|
||||||
@ -5464,7 +5465,7 @@ int Field_newdate::store_time(MYSQL_TIME *ltime,timestamp_type time_type)
|
|||||||
(MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE |
|
(MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE |
|
||||||
MODE_INVALID_DATES))), &error))
|
MODE_INVALID_DATES))), &error))
|
||||||
{
|
{
|
||||||
char buff[12];
|
char buff[MAX_DATE_STRING_REP_LENGTH];
|
||||||
String str(buff, sizeof(buff), &my_charset_latin1);
|
String str(buff, sizeof(buff), &my_charset_latin1);
|
||||||
make_date((DATE_TIME_FORMAT *) 0, ltime, &str);
|
make_date((DATE_TIME_FORMAT *) 0, ltime, &str);
|
||||||
set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED,
|
set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED,
|
||||||
@ -5695,7 +5696,7 @@ int Field_datetime::store_time(MYSQL_TIME *ltime,timestamp_type time_type)
|
|||||||
(MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE |
|
(MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE |
|
||||||
MODE_INVALID_DATES))), &error))
|
MODE_INVALID_DATES))), &error))
|
||||||
{
|
{
|
||||||
char buff[19];
|
char buff[MAX_DATE_STRING_REP_LENGTH];
|
||||||
String str(buff, sizeof(buff), &my_charset_latin1);
|
String str(buff, sizeof(buff), &my_charset_latin1);
|
||||||
make_datetime((DATE_TIME_FORMAT *) 0, ltime, &str);
|
make_datetime((DATE_TIME_FORMAT *) 0, ltime, &str);
|
||||||
set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED,
|
set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED,
|
||||||
@ -5771,7 +5772,7 @@ String *Field_datetime::val_str(String *val_buffer,
|
|||||||
part1=(long) (tmp/LL(1000000));
|
part1=(long) (tmp/LL(1000000));
|
||||||
part2=(long) (tmp - (ulonglong) part1*LL(1000000));
|
part2=(long) (tmp - (ulonglong) part1*LL(1000000));
|
||||||
|
|
||||||
pos=(char*) val_buffer->ptr()+19;
|
pos=(char*) val_buffer->ptr() + MAX_DATETIME_WIDTH;
|
||||||
*pos--=0;
|
*pos--=0;
|
||||||
*pos--= (char) ('0'+(char) (part2%10)); part2/=10;
|
*pos--= (char) ('0'+(char) (part2%10)); part2/=10;
|
||||||
*pos--= (char) ('0'+(char) (part2%10)); part3= (int) (part2 / 10);
|
*pos--= (char) ('0'+(char) (part2%10)); part3= (int) (part2 / 10);
|
||||||
@ -6069,7 +6070,7 @@ int Field_str::store(double nr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint Field::is_equal(create_field *new_field)
|
uint Field::is_equal(Create_field *new_field)
|
||||||
{
|
{
|
||||||
return (new_field->sql_type == real_type());
|
return (new_field->sql_type == real_type());
|
||||||
}
|
}
|
||||||
@ -6077,7 +6078,7 @@ uint Field::is_equal(create_field *new_field)
|
|||||||
|
|
||||||
/* If one of the fields is binary and the other one isn't return 1 else 0 */
|
/* If one of the fields is binary and the other one isn't return 1 else 0 */
|
||||||
|
|
||||||
bool Field_str::compare_str_field_flags(create_field *new_field, uint32 flags)
|
bool Field_str::compare_str_field_flags(Create_field *new_field, uint32 flags)
|
||||||
{
|
{
|
||||||
return (((new_field->flags & (BINCMP_FLAG | BINARY_FLAG)) &&
|
return (((new_field->flags & (BINCMP_FLAG | BINARY_FLAG)) &&
|
||||||
!(flags & (BINCMP_FLAG | BINARY_FLAG))) ||
|
!(flags & (BINCMP_FLAG | BINARY_FLAG))) ||
|
||||||
@ -6086,7 +6087,7 @@ bool Field_str::compare_str_field_flags(create_field *new_field, uint32 flags)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint Field_str::is_equal(create_field *new_field)
|
uint Field_str::is_equal(Create_field *new_field)
|
||||||
{
|
{
|
||||||
if (compare_str_field_flags(new_field, flags))
|
if (compare_str_field_flags(new_field, flags))
|
||||||
return 0;
|
return 0;
|
||||||
@ -6939,7 +6940,7 @@ Field *Field_varstring::new_key_field(MEM_ROOT *root,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint Field_varstring::is_equal(create_field *new_field)
|
uint Field_varstring::is_equal(Create_field *new_field)
|
||||||
{
|
{
|
||||||
if (new_field->sql_type == real_type() &&
|
if (new_field->sql_type == real_type() &&
|
||||||
new_field->charset == field_charset)
|
new_field->charset == field_charset)
|
||||||
@ -7621,7 +7622,7 @@ uint Field_blob::max_packed_col_length(uint max_length)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint Field_blob::is_equal(create_field *new_field)
|
uint Field_blob::is_equal(Create_field *new_field)
|
||||||
{
|
{
|
||||||
if (compare_str_field_flags(new_field, flags))
|
if (compare_str_field_flags(new_field, flags))
|
||||||
return 0;
|
return 0;
|
||||||
@ -8159,7 +8160,7 @@ bool Field_num::eq_def(Field *field)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint Field_num::is_equal(create_field *new_field)
|
uint Field_num::is_equal(Create_field *new_field)
|
||||||
{
|
{
|
||||||
return ((new_field->sql_type == real_type()) &&
|
return ((new_field->sql_type == real_type()) &&
|
||||||
((new_field->flags & UNSIGNED_FLAG) == (uint) (flags &
|
((new_field->flags & UNSIGNED_FLAG) == (uint) (flags &
|
||||||
@ -8264,7 +8265,7 @@ Field *Field_bit::new_key_field(MEM_ROOT *root,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint Field_bit::is_equal(create_field *new_field)
|
uint Field_bit::is_equal(Create_field *new_field)
|
||||||
{
|
{
|
||||||
return (new_field->sql_type == real_type() &&
|
return (new_field->sql_type == real_type() &&
|
||||||
new_field->length == max_display_length());
|
new_field->length == max_display_length());
|
||||||
@ -8595,20 +8596,20 @@ void Field_bit_as_char::sql_type(String &res) const
|
|||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
Handling of field and create_field
|
Handling of field and Create_field
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Convert create_field::length from number of characters to number of bytes
|
Convert Create_field::length from number of characters to number of bytes
|
||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
create_field::create_length_to_internal_length()
|
Create_field::create_length_to_internal_length()
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
Convert create_field::length from number of characters to number of bytes.
|
Convert Create_field::length from number of characters to number of bytes.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void create_field::create_length_to_internal_length(void)
|
void Create_field::create_length_to_internal_length(void)
|
||||||
{
|
{
|
||||||
switch (sql_type) {
|
switch (sql_type) {
|
||||||
case MYSQL_TYPE_TINY_BLOB:
|
case MYSQL_TYPE_TINY_BLOB:
|
||||||
@ -8655,7 +8656,7 @@ void create_field::create_length_to_internal_length(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void create_field::init_for_tmp_table(enum_field_types sql_type_arg,
|
void Create_field::init_for_tmp_table(enum_field_types sql_type_arg,
|
||||||
uint32 length_arg, uint32 decimals_arg,
|
uint32 length_arg, uint32 decimals_arg,
|
||||||
bool maybe_null, bool is_unsigned)
|
bool maybe_null, bool is_unsigned)
|
||||||
{
|
{
|
||||||
@ -8696,7 +8697,7 @@ void create_field::init_for_tmp_table(enum_field_types sql_type_arg,
|
|||||||
TRUE on error
|
TRUE on error
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool create_field::init(THD *thd, char *fld_name, enum_field_types fld_type,
|
bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type,
|
||||||
char *fld_length, char *fld_decimals,
|
char *fld_length, char *fld_decimals,
|
||||||
uint fld_type_modifier, Item *fld_default_value,
|
uint fld_type_modifier, Item *fld_default_value,
|
||||||
Item *fld_on_update_value, LEX_STRING *fld_comment,
|
Item *fld_on_update_value, LEX_STRING *fld_comment,
|
||||||
@ -8706,7 +8707,7 @@ bool create_field::init(THD *thd, char *fld_name, enum_field_types fld_type,
|
|||||||
uint sign_len, allowed_type_modifier= 0;
|
uint sign_len, allowed_type_modifier= 0;
|
||||||
ulong max_field_charlength= MAX_FIELD_CHARLENGTH;
|
ulong max_field_charlength= MAX_FIELD_CHARLENGTH;
|
||||||
|
|
||||||
DBUG_ENTER("create_field::init()");
|
DBUG_ENTER("Create_field::init()");
|
||||||
|
|
||||||
field= 0;
|
field= 0;
|
||||||
field_name= fld_name;
|
field_name= fld_name;
|
||||||
@ -8890,15 +8891,18 @@ bool create_field::init(THD *thd, char *fld_name, enum_field_types fld_type,
|
|||||||
break;
|
break;
|
||||||
case MYSQL_TYPE_TIMESTAMP:
|
case MYSQL_TYPE_TIMESTAMP:
|
||||||
if (!fld_length)
|
if (!fld_length)
|
||||||
length= 14; /* Full date YYYYMMDDHHMMSS */
|
{
|
||||||
else if (length != 19)
|
/* Compressed date YYYYMMDDHHMMSS */
|
||||||
|
length= MAX_DATETIME_COMPRESSED_WIDTH;
|
||||||
|
}
|
||||||
|
else if (length != MAX_DATETIME_WIDTH)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
We support only even TIMESTAMP lengths less or equal than 14
|
We support only even TIMESTAMP lengths less or equal than 14
|
||||||
and 19 as length of 4.1 compatible representation.
|
and 19 as length of 4.1 compatible representation.
|
||||||
*/
|
*/
|
||||||
length= ((length+1)/2)*2; /* purecov: inspected */
|
length= ((length+1)/2)*2; /* purecov: inspected */
|
||||||
length= min(length,14); /* purecov: inspected */
|
length= min(length, MAX_DATETIME_COMPRESSED_WIDTH); /* purecov: inspected */
|
||||||
}
|
}
|
||||||
flags|= ZEROFILL_FLAG | UNSIGNED_FLAG;
|
flags|= ZEROFILL_FLAG | UNSIGNED_FLAG;
|
||||||
if (fld_default_value)
|
if (fld_default_value)
|
||||||
@ -8951,7 +8955,7 @@ bool create_field::init(THD *thd, char *fld_name, enum_field_types fld_type,
|
|||||||
length= 10;
|
length= 10;
|
||||||
break;
|
break;
|
||||||
case MYSQL_TYPE_DATETIME:
|
case MYSQL_TYPE_DATETIME:
|
||||||
length= 19;
|
length= MAX_DATETIME_WIDTH;
|
||||||
break;
|
break;
|
||||||
case MYSQL_TYPE_SET:
|
case MYSQL_TYPE_SET:
|
||||||
{
|
{
|
||||||
@ -9279,7 +9283,7 @@ Field *make_field(TABLE_SHARE *share, uchar *ptr, uint32 field_length,
|
|||||||
|
|
||||||
/* Create a field suitable for create of table */
|
/* Create a field suitable for create of table */
|
||||||
|
|
||||||
create_field::create_field(Field *old_field,Field *orig_field)
|
Create_field::Create_field(Field *old_field,Field *orig_field)
|
||||||
{
|
{
|
||||||
field= old_field;
|
field= old_field;
|
||||||
field_name=change=old_field->field_name;
|
field_name=change=old_field->field_name;
|
||||||
|
32
sql/field.h
32
sql/field.h
@ -28,7 +28,7 @@
|
|||||||
|
|
||||||
class Send_field;
|
class Send_field;
|
||||||
class Protocol;
|
class Protocol;
|
||||||
class create_field;
|
class Create_field;
|
||||||
struct st_cache_field;
|
struct st_cache_field;
|
||||||
int field_conv(Field *to,Field *from);
|
int field_conv(Field *to,Field *from);
|
||||||
|
|
||||||
@ -413,7 +413,7 @@ public:
|
|||||||
/* maximum possible display length */
|
/* maximum possible display length */
|
||||||
virtual uint32 max_display_length()= 0;
|
virtual uint32 max_display_length()= 0;
|
||||||
|
|
||||||
virtual uint is_equal(create_field *new_field);
|
virtual uint is_equal(Create_field *new_field);
|
||||||
/* convert decimal to longlong with overflow check */
|
/* convert decimal to longlong with overflow check */
|
||||||
longlong convert_decimal2longlong(const my_decimal *val, bool unsigned_flag,
|
longlong convert_decimal2longlong(const my_decimal *val, bool unsigned_flag,
|
||||||
int *err);
|
int *err);
|
||||||
@ -474,14 +474,14 @@ public:
|
|||||||
Item_result result_type () const { return REAL_RESULT; }
|
Item_result result_type () const { return REAL_RESULT; }
|
||||||
void prepend_zeros(String *value);
|
void prepend_zeros(String *value);
|
||||||
void add_zerofill_and_unsigned(String &res) const;
|
void add_zerofill_and_unsigned(String &res) const;
|
||||||
friend class create_field;
|
friend class Create_field;
|
||||||
void make_field(Send_field *);
|
void make_field(Send_field *);
|
||||||
uint decimals() const { return (uint) dec; }
|
uint decimals() const { return (uint) dec; }
|
||||||
uint size_of() const { return sizeof(*this); }
|
uint size_of() const { return sizeof(*this); }
|
||||||
bool eq_def(Field *field);
|
bool eq_def(Field *field);
|
||||||
int store_decimal(const my_decimal *);
|
int store_decimal(const my_decimal *);
|
||||||
my_decimal *val_decimal(my_decimal *);
|
my_decimal *val_decimal(my_decimal *);
|
||||||
uint is_equal(create_field *new_field);
|
uint is_equal(Create_field *new_field);
|
||||||
int check_int(CHARSET_INFO *cs, const char *str, int length,
|
int check_int(CHARSET_INFO *cs, const char *str, int length,
|
||||||
const char *int_end, int error);
|
const char *int_end, int error);
|
||||||
bool get_int(CHARSET_INFO *cs, const char *from, uint len,
|
bool get_int(CHARSET_INFO *cs, const char *from, uint len,
|
||||||
@ -512,11 +512,11 @@ public:
|
|||||||
{ field_derivation= derivation_arg; }
|
{ field_derivation= derivation_arg; }
|
||||||
bool binary() const { return field_charset == &my_charset_bin; }
|
bool binary() const { return field_charset == &my_charset_bin; }
|
||||||
uint32 max_display_length() { return field_length; }
|
uint32 max_display_length() { return field_length; }
|
||||||
friend class create_field;
|
friend class Create_field;
|
||||||
my_decimal *val_decimal(my_decimal *);
|
my_decimal *val_decimal(my_decimal *);
|
||||||
virtual bool str_needs_quotes() { return TRUE; }
|
virtual bool str_needs_quotes() { return TRUE; }
|
||||||
bool compare_str_field_flags(create_field *new_field, uint32 flags);
|
bool compare_str_field_flags(Create_field *new_field, uint32 flags);
|
||||||
uint is_equal(create_field *new_field);
|
uint is_equal(Create_field *new_field);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -625,7 +625,7 @@ public:
|
|||||||
uint32 max_display_length() { return field_length; }
|
uint32 max_display_length() { return field_length; }
|
||||||
uint size_of() const { return sizeof(*this); }
|
uint size_of() const { return sizeof(*this); }
|
||||||
uint32 pack_length() const { return (uint32) bin_size; }
|
uint32 pack_length() const { return (uint32) bin_size; }
|
||||||
uint is_equal(create_field *new_field);
|
uint is_equal(Create_field *new_field);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -1257,7 +1257,7 @@ public:
|
|||||||
Field *new_key_field(MEM_ROOT *root, struct st_table *new_table,
|
Field *new_key_field(MEM_ROOT *root, struct st_table *new_table,
|
||||||
uchar *new_ptr, uchar *new_null_ptr,
|
uchar *new_ptr, uchar *new_null_ptr,
|
||||||
uint new_null_bit);
|
uint new_null_bit);
|
||||||
uint is_equal(create_field *new_field);
|
uint is_equal(Create_field *new_field);
|
||||||
void hash(ulong *nr, ulong *nr2);
|
void hash(ulong *nr, ulong *nr2);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1391,7 +1391,7 @@ public:
|
|||||||
bool has_charset(void) const
|
bool has_charset(void) const
|
||||||
{ return charset() == &my_charset_bin ? FALSE : TRUE; }
|
{ return charset() == &my_charset_bin ? FALSE : TRUE; }
|
||||||
uint32 max_display_length();
|
uint32 max_display_length();
|
||||||
uint is_equal(create_field *new_field);
|
uint is_equal(Create_field *new_field);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -1570,7 +1570,7 @@ public:
|
|||||||
bit_ptr == ((Field_bit *)field)->bit_ptr &&
|
bit_ptr == ((Field_bit *)field)->bit_ptr &&
|
||||||
bit_ofs == ((Field_bit *)field)->bit_ofs);
|
bit_ofs == ((Field_bit *)field)->bit_ofs);
|
||||||
}
|
}
|
||||||
uint is_equal(create_field *new_field);
|
uint is_equal(Create_field *new_field);
|
||||||
void move_field_offset(my_ptrdiff_t ptr_diff)
|
void move_field_offset(my_ptrdiff_t ptr_diff)
|
||||||
{
|
{
|
||||||
Field::move_field_offset(ptr_diff);
|
Field::move_field_offset(ptr_diff);
|
||||||
@ -1608,7 +1608,7 @@ public:
|
|||||||
Create field class for CREATE TABLE
|
Create field class for CREATE TABLE
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class create_field :public Sql_alloc
|
class Create_field :public Sql_alloc
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
const char *field_name;
|
const char *field_name;
|
||||||
@ -1639,11 +1639,11 @@ public:
|
|||||||
|
|
||||||
uint8 row,col,sc_length,interval_id; // For rea_create_table
|
uint8 row,col,sc_length,interval_id; // For rea_create_table
|
||||||
uint offset,pack_flag;
|
uint offset,pack_flag;
|
||||||
create_field() :after(0) {}
|
Create_field() :after(0) {}
|
||||||
create_field(Field *field, Field *orig_field);
|
Create_field(Field *field, Field *orig_field);
|
||||||
/* Used to make a clone of this object for ALTER/CREATE TABLE */
|
/* Used to make a clone of this object for ALTER/CREATE TABLE */
|
||||||
create_field *clone(MEM_ROOT *mem_root) const
|
Create_field *clone(MEM_ROOT *mem_root) const
|
||||||
{ return new (mem_root) create_field(*this); }
|
{ return new (mem_root) Create_field(*this); }
|
||||||
void create_length_to_internal_length(void);
|
void create_length_to_internal_length(void);
|
||||||
|
|
||||||
/* Init for a tmp table field. To be extended if need be. */
|
/* Init for a tmp table field. To be extended if need be. */
|
||||||
|
@ -3376,8 +3376,8 @@ TYPELIB *ha_known_exts(void)
|
|||||||
const char **ext, *old_ext;
|
const char **ext, *old_ext;
|
||||||
|
|
||||||
known_extensions_id= mysys_usage_id;
|
known_extensions_id= mysys_usage_id;
|
||||||
found_exts.push_back((char*) triggers_file_ext);
|
found_exts.push_back((char*) TRG_EXT);
|
||||||
found_exts.push_back((char*) trigname_file_ext);
|
found_exts.push_back((char*) TRN_EXT);
|
||||||
|
|
||||||
plugin_foreach(NULL, exts_handlerton,
|
plugin_foreach(NULL, exts_handlerton,
|
||||||
MYSQL_STORAGE_ENGINE_PLUGIN, &found_exts);
|
MYSQL_STORAGE_ENGINE_PLUGIN, &found_exts);
|
||||||
|
@ -1768,7 +1768,7 @@ public:
|
|||||||
We have to have a different max_length than 'length' here to
|
We have to have a different max_length than 'length' here to
|
||||||
ensure that we get the right length if we do use the item
|
ensure that we get the right length if we do use the item
|
||||||
to create a new table. In this case max_length must be the maximum
|
to create a new table. In this case max_length must be the maximum
|
||||||
number of chars for a string of this type because we in create_field::
|
number of chars for a string of this type because we in Create_field::
|
||||||
divide the max_length with mbmaxlen).
|
divide the max_length with mbmaxlen).
|
||||||
*/
|
*/
|
||||||
max_length= str_value.numchars()*cs->mbmaxlen;
|
max_length= str_value.numchars()*cs->mbmaxlen;
|
||||||
|
@ -912,8 +912,8 @@ void Item_sum_distinct::fix_length_and_dec()
|
|||||||
|
|
||||||
bool Item_sum_distinct::setup(THD *thd)
|
bool Item_sum_distinct::setup(THD *thd)
|
||||||
{
|
{
|
||||||
List<create_field> field_list;
|
List<Create_field> field_list;
|
||||||
create_field field_def; /* field definition */
|
Create_field field_def; /* field definition */
|
||||||
DBUG_ENTER("Item_sum_distinct::setup");
|
DBUG_ENTER("Item_sum_distinct::setup");
|
||||||
DBUG_ASSERT(tree == 0);
|
DBUG_ASSERT(tree == 0);
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ static bool make_datetime(date_time_format_types format, MYSQL_TIME *ltime,
|
|||||||
{
|
{
|
||||||
char *buff;
|
char *buff;
|
||||||
CHARSET_INFO *cs= &my_charset_bin;
|
CHARSET_INFO *cs= &my_charset_bin;
|
||||||
uint length= 30;
|
uint length= MAX_DATE_STRING_REP_LENGTH;
|
||||||
|
|
||||||
if (str->alloc(length))
|
if (str->alloc(length))
|
||||||
return 1;
|
return 1;
|
||||||
@ -1379,7 +1379,7 @@ String *Item_date::val_str(String *str)
|
|||||||
MYSQL_TIME ltime;
|
MYSQL_TIME ltime;
|
||||||
if (get_date(<ime, TIME_FUZZY_DATE))
|
if (get_date(<ime, TIME_FUZZY_DATE))
|
||||||
return (String *) 0;
|
return (String *) 0;
|
||||||
if (str->alloc(11))
|
if (str->alloc(MAX_DATE_STRING_REP_LENGTH))
|
||||||
{
|
{
|
||||||
null_value= 1;
|
null_value= 1;
|
||||||
return (String *) 0;
|
return (String *) 0;
|
||||||
@ -1428,7 +1428,7 @@ void Item_func_curdate::fix_length_and_dec()
|
|||||||
String *Item_func_curdate::val_str(String *str)
|
String *Item_func_curdate::val_str(String *str)
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 1);
|
DBUG_ASSERT(fixed == 1);
|
||||||
if (str->alloc(11))
|
if (str->alloc(MAX_DATE_STRING_REP_LENGTH))
|
||||||
{
|
{
|
||||||
null_value= 1;
|
null_value= 1;
|
||||||
return (String *) 0;
|
return (String *) 0;
|
||||||
@ -1657,7 +1657,8 @@ String *Item_func_sec_to_time::val_str(String *str)
|
|||||||
MYSQL_TIME ltime;
|
MYSQL_TIME ltime;
|
||||||
longlong arg_val= args[0]->val_int();
|
longlong arg_val= args[0]->val_int();
|
||||||
|
|
||||||
if ((null_value=args[0]->null_value) || str->alloc(19))
|
if ((null_value=args[0]->null_value) ||
|
||||||
|
str->alloc(MAX_DATE_STRING_REP_LENGTH))
|
||||||
{
|
{
|
||||||
null_value= 1;
|
null_value= 1;
|
||||||
return (String*) 0;
|
return (String*) 0;
|
||||||
@ -1842,6 +1843,10 @@ String *Item_func_date_format::val_str(String *str)
|
|||||||
size=max_length;
|
size=max_length;
|
||||||
else
|
else
|
||||||
size=format_length(format);
|
size=format_length(format);
|
||||||
|
|
||||||
|
if (size < MAX_DATE_STRING_REP_LENGTH)
|
||||||
|
size= MAX_DATE_STRING_REP_LENGTH;
|
||||||
|
|
||||||
if (format == str)
|
if (format == str)
|
||||||
str= &value; // Save result here
|
str= &value; // Save result here
|
||||||
if (str->alloc(size))
|
if (str->alloc(size))
|
||||||
@ -1885,13 +1890,14 @@ String *Item_func_from_unixtime::val_str(String *str)
|
|||||||
if (get_date(&time_tmp, 0))
|
if (get_date(&time_tmp, 0))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (str->alloc(20*MY_CHARSET_BIN_MB_MAXLEN))
|
if (str->alloc(MAX_DATE_STRING_REP_LENGTH))
|
||||||
{
|
{
|
||||||
null_value= 1;
|
null_value= 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
make_datetime((DATE_TIME_FORMAT *) 0, &time_tmp, str);
|
make_datetime((DATE_TIME_FORMAT *) 0, &time_tmp, str);
|
||||||
|
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1941,13 +1947,14 @@ String *Item_func_convert_tz::val_str(String *str)
|
|||||||
if (get_date(&time_tmp, 0))
|
if (get_date(&time_tmp, 0))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (str->alloc(20*MY_CHARSET_BIN_MB_MAXLEN))
|
if (str->alloc(MAX_DATE_STRING_REP_LENGTH))
|
||||||
{
|
{
|
||||||
null_value= 1;
|
null_value= 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
make_datetime((DATE_TIME_FORMAT *) 0, &time_tmp, str);
|
make_datetime((DATE_TIME_FORMAT *) 0, &time_tmp, str);
|
||||||
|
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2433,6 +2440,7 @@ String *Item_datetime_typecast::val_str(String *str)
|
|||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 1);
|
DBUG_ASSERT(fixed == 1);
|
||||||
MYSQL_TIME ltime;
|
MYSQL_TIME ltime;
|
||||||
|
|
||||||
if (!get_arg0_date(<ime, TIME_FUZZY_DATE) &&
|
if (!get_arg0_date(<ime, TIME_FUZZY_DATE) &&
|
||||||
!make_datetime(ltime.second_part ? DATE_TIME_MICROSECOND : DATE_TIME,
|
!make_datetime(ltime.second_part ? DATE_TIME_MICROSECOND : DATE_TIME,
|
||||||
<ime, str))
|
<ime, str))
|
||||||
@ -2511,7 +2519,8 @@ String *Item_date_typecast::val_str(String *str)
|
|||||||
DBUG_ASSERT(fixed == 1);
|
DBUG_ASSERT(fixed == 1);
|
||||||
MYSQL_TIME ltime;
|
MYSQL_TIME ltime;
|
||||||
|
|
||||||
if (!get_arg0_date(<ime, TIME_FUZZY_DATE) && !str->alloc(11))
|
if (!get_arg0_date(<ime, TIME_FUZZY_DATE) &&
|
||||||
|
!str->alloc(MAX_DATE_STRING_REP_LENGTH))
|
||||||
{
|
{
|
||||||
make_date((DATE_TIME_FORMAT *) 0, <ime, str);
|
make_date((DATE_TIME_FORMAT *) 0, <ime, str);
|
||||||
return str;
|
return str;
|
||||||
@ -2564,7 +2573,7 @@ String *Item_func_makedate::val_str(String *str)
|
|||||||
{
|
{
|
||||||
null_value=0;
|
null_value=0;
|
||||||
get_date_from_daynr(days,&l_time.year,&l_time.month,&l_time.day);
|
get_date_from_daynr(days,&l_time.year,&l_time.month,&l_time.day);
|
||||||
if (str->alloc(11))
|
if (str->alloc(MAX_DATE_STRING_REP_LENGTH))
|
||||||
goto err;
|
goto err;
|
||||||
make_date((DATE_TIME_FORMAT *) 0, &l_time, str);
|
make_date((DATE_TIME_FORMAT *) 0, &l_time, str);
|
||||||
return str;
|
return str;
|
||||||
@ -2700,6 +2709,7 @@ String *Item_func_add_time::val_str(String *str)
|
|||||||
days= (long)(seconds/86400L);
|
days= (long)(seconds/86400L);
|
||||||
|
|
||||||
calc_time_from_sec(&l_time3, (long)(seconds%86400L), microseconds);
|
calc_time_from_sec(&l_time3, (long)(seconds%86400L), microseconds);
|
||||||
|
|
||||||
if (!is_time)
|
if (!is_time)
|
||||||
{
|
{
|
||||||
get_date_from_daynr(days,&l_time3.year,&l_time3.month,&l_time3.day);
|
get_date_from_daynr(days,&l_time3.year,&l_time3.month,&l_time3.day);
|
||||||
@ -2815,7 +2825,7 @@ String *Item_func_maketime::val_str(String *str)
|
|||||||
args[2]->null_value ||
|
args[2]->null_value ||
|
||||||
minute < 0 || minute > 59 ||
|
minute < 0 || minute > 59 ||
|
||||||
second < 0 || second > 59 ||
|
second < 0 || second > 59 ||
|
||||||
str->alloc(19))))
|
str->alloc(MAX_DATE_STRING_REP_LENGTH))))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
bzero((char *)<ime, sizeof(ltime));
|
bzero((char *)<ime, sizeof(ltime));
|
||||||
|
11
sql/log.cc
11
sql/log.cc
@ -307,6 +307,9 @@ bool Log_to_csv_event_handler::open_log_table(uint log_table_type)
|
|||||||
table->table->use_all_columns();
|
table->table->use_all_columns();
|
||||||
table->table->locked_by_logger= TRUE;
|
table->table->locked_by_logger= TRUE;
|
||||||
table->table->no_replicate= TRUE;
|
table->table->no_replicate= TRUE;
|
||||||
|
|
||||||
|
/* Honor next number columns if present */
|
||||||
|
table->table->next_number_field= table->table->found_next_number_field;
|
||||||
}
|
}
|
||||||
/* restore thread settings */
|
/* restore thread settings */
|
||||||
if (curr)
|
if (curr)
|
||||||
@ -440,6 +443,7 @@ bool Log_to_csv_event_handler::
|
|||||||
CHARSET_INFO *client_cs)
|
CHARSET_INFO *client_cs)
|
||||||
{
|
{
|
||||||
TABLE *table= general_log.table;
|
TABLE *table= general_log.table;
|
||||||
|
uint field_index;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
"INSERT INTO general_log" can generate warning sometimes.
|
"INSERT INTO general_log" can generate warning sometimes.
|
||||||
@ -490,6 +494,12 @@ bool Log_to_csv_event_handler::
|
|||||||
table->field[4]->set_notnull();
|
table->field[4]->set_notnull();
|
||||||
table->field[5]->set_notnull();
|
table->field[5]->set_notnull();
|
||||||
|
|
||||||
|
/* Set any extra columns to their default values */
|
||||||
|
for (field_index= 6 ; field_index < table->s->fields ; field_index++)
|
||||||
|
{
|
||||||
|
table->field[field_index]->set_default();
|
||||||
|
}
|
||||||
|
|
||||||
/* log table entries are not replicated at the moment */
|
/* log table entries are not replicated at the moment */
|
||||||
tmp_disable_binlog(current_thd);
|
tmp_disable_binlog(current_thd);
|
||||||
|
|
||||||
@ -1331,6 +1341,7 @@ void Log_to_csv_event_handler::
|
|||||||
/* close the table */
|
/* close the table */
|
||||||
log_thd->store_globals();
|
log_thd->store_globals();
|
||||||
table->table->file->ha_rnd_end();
|
table->table->file->ha_rnd_end();
|
||||||
|
table->table->file->ha_release_auto_increment();
|
||||||
/* discard logger mark before unlock*/
|
/* discard logger mark before unlock*/
|
||||||
table->table->locked_by_logger= FALSE;
|
table->table->locked_by_logger= FALSE;
|
||||||
close_thread_tables(log_thd, lock_in_use);
|
close_thread_tables(log_thd, lock_in_use);
|
||||||
|
@ -101,7 +101,7 @@ char* query_table_status(THD *thd,const char *db,const char *table_name);
|
|||||||
ER_WARN_DEPRECATED_SYNTAX, ER(ER_WARN_DEPRECATED_SYNTAX), \
|
ER_WARN_DEPRECATED_SYNTAX, ER(ER_WARN_DEPRECATED_SYNTAX), \
|
||||||
(Old), (Ver), (New)); \
|
(Old), (Ver), (New)); \
|
||||||
else \
|
else \
|
||||||
sql_print_warning("The syntax %s is deprecated and will be removed " \
|
sql_print_warning("The syntax '%s' is deprecated and will be removed " \
|
||||||
"in MySQL %s. Please use %s instead.", (Old), (Ver), (New)); \
|
"in MySQL %s. Please use %s instead.", (Old), (Ver), (New)); \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
@ -618,6 +618,8 @@ bool check_string_char_length(LEX_STRING *str, const char *err_msg,
|
|||||||
uint max_char_length, CHARSET_INFO *cs,
|
uint max_char_length, CHARSET_INFO *cs,
|
||||||
bool no_error);
|
bool no_error);
|
||||||
|
|
||||||
|
bool parse_sql(THD *thd, class Lex_input_stream *lip);
|
||||||
|
|
||||||
enum enum_mysql_completiontype {
|
enum enum_mysql_completiontype {
|
||||||
ROLLBACK_RELEASE=-2, ROLLBACK=1, ROLLBACK_AND_CHAIN=7,
|
ROLLBACK_RELEASE=-2, ROLLBACK=1, ROLLBACK_AND_CHAIN=7,
|
||||||
COMMIT_RELEASE=-1, COMMIT=0, COMMIT_AND_CHAIN=6
|
COMMIT_RELEASE=-1, COMMIT=0, COMMIT_AND_CHAIN=6
|
||||||
@ -908,7 +910,7 @@ bool mysql_assign_to_keycache(THD* thd, TABLE_LIST* table_list,
|
|||||||
bool mysql_preload_keys(THD* thd, TABLE_LIST* table_list);
|
bool mysql_preload_keys(THD* thd, TABLE_LIST* table_list);
|
||||||
int reassign_keycache_tables(THD* thd, KEY_CACHE *src_cache,
|
int reassign_keycache_tables(THD* thd, KEY_CACHE *src_cache,
|
||||||
KEY_CACHE *dst_cache);
|
KEY_CACHE *dst_cache);
|
||||||
TABLE *create_virtual_tmp_table(THD *thd, List<create_field> &field_list);
|
TABLE *create_virtual_tmp_table(THD *thd, List<Create_field> &field_list);
|
||||||
|
|
||||||
bool mysql_xa_recover(THD *thd);
|
bool mysql_xa_recover(THD *thd);
|
||||||
|
|
||||||
@ -952,8 +954,8 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
|
|||||||
bool table_cant_handle_bit_fields,
|
bool table_cant_handle_bit_fields,
|
||||||
bool make_copy_field,
|
bool make_copy_field,
|
||||||
uint convert_blob_length);
|
uint convert_blob_length);
|
||||||
void sp_prepare_create_field(THD *thd, create_field *sql_field);
|
void sp_prepare_create_field(THD *thd, Create_field *sql_field);
|
||||||
int prepare_create_field(create_field *sql_field,
|
int prepare_create_field(Create_field *sql_field,
|
||||||
uint *blob_columns,
|
uint *blob_columns,
|
||||||
int *timestamps, int *timestamps_with_niladic,
|
int *timestamps, int *timestamps_with_niladic,
|
||||||
longlong table_flags);
|
longlong table_flags);
|
||||||
@ -1178,7 +1180,7 @@ bool add_field_to_list(THD *thd, LEX_STRING *field_name, enum enum_field_types t
|
|||||||
char *change, List<String> *interval_list,
|
char *change, List<String> *interval_list,
|
||||||
CHARSET_INFO *cs,
|
CHARSET_INFO *cs,
|
||||||
uint uint_geom_type);
|
uint uint_geom_type);
|
||||||
create_field * new_create_field(THD *thd, char *field_name, enum_field_types type,
|
Create_field * new_create_field(THD *thd, char *field_name, enum_field_types type,
|
||||||
char *length, char *decimals,
|
char *length, char *decimals,
|
||||||
uint type_modifier,
|
uint type_modifier,
|
||||||
Item *default_value, Item *on_update_value,
|
Item *default_value, Item *on_update_value,
|
||||||
@ -1588,6 +1590,7 @@ bool check_db_dir_existence(const char *db_name);
|
|||||||
bool load_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create);
|
bool load_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create);
|
||||||
bool load_db_opt_by_name(THD *thd, const char *db_name,
|
bool load_db_opt_by_name(THD *thd, const char *db_name,
|
||||||
HA_CREATE_INFO *db_create_info);
|
HA_CREATE_INFO *db_create_info);
|
||||||
|
CHARSET_INFO *get_default_db_collation(THD *thd, const char *db_name);
|
||||||
bool my_dbopt_init(void);
|
bool my_dbopt_init(void);
|
||||||
void my_dbopt_cleanup(void);
|
void my_dbopt_cleanup(void);
|
||||||
extern int creating_database; // How many database locks are made
|
extern int creating_database; // How many database locks are made
|
||||||
@ -1609,8 +1612,8 @@ extern const char *first_keyword, *my_localhost, *delayed_user, *binary_keyword;
|
|||||||
extern const char **errmesg; /* Error messages */
|
extern const char **errmesg; /* Error messages */
|
||||||
extern const char *myisam_recover_options_str;
|
extern const char *myisam_recover_options_str;
|
||||||
extern const char *in_left_expr_name, *in_additional_cond, *in_having_cond;
|
extern const char *in_left_expr_name, *in_additional_cond, *in_having_cond;
|
||||||
extern const char * const triggers_file_ext;
|
extern const char * const TRG_EXT;
|
||||||
extern const char * const trigname_file_ext;
|
extern const char * const TRN_EXT;
|
||||||
extern Eq_creator eq_creator;
|
extern Eq_creator eq_creator;
|
||||||
extern Ne_creator ne_creator;
|
extern Ne_creator ne_creator;
|
||||||
extern Gt_creator gt_creator;
|
extern Gt_creator gt_creator;
|
||||||
@ -1805,12 +1808,12 @@ void unireg_end(void) __attribute__((noreturn));
|
|||||||
bool mysql_create_frm(THD *thd, const char *file_name,
|
bool mysql_create_frm(THD *thd, const char *file_name,
|
||||||
const char *db, const char *table,
|
const char *db, const char *table,
|
||||||
HA_CREATE_INFO *create_info,
|
HA_CREATE_INFO *create_info,
|
||||||
List<create_field> &create_field,
|
List<Create_field> &create_field,
|
||||||
uint key_count,KEY *key_info,handler *db_type);
|
uint key_count,KEY *key_info,handler *db_type);
|
||||||
int rea_create_table(THD *thd, const char *path,
|
int rea_create_table(THD *thd, const char *path,
|
||||||
const char *db, const char *table_name,
|
const char *db, const char *table_name,
|
||||||
HA_CREATE_INFO *create_info,
|
HA_CREATE_INFO *create_info,
|
||||||
List<create_field> &create_field,
|
List<Create_field> &create_field,
|
||||||
uint key_count,KEY *key_info,
|
uint key_count,KEY *key_info,
|
||||||
handler *file);
|
handler *file);
|
||||||
int format_number(uint inputflag,uint max_length,char * pos,uint length,
|
int format_number(uint inputflag,uint max_length,char * pos,uint length,
|
||||||
@ -1961,7 +1964,6 @@ void free_list(I_List <i_string_pair> *list);
|
|||||||
void free_list(I_List <i_string> *list);
|
void free_list(I_List <i_string> *list);
|
||||||
|
|
||||||
/* sql_yacc.cc */
|
/* sql_yacc.cc */
|
||||||
extern int MYSQLparse(void *thd);
|
|
||||||
#ifndef DBUG_OFF
|
#ifndef DBUG_OFF
|
||||||
extern void turn_parser_debug_on();
|
extern void turn_parser_debug_on();
|
||||||
#endif
|
#endif
|
||||||
@ -2153,6 +2155,12 @@ bool schema_table_store_record(THD *thd, TABLE *table);
|
|||||||
int item_create_init();
|
int item_create_init();
|
||||||
void item_create_cleanup();
|
void item_create_cleanup();
|
||||||
|
|
||||||
|
inline void lex_string_set(LEX_STRING *lex_str, const char *c_str)
|
||||||
|
{
|
||||||
|
lex_str->str= (char *) c_str;
|
||||||
|
lex_str->length= strlen(c_str);
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* MYSQL_SERVER */
|
#endif /* MYSQL_SERVER */
|
||||||
#endif /* MYSQL_CLIENT */
|
#endif /* MYSQL_CLIENT */
|
||||||
|
|
||||||
|
22
sql/sp.cc
22
sql/sp.cc
@ -384,15 +384,13 @@ db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp,
|
|||||||
if ((ret= sp_use_new_db(thd, name->m_db, &old_db, 1, &dbchanged)))
|
if ((ret= sp_use_new_db(thd, name->m_db, &old_db, 1, &dbchanged)))
|
||||||
goto end;
|
goto end;
|
||||||
|
|
||||||
|
thd->spcont= NULL;
|
||||||
|
|
||||||
{
|
{
|
||||||
Lex_input_stream lip(thd, defstr.c_ptr(), defstr.length());
|
Lex_input_stream lip(thd, defstr.c_ptr(), defstr.length());
|
||||||
thd->m_lip= &lip;
|
|
||||||
lex_start(thd);
|
lex_start(thd);
|
||||||
ret= MYSQLparse(thd);
|
|
||||||
}
|
|
||||||
|
|
||||||
thd->spcont= 0;
|
if (parse_sql(thd, &lip) || newlex.sphead == NULL)
|
||||||
if (ret || thd->is_fatal_error || newlex.sphead == NULL)
|
|
||||||
{
|
{
|
||||||
sp_head *sp= newlex.sphead;
|
sp_head *sp= newlex.sphead;
|
||||||
|
|
||||||
@ -410,6 +408,8 @@ db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp,
|
|||||||
(*sphp)->set_info(created, modified, &chistics, sql_mode);
|
(*sphp)->set_info(created, modified, &chistics, sql_mode);
|
||||||
(*sphp)->optimize();
|
(*sphp)->optimize();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
end:
|
end:
|
||||||
lex_end(thd->lex);
|
lex_end(thd->lex);
|
||||||
thd->spcont= old_spcont;
|
thd->spcont= old_spcont;
|
||||||
@ -588,10 +588,14 @@ sp_create_routine(THD *thd, int type, sp_head *sp)
|
|||||||
log_query.append(STRING_WITH_LEN("CREATE "));
|
log_query.append(STRING_WITH_LEN("CREATE "));
|
||||||
append_definer(thd, &log_query, &thd->lex->definer->user,
|
append_definer(thd, &log_query, &thd->lex->definer->user,
|
||||||
&thd->lex->definer->host);
|
&thd->lex->definer->host);
|
||||||
log_query.append(thd->lex->stmt_definition_begin,
|
|
||||||
(char *)sp->m_body_begin -
|
LEX_STRING stmt_definition;
|
||||||
thd->lex->stmt_definition_begin +
|
stmt_definition.str= (char*) thd->lex->stmt_definition_begin;
|
||||||
sp->m_body.length);
|
stmt_definition.length= thd->lex->stmt_definition_end
|
||||||
|
- thd->lex->stmt_definition_begin;
|
||||||
|
trim_whitespace(thd->charset(), & stmt_definition);
|
||||||
|
|
||||||
|
log_query.append(stmt_definition.str, stmt_definition.length);
|
||||||
|
|
||||||
/* Such a statement can always go directly to binlog, no trans cache */
|
/* Such a statement can always go directly to binlog, no trans cache */
|
||||||
thd->binlog_query(THD::MYSQL_QUERY_TYPE,
|
thd->binlog_query(THD::MYSQL_QUERY_TYPE,
|
||||||
|
116
sql/sp_head.cc
116
sql/sp_head.cc
@ -564,24 +564,23 @@ sp_head::init_strings(THD *thd, LEX *lex)
|
|||||||
m_params.str= strmake_root(root, m_param_begin, m_params.length);
|
m_params.str= strmake_root(root, m_param_begin, m_params.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If ptr has overrun end_of_query then end_of_query is the end */
|
endp= lip->get_cpp_ptr();
|
||||||
endp= (lip->ptr > lip->end_of_query ? lip->end_of_query : lip->ptr);
|
lex->stmt_definition_end= endp;
|
||||||
/*
|
|
||||||
Trim "garbage" at the end. This is sometimes needed with the
|
|
||||||
"/ * ! VERSION... * /" wrapper in dump files.
|
|
||||||
*/
|
|
||||||
endp= skip_rear_comments(thd->charset(), m_body_begin, endp);
|
|
||||||
|
|
||||||
m_body.length= endp - m_body_begin;
|
m_body.length= endp - m_body_begin;
|
||||||
m_body.str= strmake_root(root, m_body_begin, m_body.length);
|
m_body.str= strmake_root(root, m_body_begin, m_body.length);
|
||||||
m_defstr.length= endp - lip->buf;
|
trim_whitespace(thd->charset(), & m_body);
|
||||||
m_defstr.str= strmake_root(root, lip->buf, m_defstr.length);
|
|
||||||
|
m_defstr.length= endp - lip->get_cpp_buf();
|
||||||
|
m_defstr.str= strmake_root(root, lip->get_cpp_buf(), m_defstr.length);
|
||||||
|
trim_whitespace(thd->charset(), & m_defstr);
|
||||||
|
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static TYPELIB *
|
static TYPELIB *
|
||||||
create_typelib(MEM_ROOT *mem_root, create_field *field_def, List<String> *src)
|
create_typelib(MEM_ROOT *mem_root, Create_field *field_def, List<String> *src)
|
||||||
{
|
{
|
||||||
TYPELIB *result= NULL;
|
TYPELIB *result= NULL;
|
||||||
CHARSET_INFO *cs= field_def->charset;
|
CHARSET_INFO *cs= field_def->charset;
|
||||||
@ -1269,30 +1268,31 @@ set_routine_security_ctx(THD *thd, sp_head *sp, bool is_proc,
|
|||||||
#endif // ! NO_EMBEDDED_ACCESS_CHECKS
|
#endif // ! NO_EMBEDDED_ACCESS_CHECKS
|
||||||
|
|
||||||
|
|
||||||
/*
|
/**
|
||||||
|
Execute trigger stored program.
|
||||||
|
|
||||||
Execute a trigger:
|
Execute a trigger:
|
||||||
- changes security context for triggers
|
- changes security context for triggers;
|
||||||
- switch to new memroot
|
- switch to new memroot;
|
||||||
- call sp_head::execute
|
- call sp_head::execute;
|
||||||
- restore old memroot
|
- restore old memroot;
|
||||||
- restores security context
|
- restores security context.
|
||||||
|
|
||||||
SYNOPSIS
|
@param thd Thread context.
|
||||||
sp_head::execute_trigger()
|
@param db_name Database name.
|
||||||
thd Thread handle
|
@param table_name Table name.
|
||||||
db database name
|
@param grant_info GRANT_INFO structure to be filled with information
|
||||||
table table name
|
about definer's privileges on subject table.
|
||||||
grant_info GRANT_INFO structure to be filled with
|
|
||||||
information about definer's privileges
|
|
||||||
on subject table
|
|
||||||
|
|
||||||
RETURN
|
@return Error status.
|
||||||
FALSE on success
|
@retval FALSE on success.
|
||||||
TRUE on error
|
@retval TRUE on error.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool
|
bool
|
||||||
sp_head::execute_trigger(THD *thd, const char *db, const char *table,
|
sp_head::execute_trigger(THD *thd,
|
||||||
|
const LEX_STRING *db_name,
|
||||||
|
const LEX_STRING *table_name,
|
||||||
GRANT_INFO *grant_info)
|
GRANT_INFO *grant_info)
|
||||||
{
|
{
|
||||||
sp_rcontext *octx = thd->spcont;
|
sp_rcontext *octx = thd->spcont;
|
||||||
@ -1305,6 +1305,46 @@ sp_head::execute_trigger(THD *thd, const char *db, const char *table,
|
|||||||
DBUG_ENTER("sp_head::execute_trigger");
|
DBUG_ENTER("sp_head::execute_trigger");
|
||||||
DBUG_PRINT("info", ("trigger %s", m_name.str));
|
DBUG_PRINT("info", ("trigger %s", m_name.str));
|
||||||
|
|
||||||
|
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||||
|
Security_context *save_ctx= NULL;
|
||||||
|
|
||||||
|
|
||||||
|
if (m_chistics->suid != SP_IS_NOT_SUID &&
|
||||||
|
m_security_ctx.change_security_context(thd,
|
||||||
|
&m_definer_user,
|
||||||
|
&m_definer_host,
|
||||||
|
&m_db,
|
||||||
|
&save_ctx))
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Fetch information about table-level privileges for subject table into
|
||||||
|
GRANT_INFO instance. The access check itself will happen in
|
||||||
|
Item_trigger_field, where this information will be used along with
|
||||||
|
information about column-level privileges.
|
||||||
|
*/
|
||||||
|
|
||||||
|
fill_effective_table_privileges(thd,
|
||||||
|
grant_info,
|
||||||
|
db_name->str,
|
||||||
|
table_name->str);
|
||||||
|
|
||||||
|
/* Check that the definer has TRIGGER privilege on the subject table. */
|
||||||
|
|
||||||
|
if (!(grant_info->privilege & TRIGGER_ACL))
|
||||||
|
{
|
||||||
|
char priv_desc[128];
|
||||||
|
get_privilege_desc(priv_desc, sizeof(priv_desc), TRIGGER_ACL);
|
||||||
|
|
||||||
|
my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0), priv_desc,
|
||||||
|
thd->security_ctx->priv_user, thd->security_ctx->host_or_ip,
|
||||||
|
table_name->str);
|
||||||
|
|
||||||
|
m_security_ctx.restore_security_context(thd, save_ctx);
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
#endif // NO_EMBEDDED_ACCESS_CHECKS
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Prepare arena and memroot for objects which lifetime is whole
|
Prepare arena and memroot for objects which lifetime is whole
|
||||||
duration of trigger call (sp_rcontext, it's tables and items,
|
duration of trigger call (sp_rcontext, it's tables and items,
|
||||||
@ -1337,6 +1377,11 @@ sp_head::execute_trigger(THD *thd, const char *db, const char *table,
|
|||||||
|
|
||||||
err_with_cleanup:
|
err_with_cleanup:
|
||||||
thd->restore_active_arena(&call_arena, &backup_arena);
|
thd->restore_active_arena(&call_arena, &backup_arena);
|
||||||
|
|
||||||
|
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||||
|
m_security_ctx.restore_security_context(thd, save_ctx);
|
||||||
|
#endif // NO_EMBEDDED_ACCESS_CHECKS
|
||||||
|
|
||||||
delete nctx;
|
delete nctx;
|
||||||
call_arena.free_items();
|
call_arena.free_items();
|
||||||
free_root(&call_mem_root, MYF(0));
|
free_root(&call_mem_root, MYF(0));
|
||||||
@ -1827,8 +1872,6 @@ sp_head::reset_lex(THD *thd)
|
|||||||
sublex->trg_table_fields.empty();
|
sublex->trg_table_fields.empty();
|
||||||
sublex->sp_lex_in_use= FALSE;
|
sublex->sp_lex_in_use= FALSE;
|
||||||
|
|
||||||
sublex->in_comment= oldlex->in_comment;
|
|
||||||
|
|
||||||
/* Reset type info. */
|
/* Reset type info. */
|
||||||
|
|
||||||
sublex->charset= NULL;
|
sublex->charset= NULL;
|
||||||
@ -1908,7 +1951,7 @@ sp_head::backpatch(sp_label_t *lab)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Prepare an instance of create_field for field creation (fill all necessary
|
Prepare an instance of Create_field for field creation (fill all necessary
|
||||||
attributes).
|
attributes).
|
||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
@ -1916,7 +1959,7 @@ sp_head::backpatch(sp_label_t *lab)
|
|||||||
thd [IN] Thread handle
|
thd [IN] Thread handle
|
||||||
lex [IN] Yacc parsing context
|
lex [IN] Yacc parsing context
|
||||||
field_type [IN] Field type
|
field_type [IN] Field type
|
||||||
field_def [OUT] An instance of create_field to be filled
|
field_def [OUT] An instance of Create_field to be filled
|
||||||
|
|
||||||
RETURN
|
RETURN
|
||||||
FALSE on success
|
FALSE on success
|
||||||
@ -1926,7 +1969,7 @@ sp_head::backpatch(sp_label_t *lab)
|
|||||||
bool
|
bool
|
||||||
sp_head::fill_field_definition(THD *thd, LEX *lex,
|
sp_head::fill_field_definition(THD *thd, LEX *lex,
|
||||||
enum enum_field_types field_type,
|
enum enum_field_types field_type,
|
||||||
create_field *field_def)
|
Create_field *field_def)
|
||||||
{
|
{
|
||||||
HA_CREATE_INFO sp_db_info;
|
HA_CREATE_INFO sp_db_info;
|
||||||
LEX_STRING cmt = { 0, 0 };
|
LEX_STRING cmt = { 0, 0 };
|
||||||
@ -2010,6 +2053,13 @@ sp_head::set_info(longlong created, longlong modified,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
sp_head::set_body_begin_ptr(Lex_input_stream *lip, const char *begin_ptr)
|
||||||
|
{
|
||||||
|
m_body_begin= begin_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
sp_head::set_definer(const char *definer, uint definerlen)
|
sp_head::set_definer(const char *definer, uint definerlen)
|
||||||
{
|
{
|
||||||
|
@ -126,7 +126,7 @@ public:
|
|||||||
int m_type;
|
int m_type;
|
||||||
uint m_flags; // Boolean attributes of a stored routine
|
uint m_flags; // Boolean attributes of a stored routine
|
||||||
|
|
||||||
create_field m_return_field_def; /* This is used for FUNCTIONs only. */
|
Create_field m_return_field_def; /* This is used for FUNCTIONs only. */
|
||||||
|
|
||||||
const char *m_tmp_query; // Temporary pointer to sub query string
|
const char *m_tmp_query; // Temporary pointer to sub query string
|
||||||
st_sp_chistics *m_chistics;
|
st_sp_chistics *m_chistics;
|
||||||
@ -178,8 +178,11 @@ public:
|
|||||||
// Pointers set during parsing
|
// Pointers set during parsing
|
||||||
const char *m_param_begin;
|
const char *m_param_begin;
|
||||||
const char *m_param_end;
|
const char *m_param_end;
|
||||||
|
|
||||||
|
private:
|
||||||
const char *m_body_begin;
|
const char *m_body_begin;
|
||||||
|
|
||||||
|
public:
|
||||||
/*
|
/*
|
||||||
Security context for stored routine which should be run under
|
Security context for stored routine which should be run under
|
||||||
definer privileges.
|
definer privileges.
|
||||||
@ -216,8 +219,10 @@ public:
|
|||||||
destroy();
|
destroy();
|
||||||
|
|
||||||
bool
|
bool
|
||||||
execute_trigger(THD *thd, const char *db, const char *table,
|
execute_trigger(THD *thd,
|
||||||
GRANT_INFO *grant_onfo);
|
const LEX_STRING *db_name,
|
||||||
|
const LEX_STRING *table_name,
|
||||||
|
GRANT_INFO *grant_info);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
execute_function(THD *thd, Item **args, uint argcount, Field *return_fld);
|
execute_function(THD *thd, Item **args, uint argcount, Field *return_fld);
|
||||||
@ -290,11 +295,13 @@ public:
|
|||||||
|
|
||||||
bool fill_field_definition(THD *thd, LEX *lex,
|
bool fill_field_definition(THD *thd, LEX *lex,
|
||||||
enum enum_field_types field_type,
|
enum enum_field_types field_type,
|
||||||
create_field *field_def);
|
Create_field *field_def);
|
||||||
|
|
||||||
void set_info(longlong created, longlong modified,
|
void set_info(longlong created, longlong modified,
|
||||||
st_sp_chistics *chistics, ulong sql_mode);
|
st_sp_chistics *chistics, ulong sql_mode);
|
||||||
|
|
||||||
|
void set_body_begin_ptr(Lex_input_stream *lip, const char *begin_ptr);
|
||||||
|
|
||||||
void set_definer(const char *definer, uint definerlen);
|
void set_definer(const char *definer, uint definerlen);
|
||||||
void set_definer(const LEX_STRING *user_name, const LEX_STRING *host_name);
|
void set_definer(const LEX_STRING *user_name, const LEX_STRING *host_name);
|
||||||
|
|
||||||
|
@ -422,7 +422,7 @@ sp_pcontext::find_cursor(LEX_STRING *name, uint *poff, my_bool scoped)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
sp_pcontext::retrieve_field_definitions(List<create_field> *field_def_lst)
|
sp_pcontext::retrieve_field_definitions(List<Create_field> *field_def_lst)
|
||||||
{
|
{
|
||||||
/* Put local/context fields in the result list. */
|
/* Put local/context fields in the result list. */
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ typedef struct sp_variable
|
|||||||
uint offset;
|
uint offset;
|
||||||
|
|
||||||
Item *dflt;
|
Item *dflt;
|
||||||
create_field field_def;
|
Create_field field_def;
|
||||||
} sp_variable_t;
|
} sp_variable_t;
|
||||||
|
|
||||||
|
|
||||||
@ -234,7 +234,7 @@ public:
|
|||||||
children.
|
children.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
retrieve_field_definitions(List<create_field> *field_def_lst);
|
retrieve_field_definitions(List<Create_field> *field_def_lst);
|
||||||
|
|
||||||
// Find by name
|
// Find by name
|
||||||
sp_variable_t *
|
sp_variable_t *
|
||||||
|
@ -102,7 +102,7 @@ bool sp_rcontext::init(THD *thd)
|
|||||||
bool
|
bool
|
||||||
sp_rcontext::init_var_table(THD *thd)
|
sp_rcontext::init_var_table(THD *thd)
|
||||||
{
|
{
|
||||||
List<create_field> field_def_lst;
|
List<Create_field> field_def_lst;
|
||||||
|
|
||||||
if (!m_root_parsing_ctx->max_var_index())
|
if (!m_root_parsing_ctx->max_var_index())
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -1459,40 +1459,62 @@ void Query_cache::invalidate(THD *thd, const char *key, uint32 key_length,
|
|||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
Remove all cached queries that uses the given database
|
@brief Remove all cached queries that uses the given database
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void Query_cache::invalidate(char *db)
|
void Query_cache::invalidate(char *db)
|
||||||
{
|
{
|
||||||
|
bool restart= FALSE;
|
||||||
DBUG_ENTER("Query_cache::invalidate (db)");
|
DBUG_ENTER("Query_cache::invalidate (db)");
|
||||||
STRUCT_LOCK(&structure_guard_mutex);
|
STRUCT_LOCK(&structure_guard_mutex);
|
||||||
if (query_cache_size > 0 && !flush_in_progress)
|
if (query_cache_size > 0 && !flush_in_progress)
|
||||||
{
|
{
|
||||||
DUMP(this);
|
|
||||||
restart_search:
|
|
||||||
if (tables_blocks)
|
if (tables_blocks)
|
||||||
{
|
{
|
||||||
Query_cache_block *curr= tables_blocks;
|
Query_cache_block *table_block = tables_blocks;
|
||||||
Query_cache_block *next;
|
do {
|
||||||
|
restart= FALSE;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
next= curr->next;
|
Query_cache_block *next= table_block->next;
|
||||||
if (strcmp(db, (char*)(curr->table()->db())) == 0)
|
Query_cache_table *table = table_block->table();
|
||||||
invalidate_table(curr);
|
if (strcmp(table->db(),db) == 0)
|
||||||
|
invalidate_table(table_block);
|
||||||
|
|
||||||
|
table_block= next;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
invalidate_table can freed block on which point 'next' (if
|
If our root node to used tables became null then the last element
|
||||||
table of this block used only in queries which was deleted
|
in the table list was removed when a query was invalidated;
|
||||||
by invalidate_table). As far as we do not allocate new blocks
|
Terminate the search.
|
||||||
and mark all headers of freed blocks as 'FREE' (even if they are
|
|
||||||
merged with other blocks) we can just test type of block
|
|
||||||
to be sure that block is not deleted
|
|
||||||
*/
|
*/
|
||||||
if (next->type == Query_cache_block::FREE)
|
if (tables_blocks == 0)
|
||||||
goto restart_search;
|
{
|
||||||
curr= next;
|
table_block= tables_blocks;
|
||||||
} while (curr != tables_blocks);
|
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
If the iterated list has changed underlying structure;
|
||||||
|
we need to restart the search.
|
||||||
|
*/
|
||||||
|
else if (table_block->type == Query_cache_block::FREE)
|
||||||
|
{
|
||||||
|
restart= TRUE;
|
||||||
|
table_block= tables_blocks;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
The used tables are linked in a circular list;
|
||||||
|
loop until we return to the begining.
|
||||||
|
*/
|
||||||
|
} while (table_block != tables_blocks);
|
||||||
|
/*
|
||||||
|
Invalidating a table will also mean that all cached queries using
|
||||||
|
this table also will be invalidated. This will in turn change the
|
||||||
|
list of tables associated with these queries and the linked list of
|
||||||
|
used table will be changed. Because of this we might need to restart
|
||||||
|
the search when a table has been invalidated.
|
||||||
|
*/
|
||||||
|
} while (restart);
|
||||||
|
} // end if( tables_blocks )
|
||||||
}
|
}
|
||||||
STRUCT_UNLOCK(&structure_guard_mutex);
|
STRUCT_UNLOCK(&structure_guard_mutex);
|
||||||
|
|
||||||
@ -2395,6 +2417,7 @@ Query_cache::register_tables_from_list(TABLE_LIST *tables_used,
|
|||||||
(ulong) tables_used->table,
|
(ulong) tables_used->table,
|
||||||
(ulong) tables_used->table->s->table_cache_key.length,
|
(ulong) tables_used->table->s->table_cache_key.length,
|
||||||
(ulong) tables_used->table->s->table_cache_key.str));
|
(ulong) tables_used->table->s->table_cache_key.str));
|
||||||
|
|
||||||
if (!insert_table(tables_used->table->s->table_cache_key.length,
|
if (!insert_table(tables_used->table->s->table_cache_key.length,
|
||||||
tables_used->table->s->table_cache_key.str,
|
tables_used->table->s->table_cache_key.str,
|
||||||
block_table,
|
block_table,
|
||||||
@ -2461,9 +2484,8 @@ my_bool Query_cache::register_all_tables(Query_cache_block *block,
|
|||||||
|
|
||||||
n= register_tables_from_list(tables_used, 0, block_table);
|
n= register_tables_from_list(tables_used, 0, block_table);
|
||||||
|
|
||||||
if (n)
|
if (n==0)
|
||||||
{
|
{
|
||||||
DBUG_PRINT("qcache", ("failed at table %d", (int) n));
|
|
||||||
/* Unlink the tables we allocated above */
|
/* Unlink the tables we allocated above */
|
||||||
for (Query_cache_block_table *tmp = block->table(0) ;
|
for (Query_cache_block_table *tmp = block->table(0) ;
|
||||||
tmp != block_table;
|
tmp != block_table;
|
||||||
@ -2953,8 +2975,11 @@ Query_cache::double_linked_list_exclude(Query_cache_block *point,
|
|||||||
{
|
{
|
||||||
point->next->prev = point->prev;
|
point->next->prev = point->prev;
|
||||||
point->prev->next = point->next;
|
point->prev->next = point->next;
|
||||||
|
/*
|
||||||
|
If the root is removed; select a new root
|
||||||
|
*/
|
||||||
if (point == *list_pointer)
|
if (point == *list_pointer)
|
||||||
*list_pointer = point->next;
|
*list_pointer= point->next;
|
||||||
}
|
}
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
@ -3752,7 +3777,7 @@ void Query_cache::tables_dump()
|
|||||||
Query_cache_table *table = table_block->table();
|
Query_cache_table *table = table_block->table();
|
||||||
DBUG_PRINT("qcache", ("'%s' '%s'", table->db(), table->table()));
|
DBUG_PRINT("qcache", ("'%s' '%s'", table->db(), table->table()));
|
||||||
table_block = table_block->next;
|
table_block = table_block->next;
|
||||||
} while ( table_block != tables_blocks);
|
} while (table_block != tables_blocks);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
DBUG_PRINT("qcache", ("no tables in list"));
|
DBUG_PRINT("qcache", ("no tables in list"));
|
||||||
|
@ -59,8 +59,8 @@ const char * const THD::DEFAULT_WHERE= "field list";
|
|||||||
/* Used templates */
|
/* Used templates */
|
||||||
template class List<Key>;
|
template class List<Key>;
|
||||||
template class List_iterator<Key>;
|
template class List_iterator<Key>;
|
||||||
template class List<key_part_spec>;
|
template class List<Key_part_spec>;
|
||||||
template class List_iterator<key_part_spec>;
|
template class List_iterator<Key_part_spec>;
|
||||||
template class List<Alter_drop>;
|
template class List<Alter_drop>;
|
||||||
template class List_iterator<Alter_drop>;
|
template class List_iterator<Alter_drop>;
|
||||||
template class List<Alter_column>;
|
template class List<Alter_column>;
|
||||||
@ -86,7 +86,7 @@ extern "C" void free_user_var(user_var_entry *entry)
|
|||||||
my_free((char*) entry,MYF(0));
|
my_free((char*) entry,MYF(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool key_part_spec::operator==(const key_part_spec& other) const
|
bool Key_part_spec::operator==(const Key_part_spec& other) const
|
||||||
{
|
{
|
||||||
return length == other.length && !strcmp(field_name, other.field_name);
|
return length == other.length && !strcmp(field_name, other.field_name);
|
||||||
}
|
}
|
||||||
@ -115,7 +115,7 @@ Key::Key(const Key &rhs, MEM_ROOT *mem_root)
|
|||||||
in THD.
|
in THD.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
foreign_key::foreign_key(const foreign_key &rhs, MEM_ROOT *mem_root)
|
Foreign_key::Foreign_key(const Foreign_key &rhs, MEM_ROOT *mem_root)
|
||||||
:Key(rhs),
|
:Key(rhs),
|
||||||
ref_table(rhs.ref_table),
|
ref_table(rhs.ref_table),
|
||||||
ref_columns(rhs.ref_columns),
|
ref_columns(rhs.ref_columns),
|
||||||
@ -160,9 +160,9 @@ bool foreign_key_prefix(Key *a, Key *b)
|
|||||||
if (a->columns.elements > b->columns.elements)
|
if (a->columns.elements > b->columns.elements)
|
||||||
return TRUE; // Can't be prefix
|
return TRUE; // Can't be prefix
|
||||||
|
|
||||||
List_iterator<key_part_spec> col_it1(a->columns);
|
List_iterator<Key_part_spec> col_it1(a->columns);
|
||||||
List_iterator<key_part_spec> col_it2(b->columns);
|
List_iterator<Key_part_spec> col_it2(b->columns);
|
||||||
const key_part_spec *col1, *col2;
|
const Key_part_spec *col1, *col2;
|
||||||
|
|
||||||
#ifdef ENABLE_WHEN_INNODB_CAN_HANDLE_SWAPED_FOREIGN_KEY_COLUMNS
|
#ifdef ENABLE_WHEN_INNODB_CAN_HANDLE_SWAPED_FOREIGN_KEY_COLUMNS
|
||||||
while ((col1= col_it1++))
|
while ((col1= col_it1++))
|
||||||
@ -342,7 +342,8 @@ THD::THD()
|
|||||||
in_lock_tables(0),
|
in_lock_tables(0),
|
||||||
bootstrap(0),
|
bootstrap(0),
|
||||||
derived_tables_processing(FALSE),
|
derived_tables_processing(FALSE),
|
||||||
spcont(NULL)
|
spcont(NULL),
|
||||||
|
m_lip(NULL)
|
||||||
{
|
{
|
||||||
ulong tmp;
|
ulong tmp;
|
||||||
|
|
||||||
|
@ -85,14 +85,14 @@ typedef struct st_copy_info {
|
|||||||
} COPY_INFO;
|
} COPY_INFO;
|
||||||
|
|
||||||
|
|
||||||
class key_part_spec :public Sql_alloc {
|
class Key_part_spec :public Sql_alloc {
|
||||||
public:
|
public:
|
||||||
const char *field_name;
|
const char *field_name;
|
||||||
uint length;
|
uint length;
|
||||||
key_part_spec(const char *name,uint len=0) :field_name(name), length(len) {}
|
Key_part_spec(const char *name,uint len=0) :field_name(name), length(len) {}
|
||||||
bool operator==(const key_part_spec& other) const;
|
bool operator==(const Key_part_spec& other) const;
|
||||||
/**
|
/**
|
||||||
Construct a copy of this key_part_spec. field_name is copied
|
Construct a copy of this Key_part_spec. field_name is copied
|
||||||
by-pointer as it is known to never change. At the same time
|
by-pointer as it is known to never change. At the same time
|
||||||
'length' may be reset in mysql_prepare_create_table, and this
|
'length' may be reset in mysql_prepare_create_table, and this
|
||||||
is why we supply it with a copy.
|
is why we supply it with a copy.
|
||||||
@ -100,8 +100,8 @@ public:
|
|||||||
@return If out of memory, 0 is returned and an error is set in
|
@return If out of memory, 0 is returned and an error is set in
|
||||||
THD.
|
THD.
|
||||||
*/
|
*/
|
||||||
key_part_spec *clone(MEM_ROOT *mem_root) const
|
Key_part_spec *clone(MEM_ROOT *mem_root) const
|
||||||
{ return new (mem_root) key_part_spec(*this); }
|
{ return new (mem_root) Key_part_spec(*this); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -114,7 +114,7 @@ public:
|
|||||||
:name(par_name), type(par_type) {}
|
:name(par_name), type(par_type) {}
|
||||||
/**
|
/**
|
||||||
Used to make a clone of this object for ALTER/CREATE TABLE
|
Used to make a clone of this object for ALTER/CREATE TABLE
|
||||||
@sa comment for key_part_spec::clone
|
@sa comment for Key_part_spec::clone
|
||||||
*/
|
*/
|
||||||
Alter_drop *clone(MEM_ROOT *mem_root) const
|
Alter_drop *clone(MEM_ROOT *mem_root) const
|
||||||
{ return new (mem_root) Alter_drop(*this); }
|
{ return new (mem_root) Alter_drop(*this); }
|
||||||
@ -129,7 +129,7 @@ public:
|
|||||||
:name(par_name), def(literal) {}
|
:name(par_name), def(literal) {}
|
||||||
/**
|
/**
|
||||||
Used to make a clone of this object for ALTER/CREATE TABLE
|
Used to make a clone of this object for ALTER/CREATE TABLE
|
||||||
@sa comment for key_part_spec::clone
|
@sa comment for Key_part_spec::clone
|
||||||
*/
|
*/
|
||||||
Alter_column *clone(MEM_ROOT *mem_root) const
|
Alter_column *clone(MEM_ROOT *mem_root) const
|
||||||
{ return new (mem_root) Alter_column(*this); }
|
{ return new (mem_root) Alter_column(*this); }
|
||||||
@ -141,13 +141,13 @@ public:
|
|||||||
enum Keytype { PRIMARY, UNIQUE, MULTIPLE, FULLTEXT, SPATIAL, FOREIGN_KEY};
|
enum Keytype { PRIMARY, UNIQUE, MULTIPLE, FULLTEXT, SPATIAL, FOREIGN_KEY};
|
||||||
enum Keytype type;
|
enum Keytype type;
|
||||||
KEY_CREATE_INFO key_create_info;
|
KEY_CREATE_INFO key_create_info;
|
||||||
List<key_part_spec> columns;
|
List<Key_part_spec> columns;
|
||||||
const char *name;
|
const char *name;
|
||||||
bool generated;
|
bool generated;
|
||||||
|
|
||||||
Key(enum Keytype type_par, const char *name_arg,
|
Key(enum Keytype type_par, const char *name_arg,
|
||||||
KEY_CREATE_INFO *key_info_arg,
|
KEY_CREATE_INFO *key_info_arg,
|
||||||
bool generated_arg, List<key_part_spec> &cols)
|
bool generated_arg, List<Key_part_spec> &cols)
|
||||||
:type(type_par), key_create_info(*key_info_arg), columns(cols),
|
:type(type_par), key_create_info(*key_info_arg), columns(cols),
|
||||||
name(name_arg), generated(generated_arg)
|
name(name_arg), generated(generated_arg)
|
||||||
{}
|
{}
|
||||||
@ -157,7 +157,7 @@ public:
|
|||||||
friend bool foreign_key_prefix(Key *a, Key *b);
|
friend bool foreign_key_prefix(Key *a, Key *b);
|
||||||
/**
|
/**
|
||||||
Used to make a clone of this object for ALTER/CREATE TABLE
|
Used to make a clone of this object for ALTER/CREATE TABLE
|
||||||
@sa comment for key_part_spec::clone
|
@sa comment for Key_part_spec::clone
|
||||||
*/
|
*/
|
||||||
virtual Key *clone(MEM_ROOT *mem_root) const
|
virtual Key *clone(MEM_ROOT *mem_root) const
|
||||||
{ return new (mem_root) Key(*this, mem_root); }
|
{ return new (mem_root) Key(*this, mem_root); }
|
||||||
@ -165,7 +165,7 @@ public:
|
|||||||
|
|
||||||
class Table_ident;
|
class Table_ident;
|
||||||
|
|
||||||
class foreign_key: public Key {
|
class Foreign_key: public Key {
|
||||||
public:
|
public:
|
||||||
enum fk_match_opt { FK_MATCH_UNDEF, FK_MATCH_FULL,
|
enum fk_match_opt { FK_MATCH_UNDEF, FK_MATCH_FULL,
|
||||||
FK_MATCH_PARTIAL, FK_MATCH_SIMPLE};
|
FK_MATCH_PARTIAL, FK_MATCH_SIMPLE};
|
||||||
@ -173,23 +173,23 @@ public:
|
|||||||
FK_OPTION_SET_NULL, FK_OPTION_NO_ACTION, FK_OPTION_DEFAULT};
|
FK_OPTION_SET_NULL, FK_OPTION_NO_ACTION, FK_OPTION_DEFAULT};
|
||||||
|
|
||||||
Table_ident *ref_table;
|
Table_ident *ref_table;
|
||||||
List<key_part_spec> ref_columns;
|
List<Key_part_spec> ref_columns;
|
||||||
uint delete_opt, update_opt, match_opt;
|
uint delete_opt, update_opt, match_opt;
|
||||||
foreign_key(const char *name_arg, List<key_part_spec> &cols,
|
Foreign_key(const char *name_arg, List<Key_part_spec> &cols,
|
||||||
Table_ident *table, List<key_part_spec> &ref_cols,
|
Table_ident *table, List<Key_part_spec> &ref_cols,
|
||||||
uint delete_opt_arg, uint update_opt_arg, uint match_opt_arg)
|
uint delete_opt_arg, uint update_opt_arg, uint match_opt_arg)
|
||||||
:Key(FOREIGN_KEY, name_arg, &default_key_create_info, 0, cols),
|
:Key(FOREIGN_KEY, name_arg, &default_key_create_info, 0, cols),
|
||||||
ref_table(table), ref_columns(cols),
|
ref_table(table), ref_columns(cols),
|
||||||
delete_opt(delete_opt_arg), update_opt(update_opt_arg),
|
delete_opt(delete_opt_arg), update_opt(update_opt_arg),
|
||||||
match_opt(match_opt_arg)
|
match_opt(match_opt_arg)
|
||||||
{}
|
{}
|
||||||
foreign_key(const foreign_key &rhs, MEM_ROOT *mem_root);
|
Foreign_key(const Foreign_key &rhs, MEM_ROOT *mem_root);
|
||||||
/**
|
/**
|
||||||
Used to make a clone of this object for ALTER/CREATE TABLE
|
Used to make a clone of this object for ALTER/CREATE TABLE
|
||||||
@sa comment for key_part_spec::clone
|
@sa comment for Key_part_spec::clone
|
||||||
*/
|
*/
|
||||||
virtual Key *clone(MEM_ROOT *mem_root) const
|
virtual Key *clone(MEM_ROOT *mem_root) const
|
||||||
{ return new (mem_root) foreign_key(*this, mem_root); }
|
{ return new (mem_root) Foreign_key(*this, mem_root); }
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct st_mysql_lock
|
typedef struct st_mysql_lock
|
||||||
|
@ -538,6 +538,37 @@ bool load_db_opt_by_name(THD *thd, const char *db_name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Return default database collation.
|
||||||
|
|
||||||
|
@param thd Thread context.
|
||||||
|
@param db_name Database name.
|
||||||
|
|
||||||
|
@return CHARSET_INFO object. The operation always return valid character
|
||||||
|
set, even if the database does not exist.
|
||||||
|
*/
|
||||||
|
|
||||||
|
CHARSET_INFO *get_default_db_collation(THD *thd, const char *db_name)
|
||||||
|
{
|
||||||
|
HA_CREATE_INFO db_info;
|
||||||
|
|
||||||
|
if (thd->db != NULL && strcmp(db_name, thd->db) == 0)
|
||||||
|
return thd->db_charset;
|
||||||
|
|
||||||
|
load_db_opt_by_name(thd, db_name, &db_info);
|
||||||
|
|
||||||
|
/*
|
||||||
|
NOTE: even if load_db_opt_by_name() fails,
|
||||||
|
db_info.default_table_charset contains valid character set
|
||||||
|
(collation_server). We should not fail if load_db_opt_by_name() fails,
|
||||||
|
because it is valid case. If a database has been created just by
|
||||||
|
"mkdir", it does not contain db.opt file, but it is valid database.
|
||||||
|
*/
|
||||||
|
|
||||||
|
return db_info.default_table_charset;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Create a database
|
Create a database
|
||||||
|
|
||||||
@ -751,10 +782,8 @@ bool mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info)
|
|||||||
if ((error=write_db_opt(thd, path, create_info)))
|
if ((error=write_db_opt(thd, path, create_info)))
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
/*
|
/* Change options if current database is being altered. */
|
||||||
Change options if current database is being altered
|
|
||||||
TODO: Delete this code
|
|
||||||
*/
|
|
||||||
if (thd->db && !strcmp(thd->db,db))
|
if (thd->db && !strcmp(thd->db,db))
|
||||||
{
|
{
|
||||||
thd->db_charset= create_info->default_table_charset ?
|
thd->db_charset= create_info->default_table_charset ?
|
||||||
@ -1358,6 +1387,7 @@ bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name, bool force_switch)
|
|||||||
|
|
||||||
Security_context *sctx= thd->security_ctx;
|
Security_context *sctx= thd->security_ctx;
|
||||||
ulong db_access= sctx->db_access;
|
ulong db_access= sctx->db_access;
|
||||||
|
CHARSET_INFO *db_default_cl;
|
||||||
|
|
||||||
DBUG_ENTER("mysql_change_db");
|
DBUG_ENTER("mysql_change_db");
|
||||||
DBUG_PRINT("enter",("name: '%s'", new_db_name->str));
|
DBUG_PRINT("enter",("name: '%s'", new_db_name->str));
|
||||||
@ -1487,16 +1517,9 @@ bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name, bool force_switch)
|
|||||||
attributes and will be freed in THD::~THD().
|
attributes and will be freed in THD::~THD().
|
||||||
*/
|
*/
|
||||||
|
|
||||||
{
|
db_default_cl= get_default_db_collation(thd, new_db_file_name.str);
|
||||||
HA_CREATE_INFO db_options;
|
|
||||||
|
|
||||||
load_db_opt_by_name(thd, new_db_name->str, &db_options);
|
mysql_change_db_impl(thd, &new_db_file_name, db_access, db_default_cl);
|
||||||
|
|
||||||
mysql_change_db_impl(thd, &new_db_file_name, db_access,
|
|
||||||
db_options.default_table_charset ?
|
|
||||||
db_options.default_table_charset :
|
|
||||||
thd->variables.collation_server);
|
|
||||||
}
|
|
||||||
|
|
||||||
DBUG_RETURN(FALSE);
|
DBUG_RETURN(FALSE);
|
||||||
}
|
}
|
||||||
|
@ -3213,7 +3213,7 @@ static TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
|
|||||||
MYSQL_LOCK **lock,
|
MYSQL_LOCK **lock,
|
||||||
TABLEOP_HOOKS *hooks)
|
TABLEOP_HOOKS *hooks)
|
||||||
{
|
{
|
||||||
TABLE tmp_table; // Used during 'create_field()'
|
TABLE tmp_table; // Used during 'Create_field()'
|
||||||
TABLE_SHARE share;
|
TABLE_SHARE share;
|
||||||
TABLE *table= 0;
|
TABLE *table= 0;
|
||||||
uint select_field_count= items->elements;
|
uint select_field_count= items->elements;
|
||||||
@ -3257,7 +3257,7 @@ static TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
|
|||||||
|
|
||||||
while ((item=it++))
|
while ((item=it++))
|
||||||
{
|
{
|
||||||
create_field *cr_field;
|
Create_field *cr_field;
|
||||||
Field *field, *def_field;
|
Field *field, *def_field;
|
||||||
if (item->type() == Item::FUNC_ITEM)
|
if (item->type() == Item::FUNC_ITEM)
|
||||||
field= item->tmp_table_field(&tmp_table);
|
field= item->tmp_table_field(&tmp_table);
|
||||||
@ -3266,7 +3266,7 @@ static TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
|
|||||||
(Item ***) 0, &tmp_field, &def_field, 0, 0, 0, 0,
|
(Item ***) 0, &tmp_field, &def_field, 0, 0, 0, 0,
|
||||||
0);
|
0);
|
||||||
if (!field ||
|
if (!field ||
|
||||||
!(cr_field=new create_field(field,(item->type() == Item::FIELD_ITEM ?
|
!(cr_field=new Create_field(field,(item->type() == Item::FIELD_ITEM ?
|
||||||
((Item_field *)item)->field :
|
((Item_field *)item)->field :
|
||||||
(Field*) 0))))
|
(Field*) 0))))
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
|
516
sql/sql_lex.cc
516
sql/sql_lex.cc
@ -31,16 +31,6 @@
|
|||||||
|
|
||||||
sys_var *trg_new_row_fake_var= (sys_var*) 0x01;
|
sys_var *trg_new_row_fake_var= (sys_var*) 0x01;
|
||||||
|
|
||||||
/* Macros to look like lex */
|
|
||||||
|
|
||||||
#define yyGet() ((uchar) *(lip->ptr++))
|
|
||||||
#define yyGetLast() ((uchar) lip->ptr[-1])
|
|
||||||
#define yyPeek() ((uchar) lip->ptr[0])
|
|
||||||
#define yyPeek2() ((uchar) lip->ptr[1])
|
|
||||||
#define yyUnget() lip->ptr--
|
|
||||||
#define yySkip() lip->ptr++
|
|
||||||
#define yyLength() ((uint) (lip->ptr - lip->tok_start)-1)
|
|
||||||
|
|
||||||
/* Longest standard keyword name */
|
/* Longest standard keyword name */
|
||||||
#define TOCK_NAME_LENGTH 24
|
#define TOCK_NAME_LENGTH 24
|
||||||
|
|
||||||
@ -127,17 +117,24 @@ Lex_input_stream::Lex_input_stream(THD *thd,
|
|||||||
yylineno(1),
|
yylineno(1),
|
||||||
yytoklen(0),
|
yytoklen(0),
|
||||||
yylval(NULL),
|
yylval(NULL),
|
||||||
ptr(buffer),
|
m_ptr(buffer),
|
||||||
tok_start(NULL),
|
m_tok_start(NULL),
|
||||||
tok_end(NULL),
|
m_tok_end(NULL),
|
||||||
end_of_query(buffer + length),
|
m_end_of_query(buffer + length),
|
||||||
tok_start_prev(NULL),
|
m_tok_start_prev(NULL),
|
||||||
buf(buffer),
|
m_buf(buffer),
|
||||||
|
m_echo(true),
|
||||||
|
m_cpp_tok_start(NULL),
|
||||||
|
m_cpp_tok_start_prev(NULL),
|
||||||
|
m_cpp_tok_end(NULL),
|
||||||
next_state(MY_LEX_START),
|
next_state(MY_LEX_START),
|
||||||
found_semicolon(NULL),
|
found_semicolon(NULL),
|
||||||
ignore_space(test(thd->variables.sql_mode & MODE_IGNORE_SPACE)),
|
ignore_space(test(thd->variables.sql_mode & MODE_IGNORE_SPACE)),
|
||||||
stmt_prepare_mode(FALSE)
|
stmt_prepare_mode(FALSE),
|
||||||
|
in_comment(NO_COMMENT)
|
||||||
{
|
{
|
||||||
|
m_cpp_buf= (char*) thd->alloc(length + 1);
|
||||||
|
m_cpp_ptr= m_cpp_buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
Lex_input_stream::~Lex_input_stream()
|
Lex_input_stream::~Lex_input_stream()
|
||||||
@ -192,7 +189,6 @@ void lex_start(THD *thd)
|
|||||||
lex->parsing_options.reset();
|
lex->parsing_options.reset();
|
||||||
lex->empty_field_list_on_rset= 0;
|
lex->empty_field_list_on_rset= 0;
|
||||||
lex->select_lex.select_number= 1;
|
lex->select_lex.select_number= 1;
|
||||||
lex->in_comment=0;
|
|
||||||
lex->length=0;
|
lex->length=0;
|
||||||
lex->part_info= 0;
|
lex->part_info= 0;
|
||||||
lex->select_lex.in_sum_expr=0;
|
lex->select_lex.in_sum_expr=0;
|
||||||
@ -261,7 +257,7 @@ void lex_end(LEX *lex)
|
|||||||
|
|
||||||
static int find_keyword(Lex_input_stream *lip, uint len, bool function)
|
static int find_keyword(Lex_input_stream *lip, uint len, bool function)
|
||||||
{
|
{
|
||||||
const char *tok= lip->tok_start;
|
const char *tok= lip->get_tok_start();
|
||||||
|
|
||||||
SYMBOL *symbol= get_hash_symbol(tok, len, function);
|
SYMBOL *symbol= get_hash_symbol(tok, len, function);
|
||||||
if (symbol)
|
if (symbol)
|
||||||
@ -312,9 +308,9 @@ bool is_lex_native_function(const LEX_STRING *name)
|
|||||||
static LEX_STRING get_token(Lex_input_stream *lip, uint skip, uint length)
|
static LEX_STRING get_token(Lex_input_stream *lip, uint skip, uint length)
|
||||||
{
|
{
|
||||||
LEX_STRING tmp;
|
LEX_STRING tmp;
|
||||||
yyUnget(); // ptr points now after last token char
|
lip->yyUnget(); // ptr points now after last token char
|
||||||
tmp.length=lip->yytoklen=length;
|
tmp.length=lip->yytoklen=length;
|
||||||
tmp.str= lip->m_thd->strmake(lip->tok_start + skip, tmp.length);
|
tmp.str= lip->m_thd->strmake(lip->get_tok_start() + skip, tmp.length);
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -332,10 +328,10 @@ static LEX_STRING get_quoted_token(Lex_input_stream *lip,
|
|||||||
LEX_STRING tmp;
|
LEX_STRING tmp;
|
||||||
const char *from, *end;
|
const char *from, *end;
|
||||||
char *to;
|
char *to;
|
||||||
yyUnget(); // ptr points now after last token char
|
lip->yyUnget(); // ptr points now after last token char
|
||||||
tmp.length= lip->yytoklen=length;
|
tmp.length= lip->yytoklen=length;
|
||||||
tmp.str=(char*) lip->m_thd->alloc(tmp.length+1);
|
tmp.str=(char*) lip->m_thd->alloc(tmp.length+1);
|
||||||
from= lip->tok_start + skip;
|
from= lip->get_tok_start() + skip;
|
||||||
to= tmp.str;
|
to= tmp.str;
|
||||||
end= to+length;
|
end= to+length;
|
||||||
for ( ; to != end; )
|
for ( ; to != end; )
|
||||||
@ -353,22 +349,24 @@ static LEX_STRING get_quoted_token(Lex_input_stream *lip,
|
|||||||
Fix sometimes to do only one scan of the string
|
Fix sometimes to do only one scan of the string
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static char *get_text(Lex_input_stream *lip)
|
static char *get_text(Lex_input_stream *lip, int pre_skip, int post_skip)
|
||||||
{
|
{
|
||||||
reg1 uchar c,sep;
|
reg1 uchar c,sep;
|
||||||
uint found_escape=0;
|
uint found_escape=0;
|
||||||
CHARSET_INFO *cs= lip->m_thd->charset();
|
CHARSET_INFO *cs= lip->m_thd->charset();
|
||||||
|
|
||||||
sep= yyGetLast(); // String should end with this
|
sep= lip->yyGetLast(); // String should end with this
|
||||||
while (lip->ptr != lip->end_of_query)
|
while (! lip->eof())
|
||||||
{
|
{
|
||||||
c = yyGet();
|
c= lip->yyGet();
|
||||||
#ifdef USE_MB
|
#ifdef USE_MB
|
||||||
{
|
{
|
||||||
int l;
|
int l;
|
||||||
if (use_mb(cs) &&
|
if (use_mb(cs) &&
|
||||||
(l = my_ismbchar(cs, lip->ptr-1, lip->end_of_query))) {
|
(l = my_ismbchar(cs,
|
||||||
lip->ptr += l-1;
|
lip->get_ptr() -1,
|
||||||
|
lip->get_end_of_query()))) {
|
||||||
|
lip->skip_binary(l-1);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -377,26 +375,31 @@ static char *get_text(Lex_input_stream *lip)
|
|||||||
!(lip->m_thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES))
|
!(lip->m_thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES))
|
||||||
{ // Escaped character
|
{ // Escaped character
|
||||||
found_escape=1;
|
found_escape=1;
|
||||||
if (lip->ptr == lip->end_of_query)
|
if (lip->eof())
|
||||||
return 0;
|
return 0;
|
||||||
yySkip();
|
lip->yySkip();
|
||||||
}
|
}
|
||||||
else if (c == sep)
|
else if (c == sep)
|
||||||
{
|
{
|
||||||
if (c == yyGet()) // Check if two separators in a row
|
if (c == lip->yyGet()) // Check if two separators in a row
|
||||||
{
|
{
|
||||||
found_escape=1; // dupplicate. Remember for delete
|
found_escape=1; // duplicate. Remember for delete
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
yyUnget();
|
lip->yyUnget();
|
||||||
|
|
||||||
/* Found end. Unescape and return string */
|
/* Found end. Unescape and return string */
|
||||||
const char *str, *end;
|
const char *str, *end;
|
||||||
char *start;
|
char *start;
|
||||||
|
|
||||||
str=lip->tok_start+1;
|
str= lip->get_tok_start();
|
||||||
end=lip->ptr-1;
|
end= lip->get_ptr();
|
||||||
|
/* Extract the text from the token */
|
||||||
|
str += pre_skip;
|
||||||
|
end -= post_skip;
|
||||||
|
DBUG_ASSERT(end >= str);
|
||||||
|
|
||||||
if (!(start= (char*) lip->m_thd->alloc((uint) (end-str)+1)))
|
if (!(start= (char*) lip->m_thd->alloc((uint) (end-str)+1)))
|
||||||
return (char*) ""; // Sql_alloc has set error flag
|
return (char*) ""; // Sql_alloc has set error flag
|
||||||
if (!found_escape)
|
if (!found_escape)
|
||||||
@ -581,9 +584,7 @@ int MYSQLlex(void *arg, void *yythd)
|
|||||||
|
|
||||||
lip->yylval=yylval; // The global state
|
lip->yylval=yylval; // The global state
|
||||||
|
|
||||||
lip->tok_start_prev= lip->tok_start;
|
lip->start_token();
|
||||||
|
|
||||||
lip->tok_start=lip->tok_end=lip->ptr;
|
|
||||||
state=lip->next_state;
|
state=lip->next_state;
|
||||||
lip->next_state=MY_LEX_OPERATOR_OR_IDENT;
|
lip->next_state=MY_LEX_OPERATOR_OR_IDENT;
|
||||||
LINT_INIT(c);
|
LINT_INIT(c);
|
||||||
@ -592,17 +593,22 @@ int MYSQLlex(void *arg, void *yythd)
|
|||||||
switch (state) {
|
switch (state) {
|
||||||
case MY_LEX_OPERATOR_OR_IDENT: // Next is operator or keyword
|
case MY_LEX_OPERATOR_OR_IDENT: // Next is operator or keyword
|
||||||
case MY_LEX_START: // Start of token
|
case MY_LEX_START: // Start of token
|
||||||
// Skip startspace
|
// Skip starting whitespace
|
||||||
for (c=yyGet() ; (state_map[c] == MY_LEX_SKIP) ; c= yyGet())
|
while(state_map[c= lip->yyPeek()] == MY_LEX_SKIP)
|
||||||
{
|
{
|
||||||
if (c == '\n')
|
if (c == '\n')
|
||||||
lip->yylineno++;
|
lip->yylineno++;
|
||||||
|
|
||||||
|
lip->yySkip();
|
||||||
}
|
}
|
||||||
lip->tok_start=lip->ptr-1; // Start of real token
|
|
||||||
|
/* Start of real token */
|
||||||
|
lip->restart_token();
|
||||||
|
c= lip->yyGet();
|
||||||
state= (enum my_lex_states) state_map[c];
|
state= (enum my_lex_states) state_map[c];
|
||||||
break;
|
break;
|
||||||
case MY_LEX_ESCAPE:
|
case MY_LEX_ESCAPE:
|
||||||
if (yyGet() == 'N')
|
if (lip->yyGet() == 'N')
|
||||||
{ // Allow \N as shortcut for NULL
|
{ // Allow \N as shortcut for NULL
|
||||||
yylval->lex_str.str=(char*) "\\N";
|
yylval->lex_str.str=(char*) "\\N";
|
||||||
yylval->lex_str.length=2;
|
yylval->lex_str.length=2;
|
||||||
@ -610,40 +616,53 @@ int MYSQLlex(void *arg, void *yythd)
|
|||||||
}
|
}
|
||||||
case MY_LEX_CHAR: // Unknown or single char token
|
case MY_LEX_CHAR: // Unknown or single char token
|
||||||
case MY_LEX_SKIP: // This should not happen
|
case MY_LEX_SKIP: // This should not happen
|
||||||
if (c == '-' && yyPeek() == '-' &&
|
if (c == '-' && lip->yyPeek() == '-' &&
|
||||||
(my_isspace(cs,yyPeek2()) ||
|
(my_isspace(cs,lip->yyPeekn(1)) ||
|
||||||
my_iscntrl(cs,yyPeek2())))
|
my_iscntrl(cs,lip->yyPeekn(1))))
|
||||||
{
|
{
|
||||||
state=MY_LEX_COMMENT;
|
state=MY_LEX_COMMENT;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
yylval->lex_str.str=(char*) (lip->ptr=lip->tok_start);// Set to first chr
|
|
||||||
yylval->lex_str.length=1;
|
|
||||||
c=yyGet();
|
|
||||||
if (c != ')')
|
if (c != ')')
|
||||||
lip->next_state= MY_LEX_START; // Allow signed numbers
|
lip->next_state= MY_LEX_START; // Allow signed numbers
|
||||||
|
|
||||||
if (c == ',')
|
if (c == ',')
|
||||||
lip->tok_start=lip->ptr; // Let tok_start point at next item
|
{
|
||||||
|
/*
|
||||||
|
Warning:
|
||||||
|
This is a work around, to make the "remember_name" rule in
|
||||||
|
sql/sql_yacc.yy work properly.
|
||||||
|
The problem is that, when parsing "select expr1, expr2",
|
||||||
|
the code generated by bison executes the *pre* action
|
||||||
|
remember_name (see select_item) *before* actually parsing the
|
||||||
|
first token of expr2.
|
||||||
|
*/
|
||||||
|
lip->restart_token();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
/*
|
/*
|
||||||
Check for a placeholder: it should not precede a possible identifier
|
Check for a placeholder: it should not precede a possible identifier
|
||||||
because of binlogging: when a placeholder is replaced with
|
because of binlogging: when a placeholder is replaced with
|
||||||
its value in a query for the binlog, the query must stay
|
its value in a query for the binlog, the query must stay
|
||||||
grammatically correct.
|
grammatically correct.
|
||||||
*/
|
*/
|
||||||
else if (c == '?' && lip->stmt_prepare_mode && !ident_map[yyPeek()])
|
if (c == '?' && lip->stmt_prepare_mode && !ident_map[lip->yyPeek()])
|
||||||
return(PARAM_MARKER);
|
return(PARAM_MARKER);
|
||||||
|
}
|
||||||
|
|
||||||
return((int) c);
|
return((int) c);
|
||||||
|
|
||||||
case MY_LEX_IDENT_OR_NCHAR:
|
case MY_LEX_IDENT_OR_NCHAR:
|
||||||
if (yyPeek() != '\'')
|
if (lip->yyPeek() != '\'')
|
||||||
{
|
{
|
||||||
state= MY_LEX_IDENT;
|
state= MY_LEX_IDENT;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* Found N'string' */
|
/* Found N'string' */
|
||||||
lip->tok_start++; // Skip N
|
lip->yySkip(); // Skip '
|
||||||
yySkip(); // Skip '
|
if (!(yylval->lex_str.str = get_text(lip, 2, 1)))
|
||||||
if (!(yylval->lex_str.str = get_text(lip)))
|
|
||||||
{
|
{
|
||||||
state= MY_LEX_CHAR; // Read char by char
|
state= MY_LEX_CHAR; // Read char by char
|
||||||
break;
|
break;
|
||||||
@ -652,13 +671,13 @@ int MYSQLlex(void *arg, void *yythd)
|
|||||||
return(NCHAR_STRING);
|
return(NCHAR_STRING);
|
||||||
|
|
||||||
case MY_LEX_IDENT_OR_HEX:
|
case MY_LEX_IDENT_OR_HEX:
|
||||||
if (yyPeek() == '\'')
|
if (lip->yyPeek() == '\'')
|
||||||
{ // Found x'hex-number'
|
{ // Found x'hex-number'
|
||||||
state= MY_LEX_HEX_NUMBER;
|
state= MY_LEX_HEX_NUMBER;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MY_LEX_IDENT_OR_BIN:
|
case MY_LEX_IDENT_OR_BIN:
|
||||||
if (yyPeek() == '\'')
|
if (lip->yyPeek() == '\'')
|
||||||
{ // Found b'bin-number'
|
{ // Found b'bin-number'
|
||||||
state= MY_LEX_BIN_NUMBER;
|
state= MY_LEX_BIN_NUMBER;
|
||||||
break;
|
break;
|
||||||
@ -669,54 +688,58 @@ int MYSQLlex(void *arg, void *yythd)
|
|||||||
if (use_mb(cs))
|
if (use_mb(cs))
|
||||||
{
|
{
|
||||||
result_state= IDENT_QUOTED;
|
result_state= IDENT_QUOTED;
|
||||||
if (my_mbcharlen(cs, yyGetLast()) > 1)
|
if (my_mbcharlen(cs, lip->yyGetLast()) > 1)
|
||||||
{
|
{
|
||||||
int l = my_ismbchar(cs, lip->ptr-1, lip->end_of_query);
|
int l = my_ismbchar(cs,
|
||||||
|
lip->get_ptr() -1,
|
||||||
|
lip->get_end_of_query());
|
||||||
if (l == 0) {
|
if (l == 0) {
|
||||||
state = MY_LEX_CHAR;
|
state = MY_LEX_CHAR;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
lip->ptr += l - 1;
|
lip->skip_binary(l - 1);
|
||||||
}
|
}
|
||||||
while (ident_map[c=yyGet()])
|
while (ident_map[c=lip->yyGet()])
|
||||||
{
|
{
|
||||||
if (my_mbcharlen(cs, c) > 1)
|
if (my_mbcharlen(cs, c) > 1)
|
||||||
{
|
{
|
||||||
int l;
|
int l;
|
||||||
if ((l = my_ismbchar(cs, lip->ptr-1, lip->end_of_query)) == 0)
|
if ((l = my_ismbchar(cs,
|
||||||
|
lip->get_ptr() -1,
|
||||||
|
lip->get_end_of_query())) == 0)
|
||||||
break;
|
break;
|
||||||
lip->ptr += l-1;
|
lip->skip_binary(l-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
for (result_state= c; ident_map[c= yyGet()]; result_state|= c);
|
for (result_state= c; ident_map[c= lip->yyGet()]; result_state|= c);
|
||||||
/* If there were non-ASCII characters, mark that we must convert */
|
/* If there were non-ASCII characters, mark that we must convert */
|
||||||
result_state= result_state & 0x80 ? IDENT_QUOTED : IDENT;
|
result_state= result_state & 0x80 ? IDENT_QUOTED : IDENT;
|
||||||
}
|
}
|
||||||
length= (uint) (lip->ptr - lip->tok_start)-1;
|
length= lip->yyLength();
|
||||||
start= lip->ptr;
|
start= lip->get_ptr();
|
||||||
if (lip->ignore_space)
|
if (lip->ignore_space)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
If we find a space then this can't be an identifier. We notice this
|
If we find a space then this can't be an identifier. We notice this
|
||||||
below by checking start != lex->ptr.
|
below by checking start != lex->ptr.
|
||||||
*/
|
*/
|
||||||
for (; state_map[c] == MY_LEX_SKIP ; c= yyGet());
|
for (; state_map[c] == MY_LEX_SKIP ; c= lip->yyGet());
|
||||||
}
|
}
|
||||||
if (start == lip->ptr && c == '.' && ident_map[yyPeek()])
|
if (start == lip->get_ptr() && c == '.' && ident_map[lip->yyPeek()])
|
||||||
lip->next_state=MY_LEX_IDENT_SEP;
|
lip->next_state=MY_LEX_IDENT_SEP;
|
||||||
else
|
else
|
||||||
{ // '(' must follow directly if function
|
{ // '(' must follow directly if function
|
||||||
yyUnget();
|
lip->yyUnget();
|
||||||
if ((tokval = find_keyword(lip, length,c == '(')))
|
if ((tokval = find_keyword(lip, length, c == '(')))
|
||||||
{
|
{
|
||||||
lip->next_state= MY_LEX_START; // Allow signed numbers
|
lip->next_state= MY_LEX_START; // Allow signed numbers
|
||||||
return(tokval); // Was keyword
|
return(tokval); // Was keyword
|
||||||
}
|
}
|
||||||
yySkip(); // next state does a unget
|
lip->yySkip(); // next state does a unget
|
||||||
}
|
}
|
||||||
yylval->lex_str=get_token(lip, 0, length);
|
yylval->lex_str=get_token(lip, 0, length);
|
||||||
|
|
||||||
@ -735,16 +758,48 @@ int MYSQLlex(void *arg, void *yythd)
|
|||||||
return(result_state); // IDENT or IDENT_QUOTED
|
return(result_state); // IDENT or IDENT_QUOTED
|
||||||
|
|
||||||
case MY_LEX_IDENT_SEP: // Found ident and now '.'
|
case MY_LEX_IDENT_SEP: // Found ident and now '.'
|
||||||
yylval->lex_str.str=(char*) lip->ptr;
|
yylval->lex_str.str= (char*) lip->get_ptr();
|
||||||
yylval->lex_str.length=1;
|
yylval->lex_str.length= 1;
|
||||||
c=yyGet(); // should be '.'
|
c= lip->yyGet(); // should be '.'
|
||||||
lip->next_state= MY_LEX_IDENT_START;// Next is an ident (not a keyword)
|
lip->next_state= MY_LEX_IDENT_START;// Next is an ident (not a keyword)
|
||||||
if (!ident_map[yyPeek()]) // Probably ` or "
|
if (!ident_map[lip->yyPeek()]) // Probably ` or "
|
||||||
lip->next_state= MY_LEX_START;
|
lip->next_state= MY_LEX_START;
|
||||||
return((int) c);
|
return((int) c);
|
||||||
|
|
||||||
case MY_LEX_NUMBER_IDENT: // number or ident which num-start
|
case MY_LEX_NUMBER_IDENT: // number or ident which num-start
|
||||||
while (my_isdigit(cs,(c = yyGet()))) ;
|
if (lip->yyGetLast() == '0')
|
||||||
|
{
|
||||||
|
c= lip->yyGet();
|
||||||
|
if (c == 'x')
|
||||||
|
{
|
||||||
|
while (my_isxdigit(cs,(c = lip->yyGet()))) ;
|
||||||
|
if ((lip->yyLength() >= 3) && !ident_map[c])
|
||||||
|
{
|
||||||
|
/* skip '0x' */
|
||||||
|
yylval->lex_str=get_token(lip, 2, lip->yyLength()-2);
|
||||||
|
return (HEX_NUM);
|
||||||
|
}
|
||||||
|
lip->yyUnget();
|
||||||
|
state= MY_LEX_IDENT_START;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (c == 'b')
|
||||||
|
{
|
||||||
|
while ((c= lip->yyGet()) == '0' || c == '1');
|
||||||
|
if ((lip->yyLength() >= 3) && !ident_map[c])
|
||||||
|
{
|
||||||
|
/* Skip '0b' */
|
||||||
|
yylval->lex_str= get_token(lip, 2, lip->yyLength()-2);
|
||||||
|
return (BIN_NUM);
|
||||||
|
}
|
||||||
|
lip->yyUnget();
|
||||||
|
state= MY_LEX_IDENT_START;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
lip->yyUnget();
|
||||||
|
}
|
||||||
|
|
||||||
|
while (my_isdigit(cs, (c = lip->yyGet()))) ;
|
||||||
if (!ident_map[c])
|
if (!ident_map[c])
|
||||||
{ // Can't be identifier
|
{ // Can't be identifier
|
||||||
state=MY_LEX_INT_OR_REAL;
|
state=MY_LEX_INT_OR_REAL;
|
||||||
@ -753,42 +808,18 @@ int MYSQLlex(void *arg, void *yythd)
|
|||||||
if (c == 'e' || c == 'E')
|
if (c == 'e' || c == 'E')
|
||||||
{
|
{
|
||||||
// The following test is written this way to allow numbers of type 1e1
|
// The following test is written this way to allow numbers of type 1e1
|
||||||
if (my_isdigit(cs,yyPeek()) ||
|
if (my_isdigit(cs,lip->yyPeek()) ||
|
||||||
(c=(yyGet())) == '+' || c == '-')
|
(c=(lip->yyGet())) == '+' || c == '-')
|
||||||
{ // Allow 1E+10
|
{ // Allow 1E+10
|
||||||
if (my_isdigit(cs,yyPeek())) // Number must have digit after sign
|
if (my_isdigit(cs,lip->yyPeek())) // Number must have digit after sign
|
||||||
{
|
{
|
||||||
yySkip();
|
lip->yySkip();
|
||||||
while (my_isdigit(cs,yyGet())) ;
|
while (my_isdigit(cs,lip->yyGet())) ;
|
||||||
yylval->lex_str=get_token(lip, 0, yyLength());
|
yylval->lex_str=get_token(lip, 0, lip->yyLength());
|
||||||
return(FLOAT_NUM);
|
return(FLOAT_NUM);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
yyUnget(); /* purecov: inspected */
|
lip->yyUnget();
|
||||||
}
|
|
||||||
else if (c == 'x' && (lip->ptr - lip->tok_start) == 2 &&
|
|
||||||
lip->tok_start[0] == '0' )
|
|
||||||
{ // Varbinary
|
|
||||||
while (my_isxdigit(cs,(c = yyGet()))) ;
|
|
||||||
if ((lip->ptr - lip->tok_start) >= 4 && !ident_map[c])
|
|
||||||
{
|
|
||||||
/* skip '0x' */
|
|
||||||
yylval->lex_str=get_token(lip, 2, yyLength()-2);
|
|
||||||
return (HEX_NUM);
|
|
||||||
}
|
|
||||||
yyUnget();
|
|
||||||
}
|
|
||||||
else if (c == 'b' && (lip->ptr - lip->tok_start) == 2 &&
|
|
||||||
lip->tok_start[0] == '0' )
|
|
||||||
{ // b'bin-number'
|
|
||||||
while (my_isxdigit(cs,(c = yyGet()))) ;
|
|
||||||
if ((lip->ptr - lip->tok_start) >= 4 && !ident_map[c])
|
|
||||||
{
|
|
||||||
/* Skip '0b' */
|
|
||||||
yylval->lex_str= get_token(lip, 2, yyLength()-2);
|
|
||||||
return (BIN_NUM);
|
|
||||||
}
|
|
||||||
yyUnget();
|
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case MY_LEX_IDENT_START: // We come here after '.'
|
case MY_LEX_IDENT_START: // We come here after '.'
|
||||||
@ -797,44 +828,46 @@ int MYSQLlex(void *arg, void *yythd)
|
|||||||
if (use_mb(cs))
|
if (use_mb(cs))
|
||||||
{
|
{
|
||||||
result_state= IDENT_QUOTED;
|
result_state= IDENT_QUOTED;
|
||||||
while (ident_map[c=yyGet()])
|
while (ident_map[c=lip->yyGet()])
|
||||||
{
|
{
|
||||||
if (my_mbcharlen(cs, c) > 1)
|
if (my_mbcharlen(cs, c) > 1)
|
||||||
{
|
{
|
||||||
int l;
|
int l;
|
||||||
if ((l = my_ismbchar(cs, lip->ptr-1, lip->end_of_query)) == 0)
|
if ((l = my_ismbchar(cs,
|
||||||
|
lip->get_ptr() -1,
|
||||||
|
lip->get_end_of_query())) == 0)
|
||||||
break;
|
break;
|
||||||
lip->ptr += l-1;
|
lip->skip_binary(l-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
for (result_state=0; ident_map[c= yyGet()]; result_state|= c);
|
for (result_state=0; ident_map[c= lip->yyGet()]; result_state|= c);
|
||||||
/* If there were non-ASCII characters, mark that we must convert */
|
/* If there were non-ASCII characters, mark that we must convert */
|
||||||
result_state= result_state & 0x80 ? IDENT_QUOTED : IDENT;
|
result_state= result_state & 0x80 ? IDENT_QUOTED : IDENT;
|
||||||
}
|
}
|
||||||
if (c == '.' && ident_map[yyPeek()])
|
if (c == '.' && ident_map[lip->yyPeek()])
|
||||||
lip->next_state=MY_LEX_IDENT_SEP;// Next is '.'
|
lip->next_state=MY_LEX_IDENT_SEP;// Next is '.'
|
||||||
|
|
||||||
yylval->lex_str= get_token(lip, 0, yyLength());
|
yylval->lex_str= get_token(lip, 0, lip->yyLength());
|
||||||
return(result_state);
|
return(result_state);
|
||||||
|
|
||||||
case MY_LEX_USER_VARIABLE_DELIMITER: // Found quote char
|
case MY_LEX_USER_VARIABLE_DELIMITER: // Found quote char
|
||||||
{
|
{
|
||||||
uint double_quotes= 0;
|
uint double_quotes= 0;
|
||||||
char quote_char= c; // Used char
|
char quote_char= c; // Used char
|
||||||
while ((c=yyGet()))
|
while ((c=lip->yyGet()))
|
||||||
{
|
{
|
||||||
int var_length;
|
int var_length;
|
||||||
if ((var_length= my_mbcharlen(cs, c)) == 1)
|
if ((var_length= my_mbcharlen(cs, c)) == 1)
|
||||||
{
|
{
|
||||||
if (c == quote_char)
|
if (c == quote_char)
|
||||||
{
|
{
|
||||||
if (yyPeek() != quote_char)
|
if (lip->yyPeek() != quote_char)
|
||||||
break;
|
break;
|
||||||
c=yyGet();
|
c=lip->yyGet();
|
||||||
double_quotes++;
|
double_quotes++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -842,78 +875,78 @@ int MYSQLlex(void *arg, void *yythd)
|
|||||||
#ifdef USE_MB
|
#ifdef USE_MB
|
||||||
else if (var_length < 1)
|
else if (var_length < 1)
|
||||||
break; // Error
|
break; // Error
|
||||||
lip->ptr+= var_length-1;
|
lip->skip_binary(var_length-1);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
if (double_quotes)
|
if (double_quotes)
|
||||||
yylval->lex_str=get_quoted_token(lip, 1,
|
yylval->lex_str=get_quoted_token(lip, 1,
|
||||||
yyLength() - double_quotes -1,
|
lip->yyLength() - double_quotes -1,
|
||||||
quote_char);
|
quote_char);
|
||||||
else
|
else
|
||||||
yylval->lex_str=get_token(lip, 1, yyLength() -1);
|
yylval->lex_str=get_token(lip, 1, lip->yyLength() -1);
|
||||||
if (c == quote_char)
|
if (c == quote_char)
|
||||||
yySkip(); // Skip end `
|
lip->yySkip(); // Skip end `
|
||||||
lip->next_state= MY_LEX_START;
|
lip->next_state= MY_LEX_START;
|
||||||
return(IDENT_QUOTED);
|
return(IDENT_QUOTED);
|
||||||
}
|
}
|
||||||
case MY_LEX_INT_OR_REAL: // Complete int or incomplete real
|
case MY_LEX_INT_OR_REAL: // Complete int or incomplete real
|
||||||
if (c != '.')
|
if (c != '.')
|
||||||
{ // Found complete integer number.
|
{ // Found complete integer number.
|
||||||
yylval->lex_str=get_token(lip, 0, yyLength());
|
yylval->lex_str=get_token(lip, 0, lip->yyLength());
|
||||||
return int_token(yylval->lex_str.str,yylval->lex_str.length);
|
return int_token(yylval->lex_str.str,yylval->lex_str.length);
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
case MY_LEX_REAL: // Incomplete real number
|
case MY_LEX_REAL: // Incomplete real number
|
||||||
while (my_isdigit(cs,c = yyGet())) ;
|
while (my_isdigit(cs,c = lip->yyGet())) ;
|
||||||
|
|
||||||
if (c == 'e' || c == 'E')
|
if (c == 'e' || c == 'E')
|
||||||
{
|
{
|
||||||
c = yyGet();
|
c = lip->yyGet();
|
||||||
if (c == '-' || c == '+')
|
if (c == '-' || c == '+')
|
||||||
c = yyGet(); // Skip sign
|
c = lip->yyGet(); // Skip sign
|
||||||
if (!my_isdigit(cs,c))
|
if (!my_isdigit(cs,c))
|
||||||
{ // No digit after sign
|
{ // No digit after sign
|
||||||
state= MY_LEX_CHAR;
|
state= MY_LEX_CHAR;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
while (my_isdigit(cs,yyGet())) ;
|
while (my_isdigit(cs,lip->yyGet())) ;
|
||||||
yylval->lex_str=get_token(lip, 0, yyLength());
|
yylval->lex_str=get_token(lip, 0, lip->yyLength());
|
||||||
return(FLOAT_NUM);
|
return(FLOAT_NUM);
|
||||||
}
|
}
|
||||||
yylval->lex_str=get_token(lip, 0, yyLength());
|
yylval->lex_str=get_token(lip, 0, lip->yyLength());
|
||||||
return(DECIMAL_NUM);
|
return(DECIMAL_NUM);
|
||||||
|
|
||||||
case MY_LEX_HEX_NUMBER: // Found x'hexstring'
|
case MY_LEX_HEX_NUMBER: // Found x'hexstring'
|
||||||
yyGet(); // Skip '
|
lip->yySkip(); // Accept opening '
|
||||||
while (my_isxdigit(cs,(c = yyGet()))) ;
|
while (my_isxdigit(cs, (c= lip->yyGet()))) ;
|
||||||
length=(lip->ptr - lip->tok_start); // Length of hexnum+3
|
if (c != '\'')
|
||||||
if (!(length & 1) || c != '\'')
|
|
||||||
{
|
|
||||||
return(ABORT_SYM); // Illegal hex constant
|
return(ABORT_SYM); // Illegal hex constant
|
||||||
}
|
lip->yySkip(); // Accept closing '
|
||||||
yyGet(); // get_token makes an unget
|
length= lip->yyLength(); // Length of hexnum+3
|
||||||
|
if ((length % 2) == 0)
|
||||||
|
return(ABORT_SYM); // odd number of hex digits
|
||||||
yylval->lex_str=get_token(lip,
|
yylval->lex_str=get_token(lip,
|
||||||
2, // skip x'
|
2, // skip x'
|
||||||
length-3); // don't count x' and last '
|
length-3); // don't count x' and last '
|
||||||
return (HEX_NUM);
|
return (HEX_NUM);
|
||||||
|
|
||||||
case MY_LEX_BIN_NUMBER: // Found b'bin-string'
|
case MY_LEX_BIN_NUMBER: // Found b'bin-string'
|
||||||
yyGet(); // Skip '
|
lip->yySkip(); // Accept opening '
|
||||||
while ((c= yyGet()) == '0' || c == '1');
|
while ((c= lip->yyGet()) == '0' || c == '1');
|
||||||
length= (lip->ptr - lip->tok_start); // Length of bin-num + 3
|
|
||||||
if (c != '\'')
|
if (c != '\'')
|
||||||
return(ABORT_SYM); // Illegal hex constant
|
return(ABORT_SYM); // Illegal hex constant
|
||||||
yyGet(); // get_token makes an unget
|
lip->yySkip(); // Accept closing '
|
||||||
|
length= lip->yyLength(); // Length of bin-num + 3
|
||||||
yylval->lex_str= get_token(lip,
|
yylval->lex_str= get_token(lip,
|
||||||
2, // skip b'
|
2, // skip b'
|
||||||
length-3); // don't count b' and last '
|
length-3); // don't count b' and last '
|
||||||
return (BIN_NUM);
|
return (BIN_NUM);
|
||||||
|
|
||||||
case MY_LEX_CMP_OP: // Incomplete comparison operator
|
case MY_LEX_CMP_OP: // Incomplete comparison operator
|
||||||
if (state_map[yyPeek()] == MY_LEX_CMP_OP ||
|
if (state_map[lip->yyPeek()] == MY_LEX_CMP_OP ||
|
||||||
state_map[yyPeek()] == MY_LEX_LONG_CMP_OP)
|
state_map[lip->yyPeek()] == MY_LEX_LONG_CMP_OP)
|
||||||
yySkip();
|
lip->yySkip();
|
||||||
if ((tokval = find_keyword(lip, (uint) (lip->ptr - lip->tok_start),0)))
|
if ((tokval = find_keyword(lip, lip->yyLength() + 1, 0)))
|
||||||
{
|
{
|
||||||
lip->next_state= MY_LEX_START; // Allow signed numbers
|
lip->next_state= MY_LEX_START; // Allow signed numbers
|
||||||
return(tokval);
|
return(tokval);
|
||||||
@ -922,14 +955,14 @@ int MYSQLlex(void *arg, void *yythd)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case MY_LEX_LONG_CMP_OP: // Incomplete comparison operator
|
case MY_LEX_LONG_CMP_OP: // Incomplete comparison operator
|
||||||
if (state_map[yyPeek()] == MY_LEX_CMP_OP ||
|
if (state_map[lip->yyPeek()] == MY_LEX_CMP_OP ||
|
||||||
state_map[yyPeek()] == MY_LEX_LONG_CMP_OP)
|
state_map[lip->yyPeek()] == MY_LEX_LONG_CMP_OP)
|
||||||
{
|
{
|
||||||
yySkip();
|
lip->yySkip();
|
||||||
if (state_map[yyPeek()] == MY_LEX_CMP_OP)
|
if (state_map[lip->yyPeek()] == MY_LEX_CMP_OP)
|
||||||
yySkip();
|
lip->yySkip();
|
||||||
}
|
}
|
||||||
if ((tokval = find_keyword(lip, (uint) (lip->ptr - lip->tok_start),0)))
|
if ((tokval = find_keyword(lip, lip->yyLength() + 1, 0)))
|
||||||
{
|
{
|
||||||
lip->next_state= MY_LEX_START; // Found long op
|
lip->next_state= MY_LEX_START; // Found long op
|
||||||
return(tokval);
|
return(tokval);
|
||||||
@ -938,12 +971,12 @@ int MYSQLlex(void *arg, void *yythd)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case MY_LEX_BOOL:
|
case MY_LEX_BOOL:
|
||||||
if (c != yyPeek())
|
if (c != lip->yyPeek())
|
||||||
{
|
{
|
||||||
state=MY_LEX_CHAR;
|
state=MY_LEX_CHAR;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
yySkip();
|
lip->yySkip();
|
||||||
tokval = find_keyword(lip,2,0); // Is a bool operator
|
tokval = find_keyword(lip,2,0); // Is a bool operator
|
||||||
lip->next_state= MY_LEX_START; // Allow signed numbers
|
lip->next_state= MY_LEX_START; // Allow signed numbers
|
||||||
return(tokval);
|
return(tokval);
|
||||||
@ -956,7 +989,7 @@ int MYSQLlex(void *arg, void *yythd)
|
|||||||
}
|
}
|
||||||
/* " used for strings */
|
/* " used for strings */
|
||||||
case MY_LEX_STRING: // Incomplete text string
|
case MY_LEX_STRING: // Incomplete text string
|
||||||
if (!(yylval->lex_str.str = get_text(lip)))
|
if (!(yylval->lex_str.str = get_text(lip, 1, 1)))
|
||||||
{
|
{
|
||||||
state= MY_LEX_CHAR; // Read char by char
|
state= MY_LEX_CHAR; // Read char by char
|
||||||
break;
|
break;
|
||||||
@ -966,80 +999,136 @@ int MYSQLlex(void *arg, void *yythd)
|
|||||||
|
|
||||||
case MY_LEX_COMMENT: // Comment
|
case MY_LEX_COMMENT: // Comment
|
||||||
lex->select_lex.options|= OPTION_FOUND_COMMENT;
|
lex->select_lex.options|= OPTION_FOUND_COMMENT;
|
||||||
while ((c = yyGet()) != '\n' && c) ;
|
while ((c = lip->yyGet()) != '\n' && c) ;
|
||||||
yyUnget(); // Safety against eof
|
lip->yyUnget(); // Safety against eof
|
||||||
state = MY_LEX_START; // Try again
|
state = MY_LEX_START; // Try again
|
||||||
break;
|
break;
|
||||||
case MY_LEX_LONG_COMMENT: /* Long C comment? */
|
case MY_LEX_LONG_COMMENT: /* Long C comment? */
|
||||||
if (yyPeek() != '*')
|
if (lip->yyPeek() != '*')
|
||||||
{
|
{
|
||||||
state=MY_LEX_CHAR; // Probable division
|
state=MY_LEX_CHAR; // Probable division
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
yySkip(); // Skip '*'
|
|
||||||
lex->select_lex.options|= OPTION_FOUND_COMMENT;
|
lex->select_lex.options|= OPTION_FOUND_COMMENT;
|
||||||
if (yyPeek() == '!') // MySQL command in comment
|
/* Reject '/' '*', since we might need to turn off the echo */
|
||||||
|
lip->yyUnget();
|
||||||
|
|
||||||
|
if (lip->yyPeekn(2) == '!')
|
||||||
{
|
{
|
||||||
ulong version=MYSQL_VERSION_ID;
|
lip->in_comment= DISCARD_COMMENT;
|
||||||
yySkip();
|
/* Accept '/' '*' '!', but do not keep this marker. */
|
||||||
state=MY_LEX_START;
|
lip->set_echo(false);
|
||||||
if (my_isdigit(cs,yyPeek()))
|
lip->yySkip();
|
||||||
{ // Version number
|
lip->yySkip();
|
||||||
version=strtol((char*) lip->ptr,(char**) &lip->ptr,10);
|
lip->yySkip();
|
||||||
}
|
|
||||||
|
/*
|
||||||
|
The special comment format is very strict:
|
||||||
|
'/' '*' '!', followed by exactly
|
||||||
|
2 digits (major), then 3 digits (minor).
|
||||||
|
*/
|
||||||
|
char version_str[6];
|
||||||
|
version_str[0]= lip->yyPeekn(0);
|
||||||
|
version_str[1]= lip->yyPeekn(1);
|
||||||
|
version_str[2]= lip->yyPeekn(2);
|
||||||
|
version_str[3]= lip->yyPeekn(3);
|
||||||
|
version_str[4]= lip->yyPeekn(4);
|
||||||
|
version_str[5]= 0;
|
||||||
|
if ( my_isdigit(cs, version_str[0])
|
||||||
|
&& my_isdigit(cs, version_str[1])
|
||||||
|
&& my_isdigit(cs, version_str[2])
|
||||||
|
&& my_isdigit(cs, version_str[3])
|
||||||
|
&& my_isdigit(cs, version_str[4])
|
||||||
|
)
|
||||||
|
{
|
||||||
|
ulong version;
|
||||||
|
version=strtol(version_str, NULL, 10);
|
||||||
|
|
||||||
|
/* Accept 'M' 'M' 'm' 'm' 'm' */
|
||||||
|
lip->yySkipn(5);
|
||||||
|
|
||||||
if (version <= MYSQL_VERSION_ID)
|
if (version <= MYSQL_VERSION_ID)
|
||||||
{
|
{
|
||||||
lex->in_comment=1;
|
/* Expand the content of the special comment as real code */
|
||||||
|
lip->set_echo(true);
|
||||||
|
state=MY_LEX_START;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (lip->ptr != lip->end_of_query &&
|
else
|
||||||
((c=yyGet()) != '*' || yyPeek() != '/'))
|
{
|
||||||
|
state=MY_LEX_START;
|
||||||
|
lip->set_echo(true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lip->in_comment= PRESERVE_COMMENT;
|
||||||
|
lip->yySkip(); // Accept /
|
||||||
|
lip->yySkip(); // Accept *
|
||||||
|
}
|
||||||
|
|
||||||
|
while (! lip->eof() &&
|
||||||
|
((c=lip->yyGet()) != '*' || lip->yyPeek() != '/'))
|
||||||
{
|
{
|
||||||
if (c == '\n')
|
if (c == '\n')
|
||||||
lip->yylineno++;
|
lip->yylineno++;
|
||||||
}
|
}
|
||||||
if (lip->ptr != lip->end_of_query)
|
if (! lip->eof())
|
||||||
yySkip(); // remove last '/'
|
lip->yySkip(); // remove last '/'
|
||||||
state = MY_LEX_START; // Try again
|
state = MY_LEX_START; // Try again
|
||||||
|
lip->set_echo(true);
|
||||||
break;
|
break;
|
||||||
case MY_LEX_END_LONG_COMMENT:
|
case MY_LEX_END_LONG_COMMENT:
|
||||||
if (lex->in_comment && yyPeek() == '/')
|
if ((lip->in_comment != NO_COMMENT) && lip->yyPeek() == '/')
|
||||||
{
|
{
|
||||||
yySkip();
|
/* Reject '*' '/' */
|
||||||
lex->in_comment=0;
|
lip->yyUnget();
|
||||||
|
/* Accept '*' '/', with the proper echo */
|
||||||
|
lip->set_echo(lip->in_comment == PRESERVE_COMMENT);
|
||||||
|
lip->yySkipn(2);
|
||||||
|
/* And start recording the tokens again */
|
||||||
|
lip->set_echo(true);
|
||||||
|
lip->in_comment=NO_COMMENT;
|
||||||
state=MY_LEX_START;
|
state=MY_LEX_START;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
state=MY_LEX_CHAR; // Return '*'
|
state=MY_LEX_CHAR; // Return '*'
|
||||||
break;
|
break;
|
||||||
case MY_LEX_SET_VAR: // Check if ':='
|
case MY_LEX_SET_VAR: // Check if ':='
|
||||||
if (yyPeek() != '=')
|
if (lip->yyPeek() != '=')
|
||||||
{
|
{
|
||||||
state=MY_LEX_CHAR; // Return ':'
|
state=MY_LEX_CHAR; // Return ':'
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
yySkip();
|
lip->yySkip();
|
||||||
return (SET_VAR);
|
return (SET_VAR);
|
||||||
case MY_LEX_SEMICOLON: // optional line terminator
|
case MY_LEX_SEMICOLON: // optional line terminator
|
||||||
if (yyPeek())
|
if (lip->yyPeek())
|
||||||
{
|
{
|
||||||
if ((thd->client_capabilities & CLIENT_MULTI_STATEMENTS) &&
|
if ((thd->client_capabilities & CLIENT_MULTI_STATEMENTS) &&
|
||||||
!lip->stmt_prepare_mode)
|
!lip->stmt_prepare_mode)
|
||||||
{
|
{
|
||||||
lex->safe_to_cache_query= 0;
|
lex->safe_to_cache_query= 0;
|
||||||
lip->found_semicolon= lip->ptr;
|
lip->found_semicolon= lip->get_ptr();
|
||||||
thd->server_status|= SERVER_MORE_RESULTS_EXISTS;
|
thd->server_status|= SERVER_MORE_RESULTS_EXISTS;
|
||||||
lip->next_state= MY_LEX_END;
|
lip->next_state= MY_LEX_END;
|
||||||
|
lip->set_echo(true);
|
||||||
return (END_OF_INPUT);
|
return (END_OF_INPUT);
|
||||||
}
|
}
|
||||||
state= MY_LEX_CHAR; // Return ';'
|
state= MY_LEX_CHAR; // Return ';'
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* fall true */
|
lip->next_state=MY_LEX_END; // Mark for next loop
|
||||||
|
return(END_OF_INPUT);
|
||||||
case MY_LEX_EOL:
|
case MY_LEX_EOL:
|
||||||
if (lip->ptr >= lip->end_of_query)
|
if (lip->eof())
|
||||||
{
|
{
|
||||||
|
lip->yyUnget(); // Reject the last '\0'
|
||||||
|
lip->set_echo(false);
|
||||||
|
lip->yySkip();
|
||||||
|
lip->set_echo(true);
|
||||||
lip->next_state=MY_LEX_END; // Mark for next loop
|
lip->next_state=MY_LEX_END; // Mark for next loop
|
||||||
return(END_OF_INPUT);
|
return(END_OF_INPUT);
|
||||||
}
|
}
|
||||||
@ -1051,16 +1140,16 @@ int MYSQLlex(void *arg, void *yythd)
|
|||||||
|
|
||||||
/* Actually real shouldn't start with . but allow them anyhow */
|
/* Actually real shouldn't start with . but allow them anyhow */
|
||||||
case MY_LEX_REAL_OR_POINT:
|
case MY_LEX_REAL_OR_POINT:
|
||||||
if (my_isdigit(cs,yyPeek()))
|
if (my_isdigit(cs,lip->yyPeek()))
|
||||||
state = MY_LEX_REAL; // Real
|
state = MY_LEX_REAL; // Real
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
state= MY_LEX_IDENT_SEP; // return '.'
|
state= MY_LEX_IDENT_SEP; // return '.'
|
||||||
yyUnget(); // Put back '.'
|
lip->yyUnget(); // Put back '.'
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case MY_LEX_USER_END: // end '@' of user@hostname
|
case MY_LEX_USER_END: // end '@' of user@hostname
|
||||||
switch (state_map[yyPeek()]) {
|
switch (state_map[lip->yyPeek()]) {
|
||||||
case MY_LEX_STRING:
|
case MY_LEX_STRING:
|
||||||
case MY_LEX_USER_VARIABLE_DELIMITER:
|
case MY_LEX_USER_VARIABLE_DELIMITER:
|
||||||
case MY_LEX_STRING_OR_DELIMITER:
|
case MY_LEX_STRING_OR_DELIMITER:
|
||||||
@ -1072,20 +1161,20 @@ int MYSQLlex(void *arg, void *yythd)
|
|||||||
lip->next_state=MY_LEX_HOSTNAME;
|
lip->next_state=MY_LEX_HOSTNAME;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
yylval->lex_str.str=(char*) lip->ptr;
|
yylval->lex_str.str=(char*) lip->get_ptr();
|
||||||
yylval->lex_str.length=1;
|
yylval->lex_str.length=1;
|
||||||
return((int) '@');
|
return((int) '@');
|
||||||
case MY_LEX_HOSTNAME: // end '@' of user@hostname
|
case MY_LEX_HOSTNAME: // end '@' of user@hostname
|
||||||
for (c=yyGet() ;
|
for (c=lip->yyGet() ;
|
||||||
my_isalnum(cs,c) || c == '.' || c == '_' || c == '$';
|
my_isalnum(cs,c) || c == '.' || c == '_' || c == '$';
|
||||||
c= yyGet()) ;
|
c= lip->yyGet()) ;
|
||||||
yylval->lex_str=get_token(lip, 0, yyLength());
|
yylval->lex_str=get_token(lip, 0, lip->yyLength());
|
||||||
return(LEX_HOSTNAME);
|
return(LEX_HOSTNAME);
|
||||||
case MY_LEX_SYSTEM_VAR:
|
case MY_LEX_SYSTEM_VAR:
|
||||||
yylval->lex_str.str=(char*) lip->ptr;
|
yylval->lex_str.str=(char*) lip->get_ptr();
|
||||||
yylval->lex_str.length=1;
|
yylval->lex_str.length=1;
|
||||||
yySkip(); // Skip '@'
|
lip->yySkip(); // Skip '@'
|
||||||
lip->next_state= (state_map[yyPeek()] ==
|
lip->next_state= (state_map[lip->yyPeek()] ==
|
||||||
MY_LEX_USER_VARIABLE_DELIMITER ?
|
MY_LEX_USER_VARIABLE_DELIMITER ?
|
||||||
MY_LEX_OPERATOR_OR_IDENT :
|
MY_LEX_OPERATOR_OR_IDENT :
|
||||||
MY_LEX_IDENT_OR_KEYWORD);
|
MY_LEX_IDENT_OR_KEYWORD);
|
||||||
@ -1097,18 +1186,18 @@ int MYSQLlex(void *arg, void *yythd)
|
|||||||
[(global | local | session) .]variable_name
|
[(global | local | session) .]variable_name
|
||||||
*/
|
*/
|
||||||
|
|
||||||
for (result_state= 0; ident_map[c= yyGet()]; result_state|= c);
|
for (result_state= 0; ident_map[c= lip->yyGet()]; result_state|= c);
|
||||||
/* If there were non-ASCII characters, mark that we must convert */
|
/* If there were non-ASCII characters, mark that we must convert */
|
||||||
result_state= result_state & 0x80 ? IDENT_QUOTED : IDENT;
|
result_state= result_state & 0x80 ? IDENT_QUOTED : IDENT;
|
||||||
|
|
||||||
if (c == '.')
|
if (c == '.')
|
||||||
lip->next_state=MY_LEX_IDENT_SEP;
|
lip->next_state=MY_LEX_IDENT_SEP;
|
||||||
length= (uint) (lip->ptr - lip->tok_start)-1;
|
length= lip->yyLength();
|
||||||
if (length == 0)
|
if (length == 0)
|
||||||
return(ABORT_SYM); // Names must be nonempty.
|
return(ABORT_SYM); // Names must be nonempty.
|
||||||
if ((tokval= find_keyword(lip, length,0)))
|
if ((tokval= find_keyword(lip, length,0)))
|
||||||
{
|
{
|
||||||
yyUnget(); // Put back 'c'
|
lip->yyUnget(); // Put back 'c'
|
||||||
return(tokval); // Was keyword
|
return(tokval); // Was keyword
|
||||||
}
|
}
|
||||||
yylval->lex_str=get_token(lip, 0, length);
|
yylval->lex_str=get_token(lip, 0, length);
|
||||||
@ -1135,7 +1224,7 @@ Alter_info::Alter_info(const Alter_info &rhs, MEM_ROOT *mem_root)
|
|||||||
/*
|
/*
|
||||||
Make deep copies of used objects.
|
Make deep copies of used objects.
|
||||||
This is not a fully deep copy - clone() implementations
|
This is not a fully deep copy - clone() implementations
|
||||||
of Alter_drop, Alter_column, Key, foreign_key, key_part_spec
|
of Alter_drop, Alter_column, Key, foreign_key, Key_part_spec
|
||||||
do not copy string constants. At the same length the only
|
do not copy string constants. At the same length the only
|
||||||
reason we make a copy currently is that ALTER/CREATE TABLE
|
reason we make a copy currently is that ALTER/CREATE TABLE
|
||||||
code changes input Alter_info definitions, but string
|
code changes input Alter_info definitions, but string
|
||||||
@ -1149,32 +1238,31 @@ Alter_info::Alter_info(const Alter_info &rhs, MEM_ROOT *mem_root)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
void trim_whitespace(CHARSET_INFO *cs, LEX_STRING *str)
|
||||||
Skip comment in the end of statement.
|
|
||||||
|
|
||||||
SYNOPSIS
|
|
||||||
skip_rear_comments()
|
|
||||||
cs character set
|
|
||||||
begin pointer to the beginning of statement
|
|
||||||
end pointer to the end of statement
|
|
||||||
|
|
||||||
DESCRIPTION
|
|
||||||
The function is intended to trim comments at the end of the statement.
|
|
||||||
|
|
||||||
RETURN
|
|
||||||
Pointer to the last non-comment symbol of the statement.
|
|
||||||
*/
|
|
||||||
|
|
||||||
const char *skip_rear_comments(CHARSET_INFO *cs, const char *begin,
|
|
||||||
const char *end)
|
|
||||||
{
|
{
|
||||||
while (begin < end && (end[-1] == '*' ||
|
/*
|
||||||
end[-1] == '/' || end[-1] == ';' ||
|
TODO:
|
||||||
my_isspace(cs, end[-1])))
|
This code assumes that there are no multi-bytes characters
|
||||||
end-= 1;
|
that can be considered white-space.
|
||||||
return end;
|
*/
|
||||||
|
|
||||||
|
while ((str->length > 0) && (my_isspace(cs, str->str[0])))
|
||||||
|
{
|
||||||
|
str->length --;
|
||||||
|
str->str ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
FIXME:
|
||||||
|
Also, parsing backward is not safe with multi bytes characters
|
||||||
|
*/
|
||||||
|
while ((str->length > 0) && (my_isspace(cs, str->str[str->length-1])))
|
||||||
|
{
|
||||||
|
str->length --;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
st_select_lex structures initialisations
|
st_select_lex structures initialisations
|
||||||
*/
|
*/
|
||||||
|
342
sql/sql_lex.h
342
sql/sql_lex.h
@ -850,14 +850,14 @@ public:
|
|||||||
List<Alter_drop> drop_list;
|
List<Alter_drop> drop_list;
|
||||||
List<Alter_column> alter_list;
|
List<Alter_column> alter_list;
|
||||||
List<Key> key_list;
|
List<Key> key_list;
|
||||||
List<create_field> create_list;
|
List<Create_field> create_list;
|
||||||
uint flags;
|
uint flags;
|
||||||
enum enum_enable_or_disable keys_onoff;
|
enum enum_enable_or_disable keys_onoff;
|
||||||
enum tablespace_op_type tablespace_op;
|
enum tablespace_op_type tablespace_op;
|
||||||
List<char> partition_names;
|
List<char> partition_names;
|
||||||
uint no_parts;
|
uint no_parts;
|
||||||
enum_alter_table_change_level change_level;
|
enum_alter_table_change_level change_level;
|
||||||
create_field *datetime_field;
|
Create_field *datetime_field;
|
||||||
bool error_if_not_empty;
|
bool error_if_not_empty;
|
||||||
|
|
||||||
|
|
||||||
@ -1048,9 +1048,41 @@ struct st_parsing_options
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
The state of the lexical parser, when parsing comments.
|
||||||
|
*/
|
||||||
|
enum enum_comment_state
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
Not parsing comments.
|
||||||
|
*/
|
||||||
|
NO_COMMENT,
|
||||||
|
/**
|
||||||
|
Parsing comments that need to be preserved.
|
||||||
|
Typically, these are user comments '/' '*' ... '*' '/'.
|
||||||
|
*/
|
||||||
|
PRESERVE_COMMENT,
|
||||||
|
/**
|
||||||
|
Parsing comments that need to be discarded.
|
||||||
|
Typically, these are special comments '/' '*' '!' ... '*' '/',
|
||||||
|
or '/' '*' '!' 'M' 'M' 'm' 'm' 'm' ... '*' '/', where the comment
|
||||||
|
markers should not be expanded.
|
||||||
|
*/
|
||||||
|
DISCARD_COMMENT
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This class represents the character input stream consumed during
|
This class represents the character input stream consumed during
|
||||||
lexical analysis.
|
lexical analysis.
|
||||||
|
In addition to consuming the input stream, this class performs some
|
||||||
|
comment pre processing, by filtering out out of bound special text
|
||||||
|
from the query input stream.
|
||||||
|
Two buffers, with pointers inside each buffers, are maintained in
|
||||||
|
parallel. The 'raw' buffer is the original query text, which may
|
||||||
|
contain out-of-bound comments. The 'cpp' (for comments pre processor)
|
||||||
|
is the pre-processed buffer that contains only the query text that
|
||||||
|
should be seen once out-of-bound data is removed.
|
||||||
*/
|
*/
|
||||||
class Lex_input_stream
|
class Lex_input_stream
|
||||||
{
|
{
|
||||||
@ -1058,6 +1090,218 @@ public:
|
|||||||
Lex_input_stream(THD *thd, const char* buff, unsigned int length);
|
Lex_input_stream(THD *thd, const char* buff, unsigned int length);
|
||||||
~Lex_input_stream();
|
~Lex_input_stream();
|
||||||
|
|
||||||
|
/**
|
||||||
|
Set the echo mode.
|
||||||
|
When echo is true, characters parsed from the raw input stream are
|
||||||
|
preserved. When false, characters parsed are silently ignored.
|
||||||
|
@param echo the echo mode.
|
||||||
|
*/
|
||||||
|
void set_echo(bool echo)
|
||||||
|
{
|
||||||
|
m_echo= echo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Skip binary from the input stream.
|
||||||
|
@param n number of bytes to accept.
|
||||||
|
*/
|
||||||
|
void skip_binary(int n)
|
||||||
|
{
|
||||||
|
if (m_echo)
|
||||||
|
{
|
||||||
|
memcpy(m_cpp_ptr, m_ptr, n);
|
||||||
|
m_cpp_ptr += n;
|
||||||
|
}
|
||||||
|
m_ptr += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get a character, and advance in the stream.
|
||||||
|
@return the next character to parse.
|
||||||
|
*/
|
||||||
|
char yyGet()
|
||||||
|
{
|
||||||
|
char c= *m_ptr++;
|
||||||
|
if (m_echo)
|
||||||
|
*m_cpp_ptr++ = c;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get the last character accepted.
|
||||||
|
@return the last character accepted.
|
||||||
|
*/
|
||||||
|
char yyGetLast()
|
||||||
|
{
|
||||||
|
return m_ptr[-1];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Look at the next character to parse, but do not accept it.
|
||||||
|
*/
|
||||||
|
char yyPeek()
|
||||||
|
{
|
||||||
|
return m_ptr[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Look ahead at some character to parse.
|
||||||
|
@param n offset of the character to look up
|
||||||
|
*/
|
||||||
|
char yyPeekn(int n)
|
||||||
|
{
|
||||||
|
return m_ptr[n];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Cancel the effect of the last yyGet() or yySkip().
|
||||||
|
Note that the echo mode should not change between calls to yyGet / yySkip
|
||||||
|
and yyUnget. The caller is responsible for ensuring that.
|
||||||
|
*/
|
||||||
|
void yyUnget()
|
||||||
|
{
|
||||||
|
m_ptr--;
|
||||||
|
if (m_echo)
|
||||||
|
m_cpp_ptr--;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Accept a character, by advancing the input stream.
|
||||||
|
*/
|
||||||
|
void yySkip()
|
||||||
|
{
|
||||||
|
if (m_echo)
|
||||||
|
*m_cpp_ptr++ = *m_ptr++;
|
||||||
|
else
|
||||||
|
m_ptr++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Accept multiple characters at once.
|
||||||
|
@param n the number of characters to accept.
|
||||||
|
*/
|
||||||
|
void yySkipn(int n)
|
||||||
|
{
|
||||||
|
if (m_echo)
|
||||||
|
{
|
||||||
|
memcpy(m_cpp_ptr, m_ptr, n);
|
||||||
|
m_cpp_ptr += n;
|
||||||
|
}
|
||||||
|
m_ptr += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
End of file indicator for the query text to parse.
|
||||||
|
@return true if there are no more characters to parse
|
||||||
|
*/
|
||||||
|
bool eof()
|
||||||
|
{
|
||||||
|
return (m_ptr >= m_end_of_query);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
End of file indicator for the query text to parse.
|
||||||
|
@param n number of characters expected
|
||||||
|
@return true if there are less than n characters to parse
|
||||||
|
*/
|
||||||
|
bool eof(int n)
|
||||||
|
{
|
||||||
|
return ((m_ptr + n) >= m_end_of_query);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get the raw query buffer. */
|
||||||
|
const char* get_buf()
|
||||||
|
{
|
||||||
|
return m_buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get the pre-processed query buffer. */
|
||||||
|
const char* get_cpp_buf()
|
||||||
|
{
|
||||||
|
return m_cpp_buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get the end of the raw query buffer. */
|
||||||
|
const char* get_end_of_query()
|
||||||
|
{
|
||||||
|
return m_end_of_query;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Mark the stream position as the start of a new token. */
|
||||||
|
void start_token()
|
||||||
|
{
|
||||||
|
m_tok_start_prev= m_tok_start;
|
||||||
|
m_tok_start= m_ptr;
|
||||||
|
m_tok_end= m_ptr;
|
||||||
|
|
||||||
|
m_cpp_tok_start_prev= m_cpp_tok_start;
|
||||||
|
m_cpp_tok_start= m_cpp_ptr;
|
||||||
|
m_cpp_tok_end= m_cpp_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Adjust the starting position of the current token.
|
||||||
|
This is used to compensate for starting whitespace.
|
||||||
|
*/
|
||||||
|
void restart_token()
|
||||||
|
{
|
||||||
|
m_tok_start= m_ptr;
|
||||||
|
m_cpp_tok_start= m_cpp_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get the token start position, in the raw buffer. */
|
||||||
|
const char* get_tok_start()
|
||||||
|
{
|
||||||
|
return m_tok_start;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get the token start position, in the pre-processed buffer. */
|
||||||
|
const char* get_cpp_tok_start()
|
||||||
|
{
|
||||||
|
return m_cpp_tok_start;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get the token end position, in the raw buffer. */
|
||||||
|
const char* get_tok_end()
|
||||||
|
{
|
||||||
|
return m_tok_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get the token end position, in the pre-processed buffer. */
|
||||||
|
const char* get_cpp_tok_end()
|
||||||
|
{
|
||||||
|
return m_cpp_tok_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get the previous token start position, in the raw buffer. */
|
||||||
|
const char* get_tok_start_prev()
|
||||||
|
{
|
||||||
|
return m_tok_start_prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get the current stream pointer, in the raw buffer. */
|
||||||
|
const char* get_ptr()
|
||||||
|
{
|
||||||
|
return m_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get the current stream pointer, in the pre-processed buffer. */
|
||||||
|
const char* get_cpp_ptr()
|
||||||
|
{
|
||||||
|
return m_cpp_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get the length of the current token, in the raw buffer. */
|
||||||
|
uint yyLength()
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
The assumption is that the lexical analyser is always 1 character ahead,
|
||||||
|
which the -1 account for.
|
||||||
|
*/
|
||||||
|
DBUG_ASSERT(m_ptr > m_tok_start);
|
||||||
|
return (uint) ((m_ptr - m_tok_start) - 1);
|
||||||
|
}
|
||||||
|
|
||||||
/** Current thread. */
|
/** Current thread. */
|
||||||
THD *m_thd;
|
THD *m_thd;
|
||||||
|
|
||||||
@ -1070,37 +1314,74 @@ public:
|
|||||||
/** Interface with bison, value of the last token parsed. */
|
/** Interface with bison, value of the last token parsed. */
|
||||||
LEX_YYSTYPE yylval;
|
LEX_YYSTYPE yylval;
|
||||||
|
|
||||||
/** Pointer to the current position in the input stream. */
|
private:
|
||||||
const char* ptr;
|
/** Pointer to the current position in the raw input stream. */
|
||||||
|
const char* m_ptr;
|
||||||
|
|
||||||
/** Starting position of the last token parsed. */
|
/** Starting position of the last token parsed, in the raw buffer. */
|
||||||
const char* tok_start;
|
const char* m_tok_start;
|
||||||
|
|
||||||
/** Ending position of the last token parsed. */
|
/** Ending position of the previous token parsed, in the raw buffer. */
|
||||||
const char* tok_end;
|
const char* m_tok_end;
|
||||||
|
|
||||||
/** End of the query text in the input stream. */
|
/** End of the query text in the input stream, in the raw buffer. */
|
||||||
const char* end_of_query;
|
const char* m_end_of_query;
|
||||||
|
|
||||||
/** Starting position of the previous token parsed. */
|
/** Starting position of the previous token parsed, in the raw buffer. */
|
||||||
const char* tok_start_prev;
|
const char* m_tok_start_prev;
|
||||||
|
|
||||||
/** Begining of the query text in the input stream. */
|
/** Begining of the query text in the input stream, in the raw buffer. */
|
||||||
const char* buf;
|
const char* m_buf;
|
||||||
|
|
||||||
|
/** Echo the parsed stream to the pre-processed buffer. */
|
||||||
|
bool m_echo;
|
||||||
|
|
||||||
|
/** Pre-processed buffer. */
|
||||||
|
char* m_cpp_buf;
|
||||||
|
|
||||||
|
/** Pointer to the current position in the pre-processed input stream. */
|
||||||
|
char* m_cpp_ptr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Starting position of the last token parsed,
|
||||||
|
in the pre-processed buffer.
|
||||||
|
*/
|
||||||
|
const char* m_cpp_tok_start;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Starting position of the previous token parsed,
|
||||||
|
in the pre-procedded buffer.
|
||||||
|
*/
|
||||||
|
const char* m_cpp_tok_start_prev;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Ending position of the previous token parsed,
|
||||||
|
in the pre-processed buffer.
|
||||||
|
*/
|
||||||
|
const char* m_cpp_tok_end;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
/** Current state of the lexical analyser. */
|
/** Current state of the lexical analyser. */
|
||||||
enum my_lex_states next_state;
|
enum my_lex_states next_state;
|
||||||
|
|
||||||
/** Position of ';' in the stream, to delimit multiple queries. */
|
/**
|
||||||
|
Position of ';' in the stream, to delimit multiple queries.
|
||||||
|
This delimiter is in the raw buffer.
|
||||||
|
*/
|
||||||
const char* found_semicolon;
|
const char* found_semicolon;
|
||||||
|
|
||||||
/** SQL_MODE = IGNORE_SPACE. */
|
/** SQL_MODE = IGNORE_SPACE. */
|
||||||
bool ignore_space;
|
bool ignore_space;
|
||||||
/*
|
|
||||||
|
/**
|
||||||
TRUE if we're parsing a prepared statement: in this mode
|
TRUE if we're parsing a prepared statement: in this mode
|
||||||
we should allow placeholders and disallow multi-statements.
|
we should allow placeholders and disallow multi-statements.
|
||||||
*/
|
*/
|
||||||
bool stmt_prepare_mode;
|
bool stmt_prepare_mode;
|
||||||
|
|
||||||
|
/** State of the lexical analyser for comments. */
|
||||||
|
enum_comment_state in_comment;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -1138,8 +1419,17 @@ typedef struct st_lex : public Query_tables_list
|
|||||||
CHARSET_INFO *charset, *underscore_charset;
|
CHARSET_INFO *charset, *underscore_charset;
|
||||||
/* store original leaf_tables for INSERT SELECT and PS/SP */
|
/* store original leaf_tables for INSERT SELECT and PS/SP */
|
||||||
TABLE_LIST *leaf_tables_insert;
|
TABLE_LIST *leaf_tables_insert;
|
||||||
/* Position (first character index) of SELECT of CREATE VIEW statement */
|
|
||||||
uint create_view_select_start;
|
/** Start of SELECT of CREATE VIEW statement */
|
||||||
|
const char* create_view_select_start;
|
||||||
|
/** End of SELECT of CREATE VIEW statement */
|
||||||
|
const char* create_view_select_end;
|
||||||
|
|
||||||
|
/** Start of 'ON <table>', in trigger statements. */
|
||||||
|
const char* raw_trg_on_table_name_begin;
|
||||||
|
/** End of 'ON <table>', in trigger statements. */
|
||||||
|
const char* raw_trg_on_table_name_end;
|
||||||
|
|
||||||
/* Partition info structure filled in by PARTITION BY parse part */
|
/* Partition info structure filled in by PARTITION BY parse part */
|
||||||
partition_info *part_info;
|
partition_info *part_info;
|
||||||
|
|
||||||
@ -1149,8 +1439,8 @@ typedef struct st_lex : public Query_tables_list
|
|||||||
*/
|
*/
|
||||||
LEX_USER *definer;
|
LEX_USER *definer;
|
||||||
|
|
||||||
List<key_part_spec> col_list;
|
List<Key_part_spec> col_list;
|
||||||
List<key_part_spec> ref_list;
|
List<Key_part_spec> ref_list;
|
||||||
List<String> interval_list;
|
List<String> interval_list;
|
||||||
List<LEX_USER> users_list;
|
List<LEX_USER> users_list;
|
||||||
List<LEX_COLUMN> columns;
|
List<LEX_COLUMN> columns;
|
||||||
@ -1176,7 +1466,7 @@ typedef struct st_lex : public Query_tables_list
|
|||||||
List<LEX_STRING> db_list;
|
List<LEX_STRING> db_list;
|
||||||
|
|
||||||
SQL_LIST proc_list, auxiliary_table_list, save_list;
|
SQL_LIST proc_list, auxiliary_table_list, save_list;
|
||||||
create_field *last_field;
|
Create_field *last_field;
|
||||||
Item_sum *in_sum_func;
|
Item_sum *in_sum_func;
|
||||||
udf_func udf;
|
udf_func udf;
|
||||||
HA_CHECK_OPT check_opt; // check/repair options
|
HA_CHECK_OPT check_opt; // check/repair options
|
||||||
@ -1238,7 +1528,9 @@ typedef struct st_lex : public Query_tables_list
|
|||||||
uint8 create_view_algorithm;
|
uint8 create_view_algorithm;
|
||||||
uint8 create_view_check;
|
uint8 create_view_check;
|
||||||
bool drop_if_exists, drop_temporary, local_file, one_shot_set;
|
bool drop_if_exists, drop_temporary, local_file, one_shot_set;
|
||||||
bool in_comment, verbose, no_write_to_binlog;
|
|
||||||
|
bool verbose, no_write_to_binlog;
|
||||||
|
|
||||||
bool tx_chain, tx_release;
|
bool tx_chain, tx_release;
|
||||||
/*
|
/*
|
||||||
Special JOIN::prepare mode: changing of query is prohibited.
|
Special JOIN::prepare mode: changing of query is prohibited.
|
||||||
@ -1306,6 +1598,8 @@ typedef struct st_lex : public Query_tables_list
|
|||||||
*/
|
*/
|
||||||
const char *stmt_definition_begin;
|
const char *stmt_definition_begin;
|
||||||
|
|
||||||
|
const char *stmt_definition_end;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Pointers to part of LOAD DATA statement that should be rewritten
|
Pointers to part of LOAD DATA statement that should be rewritten
|
||||||
during replication ("LOCAL 'filename' REPLACE INTO" part).
|
during replication ("LOCAL 'filename' REPLACE INTO" part).
|
||||||
@ -1434,8 +1728,8 @@ extern void lex_free(void);
|
|||||||
extern void lex_start(THD *thd);
|
extern void lex_start(THD *thd);
|
||||||
extern void lex_end(LEX *lex);
|
extern void lex_end(LEX *lex);
|
||||||
extern int MYSQLlex(void *arg, void *yythd);
|
extern int MYSQLlex(void *arg, void *yythd);
|
||||||
extern const char *skip_rear_comments(CHARSET_INFO *cs, const char *ubegin,
|
|
||||||
const char *uend);
|
extern void trim_whitespace(CHARSET_INFO *cs, LEX_STRING *str);
|
||||||
|
|
||||||
extern bool is_lex_native_function(const LEX_STRING *name);
|
extern bool is_lex_native_function(const LEX_STRING *name);
|
||||||
|
|
||||||
|
@ -5353,12 +5353,11 @@ void mysql_parse(THD *thd, const char *inBuf, uint length,
|
|||||||
sp_cache_flush_obsolete(&thd->sp_func_cache);
|
sp_cache_flush_obsolete(&thd->sp_func_cache);
|
||||||
|
|
||||||
Lex_input_stream lip(thd, inBuf, length);
|
Lex_input_stream lip(thd, inBuf, length);
|
||||||
thd->m_lip= &lip;
|
|
||||||
|
|
||||||
int err= MYSQLparse(thd);
|
bool err= parse_sql(thd, &lip);
|
||||||
*found_semicolon= lip.found_semicolon;
|
*found_semicolon= lip.found_semicolon;
|
||||||
|
|
||||||
if (!err && ! thd->is_fatal_error)
|
if (!err)
|
||||||
{
|
{
|
||||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||||
if (mqh_used && thd->user_connect &&
|
if (mqh_used && thd->user_connect &&
|
||||||
@ -5381,8 +5380,8 @@ void mysql_parse(THD *thd, const char *inBuf, uint length,
|
|||||||
PROCESSLIST.
|
PROCESSLIST.
|
||||||
Note that we don't need LOCK_thread_count to modify query_length.
|
Note that we don't need LOCK_thread_count to modify query_length.
|
||||||
*/
|
*/
|
||||||
if (lip.found_semicolon &&
|
if (*found_semicolon &&
|
||||||
(thd->query_length= (ulong)(lip.found_semicolon - thd->query)))
|
(thd->query_length= (ulong)(*found_semicolon - thd->query)))
|
||||||
thd->query_length--;
|
thd->query_length--;
|
||||||
/* Actually execute the query */
|
/* Actually execute the query */
|
||||||
mysql_execute_command(thd);
|
mysql_execute_command(thd);
|
||||||
@ -5436,12 +5435,10 @@ bool mysql_test_parse_for_slave(THD *thd, char *inBuf, uint length)
|
|||||||
DBUG_ENTER("mysql_test_parse_for_slave");
|
DBUG_ENTER("mysql_test_parse_for_slave");
|
||||||
|
|
||||||
Lex_input_stream lip(thd, inBuf, length);
|
Lex_input_stream lip(thd, inBuf, length);
|
||||||
thd->m_lip= &lip;
|
|
||||||
lex_start(thd);
|
lex_start(thd);
|
||||||
mysql_reset_thd_for_next_command(thd);
|
mysql_reset_thd_for_next_command(thd);
|
||||||
int err= MYSQLparse((void*) thd);
|
|
||||||
|
|
||||||
if (!err && ! thd->is_fatal_error &&
|
if (!parse_sql(thd, &lip) &&
|
||||||
all_tables_not_ok(thd,(TABLE_LIST*) lex->select_lex.table_list.first))
|
all_tables_not_ok(thd,(TABLE_LIST*) lex->select_lex.table_list.first))
|
||||||
error= 1; /* Ignore question */
|
error= 1; /* Ignore question */
|
||||||
thd->end_statement();
|
thd->end_statement();
|
||||||
@ -5466,7 +5463,7 @@ bool add_field_to_list(THD *thd, LEX_STRING *field_name, enum_field_types type,
|
|||||||
List<String> *interval_list, CHARSET_INFO *cs,
|
List<String> *interval_list, CHARSET_INFO *cs,
|
||||||
uint uint_geom_type)
|
uint uint_geom_type)
|
||||||
{
|
{
|
||||||
register create_field *new_field;
|
register Create_field *new_field;
|
||||||
LEX *lex= thd->lex;
|
LEX *lex= thd->lex;
|
||||||
DBUG_ENTER("add_field_to_list");
|
DBUG_ENTER("add_field_to_list");
|
||||||
|
|
||||||
@ -5479,7 +5476,7 @@ bool add_field_to_list(THD *thd, LEX_STRING *field_name, enum_field_types type,
|
|||||||
if (type_modifier & PRI_KEY_FLAG)
|
if (type_modifier & PRI_KEY_FLAG)
|
||||||
{
|
{
|
||||||
Key *key;
|
Key *key;
|
||||||
lex->col_list.push_back(new key_part_spec(field_name->str, 0));
|
lex->col_list.push_back(new Key_part_spec(field_name->str, 0));
|
||||||
key= new Key(Key::PRIMARY, NullS,
|
key= new Key(Key::PRIMARY, NullS,
|
||||||
&default_key_create_info,
|
&default_key_create_info,
|
||||||
0, lex->col_list);
|
0, lex->col_list);
|
||||||
@ -5489,7 +5486,7 @@ bool add_field_to_list(THD *thd, LEX_STRING *field_name, enum_field_types type,
|
|||||||
if (type_modifier & (UNIQUE_FLAG | UNIQUE_KEY_FLAG))
|
if (type_modifier & (UNIQUE_FLAG | UNIQUE_KEY_FLAG))
|
||||||
{
|
{
|
||||||
Key *key;
|
Key *key;
|
||||||
lex->col_list.push_back(new key_part_spec(field_name->str, 0));
|
lex->col_list.push_back(new Key_part_spec(field_name->str, 0));
|
||||||
key= new Key(Key::UNIQUE, NullS,
|
key= new Key(Key::UNIQUE, NullS,
|
||||||
&default_key_create_info, 0,
|
&default_key_create_info, 0,
|
||||||
lex->col_list);
|
lex->col_list);
|
||||||
@ -5547,7 +5544,7 @@ bool add_field_to_list(THD *thd, LEX_STRING *field_name, enum_field_types type,
|
|||||||
WARN_DEPRECATED(thd, "5.2", buf, "'TIMESTAMP'");
|
WARN_DEPRECATED(thd, "5.2", buf, "'TIMESTAMP'");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(new_field= new create_field()) ||
|
if (!(new_field= new Create_field()) ||
|
||||||
new_field->init(thd, field_name->str, type, length, decimals, type_modifier,
|
new_field->init(thd, field_name->str, type, length, decimals, type_modifier,
|
||||||
default_value, on_update_value, comment, change,
|
default_value, on_update_value, comment, change,
|
||||||
interval_list, cs, uint_geom_type))
|
interval_list, cs, uint_geom_type))
|
||||||
@ -7133,3 +7130,34 @@ bool check_string_char_length(LEX_STRING *str, const char *err_msg,
|
|||||||
my_error(ER_WRONG_STRING_LENGTH, MYF(0), str->str, err_msg, max_char_length);
|
my_error(ER_WRONG_STRING_LENGTH, MYF(0), str->str, err_msg, max_char_length);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern int MYSQLparse(void *thd); // from sql_yacc.cc
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
This is a wrapper of MYSQLparse(). All the code should call parse_sql()
|
||||||
|
instead of MYSQLparse().
|
||||||
|
|
||||||
|
@param thd Thread context.
|
||||||
|
@param lip Lexer context.
|
||||||
|
|
||||||
|
@return Error status.
|
||||||
|
@retval FALSE on success.
|
||||||
|
@retval TRUE on parsing error.
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool parse_sql(THD *thd, Lex_input_stream *lip)
|
||||||
|
{
|
||||||
|
bool err_status;
|
||||||
|
|
||||||
|
DBUG_ASSERT(thd->m_lip == NULL);
|
||||||
|
|
||||||
|
thd->m_lip= lip;
|
||||||
|
|
||||||
|
err_status= MYSQLparse(thd) != 0 || thd->is_fatal_error;
|
||||||
|
|
||||||
|
thd->m_lip= NULL;
|
||||||
|
|
||||||
|
return err_status;
|
||||||
|
}
|
||||||
|
@ -3696,7 +3696,6 @@ bool mysql_unpack_partition(THD *thd,
|
|||||||
thd->variables.character_set_client= system_charset_info;
|
thd->variables.character_set_client= system_charset_info;
|
||||||
|
|
||||||
Lex_input_stream lip(thd, part_buf, part_info_len);
|
Lex_input_stream lip(thd, part_buf, part_info_len);
|
||||||
thd->m_lip= &lip;
|
|
||||||
|
|
||||||
lex_start(thd);
|
lex_start(thd);
|
||||||
/*
|
/*
|
||||||
@ -3725,7 +3724,7 @@ bool mysql_unpack_partition(THD *thd,
|
|||||||
lex.part_info->part_state= part_state;
|
lex.part_info->part_state= part_state;
|
||||||
lex.part_info->part_state_len= part_state_len;
|
lex.part_info->part_state_len= part_state_len;
|
||||||
DBUG_PRINT("info", ("Parse: %s", part_buf));
|
DBUG_PRINT("info", ("Parse: %s", part_buf));
|
||||||
if (MYSQLparse((void*)thd) || thd->is_fatal_error)
|
if (parse_sql(thd, &lip))
|
||||||
{
|
{
|
||||||
thd->free_items();
|
thd->free_items();
|
||||||
goto end;
|
goto end;
|
||||||
|
@ -2868,12 +2868,11 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len)
|
|||||||
|
|
||||||
Lex_input_stream lip(thd, thd->query, thd->query_length);
|
Lex_input_stream lip(thd, thd->query, thd->query_length);
|
||||||
lip.stmt_prepare_mode= TRUE;
|
lip.stmt_prepare_mode= TRUE;
|
||||||
thd->m_lip= &lip;
|
|
||||||
lex_start(thd);
|
lex_start(thd);
|
||||||
int err= MYSQLparse((void *)thd);
|
|
||||||
|
|
||||||
error= err || thd->is_fatal_error ||
|
error= parse_sql(thd, &lip) ||
|
||||||
thd->net.report_error || init_param_array(this);
|
thd->net.report_error ||
|
||||||
|
init_param_array(this);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
While doing context analysis of the query (in check_prepared_statement)
|
While doing context analysis of the query (in check_prepared_statement)
|
||||||
|
@ -10083,12 +10083,12 @@ err:
|
|||||||
0 if out of memory, TABLE object in case of success
|
0 if out of memory, TABLE object in case of success
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TABLE *create_virtual_tmp_table(THD *thd, List<create_field> &field_list)
|
TABLE *create_virtual_tmp_table(THD *thd, List<Create_field> &field_list)
|
||||||
{
|
{
|
||||||
uint field_count= field_list.elements;
|
uint field_count= field_list.elements;
|
||||||
uint blob_count= 0;
|
uint blob_count= 0;
|
||||||
Field **field;
|
Field **field;
|
||||||
create_field *cdef; /* column definition */
|
Create_field *cdef; /* column definition */
|
||||||
uint record_length= 0;
|
uint record_length= 0;
|
||||||
uint null_count= 0; /* number of columns which may be null */
|
uint null_count= 0; /* number of columns which may be null */
|
||||||
uint null_pack_length; /* NULL representation array length */
|
uint null_pack_length; /* NULL representation array length */
|
||||||
@ -10116,7 +10116,7 @@ TABLE *create_virtual_tmp_table(THD *thd, List<create_field> &field_list)
|
|||||||
setup_tmp_table_column_bitmaps(table, bitmaps);
|
setup_tmp_table_column_bitmaps(table, bitmaps);
|
||||||
|
|
||||||
/* Create all fields and calculate the total length of record */
|
/* Create all fields and calculate the total length of record */
|
||||||
List_iterator_fast<create_field> it(field_list);
|
List_iterator_fast<Create_field> it(field_list);
|
||||||
while ((cdef= it++))
|
while ((cdef= it++))
|
||||||
{
|
{
|
||||||
*field= make_field(share, 0, cdef->length,
|
*field= make_field(share, 0, cdef->length,
|
||||||
|
@ -34,13 +34,13 @@ const char *primary_key_name="PRIMARY";
|
|||||||
static bool check_if_keyname_exists(const char *name,KEY *start, KEY *end);
|
static bool check_if_keyname_exists(const char *name,KEY *start, KEY *end);
|
||||||
static char *make_unique_key_name(const char *field_name,KEY *start,KEY *end);
|
static char *make_unique_key_name(const char *field_name,KEY *start,KEY *end);
|
||||||
static int copy_data_between_tables(TABLE *from,TABLE *to,
|
static int copy_data_between_tables(TABLE *from,TABLE *to,
|
||||||
List<create_field> &create, bool ignore,
|
List<Create_field> &create, bool ignore,
|
||||||
uint order_num, ORDER *order,
|
uint order_num, ORDER *order,
|
||||||
ha_rows *copied,ha_rows *deleted,
|
ha_rows *copied,ha_rows *deleted,
|
||||||
enum enum_enable_or_disable keys_onoff,
|
enum enum_enable_or_disable keys_onoff,
|
||||||
bool error_if_not_empty);
|
bool error_if_not_empty);
|
||||||
|
|
||||||
static bool prepare_blob_field(THD *thd, create_field *sql_field);
|
static bool prepare_blob_field(THD *thd, Create_field *sql_field);
|
||||||
static bool check_engine(THD *, const char *, HA_CREATE_INFO *);
|
static bool check_engine(THD *, const char *, HA_CREATE_INFO *);
|
||||||
static bool
|
static bool
|
||||||
mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
|
mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
|
||||||
@ -1939,7 +1939,7 @@ void calculate_interval_lengths(CHARSET_INFO *cs, TYPELIB *interval,
|
|||||||
table_flags table flags
|
table_flags table flags
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
This function prepares a create_field instance.
|
This function prepares a Create_field instance.
|
||||||
Fields such as pack_flag are valid after this call.
|
Fields such as pack_flag are valid after this call.
|
||||||
|
|
||||||
RETURN VALUES
|
RETURN VALUES
|
||||||
@ -1947,7 +1947,7 @@ void calculate_interval_lengths(CHARSET_INFO *cs, TYPELIB *interval,
|
|||||||
1 Error
|
1 Error
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int prepare_create_field(create_field *sql_field,
|
int prepare_create_field(Create_field *sql_field,
|
||||||
uint *blob_columns,
|
uint *blob_columns,
|
||||||
int *timestamps, int *timestamps_with_niladic,
|
int *timestamps, int *timestamps_with_niladic,
|
||||||
longlong table_flags)
|
longlong table_flags)
|
||||||
@ -2138,7 +2138,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
|
|||||||
uint *key_count, int select_field_count)
|
uint *key_count, int select_field_count)
|
||||||
{
|
{
|
||||||
const char *key_name;
|
const char *key_name;
|
||||||
create_field *sql_field,*dup_field;
|
Create_field *sql_field,*dup_field;
|
||||||
uint field,null_fields,blob_columns,max_key_length;
|
uint field,null_fields,blob_columns,max_key_length;
|
||||||
ulong record_offset= 0;
|
ulong record_offset= 0;
|
||||||
KEY *key_info;
|
KEY *key_info;
|
||||||
@ -2146,8 +2146,8 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
|
|||||||
int timestamps= 0, timestamps_with_niladic= 0;
|
int timestamps= 0, timestamps_with_niladic= 0;
|
||||||
int field_no,dup_no;
|
int field_no,dup_no;
|
||||||
int select_field_pos,auto_increment=0;
|
int select_field_pos,auto_increment=0;
|
||||||
List_iterator<create_field> it(alter_info->create_list);
|
List_iterator<Create_field> it(alter_info->create_list);
|
||||||
List_iterator<create_field> it2(alter_info->create_list);
|
List_iterator<Create_field> it2(alter_info->create_list);
|
||||||
uint total_uneven_bit_length= 0;
|
uint total_uneven_bit_length= 0;
|
||||||
DBUG_ENTER("mysql_prepare_create_table");
|
DBUG_ENTER("mysql_prepare_create_table");
|
||||||
|
|
||||||
@ -2201,7 +2201,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
|
|||||||
sql_field->sql_type == MYSQL_TYPE_ENUM))
|
sql_field->sql_type == MYSQL_TYPE_ENUM))
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
Starting from 5.1 we work here with a copy of create_field
|
Starting from 5.1 we work here with a copy of Create_field
|
||||||
created by the caller, not with the instance that was
|
created by the caller, not with the instance that was
|
||||||
originally created during parsing. It's OK to create
|
originally created during parsing. It's OK to create
|
||||||
a temporary item and initialize with it a member of the
|
a temporary item and initialize with it a member of the
|
||||||
@ -2492,7 +2492,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
|
|||||||
if (key->type == Key::FOREIGN_KEY)
|
if (key->type == Key::FOREIGN_KEY)
|
||||||
{
|
{
|
||||||
fk_key_count++;
|
fk_key_count++;
|
||||||
foreign_key *fk_key= (foreign_key*) key;
|
Foreign_key *fk_key= (Foreign_key*) key;
|
||||||
if (fk_key->ref_columns.elements &&
|
if (fk_key->ref_columns.elements &&
|
||||||
fk_key->ref_columns.elements != fk_key->columns.elements)
|
fk_key->ref_columns.elements != fk_key->columns.elements)
|
||||||
{
|
{
|
||||||
@ -2576,7 +2576,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
|
|||||||
for (; (key=key_iterator++) ; key_number++)
|
for (; (key=key_iterator++) ; key_number++)
|
||||||
{
|
{
|
||||||
uint key_length=0;
|
uint key_length=0;
|
||||||
key_part_spec *column;
|
Key_part_spec *column;
|
||||||
|
|
||||||
if (key->name == ignore_key)
|
if (key->name == ignore_key)
|
||||||
{
|
{
|
||||||
@ -2685,12 +2685,12 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
|
|||||||
if (key_info->block_size)
|
if (key_info->block_size)
|
||||||
key_info->flags|= HA_USES_BLOCK_SIZE;
|
key_info->flags|= HA_USES_BLOCK_SIZE;
|
||||||
|
|
||||||
List_iterator<key_part_spec> cols(key->columns), cols2(key->columns);
|
List_iterator<Key_part_spec> cols(key->columns), cols2(key->columns);
|
||||||
CHARSET_INFO *ft_key_charset=0; // for FULLTEXT
|
CHARSET_INFO *ft_key_charset=0; // for FULLTEXT
|
||||||
for (uint column_nr=0 ; (column=cols++) ; column_nr++)
|
for (uint column_nr=0 ; (column=cols++) ; column_nr++)
|
||||||
{
|
{
|
||||||
uint length;
|
uint length;
|
||||||
key_part_spec *dup_column;
|
Key_part_spec *dup_column;
|
||||||
|
|
||||||
it.rewind();
|
it.rewind();
|
||||||
field=0;
|
field=0;
|
||||||
@ -3000,7 +3000,7 @@ static void set_table_default_charset(THD *thd,
|
|||||||
In this case the error is given
|
In this case the error is given
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static bool prepare_blob_field(THD *thd, create_field *sql_field)
|
static bool prepare_blob_field(THD *thd, Create_field *sql_field)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("prepare_blob_field");
|
DBUG_ENTER("prepare_blob_field");
|
||||||
|
|
||||||
@ -3041,7 +3041,7 @@ static bool prepare_blob_field(THD *thd, create_field *sql_field)
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Preparation of create_field for SP function return values.
|
Preparation of Create_field for SP function return values.
|
||||||
Based on code used in the inner loop of mysql_prepare_create_table()
|
Based on code used in the inner loop of mysql_prepare_create_table()
|
||||||
above.
|
above.
|
||||||
|
|
||||||
@ -3055,7 +3055,7 @@ static bool prepare_blob_field(THD *thd, create_field *sql_field)
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void sp_prepare_create_field(THD *thd, create_field *sql_field)
|
void sp_prepare_create_field(THD *thd, Create_field *sql_field)
|
||||||
{
|
{
|
||||||
if (sql_field->sql_type == MYSQL_TYPE_SET ||
|
if (sql_field->sql_type == MYSQL_TYPE_SET ||
|
||||||
sql_field->sql_type == MYSQL_TYPE_ENUM)
|
sql_field->sql_type == MYSQL_TYPE_ENUM)
|
||||||
@ -4950,8 +4950,8 @@ compare_tables(TABLE *table,
|
|||||||
Field **f_ptr, *field;
|
Field **f_ptr, *field;
|
||||||
uint changes= 0, tmp;
|
uint changes= 0, tmp;
|
||||||
uint key_count;
|
uint key_count;
|
||||||
List_iterator_fast<create_field> new_field_it(alter_info->create_list);
|
List_iterator_fast<Create_field> new_field_it(alter_info->create_list);
|
||||||
create_field *new_field;
|
Create_field *new_field;
|
||||||
KEY_PART_INFO *key_part;
|
KEY_PART_INFO *key_part;
|
||||||
KEY_PART_INFO *end;
|
KEY_PART_INFO *end;
|
||||||
/*
|
/*
|
||||||
@ -5298,16 +5298,16 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
|
|||||||
Alter_info *alter_info)
|
Alter_info *alter_info)
|
||||||
{
|
{
|
||||||
/* New column definitions are added here */
|
/* New column definitions are added here */
|
||||||
List<create_field> new_create_list;
|
List<Create_field> new_create_list;
|
||||||
/* New key definitions are added here */
|
/* New key definitions are added here */
|
||||||
List<Key> new_key_list;
|
List<Key> new_key_list;
|
||||||
List_iterator<Alter_drop> drop_it(alter_info->drop_list);
|
List_iterator<Alter_drop> drop_it(alter_info->drop_list);
|
||||||
List_iterator<create_field> def_it(alter_info->create_list);
|
List_iterator<Create_field> def_it(alter_info->create_list);
|
||||||
List_iterator<Alter_column> alter_it(alter_info->alter_list);
|
List_iterator<Alter_column> alter_it(alter_info->alter_list);
|
||||||
List_iterator<Key> key_it(alter_info->key_list);
|
List_iterator<Key> key_it(alter_info->key_list);
|
||||||
List_iterator<create_field> find_it(new_create_list);
|
List_iterator<Create_field> find_it(new_create_list);
|
||||||
List_iterator<create_field> field_it(new_create_list);
|
List_iterator<Create_field> field_it(new_create_list);
|
||||||
List<key_part_spec> key_parts;
|
List<Key_part_spec> key_parts;
|
||||||
uint db_create_options= (table->s->db_create_options
|
uint db_create_options= (table->s->db_create_options
|
||||||
& ~(HA_OPTION_PACK_RECORD));
|
& ~(HA_OPTION_PACK_RECORD));
|
||||||
uint used_fields= create_info->used_fields;
|
uint used_fields= create_info->used_fields;
|
||||||
@ -5347,7 +5347,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
|
|||||||
create_info->tablespace= tablespace;
|
create_info->tablespace= tablespace;
|
||||||
}
|
}
|
||||||
restore_record(table, s->default_values); // Empty record for DEFAULT
|
restore_record(table, s->default_values); // Empty record for DEFAULT
|
||||||
create_field *def;
|
Create_field *def;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
First collect all fields from table which isn't in drop_list
|
First collect all fields from table which isn't in drop_list
|
||||||
@ -5403,7 +5403,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
|
|||||||
This field was not dropped and not changed, add it to the list
|
This field was not dropped and not changed, add it to the list
|
||||||
for the new table.
|
for the new table.
|
||||||
*/
|
*/
|
||||||
def= new create_field(field, field);
|
def= new Create_field(field, field);
|
||||||
new_create_list.push_back(def);
|
new_create_list.push_back(def);
|
||||||
alter_it.rewind(); // Change default if ALTER
|
alter_it.rewind(); // Change default if ALTER
|
||||||
Alter_column *alter;
|
Alter_column *alter;
|
||||||
@ -5458,7 +5458,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
|
|||||||
new_create_list.push_front(def);
|
new_create_list.push_front(def);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
create_field *find;
|
Create_field *find;
|
||||||
find_it.rewind();
|
find_it.rewind();
|
||||||
while ((find=find_it++)) // Add new columns
|
while ((find=find_it++)) // Add new columns
|
||||||
{
|
{
|
||||||
@ -5516,7 +5516,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
|
|||||||
if (!key_part->field)
|
if (!key_part->field)
|
||||||
continue; // Wrong field (from UNIREG)
|
continue; // Wrong field (from UNIREG)
|
||||||
const char *key_part_name=key_part->field->field_name;
|
const char *key_part_name=key_part->field->field_name;
|
||||||
create_field *cfield;
|
Create_field *cfield;
|
||||||
field_it.rewind();
|
field_it.rewind();
|
||||||
while ((cfield=field_it++))
|
while ((cfield=field_it++))
|
||||||
{
|
{
|
||||||
@ -5558,7 +5558,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
|
|||||||
key_part_length= 0; // Use whole field
|
key_part_length= 0; // Use whole field
|
||||||
}
|
}
|
||||||
key_part_length /= key_part->field->charset()->mbmaxlen;
|
key_part_length /= key_part->field->charset()->mbmaxlen;
|
||||||
key_parts.push_back(new key_part_spec(cfield->field_name,
|
key_parts.push_back(new Key_part_spec(cfield->field_name,
|
||||||
key_part_length));
|
key_part_length));
|
||||||
}
|
}
|
||||||
if (key_parts.elements)
|
if (key_parts.elements)
|
||||||
@ -6763,7 +6763,7 @@ err_with_placeholders:
|
|||||||
|
|
||||||
static int
|
static int
|
||||||
copy_data_between_tables(TABLE *from,TABLE *to,
|
copy_data_between_tables(TABLE *from,TABLE *to,
|
||||||
List<create_field> &create,
|
List<Create_field> &create,
|
||||||
bool ignore,
|
bool ignore,
|
||||||
uint order_num, ORDER *order,
|
uint order_num, ORDER *order,
|
||||||
ha_rows *copied,
|
ha_rows *copied,
|
||||||
@ -6817,8 +6817,8 @@ copy_data_between_tables(TABLE *from,TABLE *to,
|
|||||||
|
|
||||||
save_sql_mode= thd->variables.sql_mode;
|
save_sql_mode= thd->variables.sql_mode;
|
||||||
|
|
||||||
List_iterator<create_field> it(create);
|
List_iterator<Create_field> it(create);
|
||||||
create_field *def;
|
Create_field *def;
|
||||||
copy_end=copy;
|
copy_end=copy;
|
||||||
for (Field **ptr=to->field ; *ptr ; ptr++)
|
for (Field **ptr=to->field ; *ptr ; ptr++)
|
||||||
{
|
{
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
static const LEX_STRING triggers_file_type=
|
static const LEX_STRING triggers_file_type=
|
||||||
{ C_STRING_WITH_LEN("TRIGGERS") };
|
{ C_STRING_WITH_LEN("TRIGGERS") };
|
||||||
|
|
||||||
const char * const triggers_file_ext= ".TRG";
|
const char * const TRG_EXT= ".TRG";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Table of .TRG file field descriptors.
|
Table of .TRG file field descriptors.
|
||||||
@ -79,7 +79,7 @@ struct st_trigname
|
|||||||
static const LEX_STRING trigname_file_type=
|
static const LEX_STRING trigname_file_type=
|
||||||
{ C_STRING_WITH_LEN("TRIGGERNAME") };
|
{ C_STRING_WITH_LEN("TRIGGERNAME") };
|
||||||
|
|
||||||
const char * const trigname_file_ext= ".TRN";
|
const char * const TRN_EXT= ".TRN";
|
||||||
|
|
||||||
static File_option trigname_file_parameters[]=
|
static File_option trigname_file_parameters[]=
|
||||||
{
|
{
|
||||||
@ -132,6 +132,7 @@ private:
|
|||||||
LEX_STRING *trigger_table_value;
|
LEX_STRING *trigger_table_value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Create or drop trigger for table.
|
Create or drop trigger for table.
|
||||||
|
|
||||||
@ -463,14 +464,14 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables,
|
|||||||
sql_create_definition_file() files handles renaming and backup of older
|
sql_create_definition_file() files handles renaming and backup of older
|
||||||
versions
|
versions
|
||||||
*/
|
*/
|
||||||
file.length= build_table_filename(file_buff, FN_REFLEN-1,
|
file.length= build_table_filename(file_buff, FN_REFLEN - 1,
|
||||||
tables->db, tables->table_name,
|
tables->db, tables->table_name,
|
||||||
triggers_file_ext, 0);
|
TRG_EXT, 0);
|
||||||
file.str= file_buff;
|
file.str= file_buff;
|
||||||
trigname_file.length= build_table_filename(trigname_buff, FN_REFLEN-1,
|
trigname_file.length= build_table_filename(trigname_buff, FN_REFLEN-1,
|
||||||
tables->db,
|
tables->db,
|
||||||
lex->spname->m_name.str,
|
lex->spname->m_name.str,
|
||||||
trigname_file_ext, 0);
|
TRN_EXT, 0);
|
||||||
trigname_file.str= trigname_buff;
|
trigname_file.str= trigname_buff;
|
||||||
|
|
||||||
/* Use the filesystem to enforce trigger namespace constraints. */
|
/* Use the filesystem to enforce trigger namespace constraints. */
|
||||||
@ -563,10 +564,13 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables,
|
|||||||
append_definer(thd, stmt_query, &definer_user, &definer_host);
|
append_definer(thd, stmt_query, &definer_user, &definer_host);
|
||||||
}
|
}
|
||||||
|
|
||||||
stmt_query->append(thd->lex->stmt_definition_begin,
|
LEX_STRING stmt_definition;
|
||||||
(char *) thd->lex->sphead->m_body_begin -
|
stmt_definition.str= (char*) thd->lex->stmt_definition_begin;
|
||||||
thd->lex->stmt_definition_begin +
|
stmt_definition.length= thd->lex->stmt_definition_end
|
||||||
thd->lex->sphead->m_body.length);
|
- thd->lex->stmt_definition_begin;
|
||||||
|
trim_whitespace(thd->charset(), & stmt_definition);
|
||||||
|
|
||||||
|
stmt_query->append(stmt_definition.str, stmt_definition.length);
|
||||||
|
|
||||||
trg_def->str= stmt_query->c_ptr();
|
trg_def->str= stmt_query->c_ptr();
|
||||||
trg_def->length= stmt_query->length();
|
trg_def->length= stmt_query->length();
|
||||||
@ -601,7 +605,7 @@ err_with_cleanup:
|
|||||||
static bool rm_trigger_file(char *path, const char *db,
|
static bool rm_trigger_file(char *path, const char *db,
|
||||||
const char *table_name)
|
const char *table_name)
|
||||||
{
|
{
|
||||||
build_table_filename(path, FN_REFLEN-1, db, table_name, triggers_file_ext, 0);
|
build_table_filename(path, FN_REFLEN-1, db, table_name, TRG_EXT, 0);
|
||||||
return my_delete(path, MYF(MY_WME));
|
return my_delete(path, MYF(MY_WME));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -624,8 +628,7 @@ static bool rm_trigger_file(char *path, const char *db,
|
|||||||
static bool rm_trigname_file(char *path, const char *db,
|
static bool rm_trigname_file(char *path, const char *db,
|
||||||
const char *trigger_name)
|
const char *trigger_name)
|
||||||
{
|
{
|
||||||
build_table_filename(path, FN_REFLEN-1,
|
build_table_filename(path, FN_REFLEN - 1, db, trigger_name, TRN_EXT, 0);
|
||||||
db, trigger_name, trigname_file_ext, 0);
|
|
||||||
return my_delete(path, MYF(MY_WME));
|
return my_delete(path, MYF(MY_WME));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -650,8 +653,8 @@ static bool save_trigger_file(Table_triggers_list *triggers, const char *db,
|
|||||||
char file_buff[FN_REFLEN];
|
char file_buff[FN_REFLEN];
|
||||||
LEX_STRING file;
|
LEX_STRING file;
|
||||||
|
|
||||||
file.length= build_table_filename(file_buff, FN_REFLEN-1, db, table_name,
|
file.length= build_table_filename(file_buff, FN_REFLEN - 1, db, table_name,
|
||||||
triggers_file_ext, 0);
|
TRG_EXT, 0);
|
||||||
file.str= file_buff;
|
file.str= file_buff;
|
||||||
return sql_create_definition_file(NULL, &file, &triggers_file_type,
|
return sql_create_definition_file(NULL, &file, &triggers_file_type,
|
||||||
(uchar*)triggers, triggers_file_parameters,
|
(uchar*)triggers, triggers_file_parameters,
|
||||||
@ -831,8 +834,8 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
|
|||||||
|
|
||||||
DBUG_ENTER("Table_triggers_list::check_n_load");
|
DBUG_ENTER("Table_triggers_list::check_n_load");
|
||||||
|
|
||||||
path.length= build_table_filename(path_buff, FN_REFLEN-1,
|
path.length= build_table_filename(path_buff, FN_REFLEN - 1,
|
||||||
db, table_name, triggers_file_ext, 0);
|
db, table_name, TRG_EXT, 0);
|
||||||
path.str= path_buff;
|
path.str= path_buff;
|
||||||
|
|
||||||
// QQ: should we analyze errno somehow ?
|
// QQ: should we analyze errno somehow ?
|
||||||
@ -978,12 +981,10 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
|
|||||||
thd->variables.sql_mode= (ulong)*trg_sql_mode;
|
thd->variables.sql_mode= (ulong)*trg_sql_mode;
|
||||||
|
|
||||||
Lex_input_stream lip(thd, trg_create_str->str, trg_create_str->length);
|
Lex_input_stream lip(thd, trg_create_str->str, trg_create_str->length);
|
||||||
thd->m_lip= &lip;
|
|
||||||
lex_start(thd);
|
lex_start(thd);
|
||||||
thd->spcont= 0;
|
thd->spcont= 0;
|
||||||
int err= MYSQLparse((void *)thd);
|
|
||||||
|
|
||||||
if (err || thd->is_fatal_error)
|
if (parse_sql(thd, &lip))
|
||||||
{
|
{
|
||||||
/* Currently sphead is always deleted in case of a parse error */
|
/* Currently sphead is always deleted in case of a parse error */
|
||||||
DBUG_ASSERT(lex.sphead == 0);
|
DBUG_ASSERT(lex.sphead == 0);
|
||||||
@ -1032,7 +1033,11 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
|
|||||||
if (!(on_table_name= (LEX_STRING*) alloc_root(&table->mem_root,
|
if (!(on_table_name= (LEX_STRING*) alloc_root(&table->mem_root,
|
||||||
sizeof(LEX_STRING))))
|
sizeof(LEX_STRING))))
|
||||||
goto err_with_lex_cleanup;
|
goto err_with_lex_cleanup;
|
||||||
*on_table_name= lex.ident;
|
|
||||||
|
on_table_name->str= (char*) lex.raw_trg_on_table_name_begin;
|
||||||
|
on_table_name->length= lex.raw_trg_on_table_name_end
|
||||||
|
- lex.raw_trg_on_table_name_begin;
|
||||||
|
|
||||||
if (triggers->on_table_names_list.push_back(on_table_name, &table->mem_root))
|
if (triggers->on_table_names_list.push_back(on_table_name, &table->mem_root))
|
||||||
goto err_with_lex_cleanup;
|
goto err_with_lex_cleanup;
|
||||||
|
|
||||||
@ -1101,7 +1106,7 @@ err_with_lex_cleanup:
|
|||||||
be merged into .FRM anyway.
|
be merged into .FRM anyway.
|
||||||
*/
|
*/
|
||||||
my_error(ER_WRONG_OBJECT, MYF(0),
|
my_error(ER_WRONG_OBJECT, MYF(0),
|
||||||
table_name, triggers_file_ext+1, "TRIGGER");
|
table_name, TRG_EXT + 1, "TRIGGER");
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1161,43 +1166,38 @@ bool Table_triggers_list::get_trigger_info(THD *thd, trg_event_type event,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/**
|
||||||
Find trigger's table from trigger identifier and add it to
|
Find trigger's table from trigger identifier and add it to
|
||||||
the statement table list.
|
the statement table list.
|
||||||
|
|
||||||
SYNOPSIS
|
@param[in] thd Thread context.
|
||||||
mysql_table_for_trigger()
|
@param[in] trg_name Trigger name.
|
||||||
thd - current thread context
|
@param[in] if_exists TRUE if SQL statement contains "IF EXISTS" clause.
|
||||||
trig - identifier for trigger
|
That means a warning instead of error should be
|
||||||
if_exists - treat a not existing trigger as a warning if TRUE
|
thrown if trigger with given name does not exist.
|
||||||
table - pointer to TABLE_LIST object for the table trigger (output)
|
@param[out] table Pointer to TABLE_LIST object for the
|
||||||
|
table trigger.
|
||||||
|
|
||||||
RETURN VALUE
|
@return Operation status
|
||||||
0 Success
|
@retval FALSE On success.
|
||||||
1 Error
|
@retval TRUE Otherwise.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
bool add_table_for_trigger(THD *thd,
|
||||||
add_table_for_trigger(THD *thd, sp_name *trig, bool if_exists,
|
sp_name *trg_name,
|
||||||
|
bool if_exists,
|
||||||
TABLE_LIST **table)
|
TABLE_LIST **table)
|
||||||
{
|
{
|
||||||
LEX *lex= thd->lex;
|
LEX *lex= thd->lex;
|
||||||
char path_buff[FN_REFLEN];
|
char trn_path_buff[FN_REFLEN];
|
||||||
LEX_STRING path;
|
LEX_STRING trn_path= { trn_path_buff, 0 };
|
||||||
File_parser *parser;
|
LEX_STRING tbl_name;
|
||||||
struct st_trigname trigname;
|
|
||||||
Handle_old_incorrect_trigger_table_hook trigger_table_hook(
|
|
||||||
path_buff, &trigname.trigger_table);
|
|
||||||
|
|
||||||
DBUG_ENTER("add_table_for_trigger");
|
DBUG_ENTER("add_table_for_trigger");
|
||||||
DBUG_ASSERT(table != NULL);
|
|
||||||
|
|
||||||
path.length= build_table_filename(path_buff, FN_REFLEN-1,
|
build_trn_path(thd, trg_name, &trn_path);
|
||||||
trig->m_db.str, trig->m_name.str,
|
|
||||||
trigname_file_ext, 0);
|
|
||||||
path.str= path_buff;
|
|
||||||
|
|
||||||
if (access(path_buff, F_OK))
|
if (check_trn_exists(&trn_path))
|
||||||
{
|
{
|
||||||
if (if_exists)
|
if (if_exists)
|
||||||
{
|
{
|
||||||
@ -1205,39 +1205,27 @@ add_table_for_trigger(THD *thd, sp_name *trig, bool if_exists,
|
|||||||
MYSQL_ERROR::WARN_LEVEL_NOTE,
|
MYSQL_ERROR::WARN_LEVEL_NOTE,
|
||||||
ER_TRG_DOES_NOT_EXIST,
|
ER_TRG_DOES_NOT_EXIST,
|
||||||
ER(ER_TRG_DOES_NOT_EXIST));
|
ER(ER_TRG_DOES_NOT_EXIST));
|
||||||
|
|
||||||
*table= NULL;
|
*table= NULL;
|
||||||
DBUG_RETURN(0);
|
|
||||||
|
DBUG_RETURN(FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
my_error(ER_TRG_DOES_NOT_EXIST, MYF(0));
|
my_error(ER_TRG_DOES_NOT_EXIST, MYF(0));
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(parser= sql_parse_prepare(&path, thd->mem_root, 1)))
|
if (load_table_name_for_trigger(thd, trg_name, &trn_path, &tbl_name))
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
if (!is_equal(&trigname_file_type, parser->type()))
|
|
||||||
{
|
|
||||||
my_error(ER_WRONG_OBJECT, MYF(0), trig->m_name.str, trigname_file_ext+1,
|
|
||||||
"TRIGGERNAME");
|
|
||||||
DBUG_RETURN(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parser->parse((uchar*)&trigname, thd->mem_root,
|
|
||||||
trigname_file_parameters, 1,
|
|
||||||
&trigger_table_hook))
|
|
||||||
DBUG_RETURN(1);
|
|
||||||
|
|
||||||
/* We need to reset statement table list to be PS/SP friendly. */
|
/* We need to reset statement table list to be PS/SP friendly. */
|
||||||
lex->query_tables= 0;
|
lex->query_tables= 0;
|
||||||
lex->query_tables_last= &lex->query_tables;
|
lex->query_tables_last= &lex->query_tables;
|
||||||
*table= sp_add_to_query_tables(thd, lex, trig->m_db.str,
|
|
||||||
trigname.trigger_table.str, TL_IGNORE);
|
|
||||||
|
|
||||||
if (! *table)
|
*table= sp_add_to_query_tables(thd, lex, trg_name->m_db.str,
|
||||||
DBUG_RETURN(1);
|
tbl_name.str, TL_IGNORE);
|
||||||
|
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(*table ? FALSE : TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1348,7 +1336,12 @@ Table_triggers_list::change_table_name_in_triggers(THD *thd,
|
|||||||
|
|
||||||
/* Construct CREATE TRIGGER statement with new table name. */
|
/* Construct CREATE TRIGGER statement with new table name. */
|
||||||
buff.length(0);
|
buff.length(0);
|
||||||
|
|
||||||
|
/* WARNING: 'on_table_name' is supposed to point inside 'def' */
|
||||||
|
DBUG_ASSERT(on_table_name->str > def->str);
|
||||||
|
DBUG_ASSERT(on_table_name->str < (def->str + def->length));
|
||||||
before_on_len= on_table_name->str - def->str;
|
before_on_len= on_table_name->str - def->str;
|
||||||
|
|
||||||
buff.append(def->str, before_on_len);
|
buff.append(def->str, before_on_len);
|
||||||
buff.append(STRING_WITH_LEN("ON "));
|
buff.append(STRING_WITH_LEN("ON "));
|
||||||
append_identifier(thd, &buff, new_table_name->str, new_table_name->length);
|
append_identifier(thd, &buff, new_table_name->str, new_table_name->length);
|
||||||
@ -1416,7 +1409,7 @@ Table_triggers_list::change_table_name_in_trignames(const char *db_name,
|
|||||||
{
|
{
|
||||||
trigname_file.length= build_table_filename(trigname_buff, FN_REFLEN-1,
|
trigname_file.length= build_table_filename(trigname_buff, FN_REFLEN-1,
|
||||||
db_name, trigger->str,
|
db_name, trigger->str,
|
||||||
trigname_file_ext, 0);
|
TRN_EXT, 0);
|
||||||
trigname_file.str= trigname_buff;
|
trigname_file.str= trigname_buff;
|
||||||
|
|
||||||
trigname.trigger_table= *new_table_name;
|
trigname.trigger_table= *new_table_name;
|
||||||
@ -1525,17 +1518,33 @@ end:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Table_triggers_list::process_triggers(THD *thd, trg_event_type event,
|
/**
|
||||||
|
Execute trigger for given (event, time) pair.
|
||||||
|
|
||||||
|
The operation executes trigger for the specified event (insert, update,
|
||||||
|
delete) and time (after, before) if it is set.
|
||||||
|
|
||||||
|
@param thd
|
||||||
|
@param event
|
||||||
|
@param time_type,
|
||||||
|
@param old_row_is_record1
|
||||||
|
|
||||||
|
@return Error status.
|
||||||
|
@retval FALSE on success.
|
||||||
|
@retval TRUE on error.
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool Table_triggers_list::process_triggers(THD *thd,
|
||||||
|
trg_event_type event,
|
||||||
trg_action_time_type time_type,
|
trg_action_time_type time_type,
|
||||||
bool old_row_is_record1)
|
bool old_row_is_record1)
|
||||||
{
|
{
|
||||||
bool err_status= FALSE;
|
bool err_status;
|
||||||
sp_head *sp_trigger= bodies[event][time_type];
|
|
||||||
|
|
||||||
if (sp_trigger)
|
|
||||||
{
|
|
||||||
Sub_statement_state statement_state;
|
Sub_statement_state statement_state;
|
||||||
|
|
||||||
|
if (!bodies[event][time_type])
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
if (old_row_is_record1)
|
if (old_row_is_record1)
|
||||||
{
|
{
|
||||||
old_field= record1_field;
|
old_field= record1_field;
|
||||||
@ -1546,56 +1555,17 @@ bool Table_triggers_list::process_triggers(THD *thd, trg_event_type event,
|
|||||||
new_field= record1_field;
|
new_field= record1_field;
|
||||||
old_field= trigger_table->field;
|
old_field= trigger_table->field;
|
||||||
}
|
}
|
||||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
|
||||||
Security_context *sctx= &sp_trigger->m_security_ctx;
|
|
||||||
Security_context *save_ctx= NULL;
|
|
||||||
|
|
||||||
|
|
||||||
if (sp_trigger->m_chistics->suid != SP_IS_NOT_SUID &&
|
|
||||||
sctx->change_security_context(thd,
|
|
||||||
&sp_trigger->m_definer_user,
|
|
||||||
&sp_trigger->m_definer_host,
|
|
||||||
&sp_trigger->m_db,
|
|
||||||
&save_ctx))
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
/*
|
|
||||||
Fetch information about table-level privileges to GRANT_INFO structure for
|
|
||||||
subject table. Check of privileges that will use it and information about
|
|
||||||
column-level privileges will happen in Item_trigger_field::fix_fields().
|
|
||||||
*/
|
|
||||||
|
|
||||||
fill_effective_table_privileges(thd,
|
|
||||||
&subject_table_grants[event][time_type],
|
|
||||||
trigger_table->s->db.str,
|
|
||||||
trigger_table->s->table_name.str);
|
|
||||||
|
|
||||||
/* Check that the definer has TRIGGER privilege on the subject table. */
|
|
||||||
|
|
||||||
if (!(subject_table_grants[event][time_type].privilege & TRIGGER_ACL))
|
|
||||||
{
|
|
||||||
char priv_desc[128];
|
|
||||||
get_privilege_desc(priv_desc, sizeof(priv_desc), TRIGGER_ACL);
|
|
||||||
|
|
||||||
my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0), priv_desc,
|
|
||||||
thd->security_ctx->priv_user, thd->security_ctx->host_or_ip,
|
|
||||||
trigger_table->s->table_name.str);
|
|
||||||
|
|
||||||
sctx->restore_security_context(thd, save_ctx);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
#endif // NO_EMBEDDED_ACCESS_CHECKS
|
|
||||||
|
|
||||||
thd->reset_sub_statement_state(&statement_state, SUB_STMT_TRIGGER);
|
thd->reset_sub_statement_state(&statement_state, SUB_STMT_TRIGGER);
|
||||||
err_status= sp_trigger->execute_trigger
|
|
||||||
(thd, trigger_table->s->db.str, trigger_table->s->table_name.str,
|
|
||||||
&subject_table_grants[event][time_type]);
|
|
||||||
thd->restore_sub_statement_state(&statement_state);
|
|
||||||
|
|
||||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
err_status=
|
||||||
sctx->restore_security_context(thd, save_ctx);
|
bodies[event][time_type]->execute_trigger(
|
||||||
#endif // NO_EMBEDDED_ACCESS_CHECKS
|
thd,
|
||||||
}
|
&trigger_table->s->db,
|
||||||
|
&trigger_table->s->table_name,
|
||||||
|
&subject_table_grants[event][time_type]);
|
||||||
|
|
||||||
|
thd->restore_sub_statement_state(&statement_state);
|
||||||
|
|
||||||
return err_status;
|
return err_status;
|
||||||
}
|
}
|
||||||
@ -1737,3 +1707,95 @@ process_unknown_string(char *&unknown_key, uchar* base, MEM_ROOT *mem_root,
|
|||||||
}
|
}
|
||||||
DBUG_RETURN(FALSE);
|
DBUG_RETURN(FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Contruct path to TRN-file.
|
||||||
|
|
||||||
|
@param thd[in] Thread context.
|
||||||
|
@param trg_name[in] Trigger name.
|
||||||
|
@param trn_path[out] Variable to store constructed path
|
||||||
|
*/
|
||||||
|
|
||||||
|
void build_trn_path(THD *thd, const sp_name *trg_name, LEX_STRING *trn_path)
|
||||||
|
{
|
||||||
|
/* Construct path to the TRN-file. */
|
||||||
|
|
||||||
|
trn_path->length= build_table_filename(trn_path->str,
|
||||||
|
FN_REFLEN - 1,
|
||||||
|
trg_name->m_db.str,
|
||||||
|
trg_name->m_name.str,
|
||||||
|
TRN_EXT,
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Check if TRN-file exists.
|
||||||
|
|
||||||
|
@return
|
||||||
|
@retval TRUE if TRN-file does not exist.
|
||||||
|
@retval FALSE if TRN-file exists.
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool check_trn_exists(const LEX_STRING *trn_path)
|
||||||
|
{
|
||||||
|
return access(trn_path->str, F_OK) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Retrieve table name for given trigger.
|
||||||
|
|
||||||
|
@param thd[in] Thread context.
|
||||||
|
@param trg_name[in] Trigger name.
|
||||||
|
@param trn_path[in] Path to the corresponding TRN-file.
|
||||||
|
@param tbl_name[out] Variable to store retrieved table name.
|
||||||
|
|
||||||
|
@return Error status.
|
||||||
|
@retval FALSE on success.
|
||||||
|
@retval TRUE if table name could not be retrieved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool load_table_name_for_trigger(THD *thd,
|
||||||
|
const sp_name *trg_name,
|
||||||
|
const LEX_STRING *trn_path,
|
||||||
|
LEX_STRING *tbl_name)
|
||||||
|
{
|
||||||
|
File_parser *parser;
|
||||||
|
struct st_trigname trn_data;
|
||||||
|
|
||||||
|
Handle_old_incorrect_trigger_table_hook trigger_table_hook(
|
||||||
|
trn_path->str,
|
||||||
|
&trn_data.trigger_table);
|
||||||
|
|
||||||
|
DBUG_ENTER("load_table_name_for_trigger");
|
||||||
|
|
||||||
|
/* Parse the TRN-file. */
|
||||||
|
|
||||||
|
if (!(parser= sql_parse_prepare(trn_path, thd->mem_root, TRUE)))
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
|
if (!is_equal(&trigname_file_type, parser->type()))
|
||||||
|
{
|
||||||
|
my_error(ER_WRONG_OBJECT, MYF(0),
|
||||||
|
trg_name->m_name.str,
|
||||||
|
TRN_EXT + 1,
|
||||||
|
"TRIGGERNAME");
|
||||||
|
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parser->parse((uchar*) &trn_data, thd->mem_root,
|
||||||
|
trigname_file_parameters, 1,
|
||||||
|
&trigger_table_hook))
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
|
/* Copy trigger table name. */
|
||||||
|
|
||||||
|
*tbl_name= trn_data.trigger_table;
|
||||||
|
|
||||||
|
/* That's all. */
|
||||||
|
|
||||||
|
DBUG_RETURN(FALSE);
|
||||||
|
}
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
/*
|
/*
|
||||||
This class holds all information about triggers of table.
|
This class holds all information about triggers of table.
|
||||||
|
|
||||||
QQ: Will it be merged into TABLE in future ?
|
QQ: Will it be merged into TABLE in the future ?
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class Table_triggers_list: public Sql_alloc
|
class Table_triggers_list: public Sql_alloc
|
||||||
@ -143,6 +143,17 @@ private:
|
|||||||
extern const LEX_STRING trg_action_time_type_names[];
|
extern const LEX_STRING trg_action_time_type_names[];
|
||||||
extern const LEX_STRING trg_event_type_names[];
|
extern const LEX_STRING trg_event_type_names[];
|
||||||
|
|
||||||
int
|
bool add_table_for_trigger(THD *thd,
|
||||||
add_table_for_trigger(THD *thd, sp_name *trig, bool if_exists,
|
sp_name *trg_name,
|
||||||
|
bool continue_if_not_exist,
|
||||||
TABLE_LIST **table);
|
TABLE_LIST **table);
|
||||||
|
|
||||||
|
void build_trn_path(THD *thd, const sp_name *trg_name, LEX_STRING *trn_path);
|
||||||
|
|
||||||
|
bool check_trn_exists(const LEX_STRING *trn_path);
|
||||||
|
|
||||||
|
bool load_table_name_for_trigger(THD *thd,
|
||||||
|
const sp_name *trg_name,
|
||||||
|
const LEX_STRING *trn_path,
|
||||||
|
LEX_STRING *tbl_name);
|
||||||
|
|
||||||
|
@ -690,7 +690,6 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
|
|||||||
char md5[MD5_BUFF_LENGTH];
|
char md5[MD5_BUFF_LENGTH];
|
||||||
bool can_be_merged;
|
bool can_be_merged;
|
||||||
char dir_buff[FN_REFLEN], path_buff[FN_REFLEN];
|
char dir_buff[FN_REFLEN], path_buff[FN_REFLEN];
|
||||||
const char *endp;
|
|
||||||
LEX_STRING dir, file, path;
|
LEX_STRING dir, file, path;
|
||||||
int error= 0;
|
int error= 0;
|
||||||
DBUG_ENTER("mysql_register_view");
|
DBUG_ENTER("mysql_register_view");
|
||||||
@ -708,10 +707,12 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
|
|||||||
/* fill structure */
|
/* fill structure */
|
||||||
view->query.str= str.c_ptr_safe();
|
view->query.str= str.c_ptr_safe();
|
||||||
view->query.length= str.length();
|
view->query.length= str.length();
|
||||||
view->source.str= thd->query + thd->lex->create_view_select_start;
|
|
||||||
endp= view->source.str;
|
view->source.str= (char*) thd->lex->create_view_select_start;
|
||||||
endp= skip_rear_comments(thd->charset(), endp, thd->query + thd->query_length);
|
view->source.length= (thd->lex->create_view_select_end
|
||||||
view->source.length= endp - view->source.str;
|
- thd->lex->create_view_select_start);
|
||||||
|
trim_whitespace(thd->charset(), & view->source);
|
||||||
|
|
||||||
view->file_version= 1;
|
view->file_version= 1;
|
||||||
view->calc_md5(md5);
|
view->calc_md5(md5);
|
||||||
view->md5.str= md5;
|
view->md5.str= md5;
|
||||||
@ -892,7 +893,7 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table,
|
|||||||
LEX *old_lex, *lex;
|
LEX *old_lex, *lex;
|
||||||
Query_arena *arena, backup;
|
Query_arena *arena, backup;
|
||||||
TABLE_LIST *top_view= table->top_table();
|
TABLE_LIST *top_view= table->top_table();
|
||||||
int res;
|
bool res;
|
||||||
bool result, view_is_mergeable;
|
bool result, view_is_mergeable;
|
||||||
TABLE_LIST *view_main_select_tables;
|
TABLE_LIST *view_main_select_tables;
|
||||||
DBUG_ENTER("mysql_make_view");
|
DBUG_ENTER("mysql_make_view");
|
||||||
@ -1004,7 +1005,6 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table,
|
|||||||
|
|
||||||
{
|
{
|
||||||
Lex_input_stream lip(thd, table->query.str, table->query.length);
|
Lex_input_stream lip(thd, table->query.str, table->query.length);
|
||||||
thd->m_lip= &lip;
|
|
||||||
lex_start(thd);
|
lex_start(thd);
|
||||||
view_select= &lex->select_lex;
|
view_select= &lex->select_lex;
|
||||||
view_select->select_number= ++thd->select_number;
|
view_select->select_number= ++thd->select_number;
|
||||||
@ -1038,7 +1038,7 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table,
|
|||||||
MODE_IGNORE_SPACE | MODE_NO_BACKSLASH_ESCAPES);
|
MODE_IGNORE_SPACE | MODE_NO_BACKSLASH_ESCAPES);
|
||||||
CHARSET_INFO *save_cs= thd->variables.character_set_client;
|
CHARSET_INFO *save_cs= thd->variables.character_set_client;
|
||||||
thd->variables.character_set_client= system_charset_info;
|
thd->variables.character_set_client= system_charset_info;
|
||||||
res= MYSQLparse((void *)thd);
|
res= parse_sql(thd, &lip);
|
||||||
|
|
||||||
if ((old_lex->sql_command == SQLCOM_SHOW_FIELDS) ||
|
if ((old_lex->sql_command == SQLCOM_SHOW_FIELDS) ||
|
||||||
(old_lex->sql_command == SQLCOM_SHOW_CREATE))
|
(old_lex->sql_command == SQLCOM_SHOW_CREATE))
|
||||||
@ -1047,7 +1047,7 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table,
|
|||||||
thd->variables.character_set_client= save_cs;
|
thd->variables.character_set_client= save_cs;
|
||||||
thd->variables.sql_mode= save_mode;
|
thd->variables.sql_mode= save_mode;
|
||||||
}
|
}
|
||||||
if (!res && !thd->is_fatal_error)
|
if (!res)
|
||||||
{
|
{
|
||||||
TABLE_LIST *view_tables= lex->query_tables;
|
TABLE_LIST *view_tables= lex->query_tables;
|
||||||
TABLE_LIST *view_tables_tail= 0;
|
TABLE_LIST *view_tables_tail= 0;
|
||||||
|
156
sql/sql_yacc.yy
156
sql/sql_yacc.yy
@ -106,7 +106,7 @@ void my_parse_error(const char *s)
|
|||||||
THD *thd= current_thd;
|
THD *thd= current_thd;
|
||||||
Lex_input_stream *lip= thd->m_lip;
|
Lex_input_stream *lip= thd->m_lip;
|
||||||
|
|
||||||
const char *yytext= lip->tok_start;
|
const char *yytext= lip->get_tok_start();
|
||||||
/* Push an error into the error stack */
|
/* Push an error into the error stack */
|
||||||
my_printf_error(ER_PARSE_ERROR, ER(ER_PARSE_ERROR), MYF(0), s,
|
my_printf_error(ER_PARSE_ERROR, ER(ER_PARSE_ERROR), MYF(0), s,
|
||||||
(yytext ? yytext : ""),
|
(yytext ? yytext : ""),
|
||||||
@ -456,7 +456,7 @@ Item* handle_sql2003_note184_exception(THD *thd, Item* left, bool equal,
|
|||||||
List<Item> *item_list;
|
List<Item> *item_list;
|
||||||
List<String> *string_list;
|
List<String> *string_list;
|
||||||
String *string;
|
String *string;
|
||||||
key_part_spec *key_part;
|
Key_part_spec *key_part;
|
||||||
TABLE_LIST *table_list;
|
TABLE_LIST *table_list;
|
||||||
udf_func *udf;
|
udf_func *udf;
|
||||||
LEX_USER *lex_user;
|
LEX_USER *lex_user;
|
||||||
@ -1872,10 +1872,7 @@ ev_sql_stmt:
|
|||||||
bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
|
bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
|
||||||
lex->sphead->m_chistics= &lex->sp_chistics;
|
lex->sphead->m_chistics= &lex->sp_chistics;
|
||||||
|
|
||||||
lex->sphead->m_body_begin= lip->ptr;
|
lex->sphead->set_body_begin_ptr(lip, lip->get_cpp_ptr());
|
||||||
|
|
||||||
lex->event_parse_data->body_begin= lip->ptr;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
ev_sql_stmt_inner
|
ev_sql_stmt_inner
|
||||||
{
|
{
|
||||||
@ -1888,7 +1885,7 @@ ev_sql_stmt:
|
|||||||
|
|
||||||
lex->sp_chistics.suid= SP_IS_SUID; //always the definer!
|
lex->sp_chistics.suid= SP_IS_SUID; //always the definer!
|
||||||
|
|
||||||
lex->event_parse_data->init_body(thd);
|
lex->event_parse_data->body_changed= TRUE;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -1986,6 +1983,7 @@ create_function_tail:
|
|||||||
LEX *lex= thd->lex;
|
LEX *lex= thd->lex;
|
||||||
Lex_input_stream *lip= thd->m_lip;
|
Lex_input_stream *lip= thd->m_lip;
|
||||||
sp_head *sp;
|
sp_head *sp;
|
||||||
|
const char* tmp_param_begin;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
First check if AGGREGATE was used, in that case it's a
|
First check if AGGREGATE was used, in that case it's a
|
||||||
@ -2017,7 +2015,10 @@ create_function_tail:
|
|||||||
*/
|
*/
|
||||||
$<ulong_num>$= thd->client_capabilities & CLIENT_MULTI_QUERIES;
|
$<ulong_num>$= thd->client_capabilities & CLIENT_MULTI_QUERIES;
|
||||||
thd->client_capabilities &= ~CLIENT_MULTI_QUERIES;
|
thd->client_capabilities &= ~CLIENT_MULTI_QUERIES;
|
||||||
lex->sphead->m_param_begin= lip->tok_start+1;
|
|
||||||
|
tmp_param_begin= lip->get_cpp_tok_start();
|
||||||
|
tmp_param_begin++;
|
||||||
|
lex->sphead->m_param_begin= tmp_param_begin;
|
||||||
}
|
}
|
||||||
sp_fdparam_list ')'
|
sp_fdparam_list ')'
|
||||||
{
|
{
|
||||||
@ -2025,7 +2026,7 @@ create_function_tail:
|
|||||||
LEX *lex= thd->lex;
|
LEX *lex= thd->lex;
|
||||||
Lex_input_stream *lip= thd->m_lip;
|
Lex_input_stream *lip= thd->m_lip;
|
||||||
|
|
||||||
lex->sphead->m_param_end= lip->tok_start;
|
lex->sphead->m_param_end= lip->get_cpp_tok_start();
|
||||||
}
|
}
|
||||||
RETURNS_SYM
|
RETURNS_SYM
|
||||||
{
|
{
|
||||||
@ -2065,7 +2066,7 @@ create_function_tail:
|
|||||||
Lex_input_stream *lip= thd->m_lip;
|
Lex_input_stream *lip= thd->m_lip;
|
||||||
|
|
||||||
lex->sphead->m_chistics= &lex->sp_chistics;
|
lex->sphead->m_chistics= &lex->sp_chistics;
|
||||||
lex->sphead->m_body_begin= lip->tok_start;
|
lex->sphead->set_body_begin_ptr(lip, lip->get_cpp_tok_start());
|
||||||
}
|
}
|
||||||
sp_proc_stmt
|
sp_proc_stmt
|
||||||
{
|
{
|
||||||
@ -2676,7 +2677,7 @@ sp_proc_stmt_statement:
|
|||||||
Lex_input_stream *lip= thd->m_lip;
|
Lex_input_stream *lip= thd->m_lip;
|
||||||
|
|
||||||
lex->sphead->reset_lex(thd);
|
lex->sphead->reset_lex(thd);
|
||||||
lex->sphead->m_tmp_query= lip->tok_start;
|
lex->sphead->m_tmp_query= lip->get_tok_start();
|
||||||
}
|
}
|
||||||
statement
|
statement
|
||||||
{
|
{
|
||||||
@ -2709,9 +2710,9 @@ sp_proc_stmt_statement:
|
|||||||
lex->tok_end otherwise.
|
lex->tok_end otherwise.
|
||||||
*/
|
*/
|
||||||
if (yychar == YYEMPTY)
|
if (yychar == YYEMPTY)
|
||||||
i->m_query.length= lip->ptr - sp->m_tmp_query;
|
i->m_query.length= lip->get_ptr() - sp->m_tmp_query;
|
||||||
else
|
else
|
||||||
i->m_query.length= lip->tok_end - sp->m_tmp_query;
|
i->m_query.length= lip->get_tok_end() - sp->m_tmp_query;
|
||||||
i->m_query.str= strmake_root(thd->mem_root,
|
i->m_query.str= strmake_root(thd->mem_root,
|
||||||
sp->m_tmp_query,
|
sp->m_tmp_query,
|
||||||
i->m_query.length);
|
i->m_query.length);
|
||||||
@ -4498,7 +4499,7 @@ key_def:
|
|||||||
{
|
{
|
||||||
LEX *lex=Lex;
|
LEX *lex=Lex;
|
||||||
const char *key_name= $4 ? $4 : $1;
|
const char *key_name= $4 ? $4 : $1;
|
||||||
Key *key= new foreign_key(key_name, lex->col_list,
|
Key *key= new Foreign_key(key_name, lex->col_list,
|
||||||
$8,
|
$8,
|
||||||
lex->ref_list,
|
lex->ref_list,
|
||||||
lex->fk_delete_opt,
|
lex->fk_delete_opt,
|
||||||
@ -4925,8 +4926,8 @@ opt_ref_list:
|
|||||||
| '(' ref_list ')' opt_on_delete {};
|
| '(' ref_list ')' opt_on_delete {};
|
||||||
|
|
||||||
ref_list:
|
ref_list:
|
||||||
ref_list ',' ident { Lex->ref_list.push_back(new key_part_spec($3.str)); }
|
ref_list ',' ident { Lex->ref_list.push_back(new Key_part_spec($3.str)); }
|
||||||
| ident { Lex->ref_list.push_back(new key_part_spec($1.str)); };
|
| ident { Lex->ref_list.push_back(new Key_part_spec($1.str)); };
|
||||||
|
|
||||||
|
|
||||||
opt_on_delete:
|
opt_on_delete:
|
||||||
@ -4940,16 +4941,16 @@ opt_on_delete_list:
|
|||||||
opt_on_delete_item:
|
opt_on_delete_item:
|
||||||
ON DELETE_SYM delete_option { Lex->fk_delete_opt= $3; }
|
ON DELETE_SYM delete_option { Lex->fk_delete_opt= $3; }
|
||||||
| ON UPDATE_SYM delete_option { Lex->fk_update_opt= $3; }
|
| ON UPDATE_SYM delete_option { Lex->fk_update_opt= $3; }
|
||||||
| MATCH FULL { Lex->fk_match_option= foreign_key::FK_MATCH_FULL; }
|
| MATCH FULL { Lex->fk_match_option= Foreign_key::FK_MATCH_FULL; }
|
||||||
| MATCH PARTIAL { Lex->fk_match_option= foreign_key::FK_MATCH_PARTIAL; }
|
| MATCH PARTIAL { Lex->fk_match_option= Foreign_key::FK_MATCH_PARTIAL; }
|
||||||
| MATCH SIMPLE_SYM { Lex->fk_match_option= foreign_key::FK_MATCH_SIMPLE; };
|
| MATCH SIMPLE_SYM { Lex->fk_match_option= Foreign_key::FK_MATCH_SIMPLE; };
|
||||||
|
|
||||||
delete_option:
|
delete_option:
|
||||||
RESTRICT { $$= (int) foreign_key::FK_OPTION_RESTRICT; }
|
RESTRICT { $$= (int) Foreign_key::FK_OPTION_RESTRICT; }
|
||||||
| CASCADE { $$= (int) foreign_key::FK_OPTION_CASCADE; }
|
| CASCADE { $$= (int) Foreign_key::FK_OPTION_CASCADE; }
|
||||||
| SET NULL_SYM { $$= (int) foreign_key::FK_OPTION_SET_NULL; }
|
| SET NULL_SYM { $$= (int) Foreign_key::FK_OPTION_SET_NULL; }
|
||||||
| NO_SYM ACTION { $$= (int) foreign_key::FK_OPTION_NO_ACTION; }
|
| NO_SYM ACTION { $$= (int) Foreign_key::FK_OPTION_NO_ACTION; }
|
||||||
| SET DEFAULT { $$= (int) foreign_key::FK_OPTION_DEFAULT; };
|
| SET DEFAULT { $$= (int) Foreign_key::FK_OPTION_DEFAULT; };
|
||||||
|
|
||||||
key_type:
|
key_type:
|
||||||
key_or_index { $$= Key::MULTIPLE; }
|
key_or_index { $$= Key::MULTIPLE; }
|
||||||
@ -5061,7 +5062,7 @@ key_list:
|
|||||||
| key_part order_dir { Lex->col_list.push_back($1); };
|
| key_part order_dir { Lex->col_list.push_back($1); };
|
||||||
|
|
||||||
key_part:
|
key_part:
|
||||||
ident { $$=new key_part_spec($1.str); }
|
ident { $$=new Key_part_spec($1.str); }
|
||||||
| ident '(' NUM ')'
|
| ident '(' NUM ')'
|
||||||
{
|
{
|
||||||
int key_part_len= atoi($3.str);
|
int key_part_len= atoi($3.str);
|
||||||
@ -5069,7 +5070,7 @@ key_part:
|
|||||||
{
|
{
|
||||||
my_error(ER_KEY_PART_0, MYF(0), $1.str);
|
my_error(ER_KEY_PART_0, MYF(0), $1.str);
|
||||||
}
|
}
|
||||||
$$=new key_part_spec($1.str,(uint) key_part_len);
|
$$=new Key_part_spec($1.str,(uint) key_part_len);
|
||||||
};
|
};
|
||||||
|
|
||||||
opt_ident:
|
opt_ident:
|
||||||
@ -6229,14 +6230,14 @@ remember_name:
|
|||||||
{
|
{
|
||||||
THD *thd= YYTHD;
|
THD *thd= YYTHD;
|
||||||
Lex_input_stream *lip= thd->m_lip;
|
Lex_input_stream *lip= thd->m_lip;
|
||||||
$$= (char*) lip->tok_start;
|
$$= (char*) lip->get_cpp_tok_start();
|
||||||
};
|
};
|
||||||
|
|
||||||
remember_end:
|
remember_end:
|
||||||
{
|
{
|
||||||
THD *thd= YYTHD;
|
THD *thd= YYTHD;
|
||||||
Lex_input_stream *lip= thd->m_lip;
|
Lex_input_stream *lip= thd->m_lip;
|
||||||
$$=(char*) lip->tok_end;
|
$$= (char*) lip->get_cpp_tok_end();
|
||||||
};
|
};
|
||||||
|
|
||||||
select_item2:
|
select_item2:
|
||||||
@ -8003,16 +8004,14 @@ procedure_list2:
|
|||||||
| procedure_item;
|
| procedure_item;
|
||||||
|
|
||||||
procedure_item:
|
procedure_item:
|
||||||
remember_name expr
|
remember_name expr remember_end
|
||||||
{
|
{
|
||||||
THD *thd= YYTHD;
|
THD *thd= YYTHD;
|
||||||
Lex_input_stream *lip= thd->m_lip;
|
|
||||||
|
|
||||||
if (add_proc_to_list(thd, $2))
|
if (add_proc_to_list(thd, $2))
|
||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
if (!$2->name)
|
if (!$2->name)
|
||||||
$2->set_name($1,(uint) ((char*) lip->tok_end - $1),
|
$2->set_name($1, (uint) ($3 - $1), thd->charset());
|
||||||
thd->charset());
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -9112,7 +9111,7 @@ load: LOAD DATA_SYM
|
|||||||
my_error(ER_SP_BADSTATEMENT, MYF(0), "LOAD DATA");
|
my_error(ER_SP_BADSTATEMENT, MYF(0), "LOAD DATA");
|
||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
}
|
}
|
||||||
lex->fname_start= lip->ptr;
|
lex->fname_start= lip->get_ptr();
|
||||||
}
|
}
|
||||||
load_data
|
load_data
|
||||||
{}
|
{}
|
||||||
@ -9149,7 +9148,7 @@ load_data:
|
|||||||
THD *thd= YYTHD;
|
THD *thd= YYTHD;
|
||||||
LEX *lex= thd->lex;
|
LEX *lex= thd->lex;
|
||||||
Lex_input_stream *lip= thd->m_lip;
|
Lex_input_stream *lip= thd->m_lip;
|
||||||
lex->fname_end= lip->ptr;
|
lex->fname_end= lip->get_ptr();
|
||||||
}
|
}
|
||||||
TABLE_SYM table_ident
|
TABLE_SYM table_ident
|
||||||
{
|
{
|
||||||
@ -9338,7 +9337,7 @@ param_marker:
|
|||||||
my_error(ER_VIEW_SELECT_VARIABLE, MYF(0));
|
my_error(ER_VIEW_SELECT_VARIABLE, MYF(0));
|
||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
}
|
}
|
||||||
item= new Item_param((uint) (lip->tok_start - thd->query));
|
item= new Item_param((uint) (lip->get_tok_start() - thd->query));
|
||||||
if (!($$= item) || lex->param_list.push_back(item))
|
if (!($$= item) || lex->param_list.push_back(item))
|
||||||
{
|
{
|
||||||
my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
|
my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
|
||||||
@ -9471,7 +9470,7 @@ simple_ident:
|
|||||||
|
|
||||||
Item_splocal *splocal;
|
Item_splocal *splocal;
|
||||||
splocal= new Item_splocal($1, spv->offset, spv->type,
|
splocal= new Item_splocal($1, spv->offset, spv->type,
|
||||||
lip->tok_start_prev -
|
lip->get_tok_start_prev() -
|
||||||
lex->sphead->m_tmp_query);
|
lex->sphead->m_tmp_query);
|
||||||
#ifndef DBUG_OFF
|
#ifndef DBUG_OFF
|
||||||
if (splocal)
|
if (splocal)
|
||||||
@ -10147,7 +10146,7 @@ option_type_value:
|
|||||||
lex->option_type=OPT_SESSION;
|
lex->option_type=OPT_SESSION;
|
||||||
lex->var_list.empty();
|
lex->var_list.empty();
|
||||||
lex->one_shot_set= 0;
|
lex->one_shot_set= 0;
|
||||||
lex->sphead->m_tmp_query= lip->tok_start;
|
lex->sphead->m_tmp_query= lip->get_tok_start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ext_option_value
|
ext_option_value
|
||||||
@ -10180,9 +10179,9 @@ option_type_value:
|
|||||||
lip->tok_end otherwise.
|
lip->tok_end otherwise.
|
||||||
*/
|
*/
|
||||||
if (yychar == YYEMPTY)
|
if (yychar == YYEMPTY)
|
||||||
qbuff.length= lip->ptr - sp->m_tmp_query;
|
qbuff.length= lip->get_ptr() - sp->m_tmp_query;
|
||||||
else
|
else
|
||||||
qbuff.length= lip->tok_end - sp->m_tmp_query;
|
qbuff.length= lip->get_tok_end() - sp->m_tmp_query;
|
||||||
|
|
||||||
if (!(qbuff.str= (char*) alloc_root(thd->mem_root,
|
if (!(qbuff.str= (char*) alloc_root(thd->mem_root,
|
||||||
qbuff.length + 5)))
|
qbuff.length + 5)))
|
||||||
@ -11364,7 +11363,7 @@ view_tail:
|
|||||||
if (!lex->select_lex.add_table_to_list(thd, $3, NULL, TL_OPTION_UPDATING))
|
if (!lex->select_lex.add_table_to_list(thd, $3, NULL, TL_OPTION_UPDATING))
|
||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
}
|
}
|
||||||
view_list_opt AS view_select view_check_option
|
view_list_opt AS view_select
|
||||||
{}
|
{}
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -11389,39 +11388,31 @@ view_list:
|
|||||||
|
|
||||||
view_select:
|
view_select:
|
||||||
{
|
{
|
||||||
|
THD *thd= YYTHD;
|
||||||
LEX *lex= Lex;
|
LEX *lex= Lex;
|
||||||
|
Lex_input_stream *lip= thd->m_lip;
|
||||||
lex->parsing_options.allows_variable= FALSE;
|
lex->parsing_options.allows_variable= FALSE;
|
||||||
lex->parsing_options.allows_select_into= FALSE;
|
lex->parsing_options.allows_select_into= FALSE;
|
||||||
lex->parsing_options.allows_select_procedure= FALSE;
|
lex->parsing_options.allows_select_procedure= FALSE;
|
||||||
lex->parsing_options.allows_derived= FALSE;
|
lex->parsing_options.allows_derived= FALSE;
|
||||||
|
lex->create_view_select_start= lip->get_cpp_ptr();
|
||||||
}
|
}
|
||||||
view_select_aux
|
view_select_aux view_check_option
|
||||||
{
|
{
|
||||||
|
THD *thd= YYTHD;
|
||||||
LEX *lex= Lex;
|
LEX *lex= Lex;
|
||||||
|
Lex_input_stream *lip= thd->m_lip;
|
||||||
lex->parsing_options.allows_variable= TRUE;
|
lex->parsing_options.allows_variable= TRUE;
|
||||||
lex->parsing_options.allows_select_into= TRUE;
|
lex->parsing_options.allows_select_into= TRUE;
|
||||||
lex->parsing_options.allows_select_procedure= TRUE;
|
lex->parsing_options.allows_select_procedure= TRUE;
|
||||||
lex->parsing_options.allows_derived= TRUE;
|
lex->parsing_options.allows_derived= TRUE;
|
||||||
|
lex->create_view_select_end= lip->get_cpp_ptr();
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
view_select_aux:
|
view_select_aux:
|
||||||
SELECT_SYM remember_name select_init2
|
SELECT_SYM select_init2
|
||||||
{
|
| '(' select_paren ')' union_opt
|
||||||
THD *thd= YYTHD;
|
|
||||||
LEX *lex= thd->lex;
|
|
||||||
const char *stmt_beg= (lex->sphead ?
|
|
||||||
lex->sphead->m_tmp_query : thd->query);
|
|
||||||
lex->create_view_select_start= $2 - stmt_beg;
|
|
||||||
}
|
|
||||||
| '(' remember_name select_paren ')' union_opt
|
|
||||||
{
|
|
||||||
THD *thd= YYTHD;
|
|
||||||
LEX *lex= thd->lex;
|
|
||||||
const char *stmt_beg= (lex->sphead ?
|
|
||||||
lex->sphead->m_tmp_query : thd->query);
|
|
||||||
lex->create_view_select_start= $2 - stmt_beg;
|
|
||||||
}
|
|
||||||
;
|
;
|
||||||
|
|
||||||
view_check_option:
|
view_check_option:
|
||||||
@ -11442,9 +11433,31 @@ view_check_option:
|
|||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
trigger_tail:
|
trigger_tail:
|
||||||
TRIGGER_SYM remember_name sp_name trg_action_time trg_event
|
TRIGGER_SYM
|
||||||
ON remember_name table_ident FOR_SYM remember_name EACH_SYM ROW_SYM
|
remember_name
|
||||||
{
|
sp_name
|
||||||
|
trg_action_time
|
||||||
|
trg_event
|
||||||
|
ON
|
||||||
|
remember_name /* $7 */
|
||||||
|
{ /* $8 */
|
||||||
|
THD *thd= YYTHD;
|
||||||
|
LEX *lex= thd->lex;
|
||||||
|
Lex_input_stream *lip= thd->m_lip;
|
||||||
|
lex->raw_trg_on_table_name_begin= lip->get_tok_start();
|
||||||
|
}
|
||||||
|
table_ident /* $9 */
|
||||||
|
FOR_SYM
|
||||||
|
remember_name /* $11 */
|
||||||
|
{ /* $12 */
|
||||||
|
THD *thd= YYTHD;
|
||||||
|
LEX *lex= thd->lex;
|
||||||
|
Lex_input_stream *lip= thd->m_lip;
|
||||||
|
lex->raw_trg_on_table_name_end= lip->get_tok_start();
|
||||||
|
}
|
||||||
|
EACH_SYM
|
||||||
|
ROW_SYM
|
||||||
|
{ /* $15 */
|
||||||
THD *thd= YYTHD;
|
THD *thd= YYTHD;
|
||||||
LEX *lex= thd->lex;
|
LEX *lex= thd->lex;
|
||||||
Lex_input_stream *lip= thd->m_lip;
|
Lex_input_stream *lip= thd->m_lip;
|
||||||
@ -11463,7 +11476,7 @@ trigger_tail:
|
|||||||
sp->init_sp_name(thd, $3);
|
sp->init_sp_name(thd, $3);
|
||||||
lex->stmt_definition_begin= $2;
|
lex->stmt_definition_begin= $2;
|
||||||
lex->ident.str= $7;
|
lex->ident.str= $7;
|
||||||
lex->ident.length= $10 - $7;
|
lex->ident.length= $11 - $7;
|
||||||
|
|
||||||
sp->m_type= TYPE_ENUM_TRIGGER;
|
sp->m_type= TYPE_ENUM_TRIGGER;
|
||||||
lex->sphead= sp;
|
lex->sphead= sp;
|
||||||
@ -11478,12 +11491,10 @@ trigger_tail:
|
|||||||
|
|
||||||
bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
|
bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
|
||||||
lex->sphead->m_chistics= &lex->sp_chistics;
|
lex->sphead->m_chistics= &lex->sp_chistics;
|
||||||
lex->sphead->m_body_begin= lip->ptr;
|
lex->sphead->set_body_begin_ptr(lip, lip->get_cpp_ptr());
|
||||||
while (my_isspace(system_charset_info, lex->sphead->m_body_begin[0]))
|
|
||||||
++lex->sphead->m_body_begin;
|
|
||||||
}
|
}
|
||||||
sp_proc_stmt
|
sp_proc_stmt /* $16 */
|
||||||
{
|
{ /* $17 */
|
||||||
LEX *lex= Lex;
|
LEX *lex= Lex;
|
||||||
sp_head *sp= lex->sphead;
|
sp_head *sp= lex->sphead;
|
||||||
|
|
||||||
@ -11491,7 +11502,7 @@ trigger_tail:
|
|||||||
sp->init_strings(YYTHD, lex);
|
sp->init_strings(YYTHD, lex);
|
||||||
/* Restore flag if it was cleared above */
|
/* Restore flag if it was cleared above */
|
||||||
|
|
||||||
YYTHD->client_capabilities |= $<ulong_num>13;
|
YYTHD->client_capabilities |= $<ulong_num>15;
|
||||||
sp->restore_thd_mem_root(YYTHD);
|
sp->restore_thd_mem_root(YYTHD);
|
||||||
|
|
||||||
if (sp->is_not_allowed_in_function("trigger"))
|
if (sp->is_not_allowed_in_function("trigger"))
|
||||||
@ -11502,7 +11513,7 @@ trigger_tail:
|
|||||||
sp_proc_stmt alternatives are not saving/restoring LEX, so
|
sp_proc_stmt alternatives are not saving/restoring LEX, so
|
||||||
lex->query_tables can be wiped out.
|
lex->query_tables can be wiped out.
|
||||||
*/
|
*/
|
||||||
if (!lex->select_lex.add_table_to_list(YYTHD, $8,
|
if (!lex->select_lex.add_table_to_list(YYTHD, $9,
|
||||||
(LEX_STRING*) 0,
|
(LEX_STRING*) 0,
|
||||||
TL_OPTION_UPDATING,
|
TL_OPTION_UPDATING,
|
||||||
TL_IGNORE))
|
TL_IGNORE))
|
||||||
@ -11560,8 +11571,11 @@ sp_tail:
|
|||||||
THD *thd= YYTHD;
|
THD *thd= YYTHD;
|
||||||
LEX *lex= thd->lex;
|
LEX *lex= thd->lex;
|
||||||
Lex_input_stream *lip= thd->m_lip;
|
Lex_input_stream *lip= thd->m_lip;
|
||||||
|
const char* tmp_param_begin;
|
||||||
|
|
||||||
lex->sphead->m_param_begin= lip->tok_start+1;
|
tmp_param_begin= lip->get_cpp_tok_start();
|
||||||
|
tmp_param_begin++;
|
||||||
|
lex->sphead->m_param_begin= tmp_param_begin;
|
||||||
}
|
}
|
||||||
sp_pdparam_list
|
sp_pdparam_list
|
||||||
')'
|
')'
|
||||||
@ -11570,7 +11584,7 @@ sp_tail:
|
|||||||
LEX *lex= thd->lex;
|
LEX *lex= thd->lex;
|
||||||
Lex_input_stream *lip= thd->m_lip;
|
Lex_input_stream *lip= thd->m_lip;
|
||||||
|
|
||||||
lex->sphead->m_param_end= lip->tok_start;
|
lex->sphead->m_param_end= lip->get_cpp_tok_start();
|
||||||
bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
|
bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
|
||||||
}
|
}
|
||||||
sp_c_chistics
|
sp_c_chistics
|
||||||
@ -11580,7 +11594,7 @@ sp_tail:
|
|||||||
Lex_input_stream *lip= thd->m_lip;
|
Lex_input_stream *lip= thd->m_lip;
|
||||||
|
|
||||||
lex->sphead->m_chistics= &lex->sp_chistics;
|
lex->sphead->m_chistics= &lex->sp_chistics;
|
||||||
lex->sphead->m_body_begin= lip->tok_start;
|
lex->sphead->set_body_begin_ptr(lip, lip->get_cpp_tok_start());
|
||||||
}
|
}
|
||||||
sp_proc_stmt
|
sp_proc_stmt
|
||||||
{
|
{
|
||||||
|
@ -29,21 +29,21 @@
|
|||||||
|
|
||||||
#define FCOMP 17 /* Bytes for a packed field */
|
#define FCOMP 17 /* Bytes for a packed field */
|
||||||
|
|
||||||
static uchar * pack_screens(List<create_field> &create_fields,
|
static uchar * pack_screens(List<Create_field> &create_fields,
|
||||||
uint *info_length, uint *screens, bool small_file);
|
uint *info_length, uint *screens, bool small_file);
|
||||||
static uint pack_keys(uchar *keybuff,uint key_count, KEY *key_info,
|
static uint pack_keys(uchar *keybuff,uint key_count, KEY *key_info,
|
||||||
ulong data_offset);
|
ulong data_offset);
|
||||||
static bool pack_header(uchar *forminfo,enum legacy_db_type table_type,
|
static bool pack_header(uchar *forminfo,enum legacy_db_type table_type,
|
||||||
List<create_field> &create_fields,
|
List<Create_field> &create_fields,
|
||||||
uint info_length, uint screens, uint table_options,
|
uint info_length, uint screens, uint table_options,
|
||||||
ulong data_offset, handler *file);
|
ulong data_offset, handler *file);
|
||||||
static uint get_interval_id(uint *int_count,List<create_field> &create_fields,
|
static uint get_interval_id(uint *int_count,List<Create_field> &create_fields,
|
||||||
create_field *last_field);
|
Create_field *last_field);
|
||||||
static bool pack_fields(File file, List<create_field> &create_fields,
|
static bool pack_fields(File file, List<Create_field> &create_fields,
|
||||||
ulong data_offset);
|
ulong data_offset);
|
||||||
static bool make_empty_rec(THD *thd, int file, enum legacy_db_type table_type,
|
static bool make_empty_rec(THD *thd, int file, enum legacy_db_type table_type,
|
||||||
uint table_options,
|
uint table_options,
|
||||||
List<create_field> &create_fields,
|
List<Create_field> &create_fields,
|
||||||
uint reclength, ulong data_offset,
|
uint reclength, ulong data_offset,
|
||||||
handler *handler);
|
handler *handler);
|
||||||
|
|
||||||
@ -70,7 +70,7 @@ static bool make_empty_rec(THD *thd, int file, enum legacy_db_type table_type,
|
|||||||
bool mysql_create_frm(THD *thd, const char *file_name,
|
bool mysql_create_frm(THD *thd, const char *file_name,
|
||||||
const char *db, const char *table,
|
const char *db, const char *table,
|
||||||
HA_CREATE_INFO *create_info,
|
HA_CREATE_INFO *create_info,
|
||||||
List<create_field> &create_fields,
|
List<Create_field> &create_fields,
|
||||||
uint keys, KEY *key_info,
|
uint keys, KEY *key_info,
|
||||||
handler *db_file)
|
handler *db_file)
|
||||||
{
|
{
|
||||||
@ -294,8 +294,8 @@ bool mysql_create_frm(THD *thd, const char *file_name,
|
|||||||
Restore all UCS2 intervals.
|
Restore all UCS2 intervals.
|
||||||
HEX representation of them is not needed anymore.
|
HEX representation of them is not needed anymore.
|
||||||
*/
|
*/
|
||||||
List_iterator<create_field> it(create_fields);
|
List_iterator<Create_field> it(create_fields);
|
||||||
create_field *field;
|
Create_field *field;
|
||||||
while ((field=it++))
|
while ((field=it++))
|
||||||
{
|
{
|
||||||
if (field->save_interval)
|
if (field->save_interval)
|
||||||
@ -341,7 +341,7 @@ err3:
|
|||||||
int rea_create_table(THD *thd, const char *path,
|
int rea_create_table(THD *thd, const char *path,
|
||||||
const char *db, const char *table_name,
|
const char *db, const char *table_name,
|
||||||
HA_CREATE_INFO *create_info,
|
HA_CREATE_INFO *create_info,
|
||||||
List<create_field> &create_fields,
|
List<Create_field> &create_fields,
|
||||||
uint keys, KEY *key_info, handler *file)
|
uint keys, KEY *key_info, handler *file)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("rea_create_table");
|
DBUG_ENTER("rea_create_table");
|
||||||
@ -371,7 +371,7 @@ err_handler:
|
|||||||
|
|
||||||
/* Pack screens to a screen for save in a form-file */
|
/* Pack screens to a screen for save in a form-file */
|
||||||
|
|
||||||
static uchar *pack_screens(List<create_field> &create_fields,
|
static uchar *pack_screens(List<Create_field> &create_fields,
|
||||||
uint *info_length, uint *screens,
|
uint *info_length, uint *screens,
|
||||||
bool small_file)
|
bool small_file)
|
||||||
{
|
{
|
||||||
@ -380,7 +380,7 @@ static uchar *pack_screens(List<create_field> &create_fields,
|
|||||||
uint length,cols;
|
uint length,cols;
|
||||||
uchar *info,*pos,*start_screen;
|
uchar *info,*pos,*start_screen;
|
||||||
uint fields=create_fields.elements;
|
uint fields=create_fields.elements;
|
||||||
List_iterator<create_field> it(create_fields);
|
List_iterator<Create_field> it(create_fields);
|
||||||
DBUG_ENTER("pack_screens");
|
DBUG_ENTER("pack_screens");
|
||||||
|
|
||||||
start_row=4; end_row=22; cols=80; fields_on_screen=end_row+1-start_row;
|
start_row=4; end_row=22; cols=80; fields_on_screen=end_row+1-start_row;
|
||||||
@ -388,7 +388,7 @@ static uchar *pack_screens(List<create_field> &create_fields,
|
|||||||
*screens=(fields-1)/fields_on_screen+1;
|
*screens=(fields-1)/fields_on_screen+1;
|
||||||
length= (*screens) * (SC_INFO_LENGTH+ (cols>> 1)+4);
|
length= (*screens) * (SC_INFO_LENGTH+ (cols>> 1)+4);
|
||||||
|
|
||||||
create_field *field;
|
Create_field *field;
|
||||||
while ((field=it++))
|
while ((field=it++))
|
||||||
length+=(uint) strlen(field->field_name)+1+TE_INFO_LENGTH+cols/2;
|
length+=(uint) strlen(field->field_name)+1+TE_INFO_LENGTH+cols/2;
|
||||||
|
|
||||||
@ -401,7 +401,7 @@ static uchar *pack_screens(List<create_field> &create_fields,
|
|||||||
it.rewind();
|
it.rewind();
|
||||||
for (i=0 ; i < fields ; i++)
|
for (i=0 ; i < fields ; i++)
|
||||||
{
|
{
|
||||||
create_field *cfield=it++;
|
Create_field *cfield=it++;
|
||||||
if (row++ == end_row)
|
if (row++ == end_row)
|
||||||
{
|
{
|
||||||
if (i)
|
if (i)
|
||||||
@ -521,7 +521,7 @@ static uint pack_keys(uchar *keybuff, uint key_count, KEY *keyinfo,
|
|||||||
/* Make formheader */
|
/* Make formheader */
|
||||||
|
|
||||||
static bool pack_header(uchar *forminfo, enum legacy_db_type table_type,
|
static bool pack_header(uchar *forminfo, enum legacy_db_type table_type,
|
||||||
List<create_field> &create_fields,
|
List<Create_field> &create_fields,
|
||||||
uint info_length, uint screens, uint table_options,
|
uint info_length, uint screens, uint table_options,
|
||||||
ulong data_offset, handler *file)
|
ulong data_offset, handler *file)
|
||||||
{
|
{
|
||||||
@ -544,8 +544,8 @@ static bool pack_header(uchar *forminfo, enum legacy_db_type table_type,
|
|||||||
|
|
||||||
/* Check fields */
|
/* Check fields */
|
||||||
|
|
||||||
List_iterator<create_field> it(create_fields);
|
List_iterator<Create_field> it(create_fields);
|
||||||
create_field *field;
|
Create_field *field;
|
||||||
while ((field=it++))
|
while ((field=it++))
|
||||||
{
|
{
|
||||||
uint tmp_len= system_charset_info->cset->charpos(system_charset_info,
|
uint tmp_len= system_charset_info->cset->charpos(system_charset_info,
|
||||||
@ -687,11 +687,11 @@ static bool pack_header(uchar *forminfo, enum legacy_db_type table_type,
|
|||||||
|
|
||||||
/* get each unique interval each own id */
|
/* get each unique interval each own id */
|
||||||
|
|
||||||
static uint get_interval_id(uint *int_count,List<create_field> &create_fields,
|
static uint get_interval_id(uint *int_count,List<Create_field> &create_fields,
|
||||||
create_field *last_field)
|
Create_field *last_field)
|
||||||
{
|
{
|
||||||
List_iterator<create_field> it(create_fields);
|
List_iterator<Create_field> it(create_fields);
|
||||||
create_field *field;
|
Create_field *field;
|
||||||
TYPELIB *interval=last_field->interval;
|
TYPELIB *interval=last_field->interval;
|
||||||
|
|
||||||
while ((field=it++) != last_field)
|
while ((field=it++) != last_field)
|
||||||
@ -715,18 +715,18 @@ static uint get_interval_id(uint *int_count,List<create_field> &create_fields,
|
|||||||
|
|
||||||
/* Save fields, fieldnames and intervals */
|
/* Save fields, fieldnames and intervals */
|
||||||
|
|
||||||
static bool pack_fields(File file, List<create_field> &create_fields,
|
static bool pack_fields(File file, List<Create_field> &create_fields,
|
||||||
ulong data_offset)
|
ulong data_offset)
|
||||||
{
|
{
|
||||||
reg2 uint i;
|
reg2 uint i;
|
||||||
uint int_count, comment_length=0;
|
uint int_count, comment_length=0;
|
||||||
uchar buff[MAX_FIELD_WIDTH];
|
uchar buff[MAX_FIELD_WIDTH];
|
||||||
create_field *field;
|
Create_field *field;
|
||||||
DBUG_ENTER("pack_fields");
|
DBUG_ENTER("pack_fields");
|
||||||
|
|
||||||
/* Write field info */
|
/* Write field info */
|
||||||
|
|
||||||
List_iterator<create_field> it(create_fields);
|
List_iterator<Create_field> it(create_fields);
|
||||||
|
|
||||||
int_count=0;
|
int_count=0;
|
||||||
while ((field=it++))
|
while ((field=it++))
|
||||||
@ -856,7 +856,7 @@ static bool pack_fields(File file, List<create_field> &create_fields,
|
|||||||
|
|
||||||
static bool make_empty_rec(THD *thd, File file,enum legacy_db_type table_type,
|
static bool make_empty_rec(THD *thd, File file,enum legacy_db_type table_type,
|
||||||
uint table_options,
|
uint table_options,
|
||||||
List<create_field> &create_fields,
|
List<Create_field> &create_fields,
|
||||||
uint reclength,
|
uint reclength,
|
||||||
ulong data_offset,
|
ulong data_offset,
|
||||||
handler *handler)
|
handler *handler)
|
||||||
@ -867,7 +867,7 @@ static bool make_empty_rec(THD *thd, File file,enum legacy_db_type table_type,
|
|||||||
uchar *buff,*null_pos;
|
uchar *buff,*null_pos;
|
||||||
TABLE table;
|
TABLE table;
|
||||||
TABLE_SHARE share;
|
TABLE_SHARE share;
|
||||||
create_field *field;
|
Create_field *field;
|
||||||
enum_check_fields old_count_cuted_fields= thd->count_cuted_fields;
|
enum_check_fields old_count_cuted_fields= thd->count_cuted_fields;
|
||||||
DBUG_ENTER("make_empty_rec");
|
DBUG_ENTER("make_empty_rec");
|
||||||
|
|
||||||
@ -893,7 +893,7 @@ static bool make_empty_rec(THD *thd, File file,enum legacy_db_type table_type,
|
|||||||
}
|
}
|
||||||
null_pos= buff;
|
null_pos= buff;
|
||||||
|
|
||||||
List_iterator<create_field> it(create_fields);
|
List_iterator<Create_field> it(create_fields);
|
||||||
thd->count_cuted_fields= CHECK_FIELD_WARN; // To find wrong default values
|
thd->count_cuted_fields= CHECK_FIELD_WARN; // To find wrong default values
|
||||||
while ((field=it++))
|
while ((field=it++))
|
||||||
{
|
{
|
||||||
|
@ -74,6 +74,7 @@
|
|||||||
#define MAX_TIME_WIDTH 23 /* -DDDDDD HH:MM:SS.###### */
|
#define MAX_TIME_WIDTH 23 /* -DDDDDD HH:MM:SS.###### */
|
||||||
#define MAX_DATETIME_FULL_WIDTH 29 /* YYYY-MM-DD HH:MM:SS.###### AM */
|
#define MAX_DATETIME_FULL_WIDTH 29 /* YYYY-MM-DD HH:MM:SS.###### AM */
|
||||||
#define MAX_DATETIME_WIDTH 19 /* YYYY-MM-DD HH:MM:SS */
|
#define MAX_DATETIME_WIDTH 19 /* YYYY-MM-DD HH:MM:SS */
|
||||||
|
#define MAX_DATETIME_COMPRESSED_WIDTH 14 /* YYYYMMDDHHMMSS */
|
||||||
|
|
||||||
#define MAX_TABLES (sizeof(table_map)*8-3) /* Max tables in join */
|
#define MAX_TABLES (sizeof(table_map)*8-3) /* Max tables in join */
|
||||||
#define PARAM_TABLE_BIT (((table_map) 1) << (sizeof(table_map)*8-3))
|
#define PARAM_TABLE_BIT (((table_map) 1) << (sizeof(table_map)*8-3))
|
||||||
|
@ -16079,7 +16079,7 @@ static void test_bug24179()
|
|||||||
Bug#28075 "COM_DEBUG crashes mysqld"
|
Bug#28075 "COM_DEBUG crashes mysqld"
|
||||||
Note: Test disabled because of failure in PushBuild.
|
Note: Test disabled because of failure in PushBuild.
|
||||||
*/
|
*/
|
||||||
#ifdef fix_bug_in_pb_first
|
|
||||||
static void test_bug28075()
|
static void test_bug28075()
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
@ -16095,12 +16095,12 @@ static void test_bug28075()
|
|||||||
|
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Bug#27876 (SF with cyrillic variable name fails during execution (regression))
|
Bug#27876 (SF with cyrillic variable name fails during execution (regression))
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void test_bug27876()
|
static void test_bug27876()
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
@ -16165,6 +16165,7 @@ static void test_bug27876()
|
|||||||
Bug#28505: mysql_affected_rows() returns wrong value if CLIENT_FOUND_ROWS
|
Bug#28505: mysql_affected_rows() returns wrong value if CLIENT_FOUND_ROWS
|
||||||
flag is set.
|
flag is set.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void test_bug28505()
|
static void test_bug28505()
|
||||||
{
|
{
|
||||||
my_ulonglong res;
|
my_ulonglong res;
|
||||||
@ -16217,6 +16218,59 @@ static void test_bug28934()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Bug#27592 (stack overrun when storing datetime value using prepared statements)
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void test_bug27592()
|
||||||
|
{
|
||||||
|
const int NUM_ITERATIONS= 40;
|
||||||
|
int i;
|
||||||
|
int rc;
|
||||||
|
MYSQL_STMT *stmt= NULL;
|
||||||
|
MYSQL_BIND bind[1];
|
||||||
|
MYSQL_TIME time_val;
|
||||||
|
|
||||||
|
DBUG_ENTER("test_bug27592");
|
||||||
|
myheader("test_bug27592");
|
||||||
|
|
||||||
|
mysql_query(mysql, "DROP TABLE IF EXISTS t1");
|
||||||
|
mysql_query(mysql, "CREATE TABLE t1(c2 DATETIME)");
|
||||||
|
|
||||||
|
stmt= mysql_simple_prepare(mysql, "INSERT INTO t1 VALUES (?)");
|
||||||
|
DIE_UNLESS(stmt);
|
||||||
|
|
||||||
|
memset(bind, 0, sizeof(bind));
|
||||||
|
|
||||||
|
bind[0].buffer_type= MYSQL_TYPE_DATETIME;
|
||||||
|
bind[0].buffer= (char *) &time_val;
|
||||||
|
bind[0].length= NULL;
|
||||||
|
|
||||||
|
for (i= 0; i < NUM_ITERATIONS; i++)
|
||||||
|
{
|
||||||
|
time_val.year= 2007;
|
||||||
|
time_val.month= 6;
|
||||||
|
time_val.day= 7;
|
||||||
|
time_val.hour= 18;
|
||||||
|
time_val.minute= 41;
|
||||||
|
time_val.second= 3;
|
||||||
|
|
||||||
|
time_val.second_part=0;
|
||||||
|
time_val.neg=0;
|
||||||
|
|
||||||
|
rc= mysql_stmt_bind_param(stmt, bind);
|
||||||
|
check_execute(stmt, rc);
|
||||||
|
|
||||||
|
rc= mysql_stmt_execute(stmt);
|
||||||
|
check_execute(stmt, rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
mysql_stmt_close(stmt);
|
||||||
|
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Read and parse arguments and MySQL options from my.cnf
|
Read and parse arguments and MySQL options from my.cnf
|
||||||
*/
|
*/
|
||||||
@ -16498,15 +16552,14 @@ static struct my_tests_st my_tests[]= {
|
|||||||
{ "test_bug15518", test_bug15518 },
|
{ "test_bug15518", test_bug15518 },
|
||||||
{ "test_bug23383", test_bug23383 },
|
{ "test_bug23383", test_bug23383 },
|
||||||
{ "test_bug21635", test_bug21635 },
|
{ "test_bug21635", test_bug21635 },
|
||||||
{ "test_bug28505", test_bug28505 },
|
|
||||||
{ "test_status", test_status },
|
{ "test_status", test_status },
|
||||||
{ "test_bug24179", test_bug24179 },
|
{ "test_bug24179", test_bug24179 },
|
||||||
{ "test_ps_query_cache", test_ps_query_cache },
|
{ "test_ps_query_cache", test_ps_query_cache },
|
||||||
#ifdef fix_bug_in_pb_first
|
|
||||||
{ "test_bug28075", test_bug28075 },
|
{ "test_bug28075", test_bug28075 },
|
||||||
#endif
|
|
||||||
{ "test_bug28934", test_bug28934 },
|
|
||||||
{ "test_bug27876", test_bug27876 },
|
{ "test_bug27876", test_bug27876 },
|
||||||
|
{ "test_bug28505", test_bug28505 },
|
||||||
|
{ "test_bug28934", test_bug28934 },
|
||||||
|
{ "test_bug27592", test_bug27592 },
|
||||||
{ 0, 0 }
|
{ 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user