This commit is contained in:
monty@mashka.mysql.fi 2002-12-14 17:49:01 +02:00
commit d783e18436
76 changed files with 3257 additions and 1904 deletions

View File

@ -4502,8 +4502,8 @@ stmt_fetch_row(MYSQL_STMT *stmt, uchar **row)
MYSQL_BIND *bind, *end; MYSQL_BIND *bind, *end;
uchar *null_ptr= (uchar*) *row, bit; uchar *null_ptr= (uchar*) *row, bit;
*row+= (stmt->field_count+7)/8; row+= (stmt->field_count+9)/8;
bit=1; bit= 4; /* First 2 bits are reserved */
/* Copy complete row to application buffers */ /* Copy complete row to application buffers */
for (bind= stmt->bind, end= (MYSQL_BIND *) bind + stmt->field_count; for (bind= stmt->bind, end= (MYSQL_BIND *) bind + stmt->field_count;

View File

@ -44,7 +44,7 @@ sqlsources = convert.cc derror.cc field.cc field_conv.cc filesort.cc \
item_func.cc item_strfunc.cc item_sum.cc item_timefunc.cc \ item_func.cc item_strfunc.cc item_sum.cc item_timefunc.cc \
item_uniq.cc item_subselect.cc item_row.cc\ item_uniq.cc item_subselect.cc item_row.cc\
key.cc lock.cc log.cc log_event.cc mf_iocache.cc\ key.cc lock.cc log.cc log_event.cc mf_iocache.cc\
mini_client.cc net_pkg.cc net_serv.cc opt_ft.cc opt_range.cc \ mini_client.cc protocol.cc net_serv.cc opt_ft.cc opt_range.cc \
opt_sum.cc procedure.cc records.cc sql_acl.cc \ opt_sum.cc procedure.cc records.cc sql_acl.cc \
repl_failsafe.cc slave.cc sql_load.cc sql_olap.cc \ repl_failsafe.cc slave.cc sql_load.cc sql_olap.cc \
sql_analyse.cc sql_base.cc sql_cache.cc sql_class.cc \ sql_analyse.cc sql_base.cc sql_cache.cc sql_class.cc \

View File

@ -10,10 +10,10 @@ CASE "c" when "a" then 1 when "b" then 2 ELSE 3 END
3 3
select CASE BINARY "b" when "a" then 1 when "B" then 2 WHEN "b" then "ok" END; select CASE BINARY "b" when "a" then 1 when "B" then 2 WHEN "b" then "ok" END;
CASE BINARY "b" when "a" then 1 when "B" then 2 WHEN "b" then "ok" END CASE BINARY "b" when "a" then 1 when "B" then 2 WHEN "b" then "ok" END
ok 0
select CASE "b" when "a" then 1 when binary "B" then 2 WHEN "b" then "ok" END; select CASE "b" when "a" then 1 when binary "B" then 2 WHEN "b" then "ok" END;
CASE "b" when "a" then 1 when binary "B" then 2 WHEN "b" then "ok" END CASE "b" when "a" then 1 when binary "B" then 2 WHEN "b" then "ok" END
ok 0
select CASE concat("a","b") when concat("ab","") then "a" when "b" then "b" end; select CASE concat("a","b") when concat("ab","") then "a" when "b" then "b" end;
CASE concat("a","b") when concat("ab","") then "a" when "b" then "b" end CASE concat("a","b") when concat("ab","") then "a" when "b" then "b" end
a a

View File

@ -24,10 +24,10 @@ cast("A" as binary) = "a" cast(BINARY "a" as CHAR) = "A"
0 1 0 1
select cast("2001-1-1" as DATE), cast("2001-1-1" as DATETIME); select cast("2001-1-1" as DATE), cast("2001-1-1" as DATETIME);
cast("2001-1-1" as DATE) cast("2001-1-1" as DATETIME) cast("2001-1-1" as DATE) cast("2001-1-1" as DATETIME)
2001-1-1 2001-1-1 2001-01-01 2001-01-01 00:00:00
select cast("1:2:3" as TIME); select cast("1:2:3" as TIME);
cast("1:2:3" as TIME) cast("1:2:3" as TIME)
1:2:3 01:02:03
select cast("2001-1-1" as date) = "2001-01-01"; select cast("2001-1-1" as date) = "2001-01-01";
cast("2001-1-1" as date) = "2001-01-01" cast("2001-1-1" as date) = "2001-01-01"
0 0

View File

@ -12,9 +12,9 @@ select * from t1 where tmsp=0;
a tmsp a tmsp
select * from t1 where tmsp=19711006010203; select * from t1 where tmsp=19711006010203;
a tmsp a tmsp
5 19711006010203 5 1971-10-06 01:02:03
6 19711006010203 6 1971-10-06 01:02:03
8 19711006010203 8 1971-10-06 01:02:03
drop table t1; drop table t1;
create table t1 (a int not null auto_increment primary key, b char(10)); create table t1 (a int not null auto_increment primary key, b char(10));
insert delayed into t1 values (1,"b"); insert delayed into t1 values (1,"b");

View File

@ -114,7 +114,7 @@ a t
20 20 20 20
explain select count(*) from t1 as tt1, (select * from t1) as tt2; explain select count(*) from t1 as tt1, (select * from t1) as tt2;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY Select tables optimized away 1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
2 DERIVED tt1 index NULL a 4 NULL 10000 Using index 2 DERIVED tt1 index NULL a 4 NULL 10000 Using index
drop table if exists t1; drop table if exists t1;
SELECT * FROM (SELECT (SELECT * FROM (SELECT 1 as a) as a )) as b; SELECT * FROM (SELECT (SELECT * FROM (SELECT 1 as a) as a )) as b;

View File

@ -27,4 +27,4 @@ Key column 'foo' doesn't exist in table
drop table t1; drop table t1;
explain select 1; explain select 1;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE No tables used 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL No tables used

View File

@ -31,17 +31,17 @@ INSERT INTO t1 VALUES (357917728,7,2,2,20000319145027);
select visitor_id,max(ts) as mts from t1 group by visitor_id select visitor_id,max(ts) as mts from t1 group by visitor_id
having mts < DATE_SUB(NOW(),INTERVAL 3 MONTH); having mts < DATE_SUB(NOW(),INTERVAL 3 MONTH);
visitor_id mts visitor_id mts
48985536 20000319013932 48985536 2000-03-19 01:39:32
173865424 20000318233615 173865424 2000-03-18 23:36:15
357917728 20000319145027 357917728 2000-03-19 14:50:27
465931136 20000318160953 465931136 2000-03-18 16:09:53
1092858576 20000319013445 1092858576 2000-03-19 01:34:45
select visitor_id,max(ts) as mts from t1 group by visitor_id select visitor_id,max(ts) as mts from t1 group by visitor_id
having DATE_ADD(mts,INTERVAL 3 MONTH) < NOW(); having DATE_ADD(mts,INTERVAL 3 MONTH) < NOW();
visitor_id mts visitor_id mts
48985536 20000319013932 48985536 2000-03-19 01:39:32
173865424 20000318233615 173865424 2000-03-18 23:36:15
357917728 20000319145027 357917728 2000-03-19 14:50:27
465931136 20000318160953 465931136 2000-03-18 16:09:53
1092858576 20000319013445 1092858576 2000-03-19 01:34:45
drop table t1; drop table t1;

View File

@ -228,14 +228,14 @@ bugstatus int(10) unsigned default NULL,
submitter int(10) unsigned default NULL submitter int(10) unsigned default NULL
) TYPE=MyISAM; ) TYPE=MyISAM;
INSERT INTO t1 VALUES (1,'Link',1,1,1,'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa','2001-02-28 08:40:16',20010228084016,0,4); INSERT INTO t1 VALUES (1,'Link',1,1,1,'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa','2001-02-28 08:40:16',20010228084016,0,4);
SELECT CONCAT('"',CONCAT_WS('";"',title,prio,category,program,bugdesc,created,modified,bugstatus,submitter), '"') FROM t1; SELECT CONCAT('"',CONCAT_WS('";"',title,prio,category,program,bugdesc,created,modified+0,bugstatus,submitter), '"') FROM t1;
CONCAT('"',CONCAT_WS('";"',title,prio,category,program,bugdesc,created,modified,bugstatus,submitter), '"') CONCAT('"',CONCAT_WS('";"',title,prio,category,program,bugdesc,created,modified+0,bugstatus,submitter), '"')
"Link";"1";"1";"1";"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";"2001-02-28 08:40:16";"20010228084016";"0";"4" "Link";"1";"1";"1";"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";"2001-02-28 08:40:16";"20010228084016";"0";"4"
SELECT CONCAT('"',CONCAT_WS('";"',title,prio,category,program,bugstatus,submitter), '"') FROM t1; SELECT CONCAT('"',CONCAT_WS('";"',title,prio,category,program,bugstatus,submitter), '"') FROM t1;
CONCAT('"',CONCAT_WS('";"',title,prio,category,program,bugstatus,submitter), '"') CONCAT('"',CONCAT_WS('";"',title,prio,category,program,bugstatus,submitter), '"')
"Link";"1";"1";"1";"0";"4" "Link";"1";"1";"1";"0";"4"
SELECT CONCAT_WS('";"',title,prio,category,program,bugdesc,created,modified,bugstatus,submitter) FROM t1; SELECT CONCAT_WS('";"',title,prio,category,program,bugdesc,created,modified+0,bugstatus,submitter) FROM t1;
CONCAT_WS('";"',title,prio,category,program,bugdesc,created,modified,bugstatus,submitter) CONCAT_WS('";"',title,prio,category,program,bugdesc,created,modified+0,bugstatus,submitter)
Link";"1";"1";"1";"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";"2001-02-28 08:40:16";"20010228084016";"0";"4 Link";"1";"1";"1";"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";"2001-02-28 08:40:16";"20010228084016";"0";"4
drop table t1; drop table t1;
CREATE TABLE t1 (id int(11) NOT NULL auto_increment, tmp text NOT NULL, KEY id (id)) TYPE=MyISAM; CREATE TABLE t1 (id int(11) NOT NULL auto_increment, tmp text NOT NULL, KEY id (id)) TYPE=MyISAM;

View File

@ -392,11 +392,71 @@ CREATE TABLE t3 (ctime1 char(19) NOT NULL, ctime2 char(19) NOT NULL);
INSERT INTO t3 VALUES ("2002-10-29 16:51:06","2002-11-05 16:47:31"); INSERT INTO t3 VALUES ("2002-10-29 16:51:06","2002-11-05 16:47:31");
select * from t1, t2 where t1.start between t2.ctime1 and t2.ctime2; select * from t1, t2 where t1.start between t2.ctime1 and t2.ctime2;
start ctime1 ctime2 start ctime1 ctime2
2002-11-04 00:00:00 20021029165106 20021105164731 2002-11-04 00:00:00 2002-10-29 16:51:06 2002-11-05 16:47:31
select * from t1, t2 where t1.start >= t2.ctime1 and t1.start <= t2.ctime2; select * from t1, t2 where t1.start >= t2.ctime1 and t1.start <= t2.ctime2;
start ctime1 ctime2 start ctime1 ctime2
2002-11-04 00:00:00 20021029165106 20021105164731 2002-11-04 00:00:00 2002-10-29 16:51:06 2002-11-05 16:47:31
select * from t1, t3 where t1.start between t3.ctime1 and t3.ctime2; select * from t1, t3 where t1.start between t3.ctime1 and t3.ctime2;
start ctime1 ctime2 start ctime1 ctime2
2002-11-04 00:00:00 2002-10-29 16:51:06 2002-11-05 16:47:31 2002-11-04 00:00:00 2002-10-29 16:51:06 2002-11-05 16:47:31
drop table t1,t2,t3; drop table t1,t2,t3;
CREATE TABLE t1 (datetime datetime, timestamp timestamp, date date, time time);
INSERT INTO t1 values ("2001-01-02 03:04:05", "2002-01-02 03:04:05", "2003-01-02", "06:07:08");
SELECT * from t1;
datetime timestamp date time
2001-01-02 03:04:05 2002-01-02 03:04:05 2003-01-02 06:07:08
select date_add("1997-12-31",INTERVAL 1 SECOND);
date_add("1997-12-31",INTERVAL 1 SECOND)
1997-12-31 00:00:01
select date_add("1997-12-31",INTERVAL "1 1" YEAR_MONTH);
date_add("1997-12-31",INTERVAL "1 1" YEAR_MONTH)
1999-01-31
select date_add(datetime, INTERVAL 1 SECOND) from t1;
date_add(datetime, INTERVAL 1 SECOND)
2001-01-02 03:04:06
select date_add(datetime, INTERVAL 1 YEAR) from t1;
date_add(datetime, INTERVAL 1 YEAR)
2002-01-02 03:04:05
select date_add(date,INTERVAL 1 SECOND) from t1;
date_add(date,INTERVAL 1 SECOND)
2003-01-02 00:00:01
select date_add(date,INTERVAL 1 MINUTE) from t1;
date_add(date,INTERVAL 1 MINUTE)
2003-01-02 00:01:00
select date_add(date,INTERVAL 1 HOUR) from t1;
date_add(date,INTERVAL 1 HOUR)
2003-01-02 01:00:00
select date_add(date,INTERVAL 1 DAY) from t1;
date_add(date,INTERVAL 1 DAY)
2003-01-03
select date_add(date,INTERVAL 1 MONTH) from t1;
date_add(date,INTERVAL 1 MONTH)
2003-02-02
select date_add(date,INTERVAL 1 YEAR) from t1;
date_add(date,INTERVAL 1 YEAR)
2004-01-02
select date_add(date,INTERVAL "1:1" MINUTE_SECOND) from t1;
date_add(date,INTERVAL "1:1" MINUTE_SECOND)
2003-01-02 00:01:01
select date_add(date,INTERVAL "1:1" HOUR_MINUTE) from t1;
date_add(date,INTERVAL "1:1" HOUR_MINUTE)
2003-01-02 01:01:00
select date_add(date,INTERVAL "1:1" DAY_HOUR) from t1;
date_add(date,INTERVAL "1:1" DAY_HOUR)
2003-01-03 01:00:00
select date_add(date,INTERVAL "1 1" YEAR_MONTH) from t1;
date_add(date,INTERVAL "1 1" YEAR_MONTH)
2004-02-02
select date_add(date,INTERVAL "1:1:1" HOUR_SECOND) from t1;
date_add(date,INTERVAL "1:1:1" HOUR_SECOND)
2003-01-02 01:01:01
select date_add(date,INTERVAL "1 1:1" DAY_MINUTE) from t1;
date_add(date,INTERVAL "1 1:1" DAY_MINUTE)
2003-01-03 01:01:00
select date_add(date,INTERVAL "1 1:1:1" DAY_SECOND) from t1;
date_add(date,INTERVAL "1 1:1:1" DAY_SECOND)
2003-01-03 01:01:01
select date_add(time,INTERVAL 1 SECOND) from t1;
date_add(time,INTERVAL 1 SECOND)
2006-07-08 00:00:01
drop table t1;

View File

@ -959,29 +959,29 @@ INSERT INTO t2 VALUES (650,'San Francisco',90,0,20020109113158,342,0000000000000
INSERT INTO t2 VALUES (333,'tubs',99,2,20020109113453,501,20020109113453,500,3,10,0); INSERT INTO t2 VALUES (333,'tubs',99,2,20020109113453,501,20020109113453,500,3,10,0);
select * from t1; select * from t1;
number cname carrier_id privacy last_mod_date last_mod_id last_app_date last_app_id version assigned_scps status number cname carrier_id privacy last_mod_date last_mod_id last_app_date last_app_id version assigned_scps status
4077711111 SeanWheeler 90 2 20020111112846 500 00000000000000 -1 2 3 1 4077711111 SeanWheeler 90 2 2002-01-11 11:28:46 500 0000-00-00 00:00:00 -1 2 3 1
9197722223 berry 90 3 20020111112809 500 20020102114532 501 4 10 0 9197722223 berry 90 3 2002-01-11 11:28:09 500 2002-01-02 11:45:32 501 4 10 0
650 San Francisco 0 0 20011227111336 342 00000000000000 -1 1 24 1 650 San Francisco 0 0 2001-12-27 11:13:36 342 0000-00-00 00:00:00 -1 1 24 1
302467 Sue's Subshop 90 3 20020109113241 500 20020102115111 501 7 24 0 302467 Sue's Subshop 90 3 2002-01-09 11:32:41 500 2002-01-02 11:51:11 501 7 24 0
6014911113 SudzCarwash 520 1 20020102115234 500 20020102115259 501 33 32768 0 6014911113 SudzCarwash 520 1 2002-01-02 11:52:34 500 2002-01-02 11:52:59 501 33 32768 0
333 tubs 99 2 20020109113440 501 20020109113440 500 3 10 0 333 tubs 99 2 2002-01-09 11:34:40 501 2002-01-09 11:34:40 500 3 10 0
select * from t2; select * from t2;
number cname carrier_id privacy last_mod_date last_mod_id last_app_date last_app_id version assigned_scps status number cname carrier_id privacy last_mod_date last_mod_id last_app_date last_app_id version assigned_scps status
4077711111 SeanWheeler 0 2 20020111112853 500 00000000000000 -1 2 3 1 4077711111 SeanWheeler 0 2 2002-01-11 11:28:53 500 0000-00-00 00:00:00 -1 2 3 1
9197722223 berry 90 3 20020111112818 500 20020102114532 501 4 10 0 9197722223 berry 90 3 2002-01-11 11:28:18 500 2002-01-02 11:45:32 501 4 10 0
650 San Francisco 90 0 20020109113158 342 00000000000000 -1 1 24 1 650 San Francisco 90 0 2002-01-09 11:31:58 342 0000-00-00 00:00:00 -1 1 24 1
333 tubs 99 2 20020109113453 501 20020109113453 500 3 10 0 333 tubs 99 2 2002-01-09 11:34:53 501 2002-01-09 11:34:53 500 3 10 0
delete t1, t2 from t1 left join t2 on t1.number=t2.number where (t1.carrier_id=90 and t1.number=t2.number) or (t2.carrier_id=90 and t1.number=t2.number) or (t1.carrier_id=90 and t2.number is null); delete t1, t2 from t1 left join t2 on t1.number=t2.number where (t1.carrier_id=90 and t1.number=t2.number) or (t2.carrier_id=90 and t1.number=t2.number) or (t1.carrier_id=90 and t2.number is null);
select * from t1; select * from t1;
number cname carrier_id privacy last_mod_date last_mod_id last_app_date last_app_id version assigned_scps status number cname carrier_id privacy last_mod_date last_mod_id last_app_date last_app_id version assigned_scps status
6014911113 SudzCarwash 520 1 20020102115234 500 20020102115259 501 33 32768 0 6014911113 SudzCarwash 520 1 2002-01-02 11:52:34 500 2002-01-02 11:52:59 501 33 32768 0
333 tubs 99 2 20020109113440 501 20020109113440 500 3 10 0 333 tubs 99 2 2002-01-09 11:34:40 501 2002-01-09 11:34:40 500 3 10 0
select * from t2; select * from t2;
number cname carrier_id privacy last_mod_date last_mod_id last_app_date last_app_id version assigned_scps status number cname carrier_id privacy last_mod_date last_mod_id last_app_date last_app_id version assigned_scps status
333 tubs 99 2 20020109113453 501 20020109113453 500 3 10 0 333 tubs 99 2 2002-01-09 11:34:53 501 2002-01-09 11:34:53 500 3 10 0
select * from t2; select * from t2;
number cname carrier_id privacy last_mod_date last_mod_id last_app_date last_app_id version assigned_scps status number cname carrier_id privacy last_mod_date last_mod_id last_app_date last_app_id version assigned_scps status
333 tubs 99 2 20020109113453 501 20020109113453 500 3 10 0 333 tubs 99 2 2002-01-09 11:34:53 501 2002-01-09 11:34:53 500 3 10 0
drop table t1,t2; drop table t1,t2;
create table t1 (id int unsigned not null auto_increment, code tinyint unsigned not null, name char(20) not null, primary key (id), key (code), unique (name)) type=innodb; create table t1 (id int unsigned not null auto_increment, code tinyint unsigned not null, name char(20) not null, primary key (id), key (code), unique (name)) type=innodb;
BEGIN; BEGIN;

View File

@ -91,7 +91,7 @@ grp a c id a c d
NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
explain select t1.*,t2.* from t1,t2 where t1.a=t2.a and isnull(t2.a)=1; explain select t1.*,t2.* from t1,t2 where t1.a=t2.a and isnull(t2.a)=1;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE Impossible WHERE noticed after reading const tables 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
explain select t1.*,t2.* from t1 left join t2 on t1.a=t2.a where isnull(t2.a)=1; explain select t1.*,t2.* from t1 left join t2 on t1.a=t2.a where isnull(t2.a)=1;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 7 1 SIMPLE t1 ALL NULL NULL NULL NULL 7

View File

@ -16,5 +16,5 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 const PRIMARY PRIMARY 3 const 1 1 SIMPLE t1 const PRIMARY PRIMARY 3 const 1
describe select * from t1 where t1="ABCD"; describe select * from t1 where t1="ABCD";
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE Impossible WHERE noticed after reading const tables 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
drop table t1; drop table t1;

View File

@ -3,7 +3,7 @@ create table t1 (time time, date date, timestamp timestamp);
insert into t1 values ("12:22:22","97:02:03","1997-01-02"); insert into t1 values ("12:22:22","97:02:03","1997-01-02");
select * from t1; select * from t1;
time date timestamp time date timestamp
12:22:22 1997-02-03 19970102000000 12:22:22 1997-02-03 1997-01-02 00:00:00
select t1.time+0,t1.date+0,t1.timestamp+0,concat(date," ",time) from t1; select t1.time+0,t1.date+0,t1.timestamp+0,concat(date," ",time) from t1;
t1.time+0 t1.date+0 t1.timestamp+0 concat(date," ",time) t1.time+0 t1.date+0 t1.timestamp+0 concat(date," ",time)
122222 19970203 19970102000000 1997-02-03 12:22:22 122222 19970203 19970102000000 1997-02-03 12:22:22

View File

@ -560,7 +560,7 @@ select * from t6;
a a
1 1
2 2
drop table if exists t1, t2, t3, t4, t5, t6; drop table if exists t6, t3, t1, t2, t4, t5;
DROP TABLE IF EXISTS t1, t2; DROP TABLE IF EXISTS t1, t2;
CREATE TABLE t1 ( CREATE TABLE t1 (
fileset_id tinyint(3) unsigned NOT NULL default '0', fileset_id tinyint(3) unsigned NOT NULL default '0',
@ -595,4 +595,4 @@ EXPLAIN SELECT * FROM t2 WHERE fileset_id = 2
AND file_code = '0000000115' LIMIT 1; AND file_code = '0000000115' LIMIT 1;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 const PRIMARY,files PRIMARY 33 const,const 1 1 SIMPLE t2 const PRIMARY,files PRIMARY 33 const,const 1
DROP TABLE IF EXISTS t1, t2; DROP TABLE IF EXISTS t2, t1;

View File

@ -12,5 +12,5 @@ select * from t1 where a is null;
a b a b
explain select * from t1 where b is null; explain select * from t1 where b is null;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE Impossible WHERE noticed after reading const tables 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
drop table t1; drop table t1;

View File

@ -16,7 +16,7 @@ event_date type event_id
1999-07-14 100600 10 1999-07-14 100600 10
explain select event_date,type,event_id from t1 WHERE type = 100601 and event_date >= "1999-07-01" AND event_date < "1999-07-15" AND (type=100600 OR type=100100) ORDER BY event_date; explain select event_date,type,event_id from t1 WHERE type = 100601 and event_date >= "1999-07-01" AND event_date < "1999-07-15" AND (type=100600 OR type=100100) ORDER BY event_date;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE Impossible WHERE 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
select event_date,type,event_id from t1 WHERE event_date >= "1999-07-01" AND event_date <= "1999-07-15" AND (type=100600 OR type=100100) or event_date >= "1999-07-01" AND event_date <= "1999-07-15" AND type=100099; select event_date,type,event_id from t1 WHERE event_date >= "1999-07-01" AND event_date <= "1999-07-15" AND (type=100600 OR type=100100) or event_date >= "1999-07-01" AND event_date <= "1999-07-15" AND type=100099;
event_date type event_id event_date type event_id
1999-07-10 100100 24 1999-07-10 100100 24

View File

@ -3097,7 +3097,7 @@ fld1 sum(price)
038008 234298 038008 234298
explain select fld3 from t2 where 1>2 or 2>3; explain select fld3 from t2 where 1>2 or 2>3;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE Impossible WHERE 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
explain select fld3 from t2 where fld1=fld1; explain select fld3 from t2 where fld1=fld1;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 ALL NULL NULL NULL NULL 1199 1 SIMPLE t2 ALL NULL NULL NULL NULL 1199
@ -3152,7 +3152,7 @@ count(*)
4181 4181
explain select min(fld1),max(fld1),count(*) from t2; explain select min(fld1),max(fld1),count(*) from t2;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE Select tables optimized away 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
select min(fld1),max(fld1),count(*) from t2; select min(fld1),max(fld1),count(*) from t2;
min(fld1) max(fld1) count(*) min(fld1) max(fld1) count(*)
0 1232609 1199 0 1232609 1199

View File

@ -20,8 +20,8 @@ Reference 'a' not supported (forward reference in item list)
EXPLAIN SELECT 1 FROM (SELECT 1 as a) as b HAVING (SELECT a)=1; EXPLAIN SELECT 1 FROM (SELECT 1 as a) as b HAVING (SELECT a)=1;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> system NULL NULL NULL NULL 1 1 PRIMARY <derived2> system NULL NULL NULL NULL 1
3 DEPENDENT SUBSELECT No tables used 3 DEPENDENT SUBSELECT NULL NULL NULL NULL NULL NULL NULL No tables used
2 DERIVED No tables used 2 DERIVED NULL NULL NULL NULL NULL NULL NULL No tables used
SELECT 1 FROM (SELECT 1 as a) as b HAVING (SELECT a)=1; SELECT 1 FROM (SELECT 1 as a) as b HAVING (SELECT a)=1;
1 1
1 1
@ -280,7 +280,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index NULL PRIMARY 41 NULL 2 Using where; Using index 1 SIMPLE t1 index NULL PRIMARY 41 NULL 2 Using where; Using index
EXPLAIN SELECT (SELECT DISTINCT date FROM t1 WHERE date='2002-08-03'); EXPLAIN SELECT (SELECT DISTINCT date FROM t1 WHERE date='2002-08-03');
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY No tables used 1 PRIMARY NULL NULL NULL NULL NULL NULL NULL No tables used
2 SUBSELECT t1 index NULL PRIMARY 41 NULL 2 Using where; Using index 2 SUBSELECT t1 index NULL PRIMARY 41 NULL 2 Using where; Using index
SELECT DISTINCT date FROM t1 WHERE date='2002-08-03'; SELECT DISTINCT date FROM t1 WHERE date='2002-08-03';
date date
@ -298,8 +298,8 @@ Subselect returns more than 1 record
EXPLAIN SELECT 1 FROM t1 WHERE 1=(SELECT 1 UNION SELECT 1); EXPLAIN SELECT 1 FROM t1 WHERE 1=(SELECT 1 UNION SELECT 1);
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 index NULL topic 3 NULL 2 Using index 1 PRIMARY t1 index NULL topic 3 NULL 2 Using index
2 SUBSELECT No tables used 2 SUBSELECT NULL NULL NULL NULL NULL NULL NULL No tables used
3 UNION No tables used 3 UNION NULL NULL NULL NULL NULL NULL NULL No tables used
drop table t1; drop table t1;
CREATE TABLE `t1` ( CREATE TABLE `t1` (
`numeropost` mediumint(8) unsigned NOT NULL auto_increment, `numeropost` mediumint(8) unsigned NOT NULL auto_increment,
@ -394,11 +394,11 @@ EXPLAIN SELECT numreponse FROM t1 WHERE numeropost='1' AND numreponse=(SELECT 1
Subselect returns more than 1 record Subselect returns more than 1 record
EXPLAIN SELECT MAX(numreponse) FROM t1 WHERE numeropost='1'; EXPLAIN SELECT MAX(numreponse) FROM t1 WHERE numeropost='1';
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE Select tables optimized away 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
EXPLAIN SELECT numreponse FROM t1 WHERE numeropost='1' AND numreponse=(SELECT MAX(numreponse) FROM t1 WHERE numeropost='1'); EXPLAIN SELECT numreponse FROM t1 WHERE numeropost='1' AND numreponse=(SELECT MAX(numreponse) FROM t1 WHERE numeropost='1');
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 const PRIMARY,numreponse PRIMARY 7 const,const 1 1 PRIMARY t1 const PRIMARY,numreponse PRIMARY 7 const,const 1
2 SUBSELECT Select tables optimized away 2 SUBSELECT NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
drop table t1; drop table t1;
CREATE TABLE t1 (a int(1)); CREATE TABLE t1 (a int(1));
INSERT INTO t1 VALUES (1); INSERT INTO t1 VALUES (1);
@ -574,14 +574,14 @@ id
EXPLAIN SELECT * FROM t WHERE id IN (SELECT 1+(select 1)); EXPLAIN SELECT * FROM t WHERE id IN (SELECT 1+(select 1));
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t ref id id 5 const 1 Using where; Using index 1 PRIMARY t ref id id 5 const 1 Using where; Using index
3 SUBSELECT No tables used 3 SUBSELECT NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings: Warnings:
Note 1247 Select 2 was reduced during optimisation Note 1247 Select 2 was reduced during optimisation
EXPLAIN SELECT * FROM t WHERE id IN (SELECT 1 UNION SELECT 3); EXPLAIN SELECT * FROM t WHERE id IN (SELECT 1 UNION SELECT 3);
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t index NULL id 5 NULL 2 Using where; Using index 1 PRIMARY t index NULL id 5 NULL 2 Using where; Using index
2 DEPENDENT SUBSELECT No tables used 2 DEPENDENT SUBSELECT NULL NULL NULL NULL NULL NULL NULL No tables used
3 UNION No tables used 3 UNION NULL NULL NULL NULL NULL NULL NULL No tables used
SELECT * FROM t WHERE id IN (SELECT 5 UNION SELECT 3); SELECT * FROM t WHERE id IN (SELECT 5 UNION SELECT 3);
id id
SELECT * FROM t WHERE id IN (SELECT 5 UNION SELECT 2); SELECT * FROM t WHERE id IN (SELECT 5 UNION SELECT 2);

View File

@ -41,8 +41,8 @@ t
drop table t1; drop table t1;
CREATE TABLE t1 (a timestamp, b date, c time, d datetime); CREATE TABLE t1 (a timestamp, b date, c time, d datetime);
insert into t1 (b,c,d) values(now(),curtime(),now()); insert into t1 (b,c,d) values(now(),curtime(),now());
select date_format(a,"%Y-%m-%d")=b,right(a,6)=c+0,a=d+0 from t1; select date_format(a,"%Y-%m-%d")=b,right(a+0,6)=c+0,a=d+0 from t1;
date_format(a,"%Y-%m-%d")=b right(a,6)=c+0 a=d+0 date_format(a,"%Y-%m-%d")=b right(a+0,6)=c+0 a=d+0
1 1 1 1 1 1
drop table t1; drop table t1;
CREATE TABLE t1 (a datetime not null); CREATE TABLE t1 (a datetime not null);

View File

@ -53,7 +53,7 @@ ushort smallint(5) unsigned zerofill MUL 00000 select,insert,update,references
umedium mediumint(8) unsigned MUL 0 select,insert,update,references umedium mediumint(8) unsigned MUL 0 select,insert,update,references
ulong int(11) unsigned MUL 0 select,insert,update,references ulong int(11) unsigned MUL 0 select,insert,update,references
ulonglong bigint(13) unsigned MUL 0 select,insert,update,references ulonglong bigint(13) unsigned MUL 0 select,insert,update,references
time_stamp timestamp(14) YES NULL select,insert,update,references time_stamp timestamp YES NULL select,insert,update,references
date_field date YES NULL select,insert,update,references date_field date YES NULL select,insert,update,references
time_field time YES NULL select,insert,update,references time_field time YES NULL select,insert,update,references
date_time datetime YES NULL select,insert,update,references date_time datetime YES NULL select,insert,update,references
@ -183,7 +183,7 @@ ushort smallint(5) unsigned zerofill 00000 select,insert,update,references
umedium mediumint(8) unsigned MUL 0 select,insert,update,references umedium mediumint(8) unsigned MUL 0 select,insert,update,references
ulong int(11) unsigned MUL 0 select,insert,update,references ulong int(11) unsigned MUL 0 select,insert,update,references
ulonglong bigint(13) unsigned MUL 0 select,insert,update,references ulonglong bigint(13) unsigned MUL 0 select,insert,update,references
time_stamp timestamp(14) YES NULL select,insert,update,references time_stamp timestamp YES NULL select,insert,update,references
date_field varchar(10) character set latin1 YES NULL select,insert,update,references date_field varchar(10) character set latin1 YES NULL select,insert,update,references
time_field time YES NULL select,insert,update,references time_field time YES NULL select,insert,update,references
date_time datetime YES NULL select,insert,update,references date_time datetime YES NULL select,insert,update,references
@ -209,7 +209,7 @@ ushort smallint(5) unsigned zerofill 00000 select,insert,update,references
umedium mediumint(8) unsigned 0 select,insert,update,references umedium mediumint(8) unsigned 0 select,insert,update,references
ulong int(11) unsigned 0 select,insert,update,references ulong int(11) unsigned 0 select,insert,update,references
ulonglong bigint(13) unsigned 0 select,insert,update,references ulonglong bigint(13) unsigned 0 select,insert,update,references
time_stamp timestamp(14) YES NULL select,insert,update,references time_stamp timestamp YES NULL select,insert,update,references
date_field varchar(10) character set latin1 YES NULL select,insert,update,references date_field varchar(10) character set latin1 YES NULL select,insert,update,references
time_field time YES NULL select,insert,update,references time_field time YES NULL select,insert,update,references
date_time datetime YES NULL select,insert,update,references date_time datetime YES NULL select,insert,update,references

View File

@ -15,26 +15,26 @@ SET TIMESTAMP=1238;
insert into t1 (a) select a+1 from t2 where a=8; insert into t1 (a) select a+1 from t2 where a=8;
select * from t1; select * from t1;
a t a t
1 19700101032034 1 1970-01-01 03:20:34
2 20020303000000 2 2002-03-03 00:00:00
3 19700101032035 3 1970-01-01 03:20:35
4 19700101032036 4 1970-01-01 03:20:36
5 20020304000000 5 2002-03-04 00:00:00
6 19700101032037 6 1970-01-01 03:20:37
7 20020305000000 7 2002-03-05 00:00:00
8 00000000000000 8 0000-00-00 00:00:00
9 19700101032038 9 1970-01-01 03:20:38
drop table t1,t2; drop table t1,t2;
SET TIMESTAMP=1234; SET TIMESTAMP=1234;
CREATE TABLE t1 (value TEXT NOT NULL, id VARCHAR(32) NOT NULL, stamp timestamp, PRIMARY KEY (id)); CREATE TABLE t1 (value TEXT NOT NULL, id VARCHAR(32) NOT NULL, stamp timestamp, PRIMARY KEY (id));
INSERT INTO t1 VALUES ("my value", "myKey","1999-04-02 00:00:00"); INSERT INTO t1 VALUES ("my value", "myKey","1999-04-02 00:00:00");
SELECT stamp FROM t1 WHERE id="myKey"; SELECT stamp FROM t1 WHERE id="myKey";
stamp stamp
19990402000000 1999-04-02 00:00:00
UPDATE t1 SET value="my value" WHERE id="myKey"; UPDATE t1 SET value="my value" WHERE id="myKey";
SELECT stamp FROM t1 WHERE id="myKey"; SELECT stamp FROM t1 WHERE id="myKey";
stamp stamp
19990402000000 1999-04-02 00:00:00
drop table t1; drop table t1;
create table t1 (a timestamp); create table t1 (a timestamp);
insert into t1 values (now()); insert into t1 values (now());
@ -44,8 +44,8 @@ date_format(a,"%Y %y") year(a) year(now())
drop table t1; drop table t1;
create table t1 (ix timestamp); create table t1 (ix timestamp);
insert into t1 values (19991101000000),(19990102030405),(19990630232922),(19990601000000),(19990930232922),(19990531232922),(19990501000000),(19991101000000),(19990501000000); insert into t1 values (19991101000000),(19990102030405),(19990630232922),(19990601000000),(19990930232922),(19990531232922),(19990501000000),(19991101000000),(19990501000000);
select * from t1; select ix+0 from t1;
ix ix+0
19991101000000 19991101000000
19990102030405 19990102030405
19990630232922 19990630232922
@ -71,16 +71,16 @@ INSERT INTO t1 VALUES ("2005-01-01","2005-01-01 00:00:00",20050101000000);
INSERT INTO t1 VALUES ("2030-01-01","2030-01-01 00:00:00",20300101000000); INSERT INTO t1 VALUES ("2030-01-01","2030-01-01 00:00:00",20300101000000);
SELECT * FROM t1; SELECT * FROM t1;
date date_time time_stamp date date_time time_stamp
1998-12-31 1998-12-31 23:59:59 19981231235959 1998-12-31 1998-12-31 23:59:59 1998-12-31 23:59:59
1999-01-01 1999-01-01 00:00:00 19990101000000 1999-01-01 1999-01-01 00:00:00 1999-01-01 00:00:00
1999-09-09 1999-09-09 23:59:59 19990909235959 1999-09-09 1999-09-09 23:59:59 1999-09-09 23:59:59
2000-01-01 2000-01-01 00:00:00 20000101000000 2000-01-01 2000-01-01 00:00:00 2000-01-01 00:00:00
2000-02-28 2000-02-28 00:00:00 20000228000000 2000-02-28 2000-02-28 00:00:00 2000-02-28 00:00:00
2000-02-29 2000-02-29 00:00:00 20000229000000 2000-02-29 2000-02-29 00:00:00 2000-02-29 00:00:00
2000-03-01 2000-03-01 00:00:00 20000301000000 2000-03-01 2000-03-01 00:00:00 2000-03-01 00:00:00
2000-12-31 2000-12-31 23:59:59 20001231235959 2000-12-31 2000-12-31 23:59:59 2000-12-31 23:59:59
2001-01-01 2001-01-01 00:00:00 20010101000000 2001-01-01 2001-01-01 00:00:00 2001-01-01 00:00:00
2004-12-31 2004-12-31 23:59:59 20041231235959 2004-12-31 2004-12-31 23:59:59 2004-12-31 23:59:59
2005-01-01 2005-01-01 00:00:00 20050101000000 2005-01-01 2005-01-01 00:00:00 2005-01-01 00:00:00
2030-01-01 2030-01-01 00:00:00 20300101000000 2030-01-01 2030-01-01 00:00:00 2030-01-01 00:00:00
drop table t1; drop table t1;

View File

@ -102,16 +102,16 @@ Unknown column 'xx' in 'field list'
explain select a,b from t1 union select 1; explain select a,b from t1 union select 1;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 4 1 PRIMARY t1 ALL NULL NULL NULL NULL 4
2 UNION No tables used 2 UNION NULL NULL NULL NULL NULL NULL NULL No tables used
explain select 1 union select a,b from t1 union select 1; explain select 1 union select a,b from t1 union select 1;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY No tables used 1 PRIMARY NULL NULL NULL NULL NULL NULL NULL No tables used
2 UNION t1 ALL NULL NULL NULL NULL 4 2 UNION t1 ALL NULL NULL NULL NULL 4
3 UNION No tables used 3 UNION NULL NULL NULL NULL NULL NULL NULL No tables used
explain select a,b from t1 union select 1 limit 0; explain select a,b from t1 union select 1 limit 0;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY Impossible WHERE 1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
2 UNION Impossible WHERE 2 UNION NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
select a,b from t1 into outfile 'skr' union select a,b from t2; select a,b from t1 into outfile 'skr' union select a,b from t2;
Wrong usage of UNION and INTO Wrong usage of UNION and INTO
select a,b from t1 order by a union select a,b from t2; select a,b from t1 order by a union select a,b from t2;

View File

@ -115,9 +115,9 @@ CREATE TABLE t1 (
) TYPE=MyISAM; ) TYPE=MyISAM;
INSERT INTO t1 VALUES (1,'Link',1,1,1,'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa','2001-02-28 08:40:16',20010228084016,0,4); INSERT INTO t1 VALUES (1,'Link',1,1,1,'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa','2001-02-28 08:40:16',20010228084016,0,4);
SELECT CONCAT('"',CONCAT_WS('";"',title,prio,category,program,bugdesc,created,modified,bugstatus,submitter), '"') FROM t1; SELECT CONCAT('"',CONCAT_WS('";"',title,prio,category,program,bugdesc,created,modified+0,bugstatus,submitter), '"') FROM t1;
SELECT CONCAT('"',CONCAT_WS('";"',title,prio,category,program,bugstatus,submitter), '"') FROM t1; SELECT CONCAT('"',CONCAT_WS('";"',title,prio,category,program,bugstatus,submitter), '"') FROM t1;
SELECT CONCAT_WS('";"',title,prio,category,program,bugdesc,created,modified,bugstatus,submitter) FROM t1; SELECT CONCAT_WS('";"',title,prio,category,program,bugdesc,created,modified+0,bugstatus,submitter) FROM t1;
drop table t1; drop table t1;
# #

View File

@ -183,3 +183,34 @@ select * from t1, t2 where t1.start between t2.ctime1 and t2.ctime2;
select * from t1, t2 where t1.start >= t2.ctime1 and t1.start <= t2.ctime2; select * from t1, t2 where t1.start >= t2.ctime1 and t1.start <= t2.ctime2;
select * from t1, t3 where t1.start between t3.ctime1 and t3.ctime2; select * from t1, t3 where t1.start between t3.ctime1 and t3.ctime2;
drop table t1,t2,t3; drop table t1,t2,t3;
#
# Test types from + INTERVAL
#
CREATE TABLE t1 (datetime datetime, timestamp timestamp, date date, time time);
INSERT INTO t1 values ("2001-01-02 03:04:05", "2002-01-02 03:04:05", "2003-01-02", "06:07:08");
SELECT * from t1;
select date_add("1997-12-31",INTERVAL 1 SECOND);
select date_add("1997-12-31",INTERVAL "1 1" YEAR_MONTH);
select date_add(datetime, INTERVAL 1 SECOND) from t1;
select date_add(datetime, INTERVAL 1 YEAR) from t1;
select date_add(date,INTERVAL 1 SECOND) from t1;
select date_add(date,INTERVAL 1 MINUTE) from t1;
select date_add(date,INTERVAL 1 HOUR) from t1;
select date_add(date,INTERVAL 1 DAY) from t1;
select date_add(date,INTERVAL 1 MONTH) from t1;
select date_add(date,INTERVAL 1 YEAR) from t1;
select date_add(date,INTERVAL "1:1" MINUTE_SECOND) from t1;
select date_add(date,INTERVAL "1:1" HOUR_MINUTE) from t1;
select date_add(date,INTERVAL "1:1" DAY_HOUR) from t1;
select date_add(date,INTERVAL "1 1" YEAR_MONTH) from t1;
select date_add(date,INTERVAL "1:1:1" HOUR_SECOND) from t1;
select date_add(date,INTERVAL "1 1:1" DAY_MINUTE) from t1;
select date_add(date,INTERVAL "1 1:1:1" DAY_SECOND) from t1;
# The following is not as one would expect...
select date_add(time,INTERVAL 1 SECOND) from t1;
drop table t1;

View File

@ -202,7 +202,7 @@ insert into t4 values (1);
insert into t5 values (2); insert into t5 values (2);
create temporary table t6 (a int not null) TYPE=MERGE UNION=(t4,t5); create temporary table t6 (a int not null) TYPE=MERGE UNION=(t4,t5);
select * from t6; select * from t6;
drop table if exists t1, t2, t3, t4, t5, t6; drop table if exists t6, t3, t1, t2, t4, t5;
# #
# testing merge::records_in_range and optimizer # testing merge::records_in_range and optimizer
@ -235,5 +235,5 @@ EXPLAIN SELECT * FROM t1 WHERE fileset_id = 2
AND file_code BETWEEN '0000000115' AND '0000000120' LIMIT 1; AND file_code BETWEEN '0000000115' AND '0000000120' LIMIT 1;
EXPLAIN SELECT * FROM t2 WHERE fileset_id = 2 EXPLAIN SELECT * FROM t2 WHERE fileset_id = 2
AND file_code = '0000000115' LIMIT 1; AND file_code = '0000000115' LIMIT 1;
DROP TABLE IF EXISTS t1, t2; DROP TABLE IF EXISTS t2, t1;

View File

@ -19,7 +19,7 @@ drop table t1;
CREATE TABLE t1 (a timestamp, b date, c time, d datetime); CREATE TABLE t1 (a timestamp, b date, c time, d datetime);
insert into t1 (b,c,d) values(now(),curtime(),now()); insert into t1 (b,c,d) values(now(),curtime(),now());
select date_format(a,"%Y-%m-%d")=b,right(a,6)=c+0,a=d+0 from t1; select date_format(a,"%Y-%m-%d")=b,right(a+0,6)=c+0,a=d+0 from t1;
drop table t1; drop table t1;
# #

View File

@ -35,7 +35,7 @@ drop table t1;
create table t1 (ix timestamp); create table t1 (ix timestamp);
insert into t1 values (19991101000000),(19990102030405),(19990630232922),(19990601000000),(19990930232922),(19990531232922),(19990501000000),(19991101000000),(19990501000000); insert into t1 values (19991101000000),(19990102030405),(19990630232922),(19990601000000),(19990930232922),(19990531232922),(19990501000000),(19991101000000),(19990501000000);
select * from t1; select ix+0 from t1;
drop table t1; drop table t1;
CREATE TABLE t1 (date date, date_time datetime, time_stamp timestamp); CREATE TABLE t1 (date date, date_time datetime, time_stamp timestamp);

View File

@ -64,7 +64,7 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc \
thr_malloc.cc item_create.cc item_subselect.cc \ thr_malloc.cc item_create.cc item_subselect.cc \
item_row.cc \ item_row.cc \
field.cc key.cc sql_class.cc sql_list.cc \ field.cc key.cc sql_class.cc sql_list.cc \
net_serv.cc net_pkg.cc lock.cc my_lock.c \ net_serv.cc protocol.cc lock.cc my_lock.c \
sql_string.cc sql_manager.cc sql_map.cc \ sql_string.cc sql_manager.cc sql_map.cc \
mysqld.cc password.c hash_filo.cc hostname.cc \ mysqld.cc password.c hash_filo.cc hostname.cc \
convert.cc set_var.cc sql_parse.cc sql_yacc.yy \ convert.cc set_var.cc sql_parse.cc sql_yacc.yy \

View File

@ -196,17 +196,12 @@ void Field::copy_from_tmp(int row_offset)
} }
bool Field::send(THD *thd, String *packet) bool Field::send_binary(Protocol *protocol)
{ {
if (is_null())
return net_store_null(packet);
char buff[MAX_FIELD_WIDTH]; char buff[MAX_FIELD_WIDTH];
String tmp(buff,sizeof(buff),default_charset_info); String tmp(buff,sizeof(buff),default_charset_info);
val_str(&tmp,&tmp); val_str(&tmp,&tmp);
CONVERT *convert; return protocol->store(tmp.ptr(), tmp.length());
if ((convert=thd->variables.convert_set))
return convert->store(packet,tmp.ptr(),tmp.length());
return net_store_data(packet,tmp.ptr(),tmp.length());
} }
@ -1074,6 +1069,10 @@ String *Field_tiny::val_str(String *val_buffer,
return val_buffer; return val_buffer;
} }
bool Field_tiny::send_binary(Protocol *protocol)
{
return protocol->store_tiny((longlong) (int8) ptr[0]);
}
int Field_tiny::cmp(const char *a_ptr, const char *b_ptr) int Field_tiny::cmp(const char *a_ptr, const char *b_ptr)
{ {
@ -1285,6 +1284,7 @@ longlong Field_short::val_int(void)
return unsigned_flag ? (longlong) (unsigned short) j : (longlong) j; return unsigned_flag ? (longlong) (unsigned short) j : (longlong) j;
} }
String *Field_short::val_str(String *val_buffer, String *Field_short::val_str(String *val_buffer,
String *val_ptr __attribute__((unused))) String *val_ptr __attribute__((unused)))
{ {
@ -1312,6 +1312,12 @@ String *Field_short::val_str(String *val_buffer,
} }
bool Field_short::send_binary(Protocol *protocol)
{
return protocol->store_short(Field_short::val_int());
}
int Field_short::cmp(const char *a_ptr, const char *b_ptr) int Field_short::cmp(const char *a_ptr, const char *b_ptr)
{ {
short a,b; short a,b;
@ -1538,6 +1544,12 @@ String *Field_medium::val_str(String *val_buffer,
} }
bool Field_medium::send_binary(Protocol *protocol)
{
return protocol->store_long(Field_medium::val_int());
}
int Field_medium::cmp(const char *a_ptr, const char *b_ptr) int Field_medium::cmp(const char *a_ptr, const char *b_ptr)
{ {
long a,b; long a,b;
@ -1774,6 +1786,11 @@ String *Field_long::val_str(String *val_buffer,
} }
bool Field_long::send_binary(Protocol *protocol)
{
return protocol->store_long(Field_long::val_int());
}
int Field_long::cmp(const char *a_ptr, const char *b_ptr) int Field_long::cmp(const char *a_ptr, const char *b_ptr)
{ {
int32 a,b; int32 a,b;
@ -1988,6 +2005,12 @@ String *Field_longlong::val_str(String *val_buffer,
} }
bool Field_longlong::send_binary(Protocol *protocol)
{
return protocol->store_longlong(Field_longlong::val_int(), unsigned_flag);
}
int Field_longlong::cmp(const char *a_ptr, const char *b_ptr) int Field_longlong::cmp(const char *a_ptr, const char *b_ptr)
{ {
longlong a,b; longlong a,b;
@ -2302,6 +2325,12 @@ void Field_float::sort_string(char *to,uint length __attribute__((unused)))
} }
bool Field_float::send_binary(Protocol *protocol)
{
return protocol->store((float) Field_float::val_real(), dec, (String*) 0);
}
void Field_float::sql_type(String &res) const void Field_float::sql_type(String &res) const
{ {
if (dec == NOT_FIXED_DEC) if (dec == NOT_FIXED_DEC)
@ -2499,6 +2528,11 @@ String *Field_double::val_str(String *val_buffer,
return val_buffer; return val_buffer;
} }
bool Field_double::send_binary(Protocol *protocol)
{
return protocol->store((float) Field_double::val_real(), dec, (String*) 0);
}
int Field_double::cmp(const char *a_ptr, const char *b_ptr) int Field_double::cmp(const char *a_ptr, const char *b_ptr)
{ {
@ -2568,10 +2602,10 @@ void Field_double::sql_type(String &res) const
Field_timestamp::Field_timestamp(char *ptr_arg, uint32 len_arg, Field_timestamp::Field_timestamp(char *ptr_arg, uint32 len_arg,
enum utype unireg_check_arg, enum utype unireg_check_arg,
const char *field_name_arg, const char *field_name_arg,
struct st_table *table_arg) struct st_table *table_arg,
:Field_num(ptr_arg, len_arg, (uchar*) 0,0, CHARSET_INFO *cs)
unireg_check_arg, field_name_arg, table_arg, :Field_str(ptr_arg, 19, (uchar*) 0,0,
0, 1, 1) unireg_check_arg, field_name_arg, table_arg, cs)
{ {
if (table && !table->timestamp_field) if (table && !table->timestamp_field)
{ {
@ -2596,35 +2630,6 @@ int Field_timestamp::store(const char *from,uint len,CHARSET_INFO *cs)
return 0; return 0;
} }
void Field_timestamp::fill_and_store(char *from,uint len)
{
uint res_length;
if (len <= field_length)
res_length=field_length;
else if (len <= 12)
res_length=12; /* purecov: inspected */
else if (len <= 14)
res_length=14; /* purecov: inspected */
else
res_length=(len+1)/2*2; // must be even
if (res_length != len)
{
bmove_upp(from+res_length,from+len,len);
bfill(from,res_length-len,'0');
len=res_length;
}
long tmp=(long) str_to_timestamp(from,len);
#ifdef WORDS_BIGENDIAN
if (table->db_low_byte_first)
{
int4store(ptr,tmp);
}
else
#endif
longstore(ptr,tmp);
}
int Field_timestamp::store(double nr) int Field_timestamp::store(double nr)
{ {
int error= 0; int error= 0;
@ -2735,44 +2740,34 @@ longlong Field_timestamp::val_int(void)
time_arg=(time_t) temp; time_arg=(time_t) temp;
localtime_r(&time_arg,&tm_tmp); localtime_r(&time_arg,&tm_tmp);
l_time=&tm_tmp; l_time=&tm_tmp;
res=(longlong) 0;
for (pos=len=0; len+1 < (uint) field_length ; len+=2,pos++) part_time= l_time->tm_year % 100;
{ res= ((longlong) (part_time+ ((part_time < YY_PART_YEAR) ? 2000 : 1900))*
bool year_flag=0; LL(10000000000));
switch (dayord.pos[pos]) { part_time= l_time->tm_mon+1;
case 0: part_time=l_time->tm_year % 100; year_flag=1 ; break; res+= (longlong) part_time * LL(100000000);
case 1: part_time=l_time->tm_mon+1; break; part_time=l_time->tm_mday;
case 2: part_time=l_time->tm_mday; break; res+= (longlong) ((long) part_time * 1000000L);
case 3: part_time=l_time->tm_hour; break; part_time=l_time->tm_hour;
case 4: part_time=l_time->tm_min; break; res+= (longlong) (part_time * 10000L);
case 5: part_time=l_time->tm_sec; break; part_time=l_time->tm_min;
default: part_time=0; break; /* purecov: deadcode */ res+= (longlong) (part_time * 100);
} part_time=l_time->tm_sec;
if (year_flag && (field_length == 8 || field_length == 14)) return res+part_time;
{
res=res*(longlong) 10000+(part_time+
((part_time < YY_PART_YEAR) ? 2000 : 1900));
len+=2;
}
else
res=res*(longlong) 100+part_time;
}
return (longlong) res;
} }
String *Field_timestamp::val_str(String *val_buffer, String *Field_timestamp::val_str(String *val_buffer,
String *val_ptr __attribute__((unused))) String *val_ptr __attribute__((unused)))
{ {
uint pos; uint32 temp, temp2;
int part_time;
uint32 temp;
time_t time_arg; time_t time_arg;
struct tm *l_time; struct tm *l_time;
struct tm tm_tmp; struct tm tm_tmp;
val_buffer->alloc(field_length+1); val_buffer->alloc(field_length+1);
char *to=(char*) val_buffer->ptr(),*end=to+field_length; char *to=(char*) val_buffer->ptr(),*end=to+field_length;
val_buffer->length(field_length);
#ifdef WORDS_BIGENDIAN #ifdef WORDS_BIGENDIAN
if (table->db_low_byte_first) if (table->db_low_byte_first)
@ -2783,44 +2778,57 @@ String *Field_timestamp::val_str(String *val_buffer,
if (temp == 0L) if (temp == 0L)
{ /* Zero time is "000000" */ { /* Zero time is "000000" */
VOID(strfill(to,field_length,'0')); strmov(to, "0000-00-00 00:00:00");
val_buffer->length(field_length);
return val_buffer; return val_buffer;
} }
time_arg=(time_t) temp; time_arg=(time_t) temp;
localtime_r(&time_arg,&tm_tmp); localtime_r(&time_arg,&tm_tmp);
l_time=&tm_tmp; l_time=&tm_tmp;
for (pos=0; to < end ; pos++)
temp= l_time->tm_year % 100;
if (temp < YY_PART_YEAR)
{ {
bool year_flag=0; *to++= '2';
switch (dayord.pos[pos]) { *to++= '0';
case 0: part_time=l_time->tm_year % 100; year_flag=1; break;
case 1: part_time=l_time->tm_mon+1; break;
case 2: part_time=l_time->tm_mday; break;
case 3: part_time=l_time->tm_hour; break;
case 4: part_time=l_time->tm_min; break;
case 5: part_time=l_time->tm_sec; break;
default: part_time=0; break; /* purecov: deadcode */
}
if (year_flag && (field_length == 8 || field_length == 14))
{
if (part_time < YY_PART_YEAR)
{
*to++='2'; *to++='0'; /* purecov: inspected */
} }
else else
{ {
*to++='1'; *to++='9'; *to++= '1';
*to++= '9';
} }
} temp2=temp/10; temp=temp-temp2*10;
*to++=(char) ('0'+((uint) part_time/10)); *to++= (char) ('0'+(char) (temp2));
*to++=(char) ('0'+((uint) part_time % 10)); *to++= (char) ('0'+(char) (temp));
} *to++= '-';
*to=0; // Safeguard temp=l_time->tm_mon+1;
val_buffer->length((uint) (to-val_buffer->ptr())); temp2=temp/10; temp=temp-temp2*10;
*to++= (char) ('0'+(char) (temp2));
*to++= (char) ('0'+(char) (temp));
*to++= '-';
temp=l_time->tm_mday;
temp2=temp/10; temp=temp-temp2*10;
*to++= (char) ('0'+(char) (temp2));
*to++= (char) ('0'+(char) (temp));
*to++= ' ';
temp=l_time->tm_hour;
temp2=temp/10; temp=temp-temp2*10;
*to++= (char) ('0'+(char) (temp2));
*to++= (char) ('0'+(char) (temp));
*to++= ':';
temp=l_time->tm_min;
temp2=temp/10; temp=temp-temp2*10;
*to++= (char) ('0'+(char) (temp2));
*to++= (char) ('0'+(char) (temp));
*to++= ':';
temp=l_time->tm_sec;
temp2=temp/10; temp=temp-temp2*10;
*to++= (char) ('0'+(char) (temp2));
*to++= (char) ('0'+(char) (temp));
*to= 0;
return val_buffer; return val_buffer;
} }
bool Field_timestamp::get_date(TIME *ltime, bool fuzzydate) bool Field_timestamp::get_date(TIME *ltime, bool fuzzydate)
{ {
long temp; long temp;
@ -2860,6 +2868,15 @@ bool Field_timestamp::get_time(TIME *ltime)
return Field_timestamp::get_date(ltime,0); return Field_timestamp::get_date(ltime,0);
} }
bool Field_timestamp::send_binary(Protocol *protocol)
{
TIME tm;
Field_timestamp::get_date(&tm, 1);
return protocol->store(&tm);
}
int Field_timestamp::cmp(const char *a_ptr, const char *b_ptr) int Field_timestamp::cmp(const char *a_ptr, const char *b_ptr)
{ {
int32 a,b; int32 a,b;
@ -2878,6 +2895,7 @@ int Field_timestamp::cmp(const char *a_ptr, const char *b_ptr)
return ((uint32) a < (uint32) b) ? -1 : ((uint32) a > (uint32) b) ? 1 : 0; return ((uint32) a < (uint32) b) ? -1 : ((uint32) a > (uint32) b) ? 1 : 0;
} }
void Field_timestamp::sort_string(char *to,uint length __attribute__((unused))) void Field_timestamp::sort_string(char *to,uint length __attribute__((unused)))
{ {
#ifdef WORDS_BIGENDIAN #ifdef WORDS_BIGENDIAN
@ -2901,10 +2919,7 @@ void Field_timestamp::sort_string(char *to,uint length __attribute__((unused)))
void Field_timestamp::sql_type(String &res) const void Field_timestamp::sql_type(String &res) const
{ {
ulong length= my_sprintf((char*) res.ptr(), res.set("timestamp", 9, default_charset_info);
((char*) res.ptr(),"timestamp(%d)",
(int) field_length));
res.length(length);
} }
@ -3068,6 +3083,17 @@ bool Field_time::get_time(TIME *ltime)
return 0; return 0;
} }
bool Field_time::send_binary(Protocol *protocol)
{
TIME tm;
Field_time::get_time(&tm);
tm.day= tm.hour/3600; // Move hours to days
tm.hour-= tm.day*3600;
return protocol->store(&tm);
}
int Field_time::cmp(const char *a_ptr, const char *b_ptr) int Field_time::cmp(const char *a_ptr, const char *b_ptr)
{ {
int32 a,b; int32 a,b;
@ -3965,17 +3991,13 @@ int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs)
ThNormalize((uchar *) ptr+2, field_length, (uchar *) from, length); ThNormalize((uchar *) ptr+2, field_length, (uchar *) from, length);
} }
#else #else
if (length <= field_length) if (length > field_length)
{
memcpy(ptr+2,from,length);
}
else
{ {
length=field_length; length=field_length;
memcpy(ptr+2,from,field_length);
current_thd->cuted_fields++; current_thd->cuted_fields++;
error= 1; error= 1;
} }
memcpy(ptr+2,from,length);
#endif /* USE_TIS620 */ #endif /* USE_TIS620 */
int2store(ptr, length); int2store(ptr, length);
return error; return error;
@ -4176,6 +4198,28 @@ uint Field_varstring::max_packed_col_length(uint max_length)
return (max_length > 255 ? 2 : 1)+max_length; return (max_length > 255 ? 2 : 1)+max_length;
} }
void Field_varstring::get_key_image(char *buff, uint length, imagetype type)
{
length-= HA_KEY_BLOB_LENGTH;
uint f_length=uint2korr(ptr);
if (f_length > length)
f_length= length;
int2store(buff,length);
memcpy(buff+2,ptr+2,length);
#ifdef HAVE_purify
if (f_length < length)
bzero(buff+2+f_length, (length-f_length));
#endif
}
void Field_varstring::set_key_image(char *buff,uint length)
{
length=uint2korr(buff); // Real length is here
(void) Field_varstring::store(buff+2, length, default_charset_info);
}
/**************************************************************************** /****************************************************************************
** blob type ** blob type
** A blob is saved as a length and a pointer. The length is stored in the ** A blob is saved as a length and a pointer. The length is stored in the
@ -4443,7 +4487,6 @@ void Field_blob::get_key_image(char *buff,uint length, imagetype type)
return; return;
} }
length-=HA_KEY_BLOB_LENGTH;
if ((uint32) length > blob_length) if ((uint32) length > blob_length)
{ {
#ifdef HAVE_purify #ifdef HAVE_purify
@ -5258,7 +5301,7 @@ Field *make_field(char *ptr, uint32 field_length,
f_is_dec(pack_flag) == 0); f_is_dec(pack_flag) == 0);
case FIELD_TYPE_TIMESTAMP: case FIELD_TYPE_TIMESTAMP:
return new Field_timestamp(ptr,field_length, return new Field_timestamp(ptr,field_length,
unireg_check, field_name, table); unireg_check, field_name, table, field_charset);
case FIELD_TYPE_YEAR: case FIELD_TYPE_YEAR:
return new Field_year(ptr,field_length,null_pos,null_bit, return new Field_year(ptr,field_length,null_pos,null_bit,
unireg_check, field_name, table); unireg_check, field_name, table);

View File

@ -27,10 +27,12 @@
#define NOT_FIXED_DEC 31 #define NOT_FIXED_DEC 31
class Send_field; class Send_field;
class Protocol;
struct st_cache_field; struct st_cache_field;
void field_conv(Field *to,Field *from); void field_conv(Field *to,Field *from);
class Field { class Field
{
Field(const Item &); /* Prevent use of these */ Field(const Item &); /* Prevent use of these */
void operator=(Field &); void operator=(Field &);
public: public:
@ -164,7 +166,7 @@ public:
ptr-=row_offset; ptr-=row_offset;
return tmp; return tmp;
} }
bool send(THD *thd, String *packet); bool send_binary(Protocol *protocol);
virtual char *pack(char* to, const char *from, uint max_length=~(uint) 0) virtual char *pack(char* to, const char *from, uint max_length=~(uint) 0)
{ {
uint32 length=pack_length(); uint32 length=pack_length();
@ -329,6 +331,7 @@ public:
double val_real(void); double val_real(void);
longlong val_int(void); longlong val_int(void);
String *val_str(String*,String *); String *val_str(String*,String *);
bool send_binary(Protocol *protocol);
int cmp(const char *,const char*); int cmp(const char *,const char*);
void sort_string(char *buff,uint length); void sort_string(char *buff,uint length);
uint32 pack_length() const { return 1; } uint32 pack_length() const { return 1; }
@ -358,6 +361,7 @@ public:
double val_real(void); double val_real(void);
longlong val_int(void); longlong val_int(void);
String *val_str(String*,String *); String *val_str(String*,String *);
bool send_binary(Protocol *protocol);
int cmp(const char *,const char*); int cmp(const char *,const char*);
void sort_string(char *buff,uint length); void sort_string(char *buff,uint length);
uint32 pack_length() const { return 2; } uint32 pack_length() const { return 2; }
@ -387,6 +391,7 @@ public:
double val_real(void); double val_real(void);
longlong val_int(void); longlong val_int(void);
String *val_str(String*,String *); String *val_str(String*,String *);
bool send_binary(Protocol *protocol);
int cmp(const char *,const char*); int cmp(const char *,const char*);
void sort_string(char *buff,uint length); void sort_string(char *buff,uint length);
uint32 pack_length() const { return 3; } uint32 pack_length() const { return 3; }
@ -420,6 +425,7 @@ public:
void reset(void) { ptr[0]=ptr[1]=ptr[2]=ptr[3]=0; } void reset(void) { ptr[0]=ptr[1]=ptr[2]=ptr[3]=0; }
double val_real(void); double val_real(void);
longlong val_int(void); longlong val_int(void);
bool send_binary(Protocol *protocol);
String *val_str(String*,String *); String *val_str(String*,String *);
int cmp(const char *,const char*); int cmp(const char *,const char*);
void sort_string(char *buff,uint length); void sort_string(char *buff,uint length);
@ -457,6 +463,7 @@ public:
double val_real(void); double val_real(void);
longlong val_int(void); longlong val_int(void);
String *val_str(String*,String *); String *val_str(String*,String *);
bool send_binary(Protocol *protocol);
int cmp(const char *,const char*); int cmp(const char *,const char*);
void sort_string(char *buff,uint length); void sort_string(char *buff,uint length);
uint32 pack_length() const { return 8; } uint32 pack_length() const { return 8; }
@ -485,6 +492,7 @@ public:
double val_real(void); double val_real(void);
longlong val_int(void); longlong val_int(void);
String *val_str(String*,String *); String *val_str(String*,String *);
bool send_binary(Protocol *protocol);
int cmp(const char *,const char*); int cmp(const char *,const char*);
void sort_string(char *buff,uint length); void sort_string(char *buff,uint length);
uint32 pack_length() const { return sizeof(float); } uint32 pack_length() const { return sizeof(float); }
@ -517,6 +525,7 @@ public:
double val_real(void); double val_real(void);
longlong val_int(void); longlong val_int(void);
String *val_str(String*,String *); String *val_str(String*,String *);
bool send_binary(Protocol *protocol);
int cmp(const char *,const char*); int cmp(const char *,const char*);
void sort_string(char *buff,uint length); void sort_string(char *buff,uint length);
uint32 pack_length() const { return sizeof(double); } uint32 pack_length() const { return sizeof(double); }
@ -552,14 +561,15 @@ public:
}; };
class Field_timestamp :public Field_num { class Field_timestamp :public Field_str {
public: public:
Field_timestamp(char *ptr_arg, uint32 len_arg, Field_timestamp(char *ptr_arg, uint32 len_arg,
enum utype unireg_check_arg, const char *field_name_arg, enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg); struct st_table *table_arg,
enum Item_result result_type () const { return field_length == 8 || field_length == 14 ? INT_RESULT : STRING_RESULT; } CHARSET_INFO *cs);
enum_field_types type() const { return FIELD_TYPE_TIMESTAMP;} enum_field_types type() const { return FIELD_TYPE_TIMESTAMP;}
enum ha_base_keytype key_type() const { return HA_KEYTYPE_ULONG_INT; } enum ha_base_keytype key_type() const { return HA_KEYTYPE_ULONG_INT; }
enum Item_result cmp_type () const { return INT_RESULT; }
int store(const char *to,uint length,CHARSET_INFO *charset); int store(const char *to,uint length,CHARSET_INFO *charset);
int store(double nr); int store(double nr);
int store(longlong nr); int store(longlong nr);
@ -567,6 +577,7 @@ public:
double val_real(void); double val_real(void);
longlong val_int(void); longlong val_int(void);
String *val_str(String*,String *); String *val_str(String*,String *);
bool send_binary(Protocol *protocol);
int cmp(const char *,const char*); int cmp(const char *,const char*);
void sort_string(char *buff,uint length); void sort_string(char *buff,uint length);
uint32 pack_length() const { return 4; } uint32 pack_length() const { return 4; }
@ -588,7 +599,6 @@ public:
longget(tmp,ptr); longget(tmp,ptr);
return tmp; return tmp;
} }
void fill_and_store(char *from,uint len);
bool get_date(TIME *ltime,bool fuzzydate); bool get_date(TIME *ltime,bool fuzzydate);
bool get_time(TIME *ltime); bool get_time(TIME *ltime);
}; };
@ -610,6 +620,7 @@ public:
double val_real(void); double val_real(void);
longlong val_int(void); longlong val_int(void);
String *val_str(String*,String *); String *val_str(String*,String *);
bool send_binary(Protocol *protocol);
void sql_type(String &str) const; void sql_type(String &str) const;
}; };
@ -636,6 +647,7 @@ public:
double val_real(void); double val_real(void);
longlong val_int(void); longlong val_int(void);
String *val_str(String*,String *); String *val_str(String*,String *);
bool send_binary(Protocol *protocol);
int cmp(const char *,const char*); int cmp(const char *,const char*);
void sort_string(char *buff,uint length); void sort_string(char *buff,uint length);
uint32 pack_length() const { return 4; } uint32 pack_length() const { return 4; }
@ -664,6 +676,7 @@ public:
double val_real(void); double val_real(void);
longlong val_int(void); longlong val_int(void);
String *val_str(String*,String *); String *val_str(String*,String *);
bool send_binary(Protocol *protocol);
int cmp(const char *,const char*); int cmp(const char *,const char*);
void sort_string(char *buff,uint length); void sort_string(char *buff,uint length);
uint32 pack_length() const { return 3; } uint32 pack_length() const { return 3; }
@ -697,6 +710,7 @@ public:
double val_real(void); double val_real(void);
longlong val_int(void); longlong val_int(void);
String *val_str(String*,String *); String *val_str(String*,String *);
bool send_binary(Protocol *protocol);
bool get_time(TIME *ltime); bool get_time(TIME *ltime);
int cmp(const char *,const char*); int cmp(const char *,const char*);
void sort_string(char *buff,uint length); void sort_string(char *buff,uint length);
@ -732,6 +746,7 @@ public:
double val_real(void); double val_real(void);
longlong val_int(void); longlong val_int(void);
String *val_str(String*,String *); String *val_str(String*,String *);
bool send_binary(Protocol *protocol);
int cmp(const char *,const char*); int cmp(const char *,const char*);
void sort_string(char *buff,uint length); void sort_string(char *buff,uint length);
uint32 pack_length() const { return 8; } uint32 pack_length() const { return 8; }
@ -772,6 +787,7 @@ public:
double val_real(void); double val_real(void);
longlong val_int(void); longlong val_int(void);
String *val_str(String*,String *); String *val_str(String*,String *);
bool send_binary(Protocol *protocol);
int cmp(const char *,const char*); int cmp(const char *,const char*);
void sort_string(char *buff,uint length); void sort_string(char *buff,uint length);
void sql_type(String &str) const; void sql_type(String &str) const;
@ -812,8 +828,11 @@ public:
double val_real(void); double val_real(void);
longlong val_int(void); longlong val_int(void);
String *val_str(String*,String *); String *val_str(String*,String *);
bool send_binary(Protocol *protocol);
int cmp(const char *,const char*); int cmp(const char *,const char*);
void sort_string(char *buff,uint length); void sort_string(char *buff,uint length);
void get_key_image(char *buff,uint length, imagetype type);
void set_key_image(char *buff,uint length);
void sql_type(String &str) const; void sql_type(String &str) const;
char *pack(char *to, const char *from, uint max_length=~(uint) 0); char *pack(char *to, const char *from, uint max_length=~(uint) 0);
const char *unpack(char* to, const char *from); const char *unpack(char* to, const char *from);
@ -852,6 +871,7 @@ public:
double val_real(void); double val_real(void);
longlong val_int(void); longlong val_int(void);
String *val_str(String*,String *); String *val_str(String*,String *);
bool send_binary(Protocol *protocol);
int cmp(const char *,const char*); int cmp(const char *,const char*);
int cmp(const char *a, uint32 a_length, const char *b, uint32 b_length); int cmp(const char *a, uint32 a_length, const char *b, uint32 b_length);
int cmp_offset(uint offset); int cmp_offset(uint offset);
@ -957,6 +977,7 @@ public:
double val_real(void); double val_real(void);
longlong val_int(void); longlong val_int(void);
String *val_str(String*,String *); String *val_str(String*,String *);
bool send_binary(Protocol *protocol);
int cmp(const char *,const char*); int cmp(const char *,const char*);
void sort_string(char *buff,uint length); void sort_string(char *buff,uint length);
uint32 pack_length() const { return (uint32) packlength; } uint32 pack_length() const { return (uint32) packlength; }

View File

@ -231,10 +231,9 @@ int berkeley_rollback(THD *thd, void *trans)
} }
int berkeley_show_logs(THD *thd) int berkeley_show_logs(Protocol *protocol)
{ {
char **all_logs, **free_logs, **a, **f; char **all_logs, **free_logs, **a, **f;
String *packet= &thd->packet;
int error=1; int error=1;
MEM_ROOT show_logs_root; MEM_ROOT show_logs_root;
MEM_ROOT *old_root=my_pthread_getspecific_ptr(MEM_ROOT*,THR_MALLOC); MEM_ROOT *old_root=my_pthread_getspecific_ptr(MEM_ROOT*,THR_MALLOC);
@ -243,8 +242,9 @@ int berkeley_show_logs(THD *thd)
init_alloc_root(&show_logs_root, 1024, 1024); init_alloc_root(&show_logs_root, 1024, 1024);
my_pthread_setspecific_ptr(THR_MALLOC,&show_logs_root); my_pthread_setspecific_ptr(THR_MALLOC,&show_logs_root);
if ((error= db_env->log_archive(db_env, &all_logs, DB_ARCH_ABS | DB_ARCH_LOG)) if ((error= db_env->log_archive(db_env, &all_logs,
|| (error= db_env->log_archive(db_env, &free_logs, DB_ARCH_ABS))) DB_ARCH_ABS | DB_ARCH_LOG)) ||
(error= db_env->log_archive(db_env, &free_logs, DB_ARCH_ABS)))
{ {
DBUG_PRINT("error", ("log_archive failed (error %d)", error)); DBUG_PRINT("error", ("log_archive failed (error %d)", error));
db_env->err(db_env, error, "log_archive: DB_ARCH_ABS"); db_env->err(db_env, error, "log_archive: DB_ARCH_ABS");
@ -257,18 +257,18 @@ int berkeley_show_logs(THD *thd)
{ {
for (a = all_logs, f = free_logs; *a; ++a) for (a = all_logs, f = free_logs; *a; ++a)
{ {
packet->length(0); protocol->prepare_for_resend();
net_store_data(packet,*a); protocol->store(*a);
net_store_data(packet,"BDB"); protocol->store("BDB", 3);
if (f && *f && strcmp(*a, *f) == 0) if (f && *f && strcmp(*a, *f) == 0)
{ {
++f; f++;
net_store_data(packet, SHOW_LOG_STATUS_FREE); protocol->store(SHOW_LOG_STATUS_FREE);
} }
else else
net_store_data(packet, SHOW_LOG_STATUS_INUSE); protocol->store(SHOW_LOG_STATUS_INUSE);
if (my_net_write(&thd->net,(char*) packet->ptr(),packet->length())) if (protocol->write())
{ {
error=1; error=1;
goto err; goto err;
@ -2065,8 +2065,7 @@ void ha_berkeley::print_error(int error, myf errflag)
static void print_msg(THD *thd, const char *table_name, const char *op_name, static void print_msg(THD *thd, const char *table_name, const char *op_name,
const char *msg_type, const char *fmt, ...) const char *msg_type, const char *fmt, ...)
{ {
String* packet = &thd->packet; Protocol *protocol= thd->protocol;
packet->length(0);
char msgbuf[256]; char msgbuf[256];
msgbuf[0] = 0; msgbuf[0] = 0;
va_list args; va_list args;
@ -2074,15 +2073,14 @@ static void print_msg(THD *thd, const char *table_name, const char *op_name,
my_vsnprintf(msgbuf, sizeof(msgbuf), fmt, args); my_vsnprintf(msgbuf, sizeof(msgbuf), fmt, args);
msgbuf[sizeof(msgbuf) - 1] = 0; // healthy paranoia msgbuf[sizeof(msgbuf) - 1] = 0; // healthy paranoia
DBUG_PRINT(msg_type,("message: %s",msgbuf)); DBUG_PRINT(msg_type,("message: %s",msgbuf));
net_store_data(packet, table_name); protocol->prepare_for_resend();
net_store_data(packet, op_name); protocol->store(table_name);
net_store_data(packet, msg_type); protocol->store(op_name);
net_store_data(packet, msgbuf); protocol->store(msg_type);
if (my_net_write(&thd->net, (char*)thd->packet.ptr(), protocol->store(msgbuf);
thd->packet.length())) if (protocol->write())
thd->killed=1; thd->killed=1;
} }
#endif #endif

View File

@ -180,4 +180,4 @@ bool berkeley_end(void);
bool berkeley_flush_logs(void); bool berkeley_flush_logs(void);
int berkeley_commit(THD *thd, void *trans); int berkeley_commit(THD *thd, void *trans);
int berkeley_rollback(THD *thd, void *trans); int berkeley_rollback(THD *thd, void *trans);
int berkeley_show_logs(THD *thd); int berkeley_show_logs(Protocol *protocol);

View File

@ -3922,9 +3922,8 @@ innodb_show_status(
/*===============*/ /*===============*/
THD* thd) /* in: the MySQL query thread of the caller */ THD* thd) /* in: the MySQL query thread of the caller */
{ {
String* packet = &thd->packet;
char* buf; char* buf;
Protocol *protocol= thd->protocol;
DBUG_ENTER("innodb_show_status"); DBUG_ENTER("innodb_show_status");
if (innodb_skip) { if (innodb_skip) {
@ -3945,22 +3944,17 @@ innodb_show_status(
field_list.push_back(new Item_empty_string("Status", strlen(buf))); field_list.push_back(new Item_empty_string("Status", strlen(buf)));
if(send_fields(thd, field_list, 1)) { if (protocol->send_fields(&field_list, 1))
{
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
packet->length(0); protocol->prepare_for_resend();
protocol->store(buf, strlen(buf));
net_store_data(packet, buf);
if (my_net_write(&thd->net, (char*)thd->packet.ptr(),
packet->length())) {
ut_free(buf); ut_free(buf);
if (protocol->write())
DBUG_RETURN(-1); DBUG_RETURN(-1);
}
ut_free(buf);
send_eof(thd); send_eof(thd);

View File

@ -50,14 +50,12 @@ static void mi_check_print_msg(MI_CHECK *param, const char* msg_type,
const char *fmt, va_list args) const char *fmt, va_list args)
{ {
THD* thd = (THD*)param->thd; THD* thd = (THD*)param->thd;
String* packet = &thd->packet; Protocol *protocol= thd->protocol;
uint length; uint length, msg_length;
char msgbuf[MI_MAX_MSG_BUF]; char msgbuf[MI_MAX_MSG_BUF];
char name[NAME_LEN*2+2]; char name[NAME_LEN*2+2];
packet->length(0);
msgbuf[0] = 0; // healthy paranoia ? msg_length= my_vsnprintf(msgbuf, sizeof(msgbuf), fmt, args);
my_vsnprintf(msgbuf, sizeof(msgbuf), fmt, args);
msgbuf[sizeof(msgbuf) - 1] = 0; // healthy paranoia msgbuf[sizeof(msgbuf) - 1] = 0; // healthy paranoia
DBUG_PRINT(msg_type,("message: %s",msgbuf)); DBUG_PRINT(msg_type,("message: %s",msgbuf));
@ -67,19 +65,20 @@ static void mi_check_print_msg(MI_CHECK *param, const char* msg_type,
sql_print_error(msgbuf); sql_print_error(msgbuf);
return; return;
} }
if (param->testflag & (T_CREATE_MISSING_KEYS | T_SAFE_REPAIR | T_AUTO_REPAIR)) if (param->testflag & (T_CREATE_MISSING_KEYS | T_SAFE_REPAIR |
T_AUTO_REPAIR))
{ {
my_message(ER_NOT_KEYFILE,msgbuf,MYF(MY_WME)); my_message(ER_NOT_KEYFILE,msgbuf,MYF(MY_WME));
return; return;
} }
length=(uint) (strxmov(name, param->db_name,".",param->table_name,NullS) - length=(uint) (strxmov(name, param->db_name,".",param->table_name,NullS) -
name); name);
net_store_data(packet, name, length); protocol->prepare_for_resend();
net_store_data(packet, param->op_name); protocol->store(name, length);
net_store_data(packet, msg_type); protocol->store(param->op_name);
protocol->store(msg_type);
net_store_data(packet, msgbuf); protocol->store(msgbuf, msg_length);
if (my_net_write(&thd->net, (char*)thd->packet.ptr(), thd->packet.length())) if (protocol->write())
sql_print_error("Failed on my_net_write, writing to stderr instead: %s\n", sql_print_error("Failed on my_net_write, writing to stderr instead: %s\n",
msgbuf); msgbuf);
return; return;

View File

@ -22,6 +22,7 @@
#include "mysql_priv.h" #include "mysql_priv.h"
#include <m_ctype.h> #include <m_ctype.h>
#include "my_dir.h" #include "my_dir.h"
#include <assert.h>
/***************************************************************************** /*****************************************************************************
** Item functions ** Item functions
@ -378,12 +379,6 @@ int Item_param::save_in_field(Field *field, bool no_conversions)
} }
void Item_param::make_field(Send_field *tmp_field)
{
init_make_field(tmp_field,FIELD_TYPE_STRING);
}
double Item_param::val() double Item_param::val()
{ {
switch (item_result_type) { switch (item_result_type) {
@ -671,6 +666,18 @@ void Item::init_make_field(Send_field *tmp_field,
tmp_field->flags |= UNSIGNED_FLAG; tmp_field->flags |= UNSIGNED_FLAG;
} }
void Item::make_field(Send_field *tmp_field)
{
init_make_field(tmp_field, field_type());
}
enum_field_types Item::field_type() const
{
return ((result_type() == STRING_RESULT) ? FIELD_TYPE_VAR_STRING :
(result_type() == INT_RESULT) ? FIELD_TYPE_LONGLONG :
FIELD_TYPE_DOUBLE);
}
/* ARGSUSED */ /* ARGSUSED */
void Item_field::make_field(Send_field *tmp_field) void Item_field::make_field(Send_field *tmp_field)
{ {
@ -679,59 +686,6 @@ void Item_field::make_field(Send_field *tmp_field)
tmp_field->col_name=name; // Use user supplied name tmp_field->col_name=name; // Use user supplied name
} }
void Item_int::make_field(Send_field *tmp_field)
{
init_make_field(tmp_field,FIELD_TYPE_LONGLONG);
}
void Item_uint::make_field(Send_field *tmp_field)
{
init_make_field(tmp_field,FIELD_TYPE_LONGLONG);
tmp_field->flags|= UNSIGNED_FLAG;
unsigned_flag=1;
}
void Item_real::make_field(Send_field *tmp_field)
{
init_make_field(tmp_field,FIELD_TYPE_DOUBLE);
}
void Item_string::make_field(Send_field *tmp_field)
{
init_make_field(tmp_field,FIELD_TYPE_STRING);
}
void Item_datetime::make_field(Send_field *tmp_field)
{
init_make_field(tmp_field,FIELD_TYPE_DATETIME);
}
void Item_null::make_field(Send_field *tmp_field)
{
init_make_field(tmp_field,FIELD_TYPE_NULL);
tmp_field->length=4;
}
void Item_func::make_field(Send_field *tmp_field)
{
init_make_field(tmp_field, ((result_type() == STRING_RESULT) ?
FIELD_TYPE_VAR_STRING :
(result_type() == INT_RESULT) ?
FIELD_TYPE_LONGLONG : FIELD_TYPE_DOUBLE));
}
void Item_avg_field::make_field(Send_field *tmp_field)
{
init_make_field(tmp_field,FIELD_TYPE_DOUBLE);
}
void Item_variance_field::make_field(Send_field *tmp_field)
{
init_make_field(tmp_field,FIELD_TYPE_DOUBLE);
}
/* /*
** Set a field:s value from a item ** Set a field:s value from a item
*/ */
@ -938,30 +892,118 @@ int Item_varbinary::save_in_field(Field *field, bool no_conversions)
} }
void Item_varbinary::make_field(Send_field *tmp_field) /*
Pack data in buffer for sending
*/
bool Item_null::send(Protocol *protocol, String *packet)
{ {
init_make_field(tmp_field,FIELD_TYPE_STRING); return protocol->store_null();
} }
/* /*
** pack data in buffer for sending This is only called from items that is not of type item_field
*/ */
bool Item::send(THD *thd, String *packet) bool Item::send(Protocol *protocol, String *buffer)
{ {
char buff[MAX_FIELD_WIDTH]; bool result;
CONVERT *convert; enum_field_types type;
String s(buff,sizeof(buff),packet->charset()),*res; LINT_INIT(result);
if (!(res=val_str(&s)))
return net_store_null(packet); switch ((type=field_type())) {
if ((convert=thd->variables.convert_set)) default:
return convert->store(packet,res->ptr(),res->length()); case MYSQL_TYPE_NULL:
return net_store_data(packet,res->ptr(),res->length()); case MYSQL_TYPE_DECIMAL:
case MYSQL_TYPE_ENUM:
case MYSQL_TYPE_SET:
case MYSQL_TYPE_TINY_BLOB:
case MYSQL_TYPE_MEDIUM_BLOB:
case MYSQL_TYPE_LONG_BLOB:
case MYSQL_TYPE_BLOB:
case MYSQL_TYPE_GEOMETRY:
case MYSQL_TYPE_STRING:
case MYSQL_TYPE_VAR_STRING:
{
String *res;
if ((res=val_str(buffer)))
result= protocol->store(res->ptr(),res->length());
break;
}
case MYSQL_TYPE_TINY:
{
longlong nr;
nr= val_int();
if (!null_value)
result= protocol->store_tiny(nr);
break;
}
case MYSQL_TYPE_SHORT:
{
longlong nr;
nr= val_int();
if (!null_value)
result= protocol->store_short(nr);
break;
}
case MYSQL_TYPE_INT24:
case MYSQL_TYPE_LONG:
{
longlong nr;
nr= val_int();
if (!null_value)
result= protocol->store_long(nr);
break;
}
case MYSQL_TYPE_LONGLONG:
{
longlong nr;
nr= val_int();
if (!null_value)
result= protocol->store_longlong(nr, unsigned_flag);
break;
}
case MYSQL_TYPE_DOUBLE:
{
double nr;
nr= val();
if (!null_value)
result= protocol->store(nr, decimals, buffer);
break;
}
case MYSQL_TYPE_DATETIME:
case MYSQL_TYPE_DATE:
case MYSQL_TYPE_TIMESTAMP:
{
TIME tm;
get_date(&tm, 1);
if (!null_value)
{
if (type == MYSQL_TYPE_DATE)
return protocol->store_date(&tm);
else
result= protocol->store(&tm);
}
break;
}
case MYSQL_TYPE_TIME:
{
TIME tm;
get_time(&tm);
if (!null_value)
result= protocol->store_time(&tm);
break;
}
}
if (null_value)
result= protocol->store_null();
return result;
} }
bool Item_null::send(THD *thd, String *packet)
bool Item_field::send(Protocol *protocol, String *buffer)
{ {
return net_store_null(packet); return protocol->store(result_field);
} }
/* /*

View File

@ -19,6 +19,7 @@
#pragma interface /* gcc class implementation */ #pragma interface /* gcc class implementation */
#endif #endif
class Protocol;
struct st_table_list; struct st_table_list;
void item_init(void); /* Init item functions */ void item_init(void); /* Init item functions */
@ -54,20 +55,21 @@ public:
virtual ~Item() { name=0; } /*lint -e1509 */ virtual ~Item() { name=0; } /*lint -e1509 */
void set_name(const char *str,uint length=0); void set_name(const char *str,uint length=0);
void init_make_field(Send_field *tmp_field,enum enum_field_types type); void init_make_field(Send_field *tmp_field,enum enum_field_types type);
virtual void make_field(Send_field *field);
virtual bool fix_fields(THD *, struct st_table_list *, Item **); virtual bool fix_fields(THD *, struct st_table_list *, Item **);
virtual int save_in_field(Field *field, bool no_conversions); virtual int save_in_field(Field *field, bool no_conversions);
virtual void save_org_in_field(Field *field) virtual void save_org_in_field(Field *field)
{ (void) save_in_field(field, 1); } { (void) save_in_field(field, 1); }
virtual int save_safe_in_field(Field *field) virtual int save_safe_in_field(Field *field)
{ return save_in_field(field, 1); } { return save_in_field(field, 1); }
virtual bool send(THD *thd, String *str); virtual bool send(Protocol *protocol, String *str);
virtual bool eq(const Item *, bool binary_cmp) const; virtual bool eq(const Item *, bool binary_cmp) const;
virtual Item_result result_type () const { return REAL_RESULT; } virtual Item_result result_type () const { return REAL_RESULT; }
virtual enum_field_types field_type() const;
virtual enum Type type() const =0; virtual enum Type type() const =0;
virtual double val()=0; virtual double val()=0;
virtual longlong val_int()=0; virtual longlong val_int()=0;
virtual String *val_str(String*)=0; virtual String *val_str(String*)=0;
virtual void make_field(Send_field *field)=0;
virtual Field *tmp_table_field(TABLE *t_arg=(TABLE *)0) { return 0; } virtual Field *tmp_table_field(TABLE *t_arg=(TABLE *)0) { return 0; }
virtual const char *full_name() const { return name ? name : "???"; } virtual const char *full_name() const { return name ? name : "???"; }
virtual double val_result() { return val(); } virtual double val_result() { return val(); }
@ -119,10 +121,10 @@ public:
item (it assign '*ref' with field 'item' in derived classes) item (it assign '*ref' with field 'item' in derived classes)
*/ */
enum Type type() const { return item->type(); } enum Type type() const { return item->type(); }
enum_field_types field_type() const { return item->field_type(); }
double val() { return item->val(); } double val() { return item->val(); }
longlong val_int() { return item->val_int(); } longlong val_int() { return item->val_int(); }
String* val_str(String* s) { return item->val_str(s); } String* val_str(String* s) { return item->val_str(s); }
void make_field(Send_field* f) { item->make_field(f); }
bool check_cols(uint col) { return item->check_cols(col); } bool check_cols(uint col) { return item->check_cols(col); }
bool eq(const Item *item, bool binary_cmp) const bool eq(const Item *item, bool binary_cmp) const
{ return item->eq(item, binary_cmp); } { return item->eq(item, binary_cmp); }
@ -196,12 +198,9 @@ public:
double val_result(); double val_result();
longlong val_int_result(); longlong val_int_result();
String *str_result(String* tmp); String *str_result(String* tmp);
bool send(THD *thd, String *str_arg) bool send(Protocol *protocol, String *str_arg);
{
return result_field->send(thd,str_arg);
}
void make_field(Send_field *field);
bool fix_fields(THD *, struct st_table_list *, Item **); bool fix_fields(THD *, struct st_table_list *, Item **);
void make_field(Send_field *tmp_field);
int save_in_field(Field *field,bool no_conversions); int save_in_field(Field *field,bool no_conversions);
void save_org_in_field(Field *field); void save_org_in_field(Field *field);
table_map used_tables() const; table_map used_tables() const;
@ -209,6 +208,10 @@ public:
{ {
return field->result_type(); return field->result_type();
} }
enum_field_types field_type()
{
return field->type();
}
Field *tmp_table_field(TABLE *t_arg=(TABLE *)0) { return result_field; } Field *tmp_table_field(TABLE *t_arg=(TABLE *)0) { return result_field; }
bool get_date(TIME *ltime,bool fuzzydate); bool get_date(TIME *ltime,bool fuzzydate);
bool get_time(TIME *ltime); bool get_time(TIME *ltime);
@ -226,12 +229,17 @@ public:
double val(); double val();
longlong val_int(); longlong val_int();
String *val_str(String *str); String *val_str(String *str);
void make_field(Send_field *field);
int save_in_field(Field *field, bool no_conversions); int save_in_field(Field *field, bool no_conversions);
int save_safe_in_field(Field *field); int save_safe_in_field(Field *field);
enum Item_result result_type () const enum Item_result result_type () const { return STRING_RESULT; }
{ return STRING_RESULT; } enum_field_types field_type() const { return MYSQL_TYPE_NULL; }
bool send(THD *thd, String *str); bool fix_fields(THD *thd, struct st_table_list *list, Item **item)
{
bool res= Item::fix_fields(thd, list, item);
max_length=0;
return res;
}
bool send(Protocol *protocol, String *str);
bool basic_const_item() const { return 1; } bool basic_const_item() const { return 1; }
Item *new_item() { return new Item_null(name); } Item *new_item() { return new Item_null(name); }
bool is_null() { return 1; } bool is_null() { return 1; }
@ -258,7 +266,6 @@ public:
double val(); double val();
longlong val_int(); longlong val_int();
String *val_str(String*); String *val_str(String*);
void make_field(Send_field *field);
int save_in_field(Field *field, bool no_conversions); int save_in_field(Field *field, bool no_conversions);
void set_null(); void set_null();
void set_int(longlong i); void set_int(longlong i);
@ -272,6 +279,7 @@ public:
void (*setup_param_func)(Item_param *param, uchar **pos); void (*setup_param_func)(Item_param *param, uchar **pos);
enum Item_result result_type () const enum Item_result result_type () const
{ return item_result_type; } { return item_result_type; }
enum_field_types field_type() const { return MYSQL_TYPE_STRING; }
Item *new_item() { return new Item_param(name); } Item *new_item() { return new Item_param(name); }
}; };
@ -292,11 +300,11 @@ public:
(longlong) strtoull(str_arg,(char**) 0,10)) (longlong) strtoull(str_arg,(char**) 0,10))
{ max_length= (uint) strlen(str_arg); name=(char*) str_arg;} { max_length= (uint) strlen(str_arg); name=(char*) str_arg;}
enum Type type() const { return INT_ITEM; } enum Type type() const { return INT_ITEM; }
virtual enum Item_result result_type () const { return INT_RESULT; } enum Item_result result_type () const { return INT_RESULT; }
enum_field_types field_type() const { return MYSQL_TYPE_LONGLONG; }
longlong val_int() { return value; } longlong val_int() { return value; }
double val() { return (double) value; } double val() { return (double) value; }
String *val_str(String*); String *val_str(String*);
void make_field(Send_field *field);
int save_in_field(Field *field, bool no_conversions); int save_in_field(Field *field, bool no_conversions);
bool basic_const_item() const { return 1; } bool basic_const_item() const { return 1; }
Item *new_item() { return new Item_int(name,value,max_length); } Item *new_item() { return new Item_int(name,value,max_length); }
@ -312,8 +320,13 @@ public:
Item_uint(uint32 i) :Item_int((longlong) i, 10) {} Item_uint(uint32 i) :Item_int((longlong) i, 10) {}
double val() { return ulonglong2double(value); } double val() { return ulonglong2double(value); }
String *val_str(String*); String *val_str(String*);
void make_field(Send_field *field);
Item *new_item() { return new Item_uint(name,max_length); } Item *new_item() { return new Item_uint(name,max_length); }
bool fix_fields(THD *thd, struct st_table_list *list, Item **item)
{
bool res= Item::fix_fields(thd, list, item);
unsigned_flag= 1;
return res;
}
void print(String *str); void print(String *str);
}; };
@ -339,10 +352,10 @@ public:
Item_real(double value_par) :value(value_par) {} Item_real(double value_par) :value(value_par) {}
int save_in_field(Field *field, bool no_conversions); int save_in_field(Field *field, bool no_conversions);
enum Type type() const { return REAL_ITEM; } enum Type type() const { return REAL_ITEM; }
enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
double val() { return value; } double val() { return value; }
longlong val_int() { return (longlong) (value+(value > 0 ? 0.5 : -0.5));} longlong val_int() { return (longlong) (value+(value > 0 ? 0.5 : -0.5));}
String *val_str(String*); String *val_str(String*);
void make_field(Send_field *field);
bool basic_const_item() const { return 1; } bool basic_const_item() const { return 1; }
Item *new_item() { return new Item_real(name,value,decimals,max_length); } Item *new_item() { return new Item_real(name,value,decimals,max_length); }
}; };
@ -387,8 +400,8 @@ public:
} }
String *val_str(String*) { return (String*) &str_value; } String *val_str(String*) { return (String*) &str_value; }
int save_in_field(Field *field, bool no_conversions); int save_in_field(Field *field, bool no_conversions);
void make_field(Send_field *field);
enum Item_result result_type () const { return STRING_RESULT; } enum Item_result result_type () const { return STRING_RESULT; }
enum_field_types field_type() const { return MYSQL_TYPE_STRING; }
bool basic_const_item() const { return 1; } bool basic_const_item() const { return 1; }
bool eq(const Item *item, bool binary_cmp) const; bool eq(const Item *item, bool binary_cmp) const;
Item *new_item() Item *new_item()
@ -409,7 +422,6 @@ class Item_default :public Item
public: public:
Item_default() { name= (char*) "DEFAULT"; } Item_default() { name= (char*) "DEFAULT"; }
enum Type type() const { return DEFAULT_ITEM; } enum Type type() const { return DEFAULT_ITEM; }
void make_field(Send_field *field) {}
int save_in_field(Field *field, bool no_conversions) int save_in_field(Field *field, bool no_conversions)
{ {
field->set_default(); field->set_default();
@ -429,7 +441,7 @@ class Item_datetime :public Item_string
public: public:
Item_datetime(const char *item_name): Item_string(item_name,"",0,default_charset_info) Item_datetime(const char *item_name): Item_string(item_name,"",0,default_charset_info)
{ max_length=19;} { max_length=19;}
void make_field(Send_field *field); enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; }
}; };
class Item_empty_string :public Item_string class Item_empty_string :public Item_string
@ -439,6 +451,20 @@ public:
{ name=(char*) header; max_length=length;} { name=(char*) header; max_length=length;}
}; };
class Item_return_int :public Item_int
{
enum_field_types int_field_type;
public:
Item_return_int(const char *name, uint length,
enum_field_types field_type_arg)
:Item_int(name, 0, length), int_field_type(field_type_arg)
{
unsigned_flag=1;
}
enum_field_types field_type() const { return int_field_type; }
};
class Item_varbinary :public Item class Item_varbinary :public Item
{ {
public: public:
@ -449,8 +475,8 @@ public:
longlong val_int(); longlong val_int();
String *val_str(String*) { return &str_value; } String *val_str(String*) { return &str_value; }
int save_in_field(Field *field, bool no_conversions); int save_in_field(Field *field, bool no_conversions);
void make_field(Send_field *field);
enum Item_result result_type () const { return INT_RESULT; } enum Item_result result_type () const { return INT_RESULT; }
enum_field_types field_type() const { return MYSQL_TYPE_STRING; }
}; };
@ -505,13 +531,14 @@ public:
{ {
return (null_value=(*ref)->get_date(ltime,fuzzydate)); return (null_value=(*ref)->get_date(ltime,fuzzydate));
} }
bool send(THD *thd, String *tmp) { return (*ref)->send(thd, tmp); } bool send(Protocol *prot, String *tmp){ return (*ref)->send(prot, tmp); }
void make_field(Send_field *field) { (*ref)->make_field(field); } void make_field(Send_field *field) { (*ref)->make_field(field); }
bool fix_fields(THD *, struct st_table_list *, Item **); bool fix_fields(THD *, struct st_table_list *, Item **);
int save_in_field(Field *field, bool no_conversions) int save_in_field(Field *field, bool no_conversions)
{ return (*ref)->save_in_field(field, no_conversions); } { return (*ref)->save_in_field(field, no_conversions); }
void save_org_in_field(Field *field) { (*ref)->save_org_in_field(field); } void save_org_in_field(Field *field) { (*ref)->save_org_in_field(field); }
enum Item_result result_type () const { return (*ref)->result_type(); } enum Item_result result_type () const { return (*ref)->result_type(); }
enum_field_types field_type() const { return (*ref)->field_type(); }
table_map used_tables() const { return (*ref)->used_tables(); } table_map used_tables() const { return (*ref)->used_tables(); }
bool check_loop(uint id); bool check_loop(uint id);
}; };
@ -597,6 +624,7 @@ public:
class Item_copy_string :public Item class Item_copy_string :public Item
{ {
enum enum_field_types cached_field_type;
public: public:
Item *item; Item *item;
Item_copy_string(Item *i) :item(i) Item_copy_string(Item *i) :item(i)
@ -605,10 +633,12 @@ public:
decimals=item->decimals; decimals=item->decimals;
max_length=item->max_length; max_length=item->max_length;
name=item->name; name=item->name;
cached_field_type= item->field_type();
} }
~Item_copy_string() { delete item; } ~Item_copy_string() { delete item; }
enum Type type() const { return COPY_STR_ITEM; } enum Type type() const { return COPY_STR_ITEM; }
enum Item_result result_type () const { return STRING_RESULT; } enum Item_result result_type () const { return STRING_RESULT; }
enum_field_types field_type() const { return cached_field_type; }
double val() double val()
{ return null_value ? 0.0 : my_strntod(str_value.charset(),str_value.ptr(),str_value.length(),NULL); } { return null_value ? 0.0 : my_strntod(str_value.charset(),str_value.ptr(),str_value.length(),NULL); }
longlong val_int() longlong val_int()

View File

@ -1945,8 +1945,7 @@ static user_var_entry *get_variable(HASH *hash, LEX_STRING &name,
bool Item_func_set_user_var::fix_fields(THD *thd, TABLE_LIST *tables, bool Item_func_set_user_var::fix_fields(THD *thd, TABLE_LIST *tables,
Item **ref) Item **ref)
{ {
if (!thd) /* fix_fields will call Item_func_set_user_var::fix_length_and_dec */
thd=current_thd; // Should never happen
if (Item_func::fix_fields(thd, tables, ref) || if (Item_func::fix_fields(thd, tables, ref) ||
!(entry= get_variable(&thd->user_vars, name, 1))) !(entry= get_variable(&thd->user_vars, name, 1)))
return 1; return 1;

View File

@ -106,7 +106,6 @@ public:
Item_func(List<Item> &list); Item_func(List<Item> &list);
~Item_func() {} /* Nothing to do; Items are freed automaticly */ ~Item_func() {} /* Nothing to do; Items are freed automaticly */
bool fix_fields(THD *,struct st_table_list *, Item **ref); bool fix_fields(THD *,struct st_table_list *, Item **ref);
void make_field(Send_field *field);
table_map used_tables() const; table_map used_tables() const;
void update_used_tables(); void update_used_tables();
bool eq(const Item *item, bool binary_cmp) const; bool eq(const Item *item, bool binary_cmp) const;
@ -909,7 +908,9 @@ class Item_func_set_user_var :public Item_func
user_var_entry *entry; user_var_entry *entry;
public: public:
Item_func_set_user_var(LEX_STRING a,Item *b): Item_func(b), name(a) {} Item_func_set_user_var(LEX_STRING a,Item *b)
:Item_func(b), cached_result_type(INT_RESULT), name(a)
{}
double val(); double val();
longlong val_int(); longlong val_int();
String *val_str(String *str); String *val_str(String *str);
@ -939,6 +940,11 @@ public:
void fix_length_and_dec(); void fix_length_and_dec();
void print(String *str); void print(String *str);
enum Item_result result_type() const; enum Item_result result_type() const;
/*
We must always return variables as strings to guard against selects of type
select @t1:=1,@t1,@t:="hello",@t from foo where (@t1:= t2.b)
*/
enum_field_types field_type() const { return MYSQL_TYPE_STRING; }
const char *func_name() const { return "get_user_var"; } const char *func_name() const { return "get_user_var"; }
bool const_item() const { return const_var_flag; } bool const_item() const { return const_var_flag; }
table_map used_tables() const table_map used_tables() const

View File

@ -74,20 +74,6 @@ void Item_subselect::select_transformer(st_select_lex *select_lex)
} }
void Item_subselect::make_field (Send_field *tmp_field)
{
if (null_value)
{
init_make_field(tmp_field,FIELD_TYPE_NULL);
tmp_field->length=4;
} else {
init_make_field(tmp_field, ((result_type() == STRING_RESULT) ?
FIELD_TYPE_VAR_STRING :
(result_type() == INT_RESULT) ?
FIELD_TYPE_LONGLONG : FIELD_TYPE_DOUBLE));
}
}
bool Item_subselect::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) bool Item_subselect::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{ {
if (substitution) if (substitution)

View File

@ -76,7 +76,6 @@ public:
void assigned(bool a) { value_assigned= a; } void assigned(bool a) { value_assigned= a; }
enum Type type() const; enum Type type() const;
bool is_null() { return null_value; } bool is_null() { return null_value; }
void make_field (Send_field *);
bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref); bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref);
virtual void fix_length_and_dec(); virtual void fix_length_and_dec();
table_map used_tables() const; table_map used_tables() const;

View File

@ -47,27 +47,20 @@ void Item_sum::mark_as_sum_func()
with_sum_func= 1; with_sum_func= 1;
} }
void Item_sum::make_field(Send_field *tmp_field) void Item_sum::make_field(Send_field *tmp_field)
{ {
if (args[0]->type() == Item::FIELD_ITEM && keep_field_type()) if (args[0]->type() == Item::FIELD_ITEM && keep_field_type())
((Item_field*) args[0])->field->make_field(tmp_field);
else
{ {
tmp_field->flags=0; ((Item_field*) args[0])->field->make_field(tmp_field);
if (!maybe_null)
tmp_field->flags|= NOT_NULL_FLAG;
if (unsigned_flag)
tmp_field->flags |= UNSIGNED_FLAG;
tmp_field->length=max_length;
tmp_field->decimals=decimals;
tmp_field->type=(result_type() == INT_RESULT ? FIELD_TYPE_LONG :
result_type() == REAL_RESULT ? FIELD_TYPE_DOUBLE :
FIELD_TYPE_VAR_STRING);
}
tmp_field->db_name=(char*)""; tmp_field->db_name=(char*)"";
tmp_field->org_table_name=tmp_field->table_name=(char*)""; tmp_field->org_table_name=tmp_field->table_name=(char*)"";
tmp_field->org_col_name=tmp_field->col_name=name; tmp_field->org_col_name=tmp_field->col_name=name;
} }
else
init_make_field(tmp_field, field_type());
}
void Item_sum::print(String *str) void Item_sum::print(String *str)
{ {
@ -168,6 +161,10 @@ Item_sum_hybrid::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
null_value=1; null_value=1;
fix_length_and_dec(); fix_length_and_dec();
thd->allow_sum_func=1; // Allow group functions thd->allow_sum_func=1; // Allow group functions
if (item->type() == Item::FIELD_ITEM)
hybrid_field_type= ((Item_field*) item)->field->type();
else
hybrid_field_type= Item::field_type();
fixed= 1; fixed= 1;
return 0; return 0;
} }

View File

@ -210,7 +210,7 @@ public:
longlong val_int() { return (longlong) val(); } longlong val_int() { return (longlong) val(); }
bool is_null() { (void) val_int(); return null_value; } bool is_null() { (void) val_int(); return null_value; }
String *val_str(String*); String *val_str(String*);
void make_field(Send_field *field); enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
void fix_length_and_dec() {} void fix_length_and_dec() {}
}; };
@ -247,7 +247,7 @@ public:
longlong val_int() { return (longlong) val(); } longlong val_int() { return (longlong) val(); }
String *val_str(String*); String *val_str(String*);
bool is_null() { (void) val_int(); return null_value; } bool is_null() { (void) val_int(); return null_value; }
void make_field(Send_field *field); enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
void fix_length_and_dec() {} void fix_length_and_dec() {}
}; };
@ -318,6 +318,7 @@ class Item_sum_hybrid :public Item_sum
double sum; double sum;
longlong sum_int; longlong sum_int;
Item_result hybrid_type; Item_result hybrid_type;
enum_field_types hybrid_field_type;
int cmp_sign; int cmp_sign;
table_map used_table_cache; table_map used_table_cache;
@ -344,6 +345,7 @@ class Item_sum_hybrid :public Item_sum
void make_const() { used_table_cache=0; } void make_const() { used_table_cache=0; }
bool keep_field_type(void) const { return 1; } bool keep_field_type(void) const { return 1; }
enum Item_result result_type () const { return hybrid_type; } enum Item_result result_type () const { return hybrid_type; }
enum enum_field_types field_type() const { return hybrid_field_type; }
void update_field(int offset); void update_field(int offset);
void min_max_update_str_field(int offset); void min_max_update_str_field(int offset);
void min_max_update_real_field(int offset); void min_max_update_real_field(int offset);

View File

@ -295,8 +295,8 @@ longlong Item_func_time_to_sec::val_int()
/* /*
** Convert a string to a interval value Convert a string to a interval value
** To make code easy, allow interval objects without separators. To make code easy, allow interval objects without separators.
*/ */
static bool get_interval_value(Item *args,interval_type int_type, static bool get_interval_value(Item *args,interval_type int_type,
@ -516,12 +516,14 @@ void Item_func_curtime::fix_length_and_dec()
(int) start->tm_sec); (int) start->tm_sec);
} }
String *Item_func_now::val_str(String *str) String *Item_func_now::val_str(String *str)
{ {
str_value.set(buff,buff_length,thd_charset()); str_value.set(buff,buff_length,thd_charset());
return &str_value; return &str_value;
} }
void Item_func_now::fix_length_and_dec() void Item_func_now::fix_length_and_dec()
{ {
struct tm tm_tmp,*start; struct tm tm_tmp,*start;
@ -540,7 +542,8 @@ void Item_func_now::fix_length_and_dec()
(ulong) (((uint) start->tm_min)*100L+ (ulong) (((uint) start->tm_min)*100L+
(uint) start->tm_sec))); (uint) start->tm_sec)));
buff_length= (uint) cs->snprintf(cs,buff, sizeof(buff),"%04d-%02d-%02d %02d:%02d:%02d", buff_length= (uint) cs->snprintf(cs,buff, sizeof(buff),
"%04d-%02d-%02d %02d:%02d:%02d",
((int) (start->tm_year+1900)) % 10000, ((int) (start->tm_year+1900)) % 10000,
(int) start->tm_mon+1, (int) start->tm_mon+1,
(int) start->tm_mday, (int) start->tm_mday,
@ -995,6 +998,41 @@ bool Item_func_from_unixtime::get_date(TIME *ltime,
return 0; return 0;
} }
void Item_date_add_interval::fix_length_and_dec()
{
enum_field_types arg0_field_type;
set_charset(thd_charset());
maybe_null=1;
max_length=19*thd_charset()->mbmaxlen;
value.alloc(32);
/*
The field type for the result of an Item_date function is defined as
follows:
- If first arg is a MYSQL_TYPE_DATETIME result is MYSQL_TYPE_DATETIME
- If first arg is a MYSQL_TYPE_DATE and the interval type uses hours,
minutes or seconds then type is MYSQL_TYPE_DATETIME.
- Otherwise the result is MYSQL_TYPE_STRING
(This is because you can't know if the string contains a DATE, TIME or
DATETIME argument)
*/
cached_field_type= MYSQL_TYPE_STRING;
arg0_field_type= args[0]->field_type();
if (arg0_field_type == MYSQL_TYPE_DATETIME ||
arg0_field_type == MYSQL_TYPE_TIMESTAMP)
cached_field_type= MYSQL_TYPE_DATETIME;
else if (arg0_field_type == MYSQL_TYPE_DATE)
{
if (int_type <= INTERVAL_MONTH || int_type == INTERVAL_YEAR_MONTH)
cached_field_type= arg0_field_type;
else
cached_field_type= MYSQL_TYPE_DATETIME;
}
}
/* Here arg[1] is a Item_interval object */ /* Here arg[1] is a Item_interval object */
bool Item_date_add_interval::get_date(TIME *ltime, bool fuzzy_date) bool Item_date_add_interval::get_date(TIME *ltime, bool fuzzy_date)

View File

@ -316,6 +316,7 @@ public:
Item_date() :Item_func() {} Item_date() :Item_func() {}
Item_date(Item *a) :Item_func(a) {} Item_date(Item *a) :Item_func(a) {}
enum Item_result result_type () const { return STRING_RESULT; } enum Item_result result_type () const { return STRING_RESULT; }
enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
String *val_str(String *str); String *val_str(String *str);
double val() { return (double) val_int(); } double val() { return (double) val_int(); }
const char *func_name() const { return "date"; } const char *func_name() const { return "date"; }
@ -326,10 +327,6 @@ public:
max_length=10*thd_charset()->mbmaxlen; max_length=10*thd_charset()->mbmaxlen;
} }
int save_in_field(Field *to, bool no_conversions); int save_in_field(Field *to, bool no_conversions);
void make_field(Send_field *tmp_field)
{
init_make_field(tmp_field,FIELD_TYPE_DATE);
}
Field *tmp_table_field(TABLE *t_arg) Field *tmp_table_field(TABLE *t_arg)
{ {
return (!t_arg) ? result_field : new Field_date(maybe_null, name, t_arg, thd_charset()); return (!t_arg) ? result_field : new Field_date(maybe_null, name, t_arg, thd_charset());
@ -343,10 +340,7 @@ public:
Item_date_func() :Item_str_func() {} Item_date_func() :Item_str_func() {}
Item_date_func(Item *a) :Item_str_func(a) {} Item_date_func(Item *a) :Item_str_func(a) {}
Item_date_func(Item *a,Item *b) :Item_str_func(a,b) {} Item_date_func(Item *a,Item *b) :Item_str_func(a,b) {}
void make_field(Send_field *tmp_field) enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; }
{
init_make_field(tmp_field,FIELD_TYPE_DATETIME);
}
Field *tmp_table_field(TABLE *t_arg) Field *tmp_table_field(TABLE *t_arg)
{ {
return (!t_arg) ? result_field : new Field_datetime(maybe_null, name, return (!t_arg) ? result_field : new Field_datetime(maybe_null, name,
@ -364,15 +358,12 @@ public:
Item_func_curtime() :Item_func() {} Item_func_curtime() :Item_func() {}
Item_func_curtime(Item *a) :Item_func(a) {} Item_func_curtime(Item *a) :Item_func(a) {}
enum Item_result result_type () const { return STRING_RESULT; } enum Item_result result_type () const { return STRING_RESULT; }
enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
double val() { return (double) value; } double val() { return (double) value; }
longlong val_int() { return value; } longlong val_int() { return value; }
String *val_str(String *str); String *val_str(String *str);
const char *func_name() const { return "curtime"; } const char *func_name() const { return "curtime"; }
void fix_length_and_dec(); void fix_length_and_dec();
void make_field(Send_field *tmp_field)
{
init_make_field(tmp_field,FIELD_TYPE_TIME);
}
Field *tmp_table_field(TABLE *t_arg) Field *tmp_table_field(TABLE *t_arg)
{ {
return (!t_arg) ? result_field : return (!t_arg) ? result_field :
@ -452,7 +443,6 @@ class Item_func_from_unixtime :public Item_date_func
decimals=0; decimals=0;
max_length=19*thd_charset()->mbmaxlen; max_length=19*thd_charset()->mbmaxlen;
} }
// enum Item_result result_type () const { return STRING_RESULT; }
bool get_date(TIME *res,bool fuzzy_date); bool get_date(TIME *res,bool fuzzy_date);
}; };
@ -470,11 +460,8 @@ public:
maybe_null=1; maybe_null=1;
max_length=13*thd_charset()->mbmaxlen; max_length=13*thd_charset()->mbmaxlen;
} }
enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
const char *func_name() const { return "sec_to_time"; } const char *func_name() const { return "sec_to_time"; }
void make_field(Send_field *tmp_field)
{
init_make_field(tmp_field,FIELD_TYPE_TIME);
}
Field *tmp_table_field(TABLE *t_arg) Field *tmp_table_field(TABLE *t_arg)
{ {
return (!t_arg) ? result_field : return (!t_arg) ? result_field :
@ -482,32 +469,34 @@ public:
} }
}; };
/*
The following must be sorted so that simple intervals comes first.
(get_interval_value() depends on this)
*/
enum interval_type
{
INTERVAL_YEAR, INTERVAL_MONTH, INTERVAL_DAY, INTERVAL_HOUR, INTERVAL_MINUTE,
INTERVAL_SECOND, INTERVAL_YEAR_MONTH, INTERVAL_DAY_HOUR, INTERVAL_DAY_MINUTE,
INTERVAL_DAY_SECOND, INTERVAL_HOUR_MINUTE, INTERVAL_HOUR_SECOND,
INTERVAL_MINUTE_SECOND
};
enum interval_type { INTERVAL_YEAR, INTERVAL_MONTH, INTERVAL_DAY,
INTERVAL_HOUR, INTERVAL_MINUTE, INTERVAL_SECOND,
INTERVAL_YEAR_MONTH, INTERVAL_DAY_HOUR,
INTERVAL_DAY_MINUTE, INTERVAL_DAY_SECOND,
INTERVAL_HOUR_MINUTE, INTERVAL_HOUR_SECOND,
INTERVAL_MINUTE_SECOND};
class Item_date_add_interval :public Item_date_func class Item_date_add_interval :public Item_date_func
{ {
const interval_type int_type; const interval_type int_type;
String value; String value;
const bool date_sub_interval; const bool date_sub_interval;
enum_field_types cached_field_type;
public: public:
Item_date_add_interval(Item *a,Item *b,interval_type type_arg,bool neg_arg) Item_date_add_interval(Item *a,Item *b,interval_type type_arg,bool neg_arg)
:Item_date_func(a,b),int_type(type_arg), date_sub_interval(neg_arg) {} :Item_date_func(a,b),int_type(type_arg), date_sub_interval(neg_arg) {}
String *val_str(String *); String *val_str(String *);
const char *func_name() const { return "date_add_interval"; } const char *func_name() const { return "date_add_interval"; }
void fix_length_and_dec() void fix_length_and_dec();
{ enum_field_types field_type() const { return cached_field_type; }
set_charset(thd_charset());
maybe_null=1;
max_length=19*thd_charset()->mbmaxlen;
value.alloc(32);
}
double val() { return (double) val_int(); } double val() { return (double) val_int(); }
longlong val_int(); longlong val_int();
bool get_date(TIME *res,bool fuzzy_date); bool get_date(TIME *res,bool fuzzy_date);
@ -566,10 +555,7 @@ class Item_date_typecast :public Item_typecast
public: public:
Item_date_typecast(Item *a) :Item_typecast(a) {} Item_date_typecast(Item *a) :Item_typecast(a) {}
const char *func_name() const { return "date"; } const char *func_name() const { return "date"; }
void make_field(Send_field *tmp_field) enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
{
init_make_field(tmp_field,FIELD_TYPE_DATE);
}
Field *tmp_table_field(TABLE *t_arg) Field *tmp_table_field(TABLE *t_arg)
{ {
return (!t_arg) ? result_field : return (!t_arg) ? result_field :
@ -583,10 +569,7 @@ class Item_time_typecast :public Item_typecast
public: public:
Item_time_typecast(Item *a) :Item_typecast(a) {} Item_time_typecast(Item *a) :Item_typecast(a) {}
const char *func_name() const { return "time"; } const char *func_name() const { return "time"; }
void make_field(Send_field *tmp_field) enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
{
init_make_field(tmp_field,FIELD_TYPE_TIME);
}
Field *tmp_table_field(TABLE *t_arg) Field *tmp_table_field(TABLE *t_arg)
{ {
return (!t_arg) ? result_field : return (!t_arg) ? result_field :
@ -600,10 +583,7 @@ class Item_datetime_typecast :public Item_typecast
public: public:
Item_datetime_typecast(Item *a) :Item_typecast(a) {} Item_datetime_typecast(Item *a) :Item_typecast(a) {}
const char *func_name() const { return "datetime"; } const char *func_name() const { return "datetime"; }
void make_field(Send_field *tmp_field) enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; }
{
init_make_field(tmp_field,FIELD_TYPE_DATETIME);
}
Field *tmp_table_field(TABLE *t_arg) Field *tmp_table_field(TABLE *t_arg)
{ {
return (!t_arg) ? result_field : new Field_datetime(maybe_null, name, return (!t_arg) ? result_field : new Field_datetime(maybe_null, name,

View File

@ -306,9 +306,9 @@ int Log_event::exec_event(struct st_relay_log_info* rli)
Log_event::pack_info() Log_event::pack_info()
****************************************************************************/ ****************************************************************************/
void Log_event::pack_info(String* packet) void Log_event::pack_info(Protocol *protocol)
{ {
net_store_data(packet, "", 0); protocol->store("",0);
} }
/***************************************************************************** /*****************************************************************************
@ -319,10 +319,13 @@ void Log_event::pack_info(String* packet)
void Log_event::init_show_field_list(List<Item>* field_list) void Log_event::init_show_field_list(List<Item>* field_list)
{ {
field_list->push_back(new Item_empty_string("Log_name", 20)); field_list->push_back(new Item_empty_string("Log_name", 20));
field_list->push_back(new Item_empty_string("Pos", 20)); field_list->push_back(new Item_return_int("Pos", 11,
MYSQL_TYPE_LONGLONG));
field_list->push_back(new Item_empty_string("Event_type", 20)); field_list->push_back(new Item_empty_string("Event_type", 20));
field_list->push_back(new Item_empty_string("Server_id", 20)); field_list->push_back(new Item_return_int("Server_id", 10,
field_list->push_back(new Item_empty_string("Orig_log_pos", 20)); MYSQL_TYPE_LONG));
field_list->push_back(new Item_return_int("Orig_log_pos", 11,
MYSQL_TYPE_LONGLONG));
field_list->push_back(new Item_empty_string("Info", 20)); field_list->push_back(new Item_empty_string("Info", 20));
} }
@ -333,23 +336,22 @@ void Log_event::init_show_field_list(List<Item>* field_list)
Only called by SHOW BINLOG EVENTS Only called by SHOW BINLOG EVENTS
****************************************************************************/ ****************************************************************************/
int Log_event::net_send(THD* thd_arg, const char* log_name, my_off_t pos) int Log_event::net_send(Protocol *protocol, const char* log_name, my_off_t pos)
{ {
String* packet = &thd_arg->packet;
const char *p= strrchr(log_name, FN_LIBCHAR); const char *p= strrchr(log_name, FN_LIBCHAR);
const char *event_type; const char *event_type;
if (p) if (p)
log_name = p + 1; log_name = p + 1;
packet->length(0); protocol->prepare_for_resend();
net_store_data(packet, log_name, strlen(log_name)); protocol->store(log_name);
net_store_data(packet, (longlong) pos); protocol->store((ulonglong) pos);
event_type = get_type_str(); event_type = get_type_str();
net_store_data(packet, event_type, strlen(event_type)); protocol->store(event_type, strlen(event_type));
net_store_data(packet, server_id); protocol->store((uint32) server_id);
net_store_data(packet, (longlong) log_pos); protocol->store((ulonglong) log_pos);
pack_info(packet); pack_info(protocol);
return my_net_write(&thd_arg->net, (char*) packet->ptr(), packet->length()); return protocol->write();
} }
#endif // !MYSQL_CLIENT #endif // !MYSQL_CLIENT
@ -671,7 +673,7 @@ void Log_event::set_log_pos(MYSQL_LOG* log)
Query_log_event::pack_info() Query_log_event::pack_info()
****************************************************************************/ ****************************************************************************/
void Query_log_event::pack_info(String* packet) void Query_log_event::pack_info(Protocol *protocol)
{ {
char buf[256]; char buf[256];
String tmp(buf, sizeof(buf), system_charset_info); String tmp(buf, sizeof(buf), system_charset_info);
@ -685,7 +687,7 @@ void Query_log_event::pack_info(String* packet)
if (query && q_len) if (query && q_len)
tmp.append(query, q_len); tmp.append(query, q_len);
net_store_data(packet, (char*)tmp.ptr(), tmp.length()); protocol->store((char*) tmp.ptr(), tmp.length());
} }
#endif // !MYSQL_CLIENT #endif // !MYSQL_CLIENT
@ -925,7 +927,7 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli)
****************************************************************************/ ****************************************************************************/
#ifndef MYSQL_CLIENT #ifndef MYSQL_CLIENT
void Start_log_event::pack_info(String* packet) void Start_log_event::pack_info(Protocol *protocol)
{ {
char buf1[256]; char buf1[256];
String tmp(buf1, sizeof(buf1), system_charset_info); String tmp(buf1, sizeof(buf1), system_charset_info);
@ -936,7 +938,7 @@ void Start_log_event::pack_info(String* packet)
tmp.append(server_version); tmp.append(server_version);
tmp.append(", Binlog ver: "); tmp.append(", Binlog ver: ");
tmp.append(llstr(binlog_version, buf)); tmp.append(llstr(binlog_version, buf));
net_store_data(packet, tmp.ptr(), tmp.length()); protocol->store(tmp.ptr(), tmp.length());
} }
#endif // !MYSQL_CLIENT #endif // !MYSQL_CLIENT
@ -1036,7 +1038,7 @@ int Start_log_event::exec_event(struct st_relay_log_info* rli)
****************************************************************************/ ****************************************************************************/
#ifndef MYSQL_CLIENT #ifndef MYSQL_CLIENT
void Load_log_event::pack_info(String* packet) void Load_log_event::pack_info(Protocol *protocol)
{ {
char buf[256]; char buf[256];
String tmp(buf, sizeof(buf), system_charset_info); String tmp(buf, sizeof(buf), system_charset_info);
@ -1109,7 +1111,7 @@ void Load_log_event::pack_info(String* packet)
tmp.append(')'); tmp.append(')');
} }
net_store_data(packet, tmp.ptr(), tmp.length()); protocol->store(tmp.ptr(), tmp.length());
} }
#endif // !MYSQL_CLIENT #endif // !MYSQL_CLIENT
@ -1542,7 +1544,7 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli)
****************************************************************************/ ****************************************************************************/
#ifndef MYSQL_CLIENT #ifndef MYSQL_CLIENT
void Rotate_log_event::pack_info(String* packet) void Rotate_log_event::pack_info(Protocol *protocol)
{ {
char buf1[256], buf[22]; char buf1[256], buf[22];
String tmp(buf1, sizeof(buf1), system_charset_info); String tmp(buf1, sizeof(buf1), system_charset_info);
@ -1552,7 +1554,7 @@ void Rotate_log_event::pack_info(String* packet)
tmp.append(llstr(pos,buf)); tmp.append(llstr(pos,buf));
if (flags & LOG_EVENT_FORCED_ROTATE_F) if (flags & LOG_EVENT_FORCED_ROTATE_F)
tmp.append("; forced by master"); tmp.append("; forced by master");
net_store_data(packet, tmp.ptr(), tmp.length()); protocol->store(tmp.ptr(), tmp.length());
} }
#endif // !MYSQL_CLIENT #endif // !MYSQL_CLIENT
@ -1680,7 +1682,7 @@ int Rotate_log_event::exec_event(struct st_relay_log_info* rli)
****************************************************************************/ ****************************************************************************/
#ifndef MYSQL_CLIENT #ifndef MYSQL_CLIENT
void Intvar_log_event::pack_info(String* packet) void Intvar_log_event::pack_info(Protocol *protocol)
{ {
char buf1[256], buf[22]; char buf1[256], buf[22];
String tmp(buf1, sizeof(buf1), system_charset_info); String tmp(buf1, sizeof(buf1), system_charset_info);
@ -1688,7 +1690,7 @@ void Intvar_log_event::pack_info(String* packet)
tmp.append(get_var_type_name()); tmp.append(get_var_type_name());
tmp.append('='); tmp.append('=');
tmp.append(llstr(val, buf)); tmp.append(llstr(val, buf));
net_store_data(packet, tmp.ptr(), tmp.length()); protocol->store(tmp.ptr(), tmp.length());
} }
#endif // !MYSQL_CLIENT #endif // !MYSQL_CLIENT
@ -1801,14 +1803,14 @@ int Intvar_log_event::exec_event(struct st_relay_log_info* rli)
****************************************************************************/ ****************************************************************************/
#ifndef MYSQL_CLIENT #ifndef MYSQL_CLIENT
void Rand_log_event::pack_info(String* packet) void Rand_log_event::pack_info(Protocol *protocol)
{ {
char buf1[256], *pos; char buf1[256], *pos;
pos= strmov(buf1,"rand_seed1="); pos= strmov(buf1,"rand_seed1=");
pos= int10_to_str((long) seed1, pos, 10); pos= int10_to_str((long) seed1, pos, 10);
pos= strmov(pos, ",rand_seed2="); pos= strmov(pos, ",rand_seed2=");
pos= int10_to_str((long) seed2, pos, 10); pos= int10_to_str((long) seed2, pos, 10);
net_store_data(packet, buf1, (uint) (pos-buf1)); protocol->store(buf1, (uint) (pos-buf1));
} }
#endif // !MYSQL_CLIENT #endif // !MYSQL_CLIENT
@ -1888,7 +1890,7 @@ int Rand_log_event::exec_event(struct st_relay_log_info* rli)
****************************************************************************/ ****************************************************************************/
#ifndef MYSQL_CLIENT #ifndef MYSQL_CLIENT
void Slave_log_event::pack_info(String* packet) void Slave_log_event::pack_info(Protocol *protocol)
{ {
char buf1[256], buf[22], *end; char buf1[256], buf[22], *end;
String tmp(buf1, sizeof(buf1), system_charset_info); String tmp(buf1, sizeof(buf1), system_charset_info);
@ -1902,7 +1904,7 @@ void Slave_log_event::pack_info(String* packet)
tmp.append(master_log); tmp.append(master_log);
tmp.append(",pos="); tmp.append(",pos=");
tmp.append(llstr(master_pos,buf)); tmp.append(llstr(master_pos,buf));
net_store_data(packet, tmp.ptr(), tmp.length()); protocol->store(tmp.ptr(), tmp.length());
} }
#endif // !MYSQL_CLIENT #endif // !MYSQL_CLIENT
@ -2236,7 +2238,7 @@ void Create_file_log_event::print(FILE* file, bool short_form,
****************************************************************************/ ****************************************************************************/
#ifndef MYSQL_CLIENT #ifndef MYSQL_CLIENT
void Create_file_log_event::pack_info(String* packet) void Create_file_log_event::pack_info(Protocol *protocol)
{ {
char buf1[256],buf[22], *end; char buf1[256],buf[22], *end;
String tmp(buf1, sizeof(buf1), system_charset_info); String tmp(buf1, sizeof(buf1), system_charset_info);
@ -2251,7 +2253,7 @@ void Create_file_log_event::pack_info(String* packet)
tmp.append(";block_len="); tmp.append(";block_len=");
end= int10_to_str((long) block_len, buf, 10); end= int10_to_str((long) block_len, buf, 10);
tmp.append(buf, (uint32) (end-buf)); tmp.append(buf, (uint32) (end-buf));
net_store_data(packet, (char*) tmp.ptr(), tmp.length()); protocol->store((char*) tmp.ptr(), tmp.length());
} }
#endif // !MYSQL_CLIENT #endif // !MYSQL_CLIENT
@ -2395,14 +2397,14 @@ void Append_block_log_event::print(FILE* file, bool short_form,
****************************************************************************/ ****************************************************************************/
#ifndef MYSQL_CLIENT #ifndef MYSQL_CLIENT
void Append_block_log_event::pack_info(String* packet) void Append_block_log_event::pack_info(Protocol *protocol)
{ {
char buf[256]; char buf[256];
uint length; uint length;
length= (uint) my_sprintf(buf, length= (uint) my_sprintf(buf,
(buf, ";file_id=%u;block_len=%u", file_id, (buf, ";file_id=%u;block_len=%u", file_id,
block_len)); block_len));
net_store_data(packet, buf, (int32) length); protocol->store(buf, (int32) length);
} }
#endif // !MYSQL_CLIENT #endif // !MYSQL_CLIENT
@ -2510,12 +2512,12 @@ void Delete_file_log_event::print(FILE* file, bool short_form,
****************************************************************************/ ****************************************************************************/
#ifndef MYSQL_CLIENT #ifndef MYSQL_CLIENT
void Delete_file_log_event::pack_info(String* packet) void Delete_file_log_event::pack_info(Protocol *protocol)
{ {
char buf[64]; char buf[64];
uint length; uint length;
length= (uint) my_sprintf(buf, (buf, ";file_id=%u", (uint) file_id)); length= (uint) my_sprintf(buf, (buf, ";file_id=%u", (uint) file_id));
net_store_data(packet, buf, (int32) length); protocol->store(buf, (int32) length);
} }
#endif // !MYSQL_CLIENT #endif // !MYSQL_CLIENT
@ -2609,12 +2611,12 @@ void Execute_load_log_event::print(FILE* file, bool short_form,
****************************************************************************/ ****************************************************************************/
#ifndef MYSQL_CLIENT #ifndef MYSQL_CLIENT
void Execute_load_log_event::pack_info(String* packet) void Execute_load_log_event::pack_info(Protocol *protocol)
{ {
char buf[64]; char buf[64];
uint length; uint length;
length= (uint) my_sprintf(buf, (buf, ";file_id=%u", (uint) file_id)); length= (uint) my_sprintf(buf, (buf, ";file_id=%u", (uint) file_id));
net_store_data(packet, buf, (int32) length); protocol->store(buf, (int32) length);
} }
#endif // !MYSQL_CLIENT #endif // !MYSQL_CLIENT

View File

@ -267,8 +267,8 @@ public:
static int read_log_event(IO_CACHE* file, String* packet, static int read_log_event(IO_CACHE* file, String* packet,
pthread_mutex_t* log_lock); pthread_mutex_t* log_lock);
void set_log_pos(MYSQL_LOG* log); void set_log_pos(MYSQL_LOG* log);
virtual void pack_info(String* packet); virtual void pack_info(Protocol *protocol);
int net_send(THD* thd, const char* log_name, my_off_t pos); int net_send(Protocol *protocol, const char* log_name, my_off_t pos);
static void init_show_field_list(List<Item>* field_list); static void init_show_field_list(List<Item>* field_list);
virtual int exec_event(struct st_relay_log_info* rli); virtual int exec_event(struct st_relay_log_info* rli);
virtual const char* get_db() virtual const char* get_db()
@ -355,7 +355,7 @@ public:
Query_log_event(THD* thd_arg, const char* query_arg, ulong query_length, Query_log_event(THD* thd_arg, const char* query_arg, ulong query_length,
bool using_trans); bool using_trans);
const char* get_db() { return db; } const char* get_db() { return db; }
void pack_info(String* packet); void pack_info(Protocol* protocol);
int exec_event(struct st_relay_log_info* rli); int exec_event(struct st_relay_log_info* rli);
#else #else
void print(FILE* file, bool short_form = 0, char* last_db = 0); void print(FILE* file, bool short_form = 0, char* last_db = 0);
@ -404,7 +404,7 @@ public:
#ifndef MYSQL_CLIENT #ifndef MYSQL_CLIENT
Slave_log_event(THD* thd_arg, struct st_relay_log_info* rli); Slave_log_event(THD* thd_arg, struct st_relay_log_info* rli);
void pack_info(String* packet); void pack_info(Protocol* protocol);
int exec_event(struct st_relay_log_info* rli); int exec_event(struct st_relay_log_info* rli);
#else #else
void print(FILE* file, bool short_form = 0, char* last_db = 0); void print(FILE* file, bool short_form = 0, char* last_db = 0);
@ -454,7 +454,7 @@ public:
List<Item>& fields_arg, enum enum_duplicates handle_dup, List<Item>& fields_arg, enum enum_duplicates handle_dup,
bool using_trans); bool using_trans);
void set_fields(List<Item> &fields_arg); void set_fields(List<Item> &fields_arg);
void pack_info(String* packet); void pack_info(Protocol* protocol);
const char* get_db() { return db; } const char* get_db() { return db; }
int exec_event(struct st_relay_log_info* rli) int exec_event(struct st_relay_log_info* rli)
{ {
@ -507,7 +507,7 @@ public:
created = (uint32) when; created = (uint32) when;
memcpy(server_version, ::server_version, ST_SERVER_VER_LEN); memcpy(server_version, ::server_version, ST_SERVER_VER_LEN);
} }
void pack_info(String* packet); void pack_info(Protocol* protocol);
int exec_event(struct st_relay_log_info* rli); int exec_event(struct st_relay_log_info* rli);
#else #else
void print(FILE* file, bool short_form = 0, char* last_db = 0); void print(FILE* file, bool short_form = 0, char* last_db = 0);
@ -542,7 +542,7 @@ public:
Intvar_log_event(THD* thd_arg,uchar type_arg, ulonglong val_arg) Intvar_log_event(THD* thd_arg,uchar type_arg, ulonglong val_arg)
:Log_event(),val(val_arg),type(type_arg) :Log_event(),val(val_arg),type(type_arg)
{} {}
void pack_info(String* packet); void pack_info(Protocol* protocol);
int exec_event(struct st_relay_log_info* rli); int exec_event(struct st_relay_log_info* rli);
#else #else
void print(FILE* file, bool short_form = 0, char* last_db = 0); void print(FILE* file, bool short_form = 0, char* last_db = 0);
@ -574,7 +574,7 @@ class Rand_log_event: public Log_event
Rand_log_event(THD* thd_arg, ulonglong seed1_arg, ulonglong seed2_arg) Rand_log_event(THD* thd_arg, ulonglong seed1_arg, ulonglong seed2_arg)
:Log_event(thd_arg,0,0),seed1(seed1_arg),seed2(seed2_arg) :Log_event(thd_arg,0,0),seed1(seed1_arg),seed2(seed2_arg)
{} {}
void pack_info(String* packet); void pack_info(Protocol* protocol);
int exec_event(struct st_relay_log_info* rli); int exec_event(struct st_relay_log_info* rli);
#else #else
void print(FILE* file, bool short_form = 0, char* last_db = 0); void print(FILE* file, bool short_form = 0, char* last_db = 0);
@ -636,7 +636,7 @@ public:
pos(pos_arg),ident_len(ident_len_arg ? ident_len_arg : pos(pos_arg),ident_len(ident_len_arg ? ident_len_arg :
(uint) strlen(new_log_ident_arg)), alloced(0) (uint) strlen(new_log_ident_arg)), alloced(0)
{} {}
void pack_info(String* packet); void pack_info(Protocol* protocol);
int exec_event(struct st_relay_log_info* rli); int exec_event(struct st_relay_log_info* rli);
#else #else
void print(FILE* file, bool short_form = 0, char* last_db = 0); void print(FILE* file, bool short_form = 0, char* last_db = 0);
@ -683,7 +683,7 @@ public:
enum enum_duplicates handle_dup, enum enum_duplicates handle_dup,
char* block_arg, uint block_len_arg, char* block_arg, uint block_len_arg,
bool using_trans); bool using_trans);
void pack_info(String* packet); void pack_info(Protocol* protocol);
int exec_event(struct st_relay_log_info* rli); int exec_event(struct st_relay_log_info* rli);
#else #else
void print(FILE* file, bool short_form = 0, char* last_db = 0); void print(FILE* file, bool short_form = 0, char* last_db = 0);
@ -734,7 +734,7 @@ public:
Append_block_log_event(THD* thd, char* block_arg, Append_block_log_event(THD* thd, char* block_arg,
uint block_len_arg, bool using_trans); uint block_len_arg, bool using_trans);
int exec_event(struct st_relay_log_info* rli); int exec_event(struct st_relay_log_info* rli);
void pack_info(String* packet); void pack_info(Protocol* protocol);
#else #else
void print(FILE* file, bool short_form = 0, char* last_db = 0); void print(FILE* file, bool short_form = 0, char* last_db = 0);
#endif #endif
@ -759,7 +759,7 @@ public:
#ifndef MYSQL_CLIENT #ifndef MYSQL_CLIENT
Delete_file_log_event(THD* thd, bool using_trans); Delete_file_log_event(THD* thd, bool using_trans);
void pack_info(String* packet); void pack_info(Protocol* protocol);
int exec_event(struct st_relay_log_info* rli); int exec_event(struct st_relay_log_info* rli);
#else #else
void print(FILE* file, bool short_form = 0, char* last_db = 0); void print(FILE* file, bool short_form = 0, char* last_db = 0);
@ -785,7 +785,7 @@ public:
#ifndef MYSQL_CLIENT #ifndef MYSQL_CLIENT
Execute_load_log_event(THD* thd, bool using_trans); Execute_load_log_event(THD* thd, bool using_trans);
void pack_info(String* packet); void pack_info(Protocol* protocol);
int exec_event(struct st_relay_log_info* rli); int exec_event(struct st_relay_log_info* rli);
#else #else
void print(FILE* file, bool short_form = 0, char* last_db = 0); void print(FILE* file, bool short_form = 0, char* last_db = 0);

View File

@ -283,6 +283,7 @@ inline THD *_current_thd(void)
#include "handler.h" #include "handler.h"
#include "table.h" #include "table.h"
#include "field.h" /* Field definitions */ #include "field.h" /* Field definitions */
#include "protocol.h"
#include "sql_udf.h" #include "sql_udf.h"
#include "item.h" #include "item.h"
typedef compare_func_creator (*chooser_compare_func_creator)(bool invert); typedef compare_func_creator (*chooser_compare_func_creator)(bool invert);
@ -377,30 +378,6 @@ int mysql_optimize_table(THD* thd, TABLE_LIST* table_list,
HA_CHECK_OPT* check_opt); HA_CHECK_OPT* check_opt);
bool check_simple_select(); bool check_simple_select();
/* net_pkg.c */
void send_warning(THD *thd, uint sql_errno, const char *err=0);
void net_printf(THD *thd,uint sql_errno, ...);
void send_ok(THD *thd, ha_rows affected_rows=0L, ulonglong id=0L,
const char *info=0);
void send_eof(THD *thd, bool no_flush=0);
void net_send_error(NET *net, uint sql_errno, const char *err);
char *net_store_length(char *packet,ulonglong length);
char *net_store_length(char *packet,uint length);
char *net_store_data(char *to,const char *from);
char *net_store_data(char *to,int32 from);
char *net_store_data(char *to,longlong from);
bool net_store_null(String *packet);
bool net_store_data(String *packet,uint32 from);
bool net_store_data(String *packet,longlong from);
bool net_store_data(String *packet,const char *from);
bool net_store_data(String *packet,const char *from,uint length);
bool net_store_data(String *packet,struct tm *tmp);
bool net_store_data(String* packet, I_List<i_string>* str_list);
bool net_store_data(String *packet,CONVERT *convert, const char *from,
uint length);
bool net_store_data(String *packet, CONVERT *convert, const char *from);
SORT_FIELD * make_unireg_sortorder(ORDER *order, uint *length); SORT_FIELD * make_unireg_sortorder(ORDER *order, uint *length);
int setup_order(THD *thd,TABLE_LIST *tables, List<Item> &fields, int setup_order(THD *thd,TABLE_LIST *tables, List<Item> &fields,
List <Item> &all_fields, ORDER *order); List <Item> &all_fields, ORDER *order);
@ -594,7 +571,6 @@ int lock_tables(THD *thd,TABLE_LIST *tables);
TABLE *open_temporary_table(THD *thd, const char *path, const char *db, TABLE *open_temporary_table(THD *thd, const char *path, const char *db,
const char *table_name, bool link_in_list); const char *table_name, bool link_in_list);
bool rm_temporary_table(enum db_type base, char *path); bool rm_temporary_table(enum db_type base, char *path);
bool send_fields(THD *thd,List<Item> &item,uint send_field_count);
void free_io_cache(TABLE *entry); void free_io_cache(TABLE *entry);
void intern_close_table(TABLE *entry); void intern_close_table(TABLE *entry);
bool close_thread_table(THD *thd, TABLE **table_ptr); bool close_thread_table(THD *thd, TABLE **table_ptr);
@ -818,6 +794,7 @@ bool str_to_time(const char *str,uint length,TIME *l_time);
longlong str_to_datetime(const char *str,uint length,bool fuzzy_date); longlong str_to_datetime(const char *str,uint length,bool fuzzy_date);
timestamp_type str_to_TIME(const char *str, uint length, TIME *l_time, timestamp_type str_to_TIME(const char *str, uint length, TIME *l_time,
bool fuzzy_date); bool fuzzy_date);
void localtime_to_TIME(TIME *to, struct tm *from);
int test_if_number(char *str,int *res,bool allow_wildcards); int test_if_number(char *str,int *res,bool allow_wildcards);
void change_byte(byte *,uint,char,char); void change_byte(byte *,uint,char,char);

View File

@ -1536,7 +1536,7 @@ static void start_signal_handler(void)
(void) pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED); (void) pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED);
if (!(opt_specialflag & SPECIAL_NO_PRIOR)) if (!(opt_specialflag & SPECIAL_NO_PRIOR))
my_pthread_attr_setprio(&thr_attr,INTERRUPT_PRIOR); my_pthread_attr_setprio(&thr_attr,INTERRUPT_PRIOR);
pthread_attr_setstacksize(&thr_attr,32768); pthread_attr_setstacksize(&thr_attr, 129*1024);
#endif #endif
(void) pthread_mutex_lock(&LOCK_thread_count); (void) pthread_mutex_lock(&LOCK_thread_count);

View File

@ -1,492 +0,0 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "mysql_priv.h"
#include <stdarg.h>
/* Send a error string to client */
void send_error(THD *thd, uint sql_errno, const char *err)
{
uint length;
char buff[MYSQL_ERRMSG_SIZE+2];
NET *net= &thd->net;
DBUG_ENTER("send_error");
DBUG_PRINT("enter",("sql_errno: %d err: %s", sql_errno,
err ? err : net->last_error[0] ?
net->last_error : "NULL"));
query_cache_abort(net);
thd->query_error= 1; // needed to catch query errors during replication
if (!err)
{
if (sql_errno)
err=ER(sql_errno);
else
{
if ((err=net->last_error)[0])
sql_errno=net->last_errno;
else
{
sql_errno=ER_UNKNOWN_ERROR;
err=ER(sql_errno); /* purecov: inspected */
}
}
}
if (net->vio == 0)
{
if (thd->bootstrap)
{
/* In bootstrap it's ok to print on stderr */
fprintf(stderr,"ERROR: %d %s\n",sql_errno,err);
}
DBUG_VOID_RETURN;
}
if (net->return_errno)
{ // new client code; Add errno before message
int2store(buff,sql_errno);
length= (uint) (strmake(buff+2,err,MYSQL_ERRMSG_SIZE-1) - buff);
err=buff;
}
else
{
length=(uint) strlen(err);
set_if_smaller(length,MYSQL_ERRMSG_SIZE-1);
}
VOID(net_write_command(net,(uchar) 255, "", 0, (char*) err,length));
thd->fatal_error=0; // Error message is given
thd->net.report_error= 0;
DBUG_VOID_RETURN;
}
/*
Send an error to the client when a connection is forced close
This is used by mysqld.cc, which doesn't have a THD
*/
void net_send_error(NET *net, uint sql_errno, const char *err)
{
char buff[2];
uint length;
DBUG_ENTER("send_net_error");
int2store(buff,sql_errno);
length=(uint) strlen(err);
set_if_smaller(length,MYSQL_ERRMSG_SIZE-1);
net_write_command(net,(uchar) 255, buff, 2, err, length);
DBUG_VOID_RETURN;
}
/*
Send a warning to the end user
SYNOPSIS
send_warning()
thd Thread handler
sql_errno Warning number (error message)
err Error string. If not set, use ER(sql_errno)
DESCRIPTION
Register the warning so that the user can get it with mysql_warnings()
Send an ok (+ warning count) to the end user.
*/
void send_warning(THD *thd, uint sql_errno, const char *err)
{
DBUG_ENTER("send_warning");
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, sql_errno,
err ? err : ER(sql_errno));
send_ok(thd);
DBUG_VOID_RETURN;
}
/*
Write error package and flush to client
It's a little too low level, but I don't want to use another buffer for
this
*/
void
net_printf(THD *thd, uint errcode, ...)
{
va_list args;
uint length,offset;
const char *format,*text_pos;
int head_length= NET_HEADER_SIZE;
NET *net= &thd->net;
DBUG_ENTER("net_printf");
DBUG_PRINT("enter",("message: %u",errcode));
thd->query_error= 1; // needed to catch query errors during replication
query_cache_abort(net); // Safety
va_start(args,errcode);
/*
The following is needed to make net_printf() work with 0 argument for
errorcode and use the argument after that as the format string. This
is useful for rare errors that are not worth the hassle to put in
errmsg.sys, but at the same time, the message is not fixed text
*/
if (errcode)
format= ER(errcode);
else
{
format=va_arg(args,char*);
errcode= ER_UNKNOWN_ERROR;
}
offset= net->return_errno ? 2 : 0;
text_pos=(char*) net->buff+head_length+offset+1;
(void) vsprintf(my_const_cast(char*) (text_pos),format,args);
length=(uint) strlen((char*) text_pos);
if (length >= sizeof(net->last_error))
length=sizeof(net->last_error)-1; /* purecov: inspected */
va_end(args);
if (net->vio == 0)
{
if (thd->bootstrap)
{
/* In bootstrap it's ok to print on stderr */
fprintf(stderr,"ERROR: %d %s\n",errcode,text_pos);
thd->fatal_error=1;
}
DBUG_VOID_RETURN;
}
int3store(net->buff,length+1+offset);
net->buff[3]= (net->compress) ? 0 : (uchar) (net->pkt_nr++);
net->buff[head_length]=(uchar) 255; // Error package
if (offset)
int2store(text_pos-2, errcode);
VOID(net_real_write(net,(char*) net->buff,length+head_length+1+offset));
thd->fatal_error=0; // Error message is given
DBUG_VOID_RETURN;
}
/*
Return ok to the client.
SYNOPSIS
send_ok()
thd Thread handler
affected_rows Number of rows changed by statement
id Auto_increment id for first row (if used)
message Message to send to the client (Used by mysql_status)
DESCRIPTION
The ok packet has the following structure
0 Marker (1 byte)
affected_rows Stored in 1-9 bytes
id Stored in 1-9 bytes
server_status Copy of thd->server_status; Can be used by client
to check if we are inside an transaction
New in 4.0 protocol
warning_count Stored in 2 bytes; New in 4.1 protocol
message Stored as packed length (1-9 bytes) + message
Is not stored if no message
If net->no_send_ok return without sending packet
*/
void
send_ok(THD *thd, ha_rows affected_rows, ulonglong id, const char *message)
{
NET *net= &thd->net;
if (net->no_send_ok || !net->vio) // hack for re-parsing queries
return;
char buff[MYSQL_ERRMSG_SIZE+10],*pos;
DBUG_ENTER("send_ok");
buff[0]=0; // No fields
pos=net_store_length(buff+1,(ulonglong) affected_rows);
pos=net_store_length(pos, (ulonglong) id);
if (thd->client_capabilities & CLIENT_PROTOCOL_41)
{
int2store(pos,thd->server_status);
pos+=2;
/* We can only return up to 65535 warnings in two bytes */
uint tmp= min(thd->total_warn_count, 65535);
int2store(pos, tmp);
pos+= 2;
}
else if (net->return_status) // For 4.0 protocol
{
int2store(pos,thd->server_status);
pos+=2;
}
if (message)
pos=net_store_data((char*) pos,message);
VOID(my_net_write(net,buff,(uint) (pos-buff)));
VOID(net_flush(net));
DBUG_VOID_RETURN;
}
/*
Send eof (= end of result set) to the client
SYNOPSIS
send_eof()
thd Thread handler
no_flush Set to 1 if there will be more data to the client,
like in send_fields().
DESCRIPTION
The eof packet has the following structure
254 Marker (1 byte)
warning_count Stored in 2 bytes; New in 4.1 protocol
status_flag Stored in 2 bytes;
For flags like SERVER_STATUS_MORE_RESULTS
Note that the warning count will not be sent if 'no_flush' is set as
we don't want to report the warning count until all data is sent to the
client.
*/
void
send_eof(THD *thd, bool no_flush)
{
static char eof_buff[1]= { (char) 254 }; /* Marker for end of fields */
NET *net= &thd->net;
DBUG_ENTER("send_eof");
if (net->vio != 0)
{
if (!no_flush && (thd->client_capabilities & CLIENT_PROTOCOL_41))
{
uchar buff[5];
uint tmp= min(thd->total_warn_count, 65535);
buff[0]=254;
int2store(buff+1, tmp);
int2store(buff+3, 0); // No flags yet
VOID(my_net_write(net,(char*) buff,5));
VOID(net_flush(net));
}
else
{
VOID(my_net_write(net,eof_buff,1));
if (!no_flush)
VOID(net_flush(net));
}
}
DBUG_VOID_RETURN;
}
/****************************************************************************
** Store a field length in logical packet
****************************************************************************/
char *
net_store_length(char *pkg, ulonglong length)
{
uchar *packet=(uchar*) pkg;
if (length < LL(251))
{
*packet=(uchar) length;
return (char*) packet+1;
}
/* 251 is reserved for NULL */
if (length < LL(65536))
{
*packet++=252;
int2store(packet,(uint) length);
return (char*) packet+2;
}
if (length < LL(16777216))
{
*packet++=253;
int3store(packet,(ulong) length);
return (char*) packet+3;
}
*packet++=254;
int8store(packet,length);
return (char*) packet+9;
}
char *
net_store_length(char *pkg, uint length)
{
uchar *packet=(uchar*) pkg;
if (length < 251)
{
*packet=(uchar) length;
return (char*) packet+1;
}
*packet++=252;
int2store(packet,(uint) length);
return (char*) packet+2;
}
/* The following will only be used for short strings < 65K */
char *
net_store_data(char *to,const char *from)
{
uint length=(uint) strlen(from);
to=net_store_length(to,length);
memcpy(to,from,length);
return to+length;
}
char *
net_store_data(char *to,int32 from)
{
char buff[20];
uint length=(uint) (int10_to_str(from,buff,10)-buff);
to=net_store_length(to,length);
memcpy(to,buff,length);
return to+length;
}
char *
net_store_data(char *to,longlong from)
{
char buff[22];
uint length=(uint) (longlong10_to_str(from,buff,10)-buff);
to=net_store_length(to,length);
memcpy(to,buff,length);
return to+length;
}
bool net_store_null(String *packet)
{
return packet->append((char) 251);
}
bool
net_store_data(String *packet,const char *from,uint length)
{
ulong packet_length=packet->length();
if (packet_length+5+length > packet->alloced_length() &&
packet->realloc(packet_length+5+length))
return 1;
char *to=(char*) net_store_length((char*) packet->ptr()+packet_length,
(ulonglong) length);
memcpy(to,from,length);
packet->length((uint) (to+length-packet->ptr()));
return 0;
}
/* The following is only used at short, null terminated data */
bool
net_store_data(String *packet,const char *from)
{
uint length=(uint) strlen(from);
uint packet_length=packet->length();
if (packet_length+5+length > packet->alloced_length() &&
packet->realloc(packet_length+5+length))
return 1;
char *to=(char*) net_store_length((char*) packet->ptr()+packet_length,
length);
memcpy(to,from,length);
packet->length((uint) (to+length-packet->ptr()));
return 0;
}
bool
net_store_data(String *packet,uint32 from)
{
char buff[20];
return net_store_data(packet,(char*) buff,
(uint) (int10_to_str(from,buff,10)-buff));
}
bool
net_store_data(String *packet, longlong from)
{
char buff[22];
return net_store_data(packet,(char*) buff,
(uint) (longlong10_to_str(from,buff,10)-buff));
}
bool
net_store_data(String *packet,struct tm *tmp)
{
char buff[20];
sprintf(buff,"%04d-%02d-%02d %02d:%02d:%02d",
((int) (tmp->tm_year+1900)) % 10000,
(int) tmp->tm_mon+1,
(int) tmp->tm_mday,
(int) tmp->tm_hour,
(int) tmp->tm_min,
(int) tmp->tm_sec);
return net_store_data(packet,(char*) buff,19);
}
bool net_store_data(String* packet, I_List<i_string>* str_list)
{
char buf[256];
String tmp(buf, sizeof(buf), default_charset_info);
tmp.length(0);
I_List_iterator<i_string> it(*str_list);
i_string* s;
while ((s=it++))
{
if (tmp.length())
tmp.append(',');
tmp.append(s->ptr);
}
return net_store_data(packet, (char*)tmp.ptr(), tmp.length());
}
/*
** translate and store data; These are mainly used by the SHOW functions
*/
bool
net_store_data(String *packet,CONVERT *convert, const char *from,uint length)
{
if (convert)
return convert->store(packet, from, length);
return net_store_data(packet,from,length);
}
bool
net_store_data(String *packet, CONVERT *convert, const char *from)
{
uint length=(uint) strlen(from);
if (convert)
return convert->store(packet, from, length);
return net_store_data(packet,from,length);
}
/*
Function called by my_net_init() to set some check variables
*/
extern "C" {
void my_net_local_init(NET *net)
{
net->max_packet= (uint) global_system_variables.net_buffer_length;
net->read_timeout= (uint) global_system_variables.net_read_timeout;
net->write_timeout=(uint) global_system_variables.net_write_timeout;
net->retry_count= (uint) global_system_variables.net_retry_count;
net->max_packet_size= max(global_system_variables.net_buffer_length,
global_system_variables.max_allowed_packet);
}
}

View File

@ -1042,7 +1042,8 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part,
DBUG_RETURN(0); DBUG_RETURN(0);
if (maybe_null) if (maybe_null)
*str= (char) field->is_real_null(); // Set to 1 if null *str= (char) field->is_real_null(); // Set to 1 if null
field->get_key_image(str+maybe_null,key_part->part_length, key_part->image_type); field->get_key_image(str+maybe_null,key_part->part_length,
key_part->image_type);
if (!(tree=new SEL_ARG(field,str,str))) if (!(tree=new SEL_ARG(field,str,str)))
DBUG_RETURN(0); DBUG_RETURN(0);
@ -2284,8 +2285,10 @@ get_quick_keys(PARAM *param,QUICK_SELECT *quick,KEY_PART *key,
key_tree->min_flag : key_tree->min_flag | key_tree->max_flag; key_tree->min_flag : key_tree->min_flag | key_tree->max_flag;
} }
/* Ensure that some part of min_key and max_key are used. If not, /*
regard this as no lower/upper range */ Ensure that some part of min_key and max_key are used. If not,
regard this as no lower/upper range
*/
if ((flag & GEOM_FLAG) == 0) if ((flag & GEOM_FLAG) == 0)
{ {
if (tmp_min_key != param->min_key) if (tmp_min_key != param->min_key)
@ -2454,10 +2457,10 @@ int QUICK_SELECT::get_next()
if (range->flag & GEOM_FLAG) if (range->flag & GEOM_FLAG)
{ {
if ((result = file->index_read(record, if ((result = file->index_read(record,
(byte*) (range->min_key + ((range->flag & GEOM_FLAG) > 0)), (byte*) (range->min_key +1),
range->min_length, range->min_length,
(ha_rkey_function)(range->flag ^ GEOM_FLAG)))) (ha_rkey_function)(range->flag ^
GEOM_FLAG))))
{ {
if (result != HA_ERR_KEY_NOT_FOUND) if (result != HA_ERR_KEY_NOT_FOUND)
DBUG_RETURN(result); DBUG_RETURN(result);
@ -2478,7 +2481,8 @@ int QUICK_SELECT::get_next()
continue; continue;
} }
if ((result = file->index_read(record, if ((result = file->index_read(record,
(byte*) (range->min_key + ((range->flag & GEOM_FLAG) > 0)), (byte*) (range->min_key +
test(range->flag & GEOM_FLAG)),
range->min_length, range->min_length,
(range->flag & NEAR_MIN) ? (range->flag & NEAR_MIN) ?
HA_READ_AFTER_KEY: HA_READ_AFTER_KEY:
@ -2502,8 +2506,11 @@ int QUICK_SELECT::get_next()
} }
} }
/* compare if found key is over max-value */
/* Returns 0 if key <= range->max_key */ /*
Compare if found key is over max-value
Returns 0 if key <= range->max_key
*/
int QUICK_SELECT::cmp_next(QUICK_RANGE *range_arg) int QUICK_SELECT::cmp_next(QUICK_RANGE *range_arg)
{ {

View File

@ -55,7 +55,7 @@ public:
decimals=dec; max_length=float_length(dec); decimals=dec; max_length=float_length(dec);
} }
enum Item_result result_type () const { return REAL_RESULT; } enum Item_result result_type () const { return REAL_RESULT; }
enum_field_types field_type() const { return FIELD_TYPE_DOUBLE; } enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
void set(double nr) { value=nr; } void set(double nr) { value=nr; }
void set(longlong nr) { value=(double) nr; } void set(longlong nr) { value=(double) nr; }
void set(const char *str,uint length,CHARSET_INFO *cs) void set(const char *str,uint length,CHARSET_INFO *cs)
@ -73,7 +73,7 @@ public:
Item_proc_int(const char *name_par) :Item_proc(name_par) Item_proc_int(const char *name_par) :Item_proc(name_par)
{ max_length=11; } { max_length=11; }
enum Item_result result_type () const { return INT_RESULT; } enum Item_result result_type () const { return INT_RESULT; }
enum_field_types field_type() const { return FIELD_TYPE_LONG; } enum_field_types field_type() const { return MYSQL_TYPE_LONGLONG; }
void set(double nr) { value=(longlong) nr; } void set(double nr) { value=(longlong) nr; }
void set(longlong nr) { value=nr; } void set(longlong nr) { value=nr; }
void set(const char *str,uint length, CHARSET_INFO *cs) void set(const char *str,uint length, CHARSET_INFO *cs)
@ -91,7 +91,7 @@ public:
Item_proc_string(const char *name_par,uint length) :Item_proc(name_par) Item_proc_string(const char *name_par,uint length) :Item_proc(name_par)
{ this->max_length=length; } { this->max_length=length; }
enum Item_result result_type () const { return STRING_RESULT; } enum Item_result result_type () const { return STRING_RESULT; }
enum_field_types field_type() const { return FIELD_TYPE_STRING; } enum_field_types field_type() const { return MYSQL_TYPE_STRING; }
void set(double nr) { str_value.set(nr, 2, thd_charset()); } void set(double nr) { str_value.set(nr, 2, thd_charset()); }
void set(longlong nr) { str_value.set(nr, thd_charset()); } void set(longlong nr) { str_value.set(nr, thd_charset()); }
void set(const char *str, uint length, CHARSET_INFO *cs) void set(const char *str, uint length, CHARSET_INFO *cs)

989
sql/protocol.cc Normal file
View File

@ -0,0 +1,989 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/*
Low level functions for storing data to be send to the MySQL client
The actual communction is handled by the net_xxx functions in net_serv.cc
*/
#ifdef __GNUC__
#pragma implementation // gcc: Class implementation
#endif
#include "mysql_priv.h"
#include <stdarg.h>
#include <assert.h>
/* Send a error string to client */
void send_error(THD *thd, uint sql_errno, const char *err)
{
uint length;
char buff[MYSQL_ERRMSG_SIZE+2];
NET *net= &thd->net;
DBUG_ENTER("send_error");
DBUG_PRINT("enter",("sql_errno: %d err: %s", sql_errno,
err ? err : net->last_error[0] ?
net->last_error : "NULL"));
query_cache_abort(net);
thd->query_error= 1; // needed to catch query errors during replication
if (!err)
{
if (sql_errno)
err=ER(sql_errno);
else
{
if ((err=net->last_error)[0])
sql_errno=net->last_errno;
else
{
sql_errno=ER_UNKNOWN_ERROR;
err=ER(sql_errno); /* purecov: inspected */
}
}
}
if (net->vio == 0)
{
if (thd->bootstrap)
{
/* In bootstrap it's ok to print on stderr */
fprintf(stderr,"ERROR: %d %s\n",sql_errno,err);
}
DBUG_VOID_RETURN;
}
if (net->return_errno)
{ // new client code; Add errno before message
int2store(buff,sql_errno);
length= (uint) (strmake(buff+2,err,MYSQL_ERRMSG_SIZE-1) - buff);
err=buff;
}
else
{
length=(uint) strlen(err);
set_if_smaller(length,MYSQL_ERRMSG_SIZE-1);
}
VOID(net_write_command(net,(uchar) 255, "", 0, (char*) err,length));
thd->fatal_error=0; // Error message is given
thd->net.report_error= 0;
DBUG_VOID_RETURN;
}
/*
Send an error to the client when a connection is forced close
This is used by mysqld.cc, which doesn't have a THD
*/
void net_send_error(NET *net, uint sql_errno, const char *err)
{
char buff[2];
uint length;
DBUG_ENTER("send_net_error");
int2store(buff,sql_errno);
length=(uint) strlen(err);
set_if_smaller(length,MYSQL_ERRMSG_SIZE-1);
net_write_command(net,(uchar) 255, buff, 2, err, length);
DBUG_VOID_RETURN;
}
/*
Send a warning to the end user
SYNOPSIS
send_warning()
thd Thread handler
sql_errno Warning number (error message)
err Error string. If not set, use ER(sql_errno)
DESCRIPTION
Register the warning so that the user can get it with mysql_warnings()
Send an ok (+ warning count) to the end user.
*/
void send_warning(THD *thd, uint sql_errno, const char *err)
{
DBUG_ENTER("send_warning");
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, sql_errno,
err ? err : ER(sql_errno));
send_ok(thd);
DBUG_VOID_RETURN;
}
/*
Write error package and flush to client
It's a little too low level, but I don't want to use another buffer for
this
*/
void
net_printf(THD *thd, uint errcode, ...)
{
va_list args;
uint length,offset;
const char *format,*text_pos;
int head_length= NET_HEADER_SIZE;
NET *net= &thd->net;
DBUG_ENTER("net_printf");
DBUG_PRINT("enter",("message: %u",errcode));
thd->query_error= 1; // needed to catch query errors during replication
query_cache_abort(net); // Safety
va_start(args,errcode);
/*
The following is needed to make net_printf() work with 0 argument for
errorcode and use the argument after that as the format string. This
is useful for rare errors that are not worth the hassle to put in
errmsg.sys, but at the same time, the message is not fixed text
*/
if (errcode)
format= ER(errcode);
else
{
format=va_arg(args,char*);
errcode= ER_UNKNOWN_ERROR;
}
offset= net->return_errno ? 2 : 0;
text_pos=(char*) net->buff+head_length+offset+1;
(void) vsprintf(my_const_cast(char*) (text_pos),format,args);
length=(uint) strlen((char*) text_pos);
if (length >= sizeof(net->last_error))
length=sizeof(net->last_error)-1; /* purecov: inspected */
va_end(args);
if (net->vio == 0)
{
if (thd->bootstrap)
{
/* In bootstrap it's ok to print on stderr */
fprintf(stderr,"ERROR: %d %s\n",errcode,text_pos);
thd->fatal_error=1;
}
DBUG_VOID_RETURN;
}
int3store(net->buff,length+1+offset);
net->buff[3]= (net->compress) ? 0 : (uchar) (net->pkt_nr++);
net->buff[head_length]=(uchar) 255; // Error package
if (offset)
int2store(text_pos-2, errcode);
VOID(net_real_write(net,(char*) net->buff,length+head_length+1+offset));
thd->fatal_error=0; // Error message is given
DBUG_VOID_RETURN;
}
/*
Return ok to the client.
SYNOPSIS
send_ok()
thd Thread handler
affected_rows Number of rows changed by statement
id Auto_increment id for first row (if used)
message Message to send to the client (Used by mysql_status)
DESCRIPTION
The ok packet has the following structure
0 Marker (1 byte)
affected_rows Stored in 1-9 bytes
id Stored in 1-9 bytes
server_status Copy of thd->server_status; Can be used by client
to check if we are inside an transaction
New in 4.0 protocol
warning_count Stored in 2 bytes; New in 4.1 protocol
message Stored as packed length (1-9 bytes) + message
Is not stored if no message
If net->no_send_ok return without sending packet
*/
void
send_ok(THD *thd, ha_rows affected_rows, ulonglong id, const char *message)
{
NET *net= &thd->net;
if (net->no_send_ok || !net->vio) // hack for re-parsing queries
return;
char buff[MYSQL_ERRMSG_SIZE+10],*pos;
DBUG_ENTER("send_ok");
buff[0]=0; // No fields
pos=net_store_length(buff+1,(ulonglong) affected_rows);
pos=net_store_length(pos, (ulonglong) id);
if (thd->client_capabilities & CLIENT_PROTOCOL_41)
{
int2store(pos,thd->server_status);
pos+=2;
/* We can only return up to 65535 warnings in two bytes */
uint tmp= min(thd->total_warn_count, 65535);
int2store(pos, tmp);
pos+= 2;
}
else if (net->return_status) // For 4.0 protocol
{
int2store(pos,thd->server_status);
pos+=2;
}
if (message)
pos=net_store_data((char*) pos, message, strlen(message));
VOID(my_net_write(net,buff,(uint) (pos-buff)));
VOID(net_flush(net));
DBUG_VOID_RETURN;
}
/*
Send eof (= end of result set) to the client
SYNOPSIS
send_eof()
thd Thread handler
no_flush Set to 1 if there will be more data to the client,
like in send_fields().
DESCRIPTION
The eof packet has the following structure
254 Marker (1 byte)
warning_count Stored in 2 bytes; New in 4.1 protocol
status_flag Stored in 2 bytes;
For flags like SERVER_STATUS_MORE_RESULTS
Note that the warning count will not be sent if 'no_flush' is set as
we don't want to report the warning count until all data is sent to the
client.
*/
void
send_eof(THD *thd, bool no_flush)
{
static char eof_buff[1]= { (char) 254 }; /* Marker for end of fields */
NET *net= &thd->net;
DBUG_ENTER("send_eof");
if (net->vio != 0)
{
if (!no_flush && (thd->client_capabilities & CLIENT_PROTOCOL_41))
{
uchar buff[5];
uint tmp= min(thd->total_warn_count, 65535);
buff[0]=254;
int2store(buff+1, tmp);
int2store(buff+3, 0); // No flags yet
VOID(my_net_write(net,(char*) buff,5));
VOID(net_flush(net));
}
else
{
VOID(my_net_write(net,eof_buff,1));
if (!no_flush)
VOID(net_flush(net));
}
}
DBUG_VOID_RETURN;
}
/****************************************************************************
Store a field length in logical packet
This is used to code the string length for normal protocol
****************************************************************************/
char *
net_store_length(char *pkg, ulonglong length)
{
uchar *packet=(uchar*) pkg;
if (length < LL(251))
{
*packet=(uchar) length;
return (char*) packet+1;
}
/* 251 is reserved for NULL */
if (length < LL(65536))
{
*packet++=252;
int2store(packet,(uint) length);
return (char*) packet+2;
}
if (length < LL(16777216))
{
*packet++=253;
int3store(packet,(ulong) length);
return (char*) packet+3;
}
*packet++=254;
int8store(packet,length);
return (char*) packet+9;
}
/*
Faster net_store_length when we know length is a 32 bit integer
*/
char *net_store_length(char *pkg, uint length)
{
uchar *packet=(uchar*) pkg;
if (length < 251)
{
*packet=(uchar) length;
return (char*) packet+1;
}
*packet++=252;
int2store(packet,(uint) length);
return (char*) packet+2;
}
/*
Used internally for storing strings in packet
*/
static bool net_store_data(String *packet, const char *from, uint length)
{
ulong packet_length=packet->length();
if (packet_length+5+length > packet->alloced_length() &&
packet->realloc(packet_length+5+length))
return 1;
char *to=(char*) net_store_length((char*) packet->ptr()+packet_length,
(ulonglong) length);
memcpy(to,from,length);
packet->length((uint) (to+length-packet->ptr()));
return 0;
}
/****************************************************************************
Functions used by the protocol functions (like send_ok) to store strings
and numbers in the header result packet.
****************************************************************************/
/* The following will only be used for short strings < 65K */
char *net_store_data(char *to,const char *from, uint length)
{
to=net_store_length(to,length);
memcpy(to,from,length);
return to+length;
}
char *net_store_data(char *to,int32 from)
{
char buff[20];
uint length=(uint) (int10_to_str(from,buff,10)-buff);
to=net_store_length(to,length);
memcpy(to,buff,length);
return to+length;
}
char *net_store_data(char *to,longlong from)
{
char buff[22];
uint length=(uint) (longlong10_to_str(from,buff,10)-buff);
to=net_store_length(to,length);
memcpy(to,buff,length);
return to+length;
}
/*
Function called by my_net_init() to set some check variables
*/
extern "C" {
void my_net_local_init(NET *net)
{
net->max_packet= (uint) global_system_variables.net_buffer_length;
net->read_timeout= (uint) global_system_variables.net_read_timeout;
net->write_timeout=(uint) global_system_variables.net_write_timeout;
net->retry_count= (uint) global_system_variables.net_retry_count;
net->max_packet_size= max(global_system_variables.net_buffer_length,
global_system_variables.max_allowed_packet);
}
}
/*****************************************************************************
Default Protocol functions
*****************************************************************************/
void Protocol::init(THD *thd_arg)
{
thd=thd_arg;
convert=thd->variables.convert_set;
packet= &thd->packet;
#ifndef DEBUG_OFF
field_types= 0;
#endif
}
/*
Send name and type of result to client.
SYNOPSIS
send_fields()
THD Thread data object
list List of items to send to client
convert object used to convertation to another character set
flag Bit mask with the following functions:
1 send number of rows
2 send default values
DESCRIPTION
Sum fields has table name empty and field_name.
Uses send_fields_convert() and send_fields() depending on
if we have an active character set convert or not.
RETURN VALUES
0 ok
1 Error (Note that in this case the error is not sent to the client)
*/
bool Protocol::send_fields(List<Item> *list, uint flag)
{
List_iterator_fast<Item> it(*list);
Item *item;
char buff[80];
String tmp((char*) buff,sizeof(buff),default_charset_info);
Protocol_simple prot(thd);
String *packet= prot.storage_packet();
DBUG_ENTER("send_fields");
if (flag & 1)
{ // Packet with number of elements
char *pos=net_store_length(buff, (uint) list->elements);
(void) my_net_write(&thd->net, buff,(uint) (pos-buff));
}
#ifndef DEBUG_OFF
field_types= (enum_field_types*) thd->alloc(sizeof(field_types) *
list->elements);
uint count= 0;
#endif
while ((item=it++))
{
char *pos;
Send_field field;
item->make_field(&field);
prot.prepare_for_resend();
if (thd->client_capabilities & CLIENT_PROTOCOL_41)
{
if (prot.store(field.db_name, (uint) strlen(field.db_name)) ||
prot.store(field.table_name, (uint) strlen(field.table_name)) ||
prot.store(field.org_table_name,
(uint) strlen(field.org_table_name)) ||
prot.store(field.col_name, (uint) strlen(field.col_name)) ||
prot.store(field.org_col_name, (uint) strlen(field.org_col_name)))
goto err;
}
else
{
if (prot.store(field.table_name, (uint) strlen(field.table_name)) ||
prot.store(field.col_name, (uint) strlen(field.col_name)))
goto err;
}
if (packet->realloc(packet->length()+10))
goto err;
pos= (char*) packet->ptr()+packet->length();
#ifdef TO_BE_DELETED_IN_6
if (!(thd->client_capabilities & CLIENT_LONG_FLAG))
{
packet->length(packet->length()+9);
pos[0]=3; int3store(pos+1,field.length);
pos[4]=1; pos[5]=field.type;
pos[6]=2; pos[7]=(char) field.flags; pos[8]= (char) field.decimals;
}
else
#endif
{
packet->length(packet->length()+10);
pos[0]=3; int3store(pos+1,field.length);
pos[4]=1; pos[5]=field.type;
pos[6]=3; int2store(pos+7,field.flags); pos[9]= (char) field.decimals;
}
if (flag & 2)
item->send(&prot, &tmp); // Send default value
if (prot.write())
break; /* purecov: inspected */
#ifndef DEBUG_OFF
field_types[count++]= field.type;
#endif
}
send_eof(thd);
DBUG_RETURN(prepare_for_send(list));
err:
send_error(thd,ER_OUT_OF_RESOURCES); /* purecov: inspected */
DBUG_RETURN(1); /* purecov: inspected */
}
bool Protocol::write()
{
DBUG_ENTER("Protocol::write");
DBUG_RETURN(my_net_write(&thd->net, packet->ptr(), packet->length()));
}
/*
Send \0 end terminated string
SYNOPSIS
store()
from NullS or \0 terminated string
NOTES
In most cases one should use store(from, length) instead of this function
RETURN VALUES
0 ok
1 error
*/
bool Protocol::store(const char *from)
{
if (!from)
return store_null();
uint length= strlen(from);
return store(from, length);
}
/*
Send a set of strings as one long string with ',' in between
*/
bool Protocol::store(I_List<i_string>* str_list)
{
char buf[256];
String tmp(buf, sizeof(buf), default_charset_info);
uint32 len;
I_List_iterator<i_string> it(*str_list);
i_string* s;
tmp.length(0);
while ((s=it++))
{
tmp.append(s->ptr);
tmp.append(',');
}
if ((len= tmp.length()))
len--; // Remove last ','
return store((char*) tmp.ptr(), len);
}
/****************************************************************************
Functions to handle the simple (default) protocol where everything is
This protocol is the one that is used by default between the MySQL server
and client when you are not using prepared statements.
All data are sent as 'packed-string-length' followed by 'string-data'
****************************************************************************/
void Protocol_simple::prepare_for_resend()
{
packet->length(0);
#ifndef DEBUG_OFF
field_pos= 0;
#endif
}
bool Protocol_simple::store_null()
{
#ifndef DEBUG_OFF
field_pos++;
#endif
char buff[1];
buff[0]= 251;
return packet->append(buff, sizeof(buff), PACKET_BUFFET_EXTRA_ALLOC);
}
bool Protocol_simple::store(const char *from, uint length)
{
#ifndef DEBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_DECIMAL ||
(field_types[field_pos] >= MYSQL_TYPE_ENUM &&
field_types[field_pos] <= MYSQL_TYPE_GEOMETRY));
field_pos++;
#endif
if (convert)
return convert->store(packet, from, length);
return net_store_data(packet, from, length);
}
bool Protocol_simple::store_tiny(longlong from)
{
#ifndef DEBUG_OFF
DBUG_ASSERT(field_types == 0 || field_types[field_pos++] == MYSQL_TYPE_TINY);
#endif
char buff[20];
return net_store_data(packet,(char*) buff,
(uint) (int10_to_str((int) from,buff, -10)-buff));
}
bool Protocol_simple::store_short(longlong from)
{
#ifndef DEBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos++] == MYSQL_TYPE_SHORT);
#endif
char buff[20];
return net_store_data(packet,(char*) buff,
(uint) (int10_to_str((int) from,buff, -10)-buff));
}
bool Protocol_simple::store_long(longlong from)
{
#ifndef DEBUG_OFF
DBUG_ASSERT(field_types == 0 || field_types[field_pos++] == MYSQL_TYPE_LONG);
#endif
char buff[20];
return net_store_data(packet,(char*) buff,
(uint) (int10_to_str((int) from,buff, -10)-buff));
}
bool Protocol_simple::store_longlong(longlong from, bool unsigned_flag)
{
#ifndef DEBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos++] == MYSQL_TYPE_LONGLONG);
#endif
char buff[22];
return net_store_data(packet,(char*) buff,
(uint) (longlong10_to_str(from,buff,
unsigned_flag ? 10 : -10)-
buff));
}
bool Protocol_simple::store(float from, uint32 decimals, String *buffer)
{
#ifndef DEBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos++] == MYSQL_TYPE_FLOAT);
#endif
buffer->set((double) from, decimals, thd->thd_charset);
return net_store_data(packet,(char*) buffer->ptr(), buffer->length());
}
bool Protocol_simple::store(double from, uint32 decimals, String *buffer)
{
#ifndef DEBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos++] == MYSQL_TYPE_DOUBLE);
#endif
buffer->set(from, decimals, thd->thd_charset);
return net_store_data(packet,(char*) buffer->ptr(), buffer->length());
}
bool Protocol_simple::store(Field *field)
{
if (field->is_null())
return store_null();
#ifndef DEBUG_OFF
field_pos++;
#endif
char buff[MAX_FIELD_WIDTH];
String tmp(buff,sizeof(buff),default_charset_info);
field->val_str(&tmp,&tmp);
if (convert)
return convert->store(packet, tmp.ptr(), tmp.length());
return net_store_data(packet, tmp.ptr(), tmp.length());
}
bool Protocol_simple::store(TIME *tm)
{
#ifndef DEBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_DATETIME ||
field_types[field_pos] == MYSQL_TYPE_TIMESTAMP);
field_pos++;
#endif
char buff[40];
uint length;
length= my_sprintf(buff,(buff, "%04d-%02d-%02d %02d:%02d:%02d",
(int) tm->year,
(int) tm->month,
(int) tm->day,
(int) tm->hour,
(int) tm->minute,
(int) tm->second));
return net_store_data(packet, (char*) buff, length);
}
bool Protocol_simple::store_date(TIME *tm)
{
#ifndef DEBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos++] == MYSQL_TYPE_DATE);
#endif
char buff[40];
uint length;
length= my_sprintf(buff,(buff, "%04d-%02d-%02d",
(int) tm->year,
(int) tm->month,
(int) tm->day));
return net_store_data(packet, (char*) buff, length);
}
bool Protocol_simple::store_time(TIME *tm)
{
#ifndef DEBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos++] == MYSQL_TYPE_TIME);
#endif
char buff[40];
uint length;
length= my_sprintf(buff,(buff, "%s%02ld:%02d:%02d",
tm->neg ? "-" : "",
(long) tm->day*3600L+(long) tm->hour,
(int) tm->minute,
(int) tm->second));
return net_store_data(packet, (char*) buff, length);
}
/****************************************************************************
Functions to handle the binary protocol used with prepared statements
****************************************************************************/
bool Protocol_prep::prepare_for_send(List<Item> *item_list)
{
field_count=item_list->elements;
bit_fields= (field_count+3)/8;
if (packet->alloc(bit_fields))
return 1;
/* prepare_for_resend will be called after this one */
return 0;
}
void Protocol_prep::prepare_for_resend()
{
packet->length(bit_fields);
bzero((char*) packet->ptr()+1, bit_fields-1);
packet[0]=1; // Marker for ok packet
field_pos=0;
}
bool Protocol_prep::store(const char *from,uint length)
{
#ifndef DEBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_DECIMAL ||
(field_types[field_pos] >= MYSQL_TYPE_ENUM &&
field_types[field_pos] <= MYSQL_TYPE_GEOMETRY));
#endif
field_pos++;
if (convert)
return convert->store(packet, from, length);
return net_store_data(packet, from, length);
}
bool Protocol_prep::store_null()
{
uint offset=(field_pos+2)/8, bit= (1 << ((field_pos+2) & 7));
/* Room for this as it's allocated in prepare_for_send */
char *to= (char*) packet->ptr()+offset;
*to= (char) ((uchar) *to | (uchar) bit);
field_pos++;
return 0;
}
bool Protocol_prep::store_tiny(longlong from)
{
#ifndef DEBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_TINY);
#endif
char buff[1];
field_pos++;
buff[0]= (uchar) from;
return packet->append(buff, sizeof(buff), PACKET_BUFFET_EXTRA_ALLOC);
}
bool Protocol_prep::store_short(longlong from)
{
#ifndef DEBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_SHORT);
#endif
field_pos++;
char *to= packet->prep_append(2, PACKET_BUFFET_EXTRA_ALLOC);
if (!to)
return 1;
int2store(to, (int) from);
return 0;
}
bool Protocol_prep::store_long(longlong from)
{
#ifndef DEBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_LONG);
#endif
field_pos++;
char *to= packet->prep_append(4, PACKET_BUFFET_EXTRA_ALLOC);
if (!to)
return 1;
int4store(to, from);
return 0;
}
bool Protocol_prep::store_longlong(longlong from, bool unsigned_flag)
{
#ifndef DEBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_LONGLONG);
#endif
field_pos++;
char *to= packet->prep_append(8, PACKET_BUFFET_EXTRA_ALLOC);
if (!to)
return 1;
int8store(to, from);
return 0;
}
bool Protocol_prep::store(float from, uint32 decimals, String *buffer)
{
#ifndef DEBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_FLOAT);
#endif
field_pos++;
char *to= packet->prep_append(4, PACKET_BUFFET_EXTRA_ALLOC);
if (!to)
return 1;
float4store(to, from);
return 0;
}
bool Protocol_prep::store(double from, uint32 decimals, String *buffer)
{
#ifndef DEBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_DOUBLE);
#endif
field_pos++;
char *to= packet->prep_append(8, PACKET_BUFFET_EXTRA_ALLOC);
if (!to)
return 1;
float8store(to, from);
return 0;
}
bool Protocol_prep::store(Field *field)
{
/*
We should not count up field_pos here as send_binary() will call another
protocol function to do this for us
*/
if (field->is_null())
return store_null();
return field->send_binary(this);
}
bool Protocol_prep::store(TIME *tm)
{
#ifndef DEBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_DATETIME ||
field_types[field_pos] == MYSQL_TYPE_DATE ||
field_types[field_pos] == MYSQL_TYPE_TIMESTAMP);
#endif
char buff[12],*pos;
uint length;
field_pos++;
pos= buff+1;
int2store(pos, tm->year);
int2store(pos+2, tm->month);
int2store(pos+3, tm->day);
int2store(pos+4, tm->hour);
int2store(pos+5, tm->minute);
int2store(pos+6, tm->second);
int4store(pos+7, tm->second_part);
if (tm->second_part)
length=11;
else if (tm->hour || tm->minute || tm->second)
length=7;
else if (tm->year || tm->month || tm->day)
length=4;
else
length=0;
buff[0]=(char) length; // Length is stored first
return packet->append(buff, length+1, PACKET_BUFFET_EXTRA_ALLOC);
}
bool Protocol_prep::store_date(TIME *tm)
{
tm->hour= tm->minute= tm->second=0;
tm->second_part= 0;
return Protocol_prep::store(tm);
}
bool Protocol_prep::store_time(TIME *tm)
{
#ifndef DEBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_TIME);
#endif
char buff[15],*pos;
uint length;
field_pos++;
pos= buff+1;
pos[0]= tm->neg ? 1 : 0;
int4store(pos+1, tm->day);
int2store(pos+5, tm->hour);
int2store(pos+7, tm->minute);
int2store(pos+9, tm->second);
int4store(pos+11, tm->second_part);
if (tm->second_part)
length=14;
else if (tm->hour || tm->minute || tm->second || tm->day)
length=10;
else
length=0;
buff[0]=(char) length; // Length is stored first
return packet->append(buff, length+1, PACKET_BUFFET_EXTRA_ALLOC);
}

131
sql/protocol.h Normal file
View File

@ -0,0 +1,131 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#ifdef __GNUC__
#pragma interface /* gcc class implementation */
#endif
#define PACKET_BUFFET_EXTRA_ALLOC 1024
class CONVERT;
class i_string;
class THD;
class Protocol
{
protected:
THD *thd;
String *packet;
uint field_pos;
#ifndef DEBUG_OFF
enum enum_field_types *field_types;
#endif
public:
CONVERT *convert;
Protocol() {}
Protocol(THD *thd) { init(thd); }
void init(THD* thd);
bool send_fields(List<Item> *list, uint flag);
bool store(I_List<i_string> *str_list);
bool store(const char *from);
String *storage_packet() { return packet; }
inline void free() { packet->free(); }
bool write();
inline bool store(uint32 from)
{ return store_long((longlong) from); }
inline bool store(longlong from)
{ return store_longlong((longlong) from, 0); }
inline bool store(ulonglong from)
{ return store_longlong((longlong) from, 1); }
virtual bool prepare_for_send(List<Item> *item_list) { return 0;}
virtual void prepare_for_resend()=0;
virtual bool store_null()=0;
virtual bool store_tiny(longlong from)=0;
virtual bool store_short(longlong from)=0;
virtual bool store_long(longlong from)=0;
virtual bool store_longlong(longlong from, bool unsigned_flag)=0;
virtual bool store(const char *from, uint length)=0;
virtual bool store(float from, uint32 decimals, String *buffer)=0;
virtual bool store(double from, uint32 decimals, String *buffer)=0;
virtual bool store(TIME *time)=0;
virtual bool store_date(TIME *time)=0;
virtual bool store_time(TIME *time)=0;
virtual bool store(Field *field)=0;
};
/* Class used for the old (MySQL 4.0 protocol) */
class Protocol_simple :public Protocol
{
public:
Protocol_simple() {}
Protocol_simple(THD *thd) :Protocol(thd) {}
virtual void prepare_for_resend();
virtual bool store_null();
virtual bool store_tiny(longlong from);
virtual bool store_short(longlong from);
virtual bool store_long(longlong from);
virtual bool store_longlong(longlong from, bool unsigned_flag);
virtual bool store(const char *from, uint length);
virtual bool store(TIME *time);
virtual bool store_date(TIME *time);
virtual bool store_time(TIME *time);
virtual bool store(float nr, uint32 decimals, String *buffer);
virtual bool store(double from, uint32 decimals, String *buffer);
virtual bool store(Field *field);
};
class Protocol_prep :public Protocol
{
private:
uint field_count, bit_fields;
public:
Protocol_prep() {}
Protocol_prep(THD *thd) :Protocol(thd) {}
virtual bool prepare_for_send(List<Item> *item_list);
virtual void prepare_for_resend();
virtual bool store_null();
virtual bool store_tiny(longlong from);
virtual bool store_short(longlong from);
virtual bool store_long(longlong from);
virtual bool store_longlong(longlong from, bool unsigned_flag);
virtual bool store(const char *from,uint length);
virtual bool store(TIME *time);
virtual bool store_date(TIME *time);
virtual bool store_time(TIME *time);
virtual bool store(float nr, uint32 decimals, String *buffer);
virtual bool store(double from, uint32 decimals, String *buffer);
virtual bool store(Field *field);
};
void send_warning(THD *thd, uint sql_errno, const char *err=0);
void net_printf(THD *thd,uint sql_errno, ...);
void send_ok(THD *thd, ha_rows affected_rows=0L, ulonglong id=0L,
const char *info=0);
void send_eof(THD *thd, bool no_flush=0);
void net_send_error(NET *net, uint sql_errno, const char *err);
char *net_store_length(char *packet,ulonglong length);
char *net_store_length(char *packet,uint length);
char *net_store_data(char *to,const char *from, uint length);
char *net_store_data(char *to,int32 from);
char *net_store_data(char *to,longlong from);

View File

@ -416,6 +416,7 @@ static Slave_log_event* find_slave_event(IO_CACHE* log,
int show_new_master(THD* thd) int show_new_master(THD* thd)
{ {
Protocol *protocol= thd->protocol;
DBUG_ENTER("show_new_master"); DBUG_ENTER("show_new_master");
List<Item> field_list; List<Item> field_list;
char errmsg[SLAVE_ERRMSG_SIZE]; char errmsg[SLAVE_ERRMSG_SIZE];
@ -431,15 +432,15 @@ int show_new_master(THD* thd)
} }
else else
{ {
String* packet = &thd->packet;
field_list.push_back(new Item_empty_string("Log_name", 20)); field_list.push_back(new Item_empty_string("Log_name", 20));
field_list.push_back(new Item_empty_string("Log_pos", 20)); field_list.push_back(new Item_return_int("Log_pos", 10,
if (send_fields(thd, field_list, 1)) MYSQL_TYPE_LONGLONG));
if (protocol->send_fields(&field_list, 1))
DBUG_RETURN(-1); DBUG_RETURN(-1);
packet->length(0); protocol->prepare_for_resend();
net_store_data(packet, lex_mi->log_file_name); protocol->store(lex_mi->log_file_name);
net_store_data(packet, (longlong)lex_mi->pos); protocol->store((ulonglong) lex_mi->pos);
if (my_net_write(&thd->net, packet->ptr(), packet->length())) if (protocol->write())
DBUG_RETURN(-1); DBUG_RETURN(-1);
send_eof(thd); send_eof(thd);
DBUG_RETURN(0); DBUG_RETURN(0);
@ -580,21 +581,24 @@ int show_slave_hosts(THD* thd)
{ {
List<Item> field_list; List<Item> field_list;
NET* net = &thd->net; NET* net = &thd->net;
String* packet = &thd->packet; Protocol *protocol= thd->protocol;
DBUG_ENTER("show_slave_hosts"); DBUG_ENTER("show_slave_hosts");
field_list.push_back(new Item_empty_string("Server_id", 20)); field_list.push_back(new Item_return_int("Server_id", 10,
MYSQL_TYPE_LONG));
field_list.push_back(new Item_empty_string("Host", 20)); field_list.push_back(new Item_empty_string("Host", 20));
if (opt_show_slave_auth_info) if (opt_show_slave_auth_info)
{ {
field_list.push_back(new Item_empty_string("User",20)); field_list.push_back(new Item_empty_string("User",20));
field_list.push_back(new Item_empty_string("Password",20)); field_list.push_back(new Item_empty_string("Password",20));
} }
field_list.push_back(new Item_empty_string("Port",20)); field_list.push_back(new Item_return_int("Port", 7, MYSQL_TYPE_LONG));
field_list.push_back(new Item_empty_string("Rpl_recovery_rank", 20)); field_list.push_back(new Item_return_int("Rpl_recovery_rank", 7,
field_list.push_back(new Item_empty_string("Master_id", 20)); MYSQL_TYPE_LONG));
field_list.push_back(new Item_return_int("Master_id", 10,
MYSQL_TYPE_LONG));
if (send_fields(thd, field_list, 1)) if (protocol->send_fields(&field_list, 1))
DBUG_RETURN(-1); DBUG_RETURN(-1);
pthread_mutex_lock(&LOCK_slave_list); pthread_mutex_lock(&LOCK_slave_list);
@ -602,18 +606,18 @@ int show_slave_hosts(THD* thd)
for (uint i = 0; i < slave_list.records; ++i) for (uint i = 0; i < slave_list.records; ++i)
{ {
SLAVE_INFO* si = (SLAVE_INFO*) hash_element(&slave_list, i); SLAVE_INFO* si = (SLAVE_INFO*) hash_element(&slave_list, i);
packet->length(0); protocol->prepare_for_resend();
net_store_data(packet, si->server_id); protocol->store((uint32) si->server_id);
net_store_data(packet, si->host); protocol->store(si->host);
if (opt_show_slave_auth_info) if (opt_show_slave_auth_info)
{ {
net_store_data(packet, si->user); protocol->store(si->user);
net_store_data(packet, si->password); protocol->store(si->password);
} }
net_store_data(packet, (uint32) si->port); protocol->store((uint32) si->port);
net_store_data(packet, si->rpl_recovery_rank); protocol->store((uint32) si->rpl_recovery_rank);
net_store_data(packet, si->master_id); protocol->store((uint32) si->master_id);
if (my_net_write(net, (char*)packet->ptr(), packet->length())) if (protocol->write())
{ {
pthread_mutex_unlock(&LOCK_slave_list); pthread_mutex_unlock(&LOCK_slave_list);
DBUG_RETURN(-1); DBUG_RETURN(-1);

View File

@ -992,8 +992,12 @@ bool sys_var_thd_conv_charset::update(THD *thd, set_var *var)
if (var->type == OPT_GLOBAL) if (var->type == OPT_GLOBAL)
global_system_variables.convert_set= var->save_result.convert; global_system_variables.convert_set= var->save_result.convert;
else else
{
thd->lex.convert_set= thd->variables.convert_set= thd->lex.convert_set= thd->variables.convert_set=
var->save_result.convert; var->save_result.convert;
thd->protocol_simple.init(thd);
thd->protocol_prep.init(thd);
}
return 0; return 0;
} }

View File

@ -1513,42 +1513,38 @@ err:
*****************************************************************************/ *****************************************************************************/
int register_slave_on_master(MYSQL* mysql) int register_slave_on_master(MYSQL* mysql)
{ {
String packet; char buf[1024], *pos= buf;
char buf[4]; uint report_host_len, report_user_len=0, report_password_len=0;
if (!report_host) if (!report_host)
return 0; return 0;
report_host_len= strlen(report_host);
int4store(buf, server_id);
packet.append(buf, 4);
net_store_data(&packet, report_host);
if (report_user) if (report_user)
net_store_data(&packet, report_user); report_user_len= strlen(report_user);
else
packet.append((char)0);
if (report_password) if (report_password)
net_store_data(&packet, report_user); report_password_len= strlen(report_password);
else /* 30 is a good safety margin */
packet.append((char)0); if (report_host_len + report_user_len + report_password_len + 30 >
sizeof(buf))
return 0; // safety
int2store(buf, (uint16)report_port); int4store(pos, server_id); pos+= 4;
packet.append(buf, 2); pos= net_store_data(pos, report_host, report_host_len);
int4store(buf, rpl_recovery_rank); pos= net_store_data(pos, report_user, report_user_len);
packet.append(buf, 4); pos= net_store_data(pos, report_password, report_password_len);
int4store(buf, 0); /* tell the master will fill in master_id */ int2store(pos, (uint16) report_port); pos+= 2;
packet.append(buf, 4); int4store(pos, rpl_recovery_rank); pos+= 4;
/* The master will fill in master_id */
int4store(pos, 0); pos+= 4;
if (mc_simple_command(mysql, COM_REGISTER_SLAVE, (char*)packet.ptr(), if (mc_simple_command(mysql, COM_REGISTER_SLAVE, (char*) buf,
packet.length(), 0)) (uint) (pos- buf), 0))
{ {
sql_print_error("Error on COM_REGISTER_SLAVE: %d '%s'", sql_print_error("Error on COM_REGISTER_SLAVE: %d '%s'",
mc_mysql_errno(mysql), mc_mysql_errno(mysql),
mc_mysql_error(mysql)); mc_mysql_error(mysql));
return 1; return 1;
} }
return 0; return 0;
} }
@ -1560,60 +1556,69 @@ int register_slave_on_master(MYSQL* mysql)
int show_master_info(THD* thd, MASTER_INFO* mi) int show_master_info(THD* thd, MASTER_INFO* mi)
{ {
// TODO: fix this for multi-master // TODO: fix this for multi-master
DBUG_ENTER("show_master_info");
List<Item> field_list; List<Item> field_list;
Protocol *protocol= thd->protocol;
DBUG_ENTER("show_master_info");
field_list.push_back(new Item_empty_string("Master_Host", field_list.push_back(new Item_empty_string("Master_Host",
sizeof(mi->host))); sizeof(mi->host)));
field_list.push_back(new Item_empty_string("Master_User", field_list.push_back(new Item_empty_string("Master_User",
sizeof(mi->user))); sizeof(mi->user)));
field_list.push_back(new Item_empty_string("Master_Port", 6)); field_list.push_back(new Item_return_int("Master_Port", 7,
field_list.push_back(new Item_empty_string("Connect_retry", 6)); MYSQL_TYPE_LONG));
field_list.push_back(new Item_return_int("Connect_retry", 10,
MYSQL_TYPE_LONG));
field_list.push_back(new Item_empty_string("Master_Log_File", field_list.push_back(new Item_empty_string("Master_Log_File",
FN_REFLEN)); FN_REFLEN));
field_list.push_back(new Item_empty_string("Read_Master_Log_Pos", 12)); field_list.push_back(new Item_return_int("Read_Master_Log_Pos", 10,
MYSQL_TYPE_LONGLONG));
field_list.push_back(new Item_empty_string("Relay_Log_File", field_list.push_back(new Item_empty_string("Relay_Log_File",
FN_REFLEN)); FN_REFLEN));
field_list.push_back(new Item_empty_string("Relay_Log_Pos", 12)); field_list.push_back(new Item_return_int("Relay_Log_Pos", 10,
MYSQL_TYPE_LONGLONG));
field_list.push_back(new Item_empty_string("Relay_Master_Log_File", field_list.push_back(new Item_empty_string("Relay_Master_Log_File",
FN_REFLEN)); FN_REFLEN));
field_list.push_back(new Item_empty_string("Slave_IO_Running", 3)); field_list.push_back(new Item_empty_string("Slave_IO_Running", 3));
field_list.push_back(new Item_empty_string("Slave_SQL_Running", 3)); field_list.push_back(new Item_empty_string("Slave_SQL_Running", 3));
field_list.push_back(new Item_empty_string("Replicate_do_db", 20)); field_list.push_back(new Item_empty_string("Replicate_do_db", 20));
field_list.push_back(new Item_empty_string("Replicate_ignore_db", 20)); field_list.push_back(new Item_empty_string("Replicate_ignore_db", 20));
field_list.push_back(new Item_empty_string("Last_errno", 4)); field_list.push_back(new Item_return_int("Last_errno", 4, MYSQL_TYPE_LONG));
field_list.push_back(new Item_empty_string("Last_error", 20)); field_list.push_back(new Item_empty_string("Last_error", 20));
field_list.push_back(new Item_empty_string("Skip_counter", 12)); field_list.push_back(new Item_return_int("Skip_counter", 10,
field_list.push_back(new Item_empty_string("Exec_master_log_pos", 12)); MYSQL_TYPE_LONG));
field_list.push_back(new Item_empty_string("Relay_log_space", 12)); field_list.push_back(new Item_return_int("Exec_master_log_pos", 10,
if (send_fields(thd, field_list, 1)) MYSQL_TYPE_LONGLONG));
field_list.push_back(new Item_return_int("Relay_log_space", 10,
MYSQL_TYPE_LONGLONG));
if (protocol->send_fields(&field_list, 1))
DBUG_RETURN(-1); DBUG_RETURN(-1);
if (mi->host[0]) if (mi->host[0])
{ {
String *packet= &thd->packet; String *packet= &thd->packet;
packet->length(0); protocol->prepare_for_resend();
pthread_mutex_lock(&mi->data_lock); pthread_mutex_lock(&mi->data_lock);
pthread_mutex_lock(&mi->rli.data_lock); pthread_mutex_lock(&mi->rli.data_lock);
net_store_data(packet, mi->host); protocol->store(mi->host);
net_store_data(packet, mi->user); protocol->store(mi->user);
net_store_data(packet, (uint32) mi->port); protocol->store((uint32) mi->port);
net_store_data(packet, (uint32) mi->connect_retry); protocol->store((uint32) mi->connect_retry);
net_store_data(packet, mi->master_log_name); protocol->store(mi->master_log_name);
net_store_data(packet, (longlong) mi->master_log_pos); protocol->store((ulonglong) mi->master_log_pos);
net_store_data(packet, mi->rli.relay_log_name + protocol->store(mi->rli.relay_log_name +
dirname_length(mi->rli.relay_log_name)); dirname_length(mi->rli.relay_log_name));
net_store_data(packet, (longlong) mi->rli.relay_log_pos); protocol->store((ulonglong) mi->rli.relay_log_pos);
net_store_data(packet, mi->rli.master_log_name); protocol->store(mi->rli.master_log_name);
net_store_data(packet, mi->slave_running ? "Yes":"No"); protocol->store(mi->slave_running ? "Yes":"No");
net_store_data(packet, mi->rli.slave_running ? "Yes":"No"); protocol->store(mi->rli.slave_running ? "Yes":"No");
net_store_data(packet, &replicate_do_db); protocol->store(&replicate_do_db);
net_store_data(packet, &replicate_ignore_db); protocol->store(&replicate_ignore_db);
net_store_data(packet, (uint32)mi->rli.last_slave_errno); protocol->store((uint32) mi->rli.last_slave_errno);
net_store_data(packet, mi->rli.last_slave_error); protocol->store(mi->rli.last_slave_error);
net_store_data(packet, mi->rli.slave_skip_counter); protocol->store((uint32) mi->rli.slave_skip_counter);
net_store_data(packet, (longlong) mi->rli.master_log_pos); protocol->store((ulonglong) mi->rli.master_log_pos);
net_store_data(packet, (longlong) mi->rli.log_space_total); protocol->store((ulonglong) mi->rli.log_space_total);
pthread_mutex_unlock(&mi->rli.data_lock); pthread_mutex_unlock(&mi->rli.data_lock);
pthread_mutex_unlock(&mi->data_lock); pthread_mutex_unlock(&mi->data_lock);
@ -1640,8 +1645,7 @@ bool flush_master_info(MASTER_INFO* mi)
my_b_printf(file, "%s\n%s\n%s\n%s\n%s\n%d\n%d\n", my_b_printf(file, "%s\n%s\n%s\n%s\n%s\n%d\n%d\n",
mi->master_log_name, llstr(mi->master_log_pos, lbuf), mi->master_log_name, llstr(mi->master_log_pos, lbuf),
mi->host, mi->user, mi->host, mi->user,
mi->password, mi->port, mi->connect_retry mi->password, mi->port, mi->connect_retry);
);
flush_io_cache(file); flush_io_cache(file);
DBUG_RETURN(0); DBUG_RETURN(0);
} }

View File

@ -2776,6 +2776,7 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
int error = 0; int error = 0;
ACL_USER *acl_user; ACL_DB *acl_db; ACL_USER *acl_user; ACL_DB *acl_db;
char buff[1024]; char buff[1024];
Protocol *protocol= thd->protocol;
DBUG_ENTER("mysql_show_grants"); DBUG_ENTER("mysql_show_grants");
LINT_INIT(acl_user); LINT_INIT(acl_user);
@ -2822,7 +2823,7 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
strxmov(buff,"Grants for ",lex_user->user.str,"@", strxmov(buff,"Grants for ",lex_user->user.str,"@",
lex_user->host.str,NullS); lex_user->host.str,NullS);
field_list.push_back(field); field_list.push_back(field);
if (send_fields(thd,field_list,1)) if (protocol->send_fields(&field_list,1))
DBUG_RETURN(-1); DBUG_RETURN(-1);
rw_wrlock(&LOCK_grant); rw_wrlock(&LOCK_grant);
@ -2931,12 +2932,12 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
global.append(buff,p-buff); global.append(buff,p-buff);
} }
} }
thd->packet.length(0); protocol->prepare_for_resend();
net_store_data(&thd->packet,global.ptr(),global.length()); protocol->store(global.ptr(),global.length());
if (my_net_write(&thd->net,(char*) thd->packet.ptr(), if (protocol->write())
thd->packet.length()))
{ {
error=-1; goto end; error=-1;
goto end;
} }
} }
@ -2987,10 +2988,9 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
db.append ('\''); db.append ('\'');
if (want_access & GRANT_ACL) if (want_access & GRANT_ACL)
db.append(" WITH GRANT OPTION",18); db.append(" WITH GRANT OPTION",18);
thd->packet.length(0); protocol->prepare_for_resend();
net_store_data(&thd->packet,db.ptr(),db.length()); protocol->store(db.ptr(),db.length());
if (my_net_write(&thd->net,(char*) thd->packet.ptr(), if (protocol->write())
thd->packet.length()))
{ {
error=-1; error=-1;
goto end; goto end;
@ -3075,10 +3075,9 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
global.append('\''); global.append('\'');
if (want_access & GRANT_ACL) if (want_access & GRANT_ACL)
global.append(" WITH GRANT OPTION",18); global.append(" WITH GRANT OPTION",18);
thd->packet.length(0); protocol->prepare_for_resend();
net_store_data(&thd->packet,global.ptr(),global.length()); protocol->store(global.ptr(),global.length());
if (my_net_write(&thd->net,(char*) thd->packet.ptr(), if (protocol->write())
thd->packet.length()))
{ {
error= -1; error= -1;
break; break;

View File

@ -310,30 +310,7 @@ void field_str::add()
was_maybe_zerofill = num_info.maybe_zerofill; was_maybe_zerofill = num_info.maybe_zerofill;
} }
if (room_in_tree) /* Update min and max arguments */
{
if (res != &s)
s.copy(*res);
if (!tree_search(&tree, (void*) &s, tree.custom_arg)) // If not in tree
{
s.copy(); // slow, when SAFE_MALLOC is in use
if (!tree_insert(&tree, (void*) &s, 0, tree.custom_arg))
{
room_in_tree = 0; // Remove tree, out of RAM ?
delete_tree(&tree);
}
else
{
bzero((char*) &s, sizeof(s)); // Let tree handle free of this
if ((treemem += length) > pc->max_treemem)
{
room_in_tree = 0; // Remove tree, too big tree
delete_tree(&tree);
}
}
}
}
if (!found) if (!found)
{ {
found = 1; found = 1;
@ -364,6 +341,31 @@ void field_str::add()
max_arg.copy(*res); max_arg.copy(*res);
} }
} }
if (room_in_tree)
{
if (res != &s)
s.copy(*res);
if (!tree_search(&tree, (void*) &s, tree.custom_arg)) // If not in tree
{
s.copy(); // slow, when SAFE_MALLOC is in use
if (!tree_insert(&tree, (void*) &s, 0, tree.custom_arg))
{
room_in_tree = 0; // Remove tree, out of RAM ?
delete_tree(&tree);
}
else
{
bzero((char*) &s, sizeof(s)); // Let tree handle free of this
if ((treemem += length) > pc->max_treemem)
{
room_in_tree = 0; // Remove tree, too big tree
delete_tree(&tree);
}
}
}
}
if ((num_info.zerofill && (max_length != min_length)) || if ((num_info.zerofill && (max_length != min_length)) ||
(was_zero_fill && (max_length != min_length))) (was_zero_fill && (max_length != min_length)))
can_be_still_num = 0; // zerofilled numbers must be of same length can_be_still_num = 0; // zerofilled numbers must be of same length

View File

@ -196,250 +196,6 @@ OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *wild)
} }
/*
Send name and type of result to client converted to a given char set
SYNOPSIS
send_convert_fields()
THD Thread data object
list List of items to send to client
convert object used to convertation to another character set
flag Bit mask with the following functions:
2 send default values
4 Don't convert field names
DESCRIPTION
Sum fields has table name empty and field_name.
RETURN VALUES
0 ok
1 Error (Note that in this case the error is not sent to the client)
*/
bool
send_convert_fields(THD *thd,List<Item> &list,CONVERT *convert,uint flag)
{
List_iterator_fast<Item> it(list);
Item *item;
char buff[80];
String tmp((char*) buff,sizeof(buff),default_charset_info);
String *res,*packet= &thd->packet;
DBUG_ENTER("send_convert_fields");
while ((item=it++))
{
char *pos;
Send_field field;
item->make_field(&field);
packet->length(0);
if (thd->client_capabilities & CLIENT_PROTOCOL_41)
{
if (convert->store(packet,field.db_name,
(uint) strlen(field.db_name)) ||
convert->store(packet,field.table_name,
(uint) strlen(field.table_name)) ||
convert->store(packet,field.org_table_name,
(uint) strlen(field.org_table_name)) ||
convert->store(packet,field.col_name,
(uint) strlen(field.col_name)) ||
convert->store(packet,field.org_col_name,
(uint) strlen(field.org_col_name)) ||
packet->realloc(packet->length()+10))
goto err;
}
else
{
if (convert->store(packet,field.table_name,
(uint) strlen(field.table_name)) ||
convert->store(packet,field.col_name,
(uint) strlen(field.col_name)) ||
packet->realloc(packet->length()+10))
goto err;
}
pos= (char*) packet->ptr()+packet->length();
if (!(thd->client_capabilities & CLIENT_LONG_FLAG))
{
packet->length(packet->length()+9);
pos[0]=3; int3store(pos+1,field.length);
pos[4]=1; pos[5]=field.type;
pos[6]=2; pos[7]=(char) field.flags; pos[8]= (char) field.decimals;
}
else
{
packet->length(packet->length()+10);
pos[0]=3; int3store(pos+1,field.length);
pos[4]=1; pos[5]=field.type;
pos[6]=3; int2store(pos+7,field.flags); pos[9]= (char) field.decimals;
}
if (flag & 2)
{ // Send default value
if (!(res=item->val_str(&tmp)))
{
if (net_store_null(packet))
goto err;
}
else if (convert->store(packet,res->ptr(),res->length()))
goto err;
}
if (my_net_write(&thd->net, (char*) packet->ptr(),packet->length()))
break; /* purecov: inspected */
}
DBUG_RETURN(0);
err:
DBUG_RETURN(1);
}
/*
Send name and type of result to client.
SYNOPSIS
send_non_convert_fields()
THD Thread data object
list List of items to send to client
flag Bit mask with the following functions:
2 send default values
4 Don't convert field names
DESCRIPTION
Sum fields has table name empty and field_name.
RETURN VALUES
0 ok
1 Error
*/
bool
send_non_convert_fields(THD *thd,List<Item> &list,uint flag)
{
List_iterator_fast<Item> it(list);
Item *item;
char buff[80];
String tmp((char*) buff,sizeof(buff),default_charset_info);
String *res,*packet= &thd->packet;
while ((item=it++))
{
char *pos;
Send_field field;
item->make_field(&field);
packet->length(0);
if (thd->client_capabilities & CLIENT_PROTOCOL_41)
{
if (net_store_data(packet,field.db_name) ||
net_store_data(packet,field.table_name) ||
net_store_data(packet,field.org_table_name) ||
net_store_data(packet,field.col_name) ||
net_store_data(packet,field.org_col_name) ||
packet->realloc(packet->length()+10))
return 1;
}
else
{
if (net_store_data(packet,field.table_name) ||
net_store_data(packet,field.col_name) ||
packet->realloc(packet->length()+10))
return 1;
}
pos= (char*) packet->ptr()+packet->length();
if (!(thd->client_capabilities & CLIENT_LONG_FLAG))
{
packet->length(packet->length()+9);
pos[0]=3; int3store(pos+1,field.length);
pos[4]=1; pos[5]=field.type;
pos[6]=2; pos[7]=(char) field.flags; pos[8]= (char) field.decimals;
}
else
{
packet->length(packet->length()+10);
pos[0]=3; int3store(pos+1,field.length);
pos[4]=1; pos[5]=field.type;
pos[6]=3; int2store(pos+7,field.flags); pos[9]= (char) field.decimals;
}
if (flag & 2)
{ // Send default value
if (!(res=item->val_str(&tmp)))
{
if (net_store_null(packet))
return 1;
}
else if (net_store_data(packet,res->ptr(),res->length()))
return 1;
}
if (my_net_write(&thd->net, (char*) packet->ptr(),packet->length()))
break;
}
return 0;
}
/*
Send name and type of result to client.
SYNOPSIS
send_fields()
THD Thread data object
list List of items to send to client
convert object used to convertation to another character set
flag Bit mask with the following functions:
1 send number of rows
2 send default values
4 Don't convert field names
DESCRIPTION
Sum fields has table name empty and field_name.
Uses send_fields_convert() and send_fields() depending on
if we have an active character set convert or not.
RETURN VALUES
0 ok
1 Error (Note that in this case the error is not sent to the client)
*/
bool
send_fields(THD *thd, List<Item> &list, uint flag)
{
char buff[9]; // Big enough for store_length
CONVERT *convert= (flag & 4) ? (CONVERT*) 0 : thd->variables.convert_set;
DBUG_ENTER("send_fields");
if (thd->fatal_error) // We have got an error
goto err;
if (flag & 1)
{ // Packet with number of elements
char *pos=net_store_length(buff, (uint) list.elements);
(void) my_net_write(&thd->net, buff,(uint) (pos-buff));
}
/*
Avoid check conditions on convert() for each field
by having two different functions
*/
if (convert)
{
if (send_convert_fields(thd, list, convert, flag))
goto err;
}
else if (send_non_convert_fields(thd, list, flag))
goto err;
send_eof(thd);
DBUG_RETURN(0);
err:
send_error(thd,ER_OUT_OF_RESOURCES); /* purecov: inspected */
DBUG_RETURN(1); /* purecov: inspected */
}
/***************************************************************************** /*****************************************************************************
* Functions to free open table cache * Functions to free open table cache
****************************************************************************/ ****************************************************************************/

View File

@ -152,6 +152,11 @@ THD::THD():user_time(0), fatal_error(0),
(qsort_cmp2) compare_prep_stmt, 1, (qsort_cmp2) compare_prep_stmt, 1,
(tree_element_free) free_prep_stmt, 0); (tree_element_free) free_prep_stmt, 0);
/* Protocol */
protocol= &protocol_simple; // Default protocol
protocol_simple.init(this);
protocol_prep.init(this);
#ifdef USING_TRANSACTIONS #ifdef USING_TRANSACTIONS
bzero((char*) &transaction,sizeof(transaction)); bzero((char*) &transaction,sizeof(transaction));
if (opt_using_transactions) if (opt_using_transactions)
@ -438,7 +443,7 @@ int THD::send_explain_fields(select_result *result)
{ {
List<Item> field_list; List<Item> field_list;
Item *item; Item *item;
field_list.push_back(new Item_int("id",0,3)); field_list.push_back(new Item_return_int("id",3, MYSQL_TYPE_LONGLONG));
field_list.push_back(new Item_empty_string("select_type",19)); field_list.push_back(new Item_empty_string("select_type",19));
field_list.push_back(new Item_empty_string("table",NAME_LEN)); field_list.push_back(new Item_empty_string("table",NAME_LEN));
field_list.push_back(new Item_empty_string("type",10)); field_list.push_back(new Item_empty_string("type",10));
@ -447,12 +452,13 @@ int THD::send_explain_fields(select_result *result)
item->maybe_null=1; item->maybe_null=1;
field_list.push_back(item=new Item_empty_string("key",NAME_LEN)); field_list.push_back(item=new Item_empty_string("key",NAME_LEN));
item->maybe_null=1; item->maybe_null=1;
field_list.push_back(item=new Item_int("key_len",0,3)); field_list.push_back(item=new Item_return_int("key_len",3,
MYSQL_TYPE_LONGLONG));
item->maybe_null=1; item->maybe_null=1;
field_list.push_back(item=new Item_empty_string("ref", field_list.push_back(item=new Item_empty_string("ref",
NAME_LEN*MAX_REF_PARTS)); NAME_LEN*MAX_REF_PARTS));
item->maybe_null=1; item->maybe_null=1;
field_list.push_back(new Item_real("rows",0.0,0,10)); field_list.push_back(new Item_return_int("rows",10, MYSQL_TYPE_LONGLONG));
field_list.push_back(new Item_empty_string("Extra",255)); field_list.push_back(new Item_empty_string("Extra",255));
return (result->send_fields(field_list,1)); return (result->send_fields(field_list,1));
} }
@ -503,7 +509,7 @@ sql_exchange::sql_exchange(char *name,bool flag)
bool select_send::send_fields(List<Item> &list,uint flag) bool select_send::send_fields(List<Item> &list,uint flag)
{ {
return ::send_fields(thd,list,flag); return thd->protocol->send_fields(&list,flag);
} }
@ -511,34 +517,32 @@ bool select_send::send_fields(List<Item> &list,uint flag)
bool select_send::send_data(List<Item> &items) bool select_send::send_data(List<Item> &items)
{ {
List_iterator_fast<Item> li(items);
String *packet= &thd->packet;
DBUG_ENTER("send_data");
if (unit->offset_limit_cnt) if (unit->offset_limit_cnt)
{ // using limit offset,count { // using limit offset,count
unit->offset_limit_cnt--; unit->offset_limit_cnt--;
DBUG_RETURN(0); return 0;
} }
packet->length(0); // Reset packet
List_iterator_fast<Item> li(items);
Protocol *protocol= thd->protocol;
char buff[MAX_FIELD_WIDTH];
String buffer(buff, sizeof(buff), system_charset_info);
DBUG_ENTER("send_data");
protocol->prepare_for_resend();
Item *item; Item *item;
while ((item=li++)) while ((item=li++))
{ {
if (item->send(thd, packet)) if (item->send(protocol, &buffer))
{ {
packet->free(); // Free used protocol->free(); // Free used buffer
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));
DBUG_RETURN(1); break;
} }
} }
thd->sent_row_count++; thd->sent_row_count++;
if (!thd->net.report_error) if (!thd->net.report_error)
{ DBUG_RETURN(protocol->write());
DBUG_RETURN(my_net_write(&thd->net,
(char*) packet->ptr(),
packet->length()));
}
else
DBUG_RETURN(1); DBUG_RETURN(1);
} }

View File

@ -389,6 +389,9 @@ public:
MEM_ROOT mem_root; // 1 command-life memory pool MEM_ROOT mem_root; // 1 command-life memory pool
MEM_ROOT con_root; // connection-life memory MEM_ROOT con_root; // connection-life memory
MEM_ROOT warn_root; // For warnings and errors MEM_ROOT warn_root; // For warnings and errors
Protocol *protocol; // Current protocol
Protocol_simple protocol_simple; // Normal protocol
Protocol_prep protocol_prep; // Binary protocol
HASH user_vars; // hash for user variables HASH user_vars; // hash for user variables
TREE prepared_statements; TREE prepared_statements;
String packet; // dynamic buffer for network I/O String packet; // dynamic buffer for network I/O

View File

@ -604,7 +604,8 @@ bool mysql_change_db(THD *thd, const char *name)
} }
int mysqld_show_create_db(THD *thd, const char *dbname, HA_CREATE_INFO *create_info) int mysqld_show_create_db(THD *thd, const char *dbname,
HA_CREATE_INFO *create_info)
{ {
int length; int length;
char path[FN_REFLEN], *to; char path[FN_REFLEN], *to;
@ -613,7 +614,7 @@ int mysqld_show_create_db(THD *thd, const char *dbname, HA_CREATE_INFO *create_i
HA_CREATE_INFO create; HA_CREATE_INFO create;
CONVERT *convert=thd->variables.convert_set; CONVERT *convert=thd->variables.convert_set;
uint create_options = create_info ? create_info->options : 0; uint create_options = create_info ? create_info->options : 0;
Protocol *protocol=thd->protocol;
DBUG_ENTER("mysql_show_create_db"); DBUG_ENTER("mysql_show_create_db");
if (check_db_name(dbname)) if (check_db_name(dbname))
@ -663,12 +664,11 @@ int mysqld_show_create_db(THD *thd, const char *dbname, HA_CREATE_INFO *create_i
field_list.push_back(new Item_empty_string("Database",NAME_LEN)); field_list.push_back(new Item_empty_string("Database",NAME_LEN));
field_list.push_back(new Item_empty_string("Create Database",1024)); field_list.push_back(new Item_empty_string("Create Database",1024));
if (send_fields(thd,field_list,1)) if (protocol->send_fields(&field_list,1))
DBUG_RETURN(1); DBUG_RETURN(1);
String *packet = &thd->packet; protocol->prepare_for_resend();
packet->length(0); protocol->store(dbname, strlen(dbname));
net_store_data(packet, convert, dbname);
to= strxmov(path, "CREATE DATABASE ", NullS); to= strxmov(path, "CREATE DATABASE ", NullS);
if (create_options & HA_LEX_CREATE_IF_NOT_EXISTS) if (create_options & HA_LEX_CREATE_IF_NOT_EXISTS)
to= strxmov(to,"/*!32312 IF NOT EXISTS*/ ", NullS); to= strxmov(to,"/*!32312 IF NOT EXISTS*/ ", NullS);
@ -678,11 +678,10 @@ int mysqld_show_create_db(THD *thd, const char *dbname, HA_CREATE_INFO *create_i
to= strxmov(to," /*!40100 DEFAULT CHARACTER SET ", to= strxmov(to," /*!40100 DEFAULT CHARACTER SET ",
create.table_charset->name,"*/",NullS); create.table_charset->name,"*/",NullS);
net_store_data(packet, convert, path, (uint) (to-path)); protocol->store(path, (uint) (to-path));
if (my_net_write(&thd->net,(char*) packet->ptr(), packet->length())) if (protocol->write())
DBUG_RETURN(1); DBUG_RETURN(1);
send_eof(thd); send_eof(thd);
DBUG_RETURN(0); DBUG_RETURN(0);
} }

View File

@ -150,7 +150,7 @@ void store_warning(THD *thd, uint errcode, ...)
*/ */
static const char *warning_level_names[]= {"Note", "Warning", "Error", "?"}; static const char *warning_level_names[]= {"Note", "Warning", "Error", "?"};
static int warning_level_length[]= { 4, 7, 5, 1 };
my_bool mysqld_show_warnings(THD *thd, ulong levels_to_show) my_bool mysqld_show_warnings(THD *thd, ulong levels_to_show)
{ {
@ -158,15 +158,16 @@ my_bool mysqld_show_warnings(THD *thd, ulong levels_to_show)
DBUG_ENTER("mysqld_show_warnings"); DBUG_ENTER("mysqld_show_warnings");
field_list.push_back(new Item_empty_string("Level", 7)); field_list.push_back(new Item_empty_string("Level", 7));
field_list.push_back(new Item_int("Code",0,4)); field_list.push_back(new Item_return_int("Code",4, MYSQL_TYPE_LONG));
field_list.push_back(new Item_empty_string("Message",MYSQL_ERRMSG_SIZE)); field_list.push_back(new Item_empty_string("Message",MYSQL_ERRMSG_SIZE));
if (send_fields(thd,field_list,1)) if (thd->protocol->send_fields(&field_list,1))
DBUG_RETURN(1); DBUG_RETURN(1);
MYSQL_ERROR *err; MYSQL_ERROR *err;
SELECT_LEX *sel= &thd->lex.select_lex; SELECT_LEX *sel= &thd->lex.select_lex;
ha_rows offset= sel->offset_limit, limit= sel->select_limit; ha_rows offset= sel->offset_limit, limit= sel->select_limit;
Protocol *protocol=thd->protocol;
List_iterator_fast<MYSQL_ERROR> it(thd->warn_list); List_iterator_fast<MYSQL_ERROR> it(thd->warn_list);
while ((err= it++)) while ((err= it++))
@ -179,11 +180,12 @@ my_bool mysqld_show_warnings(THD *thd, ulong levels_to_show)
offset--; offset--;
continue; continue;
} }
thd->packet.length(0); protocol->prepare_for_resend();
net_store_data(&thd->packet,warning_level_names[err->level]); protocol->store(warning_level_names[err->level],
net_store_data(&thd->packet,(uint32) err->code); warning_level_length[err->level]);
net_store_data(&thd->packet,err->msg); protocol->store((uint32) err->code);
if (my_net_write(&thd->net,(char*)thd->packet.ptr(),thd->packet.length())) protocol->store(err->msg, strlen(err->msg));
if (protocol->write())
DBUG_RETURN(1); DBUG_RETURN(1);
if (!--limit) if (!--limit)
break; break;

View File

@ -123,6 +123,9 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
List<Item> list; List<Item> list;
list.push_front(new Item_field(NULL,NULL,"*")); list.push_front(new Item_field(NULL,NULL,"*"));
List_iterator<Item> it(list); List_iterator<Item> it(list);
Protocol *protocol= thd->protocol;
char buff[MAX_FIELD_WIDTH];
String buffer(buff, sizeof(buff), system_charset_info);
uint num_rows; uint num_rows;
it++; it++;
@ -131,7 +134,7 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
table->file->init_table_handle_for_HANDLER(); // Only InnoDB requires it table->file->init_table_handle_for_HANDLER(); // Only InnoDB requires it
select_limit+=offset_limit; select_limit+=offset_limit;
send_fields(thd,list,1); protocol->send_fields(&list,1);
HANDLER_TABLES_HACK(thd); HANDLER_TABLES_HACK(thd);
MYSQL_LOCK *lock=mysql_lock_tables(thd,&tables->table,1); MYSQL_LOCK *lock=mysql_lock_tables(thd,&tables->table,1);
@ -222,18 +225,18 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
{ {
String *packet = &thd->packet; String *packet = &thd->packet;
Item *item; Item *item;
packet->length(0); protocol->prepare_for_resend();
it.rewind(); it.rewind();
while ((item=it++)) while ((item=it++))
{ {
if (item->send(thd,packet)) if (item->send(thd->protocol, &buffer))
{ {
packet->free(); // Free used protocol->free(); // Free used
my_error(ER_OUT_OF_RESOURCES,MYF(0)); my_error(ER_OUT_OF_RESOURCES,MYF(0));
goto err; goto err;
} }
} }
my_net_write(&thd->net, (char*)packet->ptr(), packet->length()); protocol->write();
} }
} }
num_rows++; num_rows++;
@ -249,22 +252,22 @@ err0:
} }
/************************************************************************** /**************************************************************************
2Monty: It could easily happen, that the following service functions are Monty: It could easily happen, that the following service functions are
already defined somewhere in the code, but I failed to find them. already defined somewhere in the code, but I failed to find them.
If this is the case, just say a word and I'll use old functions here. If this is the case, just say a word and I'll use old functions here.
**************************************************************************/ **************************************************************************/
/* Note: this function differs from find_locked_table() because we're looking /*
Note: this function differs from find_locked_table() because we're looking
here for alias, not real table name here for alias, not real table name
*/ */
static TABLE **find_table_ptr_by_name(THD *thd, const char *db, static TABLE **find_table_ptr_by_name(THD *thd, const char *db,
const char *alias) const char *alias)
{ {
int dblen; int dblen;
TABLE **ptr; TABLE **ptr;
if (!db || ! *db)
db= thd->db ? thd->db : "";
dblen=strlen(db)+1; dblen=strlen(db)+1;
ptr= &(thd->handler_tables); ptr= &(thd->handler_tables);

View File

@ -219,22 +219,21 @@ int search_categories(THD *thd,
DBUG_RETURN(count); DBUG_RETURN(count);
} }
int send_variant_2_list(THD *thd, List<String> *names, my_bool is_category) int send_variant_2_list(Protocol *protocol, List<String> *names,
my_bool is_category)
{ {
DBUG_ENTER("send_names"); DBUG_ENTER("send_names");
List_iterator<String> it(*names); List_iterator<String> it(*names);
String *cur_name; String *cur_name;
String *packet= &thd->packet;
while ((cur_name = it++)) while ((cur_name = it++))
{ {
packet->length(0); protocol->prepare_for_resend();
net_store_data(packet, cur_name->ptr()); protocol->store(cur_name->ptr());
net_store_data(packet, is_category ? "Y" : "N"); protocol->store(is_category ? "Y" : "N");
if (my_net_write(&thd->net,(char*) packet->ptr(),packet->length())) if (protocol->write())
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
DBUG_RETURN(0); DBUG_RETURN(0);
} }
@ -296,43 +295,44 @@ int get_all_names_for_category(THD *thd,MI_INFO *file_leafs,
DBUG_RETURN(0); DBUG_RETURN(0);
} }
int send_answer_1(THD *thd, const char *s1, const char *s2, int send_answer_1(Protocol *protocol, const char *s1, const char *s2,
const char *s3, const char *s4) const char *s3, const char *s4)
{ {
DBUG_ENTER("send_answer_1"); DBUG_ENTER("send_answer_1");
List<Item> field_list; List<Item> field_list;
field_list.push_back(new Item_empty_string("name",64)); field_list.push_back(new Item_empty_string("Name",64));
field_list.push_back(new Item_empty_string("is_category",1)); field_list.push_back(new Item_empty_string("Category",1));
field_list.push_back(new Item_empty_string("description",1000)); field_list.push_back(new Item_empty_string("Description",1000));
field_list.push_back(new Item_empty_string("example",1000)); field_list.push_back(new Item_empty_string("Example",1000));
if (send_fields(thd,field_list,1)) if (protocol->send_fields(&field_list,1))
DBUG_RETURN(1); DBUG_RETURN(1);
String *packet= &thd->packet; protocol->prepare_for_resend();
packet->length(0); protocol->store(s1);
net_store_data(packet, s1); protocol->store(s2);
net_store_data(packet, s2); protocol->store(s3);
net_store_data(packet, s3); protocol->store(s4);
net_store_data(packet, s4); if (protocol->write())
if (my_net_write(&thd->net,(char*) packet->ptr(),packet->length()))
DBUG_RETURN(-1); DBUG_RETURN(-1);
DBUG_RETURN(0); DBUG_RETURN(0);
} }
int send_header_2(THD *thd)
int send_header_2(Protocol *protocol)
{ {
DBUG_ENTER("send_header2"); DBUG_ENTER("send_header2");
List<Item> field_list; List<Item> field_list;
field_list.push_back(new Item_empty_string("name",64)); field_list.push_back(new Item_empty_string("Name",64));
field_list.push_back(new Item_empty_string("is_category",1)); field_list.push_back(new Item_empty_string("Category",1));
DBUG_RETURN(send_fields(thd,field_list,1)); DBUG_RETURN(protocol->send_fields(&field_list,1));
} }
int mysqld_help(THD *thd, const char *mask) int mysqld_help(THD *thd, const char *mask)
{ {
Protocol *protocol= thd->protocol;
DBUG_ENTER("mysqld_help"); DBUG_ENTER("mysqld_help");
MI_INFO *file_leafs= 0; MI_INFO *file_leafs= 0;
@ -371,31 +371,31 @@ int mysqld_help (THD *thd, const char *mask)
example.append(*cur_leaf); example.append(*cur_leaf);
example.append("\n",1); example.append("\n",1);
} }
if ((res= send_answer_1(thd, categories_list.head()->ptr(), if ((res= send_answer_1(protocol, categories_list.head()->ptr(),
"Y","",example.ptr()))) "Y","",example.ptr())))
goto end; goto end;
} }
else else
{ {
if ((res= send_header_2(thd)) || if ((res= send_header_2(protocol)) ||
(count==0 && (count==0 &&
(search_categories(thd, 0, &categories_list, 0)<0 && (search_categories(thd, 0, &categories_list, 0)<0 &&
(res= 1))) || (res= 1))) ||
(res= send_variant_2_list(thd,&categories_list,true))) (res= send_variant_2_list(protocol,&categories_list,true)))
goto end; goto end;
} }
} }
else if (count==1) else if (count==1)
{ {
if ((res= send_answer_1(thd,name->ptr(),"N", if ((res= send_answer_1(protocol,name->ptr(),"N",
description->ptr(), example->ptr()))) description->ptr(), example->ptr())))
goto end; goto end;
} }
else if((res= send_header_2(thd)) || else if((res= send_header_2(protocol)) ||
(res= send_variant_2_list(thd,&function_list,false)) || (res= send_variant_2_list(protocol,&function_list,false)) ||
(search_categories(thd, mask, &categories_list, 0)<0 && (search_categories(thd, mask, &categories_list, 0)<0 &&
(res=1)) || (res=1)) ||
(res= send_variant_2_list(thd,&categories_list,true))) (res= send_variant_2_list(protocol,&categories_list,true)))
{ {
goto end; goto end;
} }

View File

@ -3010,11 +3010,11 @@ mysql_init_query(THD *thd)
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
void void
mysql_init_select(LEX *lex) mysql_init_select(LEX *lex)
{ {
SELECT_LEX *select_lex= lex->current_select->select_lex(); SELECT_LEX *select_lex= lex->current_select->select_lex();
DBUG_ASSERT(select_lex->linkage != GLOBAL_OPTIONS_TYPE);
select_lex->init_select(); select_lex->init_select();
select_lex->master_unit()->select_limit= select_lex->select_limit= select_lex->master_unit()->select_limit= select_lex->select_limit=
lex->thd->variables.select_limit; lex->thd->variables.select_limit;

View File

@ -512,7 +512,8 @@ static bool mysql_test_select_fields(PREP_STMT *stmt, TABLE_LIST *tables,
sending any info on where clause. sending any info on where clause.
*/ */
if (send_prep_stmt(stmt, fields.elements) || if (send_prep_stmt(stmt, fields.elements) ||
send_fields(thd,fields,0) || send_item_params(stmt)) thd->protocol_prep.send_fields(&fields,0) ||
send_item_params(stmt))
DBUG_RETURN(1); DBUG_RETURN(1);
DBUG_RETURN(0); DBUG_RETURN(0);
} }
@ -726,7 +727,9 @@ void mysql_stmt_execute(THD *thd, char *packet)
mysql_delete(), mysql_update() and mysql_select() to not to mysql_delete(), mysql_update() and mysql_select() to not to
have re-check on setup_* and other things .. have re-check on setup_* and other things ..
*/ */
thd->protocol= &thd->protocol_prep; // Switch to binary protocol
mysql_execute_command(stmt->thd); mysql_execute_command(stmt->thd);
thd->protocol= &thd->protocol_simple; // Use normal protocol
if (!(specialflag & SPECIAL_NO_PRIOR)) if (!(specialflag & SPECIAL_NO_PRIOR))
my_pthread_setprio(pthread_self(), WAIT_PRIOR); my_pthread_setprio(pthread_self(), WAIT_PRIOR);

View File

@ -928,6 +928,7 @@ int cmp_master_pos(const char* log_file_name1, ulonglong log_pos1,
int show_binlog_events(THD* thd) int show_binlog_events(THD* thd)
{ {
Protocol *protocol= thd->protocol;
DBUG_ENTER("show_binlog_events"); DBUG_ENTER("show_binlog_events");
List<Item> field_list; List<Item> field_list;
const char *errmsg = 0; const char *errmsg = 0;
@ -935,7 +936,7 @@ int show_binlog_events(THD* thd)
File file = -1; File file = -1;
Log_event::init_show_field_list(&field_list); Log_event::init_show_field_list(&field_list);
if (send_fields(thd, field_list, 1)) if (protocol-> send_fields(&field_list, 1))
DBUG_RETURN(-1); DBUG_RETURN(-1);
if (mysql_bin_log.is_open()) if (mysql_bin_log.is_open())
@ -983,7 +984,7 @@ int show_binlog_events(THD* thd)
(ev = Log_event::read_log_event(&log,(pthread_mutex_t*)0,0)); ) (ev = Log_event::read_log_event(&log,(pthread_mutex_t*)0,0)); )
{ {
if (event_count >= limit_start && if (event_count >= limit_start &&
ev->net_send(thd, linfo.log_file_name, pos)) ev->net_send(protocol, linfo.log_file_name, pos))
{ {
errmsg = "Net error"; errmsg = "Net error";
delete ev; delete ev;
@ -1029,28 +1030,29 @@ err:
int show_binlog_info(THD* thd) int show_binlog_info(THD* thd)
{ {
Protocol *protocol= thd->protocol;
DBUG_ENTER("show_binlog_info"); DBUG_ENTER("show_binlog_info");
List<Item> field_list; List<Item> field_list;
field_list.push_back(new Item_empty_string("File", FN_REFLEN)); field_list.push_back(new Item_empty_string("File", FN_REFLEN));
field_list.push_back(new Item_empty_string("Position",20)); field_list.push_back(new Item_return_int("Position",20,
field_list.push_back(new Item_empty_string("Binlog_do_db",20)); MYSQL_TYPE_LONGLONG));
field_list.push_back(new Item_empty_string("Binlog_ignore_db",20)); field_list.push_back(new Item_empty_string("Binlog_do_db",255));
field_list.push_back(new Item_empty_string("Binlog_ignore_db",255));
if (send_fields(thd, field_list, 1)) if (protocol->send_fields(&field_list, 1))
DBUG_RETURN(-1); DBUG_RETURN(-1);
String* packet = &thd->packet; protocol->prepare_for_resend();
packet->length(0);
if (mysql_bin_log.is_open()) if (mysql_bin_log.is_open())
{ {
LOG_INFO li; LOG_INFO li;
mysql_bin_log.get_current_log(&li); mysql_bin_log.get_current_log(&li);
int dir_len = dirname_length(li.log_file_name); int dir_len = dirname_length(li.log_file_name);
net_store_data(packet, li.log_file_name + dir_len); protocol->store(li.log_file_name + dir_len);
net_store_data(packet, (longlong)li.pos); protocol->store((ulonglong) li.pos);
net_store_data(packet, &binlog_do_db); protocol->store(&binlog_do_db);
net_store_data(packet, &binlog_ignore_db); protocol->store(&binlog_ignore_db);
if (my_net_write(&thd->net, (char*)thd->packet.ptr(), packet->length())) if (protocol->write())
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
send_eof(thd); send_eof(thd);
@ -1079,6 +1081,8 @@ int show_binlogs(THD* thd)
List<Item> field_list; List<Item> field_list;
String *packet = &thd->packet; String *packet = &thd->packet;
uint length; uint length;
Protocol *protocol= thd->protocol;
DBUG_ENTER("show_binlogs");
if (!mysql_bin_log.is_open()) if (!mysql_bin_log.is_open())
{ {
@ -1088,8 +1092,8 @@ int show_binlogs(THD* thd)
} }
field_list.push_back(new Item_empty_string("Log_name", 255)); field_list.push_back(new Item_empty_string("Log_name", 255));
if (send_fields(thd, field_list, 1)) if (protocol->send_fields(&field_list, 1))
return 1; DBUG_RETURN(1);
mysql_bin_log.lock_index(); mysql_bin_log.lock_index();
index_file=mysql_bin_log.get_index_file(); index_file=mysql_bin_log.get_index_file();
@ -1098,22 +1102,22 @@ int show_binlogs(THD* thd)
/* The file ends with EOF or empty line */ /* The file ends with EOF or empty line */
while ((length=my_b_gets(index_file, fname, sizeof(fname))) > 1) while ((length=my_b_gets(index_file, fname, sizeof(fname))) > 1)
{ {
protocol->prepare_for_resend();
int dir_len = dirname_length(fname); int dir_len = dirname_length(fname);
packet->length(0);
/* The -1 is for removing newline from fname */ /* The -1 is for removing newline from fname */
net_store_data(packet, fname + dir_len, length-1-dir_len); protocol->store(fname + dir_len, length-1-dir_len);
if (my_net_write(net, (char*) packet->ptr(), packet->length())) if (protocol->write())
goto err; goto err;
} }
mysql_bin_log.unlock_index(); mysql_bin_log.unlock_index();
send_eof(thd); send_eof(thd);
return 0; DBUG_RETURN(0);
err_with_msg: err_with_msg:
send_error(thd, ER_UNKNOWN_ERROR, errmsg); send_error(thd, ER_UNKNOWN_ERROR, errmsg);
err: err:
mysql_bin_log.unlock_index(); mysql_bin_log.unlock_index();
return 1; DBUG_RETURN(1);
} }

View File

@ -3059,6 +3059,7 @@ join_free(JOIN *join, bool full)
if (join->tables > join->const_tables) // Test for not-const tables if (join->tables > join->const_tables) // Test for not-const tables
free_io_cache(join->table[join->const_tables]); free_io_cache(join->table[join->const_tables]);
if (join->select_lex->dependent && !full) if (join->select_lex->dependent && !full)
{
for (tab=join->join_tab,end=tab+join->tables ; tab != end ; tab++) for (tab=join->join_tab,end=tab+join->tables ; tab != end ; tab++)
{ {
if (tab->table) if (tab->table)
@ -3073,6 +3074,7 @@ join_free(JOIN *join, bool full)
tab->table->file->index_end(); tab->table->file->index_end();
} }
} }
}
else else
{ {
for (tab=join->join_tab,end=tab+join->tables ; tab != end ; tab++) for (tab=join->join_tab,end=tab+join->tables ; tab != end ; tab++)
@ -3090,6 +3092,11 @@ join_free(JOIN *join, bool full)
/* Don't free index if we are using read_record */ /* Don't free index if we are using read_record */
if (!tab->read_record.table) if (!tab->read_record.table)
tab->table->file->index_end(); tab->table->file->index_end();
/*
We need to reset this for next select
(Tested in part_of_refkey)
*/
tab->table->reginfo.join_tab= 0;
} }
end_read_record(&tab->read_record); end_read_record(&tab->read_record);
} }
@ -7500,9 +7507,8 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
item_list.push_back(new Item_string(join->select_lex->type, item_list.push_back(new Item_string(join->select_lex->type,
strlen(join->select_lex->type), strlen(join->select_lex->type),
default_charset_info)); default_charset_info));
Item *empty= new Item_empty_string("",0);
for (uint i=0 ; i < 7; i++) for (uint i=0 ; i < 7; i++)
item_list.push_back(empty); item_list.push_back(item_null);
item_list.push_back(new Item_string(message,strlen(message), item_list.push_back(new Item_string(message,strlen(message),
default_charset_info)); default_charset_info));
if (result->send_data(item_list)) if (result->send_data(item_list))
@ -7542,7 +7548,9 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
item_list.push_back(new Item_string(table->table_name, item_list.push_back(new Item_string(table->table_name,
strlen(table->table_name), strlen(table->table_name),
default_charset_info)); default_charset_info));
item_list.push_back(new Item_string(join_type_str[tab->type],strlen(join_type_str[tab->type]),default_charset_info)); item_list.push_back(new Item_string(join_type_str[tab->type],
strlen(join_type_str[tab->type]),
default_charset_info));
key_map bits; key_map bits;
uint j; uint j;
for (j=0,bits=tab->keys ; bits ; j++,bits>>=1) for (j=0,bits=tab->keys ; bits ; j++,bits>>=1)
@ -7600,9 +7608,9 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
item_list.push_back(item_null); item_list.push_back(item_null);
item_list.push_back(item_null); item_list.push_back(item_null);
} }
sprintf(buff3,"%.0f",join->best_positions[i].records_read); item_list.push_back(new Item_int((longlong) (ulonglong)
item_list.push_back(new Item_string(buff3,strlen(buff3), join->best_positions[i]. records_read,
default_charset_info)); 21));
my_bool key_read=table->key_read; my_bool key_read=table->key_read;
if (tab->type == JT_NEXT && if (tab->type == JT_NEXT &&
((table->used_keys & ((key_map) 1 << tab->index)))) ((table->used_keys & ((key_map) 1 << tab->index))))
@ -7658,6 +7666,7 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result) int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result)
{ {
DBUG_ENTER("mysql_explain_union"); DBUG_ENTER("mysql_explain_union");
@ -7688,6 +7697,7 @@ int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result)
DBUG_RETURN(res); DBUG_RETURN(res);
} }
int mysql_explain_select(THD *thd, SELECT_LEX *select_lex, char const *type, int mysql_explain_select(THD *thd, SELECT_LEX *select_lex, char const *type,
select_result *result) select_result *result)
{ {

File diff suppressed because it is too large Load Diff

View File

@ -255,4 +255,29 @@ public:
void qs_append(double d); void qs_append(double d);
void qs_append(double *d); void qs_append(double *d);
void qs_append(const char &c); void qs_append(const char &c);
/* Inline (general) functions used by the protocol functions */
inline char *prep_append(uint32 arg_length, uint32 step_alloc)
{
uint32 new_length= arg_length + str_length;
if (new_length > Alloced_length)
{
if (realloc(new_length + step_alloc))
return 0;
}
uint32 old_length= str_length;
str_length+= arg_length;
return Ptr+ old_length; /* Area to use */
}
inline bool append(const char *s, uint32 arg_length, uint32 step_alloc)
{
uint32 new_length= arg_length + str_length;
if (new_length > Alloced_length && realloc(new_length + step_alloc))
return TRUE;
memcpy(Ptr+str_length, s, arg_length);
str_length+= arg_length;
return FALSE;
}
}; };

View File

@ -1021,16 +1021,14 @@ static int send_check_errmsg(THD* thd, TABLE_LIST* table,
const char* operator_name, const char* errmsg) const char* operator_name, const char* errmsg)
{ {
Protocol *protocol= thd->protocol;
String* packet = &thd->packet; protocol->prepare_for_resend();
packet->length(0); protocol->store(table->alias);
net_store_data(packet, table->alias); protocol->store((char*) operator_name);
net_store_data(packet, (char*)operator_name); protocol->store("error", 5);
net_store_data(packet, "error"); protocol->store(errmsg);
net_store_data(packet, errmsg);
thd->net.last_error[0]=0; thd->net.last_error[0]=0;
if (my_net_write(&thd->net, (char*) thd->packet.ptr(), if (protocol->write())
packet->length()))
return -1; return -1;
return 1; return 1;
} }
@ -1177,7 +1175,7 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
TABLE_LIST *table; TABLE_LIST *table;
List<Item> field_list; List<Item> field_list;
Item *item; Item *item;
String* packet = &thd->packet; Protocol *protocol= thd->protocol;
DBUG_ENTER("mysql_admin_table"); DBUG_ENTER("mysql_admin_table");
field_list.push_back(item = new Item_empty_string("Table", NAME_LEN*2)); field_list.push_back(item = new Item_empty_string("Table", NAME_LEN*2));
@ -1188,7 +1186,7 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
item->maybe_null = 1; item->maybe_null = 1;
field_list.push_back(item = new Item_empty_string("Msg_text", 255)); field_list.push_back(item = new Item_empty_string("Msg_text", 255));
item->maybe_null = 1; item->maybe_null = 1;
if (send_fields(thd, field_list, 1)) if (protocol->send_fields(&field_list, 1))
DBUG_RETURN(-1); DBUG_RETURN(-1);
for (table = tables; table; table = table->next) for (table = tables; table; table = table->next)
@ -1201,7 +1199,8 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
thd->open_options|= extra_open_options; thd->open_options|= extra_open_options;
table->table = open_ltable(thd, table, lock_type); table->table = open_ltable(thd, table, lock_type);
thd->open_options&= ~extra_open_options; thd->open_options&= ~extra_open_options;
packet->length(0); protocol->prepare_for_resend();
if (prepare_func) if (prepare_func)
{ {
switch ((*prepare_func)(thd, table, check_opt)) { switch ((*prepare_func)(thd, table, check_opt)) {
@ -1214,30 +1213,30 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
if (!table->table) if (!table->table)
{ {
const char *err_msg; const char *err_msg;
net_store_data(packet, table_name); protocol->prepare_for_resend();
net_store_data(packet, operator_name); protocol->store(table_name);
net_store_data(packet, "error"); protocol->store(operator_name);
protocol->store("error",5);
if (!(err_msg=thd->net.last_error)) if (!(err_msg=thd->net.last_error))
err_msg=ER(ER_CHECK_NO_SUCH_TABLE); err_msg=ER(ER_CHECK_NO_SUCH_TABLE);
net_store_data(packet, err_msg); protocol->store(err_msg);
thd->net.last_error[0]=0; thd->net.last_error[0]=0;
if (my_net_write(&thd->net, (char*) thd->packet.ptr(), if (protocol->write())
packet->length()))
goto err; goto err;
continue; continue;
} }
if ((table->table->db_stat & HA_READ_ONLY) && open_for_modify) if ((table->table->db_stat & HA_READ_ONLY) && open_for_modify)
{ {
char buff[FN_REFLEN + MYSQL_ERRMSG_SIZE]; char buff[FN_REFLEN + MYSQL_ERRMSG_SIZE];
net_store_data(packet, table_name); protocol->prepare_for_resend();
net_store_data(packet, operator_name); protocol->store(table_name);
net_store_data(packet, "error"); protocol->store(operator_name);
protocol->store("error", 5);
sprintf(buff, ER(ER_OPEN_AS_READONLY), table_name); sprintf(buff, ER(ER_OPEN_AS_READONLY), table_name);
net_store_data(packet, buff); protocol->store(buff);
close_thread_tables(thd); close_thread_tables(thd);
table->table=0; // For query cache table->table=0; // For query cache
if (my_net_write(&thd->net, (char*) thd->packet.ptr(), if (protocol->write())
packet->length()))
goto err; goto err;
continue; continue;
} }
@ -1265,50 +1264,50 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
} }
int result_code = (table->table->file->*operator_func)(thd, check_opt); int result_code = (table->table->file->*operator_func)(thd, check_opt);
packet->length(0); protocol->prepare_for_resend();
net_store_data(packet, table_name); protocol->store(table_name);
net_store_data(packet, operator_name); protocol->store(operator_name);
switch (result_code) { switch (result_code) {
case HA_ADMIN_NOT_IMPLEMENTED: case HA_ADMIN_NOT_IMPLEMENTED:
{ {
char buf[ERRMSGSIZE+20]; char buf[ERRMSGSIZE+20];
my_snprintf(buf, ERRMSGSIZE, uint length=my_snprintf(buf, ERRMSGSIZE,
ER(ER_CHECK_NOT_IMPLEMENTED), operator_name); ER(ER_CHECK_NOT_IMPLEMENTED), operator_name);
net_store_data(packet, "error"); protocol->store("error", 5);
net_store_data(packet, buf); protocol->store(buf, length);
} }
break; break;
case HA_ADMIN_OK: case HA_ADMIN_OK:
net_store_data(packet, "status"); protocol->store("status", 6);
net_store_data(packet, "OK"); protocol->store("OK",2);
break; break;
case HA_ADMIN_FAILED: case HA_ADMIN_FAILED:
net_store_data(packet, "status"); protocol->store("status", 6);
net_store_data(packet, "Operation failed"); protocol->store("Operation failed",16);
break; break;
case HA_ADMIN_ALREADY_DONE: case HA_ADMIN_ALREADY_DONE:
net_store_data(packet, "status"); protocol->store("status", 6);
net_store_data(packet, "Table is already up to date"); protocol->store("Table is already up to date", 27);
break; break;
case HA_ADMIN_CORRUPT: case HA_ADMIN_CORRUPT:
net_store_data(packet, "error"); protocol->store("error", 5);
net_store_data(packet, "Corrupt"); protocol->store("Corrupt", 8);
fatal_error=1; fatal_error=1;
break; break;
case HA_ADMIN_INVALID: case HA_ADMIN_INVALID:
net_store_data(packet, "error"); protocol->store("error", 5);
net_store_data(packet, "Invalid argument"); protocol->store("Invalid argument",16);
break; break;
default: // Probably HA_ADMIN_INTERNAL_ERROR default: // Probably HA_ADMIN_INTERNAL_ERROR
net_store_data(packet, "error"); protocol->store("error", 5);
net_store_data(packet, "Unknown - internal error during operation"); protocol->store("Unknown - internal error during operation", 41);
fatal_error=1; fatal_error=1;
break; break;
} }
@ -1325,8 +1324,7 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
} }
close_thread_tables(thd); close_thread_tables(thd);
table->table=0; // For query cache table->table=0; // For query cache
if (my_net_write(&thd->net, (char*) packet->ptr(), if (protocol->write())
packet->length()))
goto err; goto err;
} }

View File

@ -113,7 +113,8 @@ enum timestamp_type { TIMESTAMP_NONE, TIMESTAMP_DATE, TIMESTAMP_FULL,
TIMESTAMP_TIME }; TIMESTAMP_TIME };
typedef struct st_time { typedef struct st_time {
uint year,month,day,hour,minute,second,second_part; uint year,month,day,hour,minute,second;
ulong second_part;
bool neg; bool neg;
timestamp_type time_type; timestamp_type time_type;
} TIME; } TIME;

View File

@ -724,3 +724,20 @@ bool str_to_time(const char *str,uint length,TIME *l_time)
} }
return 0; return 0;
} }
/*
Convert a system time structure to TIME
*/
void localtime_to_TIME(TIME *to, struct tm *from)
{
to->neg=0;
to->second_part=0;
to->year= (int) ((from->tm_year+1900) % 10000);
to->month= (int) from->tm_mon+1;
to->day= (int) from->tm_mday;
to->hour= (int) from->tm_hour;
to->minute= (int) from->tm_min;
to->second= (int) from->tm_sec;
}

705
tests/fork_big2.pl Normal file
View File

@ -0,0 +1,705 @@
#!/usr/bin/perl -w
#
# This is a test with uses many processes to test a MySQL server.
#
# Tested a lot with: --threads=30
$opt_loop_count=500000; # Change this to make test harder/easier
##################### Standard benchmark inits ##############################
use DBI;
use Getopt::Long;
use Benchmark;
package main;
$opt_skip_create=$opt_skip_in=$opt_verbose=$opt_fast_insert=
$opt_lock_tables=$opt_debug=$opt_skip_drop=$opt_fast=$opt_force=0;
$opt_thread_factor=1;
$opt_insert=1;
$opt_select=6;$opt_join=4;
$opt_select_count=$opt_join_count=0;
$opt_update=1;$opt_delete=0;
$opt_flush=$opt_check=$opt_repair=$opt_alter=0;
$opt_join_range=100;
$opt_time=0;
$opt_host=$opt_user=$opt_password=""; $opt_db="test";
GetOptions("host=s","db=s","user=s","password=s","loop-count=i","skip-create","skip-in","skip-drop",
"verbose","fast-insert","lock-tables","debug","fast","force","thread-factor=i",
"insert=i", "select=i", "join=i", "select-count=i", "join-count=i", "update=i", "delete=i",
"flush=i", "check=i", "repair=i", "alter=i", "max-join_range=i", "time=i") || die "Aborted";
$opt_verbose=$opt_debug=$opt_lock_tables=$opt_fast_insert=$opt_fast=$opt_skip_in=$opt_force=undef; # Ignore warnings from these
print "Test of multiple connections that test the following things:\n";
print "insert, select, delete, update, alter, check, repair and flush\n";
@testtables = ( ["bench_f31", ""],
["bench_f32", "row_format=fixed"],
["bench_f33", "delay_key_write=1"],
["bench_f34", "checksum=1"],
["bench_f35", "delay_key_write=1"]);
$abort_table="bench_f39";
$numtables = $#testtables+1;
srand 100; # Make random numbers repeatable
####
#### Start timeing and start test
####
$opt_insert*=$opt_thread_factor;
$opt_select*=$opt_thread_factor;
$opt_join*=$opt_thread_factor;
$opt_select_count*=$opt_thread_factor;
$opt_join_count*=$opt_thread_factor;
$opt_update*=$opt_thread_factor;
$opt_delete*=$opt_thread_factor;
if ($opt_time == 0 && $opt_insert == 0)
{
$opt_insert=1;
}
$start_time=new Benchmark;
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
$opt_user, $opt_password,
{ PrintError => 0}) || die $DBI::errstr;
if (!$opt_skip_create)
{
my $table_def;
foreach $table_def (@testtables)
{
my ($table,$extra)= ($table_def->[0], $table_def->[1]);
print "Creating table $table in database $opt_db\n";
$dbh->do("drop table if exists $table");
$dbh->do("create table $table".
" (id int(6) not null auto_increment,".
" info varchar(32)," .
" marker timestamp," .
" flag int not null," .
" primary key(id)) $extra")
or die $DBI::errstr;
# One row in the table will make future tests easier
$dbh->do("insert into $table (id) values (null)")
or die $DBI::errstr;
}
# Create the table we use to signal that we should end the test
$dbh->do("drop table if exists $abort_table");
$dbh->do("create table $abort_table (id int(6) not null) type=heap") ||
die $DBI::errstr;
}
$dbh->do("delete from $abort_table");
$dbh->disconnect; $dbh=0; # Close handler
$|= 1; # Autoflush
####
#### Start the tests
####
if ($opt_time != 0)
{
test_abort() if (($pid=fork()) == 0); $work{$pid}="abort";
}
for ($i=0 ; $i < $opt_insert ; $i ++)
{
test_insert() if (($pid=fork()) == 0); $work{$pid}="insert";
}
$threads=$i;
for ($i=0 ; $i < $opt_select ; $i ++)
{
test_select() if (($pid=fork()) == 0); $work{$pid}="select";
}
$threads+=$i;
for ($i=0 ; $i < $opt_join ; $i ++)
{
test_join() if (($pid=fork()) == 0); $work{$pid}="join";
}
$threads+=$i;
for ($i=0 ; $i < $opt_select_count ; $i ++)
{
test_select_count() if (($pid=fork()) == 0); $work{$pid}="select_count";
}
$threads+=$i;
for ($i=0 ; $i < $opt_join_count ; $i ++)
{
test_join_count() if (($pid=fork()) == 0); $work{$pid}="join_count";
}
$threads+=$i;
for ($i=0 ; $i < $opt_update ; $i ++)
{
test_update() if (($pid=fork()) == 0); $work{$pid}="update";
}
$threads+=$i;
for ($i=0 ; $i < $opt_delete ; $i ++)
{
test_delete() if (($pid=fork()) == 0); $work{$pid}="delete";
}
$threads+=$i;
for ($i=0 ; $i < $opt_flush ; $i ++)
{
test_flush() if (($pid=fork()) == 0); $work{$pid}="flush";
}
$threads+=$i;
for ($i=0 ; $i < $opt_check ; $i ++)
{
test_check() if (($pid=fork()) == 0); $work{$pid}="check";
}
$threads+=$i;
for ($i=0 ; $i < $opt_repair ; $i ++)
{
test_repair() if (($pid=fork()) == 0); $work{$pid}="repair";
}
$threads+=$i;
for ($i=0 ; $i < $opt_alter ; $i ++)
{
test_alter() if (($pid=fork()) == 0); $work{$pid}="alter";
}
$threads+=$i;
print "Started $threads threads\n";
$errors=0;
$running_insert_threads=$opt_insert;
while (($pid=wait()) != -1)
{
$ret=$?/256;
print "thread '" . $work{$pid} . "' finished with exit code $ret\n";
if ($opt_time == 0)
{
if ($work{$pid} =~ /^insert/)
{
if (!--$running_insert_threads)
{
# Time to stop other threads
signal_abort();
}
}
}
$errors++ if ($ret != 0);
}
#
# Cleanup
#
if (!$opt_skip_drop && !$errors)
{
my $table_def;
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
$opt_user, $opt_password,
{ PrintError => 0}) || die $DBI::errstr;
$dbh->do("drop table $abort_table");
foreach $table_def (@testtables)
{
$dbh->do("drop table " . $table_def->[0]);
}
$dbh->disconnect; $dbh=0; # Close handler
}
print ($errors ? "Test failed\n" :"Test ok\n");
$end_time=new Benchmark;
print "Total time: " .
timestr(timediff($end_time, $start_time),"noc") . "\n";
exit(0);
#
# Sleep and then abort other threads
#
sub test_abort
{
sleep($opt_time);
signal_abort();
exit(0);
}
#
# Insert records in the table
#
sub test_insert
{
my ($from_table,$to_table)= @_;
my ($dbh,$i,$j,$count,$table_def,$table);
if (!defined($from_table))
{
$from_table=0; $to_table=$numtables-1;
}
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
$opt_user, $opt_password,
{ PrintError => 0}) || die $DBI::errstr;
for ($i=$count=0 ; $i < $opt_loop_count; $i++)
{
for ($j= $from_table ; $j <= $to_table ; $j++)
{
my ($table)= ($testtables[$j]->[0]);
$dbh->do("insert into $table values (NULL,'This is entry $i','',0)") || die "Got error on insert: $DBI::errstr\n";
$count++;
}
}
$dbh->disconnect; $dbh=0;
print "Test_insert: Inserted $count rows\n";
exit(0);
}
#
# select records
# Do continously select over all tables as long as there is changed
# rows in the table
#
sub test_select
{
my ($dbh, $i, $j, $count, $loop);
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
$opt_user, $opt_password,
{ PrintError => 0}) || die $DBI::errstr;
$count_query=make_count_query($numtables);
$count=0;
$loop=9999;
$i=0;
while (($i++ % 100) || !test_if_abort($dbh))
{
if ($loop++ >= 100)
{
$loop=0;
$row_counts=simple_query($dbh, $count_query);
}
for ($j=0 ; $j < $numtables ; $j++)
{
my ($id)= int rand $row_counts->[$j];
my ($table)= $testtables[$j]->[0];
simple_query($dbh, "select id,info from $table where id=$id");
$count++;
}
}
$dbh->disconnect; $dbh=0;
print "Test_select: Executed $count selects\n";
exit(0);
}
#
# Do big select count(distinct..) over the table
#
sub test_select_count
{
my ($dbh, $i, $j, $count, $loop);
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
$opt_user, $opt_password,
{ PrintError => 0}) || die $DBI::errstr;
$count=0;
$i=0;
while (!test_if_abort($dbh))
{
for ($j=0 ; $j < $numtables ; $j++)
{
my ($table)= $testtables[$j]->[0];
simple_query($dbh, "select count(distinct marker),count(distinct id),count(distinct info) from $table");
$count++;
}
sleep(20); # This query is quite slow
}
$dbh->disconnect; $dbh=0;
print "Test_select: Executed $count select count(distinct) queries\n";
exit(0);
}
#
# select records
# Do continously joins between the first and second table
#
sub test_join
{
my ($dbh, $i, $j, $count, $loop);
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
$opt_user, $opt_password,
{ PrintError => 0}) || die $DBI::errstr;
$count_query=make_count_query($numtables);
$count=0;
$loop=9999;
$i=0;
while (($i++ % 100) || !test_if_abort($dbh))
{
if ($loop++ >= 100)
{
$loop=0;
$row_counts=simple_query($dbh, $count_query);
}
for ($j=0 ; $j < $numtables-1 ; $j++)
{
my ($id)= int rand $row_counts->[$j];
my ($t1,$t2)= ($testtables[$j]->[0],$testtables[$j+1]->[0]);
simple_query($dbh, "select $t1.id,$t2.info from $t1, $t2 where $t1.id=$t2.id and $t1.id=$id");
$count++;
}
}
$dbh->disconnect; $dbh=0;
print "Test_join: Executed $count joins\n";
exit(0);
}
#
# select records
# Do continously joins between the first and second for range and count selected rows
#
sub test_join_count
{
my ($dbh, $i, $j, $count, $loop);
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
$opt_user, $opt_password,
{ PrintError => 0}) || die $DBI::errstr;
$count_query=make_count_query($numtables);
$count=0;
$loop=9999;
$sum=0;
srand();
$i=0;
while (($i++ % 10) || !test_if_abort($dbh))
{
if ($loop++ >= 10)
{
$loop=0;
$row_counts=simple_query($dbh, $count_query);
}
for ($j=0 ; $j < $numtables-1 ; $j++)
{
my ($id1)= int rand $row_counts->[$j];
my ($id2)= int rand $row_counts->[$j];
if ($id1 > $id2)
{
my $id0=$id1; $id1=$id2; $id2=$id0;
if ($id2-$id1 > $opt_join_range)
{
$id2=$id1+$opt_join_range;
}
}
my ($t1,$t2)= ($testtables[$j]->[0],$testtables[$j+1]->[0]);
$row=simple_query($dbh, "select count(*) from $t1, $t2 where $t1.id=$t2.id and $t1.id between $id1 and $id2");
$sum+=$row->[0];
$count++;
}
}
$dbh->disconnect; $dbh=0;
print "Test_join_count: Executed $count joins: total $sum rows\n";
exit(0);
}
#
# Delete 1-5 rows from the first 2 tables.
# Test ends when the number of rows for table 3 didn't change during
# one loop
#
sub test_delete
{
my ($dbh, $i,$j, $row_counts, $count_query, $table_count, $count);
$table_count=2;
$count=0;
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
$opt_user, $opt_password,
{ PrintError => 0}) || die $DBI::errstr;
$count_query=make_count_query($table_count+1);
sleep(5); # Give time to insert some rows
$i=0;
while (($i++ % 10) || !test_if_abort($dbh))
{
sleep(1);
$row_counts=simple_query($dbh, $count_query);
for ($j=0 ; $j < $table_count ; $j++)
{
my ($id)= int rand $row_counts->[$j];
my ($table)= $testtables[$j]->[0];
$dbh->do("delete from $table where id >= $id-2 and id <= $id +2") || die "Got error on delete from $table: $DBI::errstr\n";
$count++;
}
}
$dbh->disconnect; $dbh=0;
print "Test_delete: Executed $count deletes\n";
exit(0);
}
#
# Update the flag for table 2 and 3
# Will abort after a while when table1 doesn't change max value
#
sub test_update
{
my ($dbh, $i, $j, $row_counts, $count_query, $count, $loop);
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
$opt_user, $opt_password,
{ PrintError => 0}) || die $DBI::errstr;
$count_query=make_count_query(3);
$loop=9999;
$count=0;
sleep(5); # Give time to insert some rows
$i=0;
while (($i++ % 100) || !test_if_abort($dbh))
{
if ($loop++ >= 100)
{
$loop=0;
$row_counts=simple_query($dbh, $count_query);
}
for ($j=1 ; $j <= 2 ; $j++)
{
my ($id)= int rand $row_counts->[$j];
my ($table)= $testtables[$j]->[0];
# Fix to not change the same rows as the above delete
$id= ($id + $count) % $row_counts->[$j];
$dbh->do("update $table set flag=flag+1 where id >= $id-2 and id <= $id +2") || die "Got error on update of $table: $DBI::errstr\n";
$count++;
}
}
$dbh->disconnect; $dbh=0;
print "Test_update: Executed $count updates\n";
exit(0);
}
#
# Run a check on all tables except the last one
# (The last one is not checked to put pressure on the key cache)
#
sub test_check
{
my ($dbh, $row, $i, $j, $type, $table);
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
$opt_user, $opt_password,
{ PrintError => 0}) || die $DBI::errstr;
$type= "check";
for ($i=$j=0 ; !test_if_abort($dbh) ; $i++)
{
sleep(1000);
$table=$testtables[$j]->[0];
$sth=$dbh->prepare("$type table $table") || die "Got error on prepare: $DBI::errstr\n";
$sth->execute || die $DBI::errstr;
while (($row=$sth->fetchrow_arrayref))
{
if ($row->[3] ne "OK")
{
print "Got error " . $row->[3] . " when doing $type on $table\n";
exit(1);
}
}
if (++$j == $numtables-1)
{
$j=0;
}
}
$dbh->disconnect; $dbh=0;
print "test_check: Executed $i checks\n";
exit(0);
}
#
# Do a repair on the first table once in a while
#
sub test_repair
{
my ($dbh, $row, $i, $type, $table);
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
$opt_user, $opt_password,
{ PrintError => 0}) || die $DBI::errstr;
$type= "repair";
for ($i=0 ; !test_if_abort($dbh) ; $i++)
{
sleep(2000);
$table=$testtables[0]->[0];
$sth=$dbh->prepare("$type table $table") || die "Got error on prepare: $DBI::errstr\n";
$sth->execute || die $DBI::errstr;
while (($row=$sth->fetchrow_arrayref))
{
if ($row->[3] ne "OK")
{
print "Got error " . $row->[3] . " when doing $type on $table\n";
exit(1);
}
}
}
$dbh->disconnect; $dbh=0;
print "test_repair: Executed $i repairs\n";
exit(0);
}
#
# Do a flush tables on table 3 and 4 once in a while
#
sub test_flush
{
my ($dbh,$count,$tables);
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
$opt_user, $opt_password,
{ PrintError => 0}) || die $DBI::errstr;
$tables=$testtables[2]->[0] . "," . $testtables[3]->[0];
$count=0;
while (!test_if_abort($dbh))
{
sleep(3000);
$dbh->do("flush tables $tables") ||
die "Got error on flush $DBI::errstr\n";
$count++;
}
$dbh->disconnect; $dbh=0;
print "flush: Executed $count flushs\n";
exit(0);
}
#
# Test all tables in a database
#
sub test_database
{
my ($database) = @_;
my ($dbh, $row, $i, $type, $tables);
$dbh = DBI->connect("DBI:mysql:$database:$opt_host",
$opt_user, $opt_password,
{ PrintError => 0}) || die $DBI::errstr;
$tables= join(',',$dbh->func('_ListTables'));
$type= "check";
for ($i=0 ; !test_if_abort($dbh) ; $i++)
{
sleep(120);
$sth=$dbh->prepare("$type table $tables") || die "Got error on prepare: $DBI::errstr\n";
$sth->execute || die $DBI::errstr;
while (($row=$sth->fetchrow_arrayref))
{
if ($row->[3] ne "OK")
{
print "Got error " . $row->[2] . " " . $row->[3] . " when doing $type on " . $row->[0] . "\n";
exit(1);
}
}
}
$dbh->disconnect; $dbh=0;
print "test_check: Executed $i checks\n";
exit(0);
}
#
# Test ALTER TABLE on the second table
#
sub test_alter
{
my ($dbh, $row, $i, $type, $table);
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
$opt_user, $opt_password,
{ PrintError => 0}) || die $DBI::errstr;
for ($i=0 ; !test_if_abort($dbh) ; $i++)
{
sleep(100);
$table=$testtables[1]->[0];
$sth=$dbh->prepare("ALTER table $table modify info char(32)") || die "Got error on prepare: $DBI::errstr\n";
$sth->execute || die $DBI::errstr;
}
$dbh->disconnect; $dbh=0;
print "test_alter: Executed $i ALTER TABLE\n";
exit(0);
}
#
# Help functions
#
sub signal_abort
{
my ($dbh);
$dbh = DBI->connect("DBI:mysql:$opt_db:$opt_host",
$opt_user, $opt_password,
{ PrintError => 0}) || die $DBI::errstr;
$dbh->do("insert into $abort_table values(1)") || die $DBI::errstr;
$dbh->disconnect; $dbh=0;
}
sub test_if_abort()
{
my ($dbh)=@_;
$row=simple_query($dbh,"select * from $opt_db.$abort_table");
return (defined($row) && defined($row->[0]) != 0) ? 1 : 0;
}
sub make_count_query
{
my ($table_count)= @_;
my ($tables, $count_query, $i, $tables_def);
$tables="";
$count_query="select high_priority ";
$table_count--;
for ($i=0 ; $i < $table_count ; $i++)
{
my ($table_def)= $testtables[$i];
$tables.=$table_def->[0] . ",";
$count_query.= "max(" . $table_def->[0] . ".id),";
}
$table_def=$testtables[$table_count];
$tables.=$table_def->[0];
$count_query.= "max(" . $table_def->[0] . ".id) from $tables";
return $count_query;
}
sub simple_query()
{
my ($dbh, $query)= @_;
my ($sth,$row);
$sth=$dbh->prepare($query) || die "Got error on '$query': " . $dbh->errstr . "\n";
$sth->execute || die "Got error on '$query': " . $dbh->errstr . "\n";
$row= $sth->fetchrow_arrayref();
$sth=0;
return $row;
}