summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.bzrignore1
-rw-r--r--BitKeeper/etc/logging_ok2
-rw-r--r--Docs/manual.texi4
-rw-r--r--libmysql/libmysql.c4
-rw-r--r--libmysqld/Makefile.am2
-rw-r--r--mysql-test/r/analyse.result4
-rw-r--r--mysql-test/r/case.result4
-rw-r--r--mysql-test/r/cast.result4
-rw-r--r--mysql-test/r/delayed.result6
-rw-r--r--mysql-test/r/delete.result9
-rw-r--r--mysql-test/r/derived.result27
-rw-r--r--mysql-test/r/explain.result2
-rw-r--r--mysql-test/r/func_date_add.result20
-rw-r--r--mysql-test/r/func_group.result40
-rw-r--r--mysql-test/r/func_in.result87
-rw-r--r--mysql-test/r/func_str.result23
-rw-r--r--mysql-test/r/func_time.result64
-rw-r--r--mysql-test/r/having.result4
-rw-r--r--mysql-test/r/innodb.result28
-rw-r--r--mysql-test/r/join_outer.result2
-rw-r--r--mysql-test/r/key_primary.result2
-rw-r--r--mysql-test/r/keywords.result2
-rw-r--r--mysql-test/r/merge.result4
-rw-r--r--mysql-test/r/odbc.result2
-rw-r--r--mysql-test/r/range.result2
-rw-r--r--mysql-test/r/row.result136
-rw-r--r--mysql-test/r/row_test.result60
-rw-r--r--mysql-test/r/select.result20
-rw-r--r--mysql-test/r/subselect.result127
-rw-r--r--mysql-test/r/type_datetime.result4
-rw-r--r--mysql-test/r/type_ranges.result6
-rw-r--r--mysql-test/r/type_timestamp.result50
-rw-r--r--mysql-test/r/union.result13
-rw-r--r--mysql-test/t/analyse.test2
-rw-r--r--mysql-test/t/delete.test10
-rw-r--r--mysql-test/t/derived.test4
-rw-r--r--mysql-test/t/func_group.test10
-rw-r--r--mysql-test/t/func_in.test32
-rw-r--r--mysql-test/t/func_str.test9
-rw-r--r--mysql-test/t/func_time.test31
-rw-r--r--mysql-test/t/having.test1
-rw-r--r--mysql-test/t/merge.test4
-rw-r--r--mysql-test/t/row.test61
-rw-r--r--mysql-test/t/row_test.test36
-rw-r--r--mysql-test/t/select.test4
-rw-r--r--mysql-test/t/subselect.test47
-rw-r--r--mysql-test/t/type_datetime.test2
-rw-r--r--mysql-test/t/type_timestamp.test2
-rw-r--r--mysql-test/t/union.test1
-rw-r--r--sql/Makefile.am2
-rw-r--r--sql/field.cc261
-rw-r--r--sql/field.h45
-rw-r--r--sql/gen_lex_hash.cc58
-rw-r--r--sql/ha_berkeley.cc39
-rw-r--r--sql/ha_berkeley.h2
-rw-r--r--sql/ha_innodb.cc21
-rw-r--r--sql/ha_myisam.cc23
-rw-r--r--sql/item.cc229
-rw-r--r--sql/item.h178
-rw-r--r--sql/item_cmpfunc.cc302
-rw-r--r--sql/item_cmpfunc.h234
-rw-r--r--sql/item_func.cc3
-rw-r--r--sql/item_func.h10
-rw-r--r--sql/item_row.cc42
-rw-r--r--sql/item_row.h21
-rw-r--r--sql/item_subselect.cc132
-rw-r--r--sql/item_subselect.h30
-rw-r--r--sql/item_sum.cc71
-rw-r--r--sql/item_sum.h67
-rw-r--r--sql/item_timefunc.cc58
-rw-r--r--sql/item_timefunc.h64
-rw-r--r--sql/lex.h2
-rw-r--r--sql/log_event.cc76
-rw-r--r--sql/log_event.h26
-rw-r--r--sql/mysql_priv.h29
-rw-r--r--sql/mysqld.cc3
-rw-r--r--sql/net_pkg.cc525
-rw-r--r--sql/opt_range.cc45
-rw-r--r--sql/procedure.h6
-rw-r--r--sql/protocol.cc1038
-rw-r--r--sql/protocol.h131
-rw-r--r--sql/repl_failsafe.cc48
-rw-r--r--sql/set_var.cc4
-rw-r--r--sql/share/german/errmsg.txt203
-rw-r--r--sql/slave.cc122
-rw-r--r--sql/sql_acl.cc27
-rw-r--r--sql/sql_analyse.cc50
-rw-r--r--sql/sql_base.cc247
-rw-r--r--sql/sql_class.cc48
-rw-r--r--sql/sql_class.h3
-rw-r--r--sql/sql_db.cc17
-rw-r--r--sql/sql_derived.cc77
-rw-r--r--sql/sql_error.cc18
-rw-r--r--sql/sql_handler.cc33
-rw-r--r--sql/sql_help.cc72
-rw-r--r--sql/sql_lex.cc9
-rw-r--r--sql/sql_lex.h2
-rw-r--r--sql/sql_list.h10
-rw-r--r--sql/sql_parse.cc8
-rw-r--r--sql/sql_prepare.cc5
-rw-r--r--sql/sql_repl.cc46
-rw-r--r--sql/sql_select.cc41
-rw-r--r--sql/sql_show.cc660
-rw-r--r--sql/sql_string.h25
-rw-r--r--sql/sql_table.cc91
-rw-r--r--sql/sql_union.cc6
-rw-r--r--sql/sql_yacc.yy10
-rw-r--r--sql/structs.h3
-rw-r--r--sql/time.cc17
-rw-r--r--tests/fork_big2.pl705
110 files changed, 5010 insertions, 2391 deletions
diff --git a/.bzrignore b/.bzrignore
index 20d6e35bb62..2c115322cc5 100644
--- a/.bzrignore
+++ b/.bzrignore
@@ -579,3 +579,4 @@ vio/test-ssl
vio/test-sslclient
vio/test-sslserver
vio/viotest-ssl
+libmysqld/protocol.cc
diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok
index 1fbd6e2db92..00952150b8c 100644
--- a/BitKeeper/etc/logging_ok
+++ b/BitKeeper/etc/logging_ok
@@ -93,10 +93,12 @@ tonu@x153.internalnet
tonu@x3.internalnet
venu@myvenu.com
venu@work.mysql.com
+vva@eagle.mysql.r18.ru
vva@genie.(none)
walrus@mysql.com
wax@mysql.com
worm@altair.is.lan
zak@balfor.local
zak@linux.local
+zak@mysql.com
zgreant@mysql.com
diff --git a/Docs/manual.texi b/Docs/manual.texi
index 283ad00d80f..0892203bca6 100644
--- a/Docs/manual.texi
+++ b/Docs/manual.texi
@@ -32040,6 +32040,10 @@ a single backslash to be matched).
@item expr NOT LIKE pat [ESCAPE 'escape-char']
Same as @code{NOT (expr LIKE pat [ESCAPE 'escape-char'])}.
+@findex SOUNDS LIKE
+@item expr SOUNDS LIKE expr
+Same as @code{SOUNDEX(expr)=SOUNDEX(expr)}.
+
@cindex mSQL compatibility
@cindex compatibility, with mSQL
@findex REGEXP
diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c
index ad97d5b1442..d73b28863ba 100644
--- a/libmysql/libmysql.c
+++ b/libmysql/libmysql.c
@@ -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;
diff --git a/libmysqld/Makefile.am b/libmysqld/Makefile.am
index ea47126a4d5..daf65cb2f80 100644
--- a/libmysqld/Makefile.am
+++ b/libmysqld/Makefile.am
@@ -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 \
diff --git a/mysql-test/r/analyse.result b/mysql-test/r/analyse.result
index c183530df48..ede83afe4e1 100644
--- a/mysql-test/r/analyse.result
+++ b/mysql-test/r/analyse.result
@@ -11,3 +11,7 @@ Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_
t1.i 1 7 1 1 0 0 4.0000 2.2361 ENUM('1','3','5','7') NOT NULL
t1.j 2 8 1 1 0 0 5.0000 2.2361 ENUM('2','4','6','8') NOT NULL
drop table t1,t2;
+EXPLAIN SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE();
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <derived2> system NULL NULL NULL NULL 1
+2 DERIVED NULL NULL NULL NULL NULL NULL NULL No tables used
diff --git a/mysql-test/r/case.result b/mysql-test/r/case.result
index ec37c9a5763..18241a8fcc1 100644
--- a/mysql-test/r/case.result
+++ b/mysql-test/r/case.result
@@ -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
diff --git a/mysql-test/r/cast.result b/mysql-test/r/cast.result
index 572b32c171c..db28038526b 100644
--- a/mysql-test/r/cast.result
+++ b/mysql-test/r/cast.result
@@ -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
diff --git a/mysql-test/r/delayed.result b/mysql-test/r/delayed.result
index 9e375203e49..8e4b52a8366 100644
--- a/mysql-test/r/delayed.result
+++ b/mysql-test/r/delayed.result
@@ -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");
diff --git a/mysql-test/r/delete.result b/mysql-test/r/delete.result
index c2230722aa6..351798b0509 100644
--- a/mysql-test/r/delete.result
+++ b/mysql-test/r/delete.result
@@ -24,3 +24,12 @@ create table t1 (a bigint not null, primary key (a,a,a,a,a,a,a,a,a,a));
insert into t1 values (2),(4),(6),(8),(10),(12),(14),(16),(18),(20),(22),(24),(26),(23),(27);
delete from t1 where a=27;
drop table t1;
+drop table if exists t;
+CREATE TABLE `t` (
+`i` int(10) NOT NULL default '0',
+`i2` int(10) NOT NULL default '0',
+PRIMARY KEY (`i`)
+) TYPE=MyISAM CHARSET=latin1;
+DELETE FROM t USING t WHERE post='1';
+Unknown column 'post' in 'where clause'
+drop table if exists t;
diff --git a/mysql-test/r/derived.result b/mysql-test/r/derived.result
index 95640e69d8b..03e00b206b2 100644
--- a/mysql-test/r/derived.result
+++ b/mysql-test/r/derived.result
@@ -63,6 +63,31 @@ a
select 1 from (select 1) as a;
1
1
+select * from (select * from t1 union select * from t1) a;
+a b
+1 a
+2 b
+3 c
+select * from (select * from t1 union all select * from t1) a;
+a b
+1 a
+2 b
+3 c
+3 c
+1 a
+2 b
+3 c
+3 c
+explain select * from (select * from t1 union select * from t1) a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <derived2> ALL NULL NULL NULL NULL 3
+2 DERIVED t1 ALL NULL NULL NULL NULL 4
+3 UNION t1 ALL NULL NULL NULL NULL 4
+explain select * from (select * from t1 union all select * from t1) a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY <derived2> ALL NULL NULL NULL NULL 8
+2 DERIVED t1 ALL NULL NULL NULL NULL 4
+3 UNION t1 ALL NULL NULL NULL NULL 4
drop table if exists t1;
create table t1(a int not null, t char(8), index(a));
SELECT * FROM (SELECT * FROM t1) as b ORDER BY a ASC LIMIT 0,20;
@@ -89,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;
diff --git a/mysql-test/r/explain.result b/mysql-test/r/explain.result
index dafed9a7d41..2892c2ea587 100644
--- a/mysql-test/r/explain.result
+++ b/mysql-test/r/explain.result
@@ -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
diff --git a/mysql-test/r/func_date_add.result b/mysql-test/r/func_date_add.result
index acdf2c5d7be..234fded9a68 100644
--- a/mysql-test/r/func_date_add.result
+++ b/mysql-test/r/func_date_add.result
@@ -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;
diff --git a/mysql-test/r/func_group.result b/mysql-test/r/func_group.result
index c1f36283ab0..409fd110ab9 100644
--- a/mysql-test/r/func_group.result
+++ b/mysql-test/r/func_group.result
@@ -42,21 +42,21 @@ insert into t1 values (null,null,'');
select count(distinct a),count(distinct grp) from t1;
count(distinct a) count(distinct grp)
6 3
-select sum(a),count(a),avg(a),std(a),bit_or(a),bit_and(a),min(a),max(a),min(c),max(c) from t1;
-sum(a) count(a) avg(a) std(a) bit_or(a) bit_and(a) min(a) max(a) min(c) max(c)
-21 6 3.5000 1.7078 7 0 1 6 E
-select grp, sum(a),count(a),avg(a),std(a),bit_or(a),bit_and(a),min(a),max(a),min(c),max(c) from t1 group by grp;
-grp sum(a) count(a) avg(a) std(a) bit_or(a) bit_and(a) min(a) max(a) min(c) max(c)
-NULL 0 0 NULL NULL 0 0 NULL NULL
-1 1 1 1.0000 0.0000 1 1 1 1 a a
-2 5 2 2.5000 0.5000 3 2 2 3 b c
-3 15 3 5.0000 0.8165 7 4 4 6 C E
-select grp, sum(a)+count(a)+avg(a)+std(a)+bit_or(a)+bit_and(a)+min(a)+max(a)+min(c)+max(c) as sum from t1 group by grp;
+select sum(a),count(a),avg(a),std(a),variance(a),bit_or(a),bit_and(a),min(a),max(a),min(c),max(c) from t1;
+sum(a) count(a) avg(a) std(a) variance(a) bit_or(a) bit_and(a) min(a) max(a) min(c) max(c)
+21 6 3.5000 1.7078 2.9167 7 0 1 6 E
+select grp, sum(a),count(a),avg(a),std(a),variance(a),bit_or(a),bit_and(a),min(a),max(a),min(c),max(c) from t1 group by grp;
+grp sum(a) count(a) avg(a) std(a) variance(a) bit_or(a) bit_and(a) min(a) max(a) min(c) max(c)
+NULL 0 0 NULL NULL NULL 0 0 NULL NULL
+1 1 1 1.0000 0.0000 0.0000 1 1 1 1 a a
+2 5 2 2.5000 0.5000 0.2500 3 2 2 3 b c
+3 15 3 5.0000 0.8165 0.6667 7 4 4 6 C E
+select grp, sum(a)+count(a)+avg(a)+std(a)+variance(a)+bit_or(a)+bit_and(a)+min(a)+max(a)+min(c)+max(c) as sum from t1 group by grp;
grp sum
NULL NULL
1 7
-2 20
-3 44.816496580928
+2 20.25
+3 45.483163247594
create table t2 (grp int, a bigint unsigned, c char(10));
insert into t2 select grp,max(a)+max(grp),max(c) from t1 group by grp;
replace into t2 select grp, a, c from t1 limit 2,1;
@@ -72,14 +72,14 @@ CREATE TABLE t1 (id int(11),value1 float(10,2));
INSERT INTO t1 VALUES (1,0.00),(1,1.00), (1,2.00), (2,10.00), (2,11.00), (2,12.00);
CREATE TABLE t2 (id int(11),name char(20));
INSERT INTO t2 VALUES (1,'Set One'),(2,'Set Two');
-select id, avg(value1), std(value1) from t1 group by id;
-id avg(value1) std(value1)
-1 1.000000 0.816497
-2 11.000000 0.816497
-select name, avg(value1), std(value1) from t1, t2 where t1.id = t2.id group by t1.id;
-name avg(value1) std(value1)
-Set One 1.000000 0.816497
-Set Two 11.000000 0.816497
+select id, avg(value1), std(value1), variance(value1) from t1 group by id;
+id avg(value1) std(value1) variance(value1)
+1 1.000000 0.816497 0.666667
+2 11.000000 0.816497 0.666667
+select name, avg(value1), std(value1), variance(value1) from t1, t2 where t1.id = t2.id group by t1.id;
+name avg(value1) std(value1) variance(value1)
+Set One 1.000000 0.816497 0.666667
+Set Two 11.000000 0.816497 0.666667
drop table t1,t2;
create table t1 (id int not null);
create table t2 (id int not null,rating int null);
diff --git a/mysql-test/r/func_in.result b/mysql-test/r/func_in.result
index ba33ee0831d..01d70c7c4c6 100644
--- a/mysql-test/r/func_in.result
+++ b/mysql-test/r/func_in.result
@@ -1,11 +1,95 @@
+select 1 in (1,2,3);
+1 in (1,2,3)
+1
+select 10 in (1,2,3);
+10 in (1,2,3)
+0
+select NULL in (1,2,3);
+NULL in (1,2,3)
+NULL
+select 1 in (1,NULL,3);
+1 in (1,NULL,3)
+1
+select 3 in (1,NULL,3);
+3 in (1,NULL,3)
+1
+select 10 in (1,NULL,3);
+10 in (1,NULL,3)
+NULL
+select 1.5 in (1.5,2.5,3.5);
+1.5 in (1.5,2.5,3.5)
+1
+select 10.5 in (1.5,2.5,3.5);
+10.5 in (1.5,2.5,3.5)
+0
+select NULL in (1.5,2.5,3.5);
+NULL in (1.5,2.5,3.5)
+NULL
+select 1.5 in (1.5,NULL,3.5);
+1.5 in (1.5,NULL,3.5)
+1
+select 3.5 in (1.5,NULL,3.5);
+3.5 in (1.5,NULL,3.5)
+1
+select 10.5 in (1.5,NULL,3.5);
+10.5 in (1.5,NULL,3.5)
+NULL
drop table if exists t1;
+CREATE TABLE t1 (a int, b int, c int);
+insert into t1 values (1,2,3), (1,NULL,3);
+select 1 in (a,b,c) from t1;
+1 in (a,b,c)
+1
+1
+select 3 in (a,b,c) from t1;
+3 in (a,b,c)
+1
+1
+select 10 in (a,b,c) from t1;
+10 in (a,b,c)
+0
+NULL
+select NULL in (a,b,c) from t1;
+NULL in (a,b,c)
+NULL
+NULL
+drop table t1;
+CREATE TABLE t1 (a float, b float, c float);
+insert into t1 values (1.5,2.5,3.5), (1.5,NULL,3.5);
+select 1.5 in (a,b,c) from t1;
+1.5 in (a,b,c)
+1
+1
+select 3.5 in (a,b,c) from t1;
+3.5 in (a,b,c)
+1
+1
+select 10.5 in (a,b,c) from t1;
+10.5 in (a,b,c)
+0
+NULL
+drop table t1;
+CREATE TABLE t1 (a varchar(10), b varchar(10), c varchar(10));
+insert into t1 values ('A','BC','EFD'), ('A',NULL,'EFD');
+select 'A' in (a,b,c) from t1;
+'A' in (a,b,c)
+1
+1
+select 'EFD' in (a,b,c) from t1;
+'EFD' in (a,b,c)
+1
+1
+select 'XSFGGHF' in (a,b,c) from t1;
+'XSFGGHF' in (a,b,c)
+0
+NULL
+drop table t1;
CREATE TABLE t1 (field char(1));
INSERT INTO t1 VALUES ('A'),(NULL);
SELECT * from t1 WHERE field IN (NULL);
field
SELECT * from t1 WHERE field NOT IN (NULL);
field
-A
SELECT * from t1 where field = field;
field
A
@@ -16,6 +100,7 @@ NULL
DELETE FROM t1 WHERE field NOT IN (NULL);
SELECT * FROM t1;
field
+A
NULL
drop table t1;
create table t1 (id int(10) primary key);
diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result
index 69e37d7b911..d0358aad6ba 100644
--- a/mysql-test/r/func_str.result
+++ b/mysql-test/r/func_str.result
@@ -80,6 +80,21 @@ this is a REAL test
select soundex(''),soundex('he'),soundex('hello all folks');
soundex('') soundex('he') soundex('hello all folks')
H000 H4142
+select 'mood' sounds like 'mud';
+'mood' sounds like 'mud'
+1
+select 'Glazgo' sounds like 'Liverpool';
+'Glazgo' sounds like 'Liverpool'
+0
+select null sounds like 'null';
+null sounds like 'null'
+NULL
+select 'null' sounds like null;
+'null' sounds like null
+NULL
+select null sounds like null;
+null sounds like null
+NULL
select md5('hello');
md5('hello')
5d41402abc4b2a76b9719d911017c592
@@ -213,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;
diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result
index 2941352c776..d8491035f0b 100644
--- a/mysql-test/r/func_time.result
+++ b/mysql-test/r/func_time.result
@@ -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;
diff --git a/mysql-test/r/having.result b/mysql-test/r/having.result
index a33ce457176..bd1bd523964 100644
--- a/mysql-test/r/having.result
+++ b/mysql-test/r/having.result
@@ -62,4 +62,8 @@ select Fld1, max(Fld2) from t1 group by Fld1 having std(Fld2) is not null;
Fld1 max(Fld2)
1 20
3 50
+select Fld1, max(Fld2) from t1 group by Fld1 having variance(Fld2) is not null;
+Fld1 max(Fld2)
+1 20
+3 50
drop table t1;
diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result
index 467436a2f85..82e678416ad 100644
--- a/mysql-test/r/innodb.result
+++ b/mysql-test/r/innodb.result
@@ -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;
diff --git a/mysql-test/r/join_outer.result b/mysql-test/r/join_outer.result
index 700b73d3eca..b89a6696727 100644
--- a/mysql-test/r/join_outer.result
+++ b/mysql-test/r/join_outer.result
@@ -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
diff --git a/mysql-test/r/key_primary.result b/mysql-test/r/key_primary.result
index e148548b721..14ca90b3dd2 100644
--- a/mysql-test/r/key_primary.result
+++ b/mysql-test/r/key_primary.result
@@ -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;
diff --git a/mysql-test/r/keywords.result b/mysql-test/r/keywords.result
index 2ca36425841..c218379110f 100644
--- a/mysql-test/r/keywords.result
+++ b/mysql-test/r/keywords.result
@@ -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
diff --git a/mysql-test/r/merge.result b/mysql-test/r/merge.result
index cd78ac791c4..d0e595d6551 100644
--- a/mysql-test/r/merge.result
+++ b/mysql-test/r/merge.result
@@ -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;
diff --git a/mysql-test/r/odbc.result b/mysql-test/r/odbc.result
index 498147704a3..30366762cd0 100644
--- a/mysql-test/r/odbc.result
+++ b/mysql-test/r/odbc.result
@@ -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;
diff --git a/mysql-test/r/range.result b/mysql-test/r/range.result
index a3663416bc8..86a93398a9f 100644
--- a/mysql-test/r/range.result
+++ b/mysql-test/r/range.result
@@ -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
diff --git a/mysql-test/r/row.result b/mysql-test/r/row.result
new file mode 100644
index 00000000000..1d606fc370c
--- /dev/null
+++ b/mysql-test/r/row.result
@@ -0,0 +1,136 @@
+select row(1,2,3) IN (row(3,2,3), row(1,2,3), row(1,3,3));
+row(1,2,3) IN (row(3,2,3), row(1,2,3), row(1,3,3))
+1
+select row(10,2,3) IN (row(3,2,3), row(1,2,3), row(1,3,3));
+row(10,2,3) IN (row(3,2,3), row(1,2,3), row(1,3,3))
+0
+select row(1,2,3) IN (row(3,NULL,3), row(1,2,3), row(1,3,3));
+row(1,2,3) IN (row(3,NULL,3), row(1,2,3), row(1,3,3))
+1
+select row(10,2,3) IN (row(3,NULL,3), row(1,2,3), row(1,3,3));
+row(10,2,3) IN (row(3,NULL,3), row(1,2,3), row(1,3,3))
+0
+select row('a',1.5,3) IN (row(1,2,3), row('a',1.5,3), row('a','a','a'));
+row('a',1.5,3) IN (row(1,2,3), row('a',1.5,3), row('a','a','a'))
+1
+select row('a',0,3) IN (row(3,2,3), row('a','0','3'), row(1,3,3));
+row('a',0,3) IN (row(3,2,3), row('a','0','3'), row(1,3,3))
+1
+select row('a',0,3) IN (row(3,2,3), row('a','a','3'), row(1,3,3));
+row('a',0,3) IN (row(3,2,3), row('a','a','3'), row(1,3,3))
+1
+select row('a',1.5,3) IN (row(3,NULL,3), row('a',1.5,3), row(1,3,3));
+row('a',1.5,3) IN (row(3,NULL,3), row('a',1.5,3), row(1,3,3))
+1
+select row('b',1.5,3) IN (row(3,NULL,3), row('a',1.5,3), row(1,3,3));
+row('b',1.5,3) IN (row(3,NULL,3), row('a',1.5,3), row(1,3,3))
+0
+select row('b',1.5,3) IN (row('b',NULL,3), row('a',1.5,3), row(1,3,3));
+row('b',1.5,3) IN (row('b',NULL,3), row('a',1.5,3), row(1,3,3))
+NULL
+select row('b',1.5,3) IN (row('b',NULL,4), row('a',1.5,3), row(1,3,3));
+row('b',1.5,3) IN (row('b',NULL,4), row('a',1.5,3), row(1,3,3))
+0
+select row(1,2,row(3,4)) IN (row(3,2,row(3,4)), row(1,2,row(3,4)));
+row(1,2,row(3,4)) IN (row(3,2,row(3,4)), row(1,2,row(3,4)))
+1
+select row(1,2,row(3,4)) IN (row(3,2,row(3,4)), row(1,2,4));
+Cardinality error (more/less than 2 columns)
+select row(1,2,row(3,4)) IN (row(3,2,row(3,4)), row(1,2,row(3,NULL)));
+row(1,2,row(3,4)) IN (row(3,2,row(3,4)), row(1,2,row(3,NULL)))
+NULL
+SELECT ROW(1,2,3)=ROW(1,2,3);
+ROW(1,2,3)=ROW(1,2,3)
+1
+SELECT ROW(2,2,3)=ROW(1+1,2,3);
+ROW(2,2,3)=ROW(1+1,2,3)
+1
+SELECT ROW(1,2,3)=ROW(1+1,2,3);
+ROW(1,2,3)=ROW(1+1,2,3)
+0
+SELECT ROW(1,2,3)<ROW(1+1,2,3);
+ROW(1,2,3)<ROW(1+1,2,3)
+1
+SELECT ROW(1,2,3)>ROW(1+1,2,3);
+ROW(1,2,3)>ROW(1+1,2,3)
+0
+SELECT ROW(1,2,3)<=ROW(1+1,2,3);
+ROW(1,2,3)<=ROW(1+1,2,3)
+1
+SELECT ROW(1,2,3)>=ROW(1+1,2,3);
+ROW(1,2,3)>=ROW(1+1,2,3)
+0
+SELECT ROW(1,2,3)<>ROW(1+1,2,3);
+ROW(1,2,3)<>ROW(1+1,2,3)
+1
+SELECT ROW(NULL,2,3)=ROW(NULL,2,3);
+ROW(NULL,2,3)=ROW(NULL,2,3)
+NULL
+SELECT ROW(NULL,2,3)<=>ROW(NULL,2,3);
+ROW(NULL,2,3)<=>ROW(NULL,2,3)
+1
+SELECT ROW(1,2,ROW(3,4,5))=ROW(1,2,ROW(3,4,5));
+ROW(1,2,ROW(3,4,5))=ROW(1,2,ROW(3,4,5))
+1
+SELECT ROW('test',2,3.33)=ROW('test',2,3.33);
+ROW('test',2,3.33)=ROW('test',2,3.33)
+1
+SELECT ROW('test',2,3.33)=ROW('test',2,3.33,4);
+Cardinality error (more/less than 3 columns)
+SELECT ROW('test',2,ROW(3,33))=ROW('test',2,ROW(3,33));
+ROW('test',2,ROW(3,33))=ROW('test',2,ROW(3,33))
+1
+SELECT ROW('test',2,ROW(3,33))=ROW('test',2,ROW(3,3));
+ROW('test',2,ROW(3,33))=ROW('test',2,ROW(3,3))
+0
+SELECT ROW('test',2,ROW(3,33))=ROW('test',2,ROW(3,NULL));
+ROW('test',2,ROW(3,33))=ROW('test',2,ROW(3,NULL))
+NULL
+SELECT ROW('test',2,ROW(3,33))=ROW('test',2,4);
+Cardinality error (more/less than 2 columns)
+drop table if exists t1;
+create table t1 ( a int, b int, c int);
+insert into t1 values (1,2,3), (2,3,1), (3,2,1), (1,2,NULL);
+select * from t1 where ROW(1,2,3)=ROW(a,b,c);
+a b c
+1 2 3
+select * from t1 where ROW(0,2,3)=ROW(a,b,c);
+a b c
+select * from t1 where ROW(1,2,3)<ROW(a,b,c);
+a b c
+2 3 1
+3 2 1
+select ROW(a,2,3) IN(row(1,b,c), row(2,3,1)) from t1;
+ROW(a,2,3) IN(row(1,b,c), row(2,3,1))
+1
+0
+0
+NULL
+select ROW(c,2,3) IN(row(1,b,a), row(2,3,1)) from t1;
+ROW(c,2,3) IN(row(1,b,a), row(2,3,1))
+0
+0
+1
+NULL
+select ROW(a,b,c) IN(row(1,2,3), row(3,2,1)) from t1;
+ROW(a,b,c) IN(row(1,2,3), row(3,2,1))
+1
+0
+1
+NULL
+select ROW(1,2,3) IN(row(a,b,c), row(1,2,3)) from t1;
+ROW(1,2,3) IN(row(a,b,c), row(1,2,3))
+1
+1
+1
+1
+drop table t1;
+select ROW(1,1);
+Cardinality error (more/less than 1 columns)
+drop table if exists t1;
+create table t1 (i int);
+select 1 from t1 where ROW(1,1);
+Cardinality error (more/less than 1 columns)
+select count(*) from t1 order by ROW(1,1);
+Cardinality error (more/less than 1 columns)
+drop table t1;
diff --git a/mysql-test/r/row_test.result b/mysql-test/r/row_test.result
deleted file mode 100644
index f6e989789c7..00000000000
--- a/mysql-test/r/row_test.result
+++ /dev/null
@@ -1,60 +0,0 @@
-SELECT ROW(1,2,3)=ROW(1,2,3);
-ROW(1,2,3)=ROW(1,2,3)
-1
-SELECT ROW(2,2,3)=ROW(1+1,2,3);
-ROW(2,2,3)=ROW(1+1,2,3)
-1
-SELECT ROW(1,2,3)=ROW(1+1,2,3);
-ROW(1,2,3)=ROW(1+1,2,3)
-0
-SELECT ROW(1,2,3)<ROW(1+1,2,3);
-ROW(1,2,3)<ROW(1+1,2,3)
-1
-SELECT ROW(1,2,3)>ROW(1+1,2,3);
-ROW(1,2,3)>ROW(1+1,2,3)
-0
-SELECT ROW(1,2,3)<=ROW(1+1,2,3);
-ROW(1,2,3)<=ROW(1+1,2,3)
-1
-SELECT ROW(1,2,3)>=ROW(1+1,2,3);
-ROW(1,2,3)>=ROW(1+1,2,3)
-0
-SELECT ROW(1,2,3)<>ROW(1+1,2,3);
-ROW(1,2,3)<>ROW(1+1,2,3)
-1
-SELECT ROW(NULL,2,3)=ROW(NULL,2,3);
-ROW(NULL,2,3)=ROW(NULL,2,3)
-NULL
-SELECT ROW(NULL,2,3)<=>ROW(NULL,2,3);
-ROW(NULL,2,3)<=>ROW(NULL,2,3)
-1
-SELECT ROW(1,2,ROW(3,4,5))=ROW(1,2,ROW(3,4,5));
-ROW(1,2,ROW(3,4,5))=ROW(1,2,ROW(3,4,5))
-1
-SELECT ROW('test',2,3.33)=ROW('test',2,3.33);
-ROW('test',2,3.33)=ROW('test',2,3.33)
-1
-SELECT ROW('test',2,3.33)=ROW('test',2,3.33,4);
-Cardinality error (more/less than 3 columns)
-drop table if exists t1;
-create table t1 ( a int, b int, c int);
-insert into t1 values (1,2,3), (2,3,1), (3,2,1);
-select * from t1 where ROW(1,2,3)=ROW(a,b,c);
-a b c
-1 2 3
-select * from t1 where ROW(0,2,3)=ROW(a,b,c);
-a b c
-select * from t1 where ROW(1,2,3)<ROW(a,b,c);
-a b c
-2 3 1
-3 2 1
-drop table t1;
-select ROW(1,1);
-Cardinality error (more/less than 1 columns)
-drop table if exists t1;
-create table t1 (i int);
-select 1 from t1 where ROW(1,1);
-Cardinality error (more/less than 1 columns)
-select count(*) from t1 order by ROW(1,1);
-Cardinality error (more/less than 1 columns)
-drop table t1;
diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result
index 46343eb8248..80aa6046e8d 100644
--- a/mysql-test/r/select.result
+++ b/mysql-test/r/select.result
@@ -2656,14 +2656,14 @@ companynr count(*)
58 23
53 4
50 11
-select count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1) from t2 where companynr = 34 and fld4<>"";
-count(*) min(fld4) max(fld4) sum(fld1) avg(fld1) std(fld1)
-70 absentee vest 17788966 254128.0857 3272.5940
-select companynr,count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1) from t2 group by companynr limit 3;
-companynr count(*) min(fld4) max(fld4) sum(fld1) avg(fld1) std(fld1)
-00 82 Anthony windmills 10355753 126289.6707 115550.9757
-29 95 abut wetness 14473298 152350.5053 8368.5480
-34 70 absentee vest 17788966 254128.0857 3272.5940
+select count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1),variance(fld1) from t2 where companynr = 34 and fld4<>"";
+count(*) min(fld4) max(fld4) sum(fld1) avg(fld1) std(fld1) variance(fld1)
+70 absentee vest 17788966 254128.0857 3272.5940 10709871.3069
+select companynr,count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1),variance(fld1) from t2 group by companynr limit 3;
+companynr count(*) min(fld4) max(fld4) sum(fld1) avg(fld1) std(fld1) variance(fld1)
+00 82 Anthony windmills 10355753 126289.6707 115550.9757 13352027981.7087
+29 95 abut wetness 14473298 152350.5053 8368.5480 70032594.9026
+34 70 absentee vest 17788966 254128.0857 3272.5940 10709871.3069
select companynr,t2nr,count(price),sum(price),min(price),max(price),avg(price) from t3 where companynr = 37 group by companynr,t2nr limit 10;
companynr t2nr count(price) sum(price) min(price) max(price) avg(price)
37 1 1 5987435 5987435 5987435 5987435.0000
@@ -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
diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result
index d442e4d97ce..493768ece4a 100644
--- a/mysql-test/r/subselect.result
+++ b/mysql-test/r/subselect.result
@@ -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
@@ -47,6 +47,11 @@ select (SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE(1));
Wrong usage of PROCEDURE and subquery
SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE((SELECT 1));
Incorrect parameters to procedure 'ANALYSE'
+SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NULL;
+a
+SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NOT NULL;
+a
+1
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8;
create table t1 (a int);
create table t2 (a int, b int);
@@ -280,7 +285,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 +303,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 +399,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 +579,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);
@@ -598,3 +603,105 @@ INSERT INTO t1 values (1),(1);
UPDATE t SET id=(SELECT * FROM t1);
Subselect returns more than 1 record
drop table t;
+create table t (a int);
+insert into t values (1),(2),(3);
+select 1 IN (SELECT * from t);
+1 IN (SELECT * from t)
+1
+select 10 IN (SELECT * from t);
+10 IN (SELECT * from t)
+0
+select NULL IN (SELECT * from t);
+NULL IN (SELECT * from t)
+NULL
+update t set a=NULL where a=2;
+select 1 IN (SELECT * from t);
+1 IN (SELECT * from t)
+1
+select 3 IN (SELECT * from t);
+3 IN (SELECT * from t)
+1
+select 10 IN (SELECT * from t);
+10 IN (SELECT * from t)
+NULL
+select 1 > ALL (SELECT * from t);
+1 > ALL (SELECT * from t)
+0
+select 10 > ALL (SELECT * from t);
+10 > ALL (SELECT * from t)
+NULL
+select 1 > ANY (SELECT * from t);
+1 > ANY (SELECT * from t)
+NULL
+select 10 > ANY (SELECT * from t);
+10 > ANY (SELECT * from t)
+1
+drop table t;
+create table t (a varchar(20));
+insert into t values ('A'),('BC'),('DEF');
+select 'A' IN (SELECT * from t);
+'A' IN (SELECT * from t)
+1
+select 'XYZS' IN (SELECT * from t);
+'XYZS' IN (SELECT * from t)
+0
+select NULL IN (SELECT * from t);
+NULL IN (SELECT * from t)
+NULL
+update t set a=NULL where a='BC';
+select 'A' IN (SELECT * from t);
+'A' IN (SELECT * from t)
+1
+select 'DEF' IN (SELECT * from t);
+'DEF' IN (SELECT * from t)
+1
+select 'XYZS' IN (SELECT * from t);
+'XYZS' IN (SELECT * from t)
+NULL
+select 'A' > ALL (SELECT * from t);
+'A' > ALL (SELECT * from t)
+0
+select 'XYZS' > ALL (SELECT * from t);
+'XYZS' > ALL (SELECT * from t)
+NULL
+select 'A' > ANY (SELECT * from t);
+'A' > ANY (SELECT * from t)
+NULL
+select 'XYZS' > ANY (SELECT * from t);
+'XYZS' > ANY (SELECT * from t)
+1
+drop table t;
+create table t (a float);
+insert into t values (1.5),(2.5),(3.5);
+select 1.5 IN (SELECT * from t);
+1.5 IN (SELECT * from t)
+1
+select 10.5 IN (SELECT * from t);
+10.5 IN (SELECT * from t)
+0
+select NULL IN (SELECT * from t);
+NULL IN (SELECT * from t)
+NULL
+update t set a=NULL where a=2.5;
+select 1.5 IN (SELECT * from t);
+1.5 IN (SELECT * from t)
+1
+select 3.5 IN (SELECT * from t);
+3.5 IN (SELECT * from t)
+1
+select 10.5 IN (SELECT * from t);
+10.5 IN (SELECT * from t)
+NULL
+select 1.5 > ALL (SELECT * from t);
+1.5 > ALL (SELECT * from t)
+0
+select 10.5 > ALL (SELECT * from t);
+10.5 > ALL (SELECT * from t)
+NULL
+select 1.5 > ANY (SELECT * from t);
+1.5 > ANY (SELECT * from t)
+NULL
+select 10.5 > ANY (SELECT * from t);
+10.5 > ANY (SELECT * from t)
+1
+drop table t;
diff --git a/mysql-test/r/type_datetime.result b/mysql-test/r/type_datetime.result
index 1e58b8da42e..cac8cd3d71e 100644
--- a/mysql-test/r/type_datetime.result
+++ b/mysql-test/r/type_datetime.result
@@ -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);
diff --git a/mysql-test/r/type_ranges.result b/mysql-test/r/type_ranges.result
index d0f964e4641..ea2863aefce 100644
--- a/mysql-test/r/type_ranges.result
+++ b/mysql-test/r/type_ranges.result
@@ -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
diff --git a/mysql-test/r/type_timestamp.result b/mysql-test/r/type_timestamp.result
index 088f3b205b9..26dedf544c4 100644
--- a/mysql-test/r/type_timestamp.result
+++ b/mysql-test/r/type_timestamp.result
@@ -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;
diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result
index 02dda58d48f..3930e5e25c1 100644
--- a/mysql-test/r/union.result
+++ b/mysql-test/r/union.result
@@ -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;
@@ -201,3 +201,6 @@ set SQL_SELECT_LIMIT=DEFAULT;
drop table t1,t2;
select * union select 1;
No tables used
+select 1 as a,(select a union select a);
+a (select a union select a)
+1 1
diff --git a/mysql-test/t/analyse.test b/mysql-test/t/analyse.test
index 3f56b3e47ce..68b038c089f 100644
--- a/mysql-test/t/analyse.test
+++ b/mysql-test/t/analyse.test
@@ -9,3 +9,5 @@ select * from t1 procedure analyse();
create table t2 select * from t1 procedure analyse();
select * from t2;
drop table t1,t2;
+
+EXPLAIN SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE(); \ No newline at end of file
diff --git a/mysql-test/t/delete.test b/mysql-test/t/delete.test
index 953e22cdd55..704fb7ada1c 100644
--- a/mysql-test/t/delete.test
+++ b/mysql-test/t/delete.test
@@ -35,3 +35,13 @@ create table t1 (a bigint not null, primary key (a,a,a,a,a,a,a,a,a,a));
insert into t1 values (2),(4),(6),(8),(10),(12),(14),(16),(18),(20),(22),(24),(26),(23),(27);
delete from t1 where a=27;
drop table t1;
+
+drop table if exists t;
+CREATE TABLE `t` (
+ `i` int(10) NOT NULL default '0',
+ `i2` int(10) NOT NULL default '0',
+ PRIMARY KEY (`i`)
+) TYPE=MyISAM CHARSET=latin1;
+-- error 1054
+DELETE FROM t USING t WHERE post='1';
+drop table if exists t; \ No newline at end of file
diff --git a/mysql-test/t/derived.test b/mysql-test/t/derived.test
index 8f187dd46ba..5f63cea3c11 100644
--- a/mysql-test/t/derived.test
+++ b/mysql-test/t/derived.test
@@ -24,6 +24,10 @@ drop table if exists t1.t2,t3;
select * from (select 1) as a;
select a from (select 1 as a) as b;
select 1 from (select 1) as a;
+select * from (select * from t1 union select * from t1) a;
+select * from (select * from t1 union all select * from t1) a;
+explain select * from (select * from t1 union select * from t1) a;
+explain select * from (select * from t1 union all select * from t1) a;
drop table if exists t1;
create table t1(a int not null, t char(8), index(a));
disable_query_log;
diff --git a/mysql-test/t/func_group.test b/mysql-test/t/func_group.test
index 57e9ae24e08..8a9a5655e1b 100644
--- a/mysql-test/t/func_group.test
+++ b/mysql-test/t/func_group.test
@@ -21,9 +21,9 @@ select count(distinct a),count(distinct grp) from t1;
insert into t1 values (null,null,'');
select count(distinct a),count(distinct grp) from t1;
-select sum(a),count(a),avg(a),std(a),bit_or(a),bit_and(a),min(a),max(a),min(c),max(c) from t1;
-select grp, sum(a),count(a),avg(a),std(a),bit_or(a),bit_and(a),min(a),max(a),min(c),max(c) from t1 group by grp;
-select grp, sum(a)+count(a)+avg(a)+std(a)+bit_or(a)+bit_and(a)+min(a)+max(a)+min(c)+max(c) as sum from t1 group by grp;
+select sum(a),count(a),avg(a),std(a),variance(a),bit_or(a),bit_and(a),min(a),max(a),min(c),max(c) from t1;
+select grp, sum(a),count(a),avg(a),std(a),variance(a),bit_or(a),bit_and(a),min(a),max(a),min(c),max(c) from t1 group by grp;
+select grp, sum(a)+count(a)+avg(a)+std(a)+variance(a)+bit_or(a)+bit_and(a)+min(a)+max(a)+min(c)+max(c) as sum from t1 group by grp;
create table t2 (grp int, a bigint unsigned, c char(10));
insert into t2 select grp,max(a)+max(grp),max(c) from t1 group by grp;
@@ -40,8 +40,8 @@ CREATE TABLE t1 (id int(11),value1 float(10,2));
INSERT INTO t1 VALUES (1,0.00),(1,1.00), (1,2.00), (2,10.00), (2,11.00), (2,12.00);
CREATE TABLE t2 (id int(11),name char(20));
INSERT INTO t2 VALUES (1,'Set One'),(2,'Set Two');
-select id, avg(value1), std(value1) from t1 group by id;
-select name, avg(value1), std(value1) from t1, t2 where t1.id = t2.id group by t1.id;
+select id, avg(value1), std(value1), variance(value1) from t1 group by id;
+select name, avg(value1), std(value1), variance(value1) from t1, t2 where t1.id = t2.id group by t1.id;
drop table t1,t2;
#
diff --git a/mysql-test/t/func_in.test b/mysql-test/t/func_in.test
index e5d42ec25c4..7bbc560276f 100644
--- a/mysql-test/t/func_in.test
+++ b/mysql-test/t/func_in.test
@@ -2,7 +2,39 @@
# test of IN (NULL)
#
+select 1 in (1,2,3);
+select 10 in (1,2,3);
+select NULL in (1,2,3);
+select 1 in (1,NULL,3);
+select 3 in (1,NULL,3);
+select 10 in (1,NULL,3);
+select 1.5 in (1.5,2.5,3.5);
+select 10.5 in (1.5,2.5,3.5);
+select NULL in (1.5,2.5,3.5);
+select 1.5 in (1.5,NULL,3.5);
+select 3.5 in (1.5,NULL,3.5);
+select 10.5 in (1.5,NULL,3.5);
drop table if exists t1;
+CREATE TABLE t1 (a int, b int, c int);
+insert into t1 values (1,2,3), (1,NULL,3);
+select 1 in (a,b,c) from t1;
+select 3 in (a,b,c) from t1;
+select 10 in (a,b,c) from t1;
+select NULL in (a,b,c) from t1;
+drop table t1;
+CREATE TABLE t1 (a float, b float, c float);
+insert into t1 values (1.5,2.5,3.5), (1.5,NULL,3.5);
+select 1.5 in (a,b,c) from t1;
+select 3.5 in (a,b,c) from t1;
+select 10.5 in (a,b,c) from t1;
+drop table t1;
+CREATE TABLE t1 (a varchar(10), b varchar(10), c varchar(10));
+insert into t1 values ('A','BC','EFD'), ('A',NULL,'EFD');
+select 'A' in (a,b,c) from t1;
+select 'EFD' in (a,b,c) from t1;
+select 'XSFGGHF' in (a,b,c) from t1;
+drop table t1;
+
CREATE TABLE t1 (field char(1));
INSERT INTO t1 VALUES ('A'),(NULL);
SELECT * from t1 WHERE field IN (NULL);
diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test
index 717b9c86a07..d355cc95317 100644
--- a/mysql-test/t/func_str.test
+++ b/mysql-test/t/func_str.test
@@ -36,6 +36,11 @@ select insert('txs',2,1,'hi'),insert('is ',4,0,'a'),insert('txxxxt',2,4,'es');
select replace('aaaa','a','b'),replace('aaaa','aa','b'),replace('aaaa','a','bb'),replace('aaaa','','b'),replace('bbbb','a','c');
select replace(concat(lcase(concat('THIS',' ','IS',' ','A',' ')),ucase('false'),' ','test'),'FALSE','REAL') ;
select soundex(''),soundex('he'),soundex('hello all folks');
+select 'mood' sounds like 'mud';
+select 'Glazgo' sounds like 'Liverpool';
+select null sounds like 'null';
+select 'null' sounds like null;
+select null sounds like null;
select md5('hello');
select sha('abc');
select sha1('abc');
@@ -110,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;
#
diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test
index dd589ff2e66..2e913bdf943 100644
--- a/mysql-test/t/func_time.test
+++ b/mysql-test/t/func_time.test
@@ -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;
diff --git a/mysql-test/t/having.test b/mysql-test/t/having.test
index 8dd7606d82b..7f0a1225bda 100644
--- a/mysql-test/t/having.test
+++ b/mysql-test/t/having.test
@@ -59,4 +59,5 @@ select Fld1, max(Fld2) as q from t1 group by Fld1 having q is not null;
select Fld1, max(Fld2) from t1 group by Fld1 having max(Fld2) is not null;
select Fld1, max(Fld2) from t1 group by Fld1 having avg(Fld2) is not null;
select Fld1, max(Fld2) from t1 group by Fld1 having std(Fld2) is not null;
+select Fld1, max(Fld2) from t1 group by Fld1 having variance(Fld2) is not null;
drop table t1;
diff --git a/mysql-test/t/merge.test b/mysql-test/t/merge.test
index 2199f50fb16..39c33ef8684 100644
--- a/mysql-test/t/merge.test
+++ b/mysql-test/t/merge.test
@@ -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;
diff --git a/mysql-test/t/row.test b/mysql-test/t/row.test
new file mode 100644
index 00000000000..593e2342856
--- /dev/null
+++ b/mysql-test/t/row.test
@@ -0,0 +1,61 @@
+select row(1,2,3) IN (row(3,2,3), row(1,2,3), row(1,3,3));
+select row(10,2,3) IN (row(3,2,3), row(1,2,3), row(1,3,3));
+select row(1,2,3) IN (row(3,NULL,3), row(1,2,3), row(1,3,3));
+select row(10,2,3) IN (row(3,NULL,3), row(1,2,3), row(1,3,3));
+select row('a',1.5,3) IN (row(1,2,3), row('a',1.5,3), row('a','a','a'));
+select row('a',0,3) IN (row(3,2,3), row('a','0','3'), row(1,3,3));
+select row('a',0,3) IN (row(3,2,3), row('a','a','3'), row(1,3,3));
+select row('a',1.5,3) IN (row(3,NULL,3), row('a',1.5,3), row(1,3,3));
+select row('b',1.5,3) IN (row(3,NULL,3), row('a',1.5,3), row(1,3,3));
+select row('b',1.5,3) IN (row('b',NULL,3), row('a',1.5,3), row(1,3,3));
+select row('b',1.5,3) IN (row('b',NULL,4), row('a',1.5,3), row(1,3,3));
+select row(1,2,row(3,4)) IN (row(3,2,row(3,4)), row(1,2,row(3,4)));
+-- error 1239
+select row(1,2,row(3,4)) IN (row(3,2,row(3,4)), row(1,2,4));
+select row(1,2,row(3,4)) IN (row(3,2,row(3,4)), row(1,2,row(3,NULL)));
+
+SELECT ROW(1,2,3)=ROW(1,2,3);
+SELECT ROW(2,2,3)=ROW(1+1,2,3);
+SELECT ROW(1,2,3)=ROW(1+1,2,3);
+SELECT ROW(1,2,3)<ROW(1+1,2,3);
+SELECT ROW(1,2,3)>ROW(1+1,2,3);
+SELECT ROW(1,2,3)<=ROW(1+1,2,3);
+SELECT ROW(1,2,3)>=ROW(1+1,2,3);
+SELECT ROW(1,2,3)<>ROW(1+1,2,3);
+SELECT ROW(NULL,2,3)=ROW(NULL,2,3);
+SELECT ROW(NULL,2,3)<=>ROW(NULL,2,3);
+SELECT ROW(1,2,ROW(3,4,5))=ROW(1,2,ROW(3,4,5));
+SELECT ROW('test',2,3.33)=ROW('test',2,3.33);
+-- error 1239
+SELECT ROW('test',2,3.33)=ROW('test',2,3.33,4);
+SELECT ROW('test',2,ROW(3,33))=ROW('test',2,ROW(3,33));
+SELECT ROW('test',2,ROW(3,33))=ROW('test',2,ROW(3,3));
+SELECT ROW('test',2,ROW(3,33))=ROW('test',2,ROW(3,NULL));
+-- error 1239
+SELECT ROW('test',2,ROW(3,33))=ROW('test',2,4);
+drop table if exists t1;
+create table t1 ( a int, b int, c int);
+insert into t1 values (1,2,3), (2,3,1), (3,2,1), (1,2,NULL);
+select * from t1 where ROW(1,2,3)=ROW(a,b,c);
+select * from t1 where ROW(0,2,3)=ROW(a,b,c);
+select * from t1 where ROW(1,2,3)<ROW(a,b,c);
+select ROW(a,2,3) IN(row(1,b,c), row(2,3,1)) from t1;
+select ROW(c,2,3) IN(row(1,b,a), row(2,3,1)) from t1;
+select ROW(a,b,c) IN(row(1,2,3), row(3,2,1)) from t1;
+select ROW(1,2,3) IN(row(a,b,c), row(1,2,3)) from t1;
+drop table t1;
+
+-- error 1239
+select ROW(1,1);
+drop table if exists t1;
+create table t1 (i int);
+-- error 1239
+select 1 from t1 where ROW(1,1);
+-- error 1239
+select count(*) from t1 order by ROW(1,1);
+#TODO remove comments after parser fixing
+#-- error 1239
+#select count(*) from t1 order by i having (1,1);
+#-- error 1239
+#select 1 from t1 limit (1,1), (1,1);
+drop table t1;
diff --git a/mysql-test/t/row_test.test b/mysql-test/t/row_test.test
deleted file mode 100644
index 5daacaa1ee6..00000000000
--- a/mysql-test/t/row_test.test
+++ /dev/null
@@ -1,36 +0,0 @@
-SELECT ROW(1,2,3)=ROW(1,2,3);
-SELECT ROW(2,2,3)=ROW(1+1,2,3);
-SELECT ROW(1,2,3)=ROW(1+1,2,3);
-SELECT ROW(1,2,3)<ROW(1+1,2,3);
-SELECT ROW(1,2,3)>ROW(1+1,2,3);
-SELECT ROW(1,2,3)<=ROW(1+1,2,3);
-SELECT ROW(1,2,3)>=ROW(1+1,2,3);
-SELECT ROW(1,2,3)<>ROW(1+1,2,3);
-SELECT ROW(NULL,2,3)=ROW(NULL,2,3);
-SELECT ROW(NULL,2,3)<=>ROW(NULL,2,3);
-SELECT ROW(1,2,ROW(3,4,5))=ROW(1,2,ROW(3,4,5));
-SELECT ROW('test',2,3.33)=ROW('test',2,3.33);
--- error 1239
-SELECT ROW('test',2,3.33)=ROW('test',2,3.33,4);
-drop table if exists t1;
-create table t1 ( a int, b int, c int);
-insert into t1 values (1,2,3), (2,3,1), (3,2,1);
-select * from t1 where ROW(1,2,3)=ROW(a,b,c);
-select * from t1 where ROW(0,2,3)=ROW(a,b,c);
-select * from t1 where ROW(1,2,3)<ROW(a,b,c);
-drop table t1;
-
--- error 1239
-select ROW(1,1);
-drop table if exists t1;
-create table t1 (i int);
--- error 1239
-select 1 from t1 where ROW(1,1);
--- error 1239
-select count(*) from t1 order by ROW(1,1);
-#TODO remove comments after parser fixing
-#-- error 1239
-#select count(*) from t1 order by i having (1,1);
-#-- error 1239
-#select 1 from t1 limit (1,1), (1,1);
-drop table t1;
diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test
index 64287dc4170..7ea86845cb0 100644
--- a/mysql-test/t/select.test
+++ b/mysql-test/t/select.test
@@ -1577,8 +1577,8 @@ select fld3 from t2 where (((fld3 like "_%L%" ) or (fld3 like "%ok%")) and ( fld
select count(*) from t1;
select companynr,count(*),sum(fld1) from t2 group by companynr;
select companynr,count(*) from t2 group by companynr order by companynr desc limit 5;
-select count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1) from t2 where companynr = 34 and fld4<>"";
-select companynr,count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1) from t2 group by companynr limit 3;
+select count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1),variance(fld1) from t2 where companynr = 34 and fld4<>"";
+select companynr,count(*),min(fld4),max(fld4),sum(fld1),avg(fld1),std(fld1),variance(fld1) from t2 group by companynr limit 3;
select companynr,t2nr,count(price),sum(price),min(price),max(price),avg(price) from t3 where companynr = 37 group by companynr,t2nr limit 10;
select /*! SQL_SMALL_RESULT */ companynr,t2nr,count(price),sum(price),min(price),max(price),avg(price) from t3 where companynr = 37 group by companynr,t2nr limit 10;
select companynr,count(price),sum(price),min(price),max(price),avg(price) from t3 group by companynr ;
diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test
index 8b174882bc6..0527d6a2001 100644
--- a/mysql-test/t/subselect.test
+++ b/mysql-test/t/subselect.test
@@ -24,6 +24,8 @@ SELECT 1 FROM (SELECT 1 as a) b WHERE 1 IN (SELECT (SELECT a));
select (SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE(1));
-- error 1108
SELECT 1 FROM (SELECT 1) a PROCEDURE ANALYSE((SELECT 1));
+SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NULL;
+SELECT (SELECT 1) as a FROM (SELECT 1) b WHERE (SELECT a) IS NOT NULL;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8;
create table t1 (a int);
@@ -362,3 +364,48 @@ INSERT INTO t1 values (1),(1);
-- error 1240
UPDATE t SET id=(SELECT * FROM t1);
drop table t;
+
+
+#NULL test
+create table t (a int);
+insert into t values (1),(2),(3);
+select 1 IN (SELECT * from t);
+select 10 IN (SELECT * from t);
+select NULL IN (SELECT * from t);
+update t set a=NULL where a=2;
+select 1 IN (SELECT * from t);
+select 3 IN (SELECT * from t);
+select 10 IN (SELECT * from t);
+select 1 > ALL (SELECT * from t);
+select 10 > ALL (SELECT * from t);
+select 1 > ANY (SELECT * from t);
+select 10 > ANY (SELECT * from t);
+drop table t;
+create table t (a varchar(20));
+insert into t values ('A'),('BC'),('DEF');
+select 'A' IN (SELECT * from t);
+select 'XYZS' IN (SELECT * from t);
+select NULL IN (SELECT * from t);
+update t set a=NULL where a='BC';
+select 'A' IN (SELECT * from t);
+select 'DEF' IN (SELECT * from t);
+select 'XYZS' IN (SELECT * from t);
+select 'A' > ALL (SELECT * from t);
+select 'XYZS' > ALL (SELECT * from t);
+select 'A' > ANY (SELECT * from t);
+select 'XYZS' > ANY (SELECT * from t);
+drop table t;
+create table t (a float);
+insert into t values (1.5),(2.5),(3.5);
+select 1.5 IN (SELECT * from t);
+select 10.5 IN (SELECT * from t);
+select NULL IN (SELECT * from t);
+update t set a=NULL where a=2.5;
+select 1.5 IN (SELECT * from t);
+select 3.5 IN (SELECT * from t);
+select 10.5 IN (SELECT * from t);
+select 1.5 > ALL (SELECT * from t);
+select 10.5 > ALL (SELECT * from t);
+select 1.5 > ANY (SELECT * from t);
+select 10.5 > ANY (SELECT * from t);
+drop table t;
diff --git a/mysql-test/t/type_datetime.test b/mysql-test/t/type_datetime.test
index a516bc89f99..991f11e86ea 100644
--- a/mysql-test/t/type_datetime.test
+++ b/mysql-test/t/type_datetime.test
@@ -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;
#
diff --git a/mysql-test/t/type_timestamp.test b/mysql-test/t/type_timestamp.test
index 2929184df93..c51d439fde4 100644
--- a/mysql-test/t/type_timestamp.test
+++ b/mysql-test/t/type_timestamp.test
@@ -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);
diff --git a/mysql-test/t/union.test b/mysql-test/t/union.test
index 9ddfda7872f..449bafbdef6 100644
--- a/mysql-test/t/union.test
+++ b/mysql-test/t/union.test
@@ -103,3 +103,4 @@ drop table t1,t2;
--error 1096
select * union select 1;
+select 1 as a,(select a union select a);
diff --git a/sql/Makefile.am b/sql/Makefile.am
index c5af51e8397..245e4c5d258 100644
--- a/sql/Makefile.am
+++ b/sql/Makefile.am
@@ -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 \
diff --git a/sql/field.cc b/sql/field.cc
index 59033dd2d7f..e6a4c30d7f5 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -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++)
- {
- 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=0; // Safeguard
- val_buffer->length((uint) (to-val_buffer->ptr()));
+
+ temp= l_time->tm_year % 100;
+ if (temp < YY_PART_YEAR)
+ {
+ *to++= '2';
+ *to++= '0';
+ }
+ 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
@@ -5265,7 +5308,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);
diff --git a/sql/field.h b/sql/field.h
index 7a1a191ab43..9258e15ed04 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -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);
@@ -959,6 +979,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; }
diff --git a/sql/gen_lex_hash.cc b/sql/gen_lex_hash.cc
index 7daab228093..7ae28e0ce77 100644
--- a/sql/gen_lex_hash.cc
+++ b/sql/gen_lex_hash.cc
@@ -200,19 +200,21 @@ void insert_sql_functions()
}
}
-void generate_find_structs()
+void calc_length()
{
- root_by_len= 0;
- max_len=0;
- size_t i;
-
SYMBOL *cur, *end= symbols + array_elements(symbols);
for (cur= symbols; cur < end; cur++)
cur->length=(uchar) strlen(cur->name);
end= sql_functions + array_elements(sql_functions);
for (cur= sql_functions; cur<end; cur++)
cur->length=(uchar) strlen(cur->name);
-
+}
+
+void generate_find_structs()
+{
+ root_by_len= 0;
+ max_len=0;
+
insert_symbols();
root_by_len2= root_by_len;
@@ -351,6 +353,45 @@ static int get_options(int argc, char **argv)
return(0);
}
+int check_dup_symbols(SYMBOL *s1, SYMBOL *s2)
+{
+ if (s1->length!=s2->length || strncmp(s1->name,s2->name,s1->length))
+ return 0;
+
+ const char *err_tmpl= "\ngen_lex_hash fatal error : \
+Unfortunately gen_lex_hash can not generate a hash,\n since \
+your lex.h has duplicate definition for a symbol \"%s\"\n\n";
+ printf (err_tmpl,s1->name);
+ fprintf (stderr,err_tmpl,s1->name);
+
+ return 1;
+}
+
+int check_duplicates()
+{
+ SYMBOL *cur1, *cur2, *s_end, *f_end;
+
+ s_end= symbols + array_elements(symbols);
+ f_end= sql_functions + array_elements(sql_functions);
+
+ for (cur1= symbols; cur1<s_end; cur1++)
+ {
+ for (cur2= cur1+1; cur2<s_end; cur2++)
+ if (check_dup_symbols(cur1,cur2))
+ return 1;
+ for (cur2= sql_functions; cur2<f_end; cur2++)
+ if (check_dup_symbols(cur1,cur2))
+ return 1;
+ }
+
+ for (cur1= sql_functions; cur1<f_end; cur1++)
+ for (cur2= cur1+1; cur2< f_end; cur2++)
+ if (check_dup_symbols(cur1,cur2))
+ return 1;
+
+ return 0;
+}
+
int main(int argc,char **argv)
{
MY_INIT(argv[0]);
@@ -376,6 +417,11 @@ int main(int argc,char **argv)
a perfect\nhash function */\n\n");
printf("#include \"lex.h\"\n\n");
+ calc_length();
+
+ if (check_duplicates())
+ exit(1);
+
generate_find_structs();
print_find_structs();
diff --git a/sql/ha_berkeley.cc b/sql/ha_berkeley.cc
index bcbc3335203..1b8a2d9b3f8 100644
--- a/sql/ha_berkeley.cc
+++ b/sql/ha_berkeley.cc
@@ -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,19 +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 (SEND_ROW(thd, 3, (char*) packet->ptr(),packet->length()))
+ if (protocol->write())
{
error=1;
goto err;
@@ -2066,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;
@@ -2075,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
diff --git a/sql/ha_berkeley.h b/sql/ha_berkeley.h
index f2a81d123f1..dfdd12470d6 100644
--- a/sql/ha_berkeley.h
+++ b/sql/ha_berkeley.h
@@ -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);
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index 300de4748bc..f4d21bf6216 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -3924,9 +3924,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) {
@@ -3947,21 +3946,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 (SEND_ROW(thd, field_list.elements, (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);
diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc
index 5cf77698e6b..0680f13a7df 100644
--- a/sql/ha_myisam.cc
+++ b/sql/ha_myisam.cc
@@ -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));
@@ -70,19 +68,20 @@ static void mi_check_print_msg(MI_CHECK *param, const char* msg_type,
}
#endif
- 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 (SEND_ROW(thd, 4, (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;
diff --git a/sql/item.cc b/sql/item.cc
index 6eb2adb9392..10d26060278 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -22,6 +22,7 @@
#include "mysql_priv.h"
#include <m_ctype.h>
#include "my_dir.h"
+#include <assert.h>
/*****************************************************************************
** Item functions
@@ -46,6 +47,12 @@ Item::Item():
loop_id= 0;
}
+Item_ref_in_optimizer::Item_ref_in_optimizer(Item_in_optimizer *master,
+ char *table_name_par,
+ char *field_name_par):
+ Item_ref(master->args, table_name_par, field_name_par), owner(master) {}
+
+
bool Item::check_loop(uint id)
{
DBUG_ENTER("Item::check_loop");
@@ -372,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) {
@@ -436,6 +437,20 @@ String *Item_copy_string::val_str(String *str)
return &str_value;
}
+double Item_ref_in_optimizer::val()
+{
+ return owner->get_cache();
+}
+longlong Item_ref_in_optimizer::val_int()
+{
+ return owner->get_cache_int();
+}
+String* Item_ref_in_optimizer::val_str(String* s)
+{
+ return owner->get_cache_str(s);
+}
+
+
/*
Functions to convert item to field (for send_fields)
*/
@@ -511,10 +526,31 @@ bool Item_asterisk_remover::fix_fields(THD *thd,
res= item->fix_fields(thd, list, &item);
else
thd->fatal_error= 1; // no item given => out of memory
- *ref= item;
DBUG_RETURN(res);
}
+double Item_ref_null_helper::val()
+{
+ double tmp= (*ref)->val_result();
+ owner->was_null|= null_value= (*ref)->null_value;
+ return tmp;
+}
+longlong Item_ref_null_helper::val_int()
+{
+ longlong tmp= (*ref)->val_int_result();
+ owner->was_null|= null_value= (*ref)->null_value;
+ return tmp;
+}
+String* Item_ref_null_helper::val_str(String* s)
+{
+ String* tmp= (*ref)->str_result(s);
+ owner->was_null|= null_value= (*ref)->null_value;
+ return tmp;
+}
+bool Item_ref_null_helper::get_date(TIME *ltime, bool fuzzydate)
+{
+ return (owner->was_null|= null_value= (*ref)->get_date(ltime, fuzzydate));
+}
bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{
@@ -632,65 +668,24 @@ void Item::init_make_field(Send_field *tmp_field,
tmp_field->flags |= UNSIGNED_FLAG;
}
-/* ARGSUSED */
-void Item_field::make_field(Send_field *tmp_field)
-{
- field->make_field(tmp_field);
- if (name)
- tmp_field->col_name=name; // Use user supplied name
-}
-
-void Item_int::make_field(Send_field *tmp_field)
-{
- init_make_field(tmp_field,FIELD_TYPE_LONGLONG);
-}
-
-void Item_uint::make_field(Send_field *tmp_field)
+void Item::make_field(Send_field *tmp_field)
{
- init_make_field(tmp_field,FIELD_TYPE_LONGLONG);
- tmp_field->flags|= UNSIGNED_FLAG;
- unsigned_flag=1;
+ init_make_field(tmp_field, field_type());
}
-void Item_real::make_field(Send_field *tmp_field)
+enum_field_types Item::field_type() const
{
- init_make_field(tmp_field,FIELD_TYPE_DOUBLE);
+ return ((result_type() == STRING_RESULT) ? FIELD_TYPE_VAR_STRING :
+ (result_type() == INT_RESULT) ? FIELD_TYPE_LONGLONG :
+ 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_std_field::make_field(Send_field *tmp_field)
+/* ARGSUSED */
+void Item_field::make_field(Send_field *tmp_field)
{
- init_make_field(tmp_field,FIELD_TYPE_DOUBLE);
+ field->make_field(tmp_field);
+ if (name)
+ tmp_field->col_name=name; // Use user supplied name
}
/*
@@ -899,31 +894,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);
}
#ifdef EMBEDDED_LIBRARY
@@ -985,7 +1067,6 @@ bool Item_field::embedded_send(const CONVERT *convert, CHARSET_INFO *charset, ME
#endif
-
/*
This is used for HAVING clause
Find field in select list having the same name
diff --git a/sql/item.h b/sql/item.h
index 8c7cc2a2f68..47c7541d3e3 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -20,6 +20,8 @@
#endif
class CONVERT;
+class Protocol;
+struct st_table_list;
void item_init(void); /* Init item functions */
class Item {
@@ -33,7 +35,8 @@ public:
enum Type {FIELD_ITEM,FUNC_ITEM,SUM_FUNC_ITEM,STRING_ITEM,
INT_ITEM,REAL_ITEM,NULL_ITEM,VARBIN_ITEM,
COPY_STR_ITEM,FIELD_AVG_ITEM, DEFAULT_ITEM,
- PROC_ITEM,COND_ITEM,REF_ITEM,FIELD_STD_ITEM, CONST_ITEM,
+ PROC_ITEM,COND_ITEM,REF_ITEM,FIELD_STD_ITEM,
+ FIELD_VARIANCE_ITEM,CONST_ITEM,
SUBSELECT_ITEM, ROW_ITEM};
enum cond_result { COND_UNDEF,COND_OK,COND_TRUE,COND_FALSE };
@@ -53,30 +56,30 @@ 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);
#ifdef EMBEDDED_LIBRARY
virtual bool embedded_send(const CONVERT *convert, CHARSET_INFO *charset, MEM_ROOT *alloc,
char **result, ulong *length);
#endif
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(); }
virtual longlong val_int_result() { return val_int(); }
virtual String *str_result(String* tmp) { return val_str(tmp); }
- virtual bool is_null_result() { return is_null(); }
virtual table_map used_tables() const { return (table_map) 0L; }
virtual bool basic_const_item() const { return 0; }
virtual Item *new_item() { return 0; } /* Only for const items */
@@ -104,6 +107,8 @@ public:
virtual Item* el(uint i) { return this; }
virtual Item** addr(uint i) { return 0; }
virtual bool check_cols(uint c);
+ // It is not row => null inside is impossible
+ virtual bool null_inside() { return 0; };
};
@@ -121,11 +126,30 @@ 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); }
+ bool is_null()
+ {
+ item->val_int();
+ return item->null_value;
+ }
+ bool get_date(TIME *ltime, bool fuzzydate)
+ {
+ return (null_value=item->get_date(ltime, fuzzydate));
+ }
+ bool send(Protocol *prot, String *tmp) { return item->send(prot, tmp); }
+ int save_in_field(Field *field, bool no_conversions)
+ {
+ return item->save_in_field(field, no_conversions);
+ }
+ void save_org_in_field(Field *field) { item->save_org_in_field(field); }
+ enum Item_result result_type () const { return item->result_type(); }
+ table_map used_tables() const { return item->used_tables(); }
};
@@ -142,19 +166,6 @@ public:
bool fix_fields(THD *, struct st_table_list *, Item ** ref);
};
-/*
- To resolve '*' field moved to condition
-*/
-class Item_asterisk_remover :public Item_wrapper
-{
-public:
- Item_asterisk_remover(Item *it)
- {
- item= it;
- }
- bool fix_fields(THD *, struct st_table_list *, Item ** ref);
-};
-
class st_select_lex;
class Item_ident :public Item
{
@@ -192,17 +203,13 @@ public:
double val_result();
longlong val_int_result();
String *str_result(String* tmp);
- bool is_null_result() { return result_field->is_null(); }
- bool send(THD *thd, String *str_arg)
- {
- return result_field->send(thd,str_arg);
- }
+ bool send(Protocol *protocol, String *str_arg);
#ifdef EMBEDDED_LIBRARY
bool embedded_send(const CONVERT *convert, CHARSET_INFO *charset, MEM_ROOT *alloc,
char **result, ulong *length);
#endif
- void make_field(Send_field *field);
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;
@@ -210,6 +217,10 @@ public:
{
return field->result_type();
}
+ enum_field_types field_type() const
+ {
+ 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);
@@ -227,16 +238,21 @@ 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);
+ bool send(Protocol *protocol, String *str);
#ifdef EMBEDDED_LIBRARY
bool embedded_send(const CONVERT *convert, CHARSET_INFO *charset, MEM_ROOT *alloc,
char **result, ulong *length);
#endif
+ 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 basic_const_item() const { return 1; }
Item *new_item() { return new Item_null(name); }
bool is_null() { return 1; }
@@ -263,7 +279,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);
@@ -277,6 +292,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); }
};
@@ -297,11 +313,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); }
@@ -317,8 +333,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);
};
@@ -344,10 +365,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); }
};
@@ -392,13 +413,17 @@ 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() { return new Item_string(name,str_value.ptr(),max_length,default_charset_info); }
+ Item *new_item()
+ {
+ return new Item_string(name, str_value.ptr(), max_length,
+ default_charset_info);
+ }
String *const_string() { return &str_value; }
- inline void append(char *str,uint length) { str_value.append(str,length); }
+ inline void append(char *str, uint length) { str_value.append(str, length); }
void print(String *str);
};
@@ -410,7 +435,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();
@@ -430,7 +454,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
@@ -440,6 +464,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:
@@ -450,8 +488,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; }
};
@@ -482,31 +520,31 @@ public:
double val()
{
double tmp=(*ref)->val_result();
- null_value=(*ref)->is_null_result();
+ null_value=(*ref)->null_value;
return tmp;
}
longlong val_int()
{
longlong tmp=(*ref)->val_int_result();
- null_value=(*ref)->is_null_result();
+ null_value=(*ref)->null_value;
return tmp;
}
String *val_str(String* tmp)
{
tmp=(*ref)->str_result(tmp);
- null_value=(*ref)->is_null_result();
+ null_value=(*ref)->null_value;
return tmp;
}
bool is_null()
{
(void) (*ref)->val_int_result();
- return (*ref)->is_null_result();
+ return (*ref)->null_value;
}
bool get_date(TIME *ltime,bool fuzzydate)
{
return (null_value=(*ref)->get_date(ltime,fuzzydate));
}
- bool send(THD *thd, String *tmp) { return (*ref)->send(thd, tmp); }
+ bool send(Protocol *prot, String *tmp){ return (*ref)->send(prot, tmp); }
#ifdef EMBEDDED_LIBRARY
bool embedded_send(const CONVERT *convert, CHARSET_INFO *charset, MEM_ROOT *alloc,
char **result, ulong *length)
@@ -518,10 +556,59 @@ public:
{ 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);
};
+class Item_in_subselect;
+class Item_ref_null_helper: public Item_ref
+{
+protected:
+ Item_in_subselect* owner;
+public:
+ Item_ref_null_helper(Item_in_subselect* master, Item **item,
+ char *table_name_par,char *field_name_par):
+ Item_ref(item, table_name_par, field_name_par), owner(master) {}
+ double val();
+ longlong val_int();
+ String* val_str(String* s);
+ bool get_date(TIME *ltime, bool fuzzydate);
+};
+
+/*
+ To resolve '*' field moved to condition
+ and register NULL values
+*/
+class Item_asterisk_remover :public Item_ref_null_helper
+{
+ Item *item;
+public:
+ Item_asterisk_remover(Item_in_subselect *master, Item *it,
+ char *table, char *field):
+ Item_ref_null_helper(master, &item, table, field),
+ item(it)
+ {}
+ bool fix_fields(THD *, struct st_table_list *, Item ** ref);
+};
+
+class Item_in_optimizer;
+class Item_ref_in_optimizer: public Item_ref
+{
+protected:
+ Item_in_optimizer* owner;
+public:
+ Item_ref_in_optimizer(Item_in_optimizer* master,
+ char *table_name_par,char *field_name_par);
+ double val();
+ longlong val_int();
+ String* val_str(String* s);
+ bool fix_fields(THD *, struct st_table_list *, Item ** ref)
+ {
+ fixed= 1;
+ return 0;
+ }
+};
/*
The following class is used to optimize comparing of date columns
@@ -555,6 +642,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)
@@ -563,10 +651,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()
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index dd8d1aeff02..a30faae9a01 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -90,7 +90,7 @@ static bool convert_constant_item(Field *field, Item **item)
void Item_bool_func2::fix_length_and_dec()
{
- max_length=1; // Function returns 0 or 1
+ max_length= 1; // Function returns 0 or 1
/*
As some compare functions are generated after sql_yacc,
@@ -144,7 +144,14 @@ int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type)
}
if ((comparators= (Arg_comparator *) sql_alloc(sizeof(Arg_comparator)*n)))
for (uint i=0; i < n; i++)
+ {
+ if ((*a)->el(i)->cols() != (*b)->el(i)->cols())
+ {
+ my_error(ER_CARDINALITY_COL, MYF(0), (*a)->el(i)->cols());
+ return 1;
+ }
comparators[i].set_cmp_func(owner, (*a)->addr(i), (*b)->addr(i));
+ }
else
{
my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
@@ -263,6 +270,61 @@ int Arg_comparator::compare_e_row()
return 1;
}
+longlong Item_in_optimizer::val_int()
+{
+ int_cache_ok= 1;
+ flt_cache_ok= 0;
+ str_cache_ok= 0;
+ int_cache= args[0]->val_int_result();
+ if (args[0]->null_value)
+ {
+ null_value= 1;
+ return 0;
+ }
+ longlong tmp= args[1]->val_int_result();
+ null_value= args[1]->null_value;
+ return tmp;
+}
+
+longlong Item_in_optimizer::get_cache_int()
+{
+ if (!int_cache_ok)
+ {
+ int_cache_ok= 1;
+ flt_cache_ok= 0;
+ str_cache_ok= 0;
+ int_cache= args[0]->val_int_result();
+ null_value= args[0]->null_value;
+ }
+ return int_cache;
+}
+
+double Item_in_optimizer::get_cache()
+{
+ if (!flt_cache_ok)
+ {
+ flt_cache_ok= 1;
+ int_cache_ok= 0;
+ str_cache_ok= 0;
+ flt_cache= args[0]->val_result();
+ null_value= args[0]->null_value;
+ }
+ return flt_cache;
+}
+
+String *Item_in_optimizer::get_cache_str(String *s)
+{
+ if (!str_cache_ok)
+ {
+ str_cache_ok= 1;
+ int_cache_ok= 0;
+ flt_cache_ok= 0;
+ str_value.set(buffer, sizeof(buffer), s->charset());
+ str_cache= args[0]->str_result(&str_value);
+ null_value= args[0]->null_value;
+ }
+ return str_cache;
+}
longlong Item_func_eq::val_int()
{
@@ -356,7 +418,8 @@ void Item_func_interval::fix_length_and_dec()
intervals[i]=args[i]->val();
}
}
- maybe_null=0; max_length=2;
+ maybe_null= 0;
+ max_length= 2;
used_tables_cache|=item->used_tables();
}
@@ -415,7 +478,7 @@ bool Item_func_interval::check_loop(uint id)
void Item_func_between::fix_length_and_dec()
{
- max_length=1;
+ max_length= 1;
/*
As some compare functions are generated after sql_yacc,
@@ -968,8 +1031,8 @@ double Item_func_coalesce::val()
void Item_func_coalesce::fix_length_and_dec()
{
- max_length=0;
- decimals=0;
+ max_length= 0;
+ decimals= 0;
cached_result_type = args[0]->result_type();
for (uint i=0 ; i < arg_count ; i++)
{
@@ -992,6 +1055,11 @@ static int cmp_double(double *a,double *b)
return *a < *b ? -1 : *a == *b ? 0 : 1;
}
+static int cmp_row(cmp_item_row* a, cmp_item_row* b)
+{
+ return a->compare(b);
+}
+
int in_vector::find(Item *item)
{
byte *result=get_value(item);
@@ -1014,7 +1082,6 @@ int in_vector::find(Item *item)
return (int) ((*compare)(base+start*size,result) == 0);
}
-
in_string::in_string(uint elements,qsort_cmp cmp_func)
:in_vector(elements,sizeof(String),cmp_func),tmp(buff,sizeof(buff),default_charset_info)
{}
@@ -1041,6 +1108,29 @@ byte *in_string::get_value(Item *item)
return (byte*) item->val_str(&tmp);
}
+in_row::in_row(uint elements, Item * item)
+{
+ DBUG_ENTER("in_row::in_row");
+ base= (char*) new cmp_item_row[elements];
+ size= sizeof(cmp_item_row);
+ compare= (qsort_cmp) cmp_row;
+ tmp.store_value(item);
+ DBUG_VOID_RETURN;
+}
+
+byte *in_row::get_value(Item *item)
+{
+ tmp.store_value(item);
+ return (byte *)&tmp;
+}
+
+void in_row::set(uint pos, Item *item)
+{
+ DBUG_ENTER("in_row::set");
+ DBUG_PRINT("enter", ("pos %u item 0x%lx", pos, (ulong) item));
+ ((cmp_item_row*) base)[pos].store_value_by_template(&tmp, item);
+ DBUG_VOID_RETURN;
+}
in_longlong::in_longlong(uint elements)
:in_vector(elements,sizeof(longlong),(qsort_cmp) cmp_longlong)
@@ -1053,13 +1143,12 @@ void in_longlong::set(uint pos,Item *item)
byte *in_longlong::get_value(Item *item)
{
- tmp=item->val_int();
+ tmp= item->val_int();
if (item->null_value)
- return 0; /* purecov: inspected */
+ return 0;
return (byte*) &tmp;
}
-
in_double::in_double(uint elements)
:in_vector(elements,sizeof(double),(qsort_cmp) cmp_double)
{}
@@ -1071,21 +1160,173 @@ void in_double::set(uint pos,Item *item)
byte *in_double::get_value(Item *item)
{
- tmp=item->val();
+ tmp= item->val();
if (item->null_value)
return 0; /* purecov: inspected */
return (byte*) &tmp;
}
+cmp_item* cmp_item::get_comparator (Item *item)
+{
+ switch (item->result_type()) {
+ case STRING_RESULT:
+ if (item->binary())
+ return new cmp_item_binary_string;
+ else
+ return new cmp_item_sort_string;
+ break;
+ case INT_RESULT:
+ return new cmp_item_int;
+ break;
+ case REAL_RESULT:
+ return new cmp_item_real;
+ break;
+ case ROW_RESULT:
+ return new cmp_item_row;
+ break;
+ }
+ return 0; // to satisfy compiler :)
+}
+
+cmp_item* cmp_item_sort_string::make_same()
+{
+ return new cmp_item_sort_string_in_static();
+}
+
+cmp_item* cmp_item_binary_string::make_same()
+{
+ return new cmp_item_binary_string_in_static();
+}
+
+cmp_item* cmp_item_int::make_same()
+{
+ return new cmp_item_int();
+}
+
+cmp_item* cmp_item_real::make_same()
+{
+ return new cmp_item_real();
+}
+
+cmp_item* cmp_item_row::make_same()
+{
+ return new cmp_item_row();
+}
+
+void cmp_item_row::store_value(Item *item)
+{
+ THD *thd= current_thd;
+ n= item->cols();
+ if ((comparators= (cmp_item **) thd->alloc(sizeof(cmp_item *)*n)))
+ {
+ item->null_value= 0;
+ for (uint i=0; i < n; i++)
+ if ((comparators[i]= cmp_item::get_comparator(item->el(i))))
+ {
+ comparators[i]->store_value(item->el(i));
+ item->null_value|= item->el(i)->null_value;
+ }
+ else
+ {
+ my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
+ thd->fatal_error= 1;
+ return;
+ }
+ }
+ else
+ {
+ my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
+ thd->fatal_error= 1;
+ return;
+ }
+}
+
+void cmp_item_row::store_value_by_template(cmp_item *t, Item *item)
+{
+ cmp_item_row *tmpl= (cmp_item_row*) t;
+ if (tmpl->n != item->cols())
+ {
+ my_error(ER_CARDINALITY_COL, MYF(0), tmpl->n);
+ return;
+ }
+ n= tmpl->n;
+ if ((comparators= (cmp_item **) sql_alloc(sizeof(cmp_item *)*n)))
+ {
+ item->null_value= 0;
+ for (uint i=0; i < n; i++)
+ if ((comparators[i]= tmpl->comparators[i]->make_same()))
+ {
+ comparators[i]->store_value_by_template(tmpl->comparators[i],
+ item->el(i));
+ item->null_value|= item->el(i)->null_value;
+ }
+ else
+ {
+ my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
+ current_thd->fatal_error= 1;
+ return;
+ }
+ }
+ else
+ {
+ my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
+ current_thd->fatal_error= 1;
+ return;
+ }
+}
+
+int cmp_item_row::cmp(Item *arg)
+{
+ arg->null_value= 0;
+ if (arg->cols() != n)
+ {
+ my_error(ER_CARDINALITY_COL, MYF(0), n);
+ return 1;
+ }
+ bool was_null= 0;
+ for (uint i=0; i < n; i++)
+ if (comparators[i]->cmp(arg->el(i)))
+ {
+ if (!arg->el(i)->null_value)
+ return 1;
+ was_null= 1;
+ }
+ return (arg->null_value= was_null);
+}
+
+int cmp_item_row::compare(cmp_item *c)
+{
+ int res;
+ cmp_item_row *cmp= (cmp_item_row *) c;
+ for (uint i=0; i < n; i++)
+ if ((res= comparators[i]->compare(cmp->comparators[i])))
+ return res;
+ return 0;
+}
+
+bool Item_func_in::nulls_in_row()
+{
+ Item **arg,**arg_end;
+ for (arg= args, arg_end= args+arg_count; arg != arg_end ; arg++)
+ {
+ if ((*arg)->null_inside())
+ return 1;
+ }
+ return 0;
+}
void Item_func_in::fix_length_and_dec()
{
- if (const_item())
+ /*
+ Row item with NULLs inside can return NULL or FALSE =>
+ they can't be processed as static
+ */
+ if (const_item() && !nulls_in_row())
{
switch (item->result_type()) {
case STRING_RESULT:
if (item->binary())
- array=new in_string(arg_count,(qsort_cmp) stringcmp); /* purecov: inspected */
+ array=new in_string(arg_count,(qsort_cmp) stringcmp);
else
array=new in_string(arg_count,(qsort_cmp) sortcmp);
break;
@@ -1096,8 +1337,7 @@ void Item_func_in::fix_length_and_dec()
array= new in_double(arg_count);
break;
case ROW_RESULT:
- // This case should never be choosen
- DBUG_ASSERT(0);
+ array= new in_row(arg_count, item);
break;
}
uint j=0;
@@ -1106,33 +1346,18 @@ void Item_func_in::fix_length_and_dec()
array->set(j,args[i]);
if (!args[i]->null_value) // Skip NULL values
j++;
+ else
+ have_null= 1;
}
if ((array->used_count=j))
array->sort();
}
else
{
- switch (item->result_type()) {
- case STRING_RESULT:
- if (item->binary())
- in_item= new cmp_item_binary_string;
- else
- in_item= new cmp_item_sort_string;
- break;
- case INT_RESULT:
- in_item= new cmp_item_int;
- break;
- case REAL_RESULT:
- in_item= new cmp_item_real;
- break;
- case ROW_RESULT:
- // This case should never be choosen
- DBUG_ASSERT(0);
- break;
- }
+ in_item= cmp_item:: get_comparator(item);
}
maybe_null= item->maybe_null;
- max_length=2;
+ max_length= 1;
used_tables_cache|=item->used_tables();
const_item_cache&=item->const_item();
}
@@ -1152,17 +1377,20 @@ longlong Item_func_in::val_int()
if (array)
{
int tmp=array->find(item);
- null_value=item->null_value;
+ null_value=item->null_value || (!tmp && have_null);
return tmp;
}
in_item->store_value(item);
if ((null_value=item->null_value))
return 0;
+ have_null= 0;
for (uint i=0 ; i < arg_count ; i++)
{
if (!in_item->cmp(args[i]) && !args[i]->null_value)
return 1; // Would maybe be nice with i ?
+ have_null|= args[i]->null_value;
}
+ null_value= have_null;
return 0;
}
@@ -1452,7 +1680,8 @@ longlong Item_func_isnotnull::val_int()
void Item_func_like::fix_length_and_dec()
{
- decimals=0; max_length=1;
+ decimals= 0;
+ max_length= 1;
// cmp_type=STRING_RESULT; // For quick select
}
@@ -1559,7 +1788,8 @@ Item_func_regex::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
args[1]->fix_fields(thd,tables, args + 1))
return 1; /* purecov: inspected */
with_sum_func=args[0]->with_sum_func || args[1]->with_sum_func;
- max_length=1; decimals=0;
+ max_length= 1;
+ decimals= 0;
if (args[0]->binary() || args[1]->binary())
set_charset(my_charset_bin);
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index b4f4872bd95..994e51ef89f 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -17,6 +17,8 @@
/* compare and test functions */
+#include "assert.h"
+
#ifdef __GNUC__
#pragma interface /* gcc class implementation */
#endif
@@ -38,16 +40,12 @@ public:
Arg_comparator() {};
Arg_comparator(Item **a1, Item **a2): a(a1), b(a2) {};
- inline void seta(Item **item) { a= item; }
- inline void setb(Item **item) { b= item; }
-
int set_compare_func(Item_bool_func2 *owner, Item_result type);
inline int set_compare_func(Item_bool_func2 *owner)
{
return set_compare_func(owner, item_cmp_type((*a)->result_type(),
(*b)->result_type()));
}
-
inline int set_cmp_func(Item_bool_func2 *owner,
Item **a1, Item **a2,
Item_result type)
@@ -87,6 +85,27 @@ public:
void fix_length_and_dec() { decimals=0; max_length=1; }
};
+class Item_in_optimizer: public Item_bool_func
+{
+protected:
+ char buffer[80];
+ longlong int_cache;
+ double flt_cache;
+ String *str_cache;
+ bool int_cache_ok, flt_cache_ok, str_cache_ok;
+public:
+ Item_in_optimizer(Item *a,Item *b):
+ Item_bool_func(a,b), int_cache_ok(0), flt_cache_ok(0), str_cache_ok(0) {}
+ bool is_null() { return test(args[0]->is_null() || args[1]->is_null()); }
+ longlong val_int();
+
+ double get_cache();
+ longlong get_cache_int();
+ String *get_cache_str(String *s);
+
+ friend class Item_ref_in_optimizer;
+};
+
class Item_bool_func2 :public Item_int_func
{ /* Bool with 2 string args */
protected:
@@ -358,6 +377,7 @@ class in_vector :public Sql_alloc
uint count;
public:
uint used_count;
+ in_vector() {}
in_vector(uint elements,uint element_length,qsort_cmp cmp_func)
:base((char*) sql_calloc(elements*element_length)),
size(element_length), compare(cmp_func), count(elements),
@@ -372,7 +392,6 @@ public:
int find(Item *item);
};
-
class in_string :public in_vector
{
char buff[80];
@@ -384,7 +403,6 @@ public:
byte *get_value(Item *item);
};
-
class in_longlong :public in_vector
{
longlong tmp;
@@ -394,7 +412,6 @@ public:
byte *get_value(Item *item);
};
-
class in_double :public in_vector
{
double tmp;
@@ -404,7 +421,6 @@ public:
byte *get_value(Item *item);
};
-
/*
** Classes for easy comparing of non const items
*/
@@ -414,88 +430,201 @@ class cmp_item :public Sql_alloc
public:
cmp_item() {}
virtual ~cmp_item() {}
- virtual void store_value(Item *item)=0;
- virtual int cmp(Item *item)=0;
+ virtual void store_value(Item *item)= 0;
+ virtual int cmp(Item *item)= 0;
+ // for optimized IN with row
+ virtual int compare(cmp_item *item)= 0;
+ static cmp_item* get_comparator(Item *);
+ virtual cmp_item *make_same()= 0;
+ virtual void store_value_by_template(cmp_item *tmpl, Item *item)
+ {
+ store_value(item);
+ }
};
+typedef int (*str_cmp_func_pointer)(const String *, const String *);
+class cmp_item_string :public cmp_item
+{
+protected:
+ str_cmp_func_pointer str_cmp_func;
+ String *value_res;
+public:
+ cmp_item_string (str_cmp_func_pointer cmp): str_cmp_func(cmp) {}
+ friend class cmp_item_sort_string;
+ friend class cmp_item_binary_string;
+ friend class cmp_item_sort_string_in_static;
+ friend class cmp_item_binary_string_in_static;
+};
-class cmp_item_sort_string :public cmp_item {
- protected:
+class cmp_item_sort_string :public cmp_item_string
+{
+protected:
char value_buff[80];
- String value,*value_res;
-public:
- cmp_item_sort_string() :value(value_buff,sizeof(value_buff),default_charset_info) {}
+ String value;
+public:
+ cmp_item_sort_string(str_cmp_func_pointer cmp):
+ cmp_item_string(cmp),
+ value(value_buff, sizeof(value_buff), default_charset_info) {}
+ cmp_item_sort_string():
+ cmp_item_string(&sortcmp),
+ value(value_buff, sizeof(value_buff), default_charset_info) {}
void store_value(Item *item)
- {
- value_res=item->val_str(&value);
- }
+ {
+ value_res= item->val_str(&value);
+ }
int cmp(Item *arg)
- {
- char buff[80];
- String tmp(buff,sizeof(buff),default_charset_info),*res;
- if (!(res=arg->val_str(&tmp)))
- return 1; /* Can't be right */
- return sortcmp(value_res,res);
- }
+ {
+ char buff[80];
+ String tmp(buff, sizeof(buff), default_charset_info), *res;
+ if (!(res= arg->val_str(&tmp)))
+ return 1; /* Can't be right */
+ return (*str_cmp_func)(value_res, res);
+ }
+ int compare(cmp_item *c)
+ {
+ cmp_item_string *cmp= (cmp_item_string *)c;
+ return (*str_cmp_func)(value_res, cmp->value_res);
+ }
+ cmp_item *make_same();
};
class cmp_item_binary_string :public cmp_item_sort_string {
public:
- cmp_item_binary_string() {}
- int cmp(Item *arg)
- {
- char buff[80];
- String tmp(buff,sizeof(buff),default_charset_info),*res;
- if (!(res=arg->val_str(&tmp)))
- return 1; /* Can't be right */
- return stringcmp(value_res,res);
- }
+ cmp_item_binary_string(): cmp_item_sort_string(&stringcmp) {}
+ cmp_item *make_same();
};
-
class cmp_item_int :public cmp_item
{
longlong value;
public:
void store_value(Item *item)
- {
- value=item->val_int();
- }
+ {
+ value= item->val_int();
+ }
int cmp(Item *arg)
- {
- return value != arg->val_int();
- }
+ {
+ return value != arg->val_int();
+ }
+ int compare(cmp_item *c)
+ {
+ cmp_item_int *cmp= (cmp_item_int *)c;
+ return (value < cmp->value) ? -1 : ((value == cmp->value) ? 0 : 1);
+ }
+ cmp_item *make_same();
};
-
class cmp_item_real :public cmp_item
{
double value;
public:
void store_value(Item *item)
- {
- value= item->val();
- }
+ {
+ value= item->val();
+ }
int cmp(Item *arg)
- {
- return value != arg->val();
- }
+ {
+ return value != arg->val();
+ }
+ int compare(cmp_item *c)
+ {
+ cmp_item_real *cmp= (cmp_item_real *)c;
+ return (value < cmp->value)? -1 : ((value == cmp->value) ? 0 : 1);
+ }
+ cmp_item *make_same();
+};
+
+class cmp_item_row :public cmp_item
+{
+ cmp_item **comparators;
+ uint n;
+public:
+ cmp_item_row(): comparators(0), n(0) {}
+ ~cmp_item_row()
+ {
+ if(comparators)
+ for(uint i= 0; i < n; i++)
+ if (comparators[i])
+ delete comparators[i];
+ }
+ void store_value(Item *item);
+ int cmp(Item *arg);
+ int compare(cmp_item *arg);
+ cmp_item *make_same();
+ void store_value_by_template(cmp_item *tmpl, Item *);
+};
+
+
+class in_row :public in_vector
+{
+ cmp_item_row tmp;
+public:
+ in_row(uint elements, Item *);
+ void set(uint pos,Item *item);
+ byte *get_value(Item *item);
};
+/*
+ cmp_item for optimized IN with row (right part string, which never
+ be changed)
+*/
+
+class cmp_item_sort_string_in_static :public cmp_item_string
+{
+ protected:
+ String value;
+public:
+ cmp_item_sort_string_in_static(str_cmp_func_pointer cmp):
+ cmp_item_string(cmp) {}
+ cmp_item_sort_string_in_static(): cmp_item_string(&sortcmp) {}
+ void store_value(Item *item)
+ {
+ value_res= item->val_str(&value);
+ }
+ int cmp(Item *item)
+ {
+ // Should never be called
+ DBUG_ASSERT(0);
+ return 1;
+ }
+ int compare(cmp_item *c)
+ {
+ cmp_item_string *cmp= (cmp_item_string *)c;
+ return (*str_cmp_func)(value_res, cmp->value_res);
+ }
+ cmp_item * make_same()
+ {
+ return new cmp_item_sort_string_in_static();
+ }
+};
+
+class cmp_item_binary_string_in_static :public cmp_item_sort_string_in_static {
+public:
+ cmp_item_binary_string_in_static():
+ cmp_item_sort_string_in_static(&stringcmp) {}
+ cmp_item * make_same()
+ {
+ return new cmp_item_binary_string_in_static();
+ }
+};
class Item_func_in :public Item_int_func
{
Item *item;
in_vector *array;
cmp_item *in_item;
+ bool have_null;
public:
Item_func_in(Item *a,List<Item> &list)
- :Item_int_func(list),item(a),array(0),in_item(0) {}
+ :Item_int_func(list), item(a), array(0), in_item(0), have_null(0)
+ {
+ allowed_arg_cols= item->cols();
+ }
longlong val_int();
bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref)
{
- bool res=(item->check_cols(1) ||
- item->fix_fields(thd, tlist, &item) ||
+ // We do not check item->cols(), because allowed_arg_cols assigned from it
+ bool res=(item->fix_fields(thd, tlist, &item) ||
Item_func::fix_fields(thd, tlist, ref));
with_sum_func= with_sum_func || item->with_sum_func;
return res;
@@ -517,10 +646,9 @@ class Item_func_in :public Item_int_func
DBUG_RETURN(1);
DBUG_RETURN(item->check_loop(id));
}
+ bool nulls_in_row();
};
-
-
/* Functions used by where clause */
class Item_func_isnull :public Item_bool_func
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 0f4239ca560..bcc04aac6a9 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -1947,8 +1947,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;
diff --git a/sql/item_func.h b/sql/item_func.h
index 98e56af368c..36d6dcbe002 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -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
diff --git a/sql/item_row.cc b/sql/item_row.cc
index 464a8fd0ec5..85a81a50256 100644
--- a/sql/item_row.cc
+++ b/sql/item_row.cc
@@ -18,8 +18,10 @@
#include "assert.h"
Item_row::Item_row(List<Item> &arg):
- Item(), array_holder(1)
+ Item(), array_holder(1), used_tables_cache(0), const_item_cache(1)
{
+
+ //TODO: think placing 2-3 component items in item (as it done for function)
if ((arg_count= arg.elements))
items= (Item**) sql_alloc(sizeof(Item*)*arg_count);
else
@@ -45,16 +47,31 @@ void Item_row::illegal_method_call(const char *method)
bool Item_row::fix_fields(THD *thd, TABLE_LIST *tabl, Item **ref)
{
- tables= 0;
+ null_value= 0;
+ maybe_null= 0;
for (uint i= 0; i < arg_count; i++)
{
if (items[i]->fix_fields(thd, tabl, items+i))
return 1;
- tables |= items[i]->used_tables();
+ used_tables_cache |= items[i]->used_tables();
+ const_item_cache&= items[i]->const_item();
+ maybe_null|= items[i]->maybe_null;
}
return 0;
}
+void Item_row::update_used_tables()
+{
+ used_tables_cache= 0;
+ const_item_cache= 1;
+ for (uint i= 0; i < arg_count; i++)
+ {
+ items[i]->update_used_tables();
+ used_tables_cache|= items[i]->used_tables();
+ const_item_cache&= items[i]->const_item();
+ }
+}
+
bool Item_row::check_cols(uint c)
{
if (c != arg_count)
@@ -64,3 +81,22 @@ bool Item_row::check_cols(uint c)
}
return 0;
}
+
+bool Item_row::null_inside()
+{
+ for (uint i= 0; i < arg_count; i++)
+ {
+ if (items[i]->cols() > 1)
+ {
+ if (items[i]->null_inside())
+ return 1;
+ }
+ else
+ {
+ items[i]->val_int();
+ if (items[i]->null_value)
+ return 1;
+ }
+ }
+ return 0;
+}
diff --git a/sql/item_row.h b/sql/item_row.h
index 5580250b4fb..4767d19d08f 100644
--- a/sql/item_row.h
+++ b/sql/item_row.h
@@ -17,13 +17,17 @@
class Item_row: public Item
{
bool array_holder;
- table_map tables;
+ table_map used_tables_cache;
+ bool const_item_cache;
uint arg_count;
Item **items;
public:
Item_row(List<Item> &);
Item_row(Item_row *item):
- Item(), array_holder(0), tables(item->tables), arg_count(item->arg_count),
+ Item(), array_holder(0),
+ used_tables_cache(item->used_tables_cache),
+ const_item_cache(item->const_item_cache),
+ arg_count(item->arg_count),
items(item->items)
{}
@@ -56,11 +60,14 @@ public:
return 0;
};
bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref);
- table_map used_tables() const { return tables; };
+ table_map used_tables() const { return used_tables_cache; };
+ bool const_item() const { return const_item_cache; };
enum Item_result result_type() const { return ROW_RESULT; }
+ void update_used_tables();
- virtual uint cols() { return arg_count; }
- virtual Item* el(uint i) { return items[i]; }
- virtual Item** addr(uint i) { return items + i; }
- virtual bool check_cols(uint c);
+ uint cols() { return arg_count; }
+ Item* el(uint i) { return items[i]; }
+ Item** addr(uint i) { return items + i; }
+ bool check_cols(uint c);
+ bool null_inside();
};
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index e087664e060..a8bbc433b7a 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -33,9 +33,10 @@ SUBSELECT TODO:
#include "sql_select.h"
Item_subselect::Item_subselect():
- Item_result_field(), engine_owner(1), value_assigned(0), substitution(0)
+ Item_result_field(), engine_owner(1), value_assigned(0), substitution(0),
+ have_to_be_excluded(0)
{
- assign_null();
+ reset();
/*
item value is NULL if select_subselect not changed this value
(i.e. some rows will be found returned)
@@ -73,28 +74,16 @@ 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)
{
(*ref)= substitution;
substitution->name= name;
- engine->exclude();
- return substitution->fix_fields(thd, tables, ref);
+ if (have_to_be_excluded)
+ engine->exclude();
+ substitution= 0;
+ return (*ref)->fix_fields(thd, tables, ref);
}
char const *save_where= thd->where;
@@ -159,7 +148,7 @@ double Item_singleval_subselect::val ()
{
if (engine->exec())
{
- assign_null();
+ reset();
return 0;
}
return real_value;
@@ -169,7 +158,7 @@ longlong Item_singleval_subselect::val_int ()
{
if (engine->exec())
{
- assign_null();
+ reset();
return 0;
}
return int_value;
@@ -179,7 +168,7 @@ String *Item_singleval_subselect::val_str (String *str)
{
if (engine->exec() || null_value)
{
- assign_null();
+ reset();
return 0;
}
return &string_value;
@@ -208,9 +197,8 @@ Item_in_subselect::Item_in_subselect(THD *thd, Item * left_exp,
left_expr= left_exp;
init(thd, select_lex, new select_exists_subselect(this));
max_columns= UINT_MAX;
- null_value= 0; //can't be NULL
- maybe_null= 0; //can't be NULL
- value= 0;
+ maybe_null= 1;
+ reset();
// We need only 1 row to determinate existence
select_lex->master_unit()->global_parameters->select_limit= 1;
DBUG_VOID_RETURN;
@@ -226,9 +214,7 @@ Item_allany_subselect::Item_allany_subselect(THD *thd, Item * left_exp,
func= f;
init(thd, select_lex, new select_exists_subselect(this));
max_columns= UINT_MAX;
- null_value= 0; //can't be NULL
- maybe_null= 0; //can't be NULL
- value= 0;
+ reset();
// We need only 1 row to determinate existence
select_lex->master_unit()->global_parameters->select_limit= 1;
DBUG_VOID_RETURN;
@@ -237,14 +223,15 @@ Item_allany_subselect::Item_allany_subselect(THD *thd, Item * left_exp,
void Item_exists_subselect::fix_length_and_dec()
{
- max_length= 1;
+ decimals=0;
+ max_length= 1;
}
double Item_exists_subselect::val ()
{
if (engine->exec())
{
- assign_null();
+ reset();
return 0;
}
return (double) value;
@@ -254,7 +241,7 @@ longlong Item_exists_subselect::val_int ()
{
if (engine->exec())
{
- assign_null();
+ reset();
return 0;
}
return value;
@@ -264,7 +251,50 @@ String *Item_exists_subselect::val_str(String *str)
{
if (engine->exec())
{
- assign_null();
+ reset();
+ return 0;
+ }
+ str->set(value,thd_charset());
+ return str;
+}
+
+double Item_in_subselect::val ()
+{
+ if (engine->exec())
+ {
+ reset();
+ null_value= 1;
+ return 0;
+ }
+ if (was_null && !value)
+ null_value= 1;
+ return (double) value;
+}
+
+longlong Item_in_subselect::val_int ()
+{
+ if (engine->exec())
+ {
+ reset();
+ null_value= 1;
+ return 0;
+ }
+ if (was_null && !value)
+ null_value= 1;
+ return value;
+}
+
+String *Item_in_subselect::val_str(String *str)
+{
+ if (engine->exec())
+ {
+ reset();
+ null_value= 1;
+ return 0;
+ }
+ if (was_null && !value)
+ {
+ null_value= 1;
return 0;
}
str->set(value,thd_charset());
@@ -288,8 +318,23 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex,
compare_func_creator func)
{
DBUG_ENTER("Item_in_subselect::single_value_transformer");
+ Item_in_optimizer *optimizer;
+ substitution= optimizer= new Item_in_optimizer(left_expr, this);
+ if (!optimizer)
+ {
+ current_thd->fatal_error= 1;
+ DBUG_VOID_RETURN;
+ }
+ /*
+ As far as Item_ref_in_optimizer do not substitude itself on fix_fields
+ we can use same item for all selects.
+ */
+ Item *expr= new Item_ref_in_optimizer(optimizer, (char *)"<no matter>",
+ (char*)"<left expr>");
+ select_lex->master_unit()->dependent= 1;
for (SELECT_LEX * sl= select_lex; sl; sl= sl->next_select())
{
+ select_lex->dependent= 1;
Item *item;
if (sl->item_list.elements > 1)
{
@@ -299,14 +344,14 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex,
else
item= (Item*) sl->item_list.pop();
- Item *expr= new Item_outer_select_context_saver(left_expr);
-
if (sl->having || sl->with_sum_func || sl->group_list.first ||
sl->order_list.first)
{
sl->item_list.push_back(item);
- item= (*func)(expr, new Item_ref(sl->item_list.head_ref(),
- 0, (char*)"<result>"));
+ item= (*func)(expr, new Item_ref_null_helper(this,
+ sl->item_list.head_ref(),
+ (char *)"<no matter>",
+ (char*)"<result>"));
if (sl->having || sl->with_sum_func || sl->group_list.first)
if (sl->having)
sl->having= new Item_cond_and(sl->having, item);
@@ -324,7 +369,9 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex,
sl->item_list.push_back(new Item_int(1));
if (sl->table_list.elements)
{
- item= (*func)(expr, new Item_asterisk_remover(item));
+ item= (*func)(expr, new Item_asterisk_remover(this, item,
+ (char *)"<no matter>",
+ (char*)"<result>"));
if (sl->where)
sl->where= new Item_cond_and(sl->where, item);
else
@@ -340,14 +387,21 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex,
}
if (select_lex->next_select())
{
- // it is in union => we should perform it
- sl->having= (*func)(expr, item);
+ /*
+ It is in union => we should perform it.
+ Item_asterisk_remover used only as wrapper to receine NULL value
+ */
+ sl->having= (*func)(expr,
+ new Item_asterisk_remover(this, item,
+ (char *)"<no matter>",
+ (char*)"<result>"));
}
else
{
// it is single select without tables => possible optimization
item= (*func)(left_expr, item);
substitution= item;
+ have_to_be_excluded= 1;
THD *thd= current_thd;
if (thd->lex.describe)
{
@@ -489,7 +543,7 @@ int subselect_single_select_engine::exec()
join->thd->where= save_where;
DBUG_RETURN(1);
}
- item->assign_null();
+ item->reset();
item->assigned((executed= 0));
}
if (!executed)
diff --git a/sql/item_subselect.h b/sql/item_subselect.h
index d323dab51f1..0e6f939803d 100644
--- a/sql/item_subselect.h
+++ b/sql/item_subselect.h
@@ -42,6 +42,8 @@ protected:
subselect_engine *engine;
/* allowed number of columns (1 for single value subqueries) */
uint max_columns;
+ /* work with 'substitution' */
+ bool have_to_be_excluded;
public:
Item_subselect();
@@ -65,7 +67,7 @@ public:
select_subselect *result);
~Item_subselect();
- virtual void assign_null()
+ virtual void reset()
{
null_value= 1;
}
@@ -73,8 +75,11 @@ public:
bool assigned() { return value_assigned; }
void assigned(bool a) { value_assigned= a; }
enum Type type() const;
- bool is_null() { return null_value; }
- void make_field (Send_field *);
+ bool is_null()
+ {
+ val_int();
+ return null_value;
+ }
bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref);
virtual void fix_length_and_dec();
table_map used_tables() const;
@@ -110,7 +115,7 @@ public:
decimals= item->decimals;
res_type= item->res_type;
}
- virtual void assign_null()
+ virtual void reset()
{
null_value= 1;
int_value= 0;
@@ -144,7 +149,7 @@ public:
}
Item_exists_subselect(): Item_subselect() {}
- virtual void assign_null()
+ virtual void reset()
{
value= 0;
}
@@ -155,6 +160,7 @@ public:
double val();
String *val_str(String*);
void fix_length_and_dec();
+
friend class select_exists_subselect;
};
@@ -164,14 +170,26 @@ class Item_in_subselect :public Item_exists_subselect
{
protected:
Item * left_expr;
-
+ bool was_null;
public:
Item_in_subselect(THD *thd, Item * left_expr, st_select_lex *select_lex);
Item_in_subselect(Item_in_subselect *item);
Item_in_subselect(): Item_exists_subselect() {}
+ void reset()
+ {
+ value= 0;
+ null_value= 0;
+ was_null= 0;
+ }
virtual void select_transformer(st_select_lex *select_lex);
void single_value_transformer(st_select_lex *select_lex,
Item *left_expr, compare_func_creator func);
+ longlong val_int();
+ double val();
+ String *val_str(String*);
+
+ friend class Item_asterisk_remover;
+ friend class Item_ref_null_helper;
};
/* ALL/ANY/SOME subselect */
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 4a2d716c953..f54ab87b81d 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -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;
}
@@ -253,12 +250,24 @@ double Item_sum_avg::val()
** Standard deviation
*/
-void Item_sum_std::reset()
+double Item_sum_std::val()
{
- sum=sum_sqr=0.0; count=0; (void) Item_sum_std::add();
+ double tmp= Item_sum_variance::val();
+ return tmp <= 0.0 ? 0.0 : sqrt(tmp);
}
-bool Item_sum_std::add()
+/*
+** variance
+*/
+
+void Item_sum_variance::reset()
+{
+ sum=sum_sqr=0.0;
+ count=0;
+ (void) Item_sum_variance::add();
+}
+
+bool Item_sum_variance::add()
{
double nr=args[0]->val();
if (!args[0]->null_value)
@@ -270,7 +279,7 @@ bool Item_sum_std::add()
return 0;
}
-double Item_sum_std::val()
+double Item_sum_variance::val()
{
if (!count)
{
@@ -281,11 +290,10 @@ double Item_sum_std::val()
/* Avoid problems when the precision isn't good enough */
double tmp=ulonglong2double(count);
double tmp2=(sum_sqr - sum*sum/tmp)/tmp;
- return tmp2 <= 0.0 ? 0.0 : sqrt(tmp2);
+ return tmp2 <= 0.0 ? 0.0 : tmp2;
}
-
-void Item_sum_std::reset_field()
+void Item_sum_variance::reset_field()
{
double nr=args[0]->val();
char *res=result_field->ptr;
@@ -302,7 +310,7 @@ void Item_sum_std::reset_field()
}
}
-void Item_sum_std::update_field(int offset)
+void Item_sum_variance::update_field(int offset)
{
double nr,old_nr,old_sqr;
longlong field_count;
@@ -836,6 +844,17 @@ String *Item_avg_field::val_str(String *str)
}
Item_std_field::Item_std_field(Item_sum_std *item)
+ : Item_variance_field(item)
+{
+}
+
+double Item_std_field::val()
+{
+ double tmp= Item_variance_field::val();
+ return tmp <= 0.0 ? 0.0 : sqrt(tmp);
+}
+
+Item_variance_field::Item_variance_field(Item_sum_variance *item)
{
name=item->name;
decimals=item->decimals;
@@ -844,7 +863,7 @@ Item_std_field::Item_std_field(Item_sum_std *item)
maybe_null=1;
}
-double Item_std_field::val()
+double Item_variance_field::val()
{
double sum,sum_sqr;
longlong count;
@@ -860,10 +879,10 @@ double Item_std_field::val()
null_value=0;
double tmp= (double) count;
double tmp2=(sum_sqr - sum*sum/tmp)/tmp;
- return tmp2 <= 0.0 ? 0.0 : sqrt(tmp2);
+ return tmp2 <= 0.0 ? 0.0 : tmp2;
}
-String *Item_std_field::val_str(String *str)
+String *Item_variance_field::val_str(String *str)
{
double nr=val();
if (null_value)
diff --git a/sql/item_sum.h b/sql/item_sum.h
index 23b8482d41a..50375fbf77c 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -27,7 +27,7 @@ class Item_sum :public Item_result_field
{
public:
enum Sumfunctype {COUNT_FUNC,COUNT_DISTINCT_FUNC,SUM_FUNC,AVG_FUNC,MIN_FUNC,
- MAX_FUNC, UNIQUE_USERS_FUNC,STD_FUNC,SUM_BIT_FUNC,
+ MAX_FUNC, UNIQUE_USERS_FUNC,STD_FUNC,VARIANCE_FUNC,SUM_BIT_FUNC,
UDF_SUM_FUNC };
Item **args,*tmp_args[2];
@@ -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() {}
};
@@ -235,42 +235,79 @@ class Item_sum_avg :public Item_sum_num
const char *func_name() const { return "avg"; }
};
-class Item_sum_std;
+class Item_sum_variance;
-class Item_std_field :public Item_result_field
+class Item_variance_field :public Item_result_field
{
public:
Field *field;
- Item_std_field(Item_sum_std *item);
- enum Type type() const { return FIELD_STD_ITEM; }
+ Item_variance_field(Item_sum_variance *item);
+ enum Type type() const {return FIELD_VARIANCE_ITEM; }
double val();
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() {}
};
-class Item_sum_std :public Item_sum_num
+/*
+
+variance(a) =
+
+= sum (ai - avg(a))^2 / count(a) )
+= sum (ai^2 - 2*ai*avg(a) + avg(a)^2) / count(a)
+= (sum(ai^2) - sum(2*ai*avg(a)) + sum(avg(a)^2))/count(a) =
+= (sum(ai^2) - 2*avg(a)*sum(a) + count(a)*avg(a)^2)/count(a) =
+= (sum(ai^2) - 2*sum(a)*sum(a)/count(a) + count(a)*sum(a)^2/count(a)^2 )/count(a) =
+= (sum(ai^2) - 2*sum(a)^2/count(a) + sum(a)^2/count(a) )/count(a) =
+= (sum(ai^2) - sum(a)^2/count(a))/count(a)
+
+*/
+
+class Item_sum_variance : public Item_sum_num
{
- double sum;
- double sum_sqr;
+ double sum, sum_sqr;
ulonglong count;
void fix_length_and_dec() { decimals+=4; maybe_null=1; }
public:
- Item_sum_std(Item *item_par) :Item_sum_num(item_par),count(0) {}
- enum Sumfunctype sum_func () const { return STD_FUNC; }
+ Item_sum_variance(Item *item_par) :Item_sum_num(item_par),count(0) {}
+ enum Sumfunctype sum_func () const { return VARIANCE_FUNC; }
void reset();
bool add();
double val();
void reset_field();
void update_field(int offset);
Item *result_item(Field *field)
- { return new Item_std_field(this); }
- const char *func_name() const { return "std"; }
+ { return new Item_variance_field(this); }
+ const char *func_name() const { return "variance"; }
};
+class Item_sum_std;
+
+class Item_std_field :public Item_variance_field
+{
+public:
+ Item_std_field(Item_sum_std *item);
+ enum Type type() const { return FIELD_STD_ITEM; }
+ double val();
+};
+
+/*
+ standard_deviation(a) = sqrt(variance(a))
+*/
+
+class Item_sum_std :public Item_sum_variance
+{
+ public:
+ Item_sum_std(Item *item_par) :Item_sum_variance(item_par){}
+ enum Sumfunctype sum_func () const { return STD_FUNC; }
+ double val();
+ Item *result_item(Field *field)
+ { return new Item_std_field(this); }
+ const char *func_name() const { return "std"; }
+};
// This class is a string or number function depending on num_func
@@ -281,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;
@@ -307,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);
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index 7e2e8f7cfbd..061cf208052 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -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_DAY || 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)
{
diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h
index 40397351c18..aa075e1a91d 100644
--- a/sql/item_timefunc.h
+++ b/sql/item_timefunc.h
@@ -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,
diff --git a/sql/lex.h b/sql/lex.h
index eb03c0b36ec..421ac933f50 100644
--- a/sql/lex.h
+++ b/sql/lex.h
@@ -344,6 +344,7 @@ static SYMBOL symbols[] = {
{ "SQL_NO_CACHE", SYM(SQL_NO_CACHE_SYM), 0, 0},
{ "SQL_SMALL_RESULT", SYM(SQL_SMALL_RESULT),0,0},
{ "SQL_THREAD", SYM(SQL_THREAD),0,0},
+ { "SOUNDS", SYM(SOUNDS_SYM),0,0},
{ "SSL", SYM(SSL_SYM),0,0},
{ "STRAIGHT_JOIN", SYM(STRAIGHT_JOIN),0,0},
{ "START", SYM(START_SYM),0,0},
@@ -584,6 +585,7 @@ static SYMBOL sql_functions[] = {
{ "UNIX_TIMESTAMP", SYM(UNIX_TIMESTAMP),0,0},
{ "UPPER", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ucase)},
{ "USER", SYM(USER),0,0},
+ { "VARIANCE", SYM(VARIANCE_SYM),0,0},
{ "VERSION", SYM(FUNC_ARG0),0,CREATE_FUNC(create_func_version)},
{ "WEEK", SYM(WEEK_SYM),0,0},
{ "WEEKDAY", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_weekday)},
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 6bb1a1c65a9..913af1bdd7c 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -313,9 +313,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);
}
#endif /* EMBEDDED_LIBRARY */
@@ -327,10 +327,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));
}
@@ -342,23 +345,22 @@ void Log_event::init_show_field_list(List<Item>* field_list)
****************************************************************************/
#ifndef EMBEDDED_LIBRARY
-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 SEND_ROW(thd_arg, 5, (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 /* EMBEDDED_LIBRARY */
#endif // !MYSQL_CLIENT
@@ -686,7 +688,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);
@@ -700,7 +702,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
#endif /* EMBEDDED_LIBRARY */
@@ -944,7 +946,7 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli)
****************************************************************************/
#ifndef EMBEDDED_LIBRARY
#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);
@@ -955,7 +957,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
#endif /* EMBEDDED_LIBRARY */
@@ -1059,7 +1061,7 @@ int Start_log_event::exec_event(struct st_relay_log_info* rli)
****************************************************************************/
#ifndef EMBEDDED_LIBRARY
#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);
@@ -1132,7 +1134,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
#endif /* EMBEDDED_LIBRARY */
@@ -1569,7 +1571,7 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli)
****************************************************************************/
#ifndef EMBEDDED_LIBRARY
#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);
@@ -1579,7 +1581,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
#endif /* EMBEDDED_LIBRARY */
@@ -1711,7 +1713,7 @@ int Rotate_log_event::exec_event(struct st_relay_log_info* rli)
****************************************************************************/
#ifndef EMBEDDED_LIBRARY
#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);
@@ -1719,7 +1721,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
#endif /* EMBEDDED_LIBRARY */
@@ -1836,14 +1838,14 @@ int Intvar_log_event::exec_event(struct st_relay_log_info* rli)
****************************************************************************/
#ifndef EMBEDDED_LIBRARY
#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
#endif /* EMBEDDED_LIBRARY */
@@ -1928,7 +1930,7 @@ int Rand_log_event::exec_event(struct st_relay_log_info* rli)
#ifndef EMBEDDED_LIBRARY
#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);
@@ -1942,7 +1944,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
@@ -2278,7 +2280,7 @@ void Create_file_log_event::print(FILE* file, bool short_form,
****************************************************************************/
#ifndef EMBEDDED_LIBRARY
#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);
@@ -2293,7 +2295,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
#endif /* EMBEDDED_LIBRARY */
@@ -2441,14 +2443,14 @@ void Append_block_log_event::print(FILE* file, bool short_form,
****************************************************************************/
#ifndef EMBEDDED_LIBRARY
#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
#endif /* EMBEDDED_LIBRARY */
@@ -2560,12 +2562,12 @@ void Delete_file_log_event::print(FILE* file, bool short_form,
****************************************************************************/
#ifndef EMBEDDED_LIBRARY
#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
#endif /* EMBEDDED_LIBRARY */
@@ -2663,12 +2665,12 @@ void Execute_load_log_event::print(FILE* file, bool short_form,
****************************************************************************/
#ifndef EMBEDDED_LIBRARY
#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
#endif /* EMBEDDED_LIBRARY */
diff --git a/sql/log_event.h b/sql/log_event.h
index db5b1790123..e0ebe4150bb 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -269,8 +269,8 @@ public:
void set_log_pos(MYSQL_LOG* log);
static void init_show_field_list(List<Item>* field_list);
#ifndef EMBEDDED_LIBRARY
- int net_send(THD* thd, const char* log_name, my_off_t pos);
- virtual void pack_info(String* packet);
+ int net_send(Protocol *protocol, const char* log_name, my_off_t pos);
+ virtual void pack_info(Protocol *protocol);
virtual int exec_event(struct st_relay_log_info* rli);
#endif /* EMBEDDED_LIBRARY */
virtual const char* get_db()
@@ -358,7 +358,7 @@ public:
bool using_trans);
const char* get_db() { return db; }
#ifndef EMBEDDED_LIBRARY
- void pack_info(String* packet);
+ void pack_info(Protocol* protocol);
int exec_event(struct st_relay_log_info* rli);
#endif /* EMBEDDED_LIBRARY */
#else
@@ -410,7 +410,7 @@ public:
#ifndef MYSQL_CLIENT
Slave_log_event(THD* thd_arg, struct st_relay_log_info* rli);
#ifndef EMBEDDED_LIBRARY
- void pack_info(String* packet);
+ void pack_info(Protocol* protocol);
int exec_event(struct st_relay_log_info* rli);
#endif /* EMBEDDED_LIBRARY */
#else
@@ -465,7 +465,7 @@ public:
void set_fields(List<Item> &fields_arg);
const char* get_db() { return db; }
#ifndef EMBEDDED_LIBRARY
- void pack_info(String* packet);
+ void pack_info(Protocol* protocol);
int exec_event(struct st_relay_log_info* rli)
{
return exec_event(thd->slave_net,rli);
@@ -519,7 +519,7 @@ public:
memcpy(server_version, ::server_version, ST_SERVER_VER_LEN);
}
#ifndef EMBEDDED_LIBRARY
- void pack_info(String* packet);
+ void pack_info(Protocol* protocol);
int exec_event(struct st_relay_log_info* rli);
#endif /* EMBEDDED_LIBRARY */
#else
@@ -556,7 +556,7 @@ public:
:Log_event(),val(val_arg),type(type_arg)
{}
#ifndef EMBEDDED_LIBRARY
- void pack_info(String* packet);
+ void pack_info(Protocol* protocol);
int exec_event(struct st_relay_log_info* rli);
#endif /* EMBEDDED_LIBRARY */
#else
@@ -590,7 +590,7 @@ class Rand_log_event: public Log_event
:Log_event(thd_arg,0,0),seed1(seed1_arg),seed2(seed2_arg)
{}
#ifndef EMBEDDED_LIBRARY
- void pack_info(String* packet);
+ void pack_info(Protocol* protocol);
int exec_event(struct st_relay_log_info* rli);
#endif /* EMBEDDED_LIBRARY */
#else
@@ -660,7 +660,7 @@ public:
(uint) strlen(new_log_ident_arg)), alloced(0)
{}
#ifndef EMBEDDED_LIBRARY
- void pack_info(String* packet);
+ void pack_info(Protocol* protocol);
int exec_event(struct st_relay_log_info* rli);
#endif /* EMBEDDED_LIBRARY */
#else
@@ -709,7 +709,7 @@ public:
char* block_arg, uint block_len_arg,
bool using_trans);
#ifndef EMBEDDED_LIBRARY
- void pack_info(String* packet);
+ void pack_info(Protocol* protocol);
int exec_event(struct st_relay_log_info* rli);
#endif /* EMBEDDED_LIBRARY */
#else
@@ -762,7 +762,7 @@ public:
uint block_len_arg, bool using_trans);
#ifndef EMBEDDED_LIBRARY
int exec_event(struct st_relay_log_info* rli);
- void pack_info(String* packet);
+ void pack_info(Protocol* protocol);
#endif /* EMBEDDED_LIBRARY */
#else
void print(FILE* file, bool short_form = 0, char* last_db = 0);
@@ -789,7 +789,7 @@ public:
#ifndef MYSQL_CLIENT
Delete_file_log_event(THD* thd, bool using_trans);
#ifndef EMBEDDED_LIBRARY
- void pack_info(String* packet);
+ void pack_info(Protocol* protocol);
int exec_event(struct st_relay_log_info* rli);
#endif /* EMBEDDED_LIBRARY */
#else
@@ -817,7 +817,7 @@ public:
#ifndef MYSQL_CLIENT
Execute_load_log_event(THD* thd, bool using_trans);
#ifndef EMBEDDED_LIBRARY
- void pack_info(String* packet);
+ void pack_info(Protocol* protocol);
int exec_event(struct st_relay_log_info* rli);
#endif /* EMBEDDED_LIBRARY */
#else
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index ed618f3ba80..a489237a6e8 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -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);
@@ -419,7 +396,7 @@ int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit,
select_result *result);
int mysql_explain_select(THD *thd, SELECT_LEX *sl, char const *type,
select_result *result);
-int mysql_union(THD *thd, LEX *lex,select_result *result);
+int mysql_union(THD *thd, LEX *lex,select_result *result,SELECT_LEX_UNIT *unit);
int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *s, TABLE_LIST *t);
Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
Item_result_field ***copy_func, Field **from_field,
@@ -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);
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 78cbfba26ca..8869a642ed3 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -184,7 +184,6 @@ static uint handler_count;
static bool opt_enable_named_pipe = 0;
#endif
#ifdef __WIN__
-static bool opt_console=0,start_mode=0;
static pthread_cond_t COND_handler_count;
static uint handler_count;
static bool opt_console=0, start_mode=0, use_opt_args;
@@ -1551,7 +1550,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);
diff --git a/sql/net_pkg.cc b/sql/net_pkg.cc
deleted file mode 100644
index 7a3ec5ebf64..00000000000
--- a/sql/net_pkg.cc
+++ /dev/null
@@ -1,525 +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"));
-
-#ifndef EMBEDDED_LIBRARY
- query_cache_abort(net);
-#endif
- 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 */
- }
- }
- }
-
-#ifdef EMBEDDED_LIBRARY
- net->last_errno= sql_errno;
- strmake(net->last_error, err, sizeof(net->last_error)-1);
-#else
-
- 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));
-#endif /* EMBEDDED_LIBRARY*/
- 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
-*/
-
-#ifndef EMBEDDED_LIBRARY
-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;
-}
-#endif
-
-/*
- 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;
-#ifndef EMBEDDED_LIBRARY
- const char *text_pos;
-#else
- char text_pos[500];
-#endif
- 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
-#ifndef EMBEDDED_LIBRARY
- query_cache_abort(net); // Safety
-#endif
- 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;
-#ifndef EMBEDDED_LIBRARY
- text_pos=(char*) net->buff+head_length+offset+1;
-#endif
- (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);
-
-#ifndef EMBEDDED_LIBRARY
- 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));
-#else
- net->last_errno= errcode;
- strmake(net->last_error, text_pos, length);
-#endif
- thd->fatal_error=0; // Error message is given
- DBUG_VOID_RETURN;
-}
-
-/*
- Function called by my_net_init() to set some check variables
-*/
-
-#ifndef EMBEDDED_LIBRARY
-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);
-}
-}
-
-#else /* EMBEDDED_LIBRARY */
-void my_net_local_init(NET *net __attribute__(unused))
-{
-}
-#endif /* EMBEDDED_LIBRARY */
-
-/*
- 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
-*/
-#ifndef EMBEDDED_LIBRARY
-
-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;
-}
-#endif /* EMBEDDED_LIBRARY */
-
-
-/****************************************************************************
-** 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);
-}
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index d76737e8e31..bcea522cb6d 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -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)
{
diff --git a/sql/procedure.h b/sql/procedure.h
index b72c5cb559f..bc1b6062e1d 100644
--- a/sql/procedure.h
+++ b/sql/procedure.h
@@ -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)
diff --git a/sql/protocol.cc b/sql/protocol.cc
new file mode 100644
index 00000000000..ec7ced0e626
--- /dev/null
+++ b/sql/protocol.cc
@@ -0,0 +1,1038 @@
+/* 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"));
+
+#ifndef EMBEDDED_LIBRARY
+ query_cache_abort(net);
+#endif
+ 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 */
+ }
+ }
+ }
+
+#ifdef EMBEDDED_LIBRARY
+ net->last_errno= sql_errno;
+ strmake(net->last_error, err, sizeof(net->last_error)-1);
+#else
+
+ 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));
+#endif /* EMBEDDED_LIBRARY*/
+ 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
+*/
+
+#ifndef EMBEDDED_LIBRARY
+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;
+}
+#endif
+
+/*
+ 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;
+#ifndef EMBEDDED_LIBRARY
+ const char *text_pos;
+#else
+ char text_pos[500];
+#endif
+ 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
+#ifndef EMBEDDED_LIBRARY
+ query_cache_abort(net); // Safety
+#endif
+ 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;
+#ifndef EMBEDDED_LIBRARY
+ text_pos=(char*) net->buff+head_length+offset+1;
+#endif
+ (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);
+
+#ifndef EMBEDDED_LIBRARY
+ 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));
+#else
+ net->last_errno= errcode;
+ strmake(net->last_error, text_pos, length);
+#endif
+ thd->fatal_error=0; // Error message is given
+ DBUG_VOID_RETURN;
+}
+
+/*
+ Function called by my_net_init() to set some check variables
+*/
+
+#ifndef EMBEDDED_LIBRARY
+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);
+}
+}
+
+#else /* EMBEDDED_LIBRARY */
+void my_net_local_init(NET *net __attribute__(unused))
+{
+}
+#endif /* EMBEDDED_LIBRARY */
+
+/*
+ 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
+*/
+#ifndef EMBEDDED_LIBRARY
+
+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;
+}
+#endif /* EMBEDDED_LIBRARY */
+
+
+/****************************************************************************
+ 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);
+}
diff --git a/sql/protocol.h b/sql/protocol.h
new file mode 100644
index 00000000000..b3ab0a2b31d
--- /dev/null
+++ b/sql/protocol.h
@@ -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);
diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc
index 2af2d5ab737..4942dd9cfd8 100644
--- a/sql/repl_failsafe.cc
+++ b/sql/repl_failsafe.cc
@@ -418,6 +418,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];
@@ -433,15 +434,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);
@@ -582,21 +583,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);
@@ -604,18 +608,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);
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 81b4e59a450..dd30d2e377d 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -1012,8 +1012,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;
}
diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt
index 6b19034ae59..c996066d0eb 100644
--- a/sql/share/german/errmsg.txt
+++ b/sql/share/german/errmsg.txt
@@ -2,7 +2,13 @@
This file is public domain and comes with NO WARRANTY of any kind
Dirk Munzinger (dmun@4t2.com)
- Version: 07.06.2001 */
+ Version: 07.06.2001
+
+ Georg Richter (georg@php.net)
+ fixed typos and translation
+ translated new error messages
+ 2002-12-11
+ */
"hashchk",
"isamchk",
@@ -13,41 +19,41 @@
"Kann Datenbank '%-.64s' nicht erzeugen. (Fehler: %d)",
"Kann Datenbank '%-.64s' nicht erzeugen. Datenbank '%-.64s' existiert bereits.",
"Kann Datenbank '%-.64s' nicht löschen. Keine Datenbank '%-.64s' vorhanden.",
-"Fehler beim Löschen der Datenbank. ('%-.64s' kann nicht gelöscht werden, Fehler %d)",
-"Fehler beim Löschen der Datenbank. (Verzeichnis '%-.64s' kann nicht gelöscht werden, Fehler %d)",
+"Fehler beim Löschen der Datenbank. ('%-.64s' kann nicht gelöscht werden, Fehlernuumer: %d)",
+"Fehler beim Löschen der Datenbank. (Verzeichnis '%-.64s' kann nicht gelöscht werden, Fehlernummer: %d)",
"Fehler beim Löschen von '%-.64s'. (Fehler: %d)",
"Datensatz in der Systemtabelle nicht lesbar.",
-"Kann Status von '%-.64s' nicht erhalten. (Fehler: %d)",
-"Kann Arbeitsverzeichnis nicht erhalten. (Fehler: %d)",
-"File nicht sperrbar. (Fehler: %d)",
+"Kann Status von '%-.64s' nicht ermitteln. (Fehler: %d)",
+"Kann Arbeitsverzeichnis nicht ermitteln. (Fehler: %d)",
+"Datei nicht sperrbar. (Fehler: %d)",
"Kann Datei '%-.64s' nicht öffnen. (Fehler: %d)",
"Kann Datei '%-.64s' nicht finden. (Fehler: %d)",
"Verzeichnis von '%-.64s' nicht lesbar. (Fehler: %d)",
-"Verzeichnis kann nicht nach '%-.64s' gewechselt werden. (Fehler: %d)",
+"Kann nicht in das Verzeichnis '%-.64s' wechseln. (Fehler: %d)",
"Datensatz hat sich seit dem letzten Zugriff auf Tabelle '%-.64s' geändert.",
"Festplatte voll (%-.64s). Warte bis jemand Platz schafft ...",
"Kann nicht speichern, doppelter Schlüssel in Tabelle '%-.64s'.",
"Fehler beim Schließen von '%-.64s'. (Fehler: %d)",
"Fehler beim Lesen der Datei '%-.64s'. (Fehler: %d)",
-"Fehler beim Umbennenen von '%-.64s' nach '%-.64s'. (Fehler: %d)",
+"Fehler beim Umbenennen von '%-.64s' nach '%-.64s'. (Fehler: %d)",
"Fehler beim Speichern der Datei '%-.64s'. (Fehler: %d)",
"'%-.64s' ist für Veränderungen gesperrt.",
"Sortieren abgebrochen.",
"View '%-.64s' existiert für '%-.64s' nicht.",
-"Fehler %d. (table handler)",
-"Diese Option gibt es nicht. (table handler)",
+"Fehler %d. (Tabellenhandler)",
+"Diese Option gibt es nicht. (Tabellenhandler)",
"Kann Datensatz nicht finden.",
"Falsche Information in Datei: '%-.64s'",
"Falsche Schlüssel-Datei für Tabelle '%-.64s'. Versuche zu reparieren!",
"Alte Schlüssel-Datei für Tabelle '%-.64s'. Repariere!
"'%-.64s' ist nur lesbar.",
-"Kein Speicher (benötigt %d bytes). Server neu starten.",
-"Kein Speicher zum Sortieren. Server Sortier-Buffer erhöhen.",
-"Unerwartetes EOF beim Lesen der Datei '%-.64s'. (Fehler: %d)",
+"Kein Speicher vorhanden (benötigt %d bytes). Server neu starten.",
+"Kein Speicher zum Sortieren. sort_buffer_size sollte erhöht werden.",
+"Unerwartetes Ende beim Lesen der Datei '%-.64s'. (Fehler: %d)",
"Zu viele Verbindungen.",
"Zuwenig Speicher.",
"Kann Hostname für diese Adresse nicht erhalten.",
-"Schlechter handshake.",
+"Schlechter Handshake.",
"Keine Zugriffsberechtigung für Benutzer: '%-.32s@%-.64s' für Datenbank '%-.64s'.",
"Keine Zugriffsberechtigung für Benutzer: '%-.32s@%-.64s'. (Verwendetes Passwort: %-.64s)",
"Keine Datenbank ausgewählt.",
@@ -61,16 +67,16 @@
"Unbekanntes Tabellenfeld '%-.64s' in %-.64s.",
"'%-.64s' ist nicht in GROUP BY.",
"Gruppierung nicht möglich bei '%-.64s'.",
-"Im Statement wurden sowohl sum-Funktionen als auch Spalten verwendet. Nicht möglich.",
+"Die Verwendung von sum-Funktionen und Spalten ist nicht möglich.",
"Spaltenzähler entspricht nicht dem Wertzähler.",
-"Name des Identifizierers '%-.64s' ist zu lang.",
+"Name des Bezeichners '%-.64s' ist zu lang.",
"Doppelter Spaltenname vorhanden: '%-.64s'",
"Doppelter Name für Schlüssel (Key) vorhanden: '%-.64s'",
"Doppelter Eintrag '%-.64s' für Schlüssel %d.",
"Falsche Spalten-Spezifizierung für Spalte '%-.64s'.",
"%-.64s bei '%-.64s' in Zeile %d.",
"Leere Abfrage.",
-"Keine eindeutige(n) Tabelle/Alias: '%-.64s'",
+"Keine eindeutiger Tabellenname/Alias: '%-.64s'",
"Fehlerhafter Vorgabewert (Default-Wert): '%-.64s'",
"Mehrfacher Primärschlüssel (Primary Key) definiert.",
"Zuviele Schlüssel definiert. Maximal %d Schlüssel erlaubt.",
@@ -78,37 +84,37 @@
"Schlüssel ist zu lang. Die maximale Schlüssellänge beträgt %d.",
"In der Tabelle gibt es keine Schlüsselspalte '%-.64s'.",
"BLOB-Feld '%-.64s' kann nicht als Schlüssel verwendet werden.",
-"Feldlänge für Feld '%-.64s' zu groß (max = %d). BLOB-Feld verwenden!",
+"Feldlänge für Feld '%-.64s' zu groß (max. = %d). BLOB-Feld verwenden!",
"Nur ein Auto-Feld möglich, welches als Schlüssel definiert werden muß.",
-"%-.64s: Warten auf Verbindungen.\n",
+"%-.64s: Warte auf Verbindungen.\n",
"%-.64s: Normal beendet.\n",
"%-.64s: Signal %d erhalten. Abbruch!\n",
"%-.64s: Shutdown ausgeführt.\n",
-"%-.64s: Beendigung des Thread %ld veranlaßt. Benutzer: '%-.64s'\n",
+"%-.64s: Beendigung des Thread %ld veranlasst. Benutzer: '%-.64s'\n",
"Kann IP-Socket nicht erstellen.",
-"Tabelle '%-.64s' hat keinen solchen Index wie in CREATE INDEX verwendet. Index neu anlegen.",
-"Feld-Separator Argument ist nicht in der Form wie erwartet. Bitte im Manual nachlesen.",
+"Tabelle '%-.64s' besitzt keinen wie in CREATE INDEX verwendeten Index. Index neu anlegen.",
+"Feldbegrenzer Argument ist nicht in der Form wie erwartet. Bitte im Manual nachlesen.",
"Eine feste Reihenlänge kann für BLOBs nicht verwendet werden. Verwende 'fields terminated by' stattdessen.",
-"Feld '%-.64s' muß im Datenbank-Directory vorhanden und lesbar für alle sein.",
-"File '%-.64s' bereits vorhanden.",
+"Feld '%-.64s' muß im Datenbank-Verzeichnis vorhanden und lesbar für alle sein.",
+"Datei '%-.64s' bereits vorhanden.",
"Datensätze: %ld Gelöscht: %ld Ausgelassen: %ld Warnungen: %ld",
"Datensätze: %ld Duplikate: %ld",
-"Falscher Subteilschlüssel. Der verwendete Schlüsselteil ist entweder kein String oder die verwendete Länge ist länger als der Teilschlüssel.",
+"Falscher Unterteilschlüssel. Der verwendete Schlüsselteil ist entweder kein String, die verwendete Länge ist länger als der Teilschlüssel oder der Tabellenhandler unterstützt keine Unterteilschlüssel.",
"Mit ALTER TABLE können nicht alle Felder auf einmal gelöscht werden. Verwende DROP TABLE stattdessen.",
"Kann '%-.64s' nicht löschen (DROP). Existiert das Feld/der Schlüssel?",
"Datensätze: %ld Duplikate: %ld Warnungen: %ld",
-"You can't specify target table '%-.64s' for update in FROM clause",
+"Die Verwendung der Zieltabelle '%-.64s' ist bei Update in FROM Teil nicht zulässig.",
"Unbekannte Thread-ID: %lu",
-"Nicht Besitzer des Threads %lu.",
+"Threads %lu. ist einem anderen Besitzer zugeordnet.",
"Keine Tabellen in Verwendung.",
-"Zuviele Strings für Spalte %-.64s und SET.",
-"Kann keinen eindeutigen Log-Filenamen erstellen %-.64s.(1-999)\n",
-"Tabelle '%-.64s' mit Lese-Sperre versehen und kann nicht upgedated werden.",
+"Zuviele Angaben für Spalte %-.64s und SET.",
+"Kann keinen eindeutigen Dateinamen für die Logdatei ermitteln %-.64s.(1-999)\n",
+"Tabelle '%-.64s' mit Lese-Sperre versehen und kann nicht aktualisiert werden.",
"Tabelle '%-.64s' wurde nicht mittels LOCK TABLES gesperrt.",
"BLOB-Feld '%-.64s' kann keinen Vorgabewert (Default-Value) besitzen.",
"Unerlaubter Datenbankname '%-.64s'.",
"Unerlaubter Tabellenname '%-.64s'.",
-"Die Ausführung des SELECT würde zu viele Datensätze untersuchen und wahrscheinlich sehr lange daueren. Bitte WHERE überprüfen und SET OPTION SQL_BIG_SELECTS=1 verwenden, sofern SELECT ok ist.",
+"Die Ausführung des SELECT würde zu viele Datensätze untersuchen und wahrscheinlich sehr lange daueren. Bitte WHERE überprüfen oder gegebenenfalls SET OPTION SQL_BIG_SELECTS=1 verwenden.",
"Unbekannter Fehler.",
"Unbekannte Procedure %-.64s.",
"Falsche Parameterzahl für Procedure %-.64s.",
@@ -135,51 +141,51 @@
"Funktion '%-.64s' ist nicht definiert.",
"Host blockiert wegen zu vieler Verbindungsfehler. Aufheben der Blockierung mit 'mysqladmin flush-hosts'.",
"Host hat keine Berechtigung, eine Verbindung zu diesem MySQL Server herzustellen.",
-"Sie benutzen MySQL als anonymer User; diese User dürfen keine Passwörter ändern.",
-"Sie müssen autorisiert sein zum UPDATE von Tabellen in der mysql Datenbank, um für andere Benutzer Passwörter ändern zu können.",
-"Kann keinen passenden Datensatz in der User-Tabelle finden.",
+"Sie benutzen MySQL als anonymer Benutzer und dürfen daher keine Passwörter ändern.",
+"Sie müssen autorisiert sein zum Aktualisieren von Tabellen in der mysql Datenbank, um für andere Benutzer Passwörter ändern zu können.",
+"Kann keinen passenden Datensatz in der Benutzer-Tabelle finden.",
"Datensätze gefunden: %ld Geändert: %ld Warnungen: %ld",
-"Kann keinen neuen Thread erzeugen (errno %d). Sollte nicht die Speichergrenze erreicht sein, bitte im Manual nach vorhanden OS-Abhängigen Fehlern nachschauen.",
+"Kann keinen neuen Thread erzeugen (Fehler: %d). Sollte die Speichergrenze nicht erreicht sein, bitte in der Dokumentation nach evtl. Betriebssystem abhängigen Fehlern nachlesen.",
"Spaltenzahl stimmt nicht mit der Anzahl der Werte überein in Reihe%ld",
"Kann Tabelle'%-.64s' nicht wieder öffnen",
"Unerlaubte Verwendung eines NULL-Wertes",
"Fehler '%-.64s' von regexp",
"Das Vermischen von GROUP Spalten (MIN(),MAX(),COUNT()...) mit Nicht-GROUP Spalten ist nicht erlaubt, sofern keine GROUP BY Klausel vorhanden ist.",
"Keine solche Berechtigung für User '%-.32s' auf Host '%-.64s'",
-"%-.16s Kommando abgelehnt für User: '%-.32s@%-.64s' für Tabelle '%-.64s'",
-"%-.16s Kommando abgelehnt für User: '%-.32s@%-.64s' in Spalte '%-.64s' in Tabelle '%-.64s'",
-"Unzulässiges GRANT/REVOKE Kommando. Weiteres zum Thema Berechtigungen im Manual.",
+"%-.16s Befehl nicht erlaubt für User: '%-.32s@%-.64s' für Tabelle '%-.64s'",
+"%-.16s Befehl nicht erlaubt für User: '%-.32s@%-.64s' in Spalte '%-.64s' in Tabelle '%-.64s'",
+"Unzulässiger GRANT/REVOKE Befehl. Weiteres zum Thema Berechtigungen im Manual.",
"Das Host oder User Argument für GRANT ist zu lang",
"Tabelle '%-.64s.%-.64s' existiert nicht",
"Keine solche Berechtigung für User '%-.32s' auf Host '%-.64s' an Tabelle '%-.64s'",
-"Das used Kommando ist mit dieser MySQL Version nicht erlaubt",
+"Der used Befehl ist mit dieser MySQL Version nicht erlaubt",
"Fehler in der Syntax",
-"Verzögerter Einfüge-Thread konnte den angeforderten Lock für Tabelle %-.64s nicht bekommen",
+"Verzögerter Einfüge-Thread konnte den angeforderten Lock für Tabelle %-.64s nicht erhalten",
"Zu viele Delayed Threads in Verwendung",
"Abbruch der Verbindung %ld zur Datenbank: '%-.64s' User: '%-.64s' (%-.64s)",
"Empfangenes Paket ist größer als 'max_allowed_packet'",
"Lese-Fehler bei einer Kommunikations-Pipe",
"Fehler von fcntl()",
"Empfangenes Paket ist nicht in Reihenfolge",
-"Communikation-Packet läßt sich nicht entpacken",
-"Fehler beim Lesen eines Communication-Packets"
-"Timeout beim Lesen eines Communication-Packets",
-"Fehler beim Schreiben eines Communication-Packets",
-"Timeout beim Schreiben eines Communication-Packets",
-"Ergebnisstring ist länger als max_allowed_packet",
+"Kommunikationspaket läßt sich nicht entpacken",
+"Fehler beim Lesen eines Kommunikationspakets"
+"Zeitüberschreitung beim Lesen eines Kommunikationspakets.",
+"Fehler beim Schreiben eines Kommunikationspakets.",
+"Zeitüberschreitung beim Schreiben eines Kommunikationspakets.",
+"Ergebnis ist länger als max_allowed_packet",
"Der verwendete Tabellentyp unterstützt keine BLOB/TEXT Spalten",
"Der verwendete Tabellentyp unterstützt keine AUTO_INCREMENT Spalte",
"INSERT DELAYED kann nicht auf Tabelle '%-.64s' angewendet werden, da diese mit LOCK TABLES gesperrt ist",
"Falscher Spaltenname '%-.100s'",
"Der verwendete Tabellen-Handler kann die Spalte '%-.64s' nicht indizieren",
-"Alle Tabelle in der MERGE-Tabelle sind nicht gleich definiert",
+"Alle Tabellen in der MERGE-Tabelle sind nicht gleich definiert",
"Schreiben in Tabelle '%-.64s' nicht möglich wegen eines Unique Constraint",
"BLOB Spalte '%-.64s' wird in der Key-Definition ohne Längenangabe verwendet",
"Alle Teile eines PRIMARY KEY müssen als NOT NULL definiert sein; Wenn NULL benötigt wird sollte ein UNIQUE Key verwendet werden",
"Ergebnis besteht aus mehr als einer Reihe",
"Dieser Tabellentyp verlangt nach einem PRIMARY KEY",
"Diese MySQL-Version ist nicht mit RAID-Unterstützung kompiliert",
-"Unter Verwendung des Sicheren Updatemodes wurde versucht eine Tabelle zu updaten ohne eine KEY-Spalte in der WHERE-Klausel",
+"Unter Verwendung des sicheren Aktualisierungsmodus wurde versucht eine Tabelle zu aktualisieren ohne eine KEY-Spalte in der WHERE-Klausel",
"Schlüssel '%-.64s' existiert nicht in der Tabelle '%-.64s'",
"Kann Tabelle nicht öffnen",
"Der Tabellen-Handler für diese Tabelle unterstützt kein %s",
@@ -191,65 +197,66 @@
"Verbindungsabbruch %ld zu db: '%-.64s' user: '%-.32s' host: `%-.64s' (%-.64s)",
"Der Tabellenhandler für die Tabelle unterstützt kein Binary Tabellendump",
"Binlog wurde beendet wärend FLUSH MASTER",
-"Neubau des Index der gedumpten Tabelle '%-.64s' fehlgeschlagen",
+"Neuerstellung des Index der gedumpten Tabelle '%-.64s' fehlgeschlagen",
"Fehler vom Master: '%-.64s'",
"Netzfehler beim Lesen vom Master",
"Netzfehler beim Schreiben zum Master",
-"Kann keinen FULLTEXT-Index finden der der Spaltenliste entspricht",
+"Kann keinen FULLTEXT-Index finden, der der Spaltenliste entspricht",
"Kann das aktuelle Kommando wegen aktiver Tabellensperre oder aktiver Transaktion nicht ausführen",
-"Unbekannte System-Variabel '%-.64s'",
+"Unbekannte Systemvariable '%-.64s'",
"Tabelle '%-.64s' ist als defekt makiert und sollte repariert werden",
"Tabelle '%-.64s' ist als defekt makiert und der letzte (automatische) Reparaturversuch schlug fehl.",
"Warnung: Das Rollback konnte bei einigen Tabellen, die nicht mittels Transaktionen geändert wurden, nicht ausgeführt werden.",
-"Multi-Statement Transaktionen benötigen mehr als 'max_binlog_cache_size' Bytes An Speicher. Diese mysqld-Variabel vergrössern und nochmal versuchen.',
+"Multi-Statement Transaktionen benötigen mehr als 'max_binlog_cache_size' Bytes An Speicher. Diese mysqld-Variable vergrössern und erneut versuchen.',
"Diese Operation kann nicht bei einem aktiven Slave durchgeführt werden. Das Kommand SLAVE STOP muss zuerst ausgeführt werden.",
-"Diese Operationbenötigt einen aktiven Slave. Slave konfigurieren und mittels SLAVE START aktivieren.",
+"Diese Operation benötigt einen aktiven Slave. Slave konfigurieren und mittels SLAVE START aktivieren.",
"Der Server ist nicht als Slave konfigiriert. Im Konfigurations-File oder mittel CHANGE MASTER TO beheben.",
"Konnte Master-Info-Struktur nicht initialisieren; Berechtigungen von master.info prüfen.",
"Konnte keinen Slave-Thread starten. System-Resourcen überprüfen.",
"Benutzer %-.64s hat mehr als 'max_user_connections' aktive Verbindungen",
-"Bei der Verwendung mit SET dürfen nur Constante Ausdrücke verwendet werden",
-"Lock wait timeout exceeded",
-"The total number of locks exceeds the lock table size",
-"Update locks cannot be acquired during a READ UNCOMMITTED transaction",
-"DROP DATABASE not allowed while thread is holding global read lock",
-"CREATE DATABASE not allowed while thread is holding global read lock",
-"Wrong arguments to %s",
-"%-.32s@%-.64s is not allowed to create new users",
-"Incorrect table definition; All MERGE tables must be in the same database",
-"Deadlock found when trying to get lock; Try restarting transaction",
-"The used table type doesn't support FULLTEXT indexes",
-"Cannot add foreign key constraint",
-"Cannot add a child row: a foreign key constraint fails",
-"Cannot delete a parent row: a foreign key constraint fails",
-"Error connecting to master: %-.128s",
-"Error running query on master: %-.128s",
-"Error when executing command %s: %-.128s",
-"Wrong usage of %s and %s",
-"The used SELECT statements have a different number of columns",
-"Can't execute the query because you have a conflicting read lock",
-"Mixing of transactional and non-transactional tables is disabled",
-"Option '%s' used twice in statement",
-"User '%-.64s' has exceeded the '%s' resource (current value: %ld)",
-"Access denied. You need the %-.128s privilege for this operation",
-"Variable '%-.64s' is a LOCAL variable and can't be used with SET GLOBAL",
-"Variable '%-.64s' is a GLOBAL variable and should be set with SET GLOBAL",
-"Variable '%-.64s' doesn't have a default value",
-"Variable '%-.64s' can't be set to the value of '%-.64s'",
-"Wrong argument type to variable '%-.64s'",
-"Variable '%-.64s' can only be set, not read",
-"Wrong usage/placement of '%s'",
-"This version of MySQL doesn't yet support '%s'",
-"Got fatal error %d: '%-.128s' from master when reading data from binary log",
-"Wrong foreign key definition for '%-.64s': %s",
-"Key reference and table reference doesn't match",
-"Cardinality error (more/less than %d columns)",
-"Subselect return more than 1 record",
-"Unknown prepared statement handler (%ld) given to %s",
-"Help database is corrupt or does not exist",
-"Cyclic reference on subqueries",
-"Converting column '%s' from %s to %s",
-"Reference '%-.64s' not supported (%s)",
-"Every derived table must have it's own alias"
-"Select %u was reduced during optimisation",
-"Table '%-.64s' from one of SELECT's can not be used in %-.32s"
+"Bei der Verwendung mit SET dürfen nur konstante Ausdrücke verwendet werden",
+"Beim Warten auf einen LOCK wurde die zulässige Wartezeit überschritten.",
+"Die Gesamtanzahl der LOCKS überschreitet die Grösse der Locktabelle.",
+"Während einer READ UNCOMMITED Transaktion kann keine Update LOCK angefordert werden.",
+"Solange ein globaler Read LOCK gesetzt ist, ist DROP DATABASE nicht zulässig.",
+"Solange ein globaler Read LOCK gesetzt ist, ist CREATE DATABASE nicht zulässig.",
+"Falsche Argumente für %s",
+"%-.32s@%-.64s is nicht berechtigt neue Benutzer hinzuzufügen.",
+"Falsche Tabellendefinition: Sämtliche MERGE-Tabellen müssen in derselben Datenbank sein.",
+"Beim Versuch einen Lock anzufordern ist ein Deadlock aufgetreten. Es wird versucht die Transaktion erneut zu starten.",
+"Der verwendete Tabellentyp unterstützt keinen FULLTEXT-Index.",
+"Foreign_Key Beschränkung konnte nicht hinzugefügt werden."
+"Hinzufügen eines Kind-Datensatzes schlug aufgrund einer Foreign-Key Beschränkung fehl.",
+"Löschen eines Eltern-Datensatzes schlug aufgrund einer Foreign-Key Beschränkung fehl.",
+"Datensatz kann aufgrund einer Foreign-Key Beschränkung nicht gelöscht werden.",
+"Fehler bei der Verbindung zum Master: %-.128s",
+"Beim Ausführen einer Abfrage auf dem Master trat ein Fehler auf: %-.128s.",
+"Fehler beim Ausführen des Befehls %s: %-.128s.",
+"Falsche Verwendung von %s und %s.",
+"Die verwendeten SELECTs liefern eine unterschiedliche Anzahl von Spalten zurück.",
+"Augrund eines READ LOCK Konflikts kann die Abfrage nicht ausgeführt werden.",
+"Die Verwendung von transaktions- und nicht transaktionsaktionsunterstützenden Tabellen ist deaktiviert.",
+"Option '%s' wird im Befehl zweimal verwendet.",
+"Benutzer '%-.64s' hat Limit '%s' überschritten. (Momentaner Wert: %ld)",
+"Befehl nicht zulässig. Hierfür wird die Berechtigung %-.128s benötigt.",
+"Variable '%-.64s' ist eine lokale Variable und kann nicht mit SET GLOBAL verändert werden.",
+"Variable '%-.64s' ist eine globale Variable und muss mit SET GLOBAL verändert werden.",
+"Variable '%-.64s' besitzt keinen vorgegebenen Wert.",
+"Der Variablen '%-.64s' kann nicht der Wert '%-.64s' zugewiesen werden.",
+"Falscher Typ für Variable '%-.64s'",
+"Variable '%-.64s' kann nur verändert, nicht aber gelesen werden.",
+"Falsche Verwendung oder Platzierung von '%s'",
+"Diese MySQL-Version unterstützt momentan nicht '%s'.",
+"Schwerer Fehler %d: '%-.128s vom Master beim Lesen des Binary Logs.",
+"Falsche Foreign-Key Definition für '%-64s': %s",
+"Schlüssel- und Tabellenreferenz passen nicht zueinander.",
+"Kardinalitäts-Fehler (mehr/oder weniger als %d Spalten).",
+"Unterabfrage lieferte mehr als einen Datensatz zurück.",
+"Unbekannter prepared statement handler (%ld) für %s angegeben.",
+"Die Hilfedatenbank ist beschädigt oder existiert nicht.",
+"Zyklische Referenz in den Unterabfragen.",
+"Spalte '%s' wird von %s nach %s umgewandelt",
+"Referenz '%-.64s' wird nicht unterstützt (%s)",
+"Für jede abgeleitete Tabelle muss ein eigener Alias angegeben werden.",
+"Select %u wurde während der Optimierung reduziert.",
+"Tabelle '%-.64s', die in einem der SELECT-Befehle verwendet wurde kann nicht in %-.32s verwendet werden."
diff --git a/sql/slave.cc b/sql/slave.cc
index 16bc08a2b6e..24ec1fc2536 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -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);
-
- 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);
-
- if (mc_simple_command(mysql, COM_REGISTER_SLAVE, (char*)packet.ptr(),
- packet.length(), 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
+
+ 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*) 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);
}
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 6438e39cb6e..e2ddd2cba81 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -2780,6 +2780,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);
@@ -2826,7 +2827,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);
@@ -2935,12 +2936,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 (SEND_ROW(thd, field_list.elements, (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;
}
}
@@ -2991,10 +2992,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 (SEND_ROW(thd, field_list.elements, (char*) thd->packet.ptr(),
- thd->packet.length()))
+ protocol->prepare_for_resend();
+ protocol->store(db.ptr(),db.length());
+ if (protocol->write())
{
error=-1;
goto end;
@@ -3079,10 +3079,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 (SEND_ROW(thd, field_list.elements, (char*) thd->packet.ptr(),
- thd->packet.length()))
+ protocol->prepare_for_resend();
+ protocol->store(global.ptr(),global.length());
+ if (protocol->write())
{
error= -1;
break;
diff --git a/sql/sql_analyse.cc b/sql/sql_analyse.cc
index ecd9f635060..acd67ad66d7 100644
--- a/sql/sql_analyse.cc
+++ b/sql/sql_analyse.cc
@@ -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
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 8d77a6355bb..f7a0c6960d4 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -195,253 +195,6 @@ OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *wild)
DBUG_RETURN(open_list);
}
-/*
- 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)
-*/
-
-#ifndef EMBEDDED_LIBRARY
-
-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 */
-}
-
-#endif /* EMBEDDED_LIBRARY */
-
/*****************************************************************************
* Functions to free open table cache
****************************************************************************/
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index ed09421e66b..a4cd34e7856 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -154,6 +154,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)
@@ -442,7 +447,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));
@@ -451,12 +456,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));
}
@@ -507,7 +513,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);
}
@@ -517,35 +523,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);
}
#endif /* EMBEDDED_LIBRARY */
@@ -940,9 +944,9 @@ bool select_singleval_subselect::send_data(List<Item> &items)
calculate value on it & determinate "is it NULL?".
*/
it->real_value= val_item->val_result();
- if ((it->null_value= val_item->is_null_result()))
+ if ((it->null_value= val_item->null_value))
{
- it->assign_null();
+ it->reset();
}
else
{
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 39efba28f5f..1d5a00682b8 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -398,6 +398,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
diff --git a/sql/sql_db.cc b/sql/sql_db.cc
index f8929f207bc..bca133bd63a 100644
--- a/sql/sql_db.cc
+++ b/sql/sql_db.cc
@@ -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 (SEND_ROW(thd, field_list.elements, (char*) packet->ptr(), packet->length()))
+ if (protocol->write())
DBUG_RETURN(1);
-
send_eof(thd);
DBUG_RETURN(0);
}
diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc
index f0df6811133..f7d845e9e36 100644
--- a/sql/sql_derived.cc
+++ b/sql/sql_derived.cc
@@ -27,13 +27,33 @@
static const char *any_db="*any*"; // Special symbol for check_access
+/*
+ Resolve derived tables in all queries
+
+ SYNOPSIS
+ mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
+ thd Thread handle
+ lex LEX for this thread
+ unit node that contains all SELECT's for derived tables
+ t TABLE_LIST for the upper SELECT
+
+ IMPLEMENTATION
+
+ Derived table is resolved with temporary table. It is created based on the
+ queries defined. After temporary table is created, if this is not EXPLAIN,
+ then the entire unit / node is deleted. unit is deleted if UNION is used
+ for derived table and node is deleted is it is a simple SELECT.
+
+ After table creation, the above TABLE_LIST is updated with a new table.
+
+ This function is called before any command containing derived table is executed.
+
+ TODO: To move creation of derived tables IN open_and_lock_tables()
+*/
+
int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
{
- /*
- TODO: make derived tables with union inside (now only 1 SELECT may be
- procesed)
- */
SELECT_LEX *sl= unit->first_select();
List<Item> item_list;
TABLE *table;
@@ -41,8 +61,19 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
select_union *derived_result;
TABLE_LIST *tables= (TABLE_LIST *)sl->table_list.first;
TMP_TABLE_PARAM tmp_table_param;
+ bool is_union=sl->next_select() && sl->next_select()->linkage == UNION_TYPE;
DBUG_ENTER("mysql_derived");
+
+/*
+ In create_total_list, derived tables have to be treated in case of EXPLAIN,
+ This is because unit/node is not deleted in that case. Current code in this
+ function has to be improved to recognize better when this function is called
+ from derived tables and when from other functions.
+*/
+ if (is_union && unit->create_total_list(thd, lex, &tables))
+ DBUG_RETURN(-1);
+
if (tables)
res= check_table_access(thd,SELECT_ACL, tables);
else
@@ -58,6 +89,28 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
if (!(res=open_and_lock_tables(thd,tables)))
{
+ if (is_union)
+ {
+/*
+ The following code is a re-do of fix_tables_pointers() found in sql_select.cc
+ for UNION's within derived tables. The only difference is in navigation, as in
+ derived tables we care for this level only.
+
+ fix_tables_pointers makes sure that in UNION's we do not open single table twice
+ if found in different SELECT's.
+
+*/
+ for (SELECT_LEX *sel= sl;
+ sel;
+ sel= sel->next_select())
+ {
+ for (TABLE_LIST *cursor= (TABLE_LIST *)sel->table_list.first;
+ cursor;
+ cursor=cursor->next)
+ cursor->table= cursor->table_list->table;
+ }
+ }
+
if (setup_fields(thd,tables,item_list,0,0,1))
{
res=-1;
@@ -66,7 +119,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
bzero((char*) &tmp_table_param,sizeof(tmp_table_param));
tmp_table_param.field_count=item_list.elements;
if (!(table=create_tmp_table(thd, &tmp_table_param, item_list,
- (ORDER*) 0, 0, 1,
+ (ORDER*) 0, is_union && !unit->union_option, 1,
(sl->options | thd->options |
TMP_TABLE_ALL_COLUMNS),
HA_POS_ERROR)))
@@ -87,11 +140,14 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
SELECT_LEX_NODE *save_current_select= lex->current_select;
lex->current_select= sl;
- res= mysql_select(thd, tables, sl->item_list,
+ if (is_union)
+ res=mysql_union(thd,lex,derived_result,unit);
+ else
+ res= mysql_select(thd, tables, sl->item_list,
sl->where, (ORDER *) sl->order_list.first,
(ORDER*) sl->group_list.first,
sl->having, (ORDER*) NULL,
- sl->options | thd->options | SELECT_NO_UNLOCK,
+ sl->options | thd->options | SELECT_NO_UNLOCK,
derived_result, unit, sl, 0);
lex->current_select= save_current_select;
@@ -112,7 +168,12 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
tables->table_list->table=tables->table; // to fix a problem in EXPLAIN
}
else
- sl->exclude();
+ {
+ if (is_union)
+ unit->exclude();
+ else
+ sl->exclude();
+ }
t->db=(char *)"";
t->derived=(SELECT_LEX *)0; // just in case ...
table->file->info(HA_STATUS_VARIABLE);
diff --git a/sql/sql_error.cc b/sql/sql_error.cc
index dc9fbe8468d..c9684855b86 100644
--- a/sql/sql_error.cc
+++ b/sql/sql_error.cc
@@ -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 (SEND_ROW(thd, field_list.elements, (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;
diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc
index 2e979a948e6..97703cd6b20 100644
--- a/sql/sql_handler.cc
+++ b/sql/sql_handler.cc
@@ -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;
}
}
- SEND_ROW(thd, list.elements, (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))
diff --git a/sql/sql_help.cc b/sql/sql_help.cc
index 03a435670c4..db28823a43d 100644
--- a/sql/sql_help.cc
+++ b/sql/sql_help.cc
@@ -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 (SEND_ROW(thd,2,(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 (SEND_ROW(thd,field_list.elements,(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;
}
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 833f36dbe9f..99e465f79c0 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -941,8 +941,6 @@ int yylex(void *arg, void *yythd)
void st_select_lex_node::init_query()
{
- next= master= slave= link_next= 0;
- prev= link_prev= 0;
dependent= 0;
}
@@ -995,7 +993,8 @@ void st_select_lex::init_select()
use_index.empty();
ftfunc_list_alloc.empty();
ftfunc_list= &ftfunc_list_alloc;
- linkage= UNSPECIFIED_TYPE;
+ if (linkage != UNION_TYPE)
+ linkage= UNSPECIFIED_TYPE;
}
/*
@@ -1010,6 +1009,7 @@ void st_select_lex_node::include_down(st_select_lex_node *upper)
prev= &upper->slave;
upper->slave= this;
master= upper;
+ slave= 0;
}
/* include neighbour (on same level) */
@@ -1020,6 +1020,7 @@ void st_select_lex_node::include_neighbour(st_select_lex_node *before)
prev= &before->next;
before->next= this;
master= before->master;
+ slave= 0;
}
/* including in global SELECT_LEX list */
@@ -1206,7 +1207,7 @@ bool st_select_lex_unit::create_total_list_n_last_return(THD *thd, st_lex *lex,
net_printf(thd,ER_WRONG_USAGE,"UNION","ORDER BY");
return 1;
}
- if (sl->linkage == DERIVED_TABLE_TYPE)
+ if (sl->linkage == DERIVED_TABLE_TYPE && !sl->next_select())
continue;
for (SELECT_LEX_UNIT *inner= sl->first_inner_unit();
inner;
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 0c761baffa3..927b806a082 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -194,6 +194,7 @@ enum olap_type
Base class for st_select_lex (SELECT_LEX) &
st_select_lex_unit (SELECT_LEX_UNIT)
*/
+struct st_lex;
class st_select_lex;
class st_select_lex_unit;
class st_select_lex_node {
@@ -252,6 +253,7 @@ public:
void mark_as_dependent(st_select_lex *last);
friend class st_select_lex_unit;
+ friend bool mysql_new_select(struct st_lex *lex, bool move_down);
private:
void fast_exclude();
};
diff --git a/sql/sql_list.h b/sql/sql_list.h
index 56e6528f214..1711a340cae 100644
--- a/sql/sql_list.h
+++ b/sql/sql_list.h
@@ -25,8 +25,16 @@
class Sql_alloc
{
public:
- static void *operator new(size_t size) {return (void*) sql_alloc((uint) size); }
+ static void *operator new(size_t size)
+ {
+ return (void*) sql_alloc((uint) size);
+ }
+ static void *operator new[](size_t size)
+ {
+ return (void*) sql_alloc((uint) size);
+ }
static void operator delete(void *ptr, size_t size) {} /*lint -e715 */
+ static void operator delete[](void *ptr, size_t size) {}
#ifdef HAVE_purify
bool dummy;
inline Sql_alloc() :dummy(0) {}
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 97804a0312f..b3e44fe10b3 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -3030,11 +3030,13 @@ mysql_init_query(THD *thd)
lex->select_lex.init_query();
lex->value_list.empty();
lex->param_list.empty();
+ lex->unit.next= lex->unit.master= lex->unit.link_next= 0;
+ lex->unit.prev= lex->unit.link_prev= 0;
lex->unit.global_parameters= lex->unit.slave= lex->current_select=
lex->all_selects_list= &lex->select_lex;
lex->select_lex.master= &lex->unit;
lex->select_lex.prev= &lex->unit.slave;
- lex->select_lex.link_next= 0;
+ lex->select_lex.link_next= lex->select_lex.slave= lex->select_lex.next= 0;
lex->select_lex.link_prev= (st_select_lex_node**)&(lex->all_selects_list);
lex->olap=lex->describe=0;
lex->derived_tables= false;
@@ -3049,11 +3051,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;
@@ -3084,6 +3086,8 @@ mysql_new_select(LEX *lex, bool move_down)
unit->init_query();
unit->init_select();
unit->include_down(lex->current_select);
+ unit->link_next= 0;
+ unit->link_prev= 0;
select_lex->include_down(unit);
}
else
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 00c88752619..0c21ffe3f95 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -520,7 +520,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);
}
@@ -734,7 +735,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);
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index 54a7bdb8dc8..3bffeaccb15 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -930,14 +930,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())
@@ -985,7 +986,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;
@@ -1031,28 +1032,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);
@@ -1081,6 +1083,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())
{
@@ -1090,8 +1094,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();
@@ -1100,22 +1104,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);
}
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index a0751e16be9..c7ab438ba97 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -162,7 +162,7 @@ int handle_select(THD *thd, LEX *lex, select_result *result)
register SELECT_LEX *select_lex = &lex->select_lex;
fix_tables_pointers(lex->all_selects_list);
if (select_lex->next_select())
- res=mysql_union(thd,lex,result);
+ res=mysql_union(thd,lex,result,&lex->unit);
else
res=mysql_select(thd,(TABLE_LIST*) select_lex->table_list.first,
select_lex->item_list,
@@ -761,6 +761,8 @@ JOIN::exec()
test_if_skip_sort_order(&join_tab[const_tables], order,
select_limit, 0))))
order=0;
+ if (procedure)
+ (void)result->prepare(fields_list, unit);
select_describe(this, need_tmp,
order != 0 && !skip_sort_order,
select_distinct);
@@ -791,6 +793,16 @@ JOIN::exec()
HA_POS_ERROR)))
DBUG_VOID_RETURN;
+ /*
+ We don't have to store rows in temp table that doesn't match HAVING if:
+ - we are sorting the table and writing complete group rows to the
+ temp table.
+ - We are using DISTINCT without resolving the distinct as a GROUP BY
+ on all columns.
+
+ If having is not handled here, it will be checked before the row
+ is sent to the client.
+ */
if (having_list &&
(sort_and_group || (exec_tmp_table->distinct && !group_list)))
having=having_list;
@@ -3047,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)
@@ -3061,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++)
@@ -3078,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);
}
@@ -3775,13 +3794,14 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
else
return new Field_double(item_sum->max_length,maybe_null,
item->name, table, item_sum->decimals);
- case Item_sum::STD_FUNC: /* Place for sum & count */
+ case Item_sum::VARIANCE_FUNC: /* Place for sum & count */
+ case Item_sum::STD_FUNC:
if (group)
return new Field_string(sizeof(double)*2+sizeof(longlong),
maybe_null, item->name,table,my_charset_bin);
else
return new Field_double(item_sum->max_length, maybe_null,
- item->name,table,item_sum->decimals);
+ item->name,table,item_sum->decimals);
case Item_sum::UNIQUE_USERS_FUNC:
return new Field_long(9,maybe_null,item->name,table,1);
default:
@@ -7492,9 +7512,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))
@@ -7534,7 +7553,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)
@@ -7592,9 +7613,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))))
@@ -7650,6 +7671,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");
@@ -7680,6 +7702,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)
{
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index fb457ea28a1..1ecb5e817d7 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -60,6 +60,7 @@ mysqld_show_dbs(THD *thd,const char *wild)
char *end;
List<char> files;
char *file_name;
+ Protocol *protocol= thd->protocol;
DBUG_ENTER("mysqld_show_dbs");
field->name=(char*) thd->alloc(20+ (wild ? (uint) strlen(wild)+4: 0));
@@ -69,13 +70,12 @@ mysqld_show_dbs(THD *thd,const char *wild)
strxmov(end," (",wild,")",NullS);
field_list.push_back(field);
- if (send_fields(thd,field_list,1))
+ if (protocol->send_fields(&field_list,1))
DBUG_RETURN(1);
if (mysql_find_files(thd,&files,NullS,mysql_data_home,wild,1))
DBUG_RETURN(1);
List_iterator_fast<char> it(files);
- String *packet= &thd->packet;
while ((file_name=it++))
{
if (thd->master_access & (DB_ACLS | SHOW_DB_ACL) ||
@@ -83,10 +83,9 @@ mysqld_show_dbs(THD *thd,const char *wild)
thd->priv_user, file_name) ||
(grant_option && !check_grant_db(thd, file_name)))
{
- packet->length(0);
- net_store_data(packet, thd->variables.convert_set, file_name);
- if (SEND_ROW(thd, field_list.elements,
- (char *)packet->ptr(), packet->length()))
+ protocol->prepare_for_resend();
+ protocol->store(file_name);
+ if (protocol->write())
DBUG_RETURN(-1);
}
}
@@ -103,30 +102,28 @@ int mysqld_show_open_tables(THD *thd,const char *wild)
{
List<Item> field_list;
OPEN_TABLE_LIST *open_list;
- CONVERT *convert=thd->variables.convert_set;
+ Protocol *protocol= thd->protocol;
DBUG_ENTER("mysqld_show_open_tables");
field_list.push_back(new Item_empty_string("Database",NAME_LEN));
field_list.push_back(new Item_empty_string("Table",NAME_LEN));
- field_list.push_back(new Item_int("In_use",0, 4));
- field_list.push_back(new Item_int("Name_locked",0, 4));
+ field_list.push_back(new Item_return_int("In_use", 1, MYSQL_TYPE_TINY));
+ field_list.push_back(new Item_return_int("Name_locked", 4, MYSQL_TYPE_TINY));
- if (send_fields(thd,field_list,1))
+ if (protocol->send_fields(&field_list,1))
DBUG_RETURN(1);
if (!(open_list=list_open_tables(thd,wild)) && thd->fatal_error)
DBUG_RETURN(-1);
- String *packet= &thd->packet;
for (; open_list ; open_list=open_list->next)
{
- packet->length(0);
- net_store_data(packet,convert, open_list->db);
- net_store_data(packet,convert, open_list->table);
- net_store_data(packet,open_list->in_use);
- net_store_data(packet,open_list->locked);
- if (SEND_ROW(thd, field_list.elements,
- (char *)packet->ptr(), packet->length()))
+ protocol->prepare_for_resend();
+ protocol->store(open_list->db);
+ protocol->store(open_list->table);
+ protocol->store_tiny((longlong) open_list->in_use);
+ protocol->store_tiny((longlong) open_list->locked);
+ if (protocol->write())
{
DBUG_RETURN(-1);
}
@@ -148,9 +145,11 @@ int mysqld_show_tables(THD *thd,const char *db,const char *wild)
char path[FN_LEN],*end;
List<char> files;
char *file_name;
+ Protocol *protocol= thd->protocol;
DBUG_ENTER("mysqld_show_tables");
- field->name=(char*) thd->alloc(20+(uint) strlen(db)+(wild ? (uint) strlen(wild)+4:0));
+ field->name=(char*) thd->alloc(20+(uint) strlen(db)+
+ (wild ? (uint) strlen(wild)+4:0));
end=strxmov(field->name,"Tables_in_",db,NullS);
if (wild && wild[0])
strxmov(end," (",wild,")",NullS);
@@ -158,18 +157,16 @@ int mysqld_show_tables(THD *thd,const char *db,const char *wild)
(void) sprintf(path,"%s/%s",mysql_data_home,db);
(void) unpack_dirname(path,path);
field_list.push_back(field);
- if (send_fields(thd,field_list,1))
+ if (protocol->send_fields(&field_list,1))
DBUG_RETURN(1);
if (mysql_find_files(thd,&files,db,path,wild,0))
DBUG_RETURN(-1);
List_iterator_fast<char> it(files);
- String *packet= &thd->packet;
while ((file_name=it++))
{
- packet->length(0);
- net_store_data(packet, thd->variables.convert_set, file_name);
- if (SEND_ROW(thd, field_list.elements,
- (char *)packet->ptr(), packet->length()))
+ protocol->prepare_for_resend();
+ protocol->store(file_name);
+ if (protocol->write())
DBUG_RETURN(-1);
}
send_eof(thd);
@@ -210,31 +207,32 @@ static struct show_table_type_st sys_table_types[]=
int mysqld_show_table_types(THD *thd)
{
List<Item> field_list;
+ Protocol *protocol= thd->protocol;
DBUG_ENTER("mysqld_show_table_types");
field_list.push_back(new Item_empty_string("Type",10));
field_list.push_back(new Item_empty_string("Support",10));
field_list.push_back(new Item_empty_string("Comment",80));
- if (send_fields(thd,field_list,1))
+ if (protocol->send_fields(&field_list,1))
DBUG_RETURN(1);
- const char *default_type_name= ha_table_typelib.type_names[thd->variables.table_type];
+ const char *default_type_name=
+ ha_table_typelib.type_names[thd->variables.table_type];
show_table_type_st *types;
- String *packet= &thd->packet;
for (types= sys_table_types; types->type; types++)
{
- packet->length(0);
- net_store_data(packet, types->type);
+ protocol->prepare_for_resend();
+ protocol->store(types->type);
const char *option_name= show_comp_option_name[(int) *types->value];
if (*types->value == SHOW_OPTION_YES &&
!my_strcasecmp(system_charset_info, default_type_name, types->type))
option_name= "DEFAULT";
- net_store_data(packet, option_name);
- net_store_data(packet, types->comment);
- if (SEND_ROW(thd, field_list.elements, (char*) packet->ptr(), packet->length()))
+ protocol->store(option_name);
+ protocol->store(types->comment);
+ if (protocol->write())
DBUG_RETURN(-1);
}
send_eof(thd);
@@ -279,24 +277,24 @@ static struct show_privileges_st sys_privileges[]=
int mysqld_show_privileges(THD *thd)
{
List<Item> field_list;
+ Protocol *protocol= thd->protocol;
DBUG_ENTER("mysqld_show_privileges");
field_list.push_back(new Item_empty_string("Privilege",10));
field_list.push_back(new Item_empty_string("Context",15));
field_list.push_back(new Item_empty_string("Comment",NAME_LEN));
- if (send_fields(thd,field_list,1))
+ if (protocol->send_fields(&field_list,1))
DBUG_RETURN(1);
show_privileges_st *privilege= sys_privileges;
- String *packet= &thd->packet;
for (privilege= sys_privileges; privilege->privilege ; privilege++)
{
- packet->length(0);
- net_store_data(packet,privilege->privilege);
- net_store_data(packet,privilege->context);
- net_store_data(packet,privilege->comment);
- if (SEND_ROW(thd,field_list.elements,(char*) packet->ptr(),packet->length()))
+ protocol->prepare_for_resend();
+ protocol->store(privilege->privilege);
+ protocol->store(privilege->context);
+ protocol->store(privilege->comment);
+ if (protocol->write())
DBUG_RETURN(-1);
}
send_eof(thd);
@@ -343,14 +341,15 @@ static struct show_column_type_st sys_column_types[]=
int mysqld_show_column_types(THD *thd)
{
List<Item> field_list;
+ Protocol *protocol= thd->protocol;
DBUG_ENTER("mysqld_show_column_types");
field_list.push_back(new Item_empty_string("Type",30));
field_list.push_back(new Item_int("Size",(longlong) 1,21));
field_list.push_back(new Item_empty_string("Min_Value",20));
field_list.push_back(new Item_empty_string("Max_Value",20));
- field_list.push_back(new Item_int("Prec", 0,4));
- field_list.push_back(new Item_int("Scale", 0,4));
+ field_list.push_back(new Item_return_int("Prec", 4, MYSQL_TYPE_SHORT));
+ field_list.push_back(new Item_return_int("Scale", 4, MYSQL_TYPE_SHORT));
field_list.push_back(new Item_empty_string("Nullable",4));
field_list.push_back(new Item_empty_string("Auto_Increment",4));
field_list.push_back(new Item_empty_string("Unsigned",4));
@@ -360,29 +359,28 @@ int mysqld_show_column_types(THD *thd)
field_list.push_back(new Item_empty_string("Default",NAME_LEN));
field_list.push_back(new Item_empty_string("Comment",NAME_LEN));
- if (send_fields(thd,field_list,1))
+ if (protocol->send_fields(&field_list,1))
DBUG_RETURN(1);
/* TODO: Change the loop to not use 'i' */
- String *packet= &thd->packet;
for (uint i=0; i < sizeof(sys_column_types)/sizeof(sys_column_types[0]); i++)
{
- packet->length(0);
- net_store_data(packet,sys_column_types[i].type);
- net_store_data(packet,(longlong)sys_column_types[i].size);
- net_store_data(packet,sys_column_types[i].min_value);
- net_store_data(packet,sys_column_types[i].max_value);
- net_store_data(packet,(uint32)sys_column_types[i].precision);
- net_store_data(packet,(uint32)sys_column_types[i].scale);
- net_store_data(packet,sys_column_types[i].nullable);
- net_store_data(packet,sys_column_types[i].auto_increment);
- net_store_data(packet,sys_column_types[i].unsigned_attr);
- net_store_data(packet,sys_column_types[i].zerofill);
- net_store_data(packet,sys_column_types[i].searchable);
- net_store_data(packet,sys_column_types[i].case_sensitivity);
- net_store_data(packet,sys_column_types[i].default_value);
- net_store_data(packet,sys_column_types[i].comment);
- if (SEND_ROW(thd,field_list.elements,(char*) packet->ptr(),packet->length()))
+ protocol->prepare_for_resend();
+ protocol->store(sys_column_types[i].type);
+ protocol->store((ulonglong) sys_column_types[i].size);
+ protocol->store(sys_column_types[i].min_value);
+ protocol->store(sys_column_types[i].max_value);
+ protocol->store_short((longlong) sys_column_types[i].precision);
+ protocol->store_short((longlong) sys_column_types[i].scale);
+ protocol->store(sys_column_types[i].nullable);
+ protocol->store(sys_column_types[i].auto_increment);
+ protocol->store(sys_column_types[i].unsigned_attr);
+ protocol->store(sys_column_types[i].zerofill);
+ protocol->store(sys_column_types[i].searchable);
+ protocol->store(sys_column_types[i].case_sensitivity);
+ protocol->store(sys_column_types[i].default_value);
+ protocol->store(sys_column_types[i].comment);
+ if (protocol->write())
DBUG_RETURN(-1);
}
send_eof(thd);
@@ -477,8 +475,8 @@ int mysqld_extend_show_tables(THD *thd,const char *db,const char *wild)
char path[FN_LEN];
char *file_name;
TABLE *table;
- String *packet= &thd->packet;
- CONVERT *convert=thd->variables.convert_set;
+ Protocol *protocol= thd->protocol;
+ TIME time;
DBUG_ENTER("mysqld_extend_show_tables");
(void) sprintf(path,"%s/%s",mysql_data_home,db);
@@ -514,7 +512,7 @@ int mysqld_extend_show_tables(THD *thd,const char *db,const char *wild)
field_list.push_back(item=new Item_empty_string("Create_options",255));
item->maybe_null=1;
field_list.push_back(item=new Item_empty_string("Comment",80));
- if (send_fields(thd,field_list,1))
+ if (protocol->send_fields(&field_list,1))
DBUG_RETURN(1);
if (mysql_find_files(thd,&files,db,path,wild,0))
@@ -524,70 +522,74 @@ int mysqld_extend_show_tables(THD *thd,const char *db,const char *wild)
{
TABLE_LIST table_list;
bzero((char*) &table_list,sizeof(table_list));
- packet->length(0);
- net_store_data(packet,convert, file_name);
+ protocol->prepare_for_resend();
+ protocol->store(file_name);
table_list.db=(char*) db;
table_list.real_name= table_list.alias= file_name;
if (!(table = open_ltable(thd, &table_list, TL_READ)))
{
for (uint i=0 ; i < field_list.elements ; i++)
- net_store_null(packet);
- net_store_data(packet,convert, thd->net.last_error);
+ protocol->store_null();
+ protocol->store(thd->net.last_error);
thd->net.last_error[0]=0;
}
else
{
struct tm tm_tmp;
+ const char *str;
handler *file=table->file;
file->info(HA_STATUS_VARIABLE | HA_STATUS_TIME | HA_STATUS_NO_LOCK);
- net_store_data(packet, convert, file->table_type());
- net_store_data(packet, convert,
- (table->db_options_in_use & HA_OPTION_COMPRESS_RECORD) ?
- "Compressed" :
- (table->db_options_in_use & HA_OPTION_PACK_RECORD) ?
- "Dynamic" : "Fixed");
- net_store_data(packet, (longlong) file->records);
- net_store_data(packet, (uint32) file->mean_rec_length);
- net_store_data(packet, (longlong) file->data_file_length);
+ protocol->store(file->table_type());
+ str= ((table->db_options_in_use & HA_OPTION_COMPRESS_RECORD) ?
+ "Compressed" :
+ (table->db_options_in_use & HA_OPTION_PACK_RECORD) ?
+ "Dynamic" : "Fixed");
+ protocol->store(str);
+ protocol->store((ulonglong) file->records);
+ protocol->store((ulonglong) file->mean_rec_length);
+ protocol->store((ulonglong) file->data_file_length);
if (file->max_data_file_length)
- net_store_data(packet, (longlong) file->max_data_file_length);
+ protocol->store((ulonglong) file->max_data_file_length);
else
- net_store_null(packet);
- net_store_data(packet, (longlong) file->index_file_length);
- net_store_data(packet, (longlong) file->delete_length);
+ protocol->store_null();
+ protocol->store((ulonglong) file->index_file_length);
+ protocol->store((ulonglong) file->delete_length);
if (table->found_next_number_field)
{
table->next_number_field=table->found_next_number_field;
table->next_number_field->reset();
file->update_auto_increment();
- net_store_data(packet, table->next_number_field->val_int());
+ protocol->store(table->next_number_field->val_int());
table->next_number_field=0;
}
else
- net_store_null(packet);
+ protocol->store_null();
if (!file->create_time)
- net_store_null(packet);
+ protocol->store_null();
else
{
localtime_r(&file->create_time,&tm_tmp);
- net_store_data(packet, &tm_tmp);
+ localtime_to_TIME(&time, &tm_tmp);
+ protocol->store(&time);
}
if (!file->update_time)
- net_store_null(packet);
+ protocol->store_null();
else
{
localtime_r(&file->update_time,&tm_tmp);
- net_store_data(packet, &tm_tmp);
+ localtime_to_TIME(&time, &tm_tmp);
+ protocol->store(&time);
}
if (!file->check_time)
- net_store_null(packet);
+ protocol->store_null();
else
{
localtime_r(&file->check_time,&tm_tmp);
- net_store_data(packet, &tm_tmp);
+ localtime_to_TIME(&time, &tm_tmp);
+ protocol->store(&time);
}
- net_store_data(packet, convert, table->table_charset ?
- table->table_charset->name : "default");
+ str= (table->table_charset ? table->table_charset->name : "default");
+ protocol->store(str);
{
char option_buff[350],*ptr;
ptr=option_buff;
@@ -624,20 +626,19 @@ int mysqld_extend_show_tables(THD *thd,const char *db,const char *wild)
my_raid_type(file->raid_type), file->raid_chunks, file->raid_chunksize/RAID_BLOCK_SIZE);
ptr=strmov(ptr,buff);
}
- net_store_data(packet, convert, option_buff+1,
- (ptr == option_buff ? 0 : (uint) (ptr-option_buff)-1));
+ protocol->store(option_buff+1,
+ (ptr == option_buff ? 0 : (uint) (ptr-option_buff)-1));
}
{
char *comment=table->file->update_table_comment(table->comment);
- net_store_data(packet, comment);
+ protocol->store(comment);
if (comment != table->comment)
my_free(comment,MYF(0));
}
close_thread_tables(thd,0);
}
- if (SEND_ROW(thd, field_list.elements,
- (char *)packet->ptr(), packet->length()))
- DBUG_RETURN(-1);
+ if (protocol->write())
+ DBUG_RETURN(-1);
}
send_eof(thd);
DBUG_RETURN(0);
@@ -655,7 +656,7 @@ mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild,
handler *file;
char tmp[MAX_FIELD_WIDTH];
Item *item;
- CONVERT *convert=thd->variables.convert_set;
+ Protocol *protocol= thd->protocol;
DBUG_ENTER("mysqld_show_fields");
DBUG_PRINT("enter",("db: %s table: %s",table_list->db,
table_list->real_name));
@@ -691,7 +692,7 @@ mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild,
(void) my_net_write(&thd->net,tmp,(uint) (pos-tmp));
}
#endif
- if (send_fields(thd,field_list,0))
+ if (protocol->send_fields(&field_list,0))
DBUG_RETURN(1);
restore_record(table,2); // Get empty record
@@ -714,19 +715,19 @@ mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild,
uint col_access;
bool null_default_value=0;
- packet->length(0);
- net_store_data(packet,convert,field->field_name);
+ protocol->prepare_for_resend();
+ protocol->store(field->field_name);
field->sql_type(type);
- net_store_data(packet,convert,type.ptr(),type.length());
+ protocol->store(type.ptr(), type.length());
pos=(byte*) ((flags & NOT_NULL_FLAG) &&
field->type() != FIELD_TYPE_TIMESTAMP ?
"" : "YES");
- net_store_data(packet,convert,(const char*) pos);
+ protocol->store((const char*) pos);
pos=(byte*) ((field->flags & PRI_KEY_FLAG) ? "PRI" :
(field->flags & UNIQUE_KEY_FLAG) ? "UNI" :
(field->flags & MULTIPLE_KEY_FLAG) ? "MUL":"");
- net_store_data(packet,convert,(char*) pos);
+ protocol->store((char*) pos);
if (field->type() == FIELD_TYPE_TIMESTAMP ||
field->unireg_check == Field::NEXT_NUMBER)
@@ -735,17 +736,17 @@ mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild,
{ // Not null by default
type.set(tmp,sizeof(tmp),default_charset_info);
field->val_str(&type,&type);
- net_store_data(packet,convert,type.ptr(),type.length());
+ protocol->store(type.ptr(),type.length());
}
else if (field->maybe_null() || null_default_value)
- net_store_null(packet); // Null as default
+ protocol->store_null(); // Null as default
else
- net_store_data(packet,convert,tmp,0);
+ protocol->store("",0); // empty string
char *end=tmp;
if (field->unireg_check == Field::NEXT_NUMBER)
end=strmov(tmp,"auto_increment");
- net_store_data(packet,convert,tmp,(uint) (end-tmp));
+ protocol->store(tmp,(uint) (end-tmp));
if (verbose)
{
@@ -760,12 +761,11 @@ mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild,
end=strmov(end,grant_types.type_names[bitnr]);
}
}
- net_store_data(packet,convert, tmp+1,end == tmp ? 0 : (uint) (end-tmp-1));
- net_store_data(packet, field->comment.str,field->comment.length);
+ protocol->store(tmp+1,end == tmp ? 0 : (uint) (end-tmp-1));
+ protocol->store(field->comment.str, field->comment.length);
}
- if (SEND_ROW(thd, field_list.elements,
- (char *)packet->ptr(), packet->length()))
- DBUG_RETURN(-1);
+ if (protocol->write())
+ DBUG_RETURN(1);
}
}
}
@@ -778,7 +778,9 @@ int
mysqld_show_create(THD *thd, TABLE_LIST *table_list)
{
TABLE *table;
- CONVERT *convert=thd->variables.convert_set;
+ Protocol *protocol= thd->protocol;
+ char buff[2048];
+ String buffer(buff, sizeof(buff), system_charset_info);
DBUG_ENTER("mysqld_show_create");
DBUG_PRINT("enter",("db: %s table: %s",table_list->db,
table_list->real_name));
@@ -792,52 +794,18 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list)
List<Item> field_list;
field_list.push_back(new Item_empty_string("Table",NAME_LEN));
- field_list.push_back(new Item_empty_string("Create Table",1024));
+ field_list.push_back(new Item_empty_string("Create Table", MAX_BLOB_WIDTH));
- if (send_fields(thd,field_list,1))
+ if (protocol->send_fields(&field_list, 1))
+ DBUG_RETURN(1);
+ protocol->prepare_for_resend();
+ protocol->store(table->table_name);
+ buffer.length(0);
+ if (store_create_info(thd, table, &buffer))
+ DBUG_RETURN(-1);
+ protocol->store(buffer.ptr(), buffer.length());
+ if (protocol->write())
DBUG_RETURN(1);
-
- String *packet = &thd->packet;
- {
- packet->length(0);
- net_store_data(packet,convert, table->table_name);
- /*
- A hack - we need to reserve some space for the length before
- we know what it is - let's assume that the length of create table
- statement will fit into 3 bytes ( 16 MB max :-) )
- */
- ulong store_len_offset = packet->length();
- packet->length(store_len_offset + 4);
- if (store_create_info(thd, table, packet))
- DBUG_RETURN(-1);
- ulong create_len = packet->length() - store_len_offset - 4;
- /*
- Just in case somebody manages to create a table
- with *that* much stuff in the definition
- */
- if (create_len > 0x00ffffff) // better readable in HEX ...
- {
- /*
- Just in case somebody manages to create a table
- with *that* much stuff in the definition
- */
- DBUG_RETURN(1);
- }
-
- /*
- Now we have to store the length in three bytes, even if it would fit
- into fewer bytes, so we cannot use net_store_data() anymore,
- and do it ourselves
- */
- char* p = (char*)packet->ptr() + store_len_offset;
- *p++ = (char) 253; // The client the length is stored using 3-bytes
- int3store(p, create_len);
-
- // now we are in business :-)
- if (SEND_ROW(thd, field_list.elements,
- (char *)packet->ptr(), packet->length()))
- DBUG_RETURN(-1);
- }
send_eof(thd);
DBUG_RETURN(0);
}
@@ -846,18 +814,19 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list)
int
mysqld_show_logs(THD *thd)
{
+ List<Item> field_list;
+ Protocol *protocol= thd->protocol;
DBUG_ENTER("mysqld_show_logs");
- List<Item> field_list;
field_list.push_back(new Item_empty_string("File",FN_REFLEN));
field_list.push_back(new Item_empty_string("Type",10));
field_list.push_back(new Item_empty_string("Status",10));
- if (send_fields(thd,field_list,1))
+ if (protocol->send_fields(&field_list,1))
DBUG_RETURN(1);
#ifdef HAVE_BERKELEY_DB
- if (!berkeley_skip && berkeley_show_logs(thd))
+ if (!berkeley_skip && berkeley_show_logs(protocol))
DBUG_RETURN(-1);
#endif
@@ -871,7 +840,7 @@ mysqld_show_keys(THD *thd, TABLE_LIST *table_list)
{
TABLE *table;
char buff[256];
- CONVERT *convert=thd->variables.convert_set;
+ Protocol *protocol= thd->protocol;
DBUG_ENTER("mysqld_show_keys");
DBUG_PRINT("enter",("db: %s table: %s",table_list->db,
table_list->real_name));
@@ -885,15 +854,16 @@ mysqld_show_keys(THD *thd, TABLE_LIST *table_list)
List<Item> field_list;
Item *item;
field_list.push_back(new Item_empty_string("Table",NAME_LEN));
- field_list.push_back(new Item_int("Non_unique",0,1));
+ field_list.push_back(new Item_return_int("Non_unique",1, MYSQL_TYPE_TINY));
field_list.push_back(new Item_empty_string("Key_name",NAME_LEN));
- field_list.push_back(new Item_int("Seq_in_index",0,2));
+ field_list.push_back(new Item_return_int("Seq_in_index",2, MYSQL_TYPE_TINY));
field_list.push_back(new Item_empty_string("Column_name",NAME_LEN));
field_list.push_back(item=new Item_empty_string("Collation",1));
item->maybe_null=1;
field_list.push_back(item=new Item_int("Cardinality",0,21));
item->maybe_null=1;
- field_list.push_back(item=new Item_int("Sub_part",0,3));
+ field_list.push_back(item=new Item_return_int("Sub_part",3,
+ MYSQL_TYPE_TINY));
item->maybe_null=1;
field_list.push_back(item=new Item_empty_string("Packed",10));
item->maybe_null=1;
@@ -902,7 +872,7 @@ mysqld_show_keys(THD *thd, TABLE_LIST *table_list)
field_list.push_back(new Item_empty_string("Comment",255));
item->maybe_null=1;
- if (send_fields(thd,field_list,1))
+ if (protocol->send_fields(&field_list,1))
DBUG_RETURN(1);
String *packet= &thd->packet;
@@ -911,56 +881,49 @@ mysqld_show_keys(THD *thd, TABLE_LIST *table_list)
for (uint i=0 ; i < table->keys ; i++,key_info++)
{
KEY_PART_INFO *key_part= key_info->key_part;
- char *end;
+ const char *str;
for (uint j=0 ; j < key_info->key_parts ; j++,key_part++)
{
- packet->length(0);
- net_store_data(packet,convert,table->table_name);
- net_store_data(packet,convert,((key_info->flags & HA_NOSAME) ? "0" :"1"), 1);
- net_store_data(packet,convert,key_info->name);
- end=int10_to_str((long) (j+1),(char*) buff,10);
- net_store_data(packet,convert,buff,(uint) (end-buff));
- net_store_data(packet,convert,
- key_part->field ? key_part->field->field_name :
- "?unknown field?");
+ protocol->prepare_for_resend();
+ protocol->store(table->table_name);
+ protocol->store_tiny((longlong) ((key_info->flags & HA_NOSAME) ? 0 :1));
+ protocol->store(key_info->name);
+ protocol->store_tiny((longlong) (j+1));
+ str=(key_part->field ? key_part->field->field_name :
+ "?unknown field?");
+ protocol->store(str);
if (table->file->index_flags(i) & HA_READ_ORDER)
- net_store_data(packet,convert,
- ((key_part->key_part_flag & HA_REVERSE_SORT) ?
- "D" : "A"), 1);
+ protocol->store(((key_part->key_part_flag & HA_REVERSE_SORT) ?
+ "D" : "A"), 1);
else
- net_store_null(packet); /* purecov: inspected */
+ protocol->store_null(); /* purecov: inspected */
KEY *key=table->key_info+i;
if (key->rec_per_key[j])
{
ha_rows records=(table->file->records / key->rec_per_key[j]);
- end=longlong10_to_str((longlong) records, buff, 10);
- net_store_data(packet,convert,buff,(uint) (end-buff));
+ protocol->store((ulonglong) records);
}
else
- net_store_null(packet);
+ protocol->store_null();
/* Check if we have a key part that only uses part of the field */
if (!key_part->field ||
key_part->length !=
table->field[key_part->fieldnr-1]->key_length())
- {
- end=int10_to_str((long) key_part->length, buff,10); /* purecov: inspected */
- net_store_data(packet,convert,buff,(uint) (end-buff)); /* purecov: inspected */
- }
+ protocol->store_tiny((longlong) key_part->length);
else
- net_store_null(packet);
- net_store_null(packet); // No pack_information yet
+ protocol->store_null();
+ protocol->store_null(); // No pack_information yet
/* Null flag */
uint flags= key_part->field ? key_part->field->flags : 0;
char *pos=(char*) ((flags & NOT_NULL_FLAG) ? "" : "YES");
- net_store_data(packet,convert,(const char*) pos);
- net_store_data(packet,convert,table->file->index_type(i));
+ protocol->store((const char*) pos);
+ protocol->store(table->file->index_type(i));
/* Comment */
- net_store_data(packet,convert,"");
- if (SEND_ROW(thd, field_list.elements,
- (char *)packet->ptr(), packet->length()))
- DBUG_RETURN(-1);
+ protocol->store("", 0);
+ if (protocol->write())
+ DBUG_RETURN(1); /* purecov: inspected */
}
}
send_eof(thd);
@@ -995,7 +958,7 @@ mysqld_list_fields(THD *thd, TABLE_LIST *table_list, const char *wild)
field_list.push_back(new Item_field(field));
}
restore_record(table,2); // Get empty record
- if (send_fields(thd,field_list,2))
+ if (thd->protocol->send_fields(&field_list,2))
DBUG_VOID_RETURN;
#ifndef EMBEDDED_LIBRARY
VOID(net_flush(&thd->net));
@@ -1007,21 +970,21 @@ mysqld_list_fields(THD *thd, TABLE_LIST *table_list, const char *wild)
int
mysqld_dump_create_info(THD *thd, TABLE *table, int fd)
{
- CONVERT *convert=thd->variables.convert_set;
+ Protocol *protocol= thd->protocol;
+ String *packet= protocol->storage_packet();
DBUG_ENTER("mysqld_dump_create_info");
DBUG_PRINT("enter",("table: %s",table->real_name));
- String *packet = &thd->packet;
- packet->length(0);
- if (store_create_info(thd,table,packet))
+ protocol->prepare_for_resend();
+ if (store_create_info(thd, table, packet))
DBUG_RETURN(-1);
- if (convert)
- convert->convert((char*) packet->ptr(), packet->length());
#ifndef EMBEDDED_LIBRARY
+ if (protocol->convert)
+ protocol->convert->convert((char*) packet->ptr(), packet->length());
if (fd < 0)
{
- if (my_net_write(&thd->net, (char*)packet->ptr(), packet->length()))
+ if (protocol->write())
DBUG_RETURN(-1);
VOID(net_flush(&thd->net));
}
@@ -1285,21 +1248,21 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose)
I_List<thread_info> thread_infos;
ulong max_query_length= (verbose ? thd->variables.max_allowed_packet :
PROCESS_LIST_WIDTH);
- CONVERT *convert=thd->variables.convert_set;
+ Protocol *protocol= thd->protocol;
DBUG_ENTER("mysqld_list_processes");
- field_list.push_back(new Item_int("Id",0,7));
+ field_list.push_back(new Item_int("Id",0,11));
field_list.push_back(new Item_empty_string("User",16));
field_list.push_back(new Item_empty_string("Host",64));
field_list.push_back(field=new Item_empty_string("db",NAME_LEN));
field->maybe_null=1;
field_list.push_back(new Item_empty_string("Command",16));
- field_list.push_back(new Item_empty_string("Time",7));
+ field_list.push_back(new Item_return_int("Time",7, FIELD_TYPE_LONG));
field_list.push_back(field=new Item_empty_string("State",30));
field->maybe_null=1;
field_list.push_back(field=new Item_empty_string("Info",max_query_length));
field->maybe_null=1;
- if (send_fields(thd,field_list,1))
+ if (protocol->send_fields(&field_list,1))
DBUG_VOID_RETURN;
VOID(pthread_mutex_lock(&LOCK_thread_count)); // For unlink from list
@@ -1365,39 +1328,27 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose)
VOID(pthread_mutex_unlock(&LOCK_thread_count));
thread_info *thd_info;
- String *packet= &thd->packet;
+ time_t now= time(0);
while ((thd_info=thread_infos.get()))
{
char buff[20],*end;
- packet->length(0);
- end=int10_to_str((long) thd_info->thread_id, buff,10);
- net_store_data(packet,convert,buff,(uint) (end-buff));
- net_store_data(packet,convert,thd_info->user);
- net_store_data(packet,convert,thd_info->host);
- if (thd_info->db)
- net_store_data(packet,convert,thd_info->db);
- else
- net_store_null(packet);
+ protocol->prepare_for_resend();
+ protocol->store((ulonglong) thd_info->thread_id);
+ protocol->store(thd_info->user);
+ protocol->store(thd_info->host);
+ protocol->store(thd_info->db);
if (thd_info->proc_info)
- net_store_data(packet,convert,thd_info->proc_info);
+ protocol->store(thd_info->proc_info);
else
- net_store_data(packet,convert,command_name[thd_info->command]);
+ protocol->store(command_name[thd_info->command]);
if (thd_info->start_time)
- net_store_data(packet,
- (uint32) (time((time_t*) 0) - thd_info->start_time));
- else
- net_store_null(packet);
- if (thd_info->state_info)
- net_store_data(packet,convert,thd_info->state_info);
+ protocol->store((uint32) (now - thd_info->start_time));
else
- net_store_null(packet);
- if (thd_info->query)
- net_store_data(packet,convert,thd_info->query);
- else
- net_store_null(packet);
- if (SEND_ROW(thd, field_list.elements,
- (char *)packet->ptr(), packet->length()))
- break;
+ protocol->store_null();
+ protocol->store(thd_info->state_info);
+ protocol->store(thd_info->query);
+ if (protocol->write())
+ break; /* purecov: inspected */
}
send_eof(thd);
DBUG_VOID_RETURN;
@@ -1418,16 +1369,16 @@ int mysqld_show_charsets(THD *thd, const char *wild)
char buff[8192];
String packet2(buff,sizeof(buff),default_charset_info);
List<Item> field_list;
- CONVERT *convert=thd->variables.convert_set;
CHARSET_INFO **cs;
+ Protocol *protocol= thd->protocol;
DBUG_ENTER("mysqld_show_charsets");
field_list.push_back(new Item_empty_string("Name",30));
- field_list.push_back(new Item_int("Id",0,7));
- field_list.push_back(new Item_int("strx_maxlen",0,7));
- field_list.push_back(new Item_int("mb_maxlen",0,7));
+ field_list.push_back(new Item_return_int("Id",11, FIELD_TYPE_SHORT));
+ field_list.push_back(new Item_return_int("strx_maxlen",3, FIELD_TYPE_TINY));
+ field_list.push_back(new Item_return_int("mb_maxlen",3, FIELD_TYPE_TINY));
- if (send_fields(thd,field_list,1))
+ if (protocol->send_fields(&field_list, 1))
DBUG_RETURN(1);
for (cs=all_charsets ; cs < all_charsets+255 ; cs++ )
@@ -1437,14 +1388,13 @@ int mysqld_show_charsets(THD *thd, const char *wild)
if (!(wild && wild[0] &&
wild_case_compare(system_charset_info,cs[0]->name,wild)))
{
- packet2.length(0);
- net_store_data(&packet2,convert,cs[0]->name);
- net_store_data(&packet2,(uint32) cs[0]->number);
- net_store_data(&packet2,(uint32) cs[0]->strxfrm_multiply);
- net_store_data(&packet2,(uint32) (cs[0]->mbmaxlen));
-
- if (SEND_ROW(thd, field_list.elements, (char*) packet2.ptr(),packet2.length()))
- goto err;
+ protocol->prepare_for_resend();
+ protocol->store(cs[0]->name);
+ protocol->store_short((longlong) cs[0]->number);
+ protocol->store_tiny((longlong) cs[0]->strxfrm_multiply);
+ protocol->store_tiny((longlong) cs[0]->mbmaxlen);
+ if (protocol->write())
+ goto err;
}
}
send_eof(thd);
@@ -1458,15 +1408,14 @@ err:
int mysqld_show(THD *thd, const char *wild, show_var_st *variables,
enum enum_var_type value_type)
{
- char buff[8192];
- String packet2(buff,sizeof(buff), system_charset_info);
+ char buff[1024];
List<Item> field_list;
- CONVERT *convert=thd->variables.convert_set;
+ Protocol *protocol= thd->protocol;
DBUG_ENTER("mysqld_show");
field_list.push_back(new Item_empty_string("Variable_name",30));
field_list.push_back(new Item_empty_string("Value",256));
- if (send_fields(thd,field_list,1))
+ if (protocol->send_fields(&field_list,1))
DBUG_RETURN(1); /* purecov: inspected */
/* pthread_mutex_lock(&THR_LOCK_keycache); */
@@ -1476,236 +1425,251 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables,
if (!(wild && wild[0] && wild_case_compare(system_charset_info,
variables->name,wild)))
{
- packet2.length(0);
- net_store_data(&packet2,convert,variables->name);
+ protocol->prepare_for_resend();
+ protocol->store(variables->name);
SHOW_TYPE show_type=variables->type;
char *value=variables->value;
+ const char *pos, *end;
+ long nr;
+
if (show_type == SHOW_SYS)
{
show_type= ((sys_var*) value)->type();
value= (char*) ((sys_var*) value)->value_ptr(thd, value_type);
}
+ pos= end= buff;
switch (show_type) {
case SHOW_LONG:
case SHOW_LONG_CONST:
- net_store_data(&packet2,(uint32) *(ulong*) value);
+ end= int10_to_str(*(long*) value, buff, 10);
break;
case SHOW_LONGLONG:
- net_store_data(&packet2,(longlong) *(longlong*) value);
+ end= longlong10_to_str(*(longlong*) value, buff, 10);
break;
case SHOW_BOOL:
- net_store_data(&packet2,(ulong) *(bool*) value ? "ON" : "OFF");
+ end= strmov(buff, *(bool*) value ? "ON" : "OFF");
break;
case SHOW_MY_BOOL:
- net_store_data(&packet2,(ulong) *(my_bool*) value ? "ON" : "OFF");
+ end= strmov(buff, *(my_bool*) value ? "ON" : "OFF");
break;
case SHOW_INT_CONST:
case SHOW_INT:
- net_store_data(&packet2,(uint32) *(int*) value);
+ end= int10_to_str((long) *(uint32*) value, buff, 10);
break;
case SHOW_HAVE:
{
SHOW_COMP_OPTION tmp= *(SHOW_COMP_OPTION*) value;
- net_store_data(&packet2, show_comp_option_name[(int) tmp]);
+ pos= show_comp_option_name[(int) tmp];
+ end= strend(pos);
break;
}
case SHOW_CHAR:
- net_store_data(&packet2,convert, value);
+ pos= value;
+ end= strend(pos);
break;
case SHOW_STARTTIME:
- net_store_data(&packet2,(uint32) (thd->query_start() - start_time));
+ nr= (long) (thd->query_start() - start_time);
+ end= int10_to_str(nr, buff, 10);
break;
case SHOW_QUESTION:
- net_store_data(&packet2,(uint32) thd->query_id);
+ end= int10_to_str((long) thd->query_id, buff, 10);
break;
#ifndef EMBEDDED_LIBRARY
case SHOW_RPL_STATUS:
- net_store_data(&packet2, rpl_status_type[(int)rpl_status]);
+ end= int10_to_str((long) rpl_status_type[(int)rpl_status], buff, 10);
break;
case SHOW_SLAVE_RUNNING:
{
LOCK_ACTIVE_MI;
- net_store_data(&packet2, (active_mi->slave_running &&
- active_mi->rli.slave_running)
- ? "ON" : "OFF");
+ end= strmov(buff, (active_mi->slave_running &&
+ active_mi->rli.slave_running) ? "ON" : "OFF");
UNLOCK_ACTIVE_MI;
break;
}
#endif /* EMBEDDED_LIBRARY */
case SHOW_OPENTABLES:
- net_store_data(&packet2,(uint32) cached_tables());
+ end= int10_to_str((long) cached_tables(), buff, 10);
break;
case SHOW_CHAR_PTR:
{
- value= *(char**) value;
- net_store_data(&packet2,convert, value ? value : "");
+ if (!(pos= *(char**) value))
+ pos= "";
+ end= strend(pos);
break;
}
#ifdef HAVE_OPENSSL
/* First group - functions relying on CTX */
case SHOW_SSL_CTX_SESS_ACCEPT:
- net_store_data(&packet2,(uint32)
- (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_accept(ssl_acceptor_fd->ssl_context_)));
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_accept(ssl_acceptor_fd->
+ ssl_context_)),
+ buff, 10);
break;
case SHOW_SSL_CTX_SESS_ACCEPT_GOOD:
- net_store_data(&packet2,(uint32)
- (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_accept_good(ssl_acceptor_fd->ssl_context_)));
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_accept_good(ssl_acceptor_fd->
+ ssl_context_)),
+ buff, 10);
break;
case SHOW_SSL_CTX_SESS_CONNECT_GOOD:
- net_store_data(&packet2,(uint32)
- (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_connect_good(ssl_acceptor_fd->ssl_context_)));
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_connect_good(ssl_acceptor_fd->
+ ssl_context_)),
+ buff, 10);
break;
case SHOW_SSL_CTX_SESS_ACCEPT_RENEGOTIATE:
- net_store_data(&packet2,(uint32)
- (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_accept_renegotiate(ssl_acceptor_fd->ssl_context_)));
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_accept_renegotiate(ssl_acceptor_fd->ssl_context_)),
+ buff, 10);
break;
case SHOW_SSL_CTX_SESS_CONNECT_RENEGOTIATE:
- net_store_data(&packet2,(uint32)
- (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_connect_renegotiate(ssl_acceptor_fd->ssl_context_)));
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_connect_renegotiate(ssl_acceptor_fd-> ssl_context_)),
+ buff, 10);
break;
case SHOW_SSL_CTX_SESS_CB_HITS:
- net_store_data(&packet2,(uint32)
- (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_cb_hits(ssl_acceptor_fd->ssl_context_)));
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_cb_hits(ssl_acceptor_fd->
+ ssl_context_)),
+ buff, 10);
break;
case SHOW_SSL_CTX_SESS_HITS:
- net_store_data(&packet2,(uint32)
- (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_hits(ssl_acceptor_fd->ssl_context_)));
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_hits(ssl_acceptor_fd->
+ ssl_context_)),
+ buff, 10);
break;
case SHOW_SSL_CTX_SESS_CACHE_FULL:
- net_store_data(&packet2,(uint32)
- (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_cache_full(ssl_acceptor_fd->ssl_context_)));
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_cache_full(ssl_acceptor_fd->
+ ssl_context_)),
+ buff, 10);
break;
case SHOW_SSL_CTX_SESS_MISSES:
- net_store_data(&packet2,(uint32)
- (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_misses(ssl_acceptor_fd->ssl_context_)));
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_misses(ssl_acceptor_fd->
+ ssl_context_)),
+ buff, 10);
break;
case SHOW_SSL_CTX_SESS_TIMEOUTS:
- net_store_data(&packet2,(uint32)
- (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_timeouts(ssl_acceptor_fd->ssl_context_)));
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_timeouts(ssl_acceptor_fd->ssl_context_)),
+ buff,10);
break;
case SHOW_SSL_CTX_SESS_NUMBER:
- net_store_data(&packet2,(uint32)
- (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_number(ssl_acceptor_fd->ssl_context_)));
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_number(ssl_acceptor_fd->ssl_context_)),
+ buff,10);
break;
case SHOW_SSL_CTX_SESS_CONNECT:
- net_store_data(&packet2,(uint32)
- (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_connect(ssl_acceptor_fd->ssl_context_)));
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_connect(ssl_acceptor_fd->ssl_context_)),
+ buff,10);
break;
case SHOW_SSL_CTX_SESS_GET_CACHE_SIZE:
- net_store_data(&packet2,(uint32)
- (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_get_cache_size(ssl_acceptor_fd->ssl_context_)));
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_get_cache_size(ssl_acceptor_fd->ssl_context_)),
+ buff,10);
break;
case SHOW_SSL_CTX_GET_VERIFY_MODE:
- net_store_data(&packet2,(uint32)
- (!ssl_acceptor_fd ? 0 :
- SSL_CTX_get_verify_mode(ssl_acceptor_fd->ssl_context_)));
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_get_verify_mode(ssl_acceptor_fd->ssl_context_)),
+ buff,10);
break;
case SHOW_SSL_CTX_GET_VERIFY_DEPTH:
- net_store_data(&packet2,(uint32)
- (!ssl_acceptor_fd ? 0 :
- SSL_CTX_get_verify_depth(ssl_acceptor_fd->ssl_context_)));
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_get_verify_depth(ssl_acceptor_fd->ssl_context_)),
+ buff,10);
break;
case SHOW_SSL_CTX_GET_SESSION_CACHE_MODE:
if (!ssl_acceptor_fd)
{
- net_store_data(&packet2,"NONE" );
+ pos= "NONE";
+ end= pos+4;
break;
}
switch (SSL_CTX_get_session_cache_mode(ssl_acceptor_fd->ssl_context_))
{
case SSL_SESS_CACHE_OFF:
- net_store_data(&packet2,"OFF" );
+ pos= "OFF";
break;
case SSL_SESS_CACHE_CLIENT:
- net_store_data(&packet2,"CLIENT" );
+ pos= "CLIENT";
break;
case SSL_SESS_CACHE_SERVER:
- net_store_data(&packet2,"SERVER" );
+ pos= "SERVER";
break;
case SSL_SESS_CACHE_BOTH:
- net_store_data(&packet2,"BOTH" );
+ pos= "BOTH";
break;
case SSL_SESS_CACHE_NO_AUTO_CLEAR:
- net_store_data(&packet2,"NO_AUTO_CLEAR" );
+ pos= "NO_AUTO_CLEAR";
break;
case SSL_SESS_CACHE_NO_INTERNAL_LOOKUP:
- net_store_data(&packet2,"NO_INTERNAL_LOOKUP" );
+ pos= "NO_INTERNAL_LOOKUP";
break;
default:
- net_store_data(&packet2,"Unknown");
+ pos= "Unknown";
break;
}
+ pos= strend(pos);
break;
/* First group - functions relying on SSL */
case SHOW_SSL_GET_VERSION:
- net_store_data(&packet2, thd->net.vio->ssl_ ?
- SSL_get_version(thd->net.vio->ssl_) : "");
+ pos= thd->net.vio->ssl_ ? SSL_get_version(thd->net.vio->ssl_) : "";
+ end= strend(pos);
break;
case SHOW_SSL_SESSION_REUSED:
- net_store_data(&packet2,(uint32) (thd->net.vio->ssl_ ?
- SSL_session_reused(thd->net.vio->ssl_) : 0));
+ end= int10_to_str((long) (thd->net.vio->ssl_ ?
+ SSL_session_reused(thd->net.vio->ssl_):
+ 0), buff, 10);
break;
case SHOW_SSL_GET_DEFAULT_TIMEOUT:
- net_store_data(&packet2,(uint32) (thd->net.vio->ssl_ ?
- SSL_get_default_timeout(thd->net.vio->ssl_):0));
+ end= int10_to_str((long) (thd->net.vio->ssl_ ?
+ SSL_get_default_timeout(thd->net.vio->ssl_):
+ 0), buff, 10);
break;
case SHOW_SSL_GET_VERIFY_MODE:
- net_store_data(&packet2,(uint32) (thd->net.vio->ssl_ ?
- SSL_get_verify_mode(thd->net.vio->ssl_):0));
+ end= int10_to_str((long) (thd->net.vio->ssl_ ?
+ SSL_get_verify_mode(thd->net.vio->ssl_):
+ 0), buff, 10);
break;
case SHOW_SSL_GET_VERIFY_DEPTH:
- net_store_data(&packet2,(uint32) (thd->net.vio->ssl_ ?
- SSL_get_verify_depth(thd->net.vio->ssl_):0));
+ end= int10_to_str((long) (thd->net.vio->ssl_ ?
+ SSL_get_verify_depth(thd->net.vio->ssl_):
+ 0), buff, 10);
break;
case SHOW_SSL_GET_CIPHER:
- net_store_data(&packet2, thd->net.vio->ssl_ ?
- SSL_get_cipher(thd->net.vio->ssl_) : "");
+ pos= thd->net.vio->ssl_ ? SSL_get_cipher(thd->net.vio->ssl_) : "";
+ end= strend(pos);
break;
case SHOW_SSL_GET_CIPHER_LIST:
if (thd->net.vio->ssl_)
{
- char buf[1024], *pos;
- pos=buf;
+ char *to= buff;
for (int i=0 ; i++ ;)
{
- const char *p=SSL_get_cipher_list(thd->net.vio->ssl_,i);
+ const char *p= SSL_get_cipher_list(thd->net.vio->ssl_,i);
if (p == NULL)
break;
- pos=strmov(pos, p);
- *pos++= ':';
+ to= strmov(to, p);
+ *to++= ':';
}
- if (pos != buf)
- pos--; // Remove last ':'
- *pos=0;
- net_store_data(&packet2, buf);
+ if (to != buff)
+ to--; // Remove last ':'
+ end= to;
}
- else
- net_store_data(&packet2, "");
break;
#endif /* HAVE_OPENSSL */
case SHOW_UNDEF: // Show never happen
case SHOW_SYS:
- net_store_data(&packet2, ""); // Safety
- break;
+ break; // Return empty string
}
- if (SEND_ROW(thd, field_list.elements,
- (char *)packet2.ptr(), packet2.length()))
- goto err;
+ if (protocol->store(pos, (uint32) (end - pos)) ||
+ protocol->write())
+ goto err; /* purecov: inspected */
}
}
pthread_mutex_unlock(&LOCK_status);
diff --git a/sql/sql_string.h b/sql/sql_string.h
index dde67b11d50..d7447dd6ed6 100644
--- a/sql/sql_string.h
+++ b/sql/sql_string.h
@@ -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;
+ }
};
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 3c643584785..49e84db62c9 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -1027,19 +1027,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 (SEND_ROW(thd, 4, (char*) thd->packet.ptr(), packet->length()))
+ if (protocol->write())
return -1;
return 1;
}
@@ -1185,8 +1184,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));
@@ -1197,7 +1196,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)
@@ -1213,7 +1212,8 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
thd->net.last_errno= 0; // these errors shouldn't get client
#endif
thd->open_options&= ~extra_open_options;
- packet->length(0);
+ protocol->prepare_for_resend();
+
if (prepare_func)
{
switch ((*prepare_func)(thd, table, check_opt)) {
@@ -1226,30 +1226,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 (SEND_ROW(thd, field_list.elements, (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 (SEND_ROW(thd, field_list.elements, (char*) thd->packet.ptr(),
- packet->length()))
+ if (protocol->write())
goto err;
continue;
}
@@ -1280,50 +1280,50 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
#ifdef EMBEDDED_LIBRARY
thd->net.last_errno= 0; // these errors shouldn't get client
#endif
- 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;
}
@@ -1340,8 +1340,7 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
}
close_thread_tables(thd);
table->table=0; // For query cache
- if (SEND_ROW(thd, field_list.elements,
- (char *)thd->packet.ptr(), thd->packet.length()))
+ if (protocol->write())
goto err;
}
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index 6e8c2ebdb5c..10175bfe345 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -24,10 +24,9 @@
#include "mysql_priv.h"
#include "sql_select.h"
-int mysql_union(THD *thd, LEX *lex, select_result *result)
+int mysql_union(THD *thd, LEX *lex, select_result *result,SELECT_LEX_UNIT *unit)
{
DBUG_ENTER("mysql_union");
- SELECT_LEX_UNIT *unit= &lex->unit;
int res= 0;
if (!(res= unit->prepare(thd, result)))
res= unit->exec();
@@ -125,6 +124,7 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result)
SELECT_LEX_NODE *lex_select_save= thd->lex.current_select;
SELECT_LEX *sl;
+ thd->lex.current_select=first_select();
/* Global option */
if (((void*)(global_parameters)) == ((void*)this))
{
@@ -216,7 +216,7 @@ int st_select_lex_unit::exec()
if (optimized && item && item->assigned())
{
item->assigned(0); // We will reinit & rexecute unit
- item->assign_null();
+ item->reset();
table->file->delete_all_rows();
}
for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index ed8e8f0fb51..8e947ec7587 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -100,6 +100,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token DIV_SYM
%token EQ
%token EQUAL_SYM
+%token SOUNDS_SYM
%token GE
%token GT_SYM
%token LE
@@ -158,6 +159,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token SQL_THREAD
%token START_SYM
%token STD_SYM
+%token VARIANCE_SYM
%token STOP_SYM
%token SUM_SYM
%token SUPER_SYM
@@ -1833,6 +1835,7 @@ expr_expr:
| expr OR expr { $$= new Item_cond_or($1,$3); }
| expr XOR expr { $$= new Item_cond_xor($1,$3); }
| expr AND expr { $$= new Item_cond_and($1,$3); }
+ | expr SOUNDS_SYM LIKE expr { $$= Item_bool_func2::eq_creator(new Item_func_soundex($1), new Item_func_soundex($4));}
| expr LIKE simple_expr opt_escape { $$= new Item_func_like($1,$3,$4); }
| expr NOT LIKE simple_expr opt_escape { $$= new Item_func_not(new Item_func_like($1,$4,$5));}
| expr REGEXP expr { $$= new Item_func_regex($1,$3); }
@@ -1879,6 +1882,7 @@ no_in_expr:
| no_in_expr OR expr { $$= new Item_cond_or($1,$3); }
| no_in_expr XOR expr { $$= new Item_cond_xor($1,$3); }
| no_in_expr AND expr { $$= new Item_cond_and($1,$3); }
+ | no_in_expr SOUNDS_SYM LIKE expr { $$= Item_bool_func2::eq_creator(new Item_func_soundex($1), new Item_func_soundex($4));}
| no_in_expr LIKE simple_expr opt_escape { $$= new Item_func_like($1,$3,$4); }
| no_in_expr NOT LIKE simple_expr opt_escape { $$= new Item_func_not(new Item_func_like($1,$4,$5)); }
| no_in_expr REGEXP expr { $$= new Item_func_regex($1,$3); }
@@ -1933,6 +1937,7 @@ no_and_expr:
| no_and_expr OR_OR_CONCAT expr { $$= or_or_concat(YYTHD, $1,$3); }
| no_and_expr OR expr { $$= new Item_cond_or($1,$3); }
| no_and_expr XOR expr { $$= new Item_cond_xor($1,$3); }
+ | no_and_expr SOUNDS_SYM LIKE expr { $$= Item_bool_func2::eq_creator(new Item_func_soundex($1), new Item_func_soundex($4));}
| no_and_expr LIKE simple_expr opt_escape { $$= new Item_func_like($1,$3,$4); }
| no_and_expr NOT LIKE simple_expr opt_escape { $$= new Item_func_not(new Item_func_like($1,$4,$5)); }
| no_and_expr REGEXP expr { $$= new Item_func_regex($1,$3); }
@@ -2335,6 +2340,8 @@ sum_expr:
{ $$=new Item_sum_max($3); }
| STD_SYM '(' in_sum_expr ')'
{ $$=new Item_sum_std($3); }
+ | VARIANCE_SYM '(' in_sum_expr ')'
+ { $$=new Item_sum_variance($3); }
| SUM_SYM '(' in_sum_expr ')'
{ $$=new Item_sum_sum($3); };
@@ -2504,7 +2511,7 @@ select_derived:
mysql_init_select(lex);
lex->current_select->linkage= DERIVED_TABLE_TYPE;
}
- select_options select_item_list opt_select_from
+ select_options select_item_list opt_select_from union_opt
;
opt_outer:
@@ -3870,6 +3877,7 @@ keyword:
| VALUE_SYM {}
| WORK_SYM {}
| YEAR_SYM {}
+ | SOUNDS_SYM {}
;
/* Option functions */
diff --git a/sql/structs.h b/sql/structs.h
index 7873de4db63..604be6fcc6e 100644
--- a/sql/structs.h
+++ b/sql/structs.h
@@ -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;
diff --git a/sql/time.cc b/sql/time.cc
index 0811b896bfc..282075df9eb 100644
--- a/sql/time.cc
+++ b/sql/time.cc
@@ -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;
+}
diff --git a/tests/fork_big2.pl b/tests/fork_big2.pl
new file mode 100644
index 00000000000..b552b95ba6b
--- /dev/null
+++ b/tests/fork_big2.pl
@@ -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;
+}