mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
Fixed bug in multi-table-delete code
client/mysqltest.c: Added --big-test argument libmysqld/lib_sql.cc: Reset error messages before new query. libmysqld/lib_vio.c: Fixed reading of results. mysql-test/mysql-test-run.sh: Added option --big mysql-test/r/multi_update.result: More multi-delete tests mysql-test/t/bdb-crash.test: Added missing test if BDB is supported mysql-test/t/multi_update.test: More multi-delete tests
This commit is contained in:
@ -43,7 +43,7 @@
|
|||||||
|
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
|
|
||||||
#define MTEST_VERSION "1.9"
|
#define MTEST_VERSION "1.10"
|
||||||
|
|
||||||
#include <global.h>
|
#include <global.h>
|
||||||
#include <my_sys.h>
|
#include <my_sys.h>
|
||||||
@ -84,7 +84,7 @@
|
|||||||
static int record = 0, verbose = 0, silent = 0, opt_sleep=0;
|
static int record = 0, verbose = 0, silent = 0, opt_sleep=0;
|
||||||
static char *db = 0, *pass=0;
|
static char *db = 0, *pass=0;
|
||||||
const char* user = 0, *host = 0, *unix_sock = 0;
|
const char* user = 0, *host = 0, *unix_sock = 0;
|
||||||
static int port = 0;
|
static int port = 0, opt_big_test=0;
|
||||||
static uint start_lineno, *lineno;
|
static uint start_lineno, *lineno;
|
||||||
|
|
||||||
static char **default_argv;
|
static char **default_argv;
|
||||||
@ -1410,6 +1410,7 @@ struct option long_options[] =
|
|||||||
{
|
{
|
||||||
{"debug", optional_argument, 0, '#'},
|
{"debug", optional_argument, 0, '#'},
|
||||||
{"database", required_argument, 0, 'D'},
|
{"database", required_argument, 0, 'D'},
|
||||||
|
{"big-test", no_argument, 0, 'B'},
|
||||||
{"help", no_argument, 0, '?'},
|
{"help", no_argument, 0, '?'},
|
||||||
{"host", required_argument, 0, 'h'},
|
{"host", required_argument, 0, 'h'},
|
||||||
{"password", optional_argument, 0, 'p'},
|
{"password", optional_argument, 0, 'p'},
|
||||||
@ -1453,6 +1454,7 @@ void usage()
|
|||||||
-u, --user=... User for login.\n\
|
-u, --user=... User for login.\n\
|
||||||
-p[password], --password[=...]\n\
|
-p[password], --password[=...]\n\
|
||||||
Password to use when connecting to server.\n\
|
Password to use when connecting to server.\n\
|
||||||
|
-B, --big-test Define BIG_TEST to 1\n\
|
||||||
-D, --database=... Database to use.\n\
|
-D, --database=... Database to use.\n\
|
||||||
-P, --port=... Port number to use for connection.\n\
|
-P, --port=... Port number to use for connection.\n\
|
||||||
-S, --socket=... Socket file to use for connection.\n\
|
-S, --socket=... Socket file to use for connection.\n\
|
||||||
@ -1475,7 +1477,7 @@ int parse_args(int argc, char **argv)
|
|||||||
load_defaults("my",load_default_groups,&argc,&argv);
|
load_defaults("my",load_default_groups,&argc,&argv);
|
||||||
default_argv= argv;
|
default_argv= argv;
|
||||||
|
|
||||||
while((c = getopt_long(argc, argv, "h:p::u:P:D:S:R:x:t:T:#:?rvVq",
|
while((c = getopt_long(argc, argv, "h:p::u:BP:D:S:R:x:t:T:#:?rvVq",
|
||||||
long_options, &option_index)) != EOF)
|
long_options, &option_index)) != EOF)
|
||||||
{
|
{
|
||||||
switch(c) {
|
switch(c) {
|
||||||
@ -1508,6 +1510,9 @@ int parse_args(int argc, char **argv)
|
|||||||
else
|
else
|
||||||
tty_password=1;
|
tty_password=1;
|
||||||
break;
|
break;
|
||||||
|
case 'B':
|
||||||
|
opt_big_test=1;
|
||||||
|
break;
|
||||||
case 'P':
|
case 'P':
|
||||||
port = atoi(optarg);
|
port = atoi(optarg);
|
||||||
break;
|
break;
|
||||||
@ -1814,6 +1819,7 @@ static void var_from_env(const char* name, const char* def_val)
|
|||||||
hash_insert(&var_hash, (byte*)v);
|
hash_insert(&var_hash, (byte*)v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void init_var_hash()
|
static void init_var_hash()
|
||||||
{
|
{
|
||||||
if (hash_init(&var_hash, 1024, 0, 0, get_var_key, var_free, MYF(0)))
|
if (hash_init(&var_hash, 1024, 0, 0, get_var_key, var_free, MYF(0)))
|
||||||
@ -1821,6 +1827,7 @@ static void init_var_hash()
|
|||||||
var_from_env("MASTER_MYPORT", "9306");
|
var_from_env("MASTER_MYPORT", "9306");
|
||||||
var_from_env("SLAVE_MYPORT", "9307");
|
var_from_env("SLAVE_MYPORT", "9307");
|
||||||
var_from_env("MYSQL_TEST_DIR", "/tmp");
|
var_from_env("MYSQL_TEST_DIR", "/tmp");
|
||||||
|
var_from_env("BIG_TEST", opt_big_test ? "1" : "0");
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
|
@ -74,6 +74,9 @@ bool lib_dispatch_command(enum enum_server_command command, NET *net,
|
|||||||
{
|
{
|
||||||
THD *thd=(THD *) net->vio->dest_thd;
|
THD *thd=(THD *) net->vio->dest_thd;
|
||||||
thd->store_globals(); // Fix if more than one connect
|
thd->store_globals(); // Fix if more than one connect
|
||||||
|
thd->net.last_error[0]=0; // Clear error message
|
||||||
|
thd->net.last_errno=0;
|
||||||
|
|
||||||
net_new_transaction(&thd->net);
|
net_new_transaction(&thd->net);
|
||||||
return dispatch_command(command, thd, (char *) arg, length + 1);
|
return dispatch_command(command, thd, (char *) arg, length + 1);
|
||||||
}
|
}
|
||||||
@ -83,17 +86,17 @@ bool lib_dispatch_command(enum enum_server_command command, NET *net,
|
|||||||
void
|
void
|
||||||
lib_connection_phase(NET * net, int phase)
|
lib_connection_phase(NET * net, int phase)
|
||||||
{
|
{
|
||||||
THD * thd;
|
THD * thd;
|
||||||
thd = (THD *)(net->vio->dest_thd);
|
thd = (THD *)(net->vio->dest_thd);
|
||||||
if (thd)
|
if (thd)
|
||||||
{
|
{
|
||||||
switch (phase)
|
switch (phase)
|
||||||
{
|
{
|
||||||
case 2:
|
case 2:
|
||||||
check_connections2(thd);
|
check_connections2(thd);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void start_embedded_conn1(NET * net)
|
void start_embedded_conn1(NET * net)
|
||||||
|
@ -139,6 +139,8 @@ int vio_read(Vio * vio, gptr buf, int size)
|
|||||||
uint4korr(vio->packets + sizeof(char *));
|
uint4korr(vio->packets + sizeof(char *));
|
||||||
vio->packets = *(char **)vio->packets;
|
vio->packets = *(char **)vio->packets;
|
||||||
}
|
}
|
||||||
|
if (vio->where_in_packet + size > vio->end_of_packet)
|
||||||
|
size = vio->end_of_packet - vio->where_in_packet;
|
||||||
memcpy(buf, vio->where_in_packet, size);
|
memcpy(buf, vio->where_in_packet, size);
|
||||||
vio->where_in_packet += size;
|
vio->where_in_packet += size;
|
||||||
return (size);
|
return (size);
|
||||||
|
@ -151,6 +151,8 @@ while test $# -gt 0; do
|
|||||||
DO_BENCH=1
|
DO_BENCH=1
|
||||||
NO_SLAVE=1
|
NO_SLAVE=1
|
||||||
;;
|
;;
|
||||||
|
--big*) # Actually --big-test
|
||||||
|
EXTRA_MYSQL_TEST_OPT="$EXTRA_MYSQL_TEST_OPT $1" ;;
|
||||||
--sleep=*)
|
--sleep=*)
|
||||||
EXTRA_MYSQL_TEST_OPT="$EXTRA_MYSQL_TEST_OPT $1"
|
EXTRA_MYSQL_TEST_OPT="$EXTRA_MYSQL_TEST_OPT $1"
|
||||||
SLEEP_TIME=`$ECHO "$1" | $SED -e "s;--sleep=;;"`
|
SLEEP_TIME=`$ECHO "$1" | $SED -e "s;--sleep=;;"`
|
||||||
|
@ -1,14 +1,22 @@
|
|||||||
id1 t
|
Table Op Msg_type Msg_text
|
||||||
1 3
|
test.t1 check status OK
|
||||||
2 2
|
test.t2 check status OK
|
||||||
id2 t
|
test.t3 check status OK
|
||||||
1 3
|
count(*)
|
||||||
1 2
|
0
|
||||||
1 1
|
count(*)
|
||||||
id3 t
|
0
|
||||||
2 3
|
count(*)
|
||||||
2 2
|
0
|
||||||
2 1
|
count(*)
|
||||||
1 3
|
0
|
||||||
1 2
|
count(*)
|
||||||
1 1
|
0
|
||||||
|
count(*)
|
||||||
|
0
|
||||||
|
count(*)
|
||||||
|
0
|
||||||
|
count(*)
|
||||||
|
0
|
||||||
|
count(*)
|
||||||
|
0
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
-- source include/have_bdb.inc
|
||||||
# test for bug reported by Mark Steele
|
# test for bug reported by Mark Steele
|
||||||
|
|
||||||
drop table if exists tblChange;
|
drop table if exists tblChange;
|
||||||
|
@ -1,3 +1,10 @@
|
|||||||
|
#
|
||||||
|
# Only run the test if we are using --big-test, because this test takes a
|
||||||
|
# long time
|
||||||
|
#
|
||||||
|
-- require r/big_test.require
|
||||||
|
eval select $BIG_TEST as using_big_test;
|
||||||
|
|
||||||
drop table if exists t1,t2,t3;
|
drop table if exists t1,t2,t3;
|
||||||
create table t1(id1 int not null auto_increment primary key, t char(12));
|
create table t1(id1 int not null auto_increment primary key, t char(12));
|
||||||
create table t2(id2 int not null, t char(12), index(id2));
|
create table t2(id2 int not null, t char(12), index(id2));
|
||||||
@ -25,11 +32,20 @@ delete t1.*, t2.*, t3.* from t1,t2,t3 where t1.id1 = t2.id2 and t2.id2 = t3.id3
|
|||||||
|
|
||||||
check table t1, t2, t3;
|
check table t1, t2, t3;
|
||||||
|
|
||||||
select * from t1 where id1 > 9500;
|
select count(*) from t1 where id1 > 9500;
|
||||||
select * from t2 where id2 > 9500;
|
select count(*) from t2 where id2 > 9500;
|
||||||
select * from t3 where id3 > 9500;
|
select count(*) from t3 where id3 > 9500;
|
||||||
|
|
||||||
delete t1, t2, t3 from t1,t2,t3 where t1.id1 = t2.id2 and t2.id2 = t3.id3 and t1.id1 > 500;
|
delete t1, t2, t3 from t1,t2,t3 where t1.id1 = t2.id2 and t2.id2 = t3.id3 and t1.id1 > 500;
|
||||||
select * from t1 where id1 > 500;
|
select count(*) from t1 where id1 > 500;
|
||||||
select * from t2 where id2 > 500;
|
select count(*) from t2 where id2 > 500;
|
||||||
select * from t3 where id3 > 500;
|
select count(*) from t3 where id3 > 500;
|
||||||
|
|
||||||
|
delete t1, t2, t3 from t1,t2,t3 where t1.id1 = t2.id2 and t2.id2 = t3.id3 and t1.id1 > 0;
|
||||||
|
|
||||||
|
# These queries will force a scan of the table
|
||||||
|
select count(*) from t1 where id1;
|
||||||
|
select count(*) from t2 where id2;
|
||||||
|
select count(*) from t3 where id3;
|
||||||
|
|
||||||
|
drop table t1,t2,t3;
|
||||||
|
@ -674,7 +674,7 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
|
|||||||
int error;
|
int error;
|
||||||
uint sort_length,offset;
|
uint sort_length,offset;
|
||||||
ulong maxcount;
|
ulong maxcount;
|
||||||
ha_rows count,max_rows;
|
ha_rows max_rows,org_max_rows;
|
||||||
my_off_t to_start_filepos;
|
my_off_t to_start_filepos;
|
||||||
uchar *strpos;
|
uchar *strpos;
|
||||||
BUFFPEK *buffpek,**refpek;
|
BUFFPEK *buffpek,**refpek;
|
||||||
@ -685,12 +685,12 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
|
|||||||
|
|
||||||
statistic_increment(filesort_merge_passes, &LOCK_status);
|
statistic_increment(filesort_merge_passes, &LOCK_status);
|
||||||
|
|
||||||
count=error=0;
|
error=0;
|
||||||
offset=(sort_length=param->sort_length)-param->ref_length;
|
offset=(sort_length=param->sort_length)-param->ref_length;
|
||||||
maxcount=(ulong) (param->keys/((uint) (Tb-Fb) +1));
|
maxcount=(ulong) (param->keys/((uint) (Tb-Fb) +1));
|
||||||
to_start_filepos=my_b_tell(to_file);
|
to_start_filepos=my_b_tell(to_file);
|
||||||
strpos=(uchar*) sort_buffer;
|
strpos=(uchar*) sort_buffer;
|
||||||
max_rows=param->max_rows;
|
org_max_rows=max_rows=param->max_rows;
|
||||||
|
|
||||||
if (init_queue(&queue,(uint) (Tb-Fb)+1,offsetof(BUFFPEK,key),0,
|
if (init_queue(&queue,(uint) (Tb-Fb)+1,offsetof(BUFFPEK,key),0,
|
||||||
(int (*) (void *, byte *,byte*))
|
(int (*) (void *, byte *,byte*))
|
||||||
@ -698,7 +698,6 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
|
|||||||
DBUG_RETURN(1); /* purecov: inspected */
|
DBUG_RETURN(1); /* purecov: inspected */
|
||||||
for (buffpek= Fb ; buffpek <= Tb ; buffpek++)
|
for (buffpek= Fb ; buffpek <= Tb ; buffpek++)
|
||||||
{
|
{
|
||||||
count+= buffpek->count;
|
|
||||||
buffpek->base= strpos;
|
buffpek->base= strpos;
|
||||||
buffpek->max_keys=maxcount;
|
buffpek->max_keys=maxcount;
|
||||||
strpos+= (uint) (error=(int) read_to_buffer(from_file,buffpek,
|
strpos+= (uint) (error=(int) read_to_buffer(from_file,buffpek,
|
||||||
@ -725,6 +724,8 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
|
|||||||
error=1; goto err; /* purecov: inspected */
|
error=1; goto err; /* purecov: inspected */
|
||||||
}
|
}
|
||||||
buffpek->key+=sort_length;
|
buffpek->key+=sort_length;
|
||||||
|
buffpek->mem_count--;
|
||||||
|
max_rows--;
|
||||||
queue_replaced(&queue); // Top element has been used
|
queue_replaced(&queue); // Top element has been used
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -741,7 +742,8 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
|
|||||||
buffpek=(BUFFPEK*) queue_top(&queue);
|
buffpek=(BUFFPEK*) queue_top(&queue);
|
||||||
if (cmp) // Remove duplicates
|
if (cmp) // Remove duplicates
|
||||||
{
|
{
|
||||||
if (!cmp(&sort_length, &(param->unique_buff), (uchar**) &buffpek->key))
|
if (!(*cmp)(&sort_length, &(param->unique_buff),
|
||||||
|
(uchar**) &buffpek->key))
|
||||||
goto skip_duplicate;
|
goto skip_duplicate;
|
||||||
memcpy(param->unique_buff, (uchar*) buffpek->key,sort_length);
|
memcpy(param->unique_buff, (uchar*) buffpek->key,sort_length);
|
||||||
}
|
}
|
||||||
@ -795,7 +797,7 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
|
|||||||
break; /* One buffer have been removed */
|
break; /* One buffer have been removed */
|
||||||
}
|
}
|
||||||
else if (error == -1)
|
else if (error == -1)
|
||||||
goto err; /* purecov: inspected */
|
goto err; /* purecov: inspected */
|
||||||
}
|
}
|
||||||
queue_replaced(&queue); /* Top element has been replaced */
|
queue_replaced(&queue); /* Top element has been replaced */
|
||||||
}
|
}
|
||||||
@ -803,6 +805,20 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
|
|||||||
buffpek=(BUFFPEK*) queue_top(&queue);
|
buffpek=(BUFFPEK*) queue_top(&queue);
|
||||||
buffpek->base= sort_buffer;
|
buffpek->base= sort_buffer;
|
||||||
buffpek->max_keys=param->keys;
|
buffpek->max_keys=param->keys;
|
||||||
|
|
||||||
|
/*
|
||||||
|
As we know all entries in the buffer are unique, we only have to
|
||||||
|
check if the first one is the same as the last one we wrote
|
||||||
|
*/
|
||||||
|
if (cmp)
|
||||||
|
{
|
||||||
|
if (!(*cmp)(&sort_length, &(param->unique_buff), (uchar**) &buffpek->key))
|
||||||
|
{
|
||||||
|
buffpek->key+=sort_length; // Remove duplicate
|
||||||
|
--buffpek->mem_count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
if ((ha_rows) buffpek->mem_count > max_rows)
|
if ((ha_rows) buffpek->mem_count > max_rows)
|
||||||
@ -810,6 +826,7 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
|
|||||||
buffpek->mem_count=(uint) max_rows;
|
buffpek->mem_count=(uint) max_rows;
|
||||||
buffpek->count=0; /* Don't read more */
|
buffpek->count=0; /* Don't read more */
|
||||||
}
|
}
|
||||||
|
max_rows-=buffpek->mem_count;
|
||||||
if (flag == 0)
|
if (flag == 0)
|
||||||
{
|
{
|
||||||
if (my_b_write(to_file,(byte*) buffpek->key,
|
if (my_b_write(to_file,(byte*) buffpek->key,
|
||||||
@ -834,7 +851,7 @@ int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
|
|||||||
!= -1 && error != 0);
|
!= -1 && error != 0);
|
||||||
|
|
||||||
end:
|
end:
|
||||||
lastbuff->count=min(count,param->max_rows);
|
lastbuff->count=min(org_max_rows-max_rows,param->max_rows);
|
||||||
lastbuff->file_pos=to_start_filepos;
|
lastbuff->file_pos=to_start_filepos;
|
||||||
err:
|
err:
|
||||||
delete_queue(&queue);
|
delete_queue(&queue);
|
||||||
|
Reference in New Issue
Block a user