From 3dcf20566439858cb200ad97368232f4e2d9f943 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 7 Oct 2005 03:12:15 +0300 Subject: [PATCH 1/7] Review of new code since last pull - Use %lx instead of %p as %p is not portable - Don't replace ROW item with Item_null myisam/mi_rkey.c: Use %lx instead of %p as %p is not portable myisam/mi_search.c: Use %lx instead of %p as %p is not portable mysql-test/r/select.result: More test for ROW comparison mysql-test/t/select.test: More test for ROW comparison sql/item.cc: We can't replace a ROW item with Item_null because: - Arg_comparator is still using the orignal row items and it's not good to have args[0] different from what is actually compared - If we are using the <=> comparator, NULL can still be compared as true - We would break things if we would ever use resolve_const_item() for operators like >, < etc. --- myisam/mi_rkey.c | 4 ++-- myisam/mi_search.c | 45 +++++++++++++++++++++----------------- mysql-test/r/select.result | 7 ++++++ mysql-test/t/select.test | 4 ++++ sql/item.cc | 33 ++++++++++------------------ 5 files changed, 49 insertions(+), 44 deletions(-) diff --git a/myisam/mi_rkey.c b/myisam/mi_rkey.c index 9aa2be3c706..de4cefb19b6 100644 --- a/myisam/mi_rkey.c +++ b/myisam/mi_rkey.c @@ -31,8 +31,8 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len, HA_KEYSEG *last_used_keyseg; uint pack_key_length, use_key_length, nextflag; DBUG_ENTER("mi_rkey"); - DBUG_PRINT("enter", ("base: %p buf: %p inx: %d search_flag: %d", - info, buf, inx, search_flag)); + DBUG_PRINT("enter", ("base: %lx buf: %lx inx: %d search_flag: %d", + (long) info, (long) buf, inx, search_flag)); if ((inx = _mi_check_index(info,inx)) < 0) DBUG_RETURN(my_errno); diff --git a/myisam/mi_search.c b/myisam/mi_search.c index 82177d331b7..71a623dc9c0 100644 --- a/myisam/mi_search.c +++ b/myisam/mi_search.c @@ -257,15 +257,16 @@ int _mi_seq_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page, if (length == 0 || page > end) { my_errno=HA_ERR_CRASHED; - DBUG_PRINT("error",("Found wrong key: length: %u page: %p end: %p", - length, page, end)); + DBUG_PRINT("error",("Found wrong key: length: %u page: %lx end: %lx", + length, (long) page, (long) end)); DBUG_RETURN(MI_FOUND_WRONG_KEY); } if ((flag=ha_key_cmp(keyinfo->seg,t_buff,key,key_len,comp_flag, ¬_used)) >= 0) break; #ifdef EXTRA_DEBUG - DBUG_PRINT("loop",("page: %p key: '%s' flag: %d", page, t_buff, flag)); + DBUG_PRINT("loop",("page: %lx key: '%s' flag: %d", (long) page, t_buff, + flag)); #endif memcpy(buff,t_buff,length); *ret_pos=page; @@ -273,7 +274,7 @@ int _mi_seq_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page, if (flag == 0) memcpy(buff,t_buff,length); /* Result is first key */ *last_key= page == end; - DBUG_PRINT("exit",("flag: %d ret_pos: %p", flag, *ret_pos)); + DBUG_PRINT("exit",("flag: %d ret_pos: %lx", flag, (long) *ret_pos)); DBUG_RETURN(flag); } /* _mi_seq_search */ @@ -412,8 +413,8 @@ int _mi_prefix_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page, if (page > end) { my_errno=HA_ERR_CRASHED; - DBUG_PRINT("error",("Found wrong key: length: %u page: %p end: %p", - length, page, end)); + DBUG_PRINT("error",("Found wrong key: length: %u page: %lx end: %lx", + length, (long) page, (long) end)); DBUG_RETURN(MI_FOUND_WRONG_KEY); } @@ -546,7 +547,7 @@ int _mi_prefix_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page, *last_key= page == end; - DBUG_PRINT("exit",("flag: %d ret_pos: %p", flag, *ret_pos)); + DBUG_PRINT("exit",("flag: %d ret_pos: %lx", flag, (long) *ret_pos)); DBUG_RETURN(flag); } /* _mi_prefix_search */ @@ -807,8 +808,8 @@ uint _mi_get_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag, if (length > keyseg->length) { DBUG_PRINT("error", - ("Found too long null packed key: %u of %u at %p", - length, keyseg->length, *page_pos)); + ("Found too long null packed key: %u of %u at %lx", + length, keyseg->length, (long) *page_pos)); DBUG_DUMP("key",(char*) *page_pos,16); my_errno=HA_ERR_CRASHED; return 0; @@ -863,8 +864,8 @@ uint _mi_get_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag, } if (length > (uint) keyseg->length) { - DBUG_PRINT("error",("Found too long packed key: %u of %u at %p", - length, keyseg->length, *page_pos)); + DBUG_PRINT("error",("Found too long packed key: %u of %u at %lx", + length, keyseg->length, (long) *page_pos)); DBUG_DUMP("key",(char*) *page_pos,16); my_errno=HA_ERR_CRASHED; return 0; /* Error */ @@ -928,8 +929,8 @@ uint _mi_get_binary_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag, { if (length > keyinfo->maxlength) { - DBUG_PRINT("error",("Found too long binary packed key: %u of %u at %p", - length, keyinfo->maxlength, *page_pos)); + DBUG_PRINT("error",("Found too long binary packed key: %u of %u at %lx", + length, keyinfo->maxlength, (long) *page_pos)); DBUG_DUMP("key",(char*) *page_pos,16); my_errno=HA_ERR_CRASHED; DBUG_RETURN(0); /* Wrong key */ @@ -975,8 +976,8 @@ uint _mi_get_binary_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag, length-=tmp; from=page; from_end=page_end; } - DBUG_PRINT("info",("key: %p from: %p length: %u", - key, from, length)); + DBUG_PRINT("info",("key: %lx from: %lx length: %u", + (long) key, (long) from, length)); memcpy_overlap((byte*) key, (byte*) from, (size_t) length); key+=length; from+=length; @@ -1031,7 +1032,8 @@ uchar *_mi_get_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page, } } } - DBUG_PRINT("exit",("page: %p length: %u", page, *return_key_length)); + DBUG_PRINT("exit",("page: %lx length: %u", (long) page, + *return_key_length)); DBUG_RETURN(page); } /* _mi_get_key */ @@ -1082,7 +1084,7 @@ uchar *_mi_get_last_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page, uint nod_flag; uchar *lastpos; DBUG_ENTER("_mi_get_last_key"); - DBUG_PRINT("enter",("page: %p endpos: %p", page, endpos)); + DBUG_PRINT("enter",("page: %lx endpos: %lx", (long) page, (long) endpos)); nod_flag=mi_test_if_nod(page); if (! (keyinfo->flag & (HA_VAR_LENGTH_KEY | HA_BINARY_PACK_KEY))) @@ -1102,13 +1104,15 @@ uchar *_mi_get_last_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page, *return_key_length=(*keyinfo->get_key)(keyinfo,nod_flag,&page,lastkey); if (*return_key_length == 0) { - DBUG_PRINT("error",("Couldn't find last key: page: %p", page)); + DBUG_PRINT("error",("Couldn't find last key: page: %lx", + (long) page)); my_errno=HA_ERR_CRASHED; DBUG_RETURN(0); } } } - DBUG_PRINT("exit",("lastpos: %p length: %u", lastpos, *return_key_length)); + DBUG_PRINT("exit",("lastpos: %lx length: %u", (long) lastpos, + *return_key_length)); DBUG_RETURN(lastpos); } /* _mi_get_last_key */ @@ -1644,7 +1648,8 @@ _mi_calc_var_pack_key_length(MI_KEYDEF *keyinfo,uint nod_flag,uchar *next_key, ref_length=0; next_length_pack=0; } - DBUG_PRINT("test",("length: %d next_key: %p", length, next_key)); + DBUG_PRINT("test",("length: %d next_key: %lx", length, + (long) next_key)); { uint tmp_length; diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index 64cbaf4fa67..4effb8d173c 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -2625,4 +2625,11 @@ select f1 from t1,t2 where f1=f2 and (f1,NULL) = ((1,1)); f1 select f1 from t1,t2 where f1=f2 and (f1,f2) = ((1,NULL)); f1 +insert into t1 values(1,1),(2,null); +insert into t2 values(2); +select * from t1,t2 where f1=f3 and (f1,f2) = (2,null); +f1 f2 f3 +select * from t1,t2 where f1=f3 and (f1,f2) <=> (2,null); +f1 f2 f3 +2 NULL 2 drop table t1,t2; diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index bdadd5c536b..e6f91389d7b 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -2172,6 +2172,10 @@ create table t2(f3 int); select f1 from t1,t2 where f1=f2 and (f1,f2) = ((1,1)); select f1 from t1,t2 where f1=f2 and (f1,NULL) = ((1,1)); select f1 from t1,t2 where f1=f2 and (f1,f2) = ((1,NULL)); +insert into t1 values(1,1),(2,null); +insert into t2 values(2); +select * from t1,t2 where f1=f3 and (f1,f2) = (2,null); +select * from t1,t2 where f1=f3 and (f1,f2) <=> (2,null); drop table t1,t2; # End of 4.1 tests diff --git a/sql/item.cc b/sql/item.cc index 03ab38fc970..78e9c02f5f3 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -2872,32 +2872,21 @@ void resolve_const_item(THD *thd, Item **ref, Item *comp_item) } else if (res_type == ROW_RESULT) { + Item_row *item_row= (Item_row*) item; + Item_row *comp_item_row= (Item_row*) comp_item; + uint col; new_item= 0; /* If item and comp_item are both Item_rows and have same number of cols - then process items in Item_row one by one. If Item_row contain nulls - substitute it by Item_null. Otherwise just return. + then process items in Item_row one by one. + We can't ignore NULL values here as this item may be used with <=>, in + which case NULL's are significant. */ - if (item->result_type() == comp_item->result_type() && - ((Item_row*)item)->cols() == ((Item_row*)comp_item)->cols()) - { - Item_row *item_row= (Item_row*)item,*comp_item_row= (Item_row*)comp_item; - if (item_row->null_inside()) - new_item= (Item*) new Item_null(name); - else - { - int i= item_row->cols() - 1; - for (; i >= 0; i--) - { - if (item_row->maybe_null && item_row->el(i)->is_null()) - { - new_item= (Item*) new Item_null(name); - break; - } - resolve_const_item(thd, item_row->addr(i), comp_item_row->el(i)); - } - } - } + DBUG_ASSERT(item->result_type() == comp_item->result_type()); + DBUG_ASSERT(item_row->cols() == comp_item_row->cols()); + col= item_row->cols(); + while (col-- > 0) + resolve_const_item(thd, item_row->addr(col), comp_item_row->el(col)); } else { // It must REAL_RESULT From 8b1936fa12f80205396619ef4c0761e17fefeae1 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 7 Oct 2005 12:50:29 +0200 Subject: [PATCH 2/7] Increase the version number. --- configure.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index 97eb0cb0edf..c4ea20a0453 100644 --- a/configure.in +++ b/configure.in @@ -5,7 +5,7 @@ AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # The Docs Makefile.am parses this line! # remember to also change ndb version below and update version.c in ndb -AM_INIT_AUTOMAKE(mysql, 4.1.15) +AM_INIT_AUTOMAKE(mysql, 4.1.16) AM_CONFIG_HEADER(config.h) PROTOCOL_VERSION=10 @@ -16,7 +16,7 @@ SHARED_LIB_VERSION=14:0:0 # ndb version NDB_VERSION_MAJOR=4 NDB_VERSION_MINOR=1 -NDB_VERSION_BUILD=15 +NDB_VERSION_BUILD=16 NDB_VERSION_STATUS="" # Set all version vars based on $VERSION. How do we do this more elegant ? From c533a6bf04a0e1ba9941d72a288649f3b90dc701 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 7 Oct 2005 13:08:07 +0200 Subject: [PATCH 3/7] make_binary_distribution.sh: Copy zlib.a and valgrind.supp if exists Copy disabled.def scripts/make_binary_distribution.sh: Copy zlib.a and valgrind.supp if exists --- scripts/make_binary_distribution.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/scripts/make_binary_distribution.sh b/scripts/make_binary_distribution.sh index 0ab26f33c53..d622dfed9d3 100644 --- a/scripts/make_binary_distribution.sh +++ b/scripts/make_binary_distribution.sh @@ -167,7 +167,8 @@ copyfileto $BASE/lib \ libmysql_r/.libs/libmysqlclient_r.so* libmysql_r/libmysqlclient_r.* \ mysys/libmysys.a strings/libmystrings.a dbug/libdbug.a \ libmysqld/.libs/libmysqld.a libmysqld/.libs/libmysqld.so* \ - libmysqld/libmysqld.a netware/libmysql.imp + libmysqld/libmysqld.a netware/libmysql.imp \ + zlib/.libs/libz.a # convert the .a to .lib for NetWare if [ $BASE_SYSTEM = "netware" ] ; then @@ -204,10 +205,12 @@ rm -f $MYSQL_SHARE/Makefile* $MYSQL_SHARE/*/*.OLD copyfileto $BASE/mysql-test \ mysql-test/mysql-test-run mysql-test/install_test_db \ mysql-test/mysql-test-run.pl mysql-test/README \ + mysql-test/valgrind.supp \ netware/mysql_test_run.nlm netware/install_test_db.ncf $CP mysql-test/lib/*.pl $BASE/mysql-test/lib $CP mysql-test/lib/*.sql $BASE/mysql-test/lib +$CP mysql-test/t/*.def $BASE/mysql-test/t $CP mysql-test/include/*.inc $BASE/mysql-test/include $CP mysql-test/std_data/*.dat mysql-test/std_data/*.*001 \ $BASE/mysql-test/std_data From d40a0f423f8725a25122030a594127f167747204 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 7 Oct 2005 16:37:53 +0200 Subject: [PATCH 4/7] Copy zlib.a and valgrind.supp if exists. Copy disabled.def (Backport of Kent's change from the main tree to the 4.1.15 build clone. Original changeset: 2005/10/07 13:08:07+02:00 kent@mysql.com ) scripts/make_binary_distribution.sh: Copy zlib.a and valgrind.supp if exists. Copy disabled.def (Backport of Kent's change from the main tree to the 4.1.15 build clone.) --- scripts/make_binary_distribution.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/scripts/make_binary_distribution.sh b/scripts/make_binary_distribution.sh index 0ab26f33c53..d622dfed9d3 100644 --- a/scripts/make_binary_distribution.sh +++ b/scripts/make_binary_distribution.sh @@ -167,7 +167,8 @@ copyfileto $BASE/lib \ libmysql_r/.libs/libmysqlclient_r.so* libmysql_r/libmysqlclient_r.* \ mysys/libmysys.a strings/libmystrings.a dbug/libdbug.a \ libmysqld/.libs/libmysqld.a libmysqld/.libs/libmysqld.so* \ - libmysqld/libmysqld.a netware/libmysql.imp + libmysqld/libmysqld.a netware/libmysql.imp \ + zlib/.libs/libz.a # convert the .a to .lib for NetWare if [ $BASE_SYSTEM = "netware" ] ; then @@ -204,10 +205,12 @@ rm -f $MYSQL_SHARE/Makefile* $MYSQL_SHARE/*/*.OLD copyfileto $BASE/mysql-test \ mysql-test/mysql-test-run mysql-test/install_test_db \ mysql-test/mysql-test-run.pl mysql-test/README \ + mysql-test/valgrind.supp \ netware/mysql_test_run.nlm netware/install_test_db.ncf $CP mysql-test/lib/*.pl $BASE/mysql-test/lib $CP mysql-test/lib/*.sql $BASE/mysql-test/lib +$CP mysql-test/t/*.def $BASE/mysql-test/t $CP mysql-test/include/*.inc $BASE/mysql-test/include $CP mysql-test/std_data/*.dat mysql-test/std_data/*.*001 \ $BASE/mysql-test/std_data From d1e71faf61348f291b36dc40848900a7090ba90b Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 7 Oct 2005 20:14:34 +0500 Subject: [PATCH 5/7] Populate t1 in order to get more predictable explain results. --- mysql-test/r/subselect2.result | 1 + mysql-test/t/subselect2.test | 2 ++ 2 files changed, 3 insertions(+) diff --git a/mysql-test/r/subselect2.result b/mysql-test/r/subselect2.result index 148c670c589..8fcfa06a8ae 100644 --- a/mysql-test/r/subselect2.result +++ b/mysql-test/r/subselect2.result @@ -14,6 +14,7 @@ DOCID VARCHAR(32)BINARY NOT NULL , PRIMARY KEY ( DOCID ) ) ENGINE=InnoDB ; +INSERT INTO t1 (DOCID) VALUES ("1"), ("2"); CREATE TABLE t2 ( DOCID VARCHAR(32)BINARY NOT NULL diff --git a/mysql-test/t/subselect2.test b/mysql-test/t/subselect2.test index 839e94206d0..b21eda176b6 100644 --- a/mysql-test/t/subselect2.test +++ b/mysql-test/t/subselect2.test @@ -25,6 +25,8 @@ DOCID VARCHAR(32)BINARY NOT NULL ) ENGINE=InnoDB ; +INSERT INTO t1 (DOCID) VALUES ("1"), ("2"); + CREATE TABLE t2 ( DOCID VARCHAR(32)BINARY NOT NULL From 2b603902ccbafa97cdf9c591cbb1f4ce0e57f541 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 10 Oct 2005 12:27:48 +0200 Subject: [PATCH 6/7] Bug #13611 double [TCP DEFAULT] in config.ini crashes ndb_mgmd - Added error printout and nice exit for duplicate default sections --- ndb/src/mgmsrv/InitConfigFileParser.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ndb/src/mgmsrv/InitConfigFileParser.cpp b/ndb/src/mgmsrv/InitConfigFileParser.cpp index e0163b966c0..b2c290df9fc 100644 --- a/ndb/src/mgmsrv/InitConfigFileParser.cpp +++ b/ndb/src/mgmsrv/InitConfigFileParser.cpp @@ -558,8 +558,12 @@ InitConfigFileParser::storeSection(Context& ctx){ } } } - if(ctx.type == InitConfigFileParser::DefaultSection) - require(ctx.m_defaults->put(ctx.pname, ctx.m_currentSection)); + if(ctx.type == InitConfigFileParser::DefaultSection && + !ctx.m_defaults->put(ctx.pname, ctx.m_currentSection)) + { + ctx.reportError("Duplicate default section not allowed"); + return false; + } if(ctx.type == InitConfigFileParser::Section) require(ctx.m_config->put(ctx.pname, ctx.m_currentSection)); delete ctx.m_currentSection; ctx.m_currentSection = NULL; From 5d2bc92523991e4304d4cbad8b4759023f6213d8 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 10 Oct 2005 15:10:14 +0200 Subject: [PATCH 7/7] BUG#12618: Removing fake locking mysql-test/r/rpl_multi_update3.result: New test case mysql-test/t/rpl_multi_update3.test: New test case sql/sql_parse.cc: Removed fake locking Changed so that filtering is done later for multi-update Removed redundant code sql/sql_update.cc: Moved call to sql_parse.cc --- mysql-test/r/rpl_multi_update3.result | 72 ++++++++++++++++++ mysql-test/t/rpl_multi_update3.test | 59 +++++++++++++++ sql/sql_parse.cc | 102 +++++--------------------- sql/sql_update.cc | 3 - 4 files changed, 151 insertions(+), 85 deletions(-) diff --git a/mysql-test/r/rpl_multi_update3.result b/mysql-test/r/rpl_multi_update3.result index 1b757b1400c..b81af7c6e39 100644 --- a/mysql-test/r/rpl_multi_update3.result +++ b/mysql-test/r/rpl_multi_update3.result @@ -122,3 +122,75 @@ SELECT * FROM t1; i j x y z 1 2 23 24 71 DROP TABLE t1, t2, t3; +DROP TABLE IF EXISTS t1; +Warnings: +Note 1051 Unknown table 't1' +DROP TABLE IF EXISTS t2; +Warnings: +Note 1051 Unknown table 't2' +CREATE TABLE t1 ( +idp int(11) NOT NULL default '0', +idpro int(11) default NULL, +price decimal(19,4) default NULL, +PRIMARY KEY (idp) +); +CREATE TABLE t2 ( +idpro int(11) NOT NULL default '0', +price decimal(19,4) default NULL, +nbprice int(11) default NULL, +PRIMARY KEY (idpro) +); +INSERT INTO t1 VALUES +(1,1,'3.0000'), +(2,2,'1.0000'), +(3,1,'1.0000'), +(4,1,'4.0000'), +(5,3,'2.0000'), +(6,2,'4.0000'); +INSERT INTO t2 VALUES +(1,'0.0000',0), +(2,'0.0000',0), +(3,'0.0000',0); +update +t2 +join +( select idpro, min(price) as min_price, count(*) as nbr_price +from t1 +where idpro>0 and price>0 +group by idpro +) as table_price +on t2.idpro = table_price.idpro +set t2.price = table_price.min_price, +t2.nbprice = table_price.nbr_price; +select "-- MASTER AFTER JOIN --" as ""; + +-- MASTER AFTER JOIN -- +select * from t1; +idp idpro price +1 1 3.0000 +2 2 1.0000 +3 1 1.0000 +4 1 4.0000 +5 3 2.0000 +6 2 4.0000 +select * from t2; +idpro price nbprice +1 1.0000 3 +2 1.0000 2 +3 2.0000 1 +select "-- SLAVE AFTER JOIN --" as ""; + +-- SLAVE AFTER JOIN -- +select * from t1; +idp idpro price +1 1 3.0000 +2 2 1.0000 +3 1 1.0000 +4 1 4.0000 +5 3 2.0000 +6 2 4.0000 +select * from t2; +idpro price nbprice +1 1.0000 3 +2 1.0000 2 +3 2.0000 1 diff --git a/mysql-test/t/rpl_multi_update3.test b/mysql-test/t/rpl_multi_update3.test index 64e46882c16..36ac7a59cb3 100644 --- a/mysql-test/t/rpl_multi_update3.test +++ b/mysql-test/t/rpl_multi_update3.test @@ -158,4 +158,63 @@ SELECT * FROM t1; connection master; DROP TABLE t1, t2, t3; +############################################################################## +# +# BUG#12618 +# +# TEST: Replication of a statement containing a join in a multi-update. + +DROP TABLE IF EXISTS t1; +DROP TABLE IF EXISTS t2; + +CREATE TABLE t1 ( + idp int(11) NOT NULL default '0', + idpro int(11) default NULL, + price decimal(19,4) default NULL, + PRIMARY KEY (idp) +); + +CREATE TABLE t2 ( + idpro int(11) NOT NULL default '0', + price decimal(19,4) default NULL, + nbprice int(11) default NULL, + PRIMARY KEY (idpro) +); + +INSERT INTO t1 VALUES + (1,1,'3.0000'), + (2,2,'1.0000'), + (3,1,'1.0000'), + (4,1,'4.0000'), + (5,3,'2.0000'), + (6,2,'4.0000'); + +INSERT INTO t2 VALUES + (1,'0.0000',0), + (2,'0.0000',0), + (3,'0.0000',0); + +# This update sets t2 to the minimal prices for each product +update + t2 + join + ( select idpro, min(price) as min_price, count(*) as nbr_price + from t1 + where idpro>0 and price>0 + group by idpro + ) as table_price +on t2.idpro = table_price.idpro +set t2.price = table_price.min_price, + t2.nbprice = table_price.nbr_price; + +select "-- MASTER AFTER JOIN --" as ""; +select * from t1; +select * from t2; + +sync_slave_with_master; + +select "-- SLAVE AFTER JOIN --" as ""; +select * from t1; +select * from t2; + # End of 4.1 tests diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 3a538a7629b..54d51e42895 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1941,8 +1941,6 @@ mysql_execute_command(THD *thd) { int res= 0; LEX *lex= thd->lex; - bool slave_fake_lock= 0; - MYSQL_LOCK *fake_prev_lock= 0; SELECT_LEX *select_lex= &lex->select_lex; TABLE_LIST *tables= (TABLE_LIST*) select_lex->table_list.first; SELECT_LEX_UNIT *unit= &lex->unit; @@ -1971,35 +1969,21 @@ mysql_execute_command(THD *thd) #ifdef HAVE_REPLICATION if (thd->slave_thread) { - if (lex->sql_command == SQLCOM_UPDATE_MULTI) - { - DBUG_PRINT("info",("need faked locked tables")); - - if (check_multi_update_lock(thd, tables, &select_lex->item_list, - select_lex)) - goto error; - - /* Fix for replication, the tables are opened and locked, - now we pretend that we have performed a LOCK TABLES action */ - - fake_prev_lock= thd->locked_tables; - if (thd->lock) - thd->locked_tables= thd->lock; - thd->lock= 0; - slave_fake_lock= 1; - } /* - Skip if we are in the slave thread, some table rules have been - given and the table list says the query should not be replicated. + Check if statment should be skipped because of slave filtering + rules Exceptions are: + - UPDATE MULTI: For this statement, we want to check the filtering + rules later in the code - SET: we always execute it (Not that many SET commands exists in the binary log anyway -- only 4.1 masters write SET statements, in 5.0 there are no SET statements in the binary log) - DROP TEMPORARY TABLE IF EXISTS: we always execute it (otherwise we have stale files on slave caused by exclusion of one tmp table). */ - if (!(lex->sql_command == SQLCOM_SET_OPTION) && + if (!(lex->sql_command == SQLCOM_UPDATE_MULTI) && + !(lex->sql_command == SQLCOM_SET_OPTION) && !(lex->sql_command == SQLCOM_DROP_TABLE && lex->drop_temporary && lex->drop_if_exists) && all_tables_not_ok(thd,tables)) @@ -2852,6 +2836,20 @@ unsent_create_error: { if ((res= multi_update_precheck(thd, tables))) break; + + if ((res= mysql_multi_update_lock(thd, tables, &select_lex->item_list, + select_lex))) + break; + + /* Check slave filtering rules */ + if (thd->slave_thread) + if (all_tables_not_ok(thd,tables)) + { + /* we warn the slave SQL thread */ + my_error(ER_SLAVE_IGNORED_TABLE, MYF(0)); + break; + } + res= mysql_multi_update(thd,tables, &select_lex->item_list, &lex->value_list, @@ -3764,14 +3762,6 @@ purposes internal to the MySQL server", MYF(0)); send_error(thd,thd->killed ? ER_SERVER_SHUTDOWN : 0); error: - if (unlikely(slave_fake_lock)) - { - DBUG_PRINT("info",("undoing faked lock")); - thd->lock= thd->locked_tables; - thd->locked_tables= fake_prev_lock; - if (thd->lock == thd->locked_tables) - thd->lock= 0; - } DBUG_VOID_RETURN; } @@ -5303,58 +5293,6 @@ bool check_simple_select() return 0; } -/* - Setup locking for multi-table updates. Used by the replication slave. - Replication slave SQL thread examines (all_tables_not_ok()) the - locking state of referenced tables to determine if the query has to - be executed or ignored. Since in multi-table update, the - 'default' lock is read-only, this lock is corrected early enough by - calling this function, before the slave decides to execute/ignore. - - SYNOPSIS - check_multi_update_lock() - thd Current thread - tables List of user-supplied tables - fields List of fields requiring update - - RETURN VALUES - 0 ok - 1 error -*/ -static bool check_multi_update_lock(THD *thd, TABLE_LIST *tables, - List *fields, SELECT_LEX *select_lex) -{ - bool res= 1; - TABLE_LIST *table; - DBUG_ENTER("check_multi_update_lock"); - - if (check_db_used(thd, tables)) - goto error; - - /* - Ensure that we have UPDATE or SELECT privilege for each table - The exact privilege is checked in mysql_multi_update() - */ - for (table= tables ; table ; table= table->next) - { - TABLE_LIST *save= table->next; - table->next= 0; - if ((check_access(thd, UPDATE_ACL, table->db, &table->grant.privilege,0,1) || - (grant_option && check_grant(thd, UPDATE_ACL, table,0,1,1))) && - check_one_table_access(thd, SELECT_ACL, table)) - goto error; - table->next= save; - } - - if (mysql_multi_update_lock(thd, tables, fields, select_lex)) - goto error; - - res= 0; - -error: - DBUG_RETURN(res); -} - Comp_creator *comp_eq_creator(bool invert) { diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 2857bce09ed..a978a5edc64 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -672,9 +672,6 @@ int mysql_multi_update(THD *thd, multi_update *result; DBUG_ENTER("mysql_multi_update"); - if ((res= mysql_multi_update_lock(thd, table_list, fields, select_lex))) - DBUG_RETURN(res); - /* Setup timestamp handling */ for (tl= update_list; tl; tl= tl->next) {