mysql-test/r/derived.result:
  Auto merged
mysql-test/r/func_str.result:
  Auto merged
mysql-test/r/select.result:
  Auto merged
mysql-test/r/subselect.result:
  Auto merged
mysql-test/r/union.result:
  Auto merged
mysql-test/t/func_str.test:
  Auto merged
sql/field.cc:
  Auto merged
sql/field.h:
  Auto merged
sql/item.h:
  Auto merged
sql/item_subselect.cc:
  Auto merged
sql/item_subselect.h:
  Auto merged
sql/item_sum.cc:
  Auto merged
sql/item_sum.h:
  Auto merged
sql/mysql_priv.h:
  Auto merged
sql/mysqld.cc:
  Auto merged
sql/sql_acl.cc:
  Auto merged
sql/sql_analyse.cc:
  Auto merged
sql/sql_class.cc:
  Auto merged
sql/sql_select.cc:
  Auto merged
This commit is contained in:
unknown 2002-12-14 17:49:01 +02:00
commit 5a9437ac05
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;
uchar *null_ptr= (uchar*) *row, bit;
*row+= (stmt->field_count+7)/8;
bit=1;
row+= (stmt->field_count+9)/8;
bit= 4; /* First 2 bits are reserved */
/* Copy complete row to application buffers */
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_uniq.cc item_subselect.cc item_row.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 \
repl_failsafe.cc slave.cc sql_load.cc sql_olap.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
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
ok
0
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
ok
0
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
a

View File

@ -24,10 +24,10 @@ cast("A" as binary) = "a" cast(BINARY "a" as CHAR) = "A"
0 1
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)
2001-1-1 2001-1-1
2001-01-01 2001-01-01 00:00:00
select 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";
cast("2001-1-1" as date) = "2001-01-01"
0

View File

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

View File

@ -114,7 +114,7 @@ a t
20 20
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
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
drop table if exists t1;
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;
explain select 1;
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
having mts < DATE_SUB(NOW(),INTERVAL 3 MONTH);
visitor_id mts
48985536 20000319013932
173865424 20000318233615
357917728 20000319145027
465931136 20000318160953
1092858576 20000319013445
48985536 2000-03-19 01:39:32
173865424 2000-03-18 23:36:15
357917728 2000-03-19 14:50:27
465931136 2000-03-18 16:09:53
1092858576 2000-03-19 01:34:45
select visitor_id,max(ts) as mts from t1 group by visitor_id
having DATE_ADD(mts,INTERVAL 3 MONTH) < NOW();
visitor_id mts
48985536 20000319013932
173865424 20000318233615
357917728 20000319145027
465931136 20000318160953
1092858576 20000319013445
48985536 2000-03-19 01:39:32
173865424 2000-03-18 23:36:15
357917728 2000-03-19 14:50:27
465931136 2000-03-18 16:09:53
1092858576 2000-03-19 01:34:45
drop table t1;

View File

@ -228,14 +228,14 @@ bugstatus int(10) unsigned default NULL,
submitter int(10) unsigned default NULL
) TYPE=MyISAM;
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;
CONCAT('"',CONCAT_WS('";"',title,prio,category,program,bugdesc,created,modified,bugstatus,submitter), '"')
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+0,bugstatus,submitter), '"')
"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;
CONCAT('"',CONCAT_WS('";"',title,prio,category,program,bugstatus,submitter), '"')
"Link";"1";"1";"1";"0";"4"
SELECT CONCAT_WS('";"',title,prio,category,program,bugdesc,created,modified,bugstatus,submitter) FROM t1;
CONCAT_WS('";"',title,prio,category,program,bugdesc,created,modified,bugstatus,submitter)
SELECT CONCAT_WS('";"',title,prio,category,program,bugdesc,created,modified+0,bugstatus,submitter) FROM t1;
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
drop table t1;
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");
select * from t1, t2 where t1.start between t2.ctime1 and t2.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;
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;
start ctime1 ctime2
2002-11-04 00:00:00 2002-10-29 16:51:06 2002-11-05 16:47:31
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);
select * from t1;
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
9197722223 berry 90 3 20020111112809 500 20020102114532 501 4 10 0
650 San Francisco 0 0 20011227111336 342 00000000000000 -1 1 24 1
302467 Sue's Subshop 90 3 20020109113241 500 20020102115111 501 7 24 0
6014911113 SudzCarwash 520 1 20020102115234 500 20020102115259 501 33 32768 0
333 tubs 99 2 20020109113440 501 20020109113440 500 3 10 0
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 2002-01-11 11:28:09 500 2002-01-02 11:45:32 501 4 10 0
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 2002-01-09 11:32:41 500 2002-01-02 11:51:11 501 7 24 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 2002-01-09 11:34:40 501 2002-01-09 11:34:40 500 3 10 0
select * from t2;
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
9197722223 berry 90 3 20020111112818 500 20020102114532 501 4 10 0
650 San Francisco 90 0 20020109113158 342 00000000000000 -1 1 24 1
333 tubs 99 2 20020109113453 501 20020109113453 500 3 10 0
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 2002-01-11 11:28:18 500 2002-01-02 11:45:32 501 4 10 0
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 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);
select * from t1;
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
333 tubs 99 2 20020109113440 501 20020109113440 500 3 10 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 2002-01-09 11:34:40 501 2002-01-09 11:34:40 500 3 10 0
select * from t2;
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;
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;
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;

View File

@ -91,7 +91,7 @@ grp a c id a c d
NULL NULL NULL NULL NULL NULL
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
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;
id select_type table type possible_keys key key_len ref rows Extra
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
describe select * from t1 where t1="ABCD";
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;

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");
select * from t1;
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;
t1.time+0 t1.date+0 t1.timestamp+0 concat(date," ",time)
122222 19970203 19970102000000 1997-02-03 12:22:22

View File

@ -560,7 +560,7 @@ select * from t6;
a
1
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;
CREATE TABLE t1 (
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;
id select_type table type possible_keys key key_len ref rows Extra
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
explain select * from t1 where b is null;
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;

View File

@ -16,7 +16,7 @@ event_date type event_id
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;
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;
event_date type event_id
1999-07-10 100100 24

View File

@ -3097,7 +3097,7 @@ fld1 sum(price)
038008 234298
explain select fld3 from t2 where 1>2 or 2>3;
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;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 ALL NULL NULL NULL NULL 1199
@ -3152,7 +3152,7 @@ count(*)
4181
explain select min(fld1),max(fld1),count(*) from t2;
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;
min(fld1) max(fld1) count(*)
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;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> system NULL NULL NULL NULL 1
3 DEPENDENT SUBSELECT No tables used
2 DERIVED No tables used
3 DEPENDENT SUBSELECT NULL NULL NULL NULL NULL NULL NULL 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;
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
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
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
SELECT DISTINCT date FROM t1 WHERE date='2002-08-03';
date
@ -298,8 +298,8 @@ Subselect returns more than 1 record
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
1 PRIMARY t1 index NULL topic 3 NULL 2 Using index
2 SUBSELECT No tables used
3 UNION No tables used
2 SUBSELECT NULL NULL NULL NULL NULL NULL NULL No tables used
3 UNION NULL NULL NULL NULL NULL NULL NULL No tables used
drop table t1;
CREATE TABLE `t1` (
`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
EXPLAIN SELECT MAX(numreponse) FROM t1 WHERE numeropost='1';
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');
id select_type table type possible_keys key key_len ref rows Extra
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;
CREATE TABLE t1 (a int(1));
INSERT INTO t1 VALUES (1);
@ -574,14 +574,14 @@ id
EXPLAIN SELECT * FROM t WHERE id IN (SELECT 1+(select 1));
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
3 SUBSELECT No tables used
3 SUBSELECT NULL NULL NULL NULL NULL NULL NULL No tables used
Warnings:
Note 1247 Select 2 was reduced during optimisation
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
1 PRIMARY t index NULL id 5 NULL 2 Using where; Using index
2 DEPENDENT SUBSELECT No tables used
3 UNION No tables used
2 DEPENDENT SUBSELECT NULL NULL NULL NULL NULL NULL NULL 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);
id
SELECT * FROM t WHERE id IN (SELECT 5 UNION SELECT 2);

View File

@ -41,8 +41,8 @@ t
drop table t1;
CREATE TABLE t1 (a timestamp, b date, c time, d datetime);
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;
date_format(a,"%Y-%m-%d")=b right(a,6)=c+0 a=d+0
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+0,6)=c+0 a=d+0
1 1 1
drop table t1;
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
ulong int(11) 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
time_field time 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
ulong int(11) 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
time_field time 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
ulong int(11) 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
time_field time 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;
select * from t1;
a t
1 19700101032034
2 20020303000000
3 19700101032035
4 19700101032036
5 20020304000000
6 19700101032037
7 20020305000000
8 00000000000000
9 19700101032038
1 1970-01-01 03:20:34
2 2002-03-03 00:00:00
3 1970-01-01 03:20:35
4 1970-01-01 03:20:36
5 2002-03-04 00:00:00
6 1970-01-01 03:20:37
7 2002-03-05 00:00:00
8 0000-00-00 00:00:00
9 1970-01-01 03:20:38
drop table t1,t2;
SET TIMESTAMP=1234;
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");
SELECT stamp FROM t1 WHERE id="myKey";
stamp
19990402000000
1999-04-02 00:00:00
UPDATE t1 SET value="my value" WHERE id="myKey";
SELECT stamp FROM t1 WHERE id="myKey";
stamp
19990402000000
1999-04-02 00:00:00
drop table t1;
create table t1 (a timestamp);
insert into t1 values (now());
@ -44,8 +44,8 @@ date_format(a,"%Y %y") year(a) year(now())
drop table t1;
create table t1 (ix timestamp);
insert into t1 values (19991101000000),(19990102030405),(19990630232922),(19990601000000),(19990930232922),(19990531232922),(19990501000000),(19991101000000),(19990501000000);
select * from t1;
ix
select ix+0 from t1;
ix+0
19991101000000
19990102030405
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);
SELECT * FROM t1;
date date_time time_stamp
1998-12-31 1998-12-31 23:59:59 19981231235959
1999-01-01 1999-01-01 00:00:00 19990101000000
1999-09-09 1999-09-09 23:59:59 19990909235959
2000-01-01 2000-01-01 00:00:00 20000101000000
2000-02-28 2000-02-28 00:00:00 20000228000000
2000-02-29 2000-02-29 00:00:00 20000229000000
2000-03-01 2000-03-01 00:00:00 20000301000000
2000-12-31 2000-12-31 23:59:59 20001231235959
2001-01-01 2001-01-01 00:00:00 20010101000000
2004-12-31 2004-12-31 23:59:59 20041231235959
2005-01-01 2005-01-01 00:00:00 20050101000000
2030-01-01 2030-01-01 00:00:00 20300101000000
1998-12-31 1998-12-31 23:59:59 1998-12-31 23:59:59
1999-01-01 1999-01-01 00:00:00 1999-01-01 00:00:00
1999-09-09 1999-09-09 23:59:59 1999-09-09 23:59:59
2000-01-01 2000-01-01 00:00:00 2000-01-01 00:00:00
2000-02-28 2000-02-28 00:00:00 2000-02-28 00:00:00
2000-02-29 2000-02-29 00:00:00 2000-02-29 00:00:00
2000-03-01 2000-03-01 00:00:00 2000-03-01 00:00:00
2000-12-31 2000-12-31 23:59:59 2000-12-31 23:59:59
2001-01-01 2001-01-01 00:00:00 2001-01-01 00:00:00
2004-12-31 2004-12-31 23:59:59 2004-12-31 23:59:59
2005-01-01 2005-01-01 00:00:00 2005-01-01 00:00:00
2030-01-01 2030-01-01 00:00:00 2030-01-01 00:00:00
drop table t1;

View File

@ -102,16 +102,16 @@ Unknown column 'xx' in 'field list'
explain select a,b from t1 union select 1;
id select_type table type possible_keys key key_len ref rows Extra
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;
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
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;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY Impossible WHERE
2 UNION Impossible WHERE
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL 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;
Wrong usage of UNION and INTO
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;
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_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;
#

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, t3 where t1.start between t3.ctime1 and t3.ctime2;
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);
create temporary table t6 (a int not null) TYPE=MERGE UNION=(t4,t5);
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
@ -235,5 +235,5 @@ EXPLAIN SELECT * FROM t1 WHERE fileset_id = 2
AND file_code BETWEEN '0000000115' AND '0000000120' LIMIT 1;
EXPLAIN SELECT * FROM t2 WHERE fileset_id = 2
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);
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;
#

View File

@ -35,7 +35,7 @@ drop table t1;
create table t1 (ix timestamp);
insert into t1 values (19991101000000),(19990102030405),(19990630232922),(19990601000000),(19990930232922),(19990531232922),(19990501000000),(19991101000000),(19990501000000);
select * from t1;
select ix+0 from t1;
drop table t1;
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 \
item_row.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 \
mysqld.cc password.c hash_filo.cc hostname.cc \
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];
String tmp(buff,sizeof(buff),default_charset_info);
val_str(&tmp,&tmp);
CONVERT *convert;
if ((convert=thd->variables.convert_set))
return convert->store(packet,tmp.ptr(),tmp.length());
return net_store_data(packet,tmp.ptr(),tmp.length());
return protocol->store(tmp.ptr(), tmp.length());
}
@ -1074,6 +1069,10 @@ String *Field_tiny::val_str(String *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)
{
@ -1285,6 +1284,7 @@ longlong Field_short::val_int(void)
return unsigned_flag ? (longlong) (unsigned short) j : (longlong) j;
}
String *Field_short::val_str(String *val_buffer,
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)
{
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)
{
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)
{
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)
{
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
{
if (dec == NOT_FIXED_DEC)
@ -2499,6 +2528,11 @@ String *Field_double::val_str(String *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)
{
@ -2568,10 +2602,10 @@ void Field_double::sql_type(String &res) const
Field_timestamp::Field_timestamp(char *ptr_arg, uint32 len_arg,
enum utype unireg_check_arg,
const char *field_name_arg,
struct st_table *table_arg)
:Field_num(ptr_arg, len_arg, (uchar*) 0,0,
unireg_check_arg, field_name_arg, table_arg,
0, 1, 1)
struct st_table *table_arg,
CHARSET_INFO *cs)
:Field_str(ptr_arg, 19, (uchar*) 0,0,
unireg_check_arg, field_name_arg, table_arg, cs)
{
if (table && !table->timestamp_field)
{
@ -2596,35 +2630,6 @@ int Field_timestamp::store(const char *from,uint len,CHARSET_INFO *cs)
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 error= 0;
@ -2735,44 +2740,34 @@ longlong Field_timestamp::val_int(void)
time_arg=(time_t) temp;
localtime_r(&time_arg,&tm_tmp);
l_time=&tm_tmp;
res=(longlong) 0;
for (pos=len=0; len+1 < (uint) field_length ; len+=2,pos++)
{
bool year_flag=0;
switch (dayord.pos[pos]) {
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))
{
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;
part_time= l_time->tm_year % 100;
res= ((longlong) (part_time+ ((part_time < YY_PART_YEAR) ? 2000 : 1900))*
LL(10000000000));
part_time= l_time->tm_mon+1;
res+= (longlong) part_time * LL(100000000);
part_time=l_time->tm_mday;
res+= (longlong) ((long) part_time * 1000000L);
part_time=l_time->tm_hour;
res+= (longlong) (part_time * 10000L);
part_time=l_time->tm_min;
res+= (longlong) (part_time * 100);
part_time=l_time->tm_sec;
return res+part_time;
}
String *Field_timestamp::val_str(String *val_buffer,
String *val_ptr __attribute__((unused)))
{
uint pos;
int part_time;
uint32 temp;
uint32 temp, temp2;
time_t time_arg;
struct tm *l_time;
struct tm tm_tmp;
val_buffer->alloc(field_length+1);
char *to=(char*) val_buffer->ptr(),*end=to+field_length;
val_buffer->length(field_length);
#ifdef WORDS_BIGENDIAN
if (table->db_low_byte_first)
@ -2783,44 +2778,57 @@ String *Field_timestamp::val_str(String *val_buffer,
if (temp == 0L)
{ /* Zero time is "000000" */
VOID(strfill(to,field_length,'0'));
val_buffer->length(field_length);
strmov(to, "0000-00-00 00:00:00");
return val_buffer;
}
time_arg=(time_t) temp;
localtime_r(&time_arg,&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;
switch (dayord.pos[pos]) {
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
{
*to++='1'; *to++='9';
}
}
*to++=(char) ('0'+((uint) part_time/10));
*to++=(char) ('0'+((uint) part_time % 10));
*to++= '2';
*to++= '0';
}
*to=0; // Safeguard
val_buffer->length((uint) (to-val_buffer->ptr()));
else
{
*to++= '1';
*to++= '9';
}
temp2=temp/10; temp=temp-temp2*10;
*to++= (char) ('0'+(char) (temp2));
*to++= (char) ('0'+(char) (temp));
*to++= '-';
temp=l_time->tm_mon+1;
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;
}
bool Field_timestamp::get_date(TIME *ltime, bool fuzzydate)
{
long temp;
@ -2860,6 +2868,15 @@ bool Field_timestamp::get_time(TIME *ltime)
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)
{
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;
}
void Field_timestamp::sort_string(char *to,uint length __attribute__((unused)))
{
#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
{
ulong length= my_sprintf((char*) res.ptr(),
((char*) res.ptr(),"timestamp(%d)",
(int) field_length));
res.length(length);
res.set("timestamp", 9, default_charset_info);
}
@ -3068,6 +3083,17 @@ bool Field_time::get_time(TIME *ltime)
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)
{
int32 a,b;
@ -3965,19 +3991,15 @@ int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs)
ThNormalize((uchar *) ptr+2, field_length, (uchar *) from, length);
}
#else
if (length <= field_length)
{
memcpy(ptr+2,from,length);
}
else
if (length > field_length)
{
length=field_length;
memcpy(ptr+2,from,field_length);
current_thd->cuted_fields++;
error= 1;
}
memcpy(ptr+2,from,length);
#endif /* USE_TIS620 */
int2store(ptr,length);
int2store(ptr, length);
return error;
}
@ -4176,6 +4198,28 @@ uint Field_varstring::max_packed_col_length(uint 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
** 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;
}
length-=HA_KEY_BLOB_LENGTH;
if ((uint32) length > blob_length)
{
#ifdef HAVE_purify
@ -5258,7 +5301,7 @@ Field *make_field(char *ptr, uint32 field_length,
f_is_dec(pack_flag) == 0);
case FIELD_TYPE_TIMESTAMP:
return new Field_timestamp(ptr,field_length,
unireg_check, field_name, table);
unireg_check, field_name, table, field_charset);
case FIELD_TYPE_YEAR:
return new Field_year(ptr,field_length,null_pos,null_bit,
unireg_check, field_name, table);

View File

@ -27,10 +27,12 @@
#define NOT_FIXED_DEC 31
class Send_field;
class Protocol;
struct st_cache_field;
void field_conv(Field *to,Field *from);
class Field {
class Field
{
Field(const Item &); /* Prevent use of these */
void operator=(Field &);
public:
@ -164,7 +166,7 @@ public:
ptr-=row_offset;
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)
{
uint32 length=pack_length();
@ -268,11 +270,11 @@ public:
void set_charset(CHARSET_INFO *charset) { field_charset=charset; }
bool binary() const { return field_charset->state & MY_CS_BINSORT ? 1 : 0; }
inline int cmp_image(char *buff,uint length)
{
if (binary())
return memcmp(ptr,buff,length);
else
return my_strncasecmp(field_charset,ptr,buff,length);
{
if (binary())
return memcmp(ptr,buff,length);
else
return my_strncasecmp(field_charset,ptr,buff,length);
}
friend class create_field;
};
@ -291,7 +293,7 @@ public:
{}
enum_field_types type() const { return FIELD_TYPE_DECIMAL;}
enum ha_base_keytype key_type() const
{ return zerofill ? HA_KEYTYPE_BINARY : HA_KEYTYPE_NUM; }
{ return zerofill ? HA_KEYTYPE_BINARY : HA_KEYTYPE_NUM; }
void reset(void);
int store(const char *to,uint length,CHARSET_INFO *charset);
int store(double nr);
@ -329,6 +331,7 @@ public:
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
bool send_binary(Protocol *protocol);
int cmp(const char *,const char*);
void sort_string(char *buff,uint length);
uint32 pack_length() const { return 1; }
@ -358,6 +361,7 @@ public:
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
bool send_binary(Protocol *protocol);
int cmp(const char *,const char*);
void sort_string(char *buff,uint length);
uint32 pack_length() const { return 2; }
@ -387,6 +391,7 @@ public:
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
bool send_binary(Protocol *protocol);
int cmp(const char *,const char*);
void sort_string(char *buff,uint length);
uint32 pack_length() const { return 3; }
@ -420,6 +425,7 @@ public:
void reset(void) { ptr[0]=ptr[1]=ptr[2]=ptr[3]=0; }
double val_real(void);
longlong val_int(void);
bool send_binary(Protocol *protocol);
String *val_str(String*,String *);
int cmp(const char *,const char*);
void sort_string(char *buff,uint length);
@ -457,6 +463,7 @@ public:
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
bool send_binary(Protocol *protocol);
int cmp(const char *,const char*);
void sort_string(char *buff,uint length);
uint32 pack_length() const { return 8; }
@ -485,6 +492,7 @@ public:
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
bool send_binary(Protocol *protocol);
int cmp(const char *,const char*);
void sort_string(char *buff,uint length);
uint32 pack_length() const { return sizeof(float); }
@ -517,6 +525,7 @@ public:
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
bool send_binary(Protocol *protocol);
int cmp(const char *,const char*);
void sort_string(char *buff,uint length);
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:
Field_timestamp(char *ptr_arg, uint32 len_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg);
enum Item_result result_type () const { return field_length == 8 || field_length == 14 ? INT_RESULT : STRING_RESULT; }
struct st_table *table_arg,
CHARSET_INFO *cs);
enum_field_types type() const { return FIELD_TYPE_TIMESTAMP;}
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(double nr);
int store(longlong nr);
@ -567,6 +577,7 @@ public:
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
bool send_binary(Protocol *protocol);
int cmp(const char *,const char*);
void sort_string(char *buff,uint length);
uint32 pack_length() const { return 4; }
@ -588,7 +599,6 @@ public:
longget(tmp,ptr);
return tmp;
}
void fill_and_store(char *from,uint len);
bool get_date(TIME *ltime,bool fuzzydate);
bool get_time(TIME *ltime);
};
@ -610,6 +620,7 @@ public:
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
bool send_binary(Protocol *protocol);
void sql_type(String &str) const;
};
@ -636,6 +647,7 @@ public:
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
bool send_binary(Protocol *protocol);
int cmp(const char *,const char*);
void sort_string(char *buff,uint length);
uint32 pack_length() const { return 4; }
@ -664,6 +676,7 @@ public:
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
bool send_binary(Protocol *protocol);
int cmp(const char *,const char*);
void sort_string(char *buff,uint length);
uint32 pack_length() const { return 3; }
@ -697,6 +710,7 @@ public:
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
bool send_binary(Protocol *protocol);
bool get_time(TIME *ltime);
int cmp(const char *,const char*);
void sort_string(char *buff,uint length);
@ -732,6 +746,7 @@ public:
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
bool send_binary(Protocol *protocol);
int cmp(const char *,const char*);
void sort_string(char *buff,uint length);
uint32 pack_length() const { return 8; }
@ -772,6 +787,7 @@ public:
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
bool send_binary(Protocol *protocol);
int cmp(const char *,const char*);
void sort_string(char *buff,uint length);
void sql_type(String &str) const;
@ -812,8 +828,11 @@ public:
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
bool send_binary(Protocol *protocol);
int cmp(const char *,const char*);
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;
char *pack(char *to, const char *from, uint max_length=~(uint) 0);
const char *unpack(char* to, const char *from);
@ -852,6 +871,7 @@ public:
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
bool send_binary(Protocol *protocol);
int cmp(const char *,const char*);
int cmp(const char *a, uint32 a_length, const char *b, uint32 b_length);
int cmp_offset(uint offset);
@ -957,6 +977,7 @@ public:
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
bool send_binary(Protocol *protocol);
int cmp(const char *,const char*);
void sort_string(char *buff,uint length);
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;
String *packet= &thd->packet;
int error=1;
MEM_ROOT show_logs_root;
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);
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))
|| (error= db_env->log_archive(db_env, &free_logs, DB_ARCH_ABS)))
if ((error= db_env->log_archive(db_env, &all_logs,
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));
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)
{
packet->length(0);
net_store_data(packet,*a);
net_store_data(packet,"BDB");
protocol->prepare_for_resend();
protocol->store(*a);
protocol->store("BDB", 3);
if (f && *f && strcmp(*a, *f) == 0)
{
++f;
net_store_data(packet, SHOW_LOG_STATUS_FREE);
f++;
protocol->store(SHOW_LOG_STATUS_FREE);
}
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;
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,
const char *msg_type, const char *fmt, ...)
{
String* packet = &thd->packet;
packet->length(0);
Protocol *protocol= thd->protocol;
char msgbuf[256];
msgbuf[0] = 0;
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);
msgbuf[sizeof(msgbuf) - 1] = 0; // healthy paranoia
DBUG_PRINT(msg_type,("message: %s",msgbuf));
net_store_data(packet, table_name);
net_store_data(packet, op_name);
net_store_data(packet, msg_type);
net_store_data(packet, msgbuf);
if (my_net_write(&thd->net, (char*)thd->packet.ptr(),
thd->packet.length()))
protocol->prepare_for_resend();
protocol->store(table_name);
protocol->store(op_name);
protocol->store(msg_type);
protocol->store(msgbuf);
if (protocol->write())
thd->killed=1;
}
#endif

View File

@ -180,4 +180,4 @@ bool berkeley_end(void);
bool berkeley_flush_logs(void);
int berkeley_commit(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 */
{
String* packet = &thd->packet;
char* buf;
Protocol *protocol= thd->protocol;
DBUG_ENTER("innodb_show_status");
if (innodb_skip) {
@ -3945,22 +3944,17 @@ innodb_show_status(
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);
}
packet->length(0);
net_store_data(packet, buf);
if (my_net_write(&thd->net, (char*)thd->packet.ptr(),
packet->length())) {
ut_free(buf);
DBUG_RETURN(-1);
}
protocol->prepare_for_resend();
protocol->store(buf, strlen(buf));
ut_free(buf);
if (protocol->write())
DBUG_RETURN(-1);
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)
{
THD* thd = (THD*)param->thd;
String* packet = &thd->packet;
uint length;
Protocol *protocol= thd->protocol;
uint length, msg_length;
char msgbuf[MI_MAX_MSG_BUF];
char name[NAME_LEN*2+2];
packet->length(0);
msgbuf[0] = 0; // healthy paranoia ?
my_vsnprintf(msgbuf, sizeof(msgbuf), fmt, args);
msg_length= my_vsnprintf(msgbuf, sizeof(msgbuf), fmt, args);
msgbuf[sizeof(msgbuf) - 1] = 0; // healthy paranoia
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);
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));
return;
}
length=(uint) (strxmov(name, param->db_name,".",param->table_name,NullS) -
name);
net_store_data(packet, name, length);
net_store_data(packet, param->op_name);
net_store_data(packet, msg_type);
net_store_data(packet, msgbuf);
if (my_net_write(&thd->net, (char*)thd->packet.ptr(), thd->packet.length()))
protocol->prepare_for_resend();
protocol->store(name, length);
protocol->store(param->op_name);
protocol->store(msg_type);
protocol->store(msgbuf, msg_length);
if (protocol->write())
sql_print_error("Failed on my_net_write, writing to stderr instead: %s\n",
msgbuf);
return;

View File

@ -22,6 +22,7 @@
#include "mysql_priv.h"
#include <m_ctype.h>
#include "my_dir.h"
#include <assert.h>
/*****************************************************************************
** 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()
{
switch (item_result_type) {
@ -671,6 +666,18 @@ void Item::init_make_field(Send_field *tmp_field,
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 */
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
}
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
*/
@ -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];
CONVERT *convert;
String s(buff,sizeof(buff),packet->charset()),*res;
if (!(res=val_str(&s)))
return net_store_null(packet);
if ((convert=thd->variables.convert_set))
return convert->store(packet,res->ptr(),res->length());
return net_store_data(packet,res->ptr(),res->length());
bool result;
enum_field_types type;
LINT_INIT(result);
switch ((type=field_type())) {
default:
case MYSQL_TYPE_NULL:
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 */
#endif
class Protocol;
struct st_table_list;
void item_init(void); /* Init item functions */
@ -54,20 +55,21 @@ public:
virtual ~Item() { name=0; } /*lint -e1509 */
void set_name(const char *str,uint length=0);
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 int save_in_field(Field *field, bool no_conversions);
virtual void save_org_in_field(Field *field)
{ (void) save_in_field(field, 1); }
virtual int save_safe_in_field(Field *field)
{ 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 Item_result result_type () const { return REAL_RESULT; }
virtual enum_field_types field_type() const;
virtual enum Type type() const =0;
virtual double val()=0;
virtual longlong val_int()=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 const char *full_name() const { return name ? name : "???"; }
virtual double val_result() { return val(); }
@ -119,10 +121,10 @@ public:
item (it assign '*ref' with field 'item' in derived classes)
*/
enum Type type() const { return item->type(); }
enum_field_types field_type() const { return item->field_type(); }
double val() { return item->val(); }
longlong val_int() { return item->val_int(); }
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 eq(const Item *item, bool binary_cmp) const
{ return item->eq(item, binary_cmp); }
@ -196,12 +198,9 @@ public:
double val_result();
longlong val_int_result();
String *str_result(String* tmp);
bool send(THD *thd, String *str_arg)
{
return result_field->send(thd,str_arg);
}
void make_field(Send_field *field);
bool send(Protocol *protocol, String *str_arg);
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);
void save_org_in_field(Field *field);
table_map used_tables() const;
@ -209,6 +208,10 @@ public:
{
return field->result_type();
}
enum_field_types field_type()
{
return field->type();
}
Field *tmp_table_field(TABLE *t_arg=(TABLE *)0) { return result_field; }
bool get_date(TIME *ltime,bool fuzzydate);
bool get_time(TIME *ltime);
@ -226,12 +229,17 @@ public:
double val();
longlong val_int();
String *val_str(String *str);
void make_field(Send_field *field);
int save_in_field(Field *field, bool no_conversions);
int save_safe_in_field(Field *field);
enum Item_result result_type () const
{ return STRING_RESULT; }
bool send(THD *thd, String *str);
enum Item_result result_type () const { return STRING_RESULT; }
enum_field_types field_type() const { return MYSQL_TYPE_NULL; }
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; }
Item *new_item() { return new Item_null(name); }
bool is_null() { return 1; }
@ -258,7 +266,6 @@ public:
double val();
longlong val_int();
String *val_str(String*);
void make_field(Send_field *field);
int save_in_field(Field *field, bool no_conversions);
void set_null();
void set_int(longlong i);
@ -272,6 +279,7 @@ public:
void (*setup_param_func)(Item_param *param, uchar **pos);
enum Item_result result_type () const
{ return item_result_type; }
enum_field_types field_type() const { return MYSQL_TYPE_STRING; }
Item *new_item() { return new Item_param(name); }
};
@ -292,11 +300,11 @@ public:
(longlong) strtoull(str_arg,(char**) 0,10))
{ max_length= (uint) strlen(str_arg); name=(char*) str_arg;}
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; }
double val() { return (double) value; }
String *val_str(String*);
void make_field(Send_field *field);
int save_in_field(Field *field, bool no_conversions);
bool basic_const_item() const { return 1; }
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) {}
double val() { return ulonglong2double(value); }
String *val_str(String*);
void make_field(Send_field *field);
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);
};
@ -339,10 +352,10 @@ public:
Item_real(double value_par) :value(value_par) {}
int save_in_field(Field *field, bool no_conversions);
enum Type type() const { return REAL_ITEM; }
enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
double val() { return value; }
longlong val_int() { return (longlong) (value+(value > 0 ? 0.5 : -0.5));}
String *val_str(String*);
void make_field(Send_field *field);
bool basic_const_item() const { return 1; }
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; }
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_field_types field_type() const { return MYSQL_TYPE_STRING; }
bool basic_const_item() const { return 1; }
bool eq(const Item *item, bool binary_cmp) const;
Item *new_item()
@ -409,7 +422,6 @@ class Item_default :public Item
public:
Item_default() { name= (char*) "DEFAULT"; }
enum Type type() const { return DEFAULT_ITEM; }
void make_field(Send_field *field) {}
int save_in_field(Field *field, bool no_conversions)
{
field->set_default();
@ -429,7 +441,7 @@ class Item_datetime :public Item_string
public:
Item_datetime(const char *item_name): Item_string(item_name,"",0,default_charset_info)
{ 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
@ -439,6 +451,20 @@ public:
{ 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
{
public:
@ -449,8 +475,8 @@ public:
longlong val_int();
String *val_str(String*) { return &str_value; }
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_field_types field_type() const { return MYSQL_TYPE_STRING; }
};
@ -505,13 +531,14 @@ public:
{
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); }
bool fix_fields(THD *, struct st_table_list *, Item **);
int save_in_field(Field *field, bool no_conversions)
{ return (*ref)->save_in_field(field, no_conversions); }
void save_org_in_field(Field *field) { (*ref)->save_org_in_field(field); }
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(); }
bool check_loop(uint id);
};
@ -597,6 +624,7 @@ public:
class Item_copy_string :public Item
{
enum enum_field_types cached_field_type;
public:
Item *item;
Item_copy_string(Item *i) :item(i)
@ -605,10 +633,12 @@ public:
decimals=item->decimals;
max_length=item->max_length;
name=item->name;
cached_field_type= item->field_type();
}
~Item_copy_string() { delete item; }
enum Type type() const { return COPY_STR_ITEM; }
enum Item_result result_type () const { return STRING_RESULT; }
enum_field_types field_type() const { return cached_field_type; }
double val()
{ return null_value ? 0.0 : my_strntod(str_value.charset(),str_value.ptr(),str_value.length(),NULL); }
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,
Item **ref)
{
if (!thd)
thd=current_thd; // Should never happen
/* fix_fields will call Item_func_set_user_var::fix_length_and_dec */
if (Item_func::fix_fields(thd, tables, ref) ||
!(entry= get_variable(&thd->user_vars, name, 1)))
return 1;

View File

@ -106,7 +106,6 @@ public:
Item_func(List<Item> &list);
~Item_func() {} /* Nothing to do; Items are freed automaticly */
bool fix_fields(THD *,struct st_table_list *, Item **ref);
void make_field(Send_field *field);
table_map used_tables() const;
void update_used_tables();
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;
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();
longlong val_int();
String *val_str(String *str);
@ -939,6 +940,11 @@ public:
void fix_length_and_dec();
void print(String *str);
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"; }
bool const_item() const { return const_var_flag; }
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)
{
if (substitution)

View File

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

View File

@ -47,28 +47,21 @@ void Item_sum::mark_as_sum_func()
with_sum_func= 1;
}
void Item_sum::make_field(Send_field *tmp_field)
{
if (args[0]->type() == Item::FIELD_ITEM && keep_field_type())
((Item_field*) args[0])->field->make_field(tmp_field);
else
{
tmp_field->flags=0;
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);
((Item_field*) args[0])->field->make_field(tmp_field);
tmp_field->db_name=(char*)"";
tmp_field->org_table_name=tmp_field->table_name=(char*)"";
tmp_field->org_col_name=tmp_field->col_name=name;
}
tmp_field->db_name=(char*)"";
tmp_field->org_table_name=tmp_field->table_name=(char*)"";
tmp_field->org_col_name=tmp_field->col_name=name;
else
init_make_field(tmp_field, field_type());
}
void Item_sum::print(String *str)
{
str->append(func_name());
@ -168,6 +161,10 @@ Item_sum_hybrid::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
null_value=1;
fix_length_and_dec();
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;
return 0;
}

View File

@ -210,7 +210,7 @@ public:
longlong val_int() { return (longlong) val(); }
bool is_null() { (void) val_int(); return null_value; }
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() {}
};
@ -247,7 +247,7 @@ public:
longlong val_int() { return (longlong) val(); }
String *val_str(String*);
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() {}
};
@ -318,6 +318,7 @@ class Item_sum_hybrid :public Item_sum
double sum;
longlong sum_int;
Item_result hybrid_type;
enum_field_types hybrid_field_type;
int cmp_sign;
table_map used_table_cache;
@ -344,6 +345,7 @@ class Item_sum_hybrid :public Item_sum
void make_const() { used_table_cache=0; }
bool keep_field_type(void) const { return 1; }
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 min_max_update_str_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
** To make code easy, allow interval objects without separators.
Convert a string to a interval value
To make code easy, allow interval objects without separators.
*/
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);
}
String *Item_func_now::val_str(String *str)
{
str_value.set(buff,buff_length,thd_charset());
return &str_value;
}
void Item_func_now::fix_length_and_dec()
{
struct tm tm_tmp,*start;
@ -540,13 +542,14 @@ void Item_func_now::fix_length_and_dec()
(ulong) (((uint) start->tm_min)*100L+
(uint) start->tm_sec)));
buff_length= (uint) cs->snprintf(cs,buff, sizeof(buff),"%04d-%02d-%02d %02d:%02d:%02d",
((int) (start->tm_year+1900)) % 10000,
(int) start->tm_mon+1,
(int) start->tm_mday,
(int) start->tm_hour,
(int) start->tm_min,
(int) start->tm_sec);
buff_length= (uint) cs->snprintf(cs,buff, sizeof(buff),
"%04d-%02d-%02d %02d:%02d:%02d",
((int) (start->tm_year+1900)) % 10000,
(int) start->tm_mon+1,
(int) start->tm_mday,
(int) start->tm_hour,
(int) start->tm_min,
(int) start->tm_sec);
/* For getdate */
ltime.year= start->tm_year+1900;
ltime.month= start->tm_mon+1;
@ -995,7 +998,42 @@ bool Item_func_from_unixtime::get_date(TIME *ltime,
return 0;
}
/* Here arg[1] is a Item_interval object */
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 */
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 *a) :Item_func(a) {}
enum Item_result result_type () const { return STRING_RESULT; }
enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
String *val_str(String *str);
double val() { return (double) val_int(); }
const char *func_name() const { return "date"; }
@ -326,10 +327,6 @@ public:
max_length=10*thd_charset()->mbmaxlen;
}
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)
{
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 *a) :Item_str_func(a) {}
Item_date_func(Item *a,Item *b) :Item_str_func(a,b) {}
void make_field(Send_field *tmp_field)
{
init_make_field(tmp_field,FIELD_TYPE_DATETIME);
}
enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; }
Field *tmp_table_field(TABLE *t_arg)
{
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 *a) :Item_func(a) {}
enum Item_result result_type () const { return STRING_RESULT; }
enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
double val() { return (double) value; }
longlong val_int() { return value; }
String *val_str(String *str);
const char *func_name() const { return "curtime"; }
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)
{
return (!t_arg) ? result_field :
@ -452,7 +443,6 @@ class Item_func_from_unixtime :public Item_date_func
decimals=0;
max_length=19*thd_charset()->mbmaxlen;
}
// enum Item_result result_type () const { return STRING_RESULT; }
bool get_date(TIME *res,bool fuzzy_date);
};
@ -470,11 +460,8 @@ public:
maybe_null=1;
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"; }
void make_field(Send_field *tmp_field)
{
init_make_field(tmp_field,FIELD_TYPE_TIME);
}
Field *tmp_table_field(TABLE *t_arg)
{
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
{
const interval_type int_type;
String value;
const bool date_sub_interval;
enum_field_types cached_field_type;
public:
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) {}
String *val_str(String *);
const char *func_name() const { return "date_add_interval"; }
void fix_length_and_dec()
{
set_charset(thd_charset());
maybe_null=1;
max_length=19*thd_charset()->mbmaxlen;
value.alloc(32);
}
void fix_length_and_dec();
enum_field_types field_type() const { return cached_field_type; }
double val() { return (double) val_int(); }
longlong val_int();
bool get_date(TIME *res,bool fuzzy_date);
@ -566,10 +555,7 @@ class Item_date_typecast :public Item_typecast
public:
Item_date_typecast(Item *a) :Item_typecast(a) {}
const char *func_name() const { return "date"; }
void make_field(Send_field *tmp_field)
{
init_make_field(tmp_field,FIELD_TYPE_DATE);
}
enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
Field *tmp_table_field(TABLE *t_arg)
{
return (!t_arg) ? result_field :
@ -583,10 +569,7 @@ class Item_time_typecast :public Item_typecast
public:
Item_time_typecast(Item *a) :Item_typecast(a) {}
const char *func_name() const { return "time"; }
void make_field(Send_field *tmp_field)
{
init_make_field(tmp_field,FIELD_TYPE_TIME);
}
enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
Field *tmp_table_field(TABLE *t_arg)
{
return (!t_arg) ? result_field :
@ -600,10 +583,7 @@ class Item_datetime_typecast :public Item_typecast
public:
Item_datetime_typecast(Item *a) :Item_typecast(a) {}
const char *func_name() const { return "datetime"; }
void make_field(Send_field *tmp_field)
{
init_make_field(tmp_field,FIELD_TYPE_DATETIME);
}
enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; }
Field *tmp_table_field(TABLE *t_arg)
{
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()
****************************************************************************/
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)
{
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("Server_id", 20));
field_list->push_back(new Item_empty_string("Orig_log_pos", 20));
field_list->push_back(new Item_return_int("Server_id", 10,
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));
}
@ -333,23 +336,22 @@ void Log_event::init_show_field_list(List<Item>* field_list)
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 *event_type;
if (p)
log_name = p + 1;
packet->length(0);
net_store_data(packet, log_name, strlen(log_name));
net_store_data(packet, (longlong) pos);
protocol->prepare_for_resend();
protocol->store(log_name);
protocol->store((ulonglong) pos);
event_type = get_type_str();
net_store_data(packet, event_type, strlen(event_type));
net_store_data(packet, server_id);
net_store_data(packet, (longlong) log_pos);
pack_info(packet);
return my_net_write(&thd_arg->net, (char*) packet->ptr(), packet->length());
protocol->store(event_type, strlen(event_type));
protocol->store((uint32) server_id);
protocol->store((ulonglong) log_pos);
pack_info(protocol);
return protocol->write();
}
#endif // !MYSQL_CLIENT
@ -671,7 +673,7 @@ void Log_event::set_log_pos(MYSQL_LOG* log)
Query_log_event::pack_info()
****************************************************************************/
void Query_log_event::pack_info(String* packet)
void Query_log_event::pack_info(Protocol *protocol)
{
char buf[256];
String tmp(buf, sizeof(buf), system_charset_info);
@ -685,7 +687,7 @@ void Query_log_event::pack_info(String* packet)
if (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
@ -925,7 +927,7 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli)
****************************************************************************/
#ifndef MYSQL_CLIENT
void Start_log_event::pack_info(String* packet)
void Start_log_event::pack_info(Protocol *protocol)
{
char buf1[256];
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(", Binlog ver: ");
tmp.append(llstr(binlog_version, buf));
net_store_data(packet, tmp.ptr(), tmp.length());
protocol->store(tmp.ptr(), tmp.length());
}
#endif // !MYSQL_CLIENT
@ -1036,7 +1038,7 @@ int Start_log_event::exec_event(struct st_relay_log_info* rli)
****************************************************************************/
#ifndef MYSQL_CLIENT
void Load_log_event::pack_info(String* packet)
void Load_log_event::pack_info(Protocol *protocol)
{
char buf[256];
String tmp(buf, sizeof(buf), system_charset_info);
@ -1109,7 +1111,7 @@ void Load_log_event::pack_info(String* packet)
tmp.append(')');
}
net_store_data(packet, tmp.ptr(), tmp.length());
protocol->store(tmp.ptr(), tmp.length());
}
#endif // !MYSQL_CLIENT
@ -1542,7 +1544,7 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli)
****************************************************************************/
#ifndef MYSQL_CLIENT
void Rotate_log_event::pack_info(String* packet)
void Rotate_log_event::pack_info(Protocol *protocol)
{
char buf1[256], buf[22];
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));
if (flags & LOG_EVENT_FORCED_ROTATE_F)
tmp.append("; forced by master");
net_store_data(packet, tmp.ptr(), tmp.length());
protocol->store(tmp.ptr(), tmp.length());
}
#endif // !MYSQL_CLIENT
@ -1680,7 +1682,7 @@ int Rotate_log_event::exec_event(struct st_relay_log_info* rli)
****************************************************************************/
#ifndef MYSQL_CLIENT
void Intvar_log_event::pack_info(String* packet)
void Intvar_log_event::pack_info(Protocol *protocol)
{
char buf1[256], buf[22];
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('=');
tmp.append(llstr(val, buf));
net_store_data(packet, tmp.ptr(), tmp.length());
protocol->store(tmp.ptr(), tmp.length());
}
#endif // !MYSQL_CLIENT
@ -1801,14 +1803,14 @@ int Intvar_log_event::exec_event(struct st_relay_log_info* rli)
****************************************************************************/
#ifndef MYSQL_CLIENT
void Rand_log_event::pack_info(String* packet)
void Rand_log_event::pack_info(Protocol *protocol)
{
char buf1[256], *pos;
pos= strmov(buf1,"rand_seed1=");
pos= int10_to_str((long) seed1, pos, 10);
pos= strmov(pos, ",rand_seed2=");
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
@ -1888,7 +1890,7 @@ int Rand_log_event::exec_event(struct st_relay_log_info* rli)
****************************************************************************/
#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;
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(",pos=");
tmp.append(llstr(master_pos,buf));
net_store_data(packet, tmp.ptr(), tmp.length());
protocol->store(tmp.ptr(), tmp.length());
}
#endif // !MYSQL_CLIENT
@ -2236,7 +2238,7 @@ void Create_file_log_event::print(FILE* file, bool short_form,
****************************************************************************/
#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;
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=");
end= int10_to_str((long) block_len, buf, 10);
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
@ -2395,14 +2397,14 @@ void Append_block_log_event::print(FILE* file, bool short_form,
****************************************************************************/
#ifndef MYSQL_CLIENT
void Append_block_log_event::pack_info(String* packet)
void Append_block_log_event::pack_info(Protocol *protocol)
{
char buf[256];
uint length;
length= (uint) my_sprintf(buf,
(buf, ";file_id=%u;block_len=%u", file_id,
block_len));
net_store_data(packet, buf, (int32) length);
protocol->store(buf, (int32) length);
}
#endif // !MYSQL_CLIENT
@ -2510,12 +2512,12 @@ void Delete_file_log_event::print(FILE* file, bool short_form,
****************************************************************************/
#ifndef MYSQL_CLIENT
void Delete_file_log_event::pack_info(String* packet)
void Delete_file_log_event::pack_info(Protocol *protocol)
{
char buf[64];
uint length;
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
@ -2609,12 +2611,12 @@ void Execute_load_log_event::print(FILE* file, bool short_form,
****************************************************************************/
#ifndef MYSQL_CLIENT
void Execute_load_log_event::pack_info(String* packet)
void Execute_load_log_event::pack_info(Protocol *protocol)
{
char buf[64];
uint length;
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

View File

@ -267,8 +267,8 @@ public:
static int read_log_event(IO_CACHE* file, String* packet,
pthread_mutex_t* log_lock);
void set_log_pos(MYSQL_LOG* log);
virtual void pack_info(String* packet);
int net_send(THD* thd, const char* log_name, my_off_t pos);
virtual void pack_info(Protocol *protocol);
int net_send(Protocol *protocol, const char* log_name, my_off_t pos);
static void init_show_field_list(List<Item>* field_list);
virtual int exec_event(struct st_relay_log_info* rli);
virtual const char* get_db()
@ -355,7 +355,7 @@ public:
Query_log_event(THD* thd_arg, const char* query_arg, ulong query_length,
bool using_trans);
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);
#else
void print(FILE* file, bool short_form = 0, char* last_db = 0);
@ -404,7 +404,7 @@ public:
#ifndef MYSQL_CLIENT
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);
#else
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,
bool using_trans);
void set_fields(List<Item> &fields_arg);
void pack_info(String* packet);
void pack_info(Protocol* protocol);
const char* get_db() { return db; }
int exec_event(struct st_relay_log_info* rli)
{
@ -507,7 +507,7 @@ public:
created = (uint32) when;
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);
#else
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)
: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);
#else
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)
: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);
#else
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 :
(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);
#else
void print(FILE* file, bool short_form = 0, char* last_db = 0);
@ -683,7 +683,7 @@ public:
enum enum_duplicates handle_dup,
char* block_arg, uint block_len_arg,
bool using_trans);
void pack_info(String* packet);
void pack_info(Protocol* protocol);
int exec_event(struct st_relay_log_info* rli);
#else
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,
uint block_len_arg, bool using_trans);
int exec_event(struct st_relay_log_info* rli);
void pack_info(String* packet);
void pack_info(Protocol* protocol);
#else
void print(FILE* file, bool short_form = 0, char* last_db = 0);
#endif
@ -759,7 +759,7 @@ public:
#ifndef MYSQL_CLIENT
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);
#else
void print(FILE* file, bool short_form = 0, char* last_db = 0);
@ -785,7 +785,7 @@ public:
#ifndef MYSQL_CLIENT
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);
#else
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 "table.h"
#include "field.h" /* Field definitions */
#include "protocol.h"
#include "sql_udf.h"
#include "item.h"
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);
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);
int setup_order(THD *thd,TABLE_LIST *tables, List<Item> &fields,
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,
const char *table_name, bool link_in_list);
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 intern_close_table(TABLE *entry);
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);
timestamp_type str_to_TIME(const char *str, uint length, TIME *l_time,
bool fuzzy_date);
void localtime_to_TIME(TIME *to, struct tm *from);
int test_if_number(char *str,int *res,bool allow_wildcards);
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);
if (!(opt_specialflag & SPECIAL_NO_PRIOR))
my_pthread_attr_setprio(&thr_attr,INTERRUPT_PRIOR);
pthread_attr_setstacksize(&thr_attr,32768);
pthread_attr_setstacksize(&thr_attr, 129*1024);
#endif
(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);
if (maybe_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)))
DBUG_RETURN(0);
@ -2284,9 +2285,11 @@ get_quick_keys(PARAM *param,QUICK_SELECT *quick,KEY_PART *key,
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 */
if((flag & GEOM_FLAG) == 0)
/*
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 (tmp_min_key != param->min_key)
flag&= ~NO_MIN_RANGE;
@ -2451,17 +2454,17 @@ int QUICK_SELECT::get_next()
if (!(range=it++))
DBUG_RETURN(HA_ERR_END_OF_FILE); // All ranges used
if(range->flag & GEOM_FLAG)
if (range->flag & GEOM_FLAG)
{
if ((result = file->index_read(record,
(byte*) (range->min_key + ((range->flag & GEOM_FLAG) > 0)),
range->min_length,
(ha_rkey_function)(range->flag ^ GEOM_FLAG))))
(byte*) (range->min_key +1),
range->min_length,
(ha_rkey_function)(range->flag ^
GEOM_FLAG))))
{
if (result != HA_ERR_KEY_NOT_FOUND)
DBUG_RETURN(result);
range=0; // Not found, to next range
range=0; // Not found, to next range
continue;
}
DBUG_RETURN(0);
@ -2478,13 +2481,14 @@ int QUICK_SELECT::get_next()
continue;
}
if ((result = file->index_read(record,
(byte*) (range->min_key + ((range->flag & GEOM_FLAG) > 0)),
range->min_length,
(range->flag & NEAR_MIN) ?
HA_READ_AFTER_KEY:
(range->flag & EQ_RANGE) ?
HA_READ_KEY_EXACT :
HA_READ_KEY_OR_NEXT)))
(byte*) (range->min_key +
test(range->flag & GEOM_FLAG)),
range->min_length,
(range->flag & NEAR_MIN) ?
HA_READ_AFTER_KEY:
(range->flag & EQ_RANGE) ?
HA_READ_KEY_EXACT :
HA_READ_KEY_OR_NEXT)))
{
if (result != HA_ERR_KEY_NOT_FOUND)
@ -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)
{

View File

@ -55,7 +55,7 @@ public:
decimals=dec; max_length=float_length(dec);
}
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(longlong nr) { value=(double) nr; }
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)
{ max_length=11; }
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(longlong nr) { value=nr; }
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)
{ this->max_length=length; }
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(longlong nr) { str_value.set(nr, thd_charset()); }
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)
{
Protocol *protocol= thd->protocol;
DBUG_ENTER("show_new_master");
List<Item> field_list;
char errmsg[SLAVE_ERRMSG_SIZE];
@ -431,15 +432,15 @@ int show_new_master(THD* thd)
}
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_pos", 20));
if (send_fields(thd, field_list, 1))
field_list.push_back(new Item_return_int("Log_pos", 10,
MYSQL_TYPE_LONGLONG));
if (protocol->send_fields(&field_list, 1))
DBUG_RETURN(-1);
packet->length(0);
net_store_data(packet, lex_mi->log_file_name);
net_store_data(packet, (longlong)lex_mi->pos);
if (my_net_write(&thd->net, packet->ptr(), packet->length()))
protocol->prepare_for_resend();
protocol->store(lex_mi->log_file_name);
protocol->store((ulonglong) lex_mi->pos);
if (protocol->write())
DBUG_RETURN(-1);
send_eof(thd);
DBUG_RETURN(0);
@ -580,21 +581,24 @@ int show_slave_hosts(THD* thd)
{
List<Item> field_list;
NET* net = &thd->net;
String* packet = &thd->packet;
Protocol *protocol= thd->protocol;
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));
if (opt_show_slave_auth_info)
{
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("Port",20));
field_list.push_back(new Item_empty_string("Rpl_recovery_rank", 20));
field_list.push_back(new Item_empty_string("Master_id", 20));
field_list.push_back(new Item_return_int("Port", 7, MYSQL_TYPE_LONG));
field_list.push_back(new Item_return_int("Rpl_recovery_rank", 7,
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);
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)
{
SLAVE_INFO* si = (SLAVE_INFO*) hash_element(&slave_list, i);
packet->length(0);
net_store_data(packet, si->server_id);
net_store_data(packet, si->host);
protocol->prepare_for_resend();
protocol->store((uint32) si->server_id);
protocol->store(si->host);
if (opt_show_slave_auth_info)
{
net_store_data(packet, si->user);
net_store_data(packet, si->password);
protocol->store(si->user);
protocol->store(si->password);
}
net_store_data(packet, (uint32) si->port);
net_store_data(packet, si->rpl_recovery_rank);
net_store_data(packet, si->master_id);
if (my_net_write(net, (char*)packet->ptr(), packet->length()))
protocol->store((uint32) si->port);
protocol->store((uint32) si->rpl_recovery_rank);
protocol->store((uint32) si->master_id);
if (protocol->write())
{
pthread_mutex_unlock(&LOCK_slave_list);
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)
global_system_variables.convert_set= var->save_result.convert;
else
{
thd->lex.convert_set= thd->variables.convert_set=
var->save_result.convert;
thd->protocol_simple.init(thd);
thd->protocol_prep.init(thd);
}
return 0;
}

View File

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

View File

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

View File

@ -310,30 +310,7 @@ void field_str::add()
was_maybe_zerofill = num_info.maybe_zerofill;
}
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);
}
}
}
}
/* Update min and max arguments */
if (!found)
{
found = 1;
@ -364,6 +341,31 @@ void field_str::add()
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)) ||
(was_zero_fill && (max_length != min_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
****************************************************************************/

View File

@ -152,6 +152,11 @@ THD::THD():user_time(0), fatal_error(0),
(qsort_cmp2) compare_prep_stmt, 1,
(tree_element_free) free_prep_stmt, 0);
/* Protocol */
protocol= &protocol_simple; // Default protocol
protocol_simple.init(this);
protocol_prep.init(this);
#ifdef USING_TRANSACTIONS
bzero((char*) &transaction,sizeof(transaction));
if (opt_using_transactions)
@ -438,7 +443,7 @@ int THD::send_explain_fields(select_result *result)
{
List<Item> field_list;
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("table",NAME_LEN));
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;
field_list.push_back(item=new Item_empty_string("key",NAME_LEN));
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;
field_list.push_back(item=new Item_empty_string("ref",
NAME_LEN*MAX_REF_PARTS));
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));
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)
{
return ::send_fields(thd,list,flag);
return thd->protocol->send_fields(&list,flag);
}
@ -511,35 +517,33 @@ bool select_send::send_fields(List<Item> &list,uint flag)
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)
{ // using limit offset,count
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;
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));
DBUG_RETURN(1);
break;
}
}
thd->sent_row_count++;
if (!thd->net.report_error)
{
DBUG_RETURN(my_net_write(&thd->net,
(char*) packet->ptr(),
packet->length()));
}
else
DBUG_RETURN(1);
DBUG_RETURN(protocol->write());
DBUG_RETURN(1);
}
bool select_send::send_eof()

View File

@ -389,6 +389,9 @@ public:
MEM_ROOT mem_root; // 1 command-life memory pool
MEM_ROOT con_root; // connection-life memory
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
TREE prepared_statements;
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;
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;
CONVERT *convert=thd->variables.convert_set;
uint create_options = create_info ? create_info->options : 0;
Protocol *protocol=thd->protocol;
DBUG_ENTER("mysql_show_create_db");
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("Create Database",1024));
if (send_fields(thd,field_list,1))
if (protocol->send_fields(&field_list,1))
DBUG_RETURN(1);
String *packet = &thd->packet;
packet->length(0);
net_store_data(packet, convert, dbname);
protocol->prepare_for_resend();
protocol->store(dbname, strlen(dbname));
to= strxmov(path, "CREATE DATABASE ", NullS);
if (create_options & HA_LEX_CREATE_IF_NOT_EXISTS)
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 ",
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);
send_eof(thd);
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 int warning_level_length[]= { 4, 7, 5, 1 };
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");
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));
if (send_fields(thd,field_list,1))
if (thd->protocol->send_fields(&field_list,1))
DBUG_RETURN(1);
MYSQL_ERROR *err;
SELECT_LEX *sel= &thd->lex.select_lex;
ha_rows offset= sel->offset_limit, limit= sel->select_limit;
Protocol *protocol=thd->protocol;
List_iterator_fast<MYSQL_ERROR> it(thd->warn_list);
while ((err= it++))
@ -179,11 +180,12 @@ my_bool mysqld_show_warnings(THD *thd, ulong levels_to_show)
offset--;
continue;
}
thd->packet.length(0);
net_store_data(&thd->packet,warning_level_names[err->level]);
net_store_data(&thd->packet,(uint32) err->code);
net_store_data(&thd->packet,err->msg);
if (my_net_write(&thd->net,(char*)thd->packet.ptr(),thd->packet.length()))
protocol->prepare_for_resend();
protocol->store(warning_level_names[err->level],
warning_level_length[err->level]);
protocol->store((uint32) err->code);
protocol->store(err->msg, strlen(err->msg));
if (protocol->write())
DBUG_RETURN(1);
if (!--limit)
break;

View File

@ -123,6 +123,9 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
List<Item> list;
list.push_front(new Item_field(NULL,NULL,"*"));
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;
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
select_limit+=offset_limit;
send_fields(thd,list,1);
protocol->send_fields(&list,1);
HANDLER_TABLES_HACK(thd);
MYSQL_LOCK *lock=mysql_lock_tables(thd,&tables->table,1);
@ -141,7 +144,7 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
for (num_rows=0; num_rows < select_limit; )
{
switch(mode) {
switch (mode) {
case RFIRST:
err=keyname ?
table->file->index_first(table->record[0]) :
@ -216,24 +219,24 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
if (!cond->val_int())
continue;
}
if (num_rows>=offset_limit)
if (num_rows >= offset_limit)
{
if (!err)
{
String *packet = &thd->packet;
Item *item;
packet->length(0);
protocol->prepare_for_resend();
it.rewind();
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));
goto err;
}
}
my_net_write(&thd->net, (char*)packet->ptr(), packet->length());
protocol->write();
}
}
num_rows++;
@ -249,26 +252,26 @@ 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.
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
here for alias, not real table name
*/
/*
Note: this function differs from find_locked_table() because we're looking
here for alias, not real table name
*/
static TABLE **find_table_ptr_by_name(THD *thd, const char *db,
const char *alias)
{
int dblen;
TABLE **ptr;
if (!db || ! *db)
db= thd->db ? thd->db : "";
dblen=strlen(db)+1;
ptr=&(thd->handler_tables);
ptr= &(thd->handler_tables);
for (TABLE *table=*ptr; table ; table=*ptr)
for (TABLE *table= *ptr; table ; table= *ptr)
{
if (!memcmp(table->table_cache_key, db, dblen) &&
!my_strcasecmp(system_charset_info,table->table_name,alias))

View File

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

View File

@ -3010,11 +3010,11 @@ mysql_init_query(THD *thd)
DBUG_VOID_RETURN;
}
void
mysql_init_select(LEX *lex)
{
SELECT_LEX *select_lex= lex->current_select->select_lex();
DBUG_ASSERT(select_lex->linkage != GLOBAL_OPTIONS_TYPE);
select_lex->init_select();
select_lex->master_unit()->select_limit= select_lex->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.
*/
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(0);
}
@ -726,7 +727,9 @@ void mysql_stmt_execute(THD *thd, char *packet)
mysql_delete(), mysql_update() and mysql_select() to not to
have re-check on setup_* and other things ..
*/
thd->protocol= &thd->protocol_prep; // Switch to binary protocol
mysql_execute_command(stmt->thd);
thd->protocol= &thd->protocol_simple; // Use normal protocol
if (!(specialflag & SPECIAL_NO_PRIOR))
my_pthread_setprio(pthread_self(), WAIT_PRIOR);

View File

@ -928,14 +928,15 @@ int cmp_master_pos(const char* log_file_name1, ulonglong log_pos1,
int show_binlog_events(THD* thd)
{
Protocol *protocol= thd->protocol;
DBUG_ENTER("show_binlog_events");
List<Item> field_list;
const char* errmsg = 0;
const char *errmsg = 0;
IO_CACHE log;
File file = -1;
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);
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)); )
{
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";
delete ev;
@ -1029,28 +1030,29 @@ err:
int show_binlog_info(THD* thd)
{
Protocol *protocol= thd->protocol;
DBUG_ENTER("show_binlog_info");
List<Item> field_list;
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_empty_string("Binlog_do_db",20));
field_list.push_back(new Item_empty_string("Binlog_ignore_db",20));
field_list.push_back(new Item_return_int("Position",20,
MYSQL_TYPE_LONGLONG));
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);
String* packet = &thd->packet;
packet->length(0);
protocol->prepare_for_resend();
if (mysql_bin_log.is_open())
{
LOG_INFO li;
mysql_bin_log.get_current_log(&li);
int dir_len = dirname_length(li.log_file_name);
net_store_data(packet, li.log_file_name + dir_len);
net_store_data(packet, (longlong)li.pos);
net_store_data(packet, &binlog_do_db);
net_store_data(packet, &binlog_ignore_db);
if (my_net_write(&thd->net, (char*)thd->packet.ptr(), packet->length()))
protocol->store(li.log_file_name + dir_len);
protocol->store((ulonglong) li.pos);
protocol->store(&binlog_do_db);
protocol->store(&binlog_ignore_db);
if (protocol->write())
DBUG_RETURN(-1);
}
send_eof(thd);
@ -1079,6 +1081,8 @@ int show_binlogs(THD* thd)
List<Item> field_list;
String *packet = &thd->packet;
uint length;
Protocol *protocol= thd->protocol;
DBUG_ENTER("show_binlogs");
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));
if (send_fields(thd, field_list, 1))
return 1;
if (protocol->send_fields(&field_list, 1))
DBUG_RETURN(1);
mysql_bin_log.lock_index();
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 */
while ((length=my_b_gets(index_file, fname, sizeof(fname))) > 1)
{
protocol->prepare_for_resend();
int dir_len = dirname_length(fname);
packet->length(0);
/* The -1 is for removing newline from fname */
net_store_data(packet, fname + dir_len, length-1-dir_len);
if (my_net_write(net, (char*) packet->ptr(), packet->length()))
protocol->store(fname + dir_len, length-1-dir_len);
if (protocol->write())
goto err;
}
mysql_bin_log.unlock_index();
send_eof(thd);
return 0;
DBUG_RETURN(0);
err_with_msg:
send_error(thd, ER_UNKNOWN_ERROR, errmsg);
err:
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
free_io_cache(join->table[join->const_tables]);
if (join->select_lex->dependent && !full)
{
for (tab=join->join_tab,end=tab+join->tables ; tab != end ; tab++)
{
if (tab->table)
@ -3073,6 +3074,7 @@ join_free(JOIN *join, bool full)
tab->table->file->index_end();
}
}
}
else
{
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 */
if (!tab->read_record.table)
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);
}
@ -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,
strlen(join->select_lex->type),
default_charset_info));
Item *empty= new Item_empty_string("",0);
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),
default_charset_info));
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,
strlen(table->table_name),
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;
uint j;
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);
}
sprintf(buff3,"%.0f",join->best_positions[i].records_read);
item_list.push_back(new Item_string(buff3,strlen(buff3),
default_charset_info));
item_list.push_back(new Item_int((longlong) (ulonglong)
join->best_positions[i]. records_read,
21));
my_bool key_read=table->key_read;
if (tab->type == JT_NEXT &&
((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;
}
int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result)
{
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);
}
int mysql_explain_select(THD *thd, SELECT_LEX *select_lex, char const *type,
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(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

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

View File

@ -113,7 +113,8 @@ enum timestamp_type { TIMESTAMP_NONE, TIMESTAMP_DATE, TIMESTAMP_FULL,
TIMESTAMP_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;
timestamp_type time_type;
} TIME;

View File

@ -724,3 +724,20 @@ bool str_to_time(const char *str,uint length,TIME *l_time)
}
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;
}