Merge mysql.com:/home/mydev/mysql-5.0
into mysql.com:/home/mydev/mysql-5.0-amerge
This commit is contained in:
commit
76f066aa32
@ -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,
|
||||||
|
auto_increment);
|
||||||
set_if_bigger(info->s->state.auto_increment,
|
set_if_bigger(info->s->state.auto_increment,
|
||||||
param->auto_increment_value);
|
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));
|
||||||
|
@ -509,20 +509,19 @@ int _mi_read_key_record(MI_INFO *info, my_off_t filepos, byte *buf)
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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++;
|
||||||
|
@ -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) \
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
{
|
{
|
||||||
|
@ -425,15 +425,26 @@ bool mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info,
|
|||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user