Merge mysql.com:/home/stewart/Documents/MySQL/5.0/merge-queue

into  mysql.com:/home/stewart/Documents/MySQL/5.0/main


ndb/src/mgmsrv/MgmtSrvr.cpp:
  Auto merged
ndb/src/mgmsrv/MgmtSrvr.hpp:
  Auto merged
ndb/src/mgmsrv/Services.cpp:
  Auto merged
This commit is contained in:
unknown 2006-06-16 21:01:02 +10:00
commit 70cf824053
53 changed files with 974 additions and 209 deletions

View file

@ -144,6 +144,10 @@ SOURCE=.\readline.cpp
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\mysys\my_conio.c
# End Source File
# Begin Source File
SOURCE=.\sql_string.cpp SOURCE=.\sql_string.cpp
# End Source File # End Source File
# End Target # End Target

View file

@ -130,6 +130,10 @@ SOURCE=.\readline.cpp
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\mysys\my_conio.c
# End Source File
# Begin Source File
SOURCE=.\sql_string.cpp SOURCE=.\sql_string.cpp
# End Source File # End Source File
# End Target # End Target

View file

@ -880,7 +880,7 @@ int sendData(SSL& ssl, const void* buffer, int sz)
ssl.SetError(no_error); ssl.SetError(no_error);
ssl.verfiyHandShakeComplete(); ssl.verfiyHandShakeComplete();
if (ssl.GetError()) return 0; if (ssl.GetError()) return -1;
int sent = 0; int sent = 0;
for (;;) { for (;;) {
@ -891,7 +891,7 @@ int sendData(SSL& ssl, const void* buffer, int sz)
buildMessage(ssl, out, data); buildMessage(ssl, out, data);
ssl.Send(out.get_buffer(), out.get_size()); ssl.Send(out.get_buffer(), out.get_size());
if (ssl.GetError()) return 0; if (ssl.GetError()) return -1;
sent += len; sent += len;
if (sent == sz) break; if (sent == sz) break;
} }
@ -918,14 +918,14 @@ int receiveData(SSL& ssl, Data& data)
ssl.SetError(no_error); ssl.SetError(no_error);
ssl.verfiyHandShakeComplete(); ssl.verfiyHandShakeComplete();
if (ssl.GetError()) return 0; if (ssl.GetError()) return -1;
if (!ssl.bufferedData()) if (!ssl.bufferedData())
processReply(ssl); processReply(ssl);
ssl.fillData(data); ssl.fillData(data);
ssl.useLog().ShowData(data.get_length()); ssl.useLog().ShowData(data.get_length());
if (ssl.GetError()) return 0; if (ssl.GetError()) return -1;
if (data.get_length() == 0 && ssl.getSocket().WouldBlock()) { if (data.get_length() == 0 && ssl.getSocket().WouldBlock()) {
ssl.SetError(YasslError(SSL_ERROR_WANT_READ)); ssl.SetError(YasslError(SSL_ERROR_WANT_READ));

View file

@ -113,13 +113,22 @@ uint Socket::get_ready() const
uint Socket::send(const byte* buf, unsigned int sz, int flags) const uint Socket::send(const byte* buf, unsigned int sz, int flags) const
{ {
const byte* pos = buf;
const byte* end = pos + sz;
assert(socket_ != INVALID_SOCKET); assert(socket_ != INVALID_SOCKET);
int sent = ::send(socket_, reinterpret_cast<const char *>(buf), sz, flags);
while (pos != end) {
int sent = ::send(socket_, reinterpret_cast<const char *>(pos),
static_cast<int>(end - pos), flags);
if (sent == -1) if (sent == -1)
return 0; return 0;
return sent; pos += sent;
}
return sz;
} }

View file

@ -453,25 +453,24 @@ int chk_key(MI_CHECK *param, register MI_INFO *info)
if ((uint) share->base.auto_key -1 == key) if ((uint) share->base.auto_key -1 == key)
{ {
/* Check that auto_increment key is bigger than max key value */ /* Check that auto_increment key is bigger than max key value */
ulonglong save_auto_value=info->s->state.auto_increment; ulonglong auto_increment;
info->s->state.auto_increment=0;
info->lastinx=key; info->lastinx=key;
_mi_read_key_record(info, 0L, info->rec_buff); _mi_read_key_record(info, 0L, info->rec_buff);
update_auto_increment(info, info->rec_buff); auto_increment= retrieve_auto_increment(info, info->rec_buff);
if (info->s->state.auto_increment > save_auto_value) if (auto_increment > info->s->state.auto_increment)
{ {
mi_check_print_warning(param, mi_check_print_warning(param, "Auto-increment value: %s is smaller "
"Auto-increment value: %s is smaller than max used value: %s", "than max used value: %s",
llstr(save_auto_value,buff2), llstr(info->s->state.auto_increment,buff2),
llstr(info->s->state.auto_increment, buff)); llstr(auto_increment, buff));
} }
if (param->testflag & T_AUTO_INC) if (param->testflag & T_AUTO_INC)
{ {
set_if_bigger(info->s->state.auto_increment, set_if_bigger(info->s->state.auto_increment,
param->auto_increment_value); auto_increment);
set_if_bigger(info->s->state.auto_increment,
param->auto_increment_value);
} }
else
info->s->state.auto_increment=save_auto_value;
/* Check that there isn't a row with auto_increment = 0 in the table */ /* Check that there isn't a row with auto_increment = 0 in the table */
mi_extra(info,HA_EXTRA_KEYREAD,0); mi_extra(info,HA_EXTRA_KEYREAD,0);
@ -481,8 +480,8 @@ int chk_key(MI_CHECK *param, register MI_INFO *info)
{ {
/* Don't count this as a real warning, as myisamchk can't correct it */ /* Don't count this as a real warning, as myisamchk can't correct it */
uint save=param->warning_printed; uint save=param->warning_printed;
mi_check_print_warning(param, mi_check_print_warning(param, "Found row where the auto_increment "
"Found row where the auto_increment column has the value 0"); "column has the value 0");
param->warning_printed=save; param->warning_printed=save;
} }
mi_extra(info,HA_EXTRA_NO_KEYREAD,0); mi_extra(info,HA_EXTRA_NO_KEYREAD,0);
@ -4099,11 +4098,10 @@ void update_auto_increment_key(MI_CHECK *param, MI_INFO *info,
} }
else else
{ {
ulonglong auto_increment= (repair_only ? info->s->state.auto_increment : ulonglong auto_increment= retrieve_auto_increment(info, record);
param->auto_increment_value);
info->s->state.auto_increment=0;
update_auto_increment(info, record);
set_if_bigger(info->s->state.auto_increment,auto_increment); set_if_bigger(info->s->state.auto_increment,auto_increment);
if (!repair_only)
set_if_bigger(info->s->state.auto_increment, param->auto_increment_value);
} }
mi_extra(info,HA_EXTRA_NO_KEYREAD,0); mi_extra(info,HA_EXTRA_NO_KEYREAD,0);
my_free((char*) record, MYF(0)); my_free((char*) record, MYF(0));

View file

@ -507,22 +507,21 @@ int _mi_read_key_record(MI_INFO *info, my_off_t filepos, byte *buf)
return(-1); /* Wrong data to read */ return(-1); /* Wrong data to read */
} }
/* /*
Update auto_increment info Retrieve auto_increment info
SYNOPSIS SYNOPSIS
update_auto_increment() retrieve_auto_increment()
info MyISAM handler info MyISAM handler
record Row to update record Row to update
IMPLEMENTATION IMPLEMENTATION
Only replace the auto_increment value if it is higher than the previous For signed columns we don't retrieve the auto increment value if it's
one. For signed columns we don't update the auto increment value if it's
less than zero. less than zero.
*/ */
void update_auto_increment(MI_INFO *info,const byte *record) ulonglong retrieve_auto_increment(MI_INFO *info,const byte *record)
{ {
ulonglong value= 0; /* Store unsigned values here */ ulonglong value= 0; /* Store unsigned values here */
longlong s_value= 0; /* Store signed values here */ longlong s_value= 0; /* Store signed values here */
@ -587,6 +586,5 @@ void update_auto_increment(MI_INFO *info,const byte *record)
and if s_value == 0 then value will contain either s_value or the and if s_value == 0 then value will contain either s_value or the
correct value. correct value.
*/ */
set_if_bigger(info->s->state.auto_increment, return (s_value > 0) ? (ulonglong) s_value : value;
(s_value > 0) ? (ulonglong) s_value : value);
} }

View file

@ -164,7 +164,8 @@ int mi_update(register MI_INFO *info, const byte *oldrec, byte *newrec)
key_changed|= HA_STATE_CHANGED; /* Must update index file */ key_changed|= HA_STATE_CHANGED; /* Must update index file */
} }
if (auto_key_changed) if (auto_key_changed)
update_auto_increment(info,newrec); set_if_bigger(info->s->state.auto_increment,
retrieve_auto_increment(info, newrec));
if (share->calc_checksum) if (share->calc_checksum)
info->state->checksum+=(info->checksum - old_checksum); info->state->checksum+=(info->checksum - old_checksum);

View file

@ -149,7 +149,8 @@ int mi_write(MI_INFO *info, byte *record)
info->state->checksum+=info->checksum; info->state->checksum+=info->checksum;
} }
if (share->base.auto_key) if (share->base.auto_key)
update_auto_increment(info,record); set_if_bigger(info->s->state.auto_increment,
retrieve_auto_increment(info, record));
info->update= (HA_STATE_CHANGED | HA_STATE_AKTIV | HA_STATE_WRITTEN | info->update= (HA_STATE_CHANGED | HA_STATE_AKTIV | HA_STATE_WRITTEN |
HA_STATE_ROW_CHANGED); HA_STATE_ROW_CHANGED);
info->state->records++; info->state->records++;

View file

@ -582,7 +582,7 @@ extern uint _mi_pack_key(MI_INFO *info,uint keynr,uchar *key,uchar *old,
extern int _mi_read_key_record(MI_INFO *info,my_off_t filepos,byte *buf); extern int _mi_read_key_record(MI_INFO *info,my_off_t filepos,byte *buf);
extern int _mi_read_cache(IO_CACHE *info,byte *buff,my_off_t pos, extern int _mi_read_cache(IO_CACHE *info,byte *buff,my_off_t pos,
uint length,int re_read_if_possibly); uint length,int re_read_if_possibly);
extern void update_auto_increment(MI_INFO *info,const byte *record); extern ulonglong retrieve_auto_increment(MI_INFO *info,const byte *record);
extern byte *mi_alloc_rec_buff(MI_INFO *,ulong, byte**); extern byte *mi_alloc_rec_buff(MI_INFO *,ulong, byte**);
#define mi_get_rec_buff_ptr(info,buf) \ #define mi_get_rec_buff_ptr(info,buf) \

View file

@ -671,6 +671,12 @@ sub command_line_setup () {
{ {
push(@opt_extra_mysqld_opt, $arg); push(@opt_extra_mysqld_opt, $arg);
} }
elsif ( $arg =~ /^--$/ )
{
# It is an effect of setting 'pass_through' in option processing
# that the lone '--' separating options from arguments survives,
# simply ignore it.
}
elsif ( $arg =~ /^-/ ) elsif ( $arg =~ /^-/ )
{ {
usage("Invalid option \"$arg\""); usage("Invalid option \"$arg\"");
@ -3428,6 +3434,13 @@ sub valgrind_arguments {
############################################################################## ##############################################################################
sub usage ($) { sub usage ($) {
my $message= shift;
if ( $message )
{
print STDERR "$message \n";
}
print STDERR <<HERE; print STDERR <<HERE;
mysql-test-run [ OPTIONS ] [ TESTCASE ] mysql-test-run [ OPTIONS ] [ TESTCASE ]

View file

@ -172,6 +172,6 @@ c2h
ab_def ab_def
drop table t1; drop table t1;
SET NAMES sjis; SET NAMES sjis;
SELECT HEX('佐淘 \圭') FROM DUAL; SELECT HEX('佐淘 圭') FROM DUAL;
HEX('佐淘 圭') HEX('佐淘 圭')
8DB2939181408C5C 8DB2939181408C5C

View file

@ -7,20 +7,20 @@ period_add("9602",-12) period_diff(199505,"9404")
199502 13 199502 13
select now()-now(),weekday(curdate())-weekday(now()),unix_timestamp()-unix_timestamp(now()); select now()-now(),weekday(curdate())-weekday(now()),unix_timestamp()-unix_timestamp(now());
now()-now() weekday(curdate())-weekday(now()) unix_timestamp()-unix_timestamp(now()) now()-now() weekday(curdate())-weekday(now()) unix_timestamp()-unix_timestamp(now())
0 0 0 0.000000 0 0
select from_unixtime(unix_timestamp("1994-03-02 10:11:12")),from_unixtime(unix_timestamp("1994-03-02 10:11:12"),"%Y-%m-%d %h:%i:%s"),from_unixtime(unix_timestamp("1994-03-02 10:11:12"))+0; select from_unixtime(unix_timestamp("1994-03-02 10:11:12")),from_unixtime(unix_timestamp("1994-03-02 10:11:12"),"%Y-%m-%d %h:%i:%s"),from_unixtime(unix_timestamp("1994-03-02 10:11:12"))+0;
from_unixtime(unix_timestamp("1994-03-02 10:11:12")) from_unixtime(unix_timestamp("1994-03-02 10:11:12"),"%Y-%m-%d %h:%i:%s") from_unixtime(unix_timestamp("1994-03-02 10:11:12"))+0 from_unixtime(unix_timestamp("1994-03-02 10:11:12")) from_unixtime(unix_timestamp("1994-03-02 10:11:12"),"%Y-%m-%d %h:%i:%s") from_unixtime(unix_timestamp("1994-03-02 10:11:12"))+0
1994-03-02 10:11:12 1994-03-02 10:11:12 19940302101112 1994-03-02 10:11:12 1994-03-02 10:11:12 19940302101112.000000
select sec_to_time(9001),sec_to_time(9001)+0,time_to_sec("15:12:22"), select sec_to_time(9001),sec_to_time(9001)+0,time_to_sec("15:12:22"),
sec_to_time(time_to_sec("0:30:47")/6.21); sec_to_time(time_to_sec("0:30:47")/6.21);
sec_to_time(9001) sec_to_time(9001)+0 time_to_sec("15:12:22") sec_to_time(time_to_sec("0:30:47")/6.21) sec_to_time(9001) sec_to_time(9001)+0 time_to_sec("15:12:22") sec_to_time(time_to_sec("0:30:47")/6.21)
02:30:01 23001 54742 00:04:57 02:30:01 23001.000000 54742 00:04:57
select sec_to_time(time_to_sec('-838:59:59')); select sec_to_time(time_to_sec('-838:59:59'));
sec_to_time(time_to_sec('-838:59:59')) sec_to_time(time_to_sec('-838:59:59'))
-838:59:59 -838:59:59
select now()-curdate()*1000000-curtime(); select now()-curdate()*1000000-curtime();
now()-curdate()*1000000-curtime() now()-curdate()*1000000-curtime()
0 0.000000
select strcmp(current_timestamp(),concat(current_date()," ",current_time())); select strcmp(current_timestamp(),concat(current_date()," ",current_time()));
strcmp(current_timestamp(),concat(current_date()," ",current_time())) strcmp(current_timestamp(),concat(current_date()," ",current_time()))
0 0
@ -751,6 +751,10 @@ select monthname(str_to_date(null, '%m')), monthname(str_to_date(null, '%m')),
monthname(str_to_date(1, '%m')), monthname(str_to_date(0, '%m')); monthname(str_to_date(1, '%m')), monthname(str_to_date(0, '%m'));
monthname(str_to_date(null, '%m')) monthname(str_to_date(null, '%m')) monthname(str_to_date(1, '%m')) monthname(str_to_date(0, '%m')) monthname(str_to_date(null, '%m')) monthname(str_to_date(null, '%m')) monthname(str_to_date(1, '%m')) monthname(str_to_date(0, '%m'))
NULL NULL January NULL NULL NULL January NULL
select now() - now() + 0, curtime() - curtime() + 0,
sec_to_time(1) + 0, from_unixtime(1) + 0;
now() - now() + 0 curtime() - curtime() + 0 sec_to_time(1) + 0 from_unixtime(1) + 0
0.000000 0.000000 1.000000 19700101030001.000000
explain extended select timestampdiff(SQL_TSI_WEEK, '2001-02-01', '2001-05-01') as a1, explain extended select timestampdiff(SQL_TSI_WEEK, '2001-02-01', '2001-05-01') as a1,
timestampdiff(SQL_TSI_FRAC_SECOND, '2001-02-01 12:59:59.120000', '2001-05-01 12:58:58.119999') as a2; timestampdiff(SQL_TSI_FRAC_SECOND, '2001-02-01 12:59:59.120000', '2001-05-01 12:58:58.119999') as a2;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra

View file

@ -43,6 +43,14 @@ Field Type Null Key Default Extra
a int(11) YES NULL a int(11) YES NULL
unlock tables; unlock tables;
drop table t1; drop table t1;
CREATE DATABASE mysqltest_1;
FLUSH TABLES WITH READ LOCK;
DROP DATABASE mysqltest_1;
DROP DATABASE mysqltest_1;
ERROR HY000: Can't execute the query because you have a conflicting read lock
UNLOCK TABLES;
DROP DATABASE mysqltest_1;
ERROR HY000: Can't drop database 'mysqltest_1'; database doesn't exist
use mysql; use mysql;
LOCK TABLES columns_priv WRITE, db WRITE, host WRITE, user WRITE; LOCK TABLES columns_priv WRITE, db WRITE, host WRITE, user WRITE;
FLUSH TABLES; FLUSH TABLES;

View file

@ -776,3 +776,9 @@ insert into t1 values ("Monty"),("WAX"),("Walrus");
alter table t1 engine=MERGE; alter table t1 engine=MERGE;
ERROR HY000: Table storage engine for 't1' doesn't have this option ERROR HY000: Table storage engine for 't1' doesn't have this option
drop table t1; drop table t1;
create table t1 (b bit(1));
create table t2 (b bit(1));
create table tm (b bit(1)) engine = merge union = (t1,t2);
select * from tm;
b
drop table tm, t1, t2;

View file

@ -1842,5 +1842,29 @@ a b
select * from t1 where b like 'abc' or b like 'abc'; select * from t1 where b like 'abc' or b like 'abc';
a b a b
3 abc 3 abc
drop table t1;
create table t1 ( fname varchar(255), lname varchar(255) )
engine=ndbcluster;
insert into t1 values ("Young","Foo");
set engine_condition_pushdown = 0;
SELECT fname, lname FROM t1 WHERE (fname like 'Y%') or (lname like 'F%');
fname lname
Young Foo
set engine_condition_pushdown = 1;
SELECT fname, lname FROM t1 WHERE (fname like 'Y%') or (lname like 'F%');
fname lname
Young Foo
insert into t1 values ("aaa", "aaa");
insert into t1 values ("bbb", "bbb");
insert into t1 values ("ccc", "ccc");
insert into t1 values ("ddd", "ddd");
set engine_condition_pushdown = 0;
SELECT fname, lname FROM t1 WHERE (fname like 'Y%') or (lname like 'F%');
fname lname
Young Foo
set engine_condition_pushdown = 1;
SELECT fname, lname FROM t1 WHERE (fname like 'Y%') or (lname like 'F%');
fname lname
Young Foo
set engine_condition_pushdown = @old_ecpd; set engine_condition_pushdown = @old_ecpd;
DROP TABLE t1,t2,t3,t4,t5; DROP TABLE t1,t2,t3,t4,t5;

View file

@ -0,0 +1,46 @@
DROP TABLE IF EXISTS t1;
create table t1(a int) engine=myisam;
select * into outfile 'MYSQLTEST_VARDIR/master-data/ndb_loaddatalocal.select_outfile' from t1;
drop table t1;
create table t1(a int) engine=ndb;
load data local infile 'MYSQLTEST_VARDIR/master-data/ndb_loaddatalocal.select_outfile' into table t1;
select count(*) from t1;
count(*)
10000
drop table t1;
create table t1(a int) engine=myisam;
insert into t1 values (1), (2), (2), (3);
select * into outfile 'MYSQLTEST_VARDIR/master-data/ndb_loaddatalocal.select_outfile' from t1;
drop table t1;
create table t1(a int primary key) engine=ndb;
load data local infile 'MYSQLTEST_VARDIR/master-data/ndb_loaddatalocal.select_outfile' into table t1;
select * from t1 order by a;
a
1
2
3
drop table t1;
create table t1(a int) engine=myisam;
insert into t1 values (1), (1), (2), (3);
select * into outfile 'MYSQLTEST_VARDIR/master-data/ndb_loaddatalocal.select_outfile' from t1;
drop table t1;
create table t1(a int primary key) engine=ndb;
load data local infile 'MYSQLTEST_VARDIR/master-data/ndb_loaddatalocal.select_outfile' into table t1;
select * from t1 order by a;
a
1
2
3
drop table t1;
create table t1(a int) engine=myisam;
insert into t1 values (1), (2), (3), (3);
select * into outfile 'MYSQLTEST_VARDIR/master-data/ndb_loaddatalocal.select_outfile' from t1;
drop table t1;
create table t1(a int primary key) engine=ndb;
load data local infile 'MYSQLTEST_VARDIR/master-data/ndb_loaddatalocal.select_outfile' into table t1;
select * from t1 order by a;
a
1
2
3
drop table t1;

View file

@ -63,3 +63,83 @@ pk u o
5 5 5 5 5 5
insert into t1 values (1,1,1); insert into t1 values (1,1,1);
drop table t1; drop table t1;
create table t1 (x integer not null primary key, y varchar(32), z integer, key(z)) engine = ndb;
insert into t1 values (1,'one',1), (2,'two',2),(3,"three",3);
begin;
select * from t1 where x = 1 for update;
x y z
1 one 1
begin;
select * from t1 where x = 2 for update;
x y z
2 two 2
select * from t1 where x = 1 for update;
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
rollback;
commit;
begin;
select * from t1 where y = 'one' or y = 'three' order by x for update;
x y z
1 one 1
3 three 3
begin;
select * from t1 where x = 1 for update;
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
rollback;
commit;
begin;
select * from t1 where z > 1 and z < 3 for update;
x y z
2 two 2
begin;
select * from t1 where x = 1 for update;
x y z
1 one 1
select * from t1 where x = 2 for update;
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
rollback;
commit;
begin;
select * from t1 where x = 1 lock in share mode;
x y z
1 one 1
begin;
select * from t1 where x = 1 lock in share mode;
x y z
1 one 1
select * from t1 where x = 2 for update;
x y z
2 two 2
select * from t1 where x = 1 for update;
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
rollback;
commit;
begin;
select * from t1 where y = 'one' or y = 'three' order by x lock in share mode;
x y z
1 one 1
3 three 3
begin;
select * from t1 where y = 'one' lock in share mode;
x y z
1 one 1
select * from t1 where x = 1 for update;
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
rollback;
commit;
begin;
select * from t1 where z > 1 and z < 3 lock in share mode;
x y z
2 two 2
begin;
select * from t1 where z = 1 lock in share mode;
x y z
1 one 1
select * from t1 where x = 1 for update;
x y z
1 one 1
select * from t1 where x = 2 for update;
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
rollback;
commit;
drop table t1;

View file

@ -1,14 +1,23 @@
DROP TABLE IF EXISTS t2; DROP TABLE IF EXISTS t1, t2;
CREATE TABLE t2 ( CREATE TABLE t1 (
a bigint unsigned NOT NULL PRIMARY KEY, a bigint unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY,
b int unsigned not null, b int unsigned not null,
c int unsigned c int unsigned
) engine=ndbcluster; ) engine=ndbcluster;
select count(*) from t2; select count(*) from t1;
count(*) count(*)
5000 5000
truncate table t2; select * from t1 order by a limit 2;
select count(*) from t2; a b c
1 509 2500
2 510 7
truncate table t1;
select count(*) from t1;
count(*) count(*)
0 0
drop table t2; insert into t1 values(NULL,1,1),(NULL,2,2);
select * from t1 order by a;
a b c
1 1 1
2 2 2
drop table t1;

View file

@ -1,4 +1,4 @@
set timestamp=1; set timestamp=1;
SELECT sleep(1),NOW()-SYSDATE() as zero; SELECT sleep(1),NOW()-SYSDATE() as zero;
sleep(1) zero sleep(1) zero
0 0 0 0.000000

View file

@ -1397,3 +1397,14 @@ c1
9999999999999999999999999999999999999999999999999999999999999999 9999999999999999999999999999999999999999999999999999999999999999
9999999999999999999999999999999999999999999999999999999999999999 9999999999999999999999999999999999999999999999999999999999999999
drop table t1; drop table t1;
create table t1 (i int, j int);
insert into t1 values (1,1), (1,2), (2,3), (2,4);
select i, count(distinct j) from t1 group by i;
i count(distinct j)
1 2
2 2
select i+0.0 as i2, count(distinct j) from t1 group by i2;
i2 count(distinct j)
1.0 2
2.0 2
drop table t1;

View file

@ -618,3 +618,32 @@ ERROR HY000: There is no 'no-such-user'@'localhost' registered
DROP VIEW v; DROP VIEW v;
DROP TABLE t1; DROP TABLE t1;
USE test; USE test;
CREATE USER mysqltest_db1@localhost identified by 'PWD';
GRANT ALL ON mysqltest_db1.* TO mysqltest_db1@localhost WITH GRANT OPTION;
CREATE SCHEMA mysqltest_db1 ;
USE mysqltest_db1 ;
CREATE TABLE t1 (f1 INTEGER);
CREATE VIEW view1 AS
SELECT * FROM t1;
SHOW CREATE VIEW view1;
View Create View
view1 CREATE ALGORITHM=UNDEFINED DEFINER=`mysqltest_db1`@`localhost` SQL SECURITY DEFINER VIEW `view1` AS select `t1`.`f1` AS `f1` from `t1`
CREATE VIEW view2 AS
SELECT * FROM view1;
# Here comes a suspicious warning
SHOW CREATE VIEW view2;
View Create View
view2 CREATE ALGORITHM=UNDEFINED DEFINER=`mysqltest_db1`@`localhost` SQL SECURITY DEFINER VIEW `view2` AS select `view1`.`f1` AS `f1` from `view1`
# But the view view2 is usable
SELECT * FROM view2;
f1
CREATE VIEW view3 AS
SELECT * FROM view2;
SELECT * from view3;
f1
DROP VIEW mysqltest_db1.view3;
DROP VIEW mysqltest_db1.view2;
DROP VIEW mysqltest_db1.view1;
DROP TABLE mysqltest_db1.t1;
DROP SCHEMA mysqltest_db1;
DROP USER mysqltest_db1@localhost;

View file

@ -78,6 +78,6 @@ SET collation_connection='sjis_bin';
--character_set sjis --character_set sjis
SET NAMES sjis; SET NAMES sjis;
SELECT HEX('佐淘 \圭') FROM DUAL; SELECT HEX('佐淘 圭') FROM DUAL;
# End of 4.1 tests # End of 4.1 tests

View file

@ -367,6 +367,13 @@ select last_day('2005-01-00');
select monthname(str_to_date(null, '%m')), monthname(str_to_date(null, '%m')), select monthname(str_to_date(null, '%m')), monthname(str_to_date(null, '%m')),
monthname(str_to_date(1, '%m')), monthname(str_to_date(0, '%m')); monthname(str_to_date(1, '%m')), monthname(str_to_date(0, '%m'));
#
# Bug #16546
#
select now() - now() + 0, curtime() - curtime() + 0,
sec_to_time(1) + 0, from_unixtime(1) + 0;
# End of 4.1 tests # End of 4.1 tests
explain extended select timestampdiff(SQL_TSI_WEEK, '2001-02-01', '2001-05-01') as a1, explain extended select timestampdiff(SQL_TSI_WEEK, '2001-02-01', '2001-05-01') as a1,

View file

@ -109,6 +109,39 @@ unlock tables;
drop table t1; drop table t1;
# #
# Bug#19815 - CREATE/RENAME/DROP DATABASE can deadlock on a global read lock
#
connect (con1,localhost,root,,);
connect (con2,localhost,root,,);
#
connection con1;
CREATE DATABASE mysqltest_1;
FLUSH TABLES WITH READ LOCK;
#
# With bug in place: acquire LOCK_mysql_create_table and
# wait in wait_if_global_read_lock().
connection con2;
send DROP DATABASE mysqltest_1;
--sleep 1
#
# With bug in place: try to acquire LOCK_mysql_create_table...
# When fixed: Reject dropping db because of the read lock.
connection con1;
--error ER_CANT_UPDATE_WITH_READLOCK
DROP DATABASE mysqltest_1;
UNLOCK TABLES;
#
connection con2;
reap;
#
connection default;
disconnect con1;
disconnect con2;
# This must have been dropped by connection 2 already,
# which waited until the global read lock was released.
--error ER_DB_DROP_EXISTS
DROP DATABASE mysqltest_1;
# Bug#16986 - Deadlock condition with MyISAM tables # Bug#16986 - Deadlock condition with MyISAM tables
# #
connection locker; connection locker;

View file

@ -390,4 +390,13 @@ insert into t1 values ("Monty"),("WAX"),("Walrus");
alter table t1 engine=MERGE; alter table t1 engine=MERGE;
drop table t1; drop table t1;
#
# BUG#19648 - Merge table does not work with bit types
#
create table t1 (b bit(1));
create table t2 (b bit(1));
create table tm (b bit(1)) engine = merge union = (t1,t2);
select * from tm;
drop table tm, t1, t2;
# End of 5.0 tests # End of 5.0 tests

View file

@ -1686,5 +1686,27 @@ select * from t1 where b like 'ab' or b like 'ab';
select * from t1 where b like 'abc'; select * from t1 where b like 'abc';
select * from t1 where b like 'abc' or b like 'abc'; select * from t1 where b like 'abc' or b like 'abc';
# bug#20406 (maybe same as bug#17421 -1, not seen on 32-bit x86)
drop table t1;
create table t1 ( fname varchar(255), lname varchar(255) )
engine=ndbcluster;
insert into t1 values ("Young","Foo");
set engine_condition_pushdown = 0;
SELECT fname, lname FROM t1 WHERE (fname like 'Y%') or (lname like 'F%');
set engine_condition_pushdown = 1;
SELECT fname, lname FROM t1 WHERE (fname like 'Y%') or (lname like 'F%');
# make sure optimizer does not do some crazy shortcut
insert into t1 values ("aaa", "aaa");
insert into t1 values ("bbb", "bbb");
insert into t1 values ("ccc", "ccc");
insert into t1 values ("ddd", "ddd");
set engine_condition_pushdown = 0;
SELECT fname, lname FROM t1 WHERE (fname like 'Y%') or (lname like 'F%');
set engine_condition_pushdown = 1;
SELECT fname, lname FROM t1 WHERE (fname like 'Y%') or (lname like 'F%');
set engine_condition_pushdown = @old_ecpd; set engine_condition_pushdown = @old_ecpd;
DROP TABLE t1,t2,t3,t4,t5; DROP TABLE t1,t2,t3,t4,t5;

View file

@ -0,0 +1,70 @@
-- source include/have_ndb.inc
-- source include/not_embedded.inc
--disable_warnings
DROP TABLE IF EXISTS t1;
--enable_warnings
create table t1(a int) engine=myisam;
let $1=10000;
disable_query_log;
set SQL_LOG_BIN=0;
while ($1)
{
insert into t1 values(1);
dec $1;
}
set SQL_LOG_BIN=1;
enable_query_log;
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
eval select * into outfile '$MYSQLTEST_VARDIR/master-data/ndb_loaddatalocal.select_outfile' from t1;
#This will generate a 20KB file, now test LOAD DATA LOCAL
drop table t1;
create table t1(a int) engine=ndb;
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
eval load data local infile '$MYSQLTEST_VARDIR/master-data/ndb_loaddatalocal.select_outfile' into table t1;
select count(*) from t1;
system rm $MYSQLTEST_VARDIR/master-data/ndb_loaddatalocal.select_outfile ;
drop table t1;
create table t1(a int) engine=myisam;
insert into t1 values (1), (2), (2), (3);
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
eval select * into outfile '$MYSQLTEST_VARDIR/master-data/ndb_loaddatalocal.select_outfile' from t1;
drop table t1;
create table t1(a int primary key) engine=ndb;
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
eval load data local infile '$MYSQLTEST_VARDIR/master-data/ndb_loaddatalocal.select_outfile' into table t1;
system rm $MYSQLTEST_VARDIR/master-data/ndb_loaddatalocal.select_outfile;
select * from t1 order by a;
drop table t1;
create table t1(a int) engine=myisam;
insert into t1 values (1), (1), (2), (3);
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
eval select * into outfile '$MYSQLTEST_VARDIR/master-data/ndb_loaddatalocal.select_outfile' from t1;
drop table t1;
create table t1(a int primary key) engine=ndb;
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
eval load data local infile '$MYSQLTEST_VARDIR/master-data/ndb_loaddatalocal.select_outfile' into table t1;
system rm $MYSQLTEST_VARDIR/master-data/ndb_loaddatalocal.select_outfile;
select * from t1 order by a;
drop table t1;
create table t1(a int) engine=myisam;
insert into t1 values (1), (2), (3), (3);
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
eval select * into outfile '$MYSQLTEST_VARDIR/master-data/ndb_loaddatalocal.select_outfile' from t1;
drop table t1;
create table t1(a int primary key) engine=ndb;
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
eval load data local infile '$MYSQLTEST_VARDIR/master-data/ndb_loaddatalocal.select_outfile' into table t1;
system rm $MYSQLTEST_VARDIR/master-data/ndb_loaddatalocal.select_outfile;
select * from t1 order by a;
drop table t1;
# End of 4.1 tests

View file

@ -69,4 +69,117 @@ insert into t1 values (1,1,1);
drop table t1; drop table t1;
# Lock for update
create table t1 (x integer not null primary key, y varchar(32), z integer, key(z)) engine = ndb;
insert into t1 values (1,'one',1), (2,'two',2),(3,"three",3);
# PK access
connection con1;
begin;
select * from t1 where x = 1 for update;
connection con2;
begin;
select * from t1 where x = 2 for update;
--error 1205
select * from t1 where x = 1 for update;
rollback;
connection con1;
commit;
# table scan
connection con1;
begin;
select * from t1 where y = 'one' or y = 'three' order by x for update;
connection con2;
begin;
# Have to check with pk access here since scans take locks on
# all rows and then release them in chunks
# Bug #20390 SELECT FOR UPDATE does not release locks of untouched rows in full table scans
#select * from t1 where x = 2 for update;
--error 1205
select * from t1 where x = 1 for update;
rollback;
connection con1;
commit;
# index scan
connection con1;
begin;
select * from t1 where z > 1 and z < 3 for update;
connection con2;
begin;
# Have to check with pk access here since scans take locks on
# all rows and then release them in chunks
select * from t1 where x = 1 for update;
--error 1205
select * from t1 where x = 2 for update;
rollback;
connection con1;
commit;
# share locking
# PK access
connection con1;
begin;
select * from t1 where x = 1 lock in share mode;
connection con2;
begin;
select * from t1 where x = 1 lock in share mode;
select * from t1 where x = 2 for update;
--error 1205
select * from t1 where x = 1 for update;
rollback;
connection con1;
commit;
# table scan
connection con1;
begin;
select * from t1 where y = 'one' or y = 'three' order by x lock in share mode;
connection con2;
begin;
select * from t1 where y = 'one' lock in share mode;
# Have to check with pk access here since scans take locks on
# all rows and then release them in chunks
# Bug #20390 SELECT FOR UPDATE does not release locks of untouched rows in full table scans
#select * from t1 where x = 2 for update;
--error 1205
select * from t1 where x = 1 for update;
rollback;
connection con1;
commit;
# index scan
connection con1;
begin;
select * from t1 where z > 1 and z < 3 lock in share mode;
connection con2;
begin;
select * from t1 where z = 1 lock in share mode;
# Have to check with pk access here since scans take locks on
# all rows and then release them in chunks
select * from t1 where x = 1 for update;
--error 1205
select * from t1 where x = 2 for update;
rollback;
connection con1;
commit;
drop table t1;
# End of 4.1 tests # End of 4.1 tests

View file

@ -2,12 +2,11 @@
-- source include/not_embedded.inc -- source include/not_embedded.inc
--disable_warnings --disable_warnings
DROP TABLE IF EXISTS t2; DROP TABLE IF EXISTS t1, t2;
--enable_warnings --enable_warnings
CREATE TABLE t1 (
CREATE TABLE t2 ( a bigint unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY,
a bigint unsigned NOT NULL PRIMARY KEY,
b int unsigned not null, b int unsigned not null,
c int unsigned c int unsigned
) engine=ndbcluster; ) engine=ndbcluster;
@ -20,17 +19,23 @@ let $1=500;
disable_query_log; disable_query_log;
while ($1) while ($1)
{ {
eval insert into t2 values($1*10, $1+9, 5*$1), ($1*10+1, $1+10, 7),($1*10+2, $1+10, 7*$1), ($1*10+3, $1+10, 10+$1), ($1*10+4, $1+10, 70*$1), ($1*10+5, $1+10, 7), ($1*10+6, $1+10, 9), ($1*10+7, $1+299, 899), ($1*10+8, $1+10, 12), ($1*10+9, $1+10, 14*$1); eval insert into t1 values(NULL, $1+9, 5*$1), (NULL, $1+10, 7),(NULL, $1+10, 7*$1), (NULL, $1+10, 10+$1), (NULL, $1+10, 70*$1), (NULL, $1+10, 7), (NULL, $1+10, 9), (NULL, $1+299, 899), (NULL, $1+10, 12), (NULL, $1+10, 14*$1);
dec $1; dec $1;
} }
enable_query_log; enable_query_log;
select count(*) from t2; select count(*) from t1;
truncate table t2; select * from t1 order by a limit 2;
select count(*) from t2; truncate table t1;
drop table t2; select count(*) from t1;
insert into t1 values(NULL,1,1),(NULL,2,2);
select * from t1 order by a;
drop table t1;
# End of 4.1 tests # End of 4.1 tests

View file

@ -1095,3 +1095,12 @@ insert into t1 values(
insert into t1 values(1e100); insert into t1 values(1e100);
select * from t1; select * from t1;
drop table t1; drop table t1;
#
# Bug#19667 group by a decimal expression yields wrong result
#
create table t1 (i int, j int);
insert into t1 values (1,1), (1,2), (2,3), (2,4);
select i, count(distinct j) from t1 group by i;
select i+0.0 as i2, count(distinct j) from t1 group by i2;
drop table t1;

View file

@ -807,3 +807,42 @@ SELECT * FROM v;
DROP VIEW v; DROP VIEW v;
DROP TABLE t1; DROP TABLE t1;
USE test; USE test;
#
# Bug#20363: Create view on just created view is now denied
#
eval CREATE USER mysqltest_db1@localhost identified by 'PWD';
eval GRANT ALL ON mysqltest_db1.* TO mysqltest_db1@localhost WITH GRANT OPTION;
# The session with the non root user is needed.
--replace_result $MASTER_MYPORT MYSQL_PORT $MASTER_MYSOCK MYSQL_SOCK
connect (session1,localhost,mysqltest_db1,PWD,test);
CREATE SCHEMA mysqltest_db1 ;
USE mysqltest_db1 ;
CREATE TABLE t1 (f1 INTEGER);
CREATE VIEW view1 AS
SELECT * FROM t1;
SHOW CREATE VIEW view1;
CREATE VIEW view2 AS
SELECT * FROM view1;
--echo # Here comes a suspicious warning
SHOW CREATE VIEW view2;
--echo # But the view view2 is usable
SELECT * FROM view2;
CREATE VIEW view3 AS
SELECT * FROM view2;
SELECT * from view3;
connection default;
DROP VIEW mysqltest_db1.view3;
DROP VIEW mysqltest_db1.view2;
DROP VIEW mysqltest_db1.view1;
DROP TABLE mysqltest_db1.t1;
DROP SCHEMA mysqltest_db1;
DROP USER mysqltest_db1@localhost;

View file

@ -292,3 +292,18 @@
futex(utime) futex(utime)
fun:__lll_mutex_unlock_wake fun:__lll_mutex_unlock_wake
} }
#
# BUG#19940: NDB sends uninitialized parts of field buffers across the wire.
# This is "works as designed"; the uninitialized part is not used at the
# other end (but Valgrind cannot see this).
#
{
bug19940
Memcheck:Param
socketcall.sendto(msg)
fun:send
fun:_ZN15TCP_Transporter6doSendEv
fun:_ZN19TransporterRegistry11performSendEv
fun:_ZN19TransporterRegistry14forceSendCheckEi
}

View file

@ -61,11 +61,14 @@ public:
Uint32 parallel, Uint32 parallel,
bool order_by, bool order_by,
bool order_desc = false, bool order_desc = false,
bool read_range_no = false) { bool read_range_no = false,
bool keyinfo = false) {
Uint32 scan_flags = Uint32 scan_flags =
(SF_OrderBy & -(Int32)order_by) | (SF_OrderBy & -(Int32)order_by) |
(SF_Descending & -(Int32)order_desc) | (SF_Descending & -(Int32)order_desc) |
(SF_ReadRangeNo & -(Int32)read_range_no); (SF_ReadRangeNo & -(Int32)read_range_no) |
(SF_KeyInfo & -(Int32)keyinfo);
return readTuples(lock_mode, scan_flags, parallel); return readTuples(lock_mode, scan_flags, parallel);
} }
#endif #endif

View file

@ -44,7 +44,8 @@ public:
SF_TupScan = (1 << 16), // scan TUP - only LM_CommittedRead SF_TupScan = (1 << 16), // scan TUP - only LM_CommittedRead
SF_OrderBy = (1 << 24), // index scan in order SF_OrderBy = (1 << 24), // index scan in order
SF_Descending = (2 << 24), // index scan in descending order SF_Descending = (2 << 24), // index scan in descending order
SF_ReadRangeNo = (4 << 24) // enable @ref get_range_no SF_ReadRangeNo = (4 << 24), // enable @ref get_range_no
SF_KeyInfo = 1 // request KeyInfo to be sent back
}; };
/** /**
@ -61,15 +62,14 @@ public:
#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED #ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
/** /**
* readTuples * readTuples
*
* @param lock_mode Lock mode * @param lock_mode Lock mode
* @param batch No of rows to fetch from each fragment at a time * @param batch No of rows to fetch from each fragment at a time
* @param parallel No of fragments to scan in parallell * @param parallel No of fragments to scan in parallell
* @note specifying 0 for batch and parallall means max performance * @note specifying 0 for batch and parallell means max performance
*/ */
#ifdef ndb_readtuples_impossible_overload #ifdef ndb_readtuples_impossible_overload
int readTuples(LockMode lock_mode = LM_Read, int readTuples(LockMode lock_mode = LM_Read,
Uint32 batch = 0, Uint32 parallel = 0); Uint32 batch = 0, Uint32 parallel = 0, bool keyinfo = false);
#endif #endif
inline int readTuples(int parallell){ inline int readTuples(int parallell){
@ -141,6 +141,20 @@ public:
*/ */
void close(bool forceSend = false, bool releaseOp = false); void close(bool forceSend = false, bool releaseOp = false);
/**
* Lock current tuple
*
* @return an NdbOperation or NULL.
*/
NdbOperation* lockCurrentTuple();
/**
* Lock current tuple
*
* @param lockTrans Transaction that should perform the lock
*
* @return an NdbOperation or NULL.
*/
NdbOperation* lockCurrentTuple(NdbTransaction* lockTrans);
/** /**
* Update current tuple * Update current tuple
* *
@ -249,6 +263,19 @@ protected:
NdbRecAttr *m_curr_row; // Pointer to last returned row NdbRecAttr *m_curr_row; // Pointer to last returned row
}; };
inline
NdbOperation*
NdbScanOperation::lockCurrentTuple(){
return lockCurrentTuple(m_transConnection);
}
inline
NdbOperation*
NdbScanOperation::lockCurrentTuple(NdbTransaction* takeOverTrans){
return takeOverScanOp(NdbOperation::ReadRequest,
takeOverTrans);
}
inline inline
NdbOperation* NdbOperation*
NdbScanOperation::updateCurrentTuple(){ NdbScanOperation::updateCurrentTuple(){

View file

@ -234,6 +234,7 @@ void Cmvmi::execEVENT_REP(Signal* signal)
void void
Cmvmi::execEVENT_SUBSCRIBE_REQ(Signal * signal){ Cmvmi::execEVENT_SUBSCRIBE_REQ(Signal * signal){
EventSubscribeReq * subReq = (EventSubscribeReq *)&signal->theData[0]; EventSubscribeReq * subReq = (EventSubscribeReq *)&signal->theData[0];
Uint32 senderRef = signal->getSendersBlockRef();
SubscriberPtr ptr; SubscriberPtr ptr;
jamEntry(); jamEntry();
DBUG_ENTER("Cmvmi::execEVENT_SUBSCRIBE_REQ"); DBUG_ENTER("Cmvmi::execEVENT_SUBSCRIBE_REQ");
@ -251,7 +252,7 @@ Cmvmi::execEVENT_SUBSCRIBE_REQ(Signal * signal){
* Create a new one * Create a new one
*/ */
if(subscribers.seize(ptr) == false){ if(subscribers.seize(ptr) == false){
sendSignal(subReq->blockRef, GSN_EVENT_SUBSCRIBE_REF, signal, 1, JBB); sendSignal(senderRef, GSN_EVENT_SUBSCRIBE_REF, signal, 1, JBB);
return; return;
} }
ptr.p->logLevel.clear(); ptr.p->logLevel.clear();
@ -278,7 +279,7 @@ Cmvmi::execEVENT_SUBSCRIBE_REQ(Signal * signal){
} }
signal->theData[0] = ptr.i; signal->theData[0] = ptr.i;
sendSignal(ptr.p->blockRef, GSN_EVENT_SUBSCRIBE_CONF, signal, 1, JBB); sendSignal(senderRef, GSN_EVENT_SUBSCRIBE_CONF, signal, 1, JBB);
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }

View file

@ -119,41 +119,50 @@ MgmtSrvr::logLevelThreadRun()
/** /**
* Handle started nodes * Handle started nodes
*/ */
EventSubscribeReq req;
req = m_event_listner[0].m_logLevel;
req.blockRef = _ownReference;
SetLogLevelOrd ord;
m_started_nodes.lock(); m_started_nodes.lock();
while(m_started_nodes.size() > 0){ if (m_started_nodes.size() > 0)
Uint32 node = m_started_nodes[0]; {
m_started_nodes.erase(0, false); // calculate max log level
m_started_nodes.unlock(); EventSubscribeReq req;
{
LogLevel tmp;
m_event_listner.lock();
for(int i = m_event_listner.m_clients.size() - 1; i >= 0; i--)
tmp.set_max(m_event_listner[i].m_logLevel);
m_event_listner.unlock();
req = tmp;
}
req.blockRef = _ownReference;
while (m_started_nodes.size() > 0)
{
Uint32 node = m_started_nodes[0];
m_started_nodes.erase(0, false);
m_started_nodes.unlock();
setEventReportingLevelImpl(node, req); setEventReportingLevelImpl(node, req);
ord = m_nodeLogLevel[node]; SetLogLevelOrd ord;
setNodeLogLevelImpl(node, ord); ord = m_nodeLogLevel[node];
setNodeLogLevelImpl(node, ord);
m_started_nodes.lock();
} m_started_nodes.lock();
}
}
m_started_nodes.unlock(); m_started_nodes.unlock();
m_log_level_requests.lock(); m_log_level_requests.lock();
while(m_log_level_requests.size() > 0){ while (m_log_level_requests.size() > 0)
req = m_log_level_requests[0]; {
EventSubscribeReq req = m_log_level_requests[0];
m_log_level_requests.erase(0, false); m_log_level_requests.erase(0, false);
m_log_level_requests.unlock(); m_log_level_requests.unlock();
LogLevel tmp;
tmp = req;
if(req.blockRef == 0){ if(req.blockRef == 0){
req.blockRef = _ownReference; req.blockRef = _ownReference;
setEventReportingLevelImpl(0, req); setEventReportingLevelImpl(0, req);
} else { } else {
ord = req; SetLogLevelOrd ord;
ord = req;
setNodeLogLevelImpl(req.blockRef, ord); setNodeLogLevelImpl(req.blockRef, ord);
} }
m_log_level_requests.lock(); m_log_level_requests.lock();
@ -1538,7 +1547,8 @@ int
MgmtSrvr::setEventReportingLevelImpl(int nodeId, MgmtSrvr::setEventReportingLevelImpl(int nodeId,
const EventSubscribeReq& ll) const EventSubscribeReq& ll)
{ {
INIT_SIGNAL_SENDER(ss,nodeId); SignalSender ss(theFacade);
ss.lock();
SimpleSignal ssig; SimpleSignal ssig;
EventSubscribeReq * dst = EventSubscribeReq * dst =
@ -1547,41 +1557,54 @@ MgmtSrvr::setEventReportingLevelImpl(int nodeId,
EventSubscribeReq::SignalLength); EventSubscribeReq::SignalLength);
*dst = ll; *dst = ll;
send(ss,ssig,nodeId,NODE_TYPE_DB); NodeBitmask nodes;
nodes.clear();
Uint32 max = (nodeId == 0) ? (nodeId = 1, MAX_NDB_NODES) : nodeId;
for(; nodeId <= max; nodeId++)
{
if (nodeTypes[nodeId] != NODE_TYPE_DB)
continue;
if (okToSendTo(nodeId, true))
continue;
if (ss.sendSignal(nodeId, &ssig) == SEND_OK)
{
nodes.set(nodeId);
}
}
#if 0 int error = 0;
while (1) while (!nodes.isclear())
{ {
SimpleSignal *signal = ss.waitFor(); SimpleSignal *signal = ss.waitFor();
int gsn = signal->readSignalNumber(); int gsn = signal->readSignalNumber();
switch (gsn) { nodeId = refToNode(signal->header.theSendersBlockRef);
switch (gsn) {
case GSN_EVENT_SUBSCRIBE_CONF:{ case GSN_EVENT_SUBSCRIBE_CONF:{
nodes.clear(nodeId);
break; break;
} }
case GSN_EVENT_SUBSCRIBE_REF:{ case GSN_EVENT_SUBSCRIBE_REF:{
return SEND_OR_RECEIVE_FAILED; nodes.clear(nodeId);
error = 1;
break;
} }
case GSN_NF_COMPLETEREP:{ case GSN_NF_COMPLETEREP:{
const NFCompleteRep * const rep = const NFCompleteRep * const rep =
CAST_CONSTPTR(NFCompleteRep, signal->getDataPtr()); CAST_CONSTPTR(NFCompleteRep, signal->getDataPtr());
if (rep->failedNodeId == nodeId) nodes.clear(rep->failedNodeId);
return SEND_OR_RECEIVE_FAILED;
break; break;
} }
case GSN_NODE_FAILREP:{ case GSN_NODE_FAILREP:{
const NodeFailRep * const rep = // ignore, NF_COMPLETEREP will arrive later
CAST_CONSTPTR(NodeFailRep, signal->getDataPtr());
if (NodeBitmask::get(rep->theNodes,nodeId))
return SEND_OR_RECEIVE_FAILED;
break; break;
} }
default: default:
report_unknown_signal(signal); report_unknown_signal(signal);
return SEND_OR_RECEIVE_FAILED; return SEND_OR_RECEIVE_FAILED;
} }
} }
#endif if (error)
return SEND_OR_RECEIVE_FAILED;
return 0; return 0;
} }
@ -1601,19 +1624,6 @@ MgmtSrvr::setNodeLogLevelImpl(int nodeId, const SetLogLevelOrd & ll)
return ss.sendSignal(nodeId, &ssig) == SEND_OK ? 0 : SEND_OR_RECEIVE_FAILED; return ss.sendSignal(nodeId, &ssig) == SEND_OK ? 0 : SEND_OR_RECEIVE_FAILED;
} }
int
MgmtSrvr::send(SignalSender &ss, SimpleSignal &ssig, Uint32 node, Uint32 node_type){
Uint32 max = (node == 0) ? MAX_NODES : node + 1;
for(; node < max; node++){
while(nodeTypes[node] != (int)node_type && node < max) node++;
if(nodeTypes[node] != (int)node_type)
break;
ss.sendSignal(node, &ssig);
}
return 0;
}
//**************************************************************************** //****************************************************************************
//**************************************************************************** //****************************************************************************

View file

@ -494,8 +494,6 @@ public:
private: private:
//************************************************************************** //**************************************************************************
int send(SignalSender &ss, SimpleSignal &ssig, Uint32 node, Uint32 node_type);
int sendStopMgmd(NodeId nodeId, int sendStopMgmd(NodeId nodeId,
bool abort, bool abort,
bool stop, bool stop,

View file

@ -840,9 +840,8 @@ MgmApiSession::setClusterLogLevel(Parser<MgmApiSession>::Context &,
m_mgmsrv.m_event_listner.unlock(); m_mgmsrv.m_event_listner.unlock();
{ {
LogLevel ll; LogLevel tmp;
ll.setLogLevel(category,level); m_mgmsrv.m_event_listner.update_max_log_level(tmp);
m_mgmsrv.m_event_listner.update_max_log_level(ll);
} }
m_output->println(reply); m_output->println(reply);
@ -1370,21 +1369,23 @@ Ndb_mgmd_event_service::log(int eventType, const Uint32* theData, NodeId nodeId)
void void
Ndb_mgmd_event_service::update_max_log_level(const LogLevel &log_level) Ndb_mgmd_event_service::update_max_log_level(const LogLevel &log_level)
{ {
LogLevel tmp= m_logLevel; LogLevel tmp = log_level;
tmp.set_max(log_level); m_clients.lock();
for(int i = m_clients.size() - 1; i >= 0; i--)
tmp.set_max(m_clients[i].m_logLevel);
m_clients.unlock();
update_log_level(tmp); update_log_level(tmp);
} }
void void
Ndb_mgmd_event_service::update_log_level(const LogLevel &tmp) Ndb_mgmd_event_service::update_log_level(const LogLevel &tmp)
{ {
if(!(tmp == m_logLevel)){ m_logLevel = tmp;
m_logLevel = tmp; EventSubscribeReq req;
EventSubscribeReq req; req = tmp;
req = tmp; // send update to all nodes
req.blockRef = 0; req.blockRef = 0;
m_mgmsrv->m_log_level_requests.push_back(req); m_mgmsrv->m_log_level_requests.push_back(req);
}
} }
void void

View file

@ -2267,7 +2267,7 @@ NdbDictionaryImpl::dropIndex(const char * indexName,
m_error.code = 4243; m_error.code = 4243;
return -1; return -1;
} }
int ret = dropIndex(*idx); //, tableName); int ret = dropIndex(*idx);
// If index stored in cache is incompatible with the one in the kernel // If index stored in cache is incompatible with the one in the kernel
// we must clear the cache and try again // we must clear the cache and try again
if (ret == INCOMPATIBLE_VERSION) { if (ret == INCOMPATIBLE_VERSION) {

View file

@ -395,7 +395,6 @@ public:
int createIndex(NdbIndexImpl &ix); int createIndex(NdbIndexImpl &ix);
int dropIndex(const char * indexName, int dropIndex(const char * indexName,
const char * tableName); const char * tableName);
// int dropIndex(NdbIndexImpl &, const char * tableName);
int dropIndex(NdbIndexImpl &); int dropIndex(NdbIndexImpl &);
NdbTableImpl * getIndexTable(NdbIndexImpl * index, NdbTableImpl * getIndexTable(NdbIndexImpl * index,
NdbTableImpl * table); NdbTableImpl * table);

View file

@ -160,7 +160,7 @@ NdbScanOperation::readTuples(NdbScanOperation::LockMode lm,
return -1; return -1;
} }
m_keyInfo = lockExcl ? 1 : 0; m_keyInfo = ((scan_flags & SF_KeyInfo) || lockExcl) ? 1 : 0;
bool rangeScan = false; bool rangeScan = false;
if (m_accessTable->m_indexType == NdbDictionary::Index::OrderedIndex) if (m_accessTable->m_indexType == NdbDictionary::Index::OrderedIndex)
@ -924,18 +924,28 @@ NdbScanOperation::takeOverScanOp(OperationType opType, NdbTransaction* pTrans)
if (newOp == NULL){ if (newOp == NULL){
return NULL; return NULL;
} }
if (!m_keyInfo)
{
// Cannot take over lock if no keyinfo was requested
setErrorCodeAbort(4604);
return NULL;
}
pTrans->theSimpleState = 0; pTrans->theSimpleState = 0;
const Uint32 len = (tRecAttr->attrSize() * tRecAttr->arraySize() + 3)/4-1; const Uint32 len = (tRecAttr->attrSize() * tRecAttr->arraySize() + 3)/4-1;
newOp->theTupKeyLen = len; newOp->theTupKeyLen = len;
newOp->theOperationType = opType; newOp->theOperationType = opType;
if (opType == DeleteRequest) { switch (opType) {
newOp->theStatus = GetValue; case (ReadRequest):
} else { newOp->theLockMode = theLockMode;
newOp->theStatus = SetValue; // Fall through
case (DeleteRequest):
newOp->theStatus = GetValue;
break;
default:
newOp->theStatus = SetValue;
} }
const Uint32 * src = (Uint32*)tRecAttr->aRef(); const Uint32 * src = (Uint32*)tRecAttr->aRef();
const Uint32 tScanInfo = src[len] & 0x3FFFF; const Uint32 tScanInfo = src[len] & 0x3FFFF;
const Uint32 tTakeOverFragment = src[len] >> 20; const Uint32 tTakeOverFragment = src[len] >> 20;

View file

@ -290,7 +290,7 @@ ErrorBundle ErrorCodes[] = {
{ 4601, AE, "Transaction is not started"}, { 4601, AE, "Transaction is not started"},
{ 4602, AE, "You must call getNdbOperation before executeScan" }, { 4602, AE, "You must call getNdbOperation before executeScan" },
{ 4603, AE, "There can only be ONE operation in a scan transaction" }, { 4603, AE, "There can only be ONE operation in a scan transaction" },
{ 4604, AE, "takeOverScanOp, opType must be UpdateRequest or DeleteRequest" }, { 4604, AE, "takeOverScanOp, to take over a scanned row one must explicitly request keyinfo in readTuples call" },
{ 4605, AE, "You may only call openScanRead or openScanExclusive once for each operation"}, { 4605, AE, "You may only call openScanRead or openScanExclusive once for each operation"},
{ 4607, AE, "There may only be one operation in a scan transaction"}, { 4607, AE, "There may only be one operation in a scan transaction"},
{ 4608, AE, "You can not takeOverScan unless you have used openScanExclusive"}, { 4608, AE, "You can not takeOverScan unless you have used openScanExclusive"},

View file

@ -37,7 +37,8 @@ class ha_myisammrg: public handler
{ {
return (HA_REC_NOT_IN_SEQ | HA_AUTO_PART_KEY | HA_READ_RND_SAME | return (HA_REC_NOT_IN_SEQ | HA_AUTO_PART_KEY | HA_READ_RND_SAME |
HA_NULL_IN_KEY | HA_CAN_INDEX_BLOBS | HA_FILE_BASED | HA_NULL_IN_KEY | HA_CAN_INDEX_BLOBS | HA_FILE_BASED |
HA_CAN_INSERT_DELAYED | HA_ANY_INDEX_MAY_BE_UNIQUE); HA_CAN_INSERT_DELAYED | HA_ANY_INDEX_MAY_BE_UNIQUE |
HA_CAN_BIT_FIELD);
} }
ulong index_flags(uint inx, uint part, bool all_parts) const ulong index_flags(uint inx, uint part, bool all_parts) const
{ {

View file

@ -70,7 +70,7 @@ handlerton ndbcluster_hton = {
NULL, /* create_cursor_read_view */ NULL, /* create_cursor_read_view */
NULL, /* set_cursor_read_view */ NULL, /* set_cursor_read_view */
NULL, /* close_cursor_read_view */ NULL, /* close_cursor_read_view */
HTON_NO_FLAGS HTON_CAN_RECREATE
}; };
#define NDB_AUTO_INCREMENT_RETRIES 10 #define NDB_AUTO_INCREMENT_RETRIES 10
@ -1174,12 +1174,23 @@ void ha_ndbcluster::release_metadata()
int ha_ndbcluster::get_ndb_lock_type(enum thr_lock_type type) int ha_ndbcluster::get_ndb_lock_type(enum thr_lock_type type)
{ {
DBUG_ENTER("ha_ndbcluster::get_ndb_lock_type");
if (type >= TL_WRITE_ALLOW_WRITE) if (type >= TL_WRITE_ALLOW_WRITE)
return NdbOperation::LM_Exclusive; {
else if (uses_blob_value(m_retrieve_all_fields)) DBUG_PRINT("info", ("Using exclusive lock"));
return NdbOperation::LM_Read; DBUG_RETURN(NdbOperation::LM_Exclusive);
}
else if (type == TL_READ_WITH_SHARED_LOCKS ||
uses_blob_value(m_retrieve_all_fields))
{
DBUG_PRINT("info", ("Using read lock"));
DBUG_RETURN(NdbOperation::LM_Read);
}
else else
return NdbOperation::LM_CommittedRead; {
DBUG_PRINT("info", ("Using committed read"));
DBUG_RETURN(NdbOperation::LM_CommittedRead);
}
} }
static const ulong index_type_flags[]= static const ulong index_type_flags[]=
@ -1679,7 +1690,30 @@ inline int ha_ndbcluster::fetch_next(NdbScanOperation* cursor)
int check; int check;
NdbTransaction *trans= m_active_trans; NdbTransaction *trans= m_active_trans;
bool contact_ndb= m_lock.type < TL_WRITE_ALLOW_WRITE; if (m_lock_tuple)
{
/*
Lock level m_lock.type either TL_WRITE_ALLOW_WRITE
(SELECT FOR UPDATE) or TL_READ_WITH_SHARED_LOCKS (SELECT
LOCK WITH SHARE MODE) and row was not explictly unlocked
with unlock_row() call
*/
NdbConnection *trans= m_active_trans;
NdbOperation *op;
// Lock row
DBUG_PRINT("info", ("Keeping lock on scanned row"));
if (!(op= m_active_cursor->lockCurrentTuple()))
{
m_lock_tuple= false;
ERR_RETURN(trans->getNdbError());
}
m_ops_pending++;
}
m_lock_tuple= false;
bool contact_ndb= m_lock.type < TL_WRITE_ALLOW_WRITE &&
m_lock.type != TL_READ_WITH_SHARED_LOCKS;
do { do {
DBUG_PRINT("info", ("Call nextResult, contact_ndb: %d", contact_ndb)); DBUG_PRINT("info", ("Call nextResult, contact_ndb: %d", contact_ndb));
/* /*
@ -1695,6 +1729,13 @@ inline int ha_ndbcluster::fetch_next(NdbScanOperation* cursor)
if ((check= cursor->nextResult(contact_ndb, m_force_send)) == 0) if ((check= cursor->nextResult(contact_ndb, m_force_send)) == 0)
{ {
/*
Explicitly lock tuple if "select for update" or
"select lock in share mode"
*/
m_lock_tuple= (m_lock.type == TL_WRITE_ALLOW_WRITE
||
m_lock.type == TL_READ_WITH_SHARED_LOCKS);
DBUG_RETURN(0); DBUG_RETURN(0);
} }
else if (check == 1 || check == 2) else if (check == 1 || check == 2)
@ -1983,10 +2024,11 @@ int ha_ndbcluster::ordered_index_scan(const key_range *start_key,
restart= FALSE; restart= FALSE;
NdbOperation::LockMode lm= NdbOperation::LockMode lm=
(NdbOperation::LockMode)get_ndb_lock_type(m_lock.type); (NdbOperation::LockMode)get_ndb_lock_type(m_lock.type);
bool need_pk = (lm == NdbOperation::LM_Read);
if (!(op= trans->getNdbIndexScanOperation((NDBINDEX *) if (!(op= trans->getNdbIndexScanOperation((NDBINDEX *)
m_index[active_index].index, m_index[active_index].index,
(const NDBTAB *) m_table)) || (const NDBTAB *) m_table)) ||
op->readTuples(lm, 0, parallelism, sorted, descending)) op->readTuples(lm, 0, parallelism, sorted, descending, false, need_pk))
ERR_RETURN(trans->getNdbError()); ERR_RETURN(trans->getNdbError());
m_active_cursor= op; m_active_cursor= op;
} else { } else {
@ -2036,8 +2078,11 @@ int ha_ndbcluster::full_table_scan(byte *buf)
NdbOperation::LockMode lm= NdbOperation::LockMode lm=
(NdbOperation::LockMode)get_ndb_lock_type(m_lock.type); (NdbOperation::LockMode)get_ndb_lock_type(m_lock.type);
bool need_pk = (lm == NdbOperation::LM_Read);
if (!(op=trans->getNdbScanOperation((const NDBTAB *) m_table)) || if (!(op=trans->getNdbScanOperation((const NDBTAB *) m_table)) ||
op->readTuples(lm, 0, parallelism)) op->readTuples(lm,
(need_pk)?NdbScanOperation::SF_KeyInfo:0,
parallelism))
ERR_RETURN(trans->getNdbError()); ERR_RETURN(trans->getNdbError());
m_active_cursor= op; m_active_cursor= op;
if (generate_scan_filter(m_cond_stack, op)) if (generate_scan_filter(m_cond_stack, op))
@ -2088,6 +2133,11 @@ int ha_ndbcluster::write_row(byte *record)
*/ */
if (!m_use_write && m_ignore_dup_key) if (!m_use_write && m_ignore_dup_key)
{ {
/*
compare if expression with that in start_bulk_insert()
start_bulk_insert will set parameters to ensure that each
write_row is committed individually
*/
int peek_res= peek_indexed_rows(record); int peek_res= peek_indexed_rows(record);
if (!peek_res) if (!peek_res)
@ -2327,6 +2377,7 @@ int ha_ndbcluster::update_row(const byte *old_data, byte *new_data)
DBUG_PRINT("info", ("Calling updateTuple on cursor")); DBUG_PRINT("info", ("Calling updateTuple on cursor"));
if (!(op= cursor->updateCurrentTuple())) if (!(op= cursor->updateCurrentTuple()))
ERR_RETURN(trans->getNdbError()); ERR_RETURN(trans->getNdbError());
m_lock_tuple= false;
m_ops_pending++; m_ops_pending++;
if (uses_blob_value(FALSE)) if (uses_blob_value(FALSE))
m_blobs_pending= TRUE; m_blobs_pending= TRUE;
@ -2406,6 +2457,7 @@ int ha_ndbcluster::delete_row(const byte *record)
DBUG_PRINT("info", ("Calling deleteTuple on cursor")); DBUG_PRINT("info", ("Calling deleteTuple on cursor"));
if (cursor->deleteCurrentTuple() != 0) if (cursor->deleteCurrentTuple() != 0)
ERR_RETURN(trans->getNdbError()); ERR_RETURN(trans->getNdbError());
m_lock_tuple= false;
m_ops_pending++; m_ops_pending++;
no_uncommitted_rows_update(-1); no_uncommitted_rows_update(-1);
@ -2529,9 +2581,9 @@ void ha_ndbcluster::unpack_record(byte* buf)
const NdbRecAttr* rec= m_value[hidden_no].rec; const NdbRecAttr* rec= m_value[hidden_no].rec;
DBUG_ASSERT(rec); DBUG_ASSERT(rec);
DBUG_PRINT("hidden", ("%d: %s \"%llu\"", hidden_no, DBUG_PRINT("hidden", ("%d: %s \"%llu\"", hidden_no,
hidden_col->getName(), rec->u_64_value())); hidden_col->getName(), rec->u_64_value()));
} }
//print_results(); print_results();
#endif #endif
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
@ -2605,6 +2657,12 @@ int ha_ndbcluster::index_init(uint index)
{ {
DBUG_ENTER("ha_ndbcluster::index_init"); DBUG_ENTER("ha_ndbcluster::index_init");
DBUG_PRINT("enter", ("index: %u", index)); DBUG_PRINT("enter", ("index: %u", index));
/*
Locks are are explicitly released in scan
unless m_lock.type == TL_READ_HIGH_PRIORITY
and no sub-sequent call to unlock_row()
*/
m_lock_tuple= false;
DBUG_RETURN(handler::index_init(index)); DBUG_RETURN(handler::index_init(index));
} }
@ -3217,6 +3275,19 @@ void ha_ndbcluster::start_bulk_insert(ha_rows rows)
DBUG_PRINT("enter", ("rows: %d", (int)rows)); DBUG_PRINT("enter", ("rows: %d", (int)rows));
m_rows_inserted= (ha_rows) 0; m_rows_inserted= (ha_rows) 0;
if (!m_use_write && m_ignore_dup_key)
{
/*
compare if expression with that in write_row
we have a situation where peek_indexed_rows() will be called
so we cannot batch
*/
DBUG_PRINT("info", ("Batching turned off as duplicate key is "
"ignored by using peek_row"));
m_rows_to_insert= 1;
m_bulk_insert_rows= 1;
DBUG_VOID_RETURN;
}
if (rows == (ha_rows) 0) if (rows == (ha_rows) 0)
{ {
/* We don't know how many will be inserted, guess */ /* We don't know how many will be inserted, guess */
@ -3613,6 +3684,22 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type)
DBUG_RETURN(error); DBUG_RETURN(error);
} }
/*
Unlock the last row read in an open scan.
Rows are unlocked by default in ndb, but
for SELECT FOR UPDATE and SELECT LOCK WIT SHARE MODE
locks are kept if unlock_row() is not called.
*/
void ha_ndbcluster::unlock_row()
{
DBUG_ENTER("unlock_row");
DBUG_PRINT("info", ("Unlocking row"));
m_lock_tuple= false;
DBUG_VOID_RETURN;
}
/* /*
Start a transaction for running a statement if one is not Start a transaction for running a statement if one is not
already running in a transaction. This will be the case in already running in a transaction. This will be the case in
@ -4085,6 +4172,12 @@ int ha_ndbcluster::create(const char *name,
set_dbname(name2); set_dbname(name2);
set_tabname(name2); set_tabname(name2);
if (current_thd->lex->sql_command == SQLCOM_TRUNCATE)
{
DBUG_PRINT("info", ("Dropping and re-creating table for TRUNCATE"));
if ((my_errno= delete_table(name)))
DBUG_RETURN(my_errno);
}
if (create_from_engine) if (create_from_engine)
{ {
/* /*
@ -4392,15 +4485,29 @@ int ha_ndbcluster::delete_table(const char *name)
int ha_ndbcluster::drop_table() int ha_ndbcluster::drop_table()
{ {
THD *thd= current_thd;
Ndb *ndb= get_ndb(); Ndb *ndb= get_ndb();
NdbDictionary::Dictionary *dict= ndb->getDictionary(); NdbDictionary::Dictionary *dict= ndb->getDictionary();
DBUG_ENTER("drop_table"); DBUG_ENTER("drop_table");
DBUG_PRINT("enter", ("Deleting %s", m_tabname)); DBUG_PRINT("enter", ("Deleting %s", m_tabname));
release_metadata(); release_metadata();
if (dict->dropTable(m_tabname)) while (dict->dropTable(m_tabname))
{
const NdbError err= dict->getNdbError();
switch (err.status)
{
case NdbError::TemporaryError:
if (!thd->killed)
continue; // retry indefinitly
break;
default:
break;
}
ERR_RETURN(dict->getNdbError()); ERR_RETURN(dict->getNdbError());
}
DBUG_RETURN(0); DBUG_RETURN(0);
} }
@ -4809,14 +4916,24 @@ int ndbcluster_drop_database(const char *path)
List_iterator_fast<char> it(drop_list); List_iterator_fast<char> it(drop_list);
while ((tabname=it++)) while ((tabname=it++))
{ {
if (dict->dropTable(tabname)) while (dict->dropTable(tabname))
{ {
const NdbError err= dict->getNdbError(); const NdbError err= dict->getNdbError();
if (err.code != 709) switch (err.status)
{
case NdbError::TemporaryError:
if (!thd->killed)
continue; // retry indefinitly
break;
default:
break;
}
if (err.code != 709) // 709: No such table existed
{ {
ERR_PRINT(err); ERR_PRINT(err);
ret= ndb_to_mysql_error(&err); ret= ndb_to_mysql_error(&err);
} }
break;
} }
} }
DBUG_RETURN(ret); DBUG_RETURN(ret);
@ -5891,6 +6008,7 @@ ha_ndbcluster::read_multi_range_first(KEY_MULTI_RANGE **found_range_p,
byte *end_of_buffer= (byte*)buffer->buffer_end; byte *end_of_buffer= (byte*)buffer->buffer_end;
NdbOperation::LockMode lm= NdbOperation::LockMode lm=
(NdbOperation::LockMode)get_ndb_lock_type(m_lock.type); (NdbOperation::LockMode)get_ndb_lock_type(m_lock.type);
bool need_pk = (lm == NdbOperation::LM_Read);
const NDBTAB *tab= (const NDBTAB *) m_table; const NDBTAB *tab= (const NDBTAB *) m_table;
const NDBINDEX *unique_idx= (NDBINDEX *) m_index[active_index].unique_index; const NDBINDEX *unique_idx= (NDBINDEX *) m_index[active_index].unique_index;
const NDBINDEX *idx= (NDBINDEX *) m_index[active_index].index; const NDBINDEX *idx= (NDBINDEX *) m_index[active_index].index;
@ -5957,7 +6075,8 @@ ha_ndbcluster::read_multi_range_first(KEY_MULTI_RANGE **found_range_p,
end_of_buffer -= reclength; end_of_buffer -= reclength;
} }
else if ((scanOp= m_active_trans->getNdbIndexScanOperation(idx, tab)) else if ((scanOp= m_active_trans->getNdbIndexScanOperation(idx, tab))
&&!scanOp->readTuples(lm, 0, parallelism, sorted, FALSE, TRUE) &&!scanOp->readTuples(lm, 0, parallelism, sorted,
FALSE, TRUE, need_pk)
&&!generate_scan_filter(m_cond_stack, scanOp) &&!generate_scan_filter(m_cond_stack, scanOp)
&&!define_read_attrs(end_of_buffer-reclength, scanOp)) &&!define_read_attrs(end_of_buffer-reclength, scanOp))
{ {

View file

@ -503,6 +503,7 @@ class ha_ndbcluster: public handler
int extra(enum ha_extra_function operation); int extra(enum ha_extra_function operation);
int extra_opt(enum ha_extra_function operation, ulong cache_size); int extra_opt(enum ha_extra_function operation, ulong cache_size);
int external_lock(THD *thd, int lock_type); int external_lock(THD *thd, int lock_type);
void unlock_row();
int start_stmt(THD *thd, thr_lock_type lock_type); int start_stmt(THD *thd, thr_lock_type lock_type);
const char * table_type() const; const char * table_type() const;
const char ** bas_ext() const; const char ** bas_ext() const;
@ -684,6 +685,7 @@ private:
char m_tabname[FN_HEADLEN]; char m_tabname[FN_HEADLEN];
ulong m_table_flags; ulong m_table_flags;
THR_LOCK_DATA m_lock; THR_LOCK_DATA m_lock;
bool m_lock_tuple;
NDB_SHARE *m_share; NDB_SHARE *m_share;
NDB_INDEX_DATA m_index[MAX_KEY]; NDB_INDEX_DATA m_index[MAX_KEY];
// NdbRecAttr has no reference to blob // NdbRecAttr has no reference to blob

View file

@ -132,7 +132,7 @@ bool Cached_item_decimal::cmp()
{ {
my_decimal tmp; my_decimal tmp;
my_decimal *ptmp= item->val_decimal(&tmp); my_decimal *ptmp= item->val_decimal(&tmp);
if (null_value != item->null_value || my_decimal_cmp(&value, ptmp) == 0) if (null_value != item->null_value || my_decimal_cmp(&value, ptmp))
{ {
null_value= item->null_value; null_value= item->null_value;
my_decimal2decimal(ptmp, &value); my_decimal2decimal(ptmp, &value);

View file

@ -1391,7 +1391,7 @@ void Item_func_curtime::fix_length_and_dec()
{ {
TIME ltime; TIME ltime;
decimals=0; decimals= DATETIME_DEC;
collation.set(&my_charset_bin); collation.set(&my_charset_bin);
store_now_in_TIME(&ltime); store_now_in_TIME(&ltime);
value= TIME_to_ulonglong_time(&ltime); value= TIME_to_ulonglong_time(&ltime);
@ -1438,7 +1438,7 @@ String *Item_func_now::val_str(String *str)
void Item_func_now::fix_length_and_dec() void Item_func_now::fix_length_and_dec()
{ {
decimals=0; decimals= DATETIME_DEC;
collation.set(&my_charset_bin); collation.set(&my_charset_bin);
store_now_in_TIME(&ltime); store_now_in_TIME(&ltime);
@ -1785,7 +1785,7 @@ void Item_func_from_unixtime::fix_length_and_dec()
{ {
thd= current_thd; thd= current_thd;
collation.set(&my_charset_bin); collation.set(&my_charset_bin);
decimals=0; decimals= DATETIME_DEC;
max_length=MAX_DATETIME_WIDTH*MY_CHARSET_BIN_MB_MAXLEN; max_length=MAX_DATETIME_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
maybe_null= 1; maybe_null= 1;
thd->time_zone_used= 1; thd->time_zone_used= 1;

View file

@ -614,6 +614,7 @@ public:
{ {
collation.set(&my_charset_bin); collation.set(&my_charset_bin);
maybe_null=1; maybe_null=1;
decimals= DATETIME_DEC;
max_length=MAX_TIME_WIDTH*MY_CHARSET_BIN_MB_MAXLEN; max_length=MAX_TIME_WIDTH*MY_CHARSET_BIN_MB_MAXLEN;
} }
enum_field_types field_type() const { return MYSQL_TYPE_TIME; } enum_field_types field_type() const { return MYSQL_TYPE_TIME; }

View file

@ -424,16 +424,27 @@ bool mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info,
my_error(ER_DB_CREATE_EXISTS, MYF(0), db); my_error(ER_DB_CREATE_EXISTS, MYF(0), db);
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
VOID(pthread_mutex_lock(&LOCK_mysql_create_db));
/* do not create database if another thread is holding read lock */ /*
Do not create database if another thread is holding read lock.
Wait for global read lock before acquiring LOCK_mysql_create_db.
After wait_if_global_read_lock() we have protection against another
global read lock. If we would acquire LOCK_mysql_create_db first,
another thread could step in and get the global read lock before we
reach wait_if_global_read_lock(). If this thread tries the same as we
(admin a db), it would then go and wait on LOCK_mysql_create_db...
Furthermore wait_if_global_read_lock() checks if the current thread
has the global read lock and refuses the operation with
ER_CANT_UPDATE_WITH_READLOCK if applicable.
*/
if (wait_if_global_read_lock(thd, 0, 1)) if (wait_if_global_read_lock(thd, 0, 1))
{ {
error= -1; error= -1;
goto exit2; goto exit2;
} }
VOID(pthread_mutex_lock(&LOCK_mysql_create_db));
/* Check directory */ /* Check directory */
strxmov(path, mysql_data_home, "/", db, NullS); strxmov(path, mysql_data_home, "/", db, NullS);
path_len= unpack_dirname(path,path); // Convert if not unix path_len= unpack_dirname(path,path); // Convert if not unix
@ -537,9 +548,9 @@ bool mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info,
} }
exit: exit:
VOID(pthread_mutex_unlock(&LOCK_mysql_create_db));
start_waiting_global_read_lock(thd); start_waiting_global_read_lock(thd);
exit2: exit2:
VOID(pthread_mutex_unlock(&LOCK_mysql_create_db));
DBUG_RETURN(error); DBUG_RETURN(error);
} }
@ -553,12 +564,23 @@ bool mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info)
int error= 0; int error= 0;
DBUG_ENTER("mysql_alter_db"); DBUG_ENTER("mysql_alter_db");
VOID(pthread_mutex_lock(&LOCK_mysql_create_db)); /*
Do not alter database if another thread is holding read lock.
/* do not alter database if another thread is holding read lock */ Wait for global read lock before acquiring LOCK_mysql_create_db.
After wait_if_global_read_lock() we have protection against another
global read lock. If we would acquire LOCK_mysql_create_db first,
another thread could step in and get the global read lock before we
reach wait_if_global_read_lock(). If this thread tries the same as we
(admin a db), it would then go and wait on LOCK_mysql_create_db...
Furthermore wait_if_global_read_lock() checks if the current thread
has the global read lock and refuses the operation with
ER_CANT_UPDATE_WITH_READLOCK if applicable.
*/
if ((error=wait_if_global_read_lock(thd,0,1))) if ((error=wait_if_global_read_lock(thd,0,1)))
goto exit2; goto exit2;
VOID(pthread_mutex_lock(&LOCK_mysql_create_db));
/* Check directory */ /* Check directory */
strxmov(path, mysql_data_home, "/", db, "/", MY_DB_OPT_FILE, NullS); strxmov(path, mysql_data_home, "/", db, "/", MY_DB_OPT_FILE, NullS);
fn_format(path, path, "", "", MYF(MY_UNPACK_FILENAME)); fn_format(path, path, "", "", MYF(MY_UNPACK_FILENAME));
@ -596,9 +618,9 @@ bool mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info)
send_ok(thd, result); send_ok(thd, result);
exit: exit:
VOID(pthread_mutex_unlock(&LOCK_mysql_create_db));
start_waiting_global_read_lock(thd); start_waiting_global_read_lock(thd);
exit2: exit2:
VOID(pthread_mutex_unlock(&LOCK_mysql_create_db));
DBUG_RETURN(error); DBUG_RETURN(error);
} }
@ -630,15 +652,26 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
TABLE_LIST* dropped_tables= 0; TABLE_LIST* dropped_tables= 0;
DBUG_ENTER("mysql_rm_db"); DBUG_ENTER("mysql_rm_db");
VOID(pthread_mutex_lock(&LOCK_mysql_create_db)); /*
Do not drop database if another thread is holding read lock.
/* do not drop database if another thread is holding read lock */ Wait for global read lock before acquiring LOCK_mysql_create_db.
After wait_if_global_read_lock() we have protection against another
global read lock. If we would acquire LOCK_mysql_create_db first,
another thread could step in and get the global read lock before we
reach wait_if_global_read_lock(). If this thread tries the same as we
(admin a db), it would then go and wait on LOCK_mysql_create_db...
Furthermore wait_if_global_read_lock() checks if the current thread
has the global read lock and refuses the operation with
ER_CANT_UPDATE_WITH_READLOCK if applicable.
*/
if (wait_if_global_read_lock(thd, 0, 1)) if (wait_if_global_read_lock(thd, 0, 1))
{ {
error= -1; error= -1;
goto exit2; goto exit2;
} }
VOID(pthread_mutex_lock(&LOCK_mysql_create_db));
(void) sprintf(path,"%s/%s",mysql_data_home,db); (void) sprintf(path,"%s/%s",mysql_data_home,db);
length= unpack_dirname(path,path); // Convert if not unix length= unpack_dirname(path,path); // Convert if not unix
strmov(path+length, MY_DB_OPT_FILE); // Append db option file name strmov(path+length, MY_DB_OPT_FILE); // Append db option file name
@ -747,7 +780,6 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
exit: exit:
(void)sp_drop_db_routines(thd, db); /* QQ Ignore errors for now */ (void)sp_drop_db_routines(thd, db); /* QQ Ignore errors for now */
start_waiting_global_read_lock(thd);
/* /*
If this database was the client's selected database, we silently change the If this database was the client's selected database, we silently change the
client's selected database to nothing (to have an empty SELECT DATABASE() client's selected database to nothing (to have an empty SELECT DATABASE()
@ -776,9 +808,9 @@ exit:
thd->db= 0; thd->db= 0;
thd->db_length= 0; thd->db_length= 0;
} }
exit2:
VOID(pthread_mutex_unlock(&LOCK_mysql_create_db)); VOID(pthread_mutex_unlock(&LOCK_mysql_create_db));
start_waiting_global_read_lock(thd);
exit2:
DBUG_RETURN(error); DBUG_RETURN(error);
} }

View file

@ -304,18 +304,7 @@ static char *get_text(LEX *lex)
found_escape=1; found_escape=1;
if (lex->ptr == lex->end_of_query) if (lex->ptr == lex->end_of_query)
return 0; return 0;
#ifdef USE_MB yySkip();
int l;
if (use_mb(cs) &&
(l = my_ismbchar(cs,
(const char *)lex->ptr,
(const char *)lex->end_of_query))) {
lex->ptr += l;
continue;
}
else
#endif
yySkip();
} }
else if (c == sep) else if (c == sep)
{ {
@ -344,9 +333,6 @@ static char *get_text(LEX *lex)
{ {
uchar *to; uchar *to;
/* Re-use found_escape for tracking state of escapes */
found_escape= 0;
for (to=start ; str != end ; str++) for (to=start ; str != end ; str++)
{ {
#ifdef USE_MB #ifdef USE_MB
@ -360,8 +346,7 @@ static char *get_text(LEX *lex)
continue; continue;
} }
#endif #endif
if (!found_escape && if (!(lex->thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES) &&
!(lex->thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES) &&
*str == '\\' && str+1 != end) *str == '\\' && str+1 != end)
{ {
switch(*++str) { switch(*++str) {
@ -388,20 +373,14 @@ static char *get_text(LEX *lex)
*to++= '\\'; // remember prefix for wildcard *to++= '\\'; // remember prefix for wildcard
/* Fall through */ /* Fall through */
default: default:
found_escape= 1; *to++= *str;
str--;
break; break;
} }
} }
else if (!found_escape && *str == sep) else if (*str == sep)
{ *to++= *str++; // Two ' or "
found_escape= 1;
}
else else
{
*to++ = *str; *to++ = *str;
found_escape= 0;
}
} }
*to=0; *to=0;
lex->yytoklen=(uint) (to-start); lex->yytoklen=(uint) (to-start);

View file

@ -5004,7 +5004,14 @@ bool check_one_table_access(THD *thd, ulong privilege, TABLE_LIST *all_tables)
if (all_tables->security_ctx) if (all_tables->security_ctx)
thd->security_ctx= all_tables->security_ctx; thd->security_ctx= all_tables->security_ctx;
if (check_access(thd, privilege, all_tables->db, const char *db_name;
if ((all_tables->view || all_tables->field_translation) &&
!all_tables->schema_table)
db_name= all_tables->view_db.str;
else
db_name= all_tables->db;
if (check_access(thd, privilege, db_name,
&all_tables->grant.privilege, 0, 0, &all_tables->grant.privilege, 0, 0,
test(all_tables->schema_table))) test(all_tables->schema_table)))
goto deny; goto deny;

View file

@ -17,6 +17,7 @@
### BEGIN INIT INFO ### BEGIN INIT INFO
# Provides: mysql # Provides: mysql
# Required-Start: $local_fs $network $remote_fs # Required-Start: $local_fs $network $remote_fs
# Should-Start: ypbind nscd ldap ntpd xntpd
# Required-Stop: $local_fs $network $remote_fs # Required-Stop: $local_fs $network $remote_fs
# Default-Start: 2 3 4 5 # Default-Start: 2 3 4 5
# Default-Stop: 0 1 6 # Default-Stop: 0 1 6

View file

@ -12794,25 +12794,26 @@ from t2);");
static void test_bug8378() static void test_bug8378()
{ {
#if defined(HAVE_CHARSET_gbk) && !defined(EMBEDDED_LIBRARY) #if defined(HAVE_CHARSET_gbk) && !defined(EMBEDDED_LIBRARY)
MYSQL *lmysql; MYSQL *old_mysql=mysql;
char out[9]; /* strlen(TEST_BUG8378)*2+1 */ char out[9]; /* strlen(TEST_BUG8378)*2+1 */
int len; char buf[256];
int len, rc;
myheader("test_bug8378"); myheader("test_bug8378");
if (!opt_silent) if (!opt_silent)
fprintf(stdout, "\n Establishing a test connection ..."); fprintf(stdout, "\n Establishing a test connection ...");
if (!(lmysql= mysql_init(NULL))) if (!(mysql= mysql_init(NULL)))
{ {
myerror("mysql_init() failed"); myerror("mysql_init() failed");
exit(1); exit(1);
} }
if (mysql_options(lmysql, MYSQL_SET_CHARSET_NAME, "gbk")) if (mysql_options(mysql, MYSQL_SET_CHARSET_NAME, "gbk"))
{ {
myerror("mysql_options() failed"); myerror("mysql_options() failed");
exit(1); exit(1);
} }
if (!(mysql_real_connect(lmysql, opt_host, opt_user, if (!(mysql_real_connect(mysql, opt_host, opt_user,
opt_password, current_db, opt_port, opt_password, current_db, opt_port,
opt_unix_socket, 0))) opt_unix_socket, 0)))
{ {
@ -12822,12 +12823,18 @@ static void test_bug8378()
if (!opt_silent) if (!opt_silent)
fprintf(stdout, " OK"); fprintf(stdout, " OK");
len= mysql_real_escape_string(lmysql, out, TEST_BUG8378_IN, 4); len= mysql_real_escape_string(mysql, out, TEST_BUG8378_IN, 4);
/* No escaping should have actually happened. */ /* No escaping should have actually happened. */
DIE_UNLESS(memcmp(out, TEST_BUG8378_OUT, len) == 0); DIE_UNLESS(memcmp(out, TEST_BUG8378_OUT, len) == 0);
mysql_close(lmysql); sprintf(buf, "SELECT '%s'", out);
rc=mysql_real_query(mysql, buf, strlen(buf));
myquery(rc);
mysql_close(mysql);
mysql=old_mysql;
#endif #endif
} }