Merge spetrunia@bk-internal.mysql.com:/home/bk/mysql-4.1
into mysql.com:/home/psergey/mysql-4.1-bug12915-r2 sql/sql_update.cc: Auto merged
This commit is contained in:
commit
7d81acb5e9
@ -263,3 +263,62 @@ test
|
|||||||
delete from t1 where count(*)=1;
|
delete from t1 where count(*)=1;
|
||||||
ERROR HY000: Invalid use of group function
|
ERROR HY000: Invalid use of group function
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
create table t1 ( a int, index (a) );
|
||||||
|
insert into t1 values (0),(0),(0),(0),(0),(0),(0),(0);
|
||||||
|
flush status;
|
||||||
|
select a from t1 order by a limit 1;
|
||||||
|
a
|
||||||
|
0
|
||||||
|
show status like 'handler_read%';
|
||||||
|
Variable_name Value
|
||||||
|
Handler_read_first 1
|
||||||
|
Handler_read_key 0
|
||||||
|
Handler_read_next 0
|
||||||
|
Handler_read_prev 0
|
||||||
|
Handler_read_rnd 0
|
||||||
|
Handler_read_rnd_next 0
|
||||||
|
flush status;
|
||||||
|
update t1 set a=unix_timestamp() order by a limit 1;
|
||||||
|
show status like 'handler_read%';
|
||||||
|
Variable_name Value
|
||||||
|
Handler_read_first 1
|
||||||
|
Handler_read_key 0
|
||||||
|
Handler_read_next 0
|
||||||
|
Handler_read_prev 0
|
||||||
|
Handler_read_rnd 1
|
||||||
|
Handler_read_rnd_next 0
|
||||||
|
flush status;
|
||||||
|
delete from t1 order by a limit 1;
|
||||||
|
show status like 'handler_read%';
|
||||||
|
Variable_name Value
|
||||||
|
Handler_read_first 1
|
||||||
|
Handler_read_key 0
|
||||||
|
Handler_read_next 0
|
||||||
|
Handler_read_prev 0
|
||||||
|
Handler_read_rnd 0
|
||||||
|
Handler_read_rnd_next 0
|
||||||
|
flush status;
|
||||||
|
delete from t1 order by a desc limit 1;
|
||||||
|
show status like 'handler_read%';
|
||||||
|
Variable_name Value
|
||||||
|
Handler_read_first 0
|
||||||
|
Handler_read_key 0
|
||||||
|
Handler_read_next 0
|
||||||
|
Handler_read_prev 0
|
||||||
|
Handler_read_rnd 1
|
||||||
|
Handler_read_rnd_next 9
|
||||||
|
alter table t1 disable keys;
|
||||||
|
flush status;
|
||||||
|
delete from t1 order by a limit 1;
|
||||||
|
show status like 'handler_read%';
|
||||||
|
Variable_name Value
|
||||||
|
Handler_read_first 0
|
||||||
|
Handler_read_key 0
|
||||||
|
Handler_read_next 0
|
||||||
|
Handler_read_prev 0
|
||||||
|
Handler_read_rnd 1
|
||||||
|
Handler_read_rnd_next 9
|
||||||
|
select count(*) from t1;
|
||||||
|
count(*)
|
||||||
|
5
|
||||||
|
drop table t1;
|
||||||
|
@ -227,4 +227,33 @@ select DATABASE();
|
|||||||
delete from t1 where count(*)=1;
|
delete from t1 where count(*)=1;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
|
# BUG#12915: Optimize "DELETE|UPDATE ... ORDER BY ... LIMIT n" to use an index
|
||||||
|
create table t1 ( a int, index (a) );
|
||||||
|
insert into t1 values (0),(0),(0),(0),(0),(0),(0),(0);
|
||||||
|
|
||||||
|
flush status;
|
||||||
|
select a from t1 order by a limit 1;
|
||||||
|
show status like 'handler_read%';
|
||||||
|
|
||||||
|
flush status;
|
||||||
|
update t1 set a=unix_timestamp() order by a limit 1;
|
||||||
|
show status like 'handler_read%';
|
||||||
|
|
||||||
|
flush status;
|
||||||
|
delete from t1 order by a limit 1;
|
||||||
|
show status like 'handler_read%';
|
||||||
|
|
||||||
|
flush status;
|
||||||
|
delete from t1 order by a desc limit 1;
|
||||||
|
show status like 'handler_read%';
|
||||||
|
|
||||||
|
alter table t1 disable keys;
|
||||||
|
|
||||||
|
flush status;
|
||||||
|
delete from t1 order by a limit 1;
|
||||||
|
show status like 'handler_read%';
|
||||||
|
|
||||||
|
select count(*) from t1;
|
||||||
|
|
||||||
|
drop table t1;
|
||||||
# End of 4.1 tests
|
# End of 4.1 tests
|
||||||
|
@ -1105,6 +1105,8 @@ void change_byte(byte *,uint,char,char);
|
|||||||
void init_read_record(READ_RECORD *info, THD *thd, TABLE *reg_form,
|
void init_read_record(READ_RECORD *info, THD *thd, TABLE *reg_form,
|
||||||
SQL_SELECT *select,
|
SQL_SELECT *select,
|
||||||
int use_record_cache, bool print_errors);
|
int use_record_cache, bool print_errors);
|
||||||
|
void init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table,
|
||||||
|
bool print_error, uint idx);
|
||||||
void end_read_record(READ_RECORD *info);
|
void end_read_record(READ_RECORD *info);
|
||||||
ha_rows filesort(THD *thd, TABLE *form,struct st_sort_field *sortorder,
|
ha_rows filesort(THD *thd, TABLE *form,struct st_sort_field *sortorder,
|
||||||
uint s_length, SQL_SELECT *select,
|
uint s_length, SQL_SELECT *select,
|
||||||
|
@ -582,6 +582,96 @@ SEL_ARG *SEL_ARG::clone_tree()
|
|||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Find the best index to retrieve first N records in given order
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
get_index_for_order()
|
||||||
|
table Table to be accessed
|
||||||
|
order Required ordering
|
||||||
|
limit Number of records that will be retrieved
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
Find the best index that allows to retrieve first #limit records in the
|
||||||
|
given order cheaper then one would retrieve them using full table scan.
|
||||||
|
|
||||||
|
IMPLEMENTATION
|
||||||
|
Run through all table indexes and find the shortest index that allows
|
||||||
|
records to be retrieved in given order. We look for the shortest index
|
||||||
|
as we will have fewer index pages to read with it.
|
||||||
|
|
||||||
|
This function is used only by UPDATE/DELETE, so we take into account how
|
||||||
|
the UPDATE/DELETE code will work:
|
||||||
|
* index can only be scanned in forward direction
|
||||||
|
* HA_EXTRA_KEYREAD will not be used
|
||||||
|
Perhaps these assumptions could be relaxed
|
||||||
|
|
||||||
|
RETURN
|
||||||
|
index number
|
||||||
|
MAX_KEY if no such index was found.
|
||||||
|
*/
|
||||||
|
|
||||||
|
uint get_index_for_order(TABLE *table, ORDER *order, ha_rows limit)
|
||||||
|
{
|
||||||
|
uint idx;
|
||||||
|
uint match_key= MAX_KEY, match_key_len= MAX_KEY_LENGTH + 1;
|
||||||
|
ORDER *ord;
|
||||||
|
|
||||||
|
for (ord= order; ord; ord= ord->next)
|
||||||
|
if (!ord->asc)
|
||||||
|
return MAX_KEY;
|
||||||
|
|
||||||
|
for (idx= 0; idx < table->keys; idx++)
|
||||||
|
{
|
||||||
|
if (!(table->keys_in_use_for_query.is_set(idx)))
|
||||||
|
continue;
|
||||||
|
KEY_PART_INFO *keyinfo= table->key_info[idx].key_part;
|
||||||
|
uint partno= 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
The below check is sufficient considering we now have either BTREE
|
||||||
|
indexes (records are returned in order for any index prefix) or HASH
|
||||||
|
indexes (records are not returned in order for any index prefix).
|
||||||
|
*/
|
||||||
|
if (!(table->file->index_flags(idx, 0, 1) & HA_READ_ORDER))
|
||||||
|
continue;
|
||||||
|
for (ord= order; ord; ord= ord->next, partno++)
|
||||||
|
{
|
||||||
|
Item *item= order->item[0];
|
||||||
|
if (!(item->type() == Item::FIELD_ITEM &&
|
||||||
|
((Item_field*)item)->field->eq(keyinfo[partno].field)))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ord && table->key_info[idx].key_length < match_key_len)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Ok, the ordering is compatible and this key is shorter then
|
||||||
|
previous match (we want shorter keys as we'll have to read fewer
|
||||||
|
index pages for the same number of records)
|
||||||
|
*/
|
||||||
|
match_key= idx;
|
||||||
|
match_key_len= table->key_info[idx].key_length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (match_key != MAX_KEY)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Found an index that allows records to be retrieved in the requested
|
||||||
|
order. Now we'll check if using the index is cheaper then doing a table
|
||||||
|
scan.
|
||||||
|
*/
|
||||||
|
double full_scan_time= table->file->scan_time();
|
||||||
|
double index_scan_time= table->file->read_time(match_key, 1, limit);
|
||||||
|
if (index_scan_time > full_scan_time)
|
||||||
|
match_key= MAX_KEY;
|
||||||
|
}
|
||||||
|
return match_key;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Test if a key can be used in different ranges
|
Test if a key can be used in different ranges
|
||||||
|
|
||||||
|
@ -167,4 +167,6 @@ public:
|
|||||||
QUICK_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table,
|
QUICK_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table,
|
||||||
struct st_table_ref *ref);
|
struct st_table_ref *ref);
|
||||||
|
|
||||||
|
uint get_index_for_order(TABLE *table, ORDER *order, ha_rows limit);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
108
sql/records.cc
108
sql/records.cc
@ -29,7 +29,59 @@ static int rr_from_cache(READ_RECORD *info);
|
|||||||
static int init_rr_cache(READ_RECORD *info);
|
static int init_rr_cache(READ_RECORD *info);
|
||||||
static int rr_cmp(uchar *a,uchar *b);
|
static int rr_cmp(uchar *a,uchar *b);
|
||||||
|
|
||||||
/* init struct for read with info->read_record */
|
static int rr_index(READ_RECORD *info);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Initialize READ_RECORD structure to perform full index scan
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
init_read_record_idx()
|
||||||
|
info READ_RECORD structure to initialize.
|
||||||
|
thd Thread handle
|
||||||
|
table Table to be accessed
|
||||||
|
print_error If true, call table->file->print_error() if an error
|
||||||
|
occurs (except for end-of-records error)
|
||||||
|
idx index to scan
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
Initialize READ_RECORD structure to perform full index scan (in forward
|
||||||
|
direction) using read_record.read_record() interface.
|
||||||
|
|
||||||
|
This function has been added at late stage and is used only by
|
||||||
|
UPDATE/DELETE. Other statements perform index scans using
|
||||||
|
join_read_first/next functions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table,
|
||||||
|
bool print_error, uint idx)
|
||||||
|
{
|
||||||
|
bzero((char*) info,sizeof(*info));
|
||||||
|
info->thd=thd;
|
||||||
|
info->table=table;
|
||||||
|
info->file= table->file;
|
||||||
|
info->forms= &info->table; /* Only one table */
|
||||||
|
|
||||||
|
info->record= table->record[0];
|
||||||
|
info->ref_length= table->file->ref_length;
|
||||||
|
|
||||||
|
info->select=NULL;
|
||||||
|
info->print_error=print_error;
|
||||||
|
info->ignore_not_found_rows= 0;
|
||||||
|
table->status=0; /* And it's always found */
|
||||||
|
|
||||||
|
if (!table->file->inited)
|
||||||
|
{
|
||||||
|
table->file->ha_index_init(idx);
|
||||||
|
table->file->extra(HA_EXTRA_RETRIEVE_PRIMARY_KEY);
|
||||||
|
}
|
||||||
|
info->read_record= rr_index;
|
||||||
|
info->first= TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* init struct for read with info->read_record */
|
||||||
|
|
||||||
void init_read_record(READ_RECORD *info,THD *thd, TABLE *table,
|
void init_read_record(READ_RECORD *info,THD *thd, TABLE *table,
|
||||||
SQL_SELECT *select,
|
SQL_SELECT *select,
|
||||||
@ -182,6 +234,60 @@ static int rr_quick(READ_RECORD *info)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
A READ_RECORD::read_record implementation that reads index sequentially
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
rr_index()
|
||||||
|
info Scan info
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
Read the next index record (in forward direction) and translate return
|
||||||
|
value.
|
||||||
|
|
||||||
|
RETURN
|
||||||
|
0 Ok
|
||||||
|
-1 End of records
|
||||||
|
1 Error
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int rr_index(READ_RECORD *info)
|
||||||
|
{
|
||||||
|
int tmp;
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
if (info->first)
|
||||||
|
{
|
||||||
|
info->first= FALSE;
|
||||||
|
tmp= info->file->index_first(info->record);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
tmp= info->file->index_next(info->record);
|
||||||
|
|
||||||
|
if (!tmp)
|
||||||
|
break;
|
||||||
|
if (info->thd->killed)
|
||||||
|
{
|
||||||
|
my_error(ER_SERVER_SHUTDOWN,MYF(0));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (tmp != HA_ERR_RECORD_DELETED)
|
||||||
|
{
|
||||||
|
if (tmp == HA_ERR_END_OF_FILE)
|
||||||
|
tmp= -1;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (info->print_error)
|
||||||
|
info->table->file->print_error(tmp,MYF(0));
|
||||||
|
if (tmp < 0) // Fix negative BDB errno
|
||||||
|
tmp=1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
static int rr_sequential(READ_RECORD *info)
|
static int rr_sequential(READ_RECORD *info)
|
||||||
{
|
{
|
||||||
int tmp;
|
int tmp;
|
||||||
|
@ -37,6 +37,7 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
|
|||||||
bool using_limit=limit != HA_POS_ERROR;
|
bool using_limit=limit != HA_POS_ERROR;
|
||||||
bool transactional_table, log_delayed, safe_update, const_cond;
|
bool transactional_table, log_delayed, safe_update, const_cond;
|
||||||
ha_rows deleted;
|
ha_rows deleted;
|
||||||
|
uint usable_index= MAX_KEY;
|
||||||
DBUG_ENTER("mysql_delete");
|
DBUG_ENTER("mysql_delete");
|
||||||
|
|
||||||
if ((open_and_lock_tables(thd, table_list)))
|
if ((open_and_lock_tables(thd, table_list)))
|
||||||
@ -119,30 +120,47 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
|
|||||||
tables.table = table;
|
tables.table = table;
|
||||||
tables.alias = table_list->alias;
|
tables.alias = table_list->alias;
|
||||||
|
|
||||||
table->sort.io_cache = (IO_CACHE *) my_malloc(sizeof(IO_CACHE),
|
|
||||||
MYF(MY_FAE | MY_ZEROFILL));
|
|
||||||
if (thd->lex->select_lex.setup_ref_array(thd, order->elements) ||
|
if (thd->lex->select_lex.setup_ref_array(thd, order->elements) ||
|
||||||
setup_order(thd, thd->lex->select_lex.ref_pointer_array, &tables,
|
setup_order(thd, thd->lex->select_lex.ref_pointer_array, &tables,
|
||||||
fields, all_fields, (ORDER*) order->first) ||
|
fields, all_fields, (ORDER*) order->first))
|
||||||
!(sortorder=make_unireg_sortorder((ORDER*) order->first, &length)) ||
|
|
||||||
(table->sort.found_records = filesort(thd, table, sortorder, length,
|
|
||||||
select, HA_POS_ERROR,
|
|
||||||
&examined_rows))
|
|
||||||
== HA_POS_ERROR)
|
|
||||||
{
|
{
|
||||||
delete select;
|
delete select;
|
||||||
free_underlaid_joins(thd, &thd->lex->select_lex);
|
free_underlaid_joins(thd, &thd->lex->select_lex);
|
||||||
DBUG_RETURN(-1); // This will force out message
|
DBUG_RETURN(-1); // This will force out message
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
Filesort has already found and selected the rows we want to delete,
|
if (!select && limit != HA_POS_ERROR)
|
||||||
so we don't need the where clause
|
usable_index= get_index_for_order(table, (ORDER*)(order->first), limit);
|
||||||
*/
|
|
||||||
delete select;
|
if (usable_index == MAX_KEY)
|
||||||
select= 0;
|
{
|
||||||
|
table->sort.io_cache= (IO_CACHE *) my_malloc(sizeof(IO_CACHE),
|
||||||
|
MYF(MY_FAE | MY_ZEROFILL));
|
||||||
|
|
||||||
|
if ( !(sortorder=make_unireg_sortorder((ORDER*) order->first, &length)) ||
|
||||||
|
(table->sort.found_records = filesort(thd, table, sortorder, length,
|
||||||
|
select, HA_POS_ERROR,
|
||||||
|
&examined_rows))
|
||||||
|
== HA_POS_ERROR)
|
||||||
|
{
|
||||||
|
delete select;
|
||||||
|
free_underlaid_joins(thd, &thd->lex->select_lex);
|
||||||
|
DBUG_RETURN(-1); // This will force out message
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
Filesort has already found and selected the rows we want to delete,
|
||||||
|
so we don't need the where clause
|
||||||
|
*/
|
||||||
|
delete select;
|
||||||
|
select= 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
init_read_record(&info,thd,table,select,1,1);
|
if (usable_index==MAX_KEY)
|
||||||
|
init_read_record(&info,thd,table,select,1,1);
|
||||||
|
else
|
||||||
|
init_read_record_idx(&info, thd, table, 1, usable_index);
|
||||||
|
|
||||||
deleted=0L;
|
deleted=0L;
|
||||||
init_ftfuncs(thd, &thd->lex->select_lex, 1);
|
init_ftfuncs(thd, &thd->lex->select_lex, 1);
|
||||||
thd->proc_info="updating";
|
thd->proc_info="updating";
|
||||||
|
@ -61,7 +61,8 @@ int mysql_update(THD *thd,
|
|||||||
bool safe_update= thd->options & OPTION_SAFE_UPDATES;
|
bool safe_update= thd->options & OPTION_SAFE_UPDATES;
|
||||||
bool used_key_is_modified, transactional_table, log_delayed;
|
bool used_key_is_modified, transactional_table, log_delayed;
|
||||||
int error=0;
|
int error=0;
|
||||||
uint used_index;
|
uint used_index= MAX_KEY;
|
||||||
|
bool need_sort= TRUE;
|
||||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||||
uint want_privilege;
|
uint want_privilege;
|
||||||
#endif
|
#endif
|
||||||
@ -145,6 +146,11 @@ int mysql_update(THD *thd,
|
|||||||
send_ok(thd); // No matching records
|
send_ok(thd); // No matching records
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
if (!select && limit != HA_POS_ERROR)
|
||||||
|
{
|
||||||
|
if (MAX_KEY != (used_index= get_index_for_order(table, order, limit)))
|
||||||
|
need_sort= FALSE;
|
||||||
|
}
|
||||||
/* If running in safe sql mode, don't allow updates without keys */
|
/* If running in safe sql mode, don't allow updates without keys */
|
||||||
if (table->quick_keys.is_clear_all())
|
if (table->quick_keys.is_clear_all())
|
||||||
{
|
{
|
||||||
@ -157,6 +163,7 @@ int mysql_update(THD *thd,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
init_ftfuncs(thd, &thd->lex->select_lex, 1);
|
init_ftfuncs(thd, &thd->lex->select_lex, 1);
|
||||||
|
|
||||||
/* Check if we are modifying a key that we are used to search with */
|
/* Check if we are modifying a key that we are used to search with */
|
||||||
if (select && select->quick)
|
if (select && select->quick)
|
||||||
{
|
{
|
||||||
@ -164,13 +171,15 @@ int mysql_update(THD *thd,
|
|||||||
used_key_is_modified= (!select->quick->unique_key_range() &&
|
used_key_is_modified= (!select->quick->unique_key_range() &&
|
||||||
check_if_key_used(table, used_index, fields));
|
check_if_key_used(table, used_index, fields));
|
||||||
}
|
}
|
||||||
|
else if (used_index != MAX_KEY)
|
||||||
|
{
|
||||||
|
used_key_is_modified= check_if_key_used(table, used_index, fields);
|
||||||
|
}
|
||||||
else if ((used_index=table->file->key_used_on_scan) < MAX_KEY)
|
else if ((used_index=table->file->key_used_on_scan) < MAX_KEY)
|
||||||
used_key_is_modified=check_if_key_used(table, used_index, fields);
|
used_key_is_modified=check_if_key_used(table, used_index, fields);
|
||||||
else
|
else
|
||||||
{
|
|
||||||
used_key_is_modified=0;
|
used_key_is_modified=0;
|
||||||
used_index= MAX_KEY;
|
|
||||||
}
|
|
||||||
if (used_key_is_modified || order)
|
if (used_key_is_modified || order)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -181,10 +190,11 @@ int mysql_update(THD *thd,
|
|||||||
if (used_index < MAX_KEY && old_used_keys.is_set(used_index))
|
if (used_index < MAX_KEY && old_used_keys.is_set(used_index))
|
||||||
{
|
{
|
||||||
table->key_read=1;
|
table->key_read=1;
|
||||||
table->file->extra(HA_EXTRA_KEYREAD);
|
table->file->extra(HA_EXTRA_KEYREAD); //todo: psergey: check
|
||||||
}
|
}
|
||||||
|
|
||||||
if (order)
|
/* note: can actually avoid sorting below.. */
|
||||||
|
if (order && need_sort)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
Doing an ORDER BY; Let filesort find and sort the rows we are going
|
Doing an ORDER BY; Let filesort find and sort the rows we are going
|
||||||
@ -225,7 +235,11 @@ int mysql_update(THD *thd,
|
|||||||
DISK_BUFFER_SIZE, MYF(MY_WME)))
|
DISK_BUFFER_SIZE, MYF(MY_WME)))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
init_read_record(&info,thd,table,select,0,1);
|
if (used_index == MAX_KEY)
|
||||||
|
init_read_record(&info,thd,table,select,0,1);
|
||||||
|
else
|
||||||
|
init_read_record_idx(&info, thd, table, 1, used_index);
|
||||||
|
|
||||||
thd->proc_info="Searching rows for update";
|
thd->proc_info="Searching rows for update";
|
||||||
uint tmp_limit= limit;
|
uint tmp_limit= limit;
|
||||||
|
|
||||||
@ -251,6 +265,10 @@ int mysql_update(THD *thd,
|
|||||||
error= 1; // Aborted
|
error= 1; // Aborted
|
||||||
limit= tmp_limit;
|
limit= tmp_limit;
|
||||||
end_read_record(&info);
|
end_read_record(&info);
|
||||||
|
|
||||||
|
/* if we got here we must not use index in the main update loop below */
|
||||||
|
used_index= MAX_KEY;
|
||||||
|
|
||||||
/* Change select to use tempfile */
|
/* Change select to use tempfile */
|
||||||
if (select)
|
if (select)
|
||||||
{
|
{
|
||||||
|
@ -132,6 +132,7 @@ typedef struct st_read_record { /* Parameter to read_record */
|
|||||||
byte *cache,*cache_pos,*cache_end,*read_positions;
|
byte *cache,*cache_pos,*cache_end,*read_positions;
|
||||||
IO_CACHE *io_cache;
|
IO_CACHE *io_cache;
|
||||||
bool print_error, ignore_not_found_rows;
|
bool print_error, ignore_not_found_rows;
|
||||||
|
bool first; /* used only with rr_index_read */
|
||||||
} READ_RECORD;
|
} READ_RECORD;
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user