mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
Reverted patch for new usage of open_count as it caused more problems than it solved
Cleaned up patch for checking locks for multi-table updates
This commit is contained in:
@ -70,8 +70,13 @@ int mi_close(register MI_INFO *info)
|
|||||||
error=my_errno;
|
error=my_errno;
|
||||||
if (share->kfile >= 0)
|
if (share->kfile >= 0)
|
||||||
{
|
{
|
||||||
/* We must always flush the state with the current open_count. */
|
/*
|
||||||
if (share->mode != O_RDONLY)
|
If we are crashed, we can safely flush the current state as it will
|
||||||
|
not change the crashed state.
|
||||||
|
We can NOT write the state in other cases as other threads
|
||||||
|
may be using the file at this point
|
||||||
|
*/
|
||||||
|
if (share->mode != O_RDONLY && mi_is_crashed(info))
|
||||||
mi_state_info_write(share->kfile, &share->state, 1);
|
mi_state_info_write(share->kfile, &share->state, 1);
|
||||||
if (my_close(share->kfile,MYF(0)))
|
if (my_close(share->kfile,MYF(0)))
|
||||||
error = my_errno;
|
error = my_errno;
|
||||||
|
@ -19,16 +19,26 @@
|
|||||||
reads info from a isam-table. Must be first request before doing any furter
|
reads info from a isam-table. Must be first request before doing any furter
|
||||||
calls to any isamfunktion. Is used to allow many process use the same
|
calls to any isamfunktion. Is used to allow many process use the same
|
||||||
isamdatabase.
|
isamdatabase.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
state.open_count in the .MYI file is used the following way:
|
||||||
|
- For the first change of the file in this process it's incremented with
|
||||||
|
mi_mark_file_change(). (We have a write lock on the file in this case)
|
||||||
|
- In mi_close() it's decremented by _mi_decrement_open_count() if it
|
||||||
|
was incremented in the same process.
|
||||||
|
|
||||||
|
This mean that if we are the only process using the file, the open_count
|
||||||
|
tells us if the MYISAM file wasn't properly closed. (This is true if
|
||||||
|
my_disable_locking is set).
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "myisamdef.h"
|
#include "myisamdef.h"
|
||||||
#ifdef __WIN__
|
#ifdef __WIN__
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int mi_unlock_open_count(MI_INFO *info, my_bool write_info);
|
|
||||||
|
|
||||||
|
|
||||||
/* lock table by F_UNLCK, F_RDLCK or F_WRLCK */
|
/* lock table by F_UNLCK, F_RDLCK or F_WRLCK */
|
||||||
|
|
||||||
int mi_lock_database(MI_INFO *info, int lock_type)
|
int mi_lock_database(MI_INFO *info, int lock_type)
|
||||||
@ -38,17 +48,17 @@ int mi_lock_database(MI_INFO *info, int lock_type)
|
|||||||
MYISAM_SHARE *share=info->s;
|
MYISAM_SHARE *share=info->s;
|
||||||
uint flag;
|
uint flag;
|
||||||
DBUG_ENTER("mi_lock_database");
|
DBUG_ENTER("mi_lock_database");
|
||||||
DBUG_PRINT("enter",("mi_lock_database: lock_type %d, old lock %d"
|
DBUG_PRINT("enter",("lock_type: %d old lock %d r_locks: %u w_locks: %u "
|
||||||
", r_locks %u, w_locks %u", lock_type,
|
"global_changed: %d open_count: %u name: '%s'",
|
||||||
info->lock_type, share->r_locks, share->w_locks));
|
lock_type, info->lock_type, share->r_locks,
|
||||||
DBUG_PRINT("enter",("mi_lock_database: gl._changed %d, open_count %u '%s'",
|
share->w_locks,
|
||||||
share->global_changed, share->state.open_count,
|
share->global_changed, share->state.open_count,
|
||||||
share->index_file_name));
|
share->index_file_name));
|
||||||
|
|
||||||
if (share->options & HA_OPTION_READ_ONLY_DATA ||
|
if (share->options & HA_OPTION_READ_ONLY_DATA ||
|
||||||
info->lock_type == lock_type)
|
info->lock_type == lock_type)
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
if (lock_type == F_EXTRA_LCK)
|
if (lock_type == F_EXTRA_LCK) /* Used by TMP tables */
|
||||||
{
|
{
|
||||||
++share->w_locks;
|
++share->w_locks;
|
||||||
++share->tot_locks;
|
++share->tot_locks;
|
||||||
@ -90,8 +100,7 @@ int mi_lock_database(MI_INFO *info, int lock_type)
|
|||||||
share->state.process= share->last_process=share->this_process;
|
share->state.process= share->last_process=share->this_process;
|
||||||
share->state.unique= info->last_unique= info->this_unique;
|
share->state.unique= info->last_unique= info->this_unique;
|
||||||
share->state.update_count= info->last_loop= ++info->this_loop;
|
share->state.update_count= info->last_loop= ++info->this_loop;
|
||||||
if (mi_unlock_open_count(info, FALSE) ||
|
if (mi_state_info_write(share->kfile, &share->state, 1))
|
||||||
mi_state_info_write(share->kfile, &share->state, 1))
|
|
||||||
error=my_errno;
|
error=my_errno;
|
||||||
share->changed=0;
|
share->changed=0;
|
||||||
if (myisam_flush)
|
if (myisam_flush)
|
||||||
@ -106,19 +115,6 @@ int mi_lock_database(MI_INFO *info, int lock_type)
|
|||||||
if (error)
|
if (error)
|
||||||
mi_mark_crashed(info);
|
mi_mark_crashed(info);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
There are chances that _mi_mark_file_changed() has been called,
|
|
||||||
while share->changed remained FALSE. Consequently, we need to
|
|
||||||
clear the open_count even when share->changed is FALSE. Note,
|
|
||||||
that mi_unlock_open_count() will only clear the open_count when
|
|
||||||
it is set and only write the status to file, if it changes it
|
|
||||||
and we are running --with-external-locking.
|
|
||||||
*/
|
|
||||||
if (mi_unlock_open_count(info, ! my_disable_locking))
|
|
||||||
error= my_errno;
|
|
||||||
}
|
|
||||||
if (info->lock_type != F_EXTRA_LCK)
|
if (info->lock_type != F_EXTRA_LCK)
|
||||||
{
|
{
|
||||||
if (share->r_locks)
|
if (share->r_locks)
|
||||||
@ -142,16 +138,17 @@ int mi_lock_database(MI_INFO *info, int lock_type)
|
|||||||
break;
|
break;
|
||||||
case F_RDLCK:
|
case F_RDLCK:
|
||||||
if (info->lock_type == F_WRLCK)
|
if (info->lock_type == F_WRLCK)
|
||||||
{ /* Change RW to READONLY */
|
{
|
||||||
/*
|
/*
|
||||||
|
Change RW to READONLY
|
||||||
|
|
||||||
mysqld does not turn write locks to read locks,
|
mysqld does not turn write locks to read locks,
|
||||||
so we're never here in mysqld.
|
so we're never here in mysqld.
|
||||||
*/
|
*/
|
||||||
if (share->w_locks == 1)
|
if (share->w_locks == 1)
|
||||||
{
|
{
|
||||||
flag=1;
|
flag=1;
|
||||||
if (mi_unlock_open_count(info, ! my_disable_locking) ||
|
if (my_lock(share->kfile,lock_type,0L,F_TO_EOF,
|
||||||
my_lock(share->kfile,lock_type,0L,F_TO_EOF,
|
|
||||||
MYF(MY_SEEK_NOT_DONE)))
|
MYF(MY_SEEK_NOT_DONE)))
|
||||||
{
|
{
|
||||||
error=my_errno;
|
error=my_errno;
|
||||||
@ -179,14 +176,6 @@ int mi_lock_database(MI_INFO *info, int lock_type)
|
|||||||
my_errno=error;
|
my_errno=error;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (share->state.open_count)
|
|
||||||
{
|
|
||||||
DBUG_PRINT("error",("RD: Table has not been correctly unlocked"
|
|
||||||
": open_count %d '%s'",
|
|
||||||
share->state.open_count,
|
|
||||||
share->index_file_name));
|
|
||||||
mi_mark_crashed(info);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
VOID(_mi_test_if_changed(info));
|
VOID(_mi_test_if_changed(info));
|
||||||
share->r_locks++;
|
share->r_locks++;
|
||||||
@ -232,14 +221,6 @@ int mi_lock_database(MI_INFO *info, int lock_type)
|
|||||||
my_errno=error;
|
my_errno=error;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (share->state.open_count)
|
|
||||||
{
|
|
||||||
DBUG_PRINT("error",("WR: Table has not been correctly unlocked"
|
|
||||||
": open_count %d '%s'",
|
|
||||||
share->state.open_count,
|
|
||||||
share->index_file_name));
|
|
||||||
mi_mark_crashed(info);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -375,9 +356,10 @@ int _mi_readinfo(register MI_INFO *info, int lock_type, int check_keybuffer)
|
|||||||
} /* _mi_readinfo */
|
} /* _mi_readinfo */
|
||||||
|
|
||||||
|
|
||||||
/* Every isam-function that uppdates the isam-database must! end */
|
/*
|
||||||
/* with this request */
|
Every isam-function that uppdates the isam-database MUST end with this
|
||||||
/* ARGSUSED */
|
request
|
||||||
|
*/
|
||||||
|
|
||||||
int _mi_writeinfo(register MI_INFO *info, uint operation)
|
int _mi_writeinfo(register MI_INFO *info, uint operation)
|
||||||
{
|
{
|
||||||
@ -450,6 +432,8 @@ int _mi_mark_file_changed(MI_INFO *info)
|
|||||||
{
|
{
|
||||||
char buff[3];
|
char buff[3];
|
||||||
register MYISAM_SHARE *share=info->s;
|
register MYISAM_SHARE *share=info->s;
|
||||||
|
DBUG_ENTER("_mi_mark_file_changed");
|
||||||
|
|
||||||
if (!(share->state.changed & STATE_CHANGED) || ! share->global_changed)
|
if (!(share->state.changed & STATE_CHANGED) || ! share->global_changed)
|
||||||
{
|
{
|
||||||
share->state.changed|=(STATE_CHANGED | STATE_NOT_ANALYZED |
|
share->state.changed|=(STATE_CHANGED | STATE_NOT_ANALYZED |
|
||||||
@ -463,12 +447,12 @@ int _mi_mark_file_changed(MI_INFO *info)
|
|||||||
{
|
{
|
||||||
mi_int2store(buff,share->state.open_count);
|
mi_int2store(buff,share->state.open_count);
|
||||||
buff[2]=1; /* Mark that it's changed */
|
buff[2]=1; /* Mark that it's changed */
|
||||||
return (my_pwrite(share->kfile,buff,sizeof(buff),
|
DBUG_RETURN(my_pwrite(share->kfile,buff,sizeof(buff),
|
||||||
sizeof(share->state.header),
|
sizeof(share->state.header),
|
||||||
MYF(MY_NABP)));
|
MYF(MY_NABP)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -501,36 +485,3 @@ int _mi_decrement_open_count(MI_INFO *info)
|
|||||||
}
|
}
|
||||||
return test(lock_error || write_error);
|
return test(lock_error || write_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
Decrement open_count in preparation for unlock.
|
|
||||||
|
|
||||||
SYNOPSIS
|
|
||||||
mi_unlock_open_count()
|
|
||||||
info Pointer to the MI_INFO structure.
|
|
||||||
write_info If info must be written when changed.
|
|
||||||
|
|
||||||
RETURN
|
|
||||||
0 OK
|
|
||||||
*/
|
|
||||||
|
|
||||||
static int mi_unlock_open_count(MI_INFO *info, my_bool write_info)
|
|
||||||
{
|
|
||||||
int rc= 0;
|
|
||||||
MYISAM_SHARE *share=info->s;
|
|
||||||
|
|
||||||
DBUG_ENTER("mi_unlock_open_count");
|
|
||||||
DBUG_PRINT("enter",("mi_unlock_open_count: gl._changed %d open_count %d '%s'",
|
|
||||||
share->global_changed, share->state.open_count,
|
|
||||||
share->index_file_name));
|
|
||||||
if (share->global_changed)
|
|
||||||
{
|
|
||||||
share->global_changed= 0;
|
|
||||||
if (share->state.open_count)
|
|
||||||
share->state.open_count--;
|
|
||||||
if (write_info)
|
|
||||||
rc= _mi_writeinfo(info, WRITEINFO_UPDATE_KEYFILE);
|
|
||||||
}
|
|
||||||
DBUG_RETURN(rc);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -998,32 +998,14 @@ int ha_myisam::delete_table(const char *name)
|
|||||||
return mi_delete_table(name);
|
return mi_delete_table(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int ha_myisam::external_lock(THD *thd, int lock_type)
|
int ha_myisam::external_lock(THD *thd, int lock_type)
|
||||||
{
|
{
|
||||||
int rc;
|
return mi_lock_database(file, !table->tmp_table ?
|
||||||
|
lock_type : ((lock_type == F_UNLCK) ?
|
||||||
while ((! (rc= mi_lock_database(file, !table->tmp_table ?
|
F_UNLCK : F_EXTRA_LCK));
|
||||||
lock_type : ((lock_type == F_UNLCK) ?
|
|
||||||
F_UNLCK : F_EXTRA_LCK)))) &&
|
|
||||||
mi_is_crashed(file) && (myisam_recover_options != HA_RECOVER_NONE))
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
check_and_repair() implicitly write locks the table, unless a
|
|
||||||
LOCK TABLES is in effect. It should be safer to always write lock here.
|
|
||||||
The implicit lock by check_and_repair() will then be a no-op.
|
|
||||||
check_and_repair() does not restore the original lock, but unlocks the
|
|
||||||
table. So we have to get the requested lock type again. And then to
|
|
||||||
check, if the table has been crashed again meanwhile by another server.
|
|
||||||
If anything fails, we break.
|
|
||||||
*/
|
|
||||||
if (((lock_type != F_WRLCK) && (rc= mi_lock_database(file, F_WRLCK))) ||
|
|
||||||
(rc= check_and_repair(thd)))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
THR_LOCK_DATA **ha_myisam::store_lock(THD *thd,
|
THR_LOCK_DATA **ha_myisam::store_lock(THD *thd,
|
||||||
THR_LOCK_DATA **to,
|
THR_LOCK_DATA **to,
|
||||||
enum thr_lock_type lock_type)
|
enum thr_lock_type lock_type)
|
||||||
|
@ -348,7 +348,7 @@ int ha_commit_trans(THD *thd, THD_TRANS* trans)
|
|||||||
if (trans == &thd->transaction.all &&
|
if (trans == &thd->transaction.all &&
|
||||||
my_b_tell(&thd->transaction.trans_log))
|
my_b_tell(&thd->transaction.trans_log))
|
||||||
{
|
{
|
||||||
if (error= wait_if_global_read_lock(thd, 0, 0))
|
if ((error= wait_if_global_read_lock(thd, 0, 0)))
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
Note that ROLLBACK [TO SAVEPOINT] does not have this test; it's
|
Note that ROLLBACK [TO SAVEPOINT] does not have this test; it's
|
||||||
|
@ -469,7 +469,7 @@ static ulong get_sort(uint count,...)
|
|||||||
uint chars= 0;
|
uint chars= 0;
|
||||||
uint wild_pos= 0; /* first wildcard position */
|
uint wild_pos= 0; /* first wildcard position */
|
||||||
|
|
||||||
if (start= str)
|
if ((start= str))
|
||||||
{
|
{
|
||||||
for (; *str ; str++)
|
for (; *str ; str++)
|
||||||
{
|
{
|
||||||
|
@ -2209,11 +2209,7 @@ copy_data_between_tables(TABLE *from,TABLE *to,
|
|||||||
DBUG_RETURN(-1); /* purecov: inspected */
|
DBUG_RETURN(-1); /* purecov: inspected */
|
||||||
|
|
||||||
if (to->file->external_lock(thd, F_WRLCK))
|
if (to->file->external_lock(thd, F_WRLCK))
|
||||||
{
|
|
||||||
/* We must always unlock, even when lock failed. */
|
|
||||||
(void) to->file->external_lock(thd, F_UNLCK);
|
|
||||||
DBUG_RETURN(-1);
|
DBUG_RETURN(-1);
|
||||||
}
|
|
||||||
to->file->extra(HA_EXTRA_WRITE_CACHE);
|
to->file->extra(HA_EXTRA_WRITE_CACHE);
|
||||||
from->file->info(HA_STATUS_VARIABLE);
|
from->file->info(HA_STATUS_VARIABLE);
|
||||||
to->file->deactivate_non_unique_index(from->file->records);
|
to->file->deactivate_non_unique_index(from->file->records);
|
||||||
@ -2313,11 +2309,11 @@ copy_data_between_tables(TABLE *from,TABLE *to,
|
|||||||
error=1;
|
error=1;
|
||||||
if (ha_commit(thd))
|
if (ha_commit(thd))
|
||||||
error=1;
|
error=1;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
free_io_cache(from);
|
free_io_cache(from);
|
||||||
*copied= found_count;
|
*copied= found_count;
|
||||||
*deleted=delete_count;
|
*deleted=delete_count;
|
||||||
/* we must always unlock the table on return. */
|
|
||||||
if (to->file->external_lock(thd,F_UNLCK))
|
if (to->file->external_lock(thd,F_UNLCK))
|
||||||
error=1;
|
error=1;
|
||||||
DBUG_RETURN(error > 0 ? -1 : 0);
|
DBUG_RETURN(error > 0 ? -1 : 0);
|
||||||
|
@ -386,6 +386,24 @@ err:
|
|||||||
Update multiple tables from join
|
Update multiple tables from join
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Get table map for list of Item_field
|
||||||
|
*/
|
||||||
|
|
||||||
|
static table_map get_table_map(List<Item> *items)
|
||||||
|
{
|
||||||
|
List_iterator_fast<Item> item_it(*items);
|
||||||
|
Item_field *item;
|
||||||
|
table_map map= 0;
|
||||||
|
|
||||||
|
while ((item= (Item_field *) item_it++))
|
||||||
|
map|= item->used_tables();
|
||||||
|
DBUG_PRINT("info",("table_map: 0x%08x", map));
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Setup multi-update handling and call SELECT to do the join
|
Setup multi-update handling and call SELECT to do the join
|
||||||
*/
|
*/
|
||||||
@ -401,59 +419,45 @@ int mysql_multi_update(THD *thd,
|
|||||||
int res;
|
int res;
|
||||||
multi_update *result;
|
multi_update *result;
|
||||||
TABLE_LIST *tl;
|
TABLE_LIST *tl;
|
||||||
const bool locked= !(thd->locked_tables);
|
const bool using_lock_tables= thd->locked_tables != 0;
|
||||||
DBUG_ENTER("mysql_multi_update");
|
DBUG_ENTER("mysql_multi_update");
|
||||||
|
|
||||||
|
thd->select_limit= HA_POS_ERROR;
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
table_map update_map= 0;
|
table_map update_map;
|
||||||
int tnr= 0;
|
int tnr;
|
||||||
|
|
||||||
if ((res= open_tables(thd, table_list)))
|
if ((res= open_tables(thd, table_list)))
|
||||||
DBUG_RETURN(res);
|
DBUG_RETURN(res);
|
||||||
|
|
||||||
/*
|
/* Only need to call lock_tables if we are not using LOCK TABLES */
|
||||||
Only need to call lock_tables if (thd->locked_tables == NULL)
|
if (!using_lock_tables && ((res= lock_tables(thd, table_list))))
|
||||||
*/
|
|
||||||
if (locked && ((res= lock_tables(thd, table_list))))
|
|
||||||
DBUG_RETURN(res);
|
DBUG_RETURN(res);
|
||||||
|
|
||||||
thd->select_limit=HA_POS_ERROR;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Ensure that we have update privilege for all tables and columns in the
|
Ensure that we have update privilege for all tables and columns in the
|
||||||
SET part
|
SET part
|
||||||
While we are here, initialize the table->map field.
|
While we are here, initialize the table->map field.
|
||||||
*/
|
*/
|
||||||
for (tl= table_list ; tl ; tl=tl->next)
|
for (tl= table_list,tnr=0 ; tl ; tl=tl->next)
|
||||||
{
|
{
|
||||||
TABLE *table= tl->table;
|
TABLE *table= tl->table;
|
||||||
table->grant.want_privilege= (UPDATE_ACL & ~table->grant.privilege);
|
table->grant.want_privilege= (UPDATE_ACL & ~table->grant.privilege);
|
||||||
table->map= (table_map) 1 << (tnr++);
|
table->map= (table_map) 1 << (tnr++);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!setup_fields(thd, table_list, *fields, 1, 0, 0))
|
if (setup_fields(thd, table_list, *fields, 1, 0, 0))
|
||||||
{
|
|
||||||
List_iterator_fast<Item> field_it(*fields);
|
|
||||||
Item_field *item;
|
|
||||||
|
|
||||||
while ((item= (Item_field *) field_it++))
|
|
||||||
update_map|= item->used_tables();
|
|
||||||
|
|
||||||
DBUG_PRINT("info",("update_map=0x%08x", update_map));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
DBUG_RETURN(-1);
|
DBUG_RETURN(-1);
|
||||||
|
|
||||||
/*
|
update_map= get_table_map(fields);
|
||||||
Unlock the tables in preparation for relocking
|
|
||||||
*/
|
/* Unlock the tables in preparation for relocking */
|
||||||
if (locked)
|
if (!using_lock_tables)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&LOCK_open);
|
|
||||||
mysql_unlock_tables(thd, thd->lock);
|
mysql_unlock_tables(thd, thd->lock);
|
||||||
thd->lock= 0;
|
thd->lock= 0;
|
||||||
pthread_mutex_unlock(&LOCK_open);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -474,26 +478,48 @@ int mysql_multi_update(THD *thd,
|
|||||||
tl->lock_type= TL_READ;
|
tl->lock_type= TL_READ;
|
||||||
tl->updating= 0;
|
tl->updating= 0;
|
||||||
}
|
}
|
||||||
if (locked)
|
if (!using_lock_tables)
|
||||||
tl->table->reginfo.lock_type= tl->lock_type;
|
tl->table->reginfo.lock_type= tl->lock_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Relock the tables with the correct modes */
|
||||||
|
res= lock_tables(thd,table_list);
|
||||||
|
if (using_lock_tables)
|
||||||
|
{
|
||||||
|
if (res)
|
||||||
|
DBUG_RETURN(res);
|
||||||
|
break; // Don't have to do setup_field()
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Relock the tables
|
We must setup fields again as the file may have been reopened
|
||||||
|
during lock_tables
|
||||||
*/
|
*/
|
||||||
if (!(res=lock_tables(thd,table_list)))
|
|
||||||
|
{
|
||||||
|
List_iterator_fast<Item> field_it(*fields);
|
||||||
|
Item_field *item;
|
||||||
|
|
||||||
|
while ((item= (Item_field *) field_it++))
|
||||||
|
#if MYSQL_VERSION < 40100
|
||||||
|
item->field= item->result_field= 0;
|
||||||
|
#else
|
||||||
|
item->cleanup();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
if (setup_fields(thd, table_list, *fields, 1, 0, 0))
|
||||||
|
DBUG_RETURN(-1);
|
||||||
|
/*
|
||||||
|
If lock succeded and the table map didn't change since the above lock
|
||||||
|
we can continue.
|
||||||
|
*/
|
||||||
|
if (!res && update_map == get_table_map(fields))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (!locked)
|
|
||||||
DBUG_RETURN(res);
|
|
||||||
|
|
||||||
List_iterator_fast<Item> field_it(*fields);
|
|
||||||
Item_field *item;
|
|
||||||
|
|
||||||
while ((item= (Item_field *) field_it++))
|
|
||||||
/* item->cleanup(); XXX Use this instead in MySQL 4.1+ */
|
|
||||||
item->field= item->result_field= 0;
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
There was some very unexpected changes in the table definition between
|
||||||
|
open tables and lock tables. Close tables and try again.
|
||||||
|
*/
|
||||||
close_thread_tables(thd);
|
close_thread_tables(thd);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -548,7 +574,7 @@ int multi_update::prepare(List<Item> ¬_used_values)
|
|||||||
{
|
{
|
||||||
TABLE_LIST *table_ref;
|
TABLE_LIST *table_ref;
|
||||||
SQL_LIST update;
|
SQL_LIST update;
|
||||||
table_map tables_to_update= 0;
|
table_map tables_to_update;
|
||||||
Item_field *item;
|
Item_field *item;
|
||||||
List_iterator_fast<Item> field_it(*fields);
|
List_iterator_fast<Item> field_it(*fields);
|
||||||
List_iterator_fast<Item> value_it(*values);
|
List_iterator_fast<Item> value_it(*values);
|
||||||
@ -559,8 +585,7 @@ int multi_update::prepare(List<Item> ¬_used_values)
|
|||||||
thd->cuted_fields=0L;
|
thd->cuted_fields=0L;
|
||||||
thd->proc_info="updating main table";
|
thd->proc_info="updating main table";
|
||||||
|
|
||||||
while ((item= (Item_field *) field_it++))
|
tables_to_update= get_table_map(fields);
|
||||||
tables_to_update|= item->used_tables();
|
|
||||||
|
|
||||||
if (!tables_to_update)
|
if (!tables_to_update)
|
||||||
{
|
{
|
||||||
@ -624,7 +649,6 @@ int multi_update::prepare(List<Item> ¬_used_values)
|
|||||||
|
|
||||||
/* Split fields into fields_for_table[] and values_by_table[] */
|
/* Split fields into fields_for_table[] and values_by_table[] */
|
||||||
|
|
||||||
field_it.rewind();
|
|
||||||
while ((item= (Item_field *) field_it++))
|
while ((item= (Item_field *) field_it++))
|
||||||
{
|
{
|
||||||
Item *value= value_it++;
|
Item *value= value_it++;
|
||||||
|
Reference in New Issue
Block a user