mirror of
https://github.com/MariaDB/server.git
synced 2025-01-17 20:42:30 +01:00
Merge bk-internal.mysql.com:/home/bk/mysql-5.0
into serg.mylan:/usr/home/serg/Abk/mysql-5.0-merged
This commit is contained in:
commit
306aa15391
24 changed files with 587 additions and 46 deletions
|
@ -369,6 +369,10 @@ SOURCE=.\my_compress.c
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\my_conio.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\my_copy.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
|
|
@ -362,6 +362,10 @@ SOURCE=.\my_compress.c
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\my_conio.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\my_copy.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
|
|
@ -959,10 +959,15 @@ static int get_options(int argc, char **argv)
|
|||
|
||||
static int read_and_execute(bool interactive)
|
||||
{
|
||||
#if defined( __WIN__) || defined(OS2) || defined(__NETWARE__)
|
||||
#if defined(OS2) || defined(__NETWARE__)
|
||||
char linebuffer[254];
|
||||
String buffer;
|
||||
#endif
|
||||
#if defined(__WIN__)
|
||||
String tmpbuf;
|
||||
String buffer;
|
||||
#endif
|
||||
|
||||
char *line;
|
||||
char in_string=0;
|
||||
ulong line_number=0;
|
||||
|
@ -993,7 +998,7 @@ static int read_and_execute(bool interactive)
|
|||
|
||||
#if defined( __WIN__) || defined(OS2) || defined(__NETWARE__)
|
||||
tee_fputs(prompt, stdout);
|
||||
#ifdef __NETWARE__
|
||||
#if defined(__NETWARE__)
|
||||
line=fgets(linebuffer, sizeof(linebuffer)-1, stdin);
|
||||
/* Remove the '\n' */
|
||||
if (line)
|
||||
|
@ -1002,7 +1007,22 @@ static int read_and_execute(bool interactive)
|
|||
if (p != NULL)
|
||||
*p = '\0';
|
||||
}
|
||||
#else
|
||||
#elif defined(__WIN__)
|
||||
if (!tmpbuf.is_alloced())
|
||||
tmpbuf.alloc(65535);
|
||||
buffer.length(0);
|
||||
unsigned long clen;
|
||||
do
|
||||
{
|
||||
line= my_cgets(tmpbuf.c_ptr(), tmpbuf.alloced_length(), &clen);
|
||||
buffer.append(line, clen);
|
||||
/*
|
||||
if we got buffer fully filled than there is a chance that
|
||||
something else is still in console input buffer
|
||||
*/
|
||||
} while (tmpbuf.alloced_length() <= clen + 1);
|
||||
line= buffer.c_ptr();
|
||||
#else /* OS2 */
|
||||
buffer.length(0);
|
||||
/* _cgets() expects the buffer size - 3 as the first byte */
|
||||
linebuffer[0]= (char) sizeof(linebuffer) - 3;
|
||||
|
@ -1078,9 +1098,14 @@ static int read_and_execute(bool interactive)
|
|||
status.exit_status=0;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined( __WIN__) || defined(OS2) || defined(__NETWARE__)
|
||||
buffer.free();
|
||||
#endif
|
||||
#if defined( __WIN__)
|
||||
tmpbuf.free();
|
||||
#endif
|
||||
|
||||
return status.exit_status;
|
||||
}
|
||||
|
||||
|
|
|
@ -887,6 +887,9 @@ int my_security_attr_create(SECURITY_ATTRIBUTES **psa, const char **perror,
|
|||
|
||||
void my_security_attr_free(SECURITY_ATTRIBUTES *sa);
|
||||
|
||||
/* implemented in my_conio.c */
|
||||
char* my_cgets(char *string, unsigned long clen, unsigned long* plen);
|
||||
|
||||
#endif
|
||||
#ifdef __NETWARE__
|
||||
void netware_reg_user(const char *ip, const char *user,
|
||||
|
|
|
@ -381,6 +381,20 @@ typedef struct st_sort_key_blocks /* Used when sorting */
|
|||
} SORT_KEY_BLOCKS;
|
||||
|
||||
|
||||
/*
|
||||
MyISAM supports several statistics collection methods. Currently statistics
|
||||
collection method is not stored in MyISAM file and has to be specified for
|
||||
each table analyze/repair operation in MI_CHECK::stats_method.
|
||||
*/
|
||||
|
||||
typedef enum
|
||||
{
|
||||
/* Treat NULLs as inequal when collecting statistics (default for 4.1/5.0) */
|
||||
MI_STATS_METHOD_NULLS_NOT_EQUAL,
|
||||
/* Treat NULLs as equal when collecting statistics (like 4.0 did) */
|
||||
MI_STATS_METHOD_NULLS_EQUAL
|
||||
} enum_mi_stats_method;
|
||||
|
||||
typedef struct st_mi_check_param
|
||||
{
|
||||
ulonglong auto_increment_value;
|
||||
|
@ -411,6 +425,7 @@ typedef struct st_mi_check_param
|
|||
void *thd;
|
||||
const char *db_name, *table_name;
|
||||
const char *op_name;
|
||||
enum_mi_stats_method stats_method;
|
||||
} MI_CHECK;
|
||||
|
||||
typedef struct st_sort_ft_buf
|
||||
|
|
|
@ -80,6 +80,7 @@ void myisamchk_init(MI_CHECK *param)
|
|||
param->start_check_pos=0;
|
||||
param->max_record_length= LONGLONG_MAX;
|
||||
param->key_cache_block_size= KEY_CACHE_BLOCK_SIZE;
|
||||
param->stats_method= MI_STATS_METHOD_NULLS_NOT_EQUAL;
|
||||
}
|
||||
|
||||
/* Check the status flags for the table */
|
||||
|
@ -559,10 +560,11 @@ static int chk_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo,
|
|||
ha_checksum *key_checksum, uint level)
|
||||
{
|
||||
int flag;
|
||||
uint used_length,comp_flag,nod_flag,key_length=0,not_used;
|
||||
uint used_length,comp_flag,nod_flag,key_length=0;
|
||||
uchar key[MI_MAX_POSSIBLE_KEY_BUFF],*temp_buff,*keypos,*old_keypos,*endpos;
|
||||
my_off_t next_page,record;
|
||||
char llbuff[22];
|
||||
uint diff_pos;
|
||||
DBUG_ENTER("chk_index");
|
||||
DBUG_DUMP("buff",(byte*) buff,mi_getint(buff));
|
||||
|
||||
|
@ -620,7 +622,7 @@ static int chk_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo,
|
|||
}
|
||||
if ((*keys)++ &&
|
||||
(flag=ha_key_cmp(keyinfo->seg,info->lastkey,key,key_length,
|
||||
comp_flag, ¬_used)) >=0)
|
||||
comp_flag, &diff_pos)) >=0)
|
||||
{
|
||||
DBUG_DUMP("old",(byte*) info->lastkey, info->lastkey_length);
|
||||
DBUG_DUMP("new",(byte*) key, key_length);
|
||||
|
@ -636,11 +638,11 @@ static int chk_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo,
|
|||
{
|
||||
if (*keys != 1L) /* not first_key */
|
||||
{
|
||||
uint diff;
|
||||
ha_key_cmp(keyinfo->seg,info->lastkey,key,USE_WHOLE_KEY,
|
||||
SEARCH_FIND | SEARCH_NULL_ARE_NOT_EQUAL,
|
||||
&diff);
|
||||
param->unique_count[diff-1]++;
|
||||
if (param->stats_method == MI_STATS_METHOD_NULLS_NOT_EQUAL)
|
||||
ha_key_cmp(keyinfo->seg,info->lastkey,key,USE_WHOLE_KEY,
|
||||
SEARCH_FIND | SEARCH_NULL_ARE_NOT_EQUAL,
|
||||
&diff_pos);
|
||||
param->unique_count[diff_pos-1]++;
|
||||
}
|
||||
}
|
||||
(*key_checksum)+= mi_byte_checksum((byte*) key,
|
||||
|
@ -2014,7 +2016,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
|
|||
sort_param.sort_info=&sort_info;
|
||||
sort_param.fix_datafile= (my_bool) (! rep_quick);
|
||||
sort_param.master =1;
|
||||
|
||||
|
||||
del=info->state->del;
|
||||
param->glob_crc=0;
|
||||
if (param->testflag & T_CALC_CHECKSUM)
|
||||
|
@ -3250,9 +3252,10 @@ static int sort_key_write(MI_SORT_PARAM *sort_param, const void *a)
|
|||
cmp=ha_key_cmp(sort_param->seg,sort_info->key_block->lastkey,
|
||||
(uchar*) a, USE_WHOLE_KEY,SEARCH_FIND | SEARCH_UPDATE,
|
||||
&diff_pos);
|
||||
ha_key_cmp(sort_param->seg,sort_info->key_block->lastkey,
|
||||
(uchar*) a, USE_WHOLE_KEY,SEARCH_FIND | SEARCH_NULL_ARE_NOT_EQUAL,
|
||||
&diff_pos);
|
||||
if (param->stats_method == MI_STATS_METHOD_NULLS_NOT_EQUAL)
|
||||
ha_key_cmp(sort_param->seg,sort_info->key_block->lastkey,
|
||||
(uchar*) a, USE_WHOLE_KEY,
|
||||
SEARCH_FIND | SEARCH_NULL_ARE_NOT_EQUAL, &diff_pos);
|
||||
sort_param->unique[diff_pos-1]++;
|
||||
}
|
||||
else
|
||||
|
@ -3989,9 +3992,10 @@ void update_auto_increment_key(MI_CHECK *param, MI_INFO *info,
|
|||
unique[0]= (#different values of {keypart1}) - 1
|
||||
unique[1]= (#different values of {keypart2,keypart1} tuple) - unique[0] - 1
|
||||
...
|
||||
Here we assume that NULL != NULL (see SEARCH_NULL_ARE_NOT_EQUAL). The
|
||||
'unique' array is collected in one sequential scan through the entire
|
||||
The 'unique' array is collected in one sequential scan through the entire
|
||||
index. This is done in two places: in chk_index() and in sort_key_write().
|
||||
Statistics collection may consider NULLs as either equal or inequal (see
|
||||
SEARCH_NULL_ARE_NOT_EQUAL, MI_STATS_METHOD_*).
|
||||
|
||||
Output is an array:
|
||||
rec_per_key_part[k] =
|
||||
|
|
|
@ -67,6 +67,7 @@ static const char *field_pack[]=
|
|||
"no zeros", "blob", "constant", "table-lockup",
|
||||
"always zero","varchar","unique-hash","?","?"};
|
||||
|
||||
static const char *myisam_stats_method_str="nulls_inequal";
|
||||
|
||||
static void get_options(int *argc,char * * *argv);
|
||||
static void print_version(void);
|
||||
|
@ -155,7 +156,7 @@ enum options_mc {
|
|||
OPT_READ_BUFFER_SIZE, OPT_WRITE_BUFFER_SIZE, OPT_SORT_BUFFER_SIZE,
|
||||
OPT_SORT_KEY_BLOCKS, OPT_DECODE_BITS, OPT_FT_MIN_WORD_LEN,
|
||||
OPT_FT_MAX_WORD_LEN, OPT_FT_STOPWORD_FILE,
|
||||
OPT_MAX_RECORD_LENGTH, OPT_AUTO_CLOSE
|
||||
OPT_MAX_RECORD_LENGTH, OPT_AUTO_CLOSE, OPT_STATS_METHOD
|
||||
};
|
||||
|
||||
static struct my_option my_long_options[] =
|
||||
|
@ -336,6 +337,11 @@ static struct my_option my_long_options[] =
|
|||
"Use stopwords from this file instead of built-in list.",
|
||||
(gptr*) &ft_stopword_file, (gptr*) &ft_stopword_file, 0, GET_STR,
|
||||
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||
{"stats_method", OPT_STATS_METHOD,
|
||||
"Specifies how index statistics collection code should threat NULLs. "
|
||||
"Possible values of name are \"nulls_inequal\" (default behavior for 4.1/5.0), and \"nulls_equal\" (emulate 4.0 behavior).",
|
||||
(gptr*) &myisam_stats_method_str, (gptr*) &myisam_stats_method_str, 0,
|
||||
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||
{ 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
|
@ -465,6 +471,12 @@ static void usage(void)
|
|||
|
||||
#include <help_end.h>
|
||||
|
||||
const char *myisam_stats_method_names[] = {"nulls_inequal", "nulls_equal",
|
||||
NullS};
|
||||
TYPELIB myisam_stats_method_typelib= {
|
||||
array_elements(myisam_stats_method_names) - 1, "",
|
||||
myisam_stats_method_names, NULL};
|
||||
|
||||
/* Read options */
|
||||
|
||||
static my_bool
|
||||
|
@ -684,6 +696,18 @@ get_one_option(int optid,
|
|||
else
|
||||
check_param.testflag|= T_CALC_CHECKSUM;
|
||||
break;
|
||||
case OPT_STATS_METHOD:
|
||||
{
|
||||
int method;
|
||||
myisam_stats_method_str= argument;
|
||||
if ((method=find_type(argument, &myisam_stats_method_typelib, 2)) <= 0)
|
||||
{
|
||||
fprintf(stderr, "Invalid value of stats_method: %s.\n", argument);
|
||||
exit(1);
|
||||
}
|
||||
check_param.stats_method= method-1;
|
||||
break;
|
||||
}
|
||||
#ifdef DEBUG /* Only useful if debugging */
|
||||
case OPT_START_CHECK_POS:
|
||||
check_param.start_check_pos= strtoull(argument, NULL, 0);
|
||||
|
|
|
@ -2450,11 +2450,6 @@ sub run_mysqltest ($) {
|
|||
mtr_add_arg($args, "--big-test");
|
||||
}
|
||||
|
||||
if ( $opt_record )
|
||||
{
|
||||
mtr_add_arg($args, "--record");
|
||||
}
|
||||
|
||||
if ( $opt_compress )
|
||||
{
|
||||
mtr_add_arg($args, "--compress");
|
||||
|
@ -2480,9 +2475,6 @@ sub run_mysqltest ($) {
|
|||
$glob_mysql_test_dir);
|
||||
}
|
||||
|
||||
mtr_add_arg($args, "-R");
|
||||
mtr_add_arg($args, $tinfo->{'result_file'});
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# If embedded server, we create server args to give mysqltest to pass on
|
||||
# ----------------------------------------------------------------------
|
||||
|
@ -2497,6 +2489,18 @@ sub run_mysqltest ($) {
|
|||
# ----------------------------------------------------------------------
|
||||
$ENV{'MYSQL_TEST'}= "$exe_mysqltest " . join(" ", @$args);
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# Add args that should not go into the MYSQL_TEST environment var
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
mtr_add_arg($args, "-R");
|
||||
mtr_add_arg($args, $tinfo->{'result_file'});
|
||||
|
||||
if ( $opt_record )
|
||||
{
|
||||
mtr_add_arg($args, "--record");
|
||||
}
|
||||
|
||||
return mtr_run_test($exe,$args,$tinfo->{'path'},"",$path_timefile,"");
|
||||
}
|
||||
|
||||
|
|
|
@ -1730,6 +1730,15 @@ explain select * from t1 order by a,b,c,d;
|
|||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 Using filesort
|
||||
drop table t1;
|
||||
create table t1 (a char(1), b char(1), key(a, b)) engine=innodb;
|
||||
insert into t1 values ('8', '6'), ('4', '7');
|
||||
select min(a) from t1;
|
||||
min(a)
|
||||
4
|
||||
select min(b) from t1 where a='8';
|
||||
min(b)
|
||||
6
|
||||
drop table t1;
|
||||
create table t1 (x bigint unsigned not null primary key) engine=innodb;
|
||||
insert into t1(x) values (0xfffffffffffffff0),(0xfffffffffffffff1);
|
||||
select * from t1;
|
||||
|
@ -1776,7 +1785,7 @@ Variable_name Value
|
|||
Innodb_rows_deleted 2070
|
||||
show status like "Innodb_rows_inserted";
|
||||
Variable_name Value
|
||||
Innodb_rows_inserted 31725
|
||||
Innodb_rows_inserted 31727
|
||||
show status like "Innodb_rows_updated";
|
||||
Variable_name Value
|
||||
Innodb_rows_updated 29530
|
||||
|
|
|
@ -608,6 +608,67 @@ checksum table t2;
|
|||
Table Checksum
|
||||
test.t2 984116287
|
||||
drop table t1, t2;
|
||||
show variables like 'myisam_stats_method';
|
||||
Variable_name Value
|
||||
myisam_stats_method nulls_inequal
|
||||
create table t1 (a int, key(a));
|
||||
insert into t1 values (0),(1),(2),(3),(4);
|
||||
insert into t1 select NULL from t1;
|
||||
analyze table t1;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 analyze status OK
|
||||
show index from t1;
|
||||
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
|
||||
t1 1 a 1 a A 10 NULL NULL YES BTREE
|
||||
insert into t1 values (11);
|
||||
delete from t1 where a=11;
|
||||
check table t1;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 check status OK
|
||||
show index from t1;
|
||||
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
|
||||
t1 1 a 1 a A 10 NULL NULL YES BTREE
|
||||
set myisam_stats_method=nulls_equal;
|
||||
show variables like 'myisam_stats_method';
|
||||
Variable_name Value
|
||||
myisam_stats_method nulls_equal
|
||||
insert into t1 values (11);
|
||||
delete from t1 where a=11;
|
||||
analyze table t1;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 analyze status OK
|
||||
show index from t1;
|
||||
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
|
||||
t1 1 a 1 a A 5 NULL NULL YES BTREE
|
||||
insert into t1 values (11);
|
||||
delete from t1 where a=11;
|
||||
check table t1;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 check status OK
|
||||
show index from t1;
|
||||
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
|
||||
t1 1 a 1 a A 5 NULL NULL YES BTREE
|
||||
set myisam_stats_method=DEFAULT;
|
||||
show variables like 'myisam_stats_method';
|
||||
Variable_name Value
|
||||
myisam_stats_method nulls_inequal
|
||||
insert into t1 values (11);
|
||||
delete from t1 where a=11;
|
||||
analyze table t1;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 analyze status OK
|
||||
show index from t1;
|
||||
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
|
||||
t1 1 a 1 a A 10 NULL NULL YES BTREE
|
||||
insert into t1 values (11);
|
||||
delete from t1 where a=11;
|
||||
check table t1;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 check status OK
|
||||
show index from t1;
|
||||
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
|
||||
t1 1 a 1 a A 10 NULL NULL YES BTREE
|
||||
drop table t1;
|
||||
set storage_engine=MyISAM;
|
||||
drop table if exists t1,t2,t3;
|
||||
--- Testing varchar ---
|
||||
|
|
|
@ -4,6 +4,26 @@ reset master;
|
|||
reset slave;
|
||||
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
|
||||
start slave;
|
||||
set sql_log_bin=0;
|
||||
create database mysqltest_from;
|
||||
set sql_log_bin=1;
|
||||
create database mysqltest_to;
|
||||
use mysqltest_from;
|
||||
drop table if exists a;
|
||||
CREATE TABLE a (i INT);
|
||||
INSERT INTO a VALUES(1);
|
||||
DELETE alias FROM a alias WHERE alias.i=1;
|
||||
SELECT * FROM a;
|
||||
i
|
||||
insert into a values(2),(3);
|
||||
delete a alias FROM a alias where alias.i=2;
|
||||
select * from a;
|
||||
i
|
||||
3
|
||||
use mysqltest_to;
|
||||
select * from a;
|
||||
i
|
||||
3
|
||||
create table t1 (a int);
|
||||
create table t2 (a int);
|
||||
insert into t1 values (1);
|
||||
|
@ -15,7 +35,10 @@ select * from t2;
|
|||
a
|
||||
1
|
||||
select * from t1;
|
||||
ERROR 42S02: Table 'test.t1' doesn't exist
|
||||
ERROR 42S02: Table 'mysqltest_to.t1' doesn't exist
|
||||
select * from t2;
|
||||
ERROR 42S02: Table 'test.t2' doesn't exist
|
||||
drop table t1,t2;
|
||||
ERROR 42S02: Table 'mysqltest_to.t2' doesn't exist
|
||||
set sql_log_bin=0;
|
||||
drop database mysqltest_from;
|
||||
set sql_log_bin=1;
|
||||
drop database mysqltest_to;
|
||||
|
|
|
@ -1259,6 +1259,15 @@ select * from t1 order by a,b,c,d;
|
|||
explain select * from t1 order by a,b,c,d;
|
||||
drop table t1;
|
||||
|
||||
#
|
||||
# BUG#11039,#13218 Wrong key length in min()
|
||||
#
|
||||
|
||||
create table t1 (a char(1), b char(1), key(a, b)) engine=innodb;
|
||||
insert into t1 values ('8', '6'), ('4', '7');
|
||||
select min(a) from t1;
|
||||
select min(b) from t1 where a='8';
|
||||
drop table t1;
|
||||
# End of 4.1 tests
|
||||
|
||||
#
|
||||
|
|
|
@ -578,6 +578,59 @@ checksum table t1;
|
|||
# The above should give the same number as the following.
|
||||
checksum table t2;
|
||||
drop table t1, t2;
|
||||
|
||||
#
|
||||
# BUG#12232: New myisam_stats_method variable.
|
||||
#
|
||||
|
||||
show variables like 'myisam_stats_method';
|
||||
|
||||
create table t1 (a int, key(a));
|
||||
insert into t1 values (0),(1),(2),(3),(4);
|
||||
insert into t1 select NULL from t1;
|
||||
|
||||
# default: NULLs considered inequal
|
||||
analyze table t1;
|
||||
show index from t1;
|
||||
insert into t1 values (11);
|
||||
delete from t1 where a=11;
|
||||
check table t1;
|
||||
show index from t1;
|
||||
|
||||
# Set nulls to be equal:
|
||||
set myisam_stats_method=nulls_equal;
|
||||
show variables like 'myisam_stats_method';
|
||||
insert into t1 values (11);
|
||||
delete from t1 where a=11;
|
||||
|
||||
analyze table t1;
|
||||
show index from t1;
|
||||
|
||||
insert into t1 values (11);
|
||||
delete from t1 where a=11;
|
||||
|
||||
check table t1;
|
||||
show index from t1;
|
||||
|
||||
# Set nulls back to be equal
|
||||
set myisam_stats_method=DEFAULT;
|
||||
show variables like 'myisam_stats_method';
|
||||
insert into t1 values (11);
|
||||
delete from t1 where a=11;
|
||||
|
||||
analyze table t1;
|
||||
show index from t1;
|
||||
|
||||
insert into t1 values (11);
|
||||
delete from t1 where a=11;
|
||||
|
||||
check table t1;
|
||||
show index from t1;
|
||||
|
||||
drop table t1;
|
||||
|
||||
# End of 4.1 tests
|
||||
|
||||
#
|
||||
# Test varchar
|
||||
#
|
||||
|
@ -700,4 +753,3 @@ create table t3 (c1 int) engine=myisam pack_keys=default;
|
|||
create table t4 (c1 int) engine=myisam pack_keys=2;
|
||||
drop table t1, t2, t3;
|
||||
|
||||
# End of 4.1 tests
|
||||
|
|
|
@ -1 +1 @@
|
|||
--replicate-wild-ignore-table=test.%
|
||||
"--replicate-rewrite-db=mysqltest_from->mysqltest_to" --replicate-do-table=mysqltest_to.a
|
||||
|
|
|
@ -1,4 +1,41 @@
|
|||
#multi delete replication bugs
|
||||
|
||||
|
||||
source include/master-slave.inc;
|
||||
|
||||
#BUG#11139 - improper wild-table and table rules
|
||||
#checking for multi deletes with an alias
|
||||
|
||||
connection master;
|
||||
set sql_log_bin=0;
|
||||
create database mysqltest_from;
|
||||
set sql_log_bin=1;
|
||||
|
||||
connection slave;
|
||||
create database mysqltest_to;
|
||||
|
||||
|
||||
connection master;
|
||||
use mysqltest_from;
|
||||
--disable_warnings
|
||||
drop table if exists a;
|
||||
--enable_warnings
|
||||
CREATE TABLE a (i INT);
|
||||
INSERT INTO a VALUES(1);
|
||||
DELETE alias FROM a alias WHERE alias.i=1;
|
||||
SELECT * FROM a;
|
||||
insert into a values(2),(3);
|
||||
delete a alias FROM a alias where alias.i=2;
|
||||
select * from a;
|
||||
save_master_pos;
|
||||
connection slave;
|
||||
|
||||
use mysqltest_to;
|
||||
sync_with_master;
|
||||
select * from a;
|
||||
|
||||
# BUG#3461
|
||||
connection master;
|
||||
create table t1 (a int);
|
||||
create table t2 (a int);
|
||||
|
||||
|
@ -19,7 +56,13 @@ select * from t1;
|
|||
error 1146;
|
||||
select * from t2;
|
||||
|
||||
# cleanup
|
||||
connection master;
|
||||
drop table t1,t2;
|
||||
set sql_log_bin=0;
|
||||
drop database mysqltest_from;
|
||||
set sql_log_bin=1;
|
||||
connection slave;
|
||||
drop database mysqltest_to;
|
||||
|
||||
# End of 4.1 tests
|
||||
|
||||
|
|
217
mysys/my_conio.c
Normal file
217
mysys/my_conio.c
Normal file
|
@ -0,0 +1,217 @@
|
|||
/* Copyright (C) 2000 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
|
||||
#include "mysys_priv.h"
|
||||
|
||||
#ifdef __WIN__
|
||||
|
||||
static HANDLE my_coninpfh= 0; /* console input */
|
||||
|
||||
/*
|
||||
functions my_pthread_auto_mutex_lock & my_pthread_auto_mutex_free
|
||||
are experimental at this moment, they are intended to bring
|
||||
ability of protecting code sections without necessity to explicitly
|
||||
initialize synchronization object in one of threads
|
||||
|
||||
if found useful they are to be exported in mysys
|
||||
*/
|
||||
|
||||
/*
|
||||
int my_pthread_auto_mutex_lock(HANDLE* ph, const char* name,
|
||||
int id, int time)
|
||||
|
||||
NOTES
|
||||
creates a mutex with given name and tries to lock it time msec.
|
||||
mutex name is appended with id to allow system wide or process wide
|
||||
locks. Handle to created mutex returned in ph argument.
|
||||
|
||||
RETURN
|
||||
0 thread owns mutex
|
||||
<>0 error
|
||||
|
||||
*/
|
||||
static
|
||||
int my_pthread_auto_mutex_lock(HANDLE* ph, const char* name, int id, int time)
|
||||
{
|
||||
int res;
|
||||
char tname[FN_REFLEN];
|
||||
|
||||
sprintf(tname, "%s-%08X", name, id);
|
||||
|
||||
*ph= CreateMutex(NULL, FALSE, tname);
|
||||
if (*ph == NULL)
|
||||
return GetLastError();
|
||||
|
||||
res= WaitForSingleObject(*ph, time);
|
||||
|
||||
if (res == WAIT_TIMEOUT)
|
||||
return ERROR_SEM_TIMEOUT;
|
||||
|
||||
if (res == WAIT_FAILED)
|
||||
return GetLastError();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
int my_pthread_auto_mutex_free(HANDLE* ph)
|
||||
|
||||
|
||||
NOTES
|
||||
releases a mutex.
|
||||
|
||||
RETURN
|
||||
0 thread released mutex
|
||||
<>0 error
|
||||
|
||||
*/
|
||||
static
|
||||
int my_pthread_auto_mutex_free(HANDLE* ph)
|
||||
{
|
||||
if (*ph)
|
||||
{
|
||||
ReleaseMutex(*ph);
|
||||
CloseHandle(*ph);
|
||||
*ph= NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#define pthread_auto_mutex_decl(name) \
|
||||
HANDLE __h##name= NULL;
|
||||
|
||||
#define pthread_auto_mutex_lock(name, proc, time) \
|
||||
my_pthread_auto_mutex_lock(&__h##name, #name, (proc), (time))
|
||||
|
||||
#define pthread_auto_mutex_free(name) \
|
||||
my_pthread_auto_mutex_free(&__h##name)
|
||||
|
||||
|
||||
/*
|
||||
char* my_cgets(char *string, unsigned long clen, unsigned long* plen)
|
||||
|
||||
NOTES
|
||||
Replaces _cgets from libc to support input of more than 255 chars.
|
||||
Reads from the console via ReadConsole into buffer which
|
||||
should be at least clen characters.
|
||||
Actual length of string returned in plen.
|
||||
|
||||
WARNING
|
||||
my_cgets() does NOT check the pushback character buffer (i.e., _chbuf).
|
||||
Thus, my_cgets() will not return any character that is pushed back by
|
||||
the _ungetch() call.
|
||||
|
||||
RETURN
|
||||
string pointer ok
|
||||
NULL Error
|
||||
|
||||
*/
|
||||
char* my_cgets(char *buffer, unsigned long clen, unsigned long* plen)
|
||||
{
|
||||
ULONG state;
|
||||
char *result;
|
||||
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
||||
|
||||
pthread_auto_mutex_decl(my_conio_cs);
|
||||
|
||||
/* lock the console for the current process*/
|
||||
if (pthread_auto_mutex_lock(my_conio_cs, GetCurrentProcessId(), INFINITE))
|
||||
{
|
||||
/* can not lock console */
|
||||
pthread_auto_mutex_free(my_conio_cs);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* init console input */
|
||||
if (my_coninpfh == 0)
|
||||
{
|
||||
/* same handle will be used until process termination */
|
||||
my_coninpfh= CreateFile("CONIN$", GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
NULL, OPEN_EXISTING, 0, NULL);
|
||||
}
|
||||
|
||||
if (my_coninpfh == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
/* unlock the console */
|
||||
pthread_auto_mutex_free(my_conio_cs);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
GetConsoleMode((HANDLE)my_coninpfh, &state);
|
||||
SetConsoleMode((HANDLE)my_coninpfh, ENABLE_LINE_INPUT |
|
||||
ENABLE_PROCESSED_INPUT | ENABLE_ECHO_INPUT);
|
||||
|
||||
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
|
||||
|
||||
/*
|
||||
there is no known way to determine allowed buffer size for input
|
||||
though it is known it should not be more than 64K
|
||||
so we cut 64K and try first size of screen buffer
|
||||
if it is still to large we cut half of it and try again
|
||||
later we may want to cycle from min(clen, 65535) to allowed size
|
||||
with small decrement to determine exact allowed buffer
|
||||
*/
|
||||
clen= min(clen, 65535);
|
||||
do
|
||||
{
|
||||
clen= min(clen, (unsigned long)csbi.dwSize.X*csbi.dwSize.Y);
|
||||
if (!ReadConsole((HANDLE)my_coninpfh, (LPVOID)buffer, clen - 1, plen, NULL))
|
||||
{
|
||||
result= NULL;
|
||||
clen>>= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
result= buffer;
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (GetLastError() == ERROR_NOT_ENOUGH_MEMORY);
|
||||
|
||||
|
||||
if (result != NULL)
|
||||
{
|
||||
if (buffer[*plen - 2] == '\r')
|
||||
{
|
||||
*plen= *plen - 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (buffer[*plen - 1] == '\r')
|
||||
{
|
||||
char tmp[3];
|
||||
int tmplen= sizeof(tmp);
|
||||
|
||||
*plen= *plen - 1;
|
||||
/* read /n left in the buffer */
|
||||
ReadConsole((HANDLE)my_coninpfh, (LPVOID)tmp, tmplen, &tmplen, NULL);
|
||||
}
|
||||
}
|
||||
buffer[*plen]= '\0';
|
||||
}
|
||||
|
||||
SetConsoleMode((HANDLE)my_coninpfh, state);
|
||||
/* unlock the console */
|
||||
pthread_auto_mutex_free(my_conio_cs);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif /* __WIN__ */
|
|
@ -39,6 +39,12 @@ const char *myisam_recover_names[] =
|
|||
TYPELIB myisam_recover_typelib= {array_elements(myisam_recover_names)-1,"",
|
||||
myisam_recover_names, NULL};
|
||||
|
||||
const char *myisam_stats_method_names[] = {"nulls_inequal", "nulls_equal",
|
||||
NullS};
|
||||
TYPELIB myisam_stats_method_typelib= {
|
||||
array_elements(myisam_stats_method_names) - 1, "",
|
||||
myisam_stats_method_names, NULL};
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
** MyISAM tables
|
||||
|
@ -324,6 +330,7 @@ int ha_myisam::check(THD* thd, HA_CHECK_OPT* check_opt)
|
|||
param.db_name= table->s->db;
|
||||
param.table_name= table->alias;
|
||||
param.testflag = check_opt->flags | T_CHECK | T_SILENT;
|
||||
param.stats_method= (enum_mi_stats_method)thd->variables.myisam_stats_method;
|
||||
|
||||
if (!(table->db_stat & HA_READ_ONLY))
|
||||
param.testflag|= T_STATISTICS;
|
||||
|
@ -413,6 +420,7 @@ int ha_myisam::analyze(THD *thd, HA_CHECK_OPT* check_opt)
|
|||
param.testflag= (T_FAST | T_CHECK | T_SILENT | T_STATISTICS |
|
||||
T_DONT_CHECK_CHECKSUM);
|
||||
param.using_global_keycache = 1;
|
||||
param.stats_method= (enum_mi_stats_method)thd->variables.myisam_stats_method;
|
||||
|
||||
if (!(share->state.changed & STATE_NOT_ANALYZED))
|
||||
return HA_ADMIN_ALREADY_DONE;
|
||||
|
@ -967,6 +975,7 @@ int ha_myisam::enable_indexes(uint mode)
|
|||
T_CREATE_MISSING_KEYS);
|
||||
param.myf_rw&= ~MY_WAIT_IF_FULL;
|
||||
param.sort_buffer_length= thd->variables.myisam_sort_buff_size;
|
||||
param.stats_method= (enum_mi_stats_method)thd->variables.myisam_stats_method;
|
||||
param.tmpdir=&mysql_tmpdir_list;
|
||||
if ((error= (repair(thd,param,0) != HA_ADMIN_OK)) && param.retry_repair)
|
||||
{
|
||||
|
|
|
@ -832,6 +832,7 @@ public:
|
|||
extern struct show_table_type_st sys_table_types[];
|
||||
extern const char *ha_row_type[];
|
||||
extern TYPELIB tx_isolation_typelib;
|
||||
extern TYPELIB myisam_stats_method_typelib;
|
||||
extern handlerton *handlertons[MAX_HA];
|
||||
extern ulong total_ha, total_ha_2pc;
|
||||
|
||||
|
|
|
@ -432,6 +432,7 @@ char server_version[SERVER_VERSION_LENGTH];
|
|||
char *mysqld_unix_port, *opt_mysql_tmpdir;
|
||||
const char **errmesg; /* Error messages */
|
||||
const char *myisam_recover_options_str="OFF";
|
||||
const char *myisam_stats_method_str="nulls_inequal";
|
||||
/* name of reference on left espression in rewritten IN subquery */
|
||||
const char *in_left_expr_name= "<left expr>";
|
||||
/* name of additional condition */
|
||||
|
@ -4360,6 +4361,7 @@ enum options_mysqld
|
|||
OPT_MAX_ERROR_COUNT, OPT_MULTI_RANGE_COUNT, OPT_MYISAM_DATA_POINTER_SIZE,
|
||||
OPT_MYISAM_BLOCK_SIZE, OPT_MYISAM_MAX_EXTRA_SORT_FILE_SIZE,
|
||||
OPT_MYISAM_MAX_SORT_FILE_SIZE, OPT_MYISAM_SORT_BUFFER_SIZE,
|
||||
OPT_MYISAM_STATS_METHOD,
|
||||
OPT_NET_BUFFER_LENGTH, OPT_NET_RETRY_COUNT,
|
||||
OPT_NET_READ_TIMEOUT, OPT_NET_WRITE_TIMEOUT,
|
||||
OPT_OPEN_FILES_LIMIT,
|
||||
|
@ -5515,6 +5517,11 @@ The minimum value for this variable is 4096.",
|
|||
(gptr*) &global_system_variables.myisam_sort_buff_size,
|
||||
(gptr*) &max_system_variables.myisam_sort_buff_size, 0,
|
||||
GET_ULONG, REQUIRED_ARG, 8192*1024, 4, ~0L, 0, 1, 0},
|
||||
{"myisam_stats_method", OPT_MYISAM_STATS_METHOD,
|
||||
"Specifies how MyISAM index statistics collection code should threat NULLs. "
|
||||
"Possible values of name are \"nulls_inequal\" (default behavior for 4.1/5.0), and \"nulls_equal\" (emulate 4.0 behavior).",
|
||||
(gptr*) &myisam_stats_method_str, (gptr*) &myisam_stats_method_str, 0,
|
||||
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||
{"net_buffer_length", OPT_NET_BUFFER_LENGTH,
|
||||
"Buffer length for TCP/IP and socket communication.",
|
||||
(gptr*) &global_system_variables.net_buffer_length,
|
||||
|
@ -6099,6 +6106,7 @@ static void mysql_init_variables(void)
|
|||
query_id= thread_id= 1L;
|
||||
strmov(server_version, MYSQL_SERVER_VERSION);
|
||||
myisam_recover_options_str= sql_mode_str= "OFF";
|
||||
myisam_stats_method_str= "nulls_inequal";
|
||||
my_bind_addr = htonl(INADDR_ANY);
|
||||
threads.empty();
|
||||
thread_cache.empty();
|
||||
|
@ -6147,6 +6155,12 @@ static void mysql_init_variables(void)
|
|||
global_system_variables.max_join_size= (ulonglong) HA_POS_ERROR;
|
||||
max_system_variables.max_join_size= (ulonglong) HA_POS_ERROR;
|
||||
global_system_variables.old_passwords= 0;
|
||||
|
||||
/*
|
||||
Default behavior for 4.1 and 5.0 is to treat NULL values as inequal
|
||||
when collecting index statistics for MyISAM tables.
|
||||
*/
|
||||
global_system_variables.myisam_stats_method= MI_STATS_METHOD_NULLS_NOT_EQUAL;
|
||||
|
||||
/* Variables that depends on compile options */
|
||||
#ifndef DBUG_OFF
|
||||
|
@ -6756,6 +6770,17 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
|
|||
fprintf(stderr, "Unknown option to tc-heuristic-recover: %s\n",argument);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
case OPT_MYISAM_STATS_METHOD:
|
||||
{
|
||||
myisam_stats_method_str= argument;
|
||||
int method;
|
||||
if ((method=find_type(argument, &myisam_stats_method_typelib, 2)) <= 0)
|
||||
{
|
||||
fprintf(stderr, "Invalid value of myisam_stats_method: %s.\n", argument);
|
||||
exit(1);
|
||||
}
|
||||
global_system_variables.myisam_stats_method= method-1;
|
||||
break;
|
||||
}
|
||||
case OPT_SQL_MODE:
|
||||
|
|
|
@ -270,6 +270,12 @@ sys_var_long_ptr sys_myisam_data_pointer_size("myisam_data_pointer_size",
|
|||
sys_var_thd_ulonglong sys_myisam_max_sort_file_size("myisam_max_sort_file_size", &SV::myisam_max_sort_file_size, fix_myisam_max_sort_file_size, 1);
|
||||
sys_var_thd_ulong sys_myisam_repair_threads("myisam_repair_threads", &SV::myisam_repair_threads);
|
||||
sys_var_thd_ulong sys_myisam_sort_buffer_size("myisam_sort_buffer_size", &SV::myisam_sort_buff_size);
|
||||
|
||||
sys_var_thd_enum sys_myisam_stats_method("myisam_stats_method",
|
||||
&SV::myisam_stats_method,
|
||||
&myisam_stats_method_typelib,
|
||||
NULL);
|
||||
|
||||
sys_var_thd_ulong sys_net_buffer_length("net_buffer_length",
|
||||
&SV::net_buffer_length);
|
||||
sys_var_thd_ulong sys_net_read_timeout("net_read_timeout",
|
||||
|
@ -630,6 +636,7 @@ sys_var *sys_variables[]=
|
|||
&sys_myisam_max_sort_file_size,
|
||||
&sys_myisam_repair_threads,
|
||||
&sys_myisam_sort_buffer_size,
|
||||
&sys_myisam_stats_method,
|
||||
&sys_net_buffer_length,
|
||||
&sys_net_read_timeout,
|
||||
&sys_net_retry_count,
|
||||
|
@ -896,6 +903,9 @@ struct show_var_st init_vars[]= {
|
|||
{sys_myisam_repair_threads.name, (char*) &sys_myisam_repair_threads,
|
||||
SHOW_SYS},
|
||||
{sys_myisam_sort_buffer_size.name, (char*) &sys_myisam_sort_buffer_size, SHOW_SYS},
|
||||
|
||||
{sys_myisam_stats_method.name, (char*) &sys_myisam_stats_method, SHOW_SYS},
|
||||
|
||||
#ifdef __NT__
|
||||
{"named_pipe", (char*) &opt_enable_named_pipe, SHOW_MY_BOOL},
|
||||
#endif
|
||||
|
|
|
@ -861,14 +861,6 @@ static TABLE_RULE_ENT* find_wild(DYNAMIC_ARRAY *a, const char* key, int len)
|
|||
rules (see code below). For that reason, users should not set conflicting
|
||||
rules because they may get unpredicted results (precedence order is
|
||||
explained in the manual).
|
||||
If no table of the list is marked "updating" (so far this can only happen
|
||||
if the statement is a multi-delete (SQLCOM_DELETE_MULTI) and the "tables"
|
||||
is the tables in the FROM): then we always return 0, because there is no
|
||||
reason we play this statement on this slave if it updates nothing. In the
|
||||
case of SQLCOM_DELETE_MULTI, there will be a second call to tables_ok(),
|
||||
with tables having "updating==TRUE" (those after the DELETE), so this
|
||||
second call will make the decision (because
|
||||
all_tables_not_ok() = !tables_ok(1st_list) && !tables_ok(2nd_list)).
|
||||
|
||||
Thought which arose from a question of a big customer "I want to include
|
||||
all tables like "abc.%" except the "%.EFG"". This can't be done now. If we
|
||||
|
|
|
@ -509,6 +509,7 @@ struct system_variables
|
|||
ulong multi_range_count;
|
||||
ulong myisam_repair_threads;
|
||||
ulong myisam_sort_buff_size;
|
||||
ulong myisam_stats_method;
|
||||
ulong net_buffer_length;
|
||||
ulong net_interactive_timeout;
|
||||
ulong net_read_timeout;
|
||||
|
|
|
@ -147,6 +147,10 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
|
|||
MYF(0));
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
/*
|
||||
This needs to be done before external_lock
|
||||
*/
|
||||
ha_enable_transaction(thd, FALSE);
|
||||
if (open_and_lock_tables(thd, table_list))
|
||||
DBUG_RETURN(TRUE);
|
||||
if (setup_tables(thd, &thd->lex->select_lex.context,
|
||||
|
@ -352,7 +356,6 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
|
|||
if (ignore ||
|
||||
handle_duplicates == DUP_REPLACE)
|
||||
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
|
||||
ha_enable_transaction(thd, FALSE);
|
||||
table->file->start_bulk_insert((ha_rows) 0);
|
||||
table->copy_blobs=1;
|
||||
|
||||
|
@ -372,10 +375,10 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
|
|||
*enclosed, skip_lines, ignore);
|
||||
if (table->file->end_bulk_insert())
|
||||
error=1; /* purecov: inspected */
|
||||
ha_enable_transaction(thd, TRUE);
|
||||
table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
|
||||
table->next_number_field=0;
|
||||
}
|
||||
ha_enable_transaction(thd, TRUE);
|
||||
if (file >= 0)
|
||||
my_close(file,MYF(0));
|
||||
free_blobs(table); /* if pack_blob was used */
|
||||
|
|
|
@ -183,10 +183,7 @@ static bool begin_trans(THD *thd)
|
|||
*/
|
||||
inline bool all_tables_not_ok(THD *thd, TABLE_LIST *tables)
|
||||
{
|
||||
return (table_rules_on && tables && !tables_ok(thd,tables) &&
|
||||
((thd->lex->sql_command != SQLCOM_DELETE_MULTI) ||
|
||||
!tables_ok(thd,
|
||||
(TABLE_LIST *)thd->lex->auxilliary_table_list.first)));
|
||||
return table_rules_on && tables && !tables_ok(thd,tables);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -7212,6 +7209,12 @@ bool multi_delete_set_locks_and_link_aux_tables(LEX *lex)
|
|||
target_tbl->table_name, "MULTI DELETE");
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
if (!walk->derived)
|
||||
{
|
||||
target_tbl->table_name= walk->table_name;
|
||||
target_tbl->table_name_length= walk->table_name_length;
|
||||
}
|
||||
walk->updating= target_tbl->updating;
|
||||
walk->lock_type= target_tbl->lock_type;
|
||||
target_tbl->correspondent_table= walk; // Remember corresponding table
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue