Merge mysql.com:/users/lthalmann/bkroot/mysql-4.1
into mysql.com:/users/lthalmann/bk/mysql-5.0 myisam/mi_rkey.c: Auto merged mysql-test/r/subselect2.result: Auto merged mysql-test/t/select.test: Auto merged ndb/src/mgmsrv/InitConfigFileParser.cpp: Auto merged scripts/make_binary_distribution.sh: Auto merged configure.in: After merge fixes myisam/mi_search.c: After merge fixes mysql-test/r/select.result: After merge fixes sql/item.cc: After merge fixes sql/sql_parse.cc: After merge fixes sql/sql_update.cc: After merge fixes
This commit is contained in:
commit
37c98812b3
@ -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);
|
||||
|
@ -259,15 +259,16 @@ int _mi_seq_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page,
|
||||
{
|
||||
mi_print_error(info->s, HA_ERR_CRASHED);
|
||||
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;
|
||||
@ -275,7 +276,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 */
|
||||
|
||||
@ -415,8 +416,8 @@ int _mi_prefix_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page,
|
||||
{
|
||||
mi_print_error(info->s, HA_ERR_CRASHED);
|
||||
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);
|
||||
}
|
||||
|
||||
@ -550,7 +551,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 */
|
||||
|
||||
@ -812,8 +813,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);
|
||||
mi_print_error(keyinfo->share, HA_ERR_CRASHED);
|
||||
my_errno=HA_ERR_CRASHED;
|
||||
@ -869,8 +870,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);
|
||||
mi_print_error(keyinfo->share, HA_ERR_CRASHED);
|
||||
my_errno=HA_ERR_CRASHED;
|
||||
@ -935,8 +936,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);
|
||||
mi_print_error(keyinfo->share, HA_ERR_CRASHED);
|
||||
my_errno=HA_ERR_CRASHED;
|
||||
@ -983,8 +984,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;
|
||||
@ -1041,7 +1042,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 */
|
||||
|
||||
@ -1093,7 +1095,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)))
|
||||
@ -1113,14 +1115,16 @@ 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));
|
||||
mi_print_error(info->s, HA_ERR_CRASHED);
|
||||
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 */
|
||||
|
||||
@ -1659,7 +1663,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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -2189,6 +2189,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
|
||||
|
@ -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
|
||||
|
@ -565,8 +565,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;
|
||||
|
@ -226,6 +226,7 @@ copyfileto $BASE/mysql-test \
|
||||
|
||||
$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/t/*.def $BASE/mysql-test/t
|
||||
$CP mysql-test/std_data/*.dat mysql-test/std_data/*.frm \
|
||||
|
33
sql/item.cc
33
sql/item.cc
@ -5236,32 +5236,21 @@ void resolve_const_item(THD *thd, Item **ref, Item *comp_item)
|
||||
}
|
||||
case 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));
|
||||
break;
|
||||
}
|
||||
case REAL_RESULT:
|
||||
|
@ -2317,8 +2317,6 @@ mysql_execute_command(THD *thd)
|
||||
LEX *lex= thd->lex;
|
||||
/* first SELECT_LEX (have special meaning for many of non-SELECTcommands) */
|
||||
SELECT_LEX *select_lex= &lex->select_lex;
|
||||
bool slave_fake_lock= 0;
|
||||
MYSQL_LOCK *fake_prev_lock= 0;
|
||||
/* first table of first SELECT_LEX */
|
||||
TABLE_LIST *first_table= (TABLE_LIST*) select_lex->table_list.first;
|
||||
/* list of all tables in query */
|
||||
@ -2367,34 +2365,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))
|
||||
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, all_tables))
|
||||
@ -3220,6 +3205,17 @@ end_with_restore_list:
|
||||
else
|
||||
res= 0;
|
||||
|
||||
if ((res= mysql_multi_update_prepare(thd)))
|
||||
break;
|
||||
|
||||
/* Check slave filtering rules */
|
||||
if (thd->slave_thread && 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, all_tables,
|
||||
&select_lex->item_list,
|
||||
&lex->value_list,
|
||||
@ -4774,14 +4770,6 @@ error:
|
||||
res= 1;
|
||||
|
||||
cleanup:
|
||||
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_RETURN(res || thd->net.report_error);
|
||||
}
|
||||
|
||||
@ -6914,57 +6902,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
|
||||
|
||||
RETURN VALUES
|
||||
0 ok
|
||||
1 error
|
||||
*/
|
||||
static bool check_multi_update_lock(THD *thd)
|
||||
{
|
||||
bool res= 1;
|
||||
LEX *lex= thd->lex;
|
||||
TABLE_LIST *table, *tables= lex->query_tables;
|
||||
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_local)
|
||||
{
|
||||
TABLE_LIST *save= table->next_local;
|
||||
table->next_local= 0;
|
||||
if ((check_access(thd, UPDATE_ACL, table->db,
|
||||
&table->grant.privilege,0,1, test(table->schema_table)) ||
|
||||
(grant_option && check_grant(thd, UPDATE_ACL, table,0,1,1))) &&
|
||||
check_one_table_access(thd, SELECT_ACL, table))
|
||||
goto error;
|
||||
table->next_local= save;
|
||||
}
|
||||
|
||||
if (mysql_multi_update_prepare(thd))
|
||||
goto error;
|
||||
|
||||
res= 0;
|
||||
|
||||
error:
|
||||
DBUG_RETURN(res);
|
||||
}
|
||||
|
||||
|
||||
Comp_creator *comp_eq_creator(bool invert)
|
||||
{
|
||||
|
@ -841,9 +841,6 @@ bool mysql_multi_update(THD *thd,
|
||||
multi_update *result;
|
||||
DBUG_ENTER("mysql_multi_update");
|
||||
|
||||
if (mysql_multi_update_prepare(thd))
|
||||
DBUG_RETURN(TRUE);
|
||||
|
||||
if (!(result= new multi_update(table_list,
|
||||
thd->lex->select_lex.leaf_tables,
|
||||
fields, values,
|
||||
|
Loading…
x
Reference in New Issue
Block a user