From ce3d8b93b95ae2387a5b34d0958f3045b6fa78ed Mon Sep 17 00:00:00 2001 From: "ramil@mysql.com" <> Date: Tue, 24 Jan 2006 13:58:28 +0400 Subject: [PATCH 01/20] Fix for bug #15756: incorrect ip address matching in ACL due to use of latin1 collation. Thanks Deomid Ryabkov for the great help! --- sql/hostname.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/hostname.cc b/sql/hostname.cc index 32e1d84fac3..32c4bb8533d 100644 --- a/sql/hostname.cc +++ b/sql/hostname.cc @@ -61,7 +61,7 @@ bool hostname_cache_init() if (!(hostname_cache=new hash_filo(HOST_CACHE_SIZE, offset, sizeof(struct in_addr),NULL, (hash_free_key) free, - &my_charset_latin1))) + &my_charset_bin))) return 1; hostname_cache->clear(); (void) pthread_mutex_init(&LOCK_hostname,MY_MUTEX_INIT_SLOW); From cfba31dd46d6e88c0c681db5484613fcd0a4367e Mon Sep 17 00:00:00 2001 From: "pem@mysql.com" <> Date: Wed, 15 Feb 2006 12:11:29 +0100 Subject: [PATCH 02/20] Fixed BUG#16887: Cursor causes server segfault The problem was a code generation bug: cpop instructions were not generated when using ITERATE back to an outer block from a context with a declared cursor; this would make it push a new cursor without popping in-between, eventually overrunning the cursor stack with a crash as the result. Fixed the calculation of how many cursors to pop (in sp_pcontext.cc: diff_cursors()), and also corrected diff_cursors() and diff_handlers() to when doing a "leave"; don't include the last context we're leaving (we are then jumping to the appropriate pop instructions). --- mysql-test/r/sp.result | 56 ++++++++++++++++++++++++++++++++++++++++++ mysql-test/t/sp.test | 54 ++++++++++++++++++++++++++++++++++++++++ sql/sp_pcontext.cc | 16 +++++++++--- sql/sp_pcontext.h | 10 +++++--- sql/sql_yacc.yy | 8 +++--- 5 files changed, 133 insertions(+), 11 deletions(-) diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index bec2f049bc4..e4168f67125 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -4519,4 +4519,60 @@ Handler Inner drop procedure bug15011| drop table t3| +drop table if exists t3| +drop procedure if exists bug16887| +create table t3 ( c varchar(1) )| +insert into t3 values +(' '),('.'),(';'),(','),('-'),('_'),('('),(')'),('/'),('\\')| +create procedure bug16887() +begin +declare i int default 10; +again: +while i > 0 do +begin +declare breakchar varchar(1); +declare done int default 0; +declare t3_cursor cursor for select c from t3; +declare continue handler for not found set done = 1; +set i = i - 1; +select i; +if i = 3 then +iterate again; +end if; +open t3_cursor; +loop +fetch t3_cursor into breakchar; +if done = 1 then +begin +close t3_cursor; +iterate again; +end; +end if; +end loop; +end; +end while; +end| +call bug16887()| +i +9 +i +8 +i +7 +i +6 +i +5 +i +4 +i +3 +i +2 +i +1 +i +0 +drop table t3| +drop procedure bug16887| drop table t1,t2; diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 53c15ffd05b..b86c39e3109 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -5311,6 +5311,60 @@ drop procedure bug15011| drop table t3| +# +# BUG#16887: Cursor causes server segfault +# +--disable_warnings +drop table if exists t3| +drop procedure if exists bug16887| +--enable_warnings + +create table t3 ( c varchar(1) )| + +insert into t3 values + (' '),('.'),(';'),(','),('-'),('_'),('('),(')'),('/'),('\\')| + +create procedure bug16887() +begin + declare i int default 10; + + again: + while i > 0 do + begin + declare breakchar varchar(1); + declare done int default 0; + declare t3_cursor cursor for select c from t3; + declare continue handler for not found set done = 1; + + set i = i - 1; + select i; + + if i = 3 then + iterate again; + end if; + + open t3_cursor; + + loop + fetch t3_cursor into breakchar; + + if done = 1 then + begin + close t3_cursor; + iterate again; + end; + end if; + end loop; + end; + end while; +end| + +call bug16887()| + +drop table t3| +drop procedure bug16887| + + # # BUG#NNNN: New bug synopsis # diff --git a/sql/sp_pcontext.cc b/sql/sp_pcontext.cc index a8bd8cd2aa0..f69053a7c88 100644 --- a/sql/sp_pcontext.cc +++ b/sql/sp_pcontext.cc @@ -122,30 +122,38 @@ sp_pcontext::pop_context() } uint -sp_pcontext::diff_handlers(sp_pcontext *ctx) +sp_pcontext::diff_handlers(sp_pcontext *ctx, bool exclusive) { uint n= 0; sp_pcontext *pctx= this; + sp_pcontext *last_ctx= NULL; while (pctx && pctx != ctx) { n+= pctx->m_handlers; + last_ctx= pctx; pctx= pctx->parent_context(); } if (pctx) - return n; + return (exclusive && last_ctx ? n - last_ctx->m_handlers : n); return 0; // Didn't find ctx } uint -sp_pcontext::diff_cursors(sp_pcontext *ctx) +sp_pcontext::diff_cursors(sp_pcontext *ctx, bool exclusive) { + uint n= 0; sp_pcontext *pctx= this; + sp_pcontext *last_ctx= NULL; while (pctx && pctx != ctx) + { + n+= pctx->m_cursor.elements; + last_ctx= pctx; pctx= pctx->parent_context(); + } if (pctx) - return ctx->current_cursors() - pctx->current_cursors(); + return (exclusive && last_ctx ? n - last_ctx->m_cursor.elements : n); return 0; // Didn't find ctx } diff --git a/sql/sp_pcontext.h b/sql/sp_pcontext.h index d1cd7b964c2..872c7c1d505 100644 --- a/sql/sp_pcontext.h +++ b/sql/sp_pcontext.h @@ -119,11 +119,15 @@ class sp_pcontext : public Sql_alloc return m_parent; } + /* + Number of handlers/cursors to pop between this context and 'ctx'. + If 'exclusive' is true, don't count the last block we are leaving; + this is used for LEAVE where we will jump to the cpop/hpop instructions. + */ uint - diff_handlers(sp_pcontext *ctx); - + diff_handlers(sp_pcontext *ctx, bool exclusive); uint - diff_cursors(sp_pcontext *ctx); + diff_cursors(sp_pcontext *ctx, bool exclusive); // diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 4f4ec5e92de..b68b822b1ac 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -2079,10 +2079,10 @@ sp_proc_stmt: uint ip= sp->instructions(); uint n; - n= ctx->diff_handlers(lab->ctx); + n= ctx->diff_handlers(lab->ctx, TRUE); /* Exclusive the dest. */ if (n) sp->add_instr(new sp_instr_hpop(ip++, ctx, n)); - n= ctx->diff_cursors(lab->ctx); + n= ctx->diff_cursors(lab->ctx, TRUE); /* Exclusive the dest. */ if (n) sp->add_instr(new sp_instr_cpop(ip++, ctx, n)); i= new sp_instr_jump(ip, ctx); @@ -2108,10 +2108,10 @@ sp_proc_stmt: uint ip= sp->instructions(); uint n; - n= ctx->diff_handlers(lab->ctx); + n= ctx->diff_handlers(lab->ctx, FALSE); /* Inclusive the dest. */ if (n) sp->add_instr(new sp_instr_hpop(ip++, ctx, n)); - n= ctx->diff_cursors(lab->ctx); + n= ctx->diff_cursors(lab->ctx, FALSE); /* Inclusive the dest. */ if (n) sp->add_instr(new sp_instr_cpop(ip++, ctx, n)); i= new sp_instr_jump(ip, ctx, lab->ip); /* Jump back */ From f2444c50fc45a509d3fce61323b272acac0b3aef Mon Sep 17 00:00:00 2001 From: "msvensson@devsrv-b.mysql.com" <> Date: Tue, 28 Feb 2006 11:17:40 +0100 Subject: [PATCH 03/20] Bug#17377 Federated Engine returns wrong Data, always the rows with the highest ID - Always make rnd_pos reposition the cursor in the fetched result set. --- mysql-test/r/federated.result | 43 +++++++++++++++++++++++++++ mysql-test/t/federated.test | 55 +++++++++++++++++++++++++++++++++++ sql/ha_federated.cc | 29 ++++++------------ sql/ha_federated.h | 1 - 4 files changed, 107 insertions(+), 21 deletions(-) diff --git a/mysql-test/r/federated.result b/mysql-test/r/federated.result index c1e7533bcee..f11da4ee62f 100644 --- a/mysql-test/r/federated.result +++ b/mysql-test/r/federated.result @@ -1558,6 +1558,49 @@ id 3 4 5 +DROP TABLE IF EXISTS federated.bug_17377_table; +CREATE TABLE federated.bug_17377_table ( +`fld_cid` bigint(20) NOT NULL auto_increment, +`fld_name` varchar(255) NOT NULL default '', +`fld_parentid` bigint(20) NOT NULL default '0', +`fld_delt` int(1) NOT NULL default '0', +PRIMARY KEY (`fld_cid`), +KEY `fld_parentid` (`fld_parentid`), +KEY `fld_delt` (`fld_delt`), +KEY `fld_cid` (`fld_cid`) +) ENGINE=MyISAM; +insert into federated.bug_17377_table( fld_name ) +values +("Mats"), ("Sivert"), ("Sigvard"), ("Torgny"), ("Torkel"); +DROP TABLE IF EXISTS federated.t1; +CREATE TABLE federated.t1 ( +`fld_cid` bigint(20) NOT NULL auto_increment, +`fld_name` varchar(255) NOT NULL default '', +`fld_parentid` bigint(20) NOT NULL default '0', +`fld_delt` int(1) NOT NULL default '0', +PRIMARY KEY (`fld_cid`), +KEY `fld_parentid` (`fld_parentid`), +KEY `fld_delt` (`fld_delt`), +KEY `fld_cid` (`fld_cid`) +) ENGINE=FEDERATED +CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/bug_17377_table'; +select * from federated.t1 where fld_parentid=0 and fld_delt=0 +order by fld_name; +fld_cid fld_name fld_parentid fld_delt +1 Mats 0 0 +3 Sigvard 0 0 +2 Sivert 0 0 +4 Torgny 0 0 +5 Torkel 0 0 +select * from federated.t1 where fld_parentid=0 and fld_delt=0; +fld_cid fld_name fld_parentid fld_delt +1 Mats 0 0 +2 Sivert 0 0 +3 Sigvard 0 0 +4 Torgny 0 0 +5 Torkel 0 0 +DROP TABLE federated.t1; +DROP TABLE federated.bug_17377_table; DROP TABLE IF EXISTS federated.t1; DROP DATABASE IF EXISTS federated; DROP TABLE IF EXISTS federated.t1; diff --git a/mysql-test/t/federated.test b/mysql-test/t/federated.test index d1e03f8a05a..80b31c610a2 100644 --- a/mysql-test/t/federated.test +++ b/mysql-test/t/federated.test @@ -1255,4 +1255,59 @@ INSERT INTO federated.t1 VALUES (); SELECT LAST_INSERT_ID(); SELECT * FROM federated.t1; +# +# Bug#17377 Federated Engine returns wrong Data, always the rows +# with the highest ID +# + +connection slave; + +--disable_warnings +DROP TABLE IF EXISTS federated.bug_17377_table; +--enable_warnings + +CREATE TABLE federated.bug_17377_table ( +`fld_cid` bigint(20) NOT NULL auto_increment, +`fld_name` varchar(255) NOT NULL default '', +`fld_parentid` bigint(20) NOT NULL default '0', +`fld_delt` int(1) NOT NULL default '0', +PRIMARY KEY (`fld_cid`), +KEY `fld_parentid` (`fld_parentid`), +KEY `fld_delt` (`fld_delt`), +KEY `fld_cid` (`fld_cid`) +) ENGINE=MyISAM; + +# Insert some test-data +insert into federated.bug_17377_table( fld_name ) +values +("Mats"), ("Sivert"), ("Sigvard"), ("Torgny"), ("Torkel"); + +connection master; +--disable_warnings +DROP TABLE IF EXISTS federated.t1; +--enable_warnings + +--replace_result $SLAVE_MYPORT SLAVE_PORT +eval CREATE TABLE federated.t1 ( +`fld_cid` bigint(20) NOT NULL auto_increment, +`fld_name` varchar(255) NOT NULL default '', +`fld_parentid` bigint(20) NOT NULL default '0', +`fld_delt` int(1) NOT NULL default '0', +PRIMARY KEY (`fld_cid`), +KEY `fld_parentid` (`fld_parentid`), +KEY `fld_delt` (`fld_delt`), +KEY `fld_cid` (`fld_cid`) +) ENGINE=FEDERATED +CONNECTION='mysql://root@127.0.0.1:$SLAVE_MYPORT/federated/bug_17377_table'; + +select * from federated.t1 where fld_parentid=0 and fld_delt=0 +order by fld_name; + +select * from federated.t1 where fld_parentid=0 and fld_delt=0; + +DROP TABLE federated.t1; +connection slave; +DROP TABLE federated.bug_17377_table; + + source include/federated_cleanup.inc; diff --git a/sql/ha_federated.cc b/sql/ha_federated.cc index af7c987e477..c6d5c77803b 100644 --- a/sql/ha_federated.cc +++ b/sql/ha_federated.cc @@ -740,7 +740,7 @@ error: ha_federated::ha_federated(TABLE *table_arg) :handler(&federated_hton, table_arg), - mysql(0), stored_result(0), scan_flag(0), + mysql(0), stored_result(0), ref_length(sizeof(MYSQL_ROW_OFFSET)), current_position(0) {} @@ -2243,7 +2243,7 @@ int ha_federated::rnd_init(bool scan) containing the correct record, hence update the wrong row! */ - scan_flag= scan; + if (scan) { DBUG_PRINT("info", ("share->select_query %s", share->select_query)); @@ -2365,24 +2365,13 @@ void ha_federated::position(const byte *record) int ha_federated::rnd_pos(byte *buf, byte *pos) { DBUG_ENTER("ha_federated::rnd_pos"); - /* - we do not need to do any of this if there has been a scan performed - already, or if this is an update and index_read_idx already has a result - set in which to build it's update query from - */ - if (scan_flag) - { - int retval; - statistic_increment(table->in_use->status_var.ha_read_rnd_count, - &LOCK_status); - memcpy_fixed(¤t_position, pos, sizeof(MYSQL_ROW_OFFSET)); // pos - /* is not aligned */ - stored_result->current_row= 0; - stored_result->data_cursor= current_position; - retval= rnd_next(buf); - DBUG_RETURN(retval); - } - DBUG_RETURN(0); + + statistic_increment(table->in_use->status_var.ha_read_rnd_count, + &LOCK_status); + memcpy_fixed(¤t_position, pos, sizeof(MYSQL_ROW_OFFSET)); + stored_result->current_row= 0; + stored_result->data_cursor= current_position; + DBUG_RETURN(rnd_next(buf)); } diff --git a/sql/ha_federated.h b/sql/ha_federated.h index 08203d7e51d..cafd1fe59a5 100644 --- a/sql/ha_federated.h +++ b/sql/ha_federated.h @@ -153,7 +153,6 @@ class ha_federated: public handler FEDERATED_SHARE *share; /* Shared lock info */ MYSQL *mysql; /* MySQL connection */ MYSQL_RES *stored_result; - bool scan_flag; uint ref_length; uint fetch_num; // stores the fetch num MYSQL_ROW_OFFSET current_position; // Current position used by ::position() From a6973ceed01a58765a6c00153046cb477a6da71a Mon Sep 17 00:00:00 2001 From: "bar@mysql.com" <> Date: Wed, 1 Mar 2006 17:58:01 +0400 Subject: [PATCH 04/20] Bug#15949 union + illegal mix of collations (IMPLICIT + COERCIBLE) union.result, union.test: Adding test case. item.cc: Allow safe character set conversion in UNION - string constant to column's charset - to unicode Thus, UNION now works the same with CONCAT (and other string functions) in respect of aggregating arguments with different character sets. --- mysql-test/r/union.result | 12 +++++++++++- mysql-test/t/union.test | 11 ++++++++++- sql/item.cc | 2 +- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result index a9b2345d834..d01ce6249f7 100644 --- a/mysql-test/r/union.result +++ b/mysql-test/r/union.result @@ -1185,6 +1185,16 @@ select concat('value is: ', @val) union select 'some text'; concat('value is: ', @val) value is: 6 some text +select concat(_latin1'a', _ascii'b' collate ascii_bin); +concat(_latin1'a', _ascii'b' collate ascii_bin) +ab +create table t1 (foo varchar(100)) collate ascii_bin; +insert into t1 (foo) values ("foo"); +select foo from t1 union select 'bar' as foo from dual; +foo +foo +bar +drop table t1; CREATE TABLE t1 ( a ENUM('ä','ö','ü') character set utf8 not null default 'ü', b ENUM("one", "two") character set utf8, @@ -1214,7 +1224,7 @@ Field Type Null Key Default Extra a char(1) drop table t2; create table t2 select a from t1 union select c from t1; -ERROR HY000: Illegal mix of collations (utf8_general_ci,IMPLICIT) and (latin1_swedish_ci,IMPLICIT) for operation 'UNION' +drop table t2; create table t2 select a from t1 union select b from t1; show columns from t2; Field Type Null Key Default Extra diff --git a/mysql-test/t/union.test b/mysql-test/t/union.test index 1f6fc2c8d3b..994546e9d97 100644 --- a/mysql-test/t/union.test +++ b/mysql-test/t/union.test @@ -710,6 +710,15 @@ drop table t1; set @val:=6; select concat('value is: ', @val) union select 'some text'; +# +# Bug#15949 union + illegal mix of collations (IMPLICIT + COERCIBLE) +# +select concat(_latin1'a', _ascii'b' collate ascii_bin); +create table t1 (foo varchar(100)) collate ascii_bin; +insert into t1 (foo) values ("foo"); +select foo from t1 union select 'bar' as foo from dual; +drop table t1; + # # Enum merging test # @@ -729,8 +738,8 @@ drop table t2; create table t2 select a from t1 union select a from t1; show columns from t2; drop table t2; --- error 1267 create table t2 select a from t1 union select c from t1; +drop table t2; create table t2 select a from t1 union select b from t1; show columns from t2; drop table t2, t1; diff --git a/sql/item.cc b/sql/item.cc index f996e962cca..5964ed388c6 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -3258,7 +3258,7 @@ bool Item_type_holder::join_types(THD *thd, Item *item) const char *old_cs, *old_derivation; old_cs= collation.collation->name; old_derivation= collation.derivation_name(); - if (collation.aggregate(item->collation)) + if (collation.aggregate(item->collation, MY_COLL_ALLOW_CONV)) { my_error(ER_CANT_AGGREGATE_2COLLATIONS, MYF(0), old_cs, old_derivation, From 103604ed06e8002f31b20bcd0f1d1ca97a6f43f8 Mon Sep 17 00:00:00 2001 From: "timour@mysql.com" <> Date: Thu, 2 Mar 2006 11:50:15 +0200 Subject: [PATCH 05/20] Fix for BUG#15229. The cause of this bug was a design flaw due to which the list of natural join columns was incorrectly computed and stored for nested joins that are not natural joins, but are operands (possibly indirect) of nested joins. The patch corrects the flaw in a such a way, that the result columns of a table reference are materialized only if it is a leaf table (that is, only if it is a view, stored table, or natural/using join). --- mysql-test/r/join.result | 47 +++++++++++++++++++++++++++ mysql-test/t/join.test | 41 +++++++++++++++++------- sql/sql_base.cc | 63 +++++++++++++++--------------------- sql/table.cc | 69 ++++++++++++++++++++++++++++++++++++---- sql/table.h | 2 +- 5 files changed, 166 insertions(+), 56 deletions(-) diff --git a/mysql-test/r/join.result b/mysql-test/r/join.result index 724d1b1e39f..bd86942072c 100644 --- a/mysql-test/r/join.result +++ b/mysql-test/r/join.result @@ -475,6 +475,22 @@ b c a c b y 1 10 2 3 1 2 1 3 2 3 1 11 1 3 2 3 1 2 +select * from t5 natural join ((t1 natural join t2), (t3 natural join t4)); +y z b c a c b +11 4 1 10 2 3 1 +11 4 1 3 2 3 1 +select * from ((t1 natural join t2), (t3 natural join t4)) natural join t5; +y b c a c b z +11 1 10 2 3 1 4 +11 1 3 2 3 1 4 +select * from t5 natural join ((t1 natural join t2) cross join (t3 natural join t4)); +y z b c a c b +11 4 1 10 2 3 1 +11 4 1 3 2 3 1 +select * from ((t1 natural join t2) cross join (t3 natural join t4)) natural join t5; +y b c a c b z +11 1 10 2 3 1 4 +11 1 3 2 3 1 4 select * from (t1 join t2 using (b)) join (t3 join t4 using (c)) using (c); c b a b y 3 1 2 1 11 @@ -665,6 +681,8 @@ select * from ((t1 natural join t2), (t3 natural join t4)) natural join t6; ERROR 23000: Column 'c' in from clause is ambiguous select * from ((t1 natural join t2), (t3 natural join t4)) natural join t6; ERROR 23000: Column 'c' in from clause is ambiguous +select * from t6 natural join ((t1 natural join t2), (t3 natural join t4)); +ERROR 23000: Column 'c' in from clause is ambiguous select * from (t1 join t2 on t1.b=t2.b) natural join (t3 natural join t4); ERROR 23000: Column 'b' in from clause is ambiguous select * from (t3 natural join t4) natural join (t1 join t2 on t1.b=t2.b); @@ -673,6 +691,8 @@ select * from (t3 join (t4 natural join t5) on (b < z)) natural join (t1 natural join t2); ERROR 23000: Column 'c' in from clause is ambiguous +select * from (t1 natural join t2) natural join (t3 join (t4 natural join t5) on (b < z)); +ERROR 23000: Column 'c' in from clause is ambiguous select t1.b from v1a; ERROR 42S22: Unknown column 't1.b' in 'field list' select * from v1a join v1b on t1.b = t2.b; @@ -692,3 +712,30 @@ drop view v2b; drop view v3a; drop view v3b; drop view v4; +create table t1 (a1 int, a2 int); +create table t2 (a1 int, b int); +create table t3 (c1 int, c2 int); +create table t4 (c2 int); +insert into t1 values (1,1); +insert into t2 values (1,1); +insert into t3 values (1,1); +insert into t4 values (1); +select * from t1 join t2 using (a1) join t3 on b=c1 join t4 using (c2); +c2 a1 a2 b c1 +1 1 1 1 1 +select * from t3 join (t1 join t2 using (a1)) on b=c1 join t4 using (c2); +c2 c1 a1 a2 b +1 1 1 1 1 +select a2 from t1 join t2 using (a1) join t3 on b=c1 join t4 using (c2); +a2 +1 +select a2 from t3 join (t1 join t2 using (a1)) on b=c1 join t4 using (c2); +a2 +1 +select a2 from ((t1 join t2 using (a1)) join t3 on b=c1) join t4 using (c2); +a2 +1 +select a2 from ((t1 natural join t2) join t3 on b=c1) natural join t4; +a2 +1 +drop table t1,t2,t3,t4; diff --git a/mysql-test/t/join.test b/mysql-test/t/join.test index 553aaf987bb..e58227df067 100644 --- a/mysql-test/t/join.test +++ b/mysql-test/t/join.test @@ -408,11 +408,10 @@ select * from t1 natural join (t2 natural join (t3 natural join t4)); select * from t5 natural right join (t4 natural right join ((t2 natural right join t1) natural right join t3)); select * from (t1 natural join t2), (t3 natural join t4); -- MySQL extension - nested comma ',' operator instead of cross join. --- BUG#15357 - natural join with nested cross-join results in incorrect columns --- select * from t5 natural join ((t1 natural join t2), (t3 natural join t4)); --- select * from ((t1 natural join t2), (t3 natural join t4)) natural join t5; --- select * from t5 natural join ((t1 natural join t2) cross join (t3 natural join t4)); --- select * from ((t1 natural join t2) cross join (t3 natural join t4)) natural join t5; +select * from t5 natural join ((t1 natural join t2), (t3 natural join t4)); +select * from ((t1 natural join t2), (t3 natural join t4)) natural join t5; +select * from t5 natural join ((t1 natural join t2) cross join (t3 natural join t4)); +select * from ((t1 natural join t2) cross join (t3 natural join t4)) natural join t5; select * from (t1 join t2 using (b)) join (t3 join t4 using (c)) using (c); select * from (t1 join t2 using (b)) natural join (t3 join t4 using (c)); @@ -500,8 +499,7 @@ select * from ((t1 natural join t2), (t3 natural join t4)) natural join t6; -- error 1052 select * from ((t1 natural join t2), (t3 natural join t4)) natural join t6; -- error 1052 --- BUG#15357: doesn't detect non-unique column 'c', as in the above query. --- select * from t6 natural join ((t1 natural join t2), (t3 natural join t4)); +select * from t6 natural join ((t1 natural join t2), (t3 natural join t4)); -- error 1052 select * from (t1 join t2 on t1.b=t2.b) natural join (t3 natural join t4); -- error 1052 @@ -512,11 +510,7 @@ select * from (t3 join (t4 natural join t5) on (b < z)) natural join (t1 natural join t2); -- error 1052 --- BUG#15357: this query should return an ambiguous column error --- Expected result: the query must return error with duplicate column 'c' ---select * from (t1 natural join t2) --- natural join --- (t3 join (t4 natural join t5) on (b < z)); +select * from (t1 natural join t2) natural join (t3 join (t4 natural join t5) on (b < z)); -- error 1054 select t1.b from v1a; @@ -540,4 +534,27 @@ drop view v3a; drop view v3b; drop view v4; +# +# BUG#15229 - columns of nested joins that are not natural joins incorrectly +# materialized +# +create table t1 (a1 int, a2 int); +create table t2 (a1 int, b int); +create table t3 (c1 int, c2 int); +create table t4 (c2 int); + +insert into t1 values (1,1); +insert into t2 values (1,1); +insert into t3 values (1,1); +insert into t4 values (1); + +select * from t1 join t2 using (a1) join t3 on b=c1 join t4 using (c2); +select * from t3 join (t1 join t2 using (a1)) on b=c1 join t4 using (c2); +select a2 from t1 join t2 using (a1) join t3 on b=c1 join t4 using (c2); +select a2 from t3 join (t1 join t2 using (a1)) on b=c1 join t4 using (c2); +select a2 from ((t1 join t2 using (a1)) join t3 on b=c1) join t4 using (c2); +select a2 from ((t1 natural join t2) join t3 on b=c1) natural join t4; + +drop table t1,t2,t3,t4; + # End of tests for WL#2486 - natural/using join diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 0e1c1525c9e..31ec95e3cc5 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -3608,8 +3608,18 @@ mark_common_columns(THD *thd, TABLE_LIST *table_ref_1, TABLE_LIST *table_ref_2, Natural_join_column *nj_col_1, *nj_col_2; const char *field_name_1; Query_arena *arena, backup; - bool add_columns= TRUE; bool result= TRUE; + bool first_outer_loop= TRUE; + /* + Leaf table references to which new natural join columns are added + if the leaves are != NULL. + */ + TABLE_LIST *leaf_1= (table_ref_1->nested_join && + !table_ref_1->is_natural_join) ? + NULL : table_ref_1; + TABLE_LIST *leaf_2= (table_ref_2->nested_join && + !table_ref_2->is_natural_join) ? + NULL : table_ref_2; DBUG_ENTER("mark_common_columns"); DBUG_PRINT("info", ("operand_1: %s operand_2: %s", @@ -3618,35 +3628,13 @@ mark_common_columns(THD *thd, TABLE_LIST *table_ref_1, TABLE_LIST *table_ref_2, *found_using_fields= 0; arena= thd->activate_stmt_arena_if_needed(&backup); - /* - TABLE_LIST::join_columns could be allocated by the previous call to - store_natural_using_join_columns() for the lower level of nested tables. - */ - if (!table_ref_1->join_columns) - { - if (!(table_ref_1->join_columns= new List)) - goto err; - table_ref_1->is_join_columns_complete= FALSE; - } - if (!table_ref_2->join_columns) - { - if (!(table_ref_2->join_columns= new List)) - goto err; - table_ref_2->is_join_columns_complete= FALSE; - } - for (it_1.set(table_ref_1); !it_1.end_of_fields(); it_1.next()) { - bool is_created_1; bool found= FALSE; - if (!(nj_col_1= it_1.get_or_create_column_ref(&is_created_1))) + if (!(nj_col_1= it_1.get_or_create_column_ref(leaf_1))) goto err; field_name_1= nj_col_1->name(); - /* If nj_col_1 was just created add it to the list of join columns. */ - if (is_created_1) - table_ref_1->join_columns->push_back(nj_col_1); - /* Find a field with the same name in table_ref_2. @@ -3657,17 +3645,12 @@ mark_common_columns(THD *thd, TABLE_LIST *table_ref_1, TABLE_LIST *table_ref_2, nj_col_2= NULL; for (it_2.set(table_ref_2); !it_2.end_of_fields(); it_2.next()) { - bool is_created_2; Natural_join_column *cur_nj_col_2; const char *cur_field_name_2; - if (!(cur_nj_col_2= it_2.get_or_create_column_ref(&is_created_2))) + if (!(cur_nj_col_2= it_2.get_or_create_column_ref(leaf_2))) goto err; cur_field_name_2= cur_nj_col_2->name(); - /* If nj_col_1 was just created add it to the list of join columns. */ - if (add_columns && is_created_2) - table_ref_2->join_columns->push_back(cur_nj_col_2); - /* Compare the two columns and check for duplicate common fields. A common field is duplicate either if it was already found in @@ -3686,9 +3669,15 @@ mark_common_columns(THD *thd, TABLE_LIST *table_ref_1, TABLE_LIST *table_ref_2, found= TRUE; } } - /* Force it_2.set() to use table_ref_2->join_columns. */ - table_ref_2->is_join_columns_complete= TRUE; - add_columns= FALSE; + if (first_outer_loop && leaf_2) + { + /* + Make sure that the next inner loop "knows" that all columns + are materialized already. + */ + leaf_2->is_join_columns_complete= TRUE; + first_outer_loop= FALSE; + } if (!found) continue; // No matching field @@ -3772,7 +3761,8 @@ mark_common_columns(THD *thd, TABLE_LIST *table_ref_1, TABLE_LIST *table_ref_2, ++(*found_using_fields); } } - table_ref_1->is_join_columns_complete= TRUE; + if (leaf_1) + leaf_1->is_join_columns_complete= TRUE; /* Everything is OK. @@ -4625,16 +4615,15 @@ insert_fields(THD *thd, Name_resolution_context *context, const char *db_name, if (tables->is_natural_join) { - bool is_created; TABLE *field_table; /* In this case we are sure that the column ref will not be created because it was already created and stored with the natural join. */ Natural_join_column *nj_col; - if (!(nj_col= field_iterator.get_or_create_column_ref(&is_created))) + if (!(nj_col= field_iterator.get_natural_column_ref())) DBUG_RETURN(TRUE); - DBUG_ASSERT(nj_col->table_field && !is_created); + DBUG_ASSERT(nj_col->table_field); field_table= nj_col->table_ref->table; if (field_table) { diff --git a/sql/table.cc b/sql/table.cc index 268d7a0be49..867ac4fb3bc 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -2816,11 +2816,31 @@ GRANT_INFO *Field_iterator_table_ref::grant() SYNOPSIS Field_iterator_table_ref::get_or_create_column_ref() - is_created [out] set to TRUE if the column was created, - FALSE if we return an already created colum + parent_table_ref the parent table reference over which the + iterator is iterating DESCRIPTION - TODO + Create a new natural join column for the current field of the + iterator if no such column was created, or return an already + created natural join column. The former happens for base tables or + views, and the latter for natural/using joins. If a new field is + created, then the field is added to 'parent_table_ref' if it is + given, or to the original table referene of the field if + parent_table_ref == NULL. + + NOTES + This method is designed so that when a Field_iterator_table_ref + walks through the fields of a table reference, all its fields + are created and stored as follows: + - If the table reference being iterated is a stored table, view or + natural/using join, store all natural join columns in a list + attached to that table reference. + - If the table reference being iterated is a nested join that is + not natural/using join, then do not materialize its result + fields. This is OK because for such table references + Field_iterator_table_ref iterates over the fields of the nested + table references (recursively). In this way we avoid the storage + of unnecessay copies of result columns of nested joins. RETURN # Pointer to a column of a natural join (or its operand) @@ -2828,22 +2848,28 @@ GRANT_INFO *Field_iterator_table_ref::grant() */ Natural_join_column * -Field_iterator_table_ref::get_or_create_column_ref(bool *is_created) +Field_iterator_table_ref::get_or_create_column_ref(TABLE_LIST *parent_table_ref) { Natural_join_column *nj_col; + bool is_created= TRUE; + uint field_count; + TABLE_LIST *add_table_ref= parent_table_ref ? + parent_table_ref : table_ref; - *is_created= TRUE; if (field_it == &table_field_it) { /* The field belongs to a stored table. */ Field *field= table_field_it.field(); nj_col= new Natural_join_column(field, table_ref); + field_count= table_ref->table->s->fields; } else if (field_it == &view_field_it) { /* The field belongs to a merge view or information schema table. */ Field_translator *translated_field= view_field_it.field_translator(); nj_col= new Natural_join_column(translated_field, table_ref); + field_count= table_ref->field_translation_end - + table_ref->field_translation; } else { @@ -2852,12 +2878,43 @@ Field_iterator_table_ref::get_or_create_column_ref(bool *is_created) already created via one of the two constructor calls above. In this case we just return the already created column reference. */ - *is_created= FALSE; + DBUG_ASSERT(table_ref->is_join_columns_complete); + is_created= FALSE; nj_col= natural_join_it.column_ref(); DBUG_ASSERT(nj_col); } DBUG_ASSERT(!nj_col->table_field || nj_col->table_ref->table == nj_col->table_field->table); + + /* + If the natural join column was just created add it to the list of + natural join columns of either 'parent_table_ref' or to the table + reference that directly contains the original field. + */ + if (is_created) + { + /* Make sure not all columns were materialized. */ + DBUG_ASSERT(!add_table_ref->is_join_columns_complete); + if (!add_table_ref->join_columns) + { + /* Create a list of natural join columns on demand. */ + if (!(add_table_ref->join_columns= new List)) + return NULL; + add_table_ref->is_join_columns_complete= FALSE; + } + add_table_ref->join_columns->push_back(nj_col); + /* + If new fields are added to their original table reference, mark if + all fields were added. We do it here as the caller has no easy way + of knowing when to do it. + If the fields are being added to parent_table_ref, then the caller + must take care to mark when all fields are created/added. + */ + if (!parent_table_ref && + add_table_ref->join_columns->elements == field_count) + add_table_ref->is_join_columns_complete= TRUE; + } + return nj_col; } diff --git a/sql/table.h b/sql/table.h index ce0616a6833..65afcac130e 100644 --- a/sql/table.h +++ b/sql/table.h @@ -782,7 +782,7 @@ public: GRANT_INFO *grant(); Item *create_item(THD *thd) { return field_it->create_item(thd); } Field *field() { return field_it->field(); } - Natural_join_column *get_or_create_column_ref(bool *is_created); + Natural_join_column *get_or_create_column_ref(TABLE_LIST *parent_table_ref); Natural_join_column *get_natural_column_ref(); }; From ff391e9fe189c8cc6a497cd1391d0a5b983747e7 Mon Sep 17 00:00:00 2001 From: "msvensson@neptunus.(none)" <> Date: Thu, 2 Mar 2006 11:08:43 +0100 Subject: [PATCH 06/20] Fix unsigned warning on windows --- client/mysqltest.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/mysqltest.c b/client/mysqltest.c index 0558df7a568..1a9f6f0d34f 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -3134,7 +3134,7 @@ static void init_win_path_patterns() static void free_win_path_patterns() { - int i= 0; + uint i= 0; for (i=0 ; i < patterns.elements ; i++) { const char** pattern= dynamic_element(&patterns, i, const char**); From e4b6f64a16240994c58a15eab12007d9650d2612 Mon Sep 17 00:00:00 2001 From: "msvensson@neptunus.(none)" <> Date: Thu, 2 Mar 2006 11:10:29 +0100 Subject: [PATCH 07/20] Make do_block return void, return value never used. --- client/mysqltest.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/mysqltest.c b/client/mysqltest.c index 1a9f6f0d34f..5dd2f5dc65e 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -2404,7 +2404,7 @@ int do_done(struct st_query *q) */ -int do_block(enum block_cmd cmd, struct st_query* q) +void do_block(enum block_cmd cmd, struct st_query* q) { char *p= q->first_argument; const char *expr_start, *expr_end; @@ -2428,7 +2428,7 @@ int do_block(enum block_cmd cmd, struct st_query* q) cur_block++; cur_block->cmd= cmd; cur_block->ok= FALSE; - return 0; + DBUG_VOID_RETURN; } /* Parse and evaluate test expression */ From 52d51e5e262a1c2ae148d03d91db9dd6a1ac089c Mon Sep 17 00:00:00 2001 From: "msvensson@neptunus.(none)" <> Date: Thu, 2 Mar 2006 16:28:45 +0100 Subject: [PATCH 08/20] Make the "system" command become executed in a bash shell in cygwin. --- client/mysqltest.c | 13 ++++++++++++- mysql-test/t/mysqldump.test | 4 ++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/client/mysqltest.c b/client/mysqltest.c index 5dd2f5dc65e..a039d970b18 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -1367,7 +1367,9 @@ int do_modify_var(struct st_query *query, const char *name, NOTE If mysqltest is executed from cygwin shell, the command will be - executed in cygwin shell. Thus commands like "rm" etc can be used. + executed in the "windows command interpreter" cmd.exe and we prepend "sh" + to make it be executed by cygwins "bash". Thus commands like "rm", + "mkdir" as well as shellscripts can executed by "system" in Windows. */ int do_system(struct st_query *command) @@ -1379,9 +1381,18 @@ int do_system(struct st_query *command) init_dynamic_string(&ds_cmd, 0, strlen(command->first_argument) + 64, 256); +#ifdef __WIN__ + /* Execute the command in "bash", ie. sh -c "" */ + dynstr_append(&ds_cmd, "sh -c \""); +#endif + /* Eval the system command, thus replacing all environment variables */ do_eval(&ds_cmd, command->first_argument, TRUE); +#ifdef __WIN__ + dynstr_append(&ds_cmd, "\""); +#endif + DBUG_PRINT("info", ("running system command '%s' as '%s'", command->first_argument, ds_cmd.str)); if (system(ds_cmd.str)) diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test index 9008eff6642..b5e05579023 100644 --- a/mysql-test/t/mysqldump.test +++ b/mysql-test/t/mysqldump.test @@ -830,8 +830,8 @@ DROP TABLE t1, t2; # Bugs #9136, #12917: problems with --defaults-extra-file option # ---system echo "[mysqltest1]" > $MYSQLTEST_VARDIR/tmp/tmp.cnf ---system echo "port=1234" >> $MYSQLTEST_VARDIR/tmp/tmp.cnf +--system echo '[mysqltest1]' > $MYSQLTEST_VARDIR/tmp/tmp.cnf +--system echo 'port=1234' >> $MYSQLTEST_VARDIR/tmp/tmp.cnf --exec $MYSQL_MY_PRINT_DEFAULTS -c $MYSQLTEST_VARDIR/tmp/tmp.cnf mysqltest1 --exec $MYSQL_MY_PRINT_DEFAULTS -e $MYSQLTEST_VARDIR/tmp/tmp.cnf mysqltest1 mysqltest1 --system rm $MYSQLTEST_VARDIR/tmp/tmp.cnf From f601d2696142787fc30982354a47aa62429998c5 Mon Sep 17 00:00:00 2001 From: "msvensson@neptunus.(none)" <> Date: Thu, 2 Mar 2006 17:33:34 +0100 Subject: [PATCH 09/20] Remove superfluous DBUG_PRINT --- client/mysqltest.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/client/mysqltest.c b/client/mysqltest.c index a039d970b18..12bcda267be 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -1120,8 +1120,6 @@ static void do_exec(struct st_query *query) ("error: %d, status: %d", error, status)); for (i= 0; i < query->expected_errors; i++) { - DBUG_PRINT("info", - ("error: %d, status: %d", error, status)); DBUG_PRINT("info", ("expected error: %d", query->expected_errno[i].code.errnum)); if ((query->expected_errno[i].type == ERR_ERRNO) && From f3e993d9a6371c6b32d336d30b1b58ca4b904e11 Mon Sep 17 00:00:00 2001 From: "gluh@eagle.intranet.mysql.r18.ru" <> Date: Fri, 3 Mar 2006 15:29:39 +0400 Subject: [PATCH 10/20] Fix for bug#17826 'type_decimal' fails with ps-protocol removed unnecessary calculation of cache value otherwise Join::preapre tries to calculate undefined values(filed values) --- mysql-test/r/type_decimal.result | 7 +++++++ mysql-test/t/type_decimal.test | 8 ++++++++ sql/item_cmpfunc.cc | 6 ------ 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/type_decimal.result b/mysql-test/r/type_decimal.result index d7f5f9fa328..8b2c08065e0 100644 --- a/mysql-test/r/type_decimal.result +++ b/mysql-test/r/type_decimal.result @@ -772,3 +772,10 @@ productid zlevelprice 003trans 39.98 004trans 31.18 drop table t1, t2; +create table t1 (f1 decimal(5)); +insert into t1 values (40); +flush tables; +select f1 from t1 where f1 in (select f1 from t1); +f1 +40 +drop table t1; diff --git a/mysql-test/t/type_decimal.test b/mysql-test/t/type_decimal.test index 07347322453..441d750004e 100644 --- a/mysql-test/t/type_decimal.test +++ b/mysql-test/t/type_decimal.test @@ -377,3 +377,11 @@ insert INTO t2 SELECT * FROM t1; select * from t2; drop table t1, t2; +# +# Bug #17826 'type_decimal' fails with ps-protocol +# +create table t1 (f1 decimal(5)); +insert into t1 values (40); +flush tables; +select f1 from t1 where f1 in (select f1 from t1); +drop table t1; diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 7ba8a536ac7..304e9e8babe 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -698,12 +698,6 @@ bool Item_in_optimizer::fix_left(THD *thd, Item **ref) return 1; cache->setup(args[0]); - /* - If it is preparation PS only then we do not know values of parameters => - cant't get there values and do not need that values. - */ - if (!thd->stmt_arena->is_stmt_prepare()) - cache->store(args[0]); if (cache->cols() == 1) { if ((used_tables_cache= args[0]->used_tables())) From 21cc7c9555ba37c058e1d9de42e86dff8cbd5848 Mon Sep 17 00:00:00 2001 From: "msvensson@neptunus.(none)" <> Date: Fri, 3 Mar 2006 14:55:05 +0100 Subject: [PATCH 11/20] Windows fixes - Use pipes "|" - Improved system command, create a temporary .sh faile that is executed with cygwins sh(bash) This makes the Windows version behave exactly as the Lunix version(well almost...) - Give unix path to DBUG, trace files is no produced if running ./mysql-test-run.pl --debug" --- client/mysqltest.c | 54 +++++++++++++++++++++++------------- mysql-test/lib/mtr_misc.pl | 11 +++++++- mysql-test/mysql-test-run.pl | 3 ++ 3 files changed, 48 insertions(+), 20 deletions(-) diff --git a/client/mysqltest.c b/client/mysqltest.c index 12bcda267be..3db51336553 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -1351,6 +1351,35 @@ int do_modify_var(struct st_query *query, const char *name, } +/* + Wrapper for 'system' function + + NOTE + If mysqltest is executed from cygwin shell, the command will be + executed in the "windows command interpreter" cmd.exe and we prepend "sh" + to make it be executed by cygwins "bash". Thus commands like "rm", + "mkdir" as well as shellscripts can executed by "system" in Windows. + +*/ + +int my_system(DYNAMIC_STRING* ds_cmd) +{ +#ifdef __WIN__ + /* Dump the command into a sh script file and execute with "sh" */ + int err; + char tmp_sh_name[64], tmp_sh_cmd[70]; + my_snprintf(tmp_sh_name, sizeof(tmp_sh_name), "tmp_%d.sh", getpid()); + my_snprintf(tmp_sh_cmd, sizeof(tmp_sh_cmd), "sh %s", tmp_sh_name); + str_to_file(tmp_sh_name, ds_cmd->str, ds_cmd->length); + err= system(tmp_sh_cmd); + my_delete(tmp_sh_name, MYF(0)); + return err; +#else + return system(ds_cmd->str); +#endif +} + + /* SYNOPSIS @@ -1363,37 +1392,24 @@ int do_modify_var(struct st_query *query, const char *name, Eval the query to expand any $variables in the command. Execute the command with the "system" command. - NOTE - If mysqltest is executed from cygwin shell, the command will be - executed in the "windows command interpreter" cmd.exe and we prepend "sh" - to make it be executed by cygwins "bash". Thus commands like "rm", - "mkdir" as well as shellscripts can executed by "system" in Windows. - */ +*/ -int do_system(struct st_query *command) +void do_system(struct st_query *command) { DYNAMIC_STRING ds_cmd; + DBUG_ENTER("do_system"); if (strlen(command->first_argument) == 0) die("Missing arguments to system, nothing to do!"); init_dynamic_string(&ds_cmd, 0, strlen(command->first_argument) + 64, 256); -#ifdef __WIN__ - /* Execute the command in "bash", ie. sh -c "" */ - dynstr_append(&ds_cmd, "sh -c \""); -#endif - /* Eval the system command, thus replacing all environment variables */ do_eval(&ds_cmd, command->first_argument, TRUE); -#ifdef __WIN__ - dynstr_append(&ds_cmd, "\""); -#endif - DBUG_PRINT("info", ("running system command '%s' as '%s'", command->first_argument, ds_cmd.str)); - if (system(ds_cmd.str)) + if (my_system(&ds_cmd)) { if (command->abort_on_error) die("system command '%s' failed", command->first_argument); @@ -1405,7 +1421,7 @@ int do_system(struct st_query *command) } command->last_argument= command->end; - return 0; + DBUG_VOID_RETURN; } @@ -1656,7 +1672,7 @@ int do_sleep(struct st_query *query, my_bool real_sleep) char *p= query->first_argument; char *sleep_start, *sleep_end= query->end; double sleep_val; - char *cmd = (real_sleep ? "real_sleep" : "sleep"); + const char *cmd = (real_sleep ? "real_sleep" : "sleep"); while (my_isspace(charset_info, *p)) p++; diff --git a/mysql-test/lib/mtr_misc.pl b/mysql-test/lib/mtr_misc.pl index a76f1b2d7b1..1f7ebdde457 100644 --- a/mysql-test/lib/mtr_misc.pl +++ b/mysql-test/lib/mtr_misc.pl @@ -96,7 +96,16 @@ sub mtr_exe_exists (@) { map {$_.= ".exe"} @path if $::glob_win32; foreach my $path ( @path ) { - return $path if -x $path; + if ( -x $path ) + { + if ( $::glob_cygwin_perl ) + { + $path= `cygpath -w $path`; + # Chop off the \n that cygpath adds + $path=~ s/\n//; + } + return $path; + } } if ( @path == 1 ) { diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 905a2b2af37..ce2dfc8f67e 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -668,6 +668,9 @@ sub command_line_setup () { $opt_vardir= "$glob_mysql_test_dir/var"; } $opt_vardir_trace= $opt_vardir; + # Chop off any "c:", DBUG likes a unix path ex: c:/src/... => /src/... + $opt_vardir_trace=~ s/^\w://; + # We make the path absolute, as the server will do a chdir() before usage unless ( $opt_vardir =~ m,^/, or ($glob_win32 and $opt_vardir =~ m,^[a-z]:/,i) ) From 2ffb679a27ba1125a739f96a3f07e1c90324b574 Mon Sep 17 00:00:00 2001 From: "kent@mysql.com" <> Date: Fri, 3 Mar 2006 20:30:28 +0100 Subject: [PATCH 12/20] mysql.spec.sh: Use installed libz.a to avoid hard to solve static linking problems --- support-files/mysql.spec.sh | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index 599f397e351..5860e612e66 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -369,8 +369,8 @@ BuildMySQL "--disable-shared \ --with-client-ldflags='-all-static' \ $USE_OTHER_LIBC_DIR \ %else -%endif --with-zlib-dir=bundled \ +%endif --with-comment=\"MySQL Community Edition - Standard (GPL)\" \ --with-server-suffix='%{server_suffix}' \ --with-archive-storage-engine \ @@ -690,8 +690,11 @@ fi %{_libdir}/mysql/libndbclient.a %{_libdir}/mysql/libndbclient.la %{_libdir}/mysql/libvio.a +%if %{STATIC_BUILD} +%else %{_libdir}/mysql/libz.a %{_libdir}/mysql/libz.la +%endif %files shared %defattr(-, root, root, 0755) @@ -723,6 +726,11 @@ fi * Fri Mar 03 2006 Kent Boortz - Don't output an embedded package as it is empty +- Can't use bundled zlib when doing static build. Might be a + automake/libtool problem, having two .la files, "libmysqlclient.la" + and "libz.la", on the same command line to link "thread_test" + expands to too many "-lc", "-lpthread" and other libs giving hard + to nail down duplicate symbol defintion problems. * Fri Jan 10 2006 Joerg Bruehe From 599c710a5b6323de1955638c274a86f2d7b12987 Mon Sep 17 00:00:00 2001 From: "cmiller@zippy.(none)" <> Date: Fri, 3 Mar 2006 16:26:38 -0500 Subject: [PATCH 13/20] Bug#16859 involves truncating column data at NUL characters. Instead, the client will now substitute spaces for NULs, so that the grid isn't messed up due to silently consumed NULs and that the full field is shown. --- client/mysql.cc | 55 +++++++++++++++++++++++++++++++++------ mysql-test/r/mysql.result | 7 +++++ mysql-test/t/mysql.test | 5 ++++ 3 files changed, 59 insertions(+), 8 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index 8d578aac58b..eb6970691bb 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -185,6 +185,7 @@ void tee_fprintf(FILE *file, const char *fmt, ...); void tee_fputs(const char *s, FILE *file); void tee_puts(const char *s, FILE *file); void tee_putc(int c, FILE *file); +static void tee_print_sized_data(const char *data, unsigned int length, unsigned int width); /* The names of functions that actually do the manipulation. */ static int get_options(int argc,char **argv); static int com_quit(String *str,char*), @@ -2308,20 +2309,29 @@ print_table_data(MYSQL_RES *result) for (uint off= 0; off < mysql_num_fields(result); off++) { const char *str= cur[off] ? cur[off] : "NULL"; + uint currlength; + uint maxlength; + uint numcells; + field= mysql_fetch_field(result); - uint maxlength= field->max_length; + maxlength= field->max_length; + currlength= (uint) lengths[off]; + numcells= charset_info->cset->numcells(charset_info, + str, str + currlength); if (maxlength > MAX_COLUMN_LENGTH) { - tee_fputs(str, PAGER); - tee_fputs(" |", PAGER); + tee_print_sized_data(str, currlength, maxlength); + tee_fputs(" |", PAGER); } else { - uint currlength= (uint) lengths[off]; - uint numcells= charset_info->cset->numcells(charset_info, - str, str + currlength); - tee_fprintf(PAGER, num_flag[off] ? "%*s |" : " %-*s|", - maxlength + currlength - numcells, str); + if (num_flag[off] != 0) + tee_fprintf(PAGER, " %-*s|", maxlength + currlength - numcells, str); + else + { + tee_print_sized_data(str, currlength, maxlength); + tee_fputs(" |", PAGER); + } } } (void) tee_fputs("\n", PAGER); @@ -2331,6 +2341,35 @@ print_table_data(MYSQL_RES *result) } +static void +tee_print_sized_data(const char *data, unsigned int length, unsigned int width) +{ + /* + It is not a number, so print each character justified to the left. + For '\0's print ASCII spaces instead, as '\0' is eaten by (at + least my) console driver, and that messes up the pretty table + grid. (The \0 is also the reason we can't use fprintf() .) + */ + unsigned int i; + const char *p; + + tee_putc(' ', PAGER); + + for (i= 0, p= data; i < length; i+= 1, p+= 1) + { + if (*p == '\0') + tee_putc((int)' ', PAGER); + else + tee_putc((int)*p, PAGER); + } + + i+= 1; + for ( ; i < width; i+= 1) + tee_putc((int)' ', PAGER); +} + + + static void print_table_data_html(MYSQL_RES *result) { diff --git a/mysql-test/r/mysql.result b/mysql-test/r/mysql.result index 611813d9c3f..57067bea36b 100644 --- a/mysql-test/r/mysql.result +++ b/mysql-test/r/mysql.result @@ -69,3 +69,10 @@ c_cp932 ソ ソ ソ ++----------------------+------------+--------+ +| concat('>',col1,'<') | col2 | col3 | ++----------------------+------------+--------+ +| >a < | b | 123421 | +| >a < | 0123456789 | 4 | +| >abcd< | | 4 | ++----------------------+------------+--------+ diff --git a/mysql-test/t/mysql.test b/mysql-test/t/mysql.test index 4712e7e8266..dbf65845e6a 100644 --- a/mysql-test/t/mysql.test +++ b/mysql-test/t/mysql.test @@ -56,3 +56,8 @@ drop table t1; --exec $MYSQL --default-character-set=utf8 test -e "charset cp932; set character_set_client= cp932; select 'ƒ\'" --exec $MYSQL --default-character-set=utf8 test -e "/*charset cp932 */; set character_set_client= cp932; select 'ƒ\'" --exec $MYSQL --default-character-set=utf8 test -e "/*!\C cp932 */; set character_set_client= cp932; select 'ƒ\'" + +# +# Bug#16859 -- NULLs in columns must not truncate data as if a C-language "string". +# +--exec $MYSQL -t test -e "create table t1 (col1 binary(4), col2 varchar(10), col3 int); insert into t1 values ('a', 'b', 123421),('a ', '0123456789', 4), ('abcd', '', 4); select concat('>',col1,'<'), col2, col3 from t1; drop table t1;" 2>&1 From efe090066980b3bed34535432cefc642b627f9dd Mon Sep 17 00:00:00 2001 From: "dlenev@mysql.com" <> Date: Sat, 4 Mar 2006 16:55:06 +0300 Subject: [PATCH 14/20] Fix for bug #17866 "Problem with renaming table with triggers with fully qualified subject table" which was introduced during work on bug #13525 "Rename table does not keep info of triggers". The bug was caused by the fact that during reconstruction of CREATE TRIGGER statement stored in .TRG file which happened during RENAME TABLE we damaged trigger definition in case when it contained fully qualified name of subject table (see comment for sql_yacc.yy for more info). --- mysql-test/r/trigger.result | 30 ++++++++++++++++++------------ mysql-test/t/trigger.test | 14 +++++++++----- sql/sql_trigger.cc | 1 + sql/sql_yacc.yy | 4 ++-- 4 files changed, 30 insertions(+), 19 deletions(-) diff --git a/mysql-test/r/trigger.result b/mysql-test/r/trigger.result index 320f4e5c3d9..c9a91758336 100644 --- a/mysql-test/r/trigger.result +++ b/mysql-test/r/trigger.result @@ -787,46 +787,52 @@ drop trigger t1_bi; ERROR 3D000: No database selected create table t1 (id int); create trigger t1_bi before insert on t1 for each row set @a:=new.id; +create trigger t1_ai after insert on test.t1 for each row set @b:=new.id; insert into t1 values (101); -select @a; -@a -101 +select @a, @b; +@a @b +101 101 select trigger_schema, trigger_name, event_object_schema, event_object_table, action_statement from information_schema.triggers where event_object_schema = 'test'; trigger_schema trigger_name event_object_schema event_object_table action_statement test t1_bi test t1 set @a:=new.id +test t1_ai test t1 set @b:=new.id rename table t1 to t2; insert into t2 values (102); -select @a; -@a -102 +select @a, @b; +@a @b +102 102 select trigger_schema, trigger_name, event_object_schema, event_object_table, action_statement from information_schema.triggers where event_object_schema = 'test'; trigger_schema trigger_name event_object_schema event_object_table action_statement test t1_bi test t2 set @a:=new.id +test t1_ai test t2 set @b:=new.id alter table t2 rename to t3; insert into t3 values (103); -select @a; -@a -103 +select @a, @b; +@a @b +103 103 select trigger_schema, trigger_name, event_object_schema, event_object_table, action_statement from information_schema.triggers where event_object_schema = 'test'; trigger_schema trigger_name event_object_schema event_object_table action_statement test t1_bi test t3 set @a:=new.id +test t1_ai test t3 set @b:=new.id alter table t3 rename to t4, add column val int default 0; insert into t4 values (104, 1); -select @a; -@a -104 +select @a, @b; +@a @b +104 104 select trigger_schema, trigger_name, event_object_schema, event_object_table, action_statement from information_schema.triggers where event_object_schema = 'test'; trigger_schema trigger_name event_object_schema event_object_table action_statement test t1_bi test t4 set @a:=new.id +test t1_ai test t4 set @b:=new.id drop trigger t1_bi; +drop trigger t1_ai; drop table t4; create database mysqltest; use mysqltest; diff --git a/mysql-test/t/trigger.test b/mysql-test/t/trigger.test index 0ac57394c2f..1d68b519f1d 100644 --- a/mysql-test/t/trigger.test +++ b/mysql-test/t/trigger.test @@ -960,38 +960,42 @@ drop trigger t1_bi; connection default; # -# Test for bug #13525 "Rename table does not keep info of triggers" +# Tests for bug #13525 "Rename table does not keep info of triggers" +# and bug #17866 "Problem with renaming table with triggers with fully +# qualified subject table". # create table t1 (id int); create trigger t1_bi before insert on t1 for each row set @a:=new.id; +create trigger t1_ai after insert on test.t1 for each row set @b:=new.id; insert into t1 values (101); -select @a; +select @a, @b; select trigger_schema, trigger_name, event_object_schema, event_object_table, action_statement from information_schema.triggers where event_object_schema = 'test'; rename table t1 to t2; # Trigger should work after rename insert into t2 values (102); -select @a; +select @a, @b; select trigger_schema, trigger_name, event_object_schema, event_object_table, action_statement from information_schema.triggers where event_object_schema = 'test'; # Let us check that the same works for simple ALTER TABLE ... RENAME alter table t2 rename to t3; insert into t3 values (103); -select @a; +select @a, @b; select trigger_schema, trigger_name, event_object_schema, event_object_table, action_statement from information_schema.triggers where event_object_schema = 'test'; # And for more complex ALTER TABLE alter table t3 rename to t4, add column val int default 0; insert into t4 values (104, 1); -select @a; +select @a, @b; select trigger_schema, trigger_name, event_object_schema, event_object_table, action_statement from information_schema.triggers where event_object_schema = 'test'; # .TRN file should be updated with new table name drop trigger t1_bi; +drop trigger t1_ai; drop table t4; # Rename between different databases if triggers exist should fail create database mysqltest; diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index 4c3ae5c032d..cef8c4dd1dc 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -1217,6 +1217,7 @@ Table_triggers_list::change_table_name_in_triggers(THD *thd, buff.append(def->str, before_on_len); buff.append(STRING_WITH_LEN("ON ")); append_identifier(thd, &buff, new_table_name->str, new_table_name->length); + buff.append(STRING_WITH_LEN(" ")); on_q_table_name_len= buff.length() - before_on_len; buff.append(on_table_name->str + on_table_name->length, def->length - (before_on_len + on_table_name->length)); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 468ade1bbbd..86d50bcd707 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -9127,7 +9127,7 @@ view_check_option: trigger_tail: TRIGGER_SYM remember_name sp_name trg_action_time trg_event - ON remember_name table_ident remember_end FOR_SYM EACH_SYM ROW_SYM + ON remember_name table_ident FOR_SYM remember_name EACH_SYM ROW_SYM { LEX *lex= Lex; sp_head *sp; @@ -9145,7 +9145,7 @@ trigger_tail: lex->trigger_definition_begin= $2; lex->ident.str= $7; - lex->ident.length= $9 - $7; + lex->ident.length= $10 - $7; sp->m_type= TYPE_ENUM_TRIGGER; lex->sphead= sp; From 2ea0b9b72c25cb5bac183289cd674000f0ff7df5 Mon Sep 17 00:00:00 2001 From: "konstantin@mysql.com" <> Date: Sun, 5 Mar 2006 00:38:54 +0300 Subject: [PATCH 15/20] Revert the changeset for Bug#16144 "mysql_stmt_attr_get type error": it breaks binary compatibility. The patch will be left intact in 5.1. --- libmysql/libmysql.c | 2 +- tests/mysql_client_test.c | 20 -------------------- 2 files changed, 1 insertion(+), 21 deletions(-) diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 498881aa947..898e0ad3273 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -2733,7 +2733,7 @@ my_bool STDCALL mysql_stmt_attr_get(MYSQL_STMT *stmt, { switch (attr_type) { case STMT_ATTR_UPDATE_MAX_LENGTH: - *(my_bool*) value= stmt->update_max_length; + *(unsigned long *) value= stmt->update_max_length; break; default: return TRUE; diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index dbc2f582466..71ae5e4f052 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -11784,25 +11784,6 @@ static void test_bug12925() } -/* Bug #16144: mysql_stmt_attr_get type error */ - -static void test_bug16144() -{ - const my_bool flag_orig= (my_bool) 0xde; - my_bool flag= flag_orig; - MYSQL_STMT *stmt; - myheader("test_bug16144"); - - /* Check that attr_get returns correct data on little and big endian CPUs */ - stmt= mysql_stmt_init(mysql); - mysql_stmt_attr_set(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, (const void*) &flag); - mysql_stmt_attr_get(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, (void*) &flag); - DIE_UNLESS(flag == flag_orig); - - mysql_stmt_close(stmt); -} - - /* Bug #15613: "libmysqlclient API function mysql_stmt_prepare returns wrong field length" @@ -12089,7 +12070,6 @@ static struct my_tests_st my_tests[]= { { "test_bug12001", test_bug12001 }, { "test_bug11718", test_bug11718 }, { "test_bug12925", test_bug12925 }, - { "test_bug16144", test_bug16144 }, { "test_bug15613", test_bug15613 }, { 0, 0 } }; From 33e7d20f370d3bd6905c10b47c0acd23dec79e4a Mon Sep 17 00:00:00 2001 From: "gluh@eagle.intranet.mysql.r18.ru" <> Date: Mon, 6 Mar 2006 12:52:38 +0400 Subject: [PATCH 16/20] Fix for bug#16678 FORMAT gives wrong result if client run with default-character-set=utf8 calculate Item_func_format::max_length using charset->mbmaxlen --- mysql-test/r/func_math.result | 20 ++++++++++++++++++++ mysql-test/t/func_math.test | 22 ++++++++++++++++++++++ sql/item_strfunc.h | 4 +++- 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/func_math.result b/mysql-test/r/func_math.result index 1507f959ae6..43748257203 100644 --- a/mysql-test/r/func_math.result +++ b/mysql-test/r/func_math.result @@ -218,3 +218,23 @@ truncate(-5000111000111000155,-1) select truncate(15000111000111000155,-1); truncate(15000111000111000155,-1) 15000111000111000150 +set names utf8; +create table t1 +(f1 varchar(32) not null, +f2 smallint(5) unsigned not null, +f3 int(10) unsigned not null default '0') +engine=myisam default charset=utf8; +insert into t1 values ('zombie',0,0),('gold',1,10000),('silver',2,10000); +create table t2 +(f1 int(10) unsigned not null, +f2 int(10) unsigned not null, +f3 smallint(5) unsigned not null) +engine=myisam default charset=utf8; +insert into t2 values (16777216,16787215,1),(33554432,33564431,2); +select format(t2.f2-t2.f1+1,0) from t1,t2 +where t1.f2 = t2.f3 order by t1.f1; +format(t2.f2-t2.f1+1,0) +10,000 +10,000 +drop table t1, t2; +set names default; diff --git a/mysql-test/t/func_math.test b/mysql-test/t/func_math.test index 8dc4eb215c7..4041c267134 100644 --- a/mysql-test/t/func_math.test +++ b/mysql-test/t/func_math.test @@ -155,3 +155,25 @@ select truncate(-5000111000111000155,-1); # truncate on unsigned bigint select truncate(15000111000111000155,-1); +# +# Bug#16678 FORMAT gives wrong result if client run with default-character-set=utf8 +# +set names utf8; +create table t1 +(f1 varchar(32) not null, + f2 smallint(5) unsigned not null, + f3 int(10) unsigned not null default '0') +engine=myisam default charset=utf8; +insert into t1 values ('zombie',0,0),('gold',1,10000),('silver',2,10000); + +create table t2 +(f1 int(10) unsigned not null, + f2 int(10) unsigned not null, + f3 smallint(5) unsigned not null) +engine=myisam default charset=utf8; +insert into t2 values (16777216,16787215,1),(33554432,33564431,2); + +select format(t2.f2-t2.f1+1,0) from t1,t2 +where t1.f2 = t2.f3 order by t1.f1; +drop table t1, t2; +set names default; diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 50ec0b36ce8..6a95a9e5d1f 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -471,7 +471,9 @@ public: void fix_length_and_dec() { collation.set(default_charset()); - max_length=args[0]->max_length+(args[0]->max_length-args[0]->decimals)/3; + uint char_length= args[0]->max_length/args[0]->collation.collation->mbmaxlen; + max_length= ((char_length + (char_length-args[0]->decimals)/3) * + collation.collation->mbmaxlen); } const char *func_name() const { return "format"; } void print(String *); From f1eaf7e8ec894a0fd0d54bf55e636f48179aaf7a Mon Sep 17 00:00:00 2001 From: "gluh@eagle.intranet.mysql.r18.ru" <> Date: Mon, 6 Mar 2006 14:03:40 +0400 Subject: [PATCH 17/20] Fix for bug#14385 GRANT and mapping to correct user account problems Check if the host of table hash record exactly matches host from GRANT command --- mysql-test/r/grant.result | 18 ++++++++++++++++++ mysql-test/t/grant.test | 16 ++++++++++++++++ sql/sql_acl.cc | 5 ++++- 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/grant.result b/mysql-test/r/grant.result index 13593ec2a88..dffa4988ea7 100644 --- a/mysql-test/r/grant.result +++ b/mysql-test/r/grant.result @@ -473,3 +473,21 @@ GRANT USAGE ON *.* TO 'mysqltest_7'@'' IDENTIFIED BY PASSWORD '*2FB071A056F9BB74 drop user mysqltest_7@; show grants for mysqltest_7@; ERROR 42000: There is no such grant defined for user 'mysqltest_7' on host '' +create database mysqltest; +use mysqltest; +create table t1(f1 int); +GRANT DELETE ON mysqltest.t1 TO mysqltest1@'%'; +GRANT SELECT ON mysqltest.t1 TO mysqltest1@'192.%'; +show grants for mysqltest1@'192.%'; +Grants for mysqltest1@192.% +GRANT USAGE ON *.* TO 'mysqltest1'@'192.%' +GRANT SELECT ON `mysqltest`.`t1` TO 'mysqltest1'@'192.%' +show grants for mysqltest1@'%'; +Grants for mysqltest1@% +GRANT USAGE ON *.* TO 'mysqltest1'@'%' +GRANT DELETE ON `mysqltest`.`t1` TO 'mysqltest1'@'%' +delete from mysql.user where user='mysqltest1'; +delete from mysql.db where user='mysqltest1'; +delete from mysql.tables_priv where user='mysqltest1'; +flush privileges; +drop database mysqltest; diff --git a/mysql-test/t/grant.test b/mysql-test/t/grant.test index 805fa881399..60b60547fcc 100644 --- a/mysql-test/t/grant.test +++ b/mysql-test/t/grant.test @@ -433,4 +433,20 @@ drop user mysqltest_7@; --error 1141 show grants for mysqltest_7@; +# +# Bug#14385: GRANT and mapping to correct user account problems +# +create database mysqltest; +use mysqltest; +create table t1(f1 int); +GRANT DELETE ON mysqltest.t1 TO mysqltest1@'%'; +GRANT SELECT ON mysqltest.t1 TO mysqltest1@'192.%'; +show grants for mysqltest1@'192.%'; +show grants for mysqltest1@'%'; +delete from mysql.user where user='mysqltest1'; +delete from mysql.db where user='mysqltest1'; +delete from mysql.tables_priv where user='mysqltest1'; +flush privileges; +drop database mysqltest; + # End of 4.1 tests diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index c1847d010c5..4626e5892a4 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -2001,7 +2001,10 @@ static GRANT_TABLE *table_hash_search(const char *host,const char* ip, { if (exact) { - if (compare_hostname(&grant_table->host, host, ip)) + if ((host && + !my_strcasecmp(system_charset_info, host, + grant_table->host.hostname)) || + (ip && !strcmp(ip, grant_table->host.hostname))) return grant_table; } else From f3ce98d2c9081316411242767f550f0ac30cb3d9 Mon Sep 17 00:00:00 2001 From: "gluh@eagle.intranet.mysql.r18.ru" <> Date: Mon, 6 Mar 2006 15:14:15 +0400 Subject: [PATCH 18/20] post-merge fix --- mysql-test/r/grant.result | 1 - 1 file changed, 1 deletion(-) diff --git a/mysql-test/r/grant.result b/mysql-test/r/grant.result index 603cf8bd675..3432de5179a 100644 --- a/mysql-test/r/grant.result +++ b/mysql-test/r/grant.result @@ -642,4 +642,3 @@ delete from mysql.db where user='mysqltest1'; delete from mysql.tables_priv where user='mysqltest1'; flush privileges; drop database mysqltest; - From 0b2f4ac3be91ae40cb2837c7dabfba1f4c76cc51 Mon Sep 17 00:00:00 2001 From: "serg@serg.mylan" <> Date: Mon, 6 Mar 2006 18:26:39 +0100 Subject: [PATCH 19/20] kill (subquery) - three years old bugfix that never worked --- mysql-test/r/kill.result | 2 ++ mysql-test/t/kill.test | 3 +++ sql/sql_yacc.yy | 17 +++++++---------- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/mysql-test/r/kill.result b/mysql-test/r/kill.result index ba9ba2833f6..7e38311a556 100644 --- a/mysql-test/r/kill.result +++ b/mysql-test/r/kill.result @@ -17,3 +17,5 @@ select 4; 4 4 drop table t1; +kill (select count(*) from mysql.user); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'select count(*) from mysql.user)' at line 1 diff --git a/mysql-test/t/kill.test b/mysql-test/t/kill.test index aada8dd2ef3..e9136ce49b4 100644 --- a/mysql-test/t/kill.test +++ b/mysql-test/t/kill.test @@ -40,4 +40,7 @@ connection con2; select 4; drop table t1; +--error 1064 +kill (select count(*) from mysql.user); + # End of 4.1 tests diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index c99abc7d349..05d95b57abb 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -3564,9 +3564,8 @@ select_derived2: { LEX *lex= Lex; lex->derived_tables= 1; - if (((int)lex->sql_command >= (int)SQLCOM_HA_OPEN && - lex->sql_command <= (int)SQLCOM_HA_READ) || - lex->sql_command == (int)SQLCOM_KILL) + if (lex->sql_command == (int)SQLCOM_HA_READ || + lex->sql_command == (int)SQLCOM_KILL) { yyerror(ER(ER_SYNTAX_ERROR)); YYABORT; @@ -4739,16 +4738,15 @@ purge_option: /* kill threads */ kill: - KILL_SYM expr + KILL_SYM { Lex->sql_command= SQLCOM_KILL; } expr { LEX *lex=Lex; - if ($2->fix_fields(lex->thd, 0, &$2) || $2->check_cols(1)) + if ($3->fix_fields(lex->thd, 0, &$3) || $3->check_cols(1)) { send_error(lex->thd, ER_SET_CONSTANTS_ONLY); YYABORT; } - lex->sql_command=SQLCOM_KILL; - lex->thread_id= (ulong) $2->val_int(); + lex->thread_id= (ulong) $3->val_int(); }; /* change database */ @@ -6162,9 +6160,8 @@ subselect_start: '(' SELECT_SYM { LEX *lex=Lex; - if (((int)lex->sql_command >= (int)SQLCOM_HA_OPEN && - lex->sql_command <= (int)SQLCOM_HA_READ) || - lex->sql_command == (int)SQLCOM_KILL) + if (lex->sql_command == (int)SQLCOM_HA_READ || + lex->sql_command == (int)SQLCOM_KILL) { yyerror(ER(ER_SYNTAX_ERROR)); YYABORT; From 5a1672dd664f97d6cccda17360415160365df866 Mon Sep 17 00:00:00 2001 From: "serg@serg.mylan" <> Date: Mon, 6 Mar 2006 22:08:29 +0100 Subject: [PATCH 20/20] compilation fixes --- .bzrignore | 1 + libmysqld/lib_sql.cc | 51 +++++++++++++++++++------------------------- 2 files changed, 23 insertions(+), 29 deletions(-) diff --git a/.bzrignore b/.bzrignore index a16ed70a812..e521692f6c2 100644 --- a/.bzrignore +++ b/.bzrignore @@ -1274,3 +1274,4 @@ vio/viotest.cpp zlib/*.ds? zlib/*.vcproj scripts/mysql_upgrade +include/openssl diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc index e4c9d8cb4e9..a2fdae994b1 100644 --- a/libmysqld/lib_sql.cc +++ b/libmysqld/lib_sql.cc @@ -38,6 +38,7 @@ int check_user(THD *thd, enum enum_server_command command, const char *passwd, uint passwd_len, const char *db, bool check_count); C_MODE_START + #include #undef ER #include "errmsg.h" @@ -46,19 +47,6 @@ C_MODE_START static my_bool emb_read_query_result(MYSQL *mysql); -void THD::clear_data_list() -{ - while (first_data) - { - MYSQL_DATA *data= first_data; - first_data= data->embedded_info->next; - free_rows(data); - } - data_tail= &first_data; - free_rows(cur_data); - cur_data= 0; -} - /* Reads error information from the MYSQL_DATA and puts @@ -423,15 +411,6 @@ MYSQL_METHODS embedded_methods= emb_read_rows_from_cursor }; -C_MODE_END - -void THD::clear_error() -{ - net.last_error[0]= 0; - net.last_errno= 0; - net.report_error= 0; -} - /* Make a copy of array and the strings array points to */ @@ -458,11 +437,7 @@ char **copy_arguments(int argc, char **argv) return res; } - -extern "C" -{ - -char ** copy_arguments_ptr= 0; +char ** copy_arguments_ptr= 0; int init_embedded_server(int argc, char **argv, char **groups) { @@ -571,9 +546,7 @@ void end_embedded_server() clean_up(0); } -} /* extern "C" */ -C_MODE_START void init_embedded_mysql(MYSQL *mysql, int client_flag, char *db) { THD *thd = (THD *)mysql->thd; @@ -693,6 +666,26 @@ err: C_MODE_END +void THD::clear_data_list() +{ + while (first_data) + { + MYSQL_DATA *data= first_data; + first_data= data->embedded_info->next; + free_rows(data); + } + data_tail= &first_data; + free_rows(cur_data); + cur_data= 0; +} + +void THD::clear_error() +{ + net.last_error[0]= 0; + net.last_errno= 0; + net.report_error= 0; +} + static char *dup_str_aux(MEM_ROOT *root, const char *from, uint length, CHARSET_INFO *fromcs, CHARSET_INFO *tocs) {