3535 Sergey Glukhov 2011-10-27
Bug#11746275 24986: CALLS TO HANDLER::RND_INIT AND HANDLER::INDEX_INIT IGNORE RETURN VALUE
Changes in init_read_record(), init_read_record_idx functions():
--return type is changed from void to bool
--added error message generation when it's necessary
@ mysql-test/r/plugin.result
result fix
@ mysql-test/t/plugin.test
test fix
@ sql/event_db_repository.cc
added return value check
@ sql/events.cc
added return value check
@ sql/opt_range.cc
added return value check
@ sql/records.cc
init_read_record(), init_read_record_idx functions():
--return type is changed from void to bool
--added error message generation when it's necessary
@ sql/records.h
init_read_record(), init_read_record_idx functions():
return type is changed from void to bool.
@ sql/sql_acl.cc
added return value check
@ sql/sql_delete.cc
added return value check
@ sql/sql_help.cc
added return value check
@ sql/sql_plugin.cc
added return value check
@ sql/sql_select.cc
added return value check
@ sql/sql_servers.cc
added return value check
@ sql/sql_table.cc
added return value check
@ sql/sql_udf.cc
added return value check
@ sql/sql_update.cc
added return value check
modified:
mysql-test/r/plugin.result
mysql-test/t/plugin.test
sql/event_db_repository.cc
sql/events.cc
sql/opt_range.cc
sql/records.cc
sql/records.h
sql/sql_acl.cc
sql/sql_delete.cc
sql/sql_help.cc
sql/sql_plugin.cc
sql/sql_select.cc
sql/sql_servers.cc
sql/sql_table.cc
sql/sql_udf.cc
sql/sql_update.cc
3534 Sergey Glukhov 2011-10-27
Bug#11747423 32254: INDEX MERGE USED UNNECESSARILY
There was an assumption that quick select is always faster
than ref access for InnoDB tables. But some test cases show
that it's not true for index merge access. In some cases
ref access by compound single key is better than
index merge access by several keys. The fix is to
add a check that INDEX MERGE access is not more expensive
than ref access.
@ mysql-test/r/index_merge_innodb.result
test case
@ mysql-test/t/index_merge_innodb.test
test case
@ sql/sql_select.cc
added a check that INDEX MERGE access is not more expensive
than ref access.
modified:
mysql-test/r/index_merge_innodb.result
mysql-test/t/index_merge_innodb.test
sql/sql_select.cc
=== modified file 'mysql-test/r/plugin.result'
--- a/mysql-test/r/plugin.result 2009-12-22 11:02:52 +0000
+++ b/mysql-test/r/plugin.result 2011-10-27 08:43:56 +0000
@@ -10,7 +10,7 @@ UNINSTALL PLUGIN example;
INSTALL PLUGIN example SONAME 'ha_example.so';
CREATE TABLE t1(a int) ENGINE=EXAMPLE;
SELECT * FROM t1;
-a
+ERROR HY000: Table storage engine for 't1' doesn't have this option
DROP TABLE t1;
set global example_ulong_var=500;
set global example_enum_var= e1;
=== modified file 'mysql-test/t/plugin.test'
--- a/mysql-test/t/plugin.test 2011-01-11 13:27:03 +0000
+++ b/mysql-test/t/plugin.test 2011-10-27 08:43:56 +0000
@@ -17,7 +17,7 @@ eval INSTALL PLUGIN example SONAME '$EXA
CREATE TABLE t1(a int) ENGINE=EXAMPLE;
-# Let's do some advanced ops with the example engine :)
+--error ER_ILLEGAL_HA
SELECT * FROM t1;
DROP TABLE t1;
=== modified file 'sql/event_db_repository.cc'
--- a/sql/event_db_repository.cc 2011-07-28 10:54:44 +0000
+++ b/sql/event_db_repository.cc 2011-10-27 08:43:56 +0000
@@ -490,7 +490,8 @@ Event_db_repository::table_scan_all_for_
READ_RECORD read_record_info;
DBUG_ENTER("Event_db_repository::table_scan_all_for_i_s");
- init_read_record(&read_record_info, thd, event_table, NULL, 1, 0, FALSE);
+ if (init_read_record(&read_record_info, thd, event_table, NULL, 1, 1, FALSE))
+ DBUG_RETURN(TRUE);
/*
rr_sequential, in read_record(), returns 137==HA_ERR_END_OF_FILE,
@@ -508,7 +509,7 @@ Event_db_repository::table_scan_all_for_
end_read_record(&read_record_info);
/* ret is guaranteed to be != 0 */
- DBUG_RETURN(ret == -1? FALSE:TRUE);
+ DBUG_RETURN(ret == -1 ? FALSE : TRUE);
}
@@ -994,7 +995,8 @@ Event_db_repository::drop_schema_events(
DBUG_VOID_RETURN;
/* only enabled events are in memory, so we go now and delete the rest */
- init_read_record(&read_record_info, thd, table, NULL, 1, 0, FALSE);
+ if (init_read_record(&read_record_info, thd, table, NULL, 1, 1, FALSE))
+ DBUG_VOID_RETURN;
while (!ret && !(read_record_info.read_record(&read_record_info)) )
{
char *et_field= get_field(thd->mem_root, table->field[field]);
=== modified file 'sql/events.cc'
--- a/sql/events.cc 2011-08-19 13:04:28 +0000
+++ b/sql/events.cc 2011-10-27 08:43:56 +0000
@@ -1100,7 +1100,11 @@ Events::load_events_from_db(THD *thd)
DBUG_RETURN(TRUE);
}
- init_read_record(&read_record_info, thd, table, NULL, 0, 1, FALSE);
+ if (init_read_record(&read_record_info, thd, table, NULL, 0, 1, FALSE))
+ {
+ sql_print_error("Event Scheduler: Error while starting read of mysql.event");
+ DBUG_RETURN(TRUE);
+ }
while (!(read_record_info.read_record(&read_record_info)))
{
Event_queue_element *et;
=== modified file 'sql/opt_range.cc'
--- a/sql/opt_range.cc 2011-10-12 12:09:14 +0000
+++ b/sql/opt_range.cc 2011-10-27 08:43:56 +0000
@@ -9350,7 +9350,8 @@ int QUICK_INDEX_MERGE_SELECT::read_keys_
doing_pk_scan= FALSE;
/* index_merge currently doesn't support "using index" at all */
head->set_keyread(FALSE);
- init_read_record(&read_record, thd, head, (SQL_SELECT*) 0, 1 , 1, TRUE);
+ if (init_read_record(&read_record, thd, head, (SQL_SELECT*) 0, 1, 1, TRUE))
+ DBUG_RETURN(1);
DBUG_RETURN(result);
}
=== modified file 'sql/records.cc'
--- a/sql/records.cc 2011-08-26 08:55:54 +0000
+++ b/sql/records.cc 2011-10-27 08:43:56 +0000
@@ -58,11 +58,15 @@ static int rr_index_desc(READ_RECORD *in
occurs (except for end-of-records error)
@param idx index to scan
@param reverse Scan in the reverse direction
+
+ @retval true error
+ @retval false success
*/
-void init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table,
+bool init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table,
bool print_error, uint idx, bool reverse)
{
+ int error;
empty_record(table);
memset(info, 0, sizeof(*info));
info->thd= thd;
@@ -72,10 +76,17 @@ void init_read_record_idx(READ_RECORD *i
info->unlock_row= rr_unlock_row;
table->status=0; /* And it's always found */
- if (!table->file->inited)
- table->file->ha_index_init(idx, 1);
+ if (!table->file->inited &&
+ (error= table->file->ha_index_init(idx, 1)))
+ {
+ if (print_error)
+ table->file->print_error(error, MYF(0));
+ return true;
+ }
+
/* read_record will be changed to rr_index in rr_index_first */
info->read_record= reverse ? rr_index_last : rr_index_first;
+ return false;
}
@@ -163,12 +174,16 @@ void init_read_record_idx(READ_RECORD *i
--------------
This is the most basic access method of a table using rnd_init,
ha_rnd_next and rnd_end. No indexes are used.
+
+ @retval true error
+ @retval false success
*/
-void init_read_record(READ_RECORD *info,THD *thd, TABLE *table,
+bool init_read_record(READ_RECORD *info,THD *thd, TABLE *table,
SQL_SELECT *select,
int use_record_cache, bool print_error,
bool disable_rr_cache)
{
+ int error= 0;
IO_CACHE *tempfile;
DBUG_ENTER("init_read_record");
@@ -219,8 +234,9 @@ void init_read_record(READ_RECORD *info,
info->io_cache=tempfile;
reinit_io_cache(info->io_cache,READ_CACHE,0L,0,0);
info->ref_pos=table->file->ref;
- if (!table->file->inited)
- table->file->ha_rnd_init(0);
+ if (!table->file->inited &&
+ (error= table->file->ha_rnd_init(0)))
+ goto err;
/*
table->sort.addon_field is checked because if we use addon fields,
@@ -242,11 +258,10 @@ void init_read_record(READ_RECORD *info,
!table->s->blob_fields &&
info->ref_length <= MAX_REFLENGTH)
{
- if (! init_rr_cache(thd, info))
- {
- DBUG_PRINT("info",("using rr_from_cache"));
- info->read_record=rr_from_cache;
- }
+ if (init_rr_cache(thd, info))
+ DBUG_RETURN(true);
+ DBUG_PRINT("info",("using rr_from_cache"));
+ info->read_record=rr_from_cache;
}
}
else if (select && select->quick)
@@ -257,7 +272,8 @@ void init_read_record(READ_RECORD *info,
else if (table->sort.record_pointers)
{
DBUG_PRINT("info",("using record_pointers"));
- table->file->ha_rnd_init(0);
+ if ((error= table->file->ha_rnd_init(0)))
+ goto err;
info->cache_pos=table->sort.record_pointers;
info->cache_end=info->cache_pos+
table->sort.found_records*info->ref_length;
@@ -268,7 +284,8 @@ void init_read_record(READ_RECORD *info,
{
DBUG_PRINT("info",("using rr_sequential"));
info->read_record=rr_sequential;
- table->file->ha_rnd_init(1);
+ if ((error= table->file->ha_rnd_init(1)))
+ goto err;
/* We can use record cache if we don't update dynamic length tables */
if (!table->no_cache &&
(use_record_cache > 0 ||
@@ -290,7 +307,12 @@ void init_read_record(READ_RECORD *info,
!table->file->pushed_cond)
table->file->cond_push(select->cond);
- DBUG_VOID_RETURN;
+ DBUG_RETURN(false);
+
+err:
+ if (print_error)
+ table->file->print_error(error, MYF(0));
+ DBUG_RETURN(true);
} /* init_read_record */
=== modified file 'sql/records.h'
--- a/sql/records.h 2011-07-28 12:53:50 +0000
+++ b/sql/records.h 2011-10-27 08:43:56 +0000
@@ -28,13 +28,16 @@ class SQL_SELECT;
index read, scan, etc, use of cache, etc.
Use by:
+@code
READ_RECORD read_record;
- init_read_record(&read_record, ...);
+ if (init_read_record(&read_record, ...))
+ return TRUE;
while (read_record.read_record())
{
...
}
end_read_record();
+@endcode
*/
class Copy_field;
@@ -70,10 +73,10 @@ public:
READ_RECORD() {}
};
-void init_read_record(READ_RECORD *info, THD *thd, TABLE *reg_form,
+bool init_read_record(READ_RECORD *info, THD *thd, TABLE *reg_form,
SQL_SELECT *select, int use_record_cache,
bool print_errors, bool disable_rr_cache);
-void init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table,
+bool init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table,
bool print_error, uint idx, bool reverse);
void end_read_record(READ_RECORD *info);
=== modified file 'sql/sql_acl.cc'
--- a/sql/sql_acl.cc 2011-09-21 11:49:00 +0000
+++ b/sql/sql_acl.cc 2011-10-27 08:43:56 +0000
@@ -713,8 +713,9 @@ static my_bool acl_load(THD *thd, TABLE_
acl_cache->clear(1); // Clear locked hostname cache
init_sql_alloc(&mem, ACL_ALLOC_BLOCK_SIZE, 0);
- init_read_record(&read_record_info,thd,table= tables[0].table,NULL,1,0,
- FALSE);
+ if (init_read_record(&read_record_info, thd, table= tables[0].table,
+ NULL, 1, 1, FALSE))
+ goto end;
table->use_all_columns();
(void) my_init_dynamic_array(&acl_hosts,sizeof(ACL_HOST),20,50);
while (!(read_record_info.read_record(&read_record_info)))
@@ -763,7 +764,9 @@ static my_bool acl_load(THD *thd, TABLE_
end_read_record(&read_record_info);
freeze_size(&acl_hosts);
- init_read_record(&read_record_info,thd,table=tables[1].table,NULL,1,0,FALSE);
+ if (init_read_record(&read_record_info, thd, table=tables[1].table,
+ NULL, 1, 1, FALSE))
+ goto end;
table->use_all_columns();
(void) my_init_dynamic_array(&acl_users,sizeof(ACL_USER),50,100);
password_length= table->field[2]->field_length /
@@ -968,7 +971,9 @@ static my_bool acl_load(THD *thd, TABLE_
end_read_record(&read_record_info);
freeze_size(&acl_users);
- init_read_record(&read_record_info,thd,table=tables[2].table,NULL,1,0,FALSE);
+ if (init_read_record(&read_record_info, thd, table=tables[2].table,
+ NULL, 1, 1, FALSE))
+ goto end;
table->use_all_columns();
(void) my_init_dynamic_array(&acl_dbs,sizeof(ACL_DB),50,100);
while (!(read_record_info.read_record(&read_record_info)))
@@ -1031,8 +1036,9 @@ static my_bool acl_load(THD *thd, TABLE_
50, 100);
if (tables[3].table)
{
- init_read_record(&read_record_info, thd, table= tables[3].table, NULL, 1,
- 0, FALSE);
+ if (init_read_record(&read_record_info, thd, table= tables[3].table,
+ NULL, 1, 1, FALSE))
+ goto end;
table->use_all_columns();
while (!(read_record_info.read_record(&read_record_info)))
{
=== modified file 'sql/sql_delete.cc'
--- a/sql/sql_delete.cc 2011-07-20 10:29:12 +0000
+++ b/sql/sql_delete.cc 2011-10-27 08:43:56 +0000
@@ -311,10 +311,22 @@ bool mysql_delete(THD *thd, TABLE_LIST *
free_underlaid_joins(thd, select_lex);
DBUG_RETURN(TRUE);
}
+
if (usable_index==MAX_KEY || (select && select->quick))
- init_read_record(&info, thd, table, select, 1, 1, FALSE);
+ error= init_read_record(&info, thd, table, select, 1, 1, FALSE);
else
- init_read_record_idx(&info, thd, table, 1, usable_index, reverse);
+ error= init_read_record_idx(&info, thd, table, 1, usable_index, reverse);
+
+ if (error)
+ {
+ if (select)
+ {
+ delete select;
+ select= 0;
+ }
+ free_underlaid_joins(thd, select_lex);
+ DBUG_RETURN(TRUE);
+ }
init_ftfuncs(thd, select_lex, 1);
THD_STAGE_INFO(thd, stage_updating);
@@ -935,7 +947,8 @@ int multi_delete::do_table_deletes(TABLE
READ_RECORD info;
ha_rows last_deleted= deleted;
DBUG_ENTER("do_deletes_for_table");
- init_read_record(&info, thd, table, NULL, 0, 1, FALSE);
+ if (init_read_record(&info, thd, table, NULL, 0, 1, FALSE))
+ DBUG_RETURN(1);
/*
Ignore any rows not found in reference tables as they may already have
been deleted by foreign key handling
=== modified file 'sql/sql_help.cc'
--- a/sql/sql_help.cc 2011-07-19 15:11:15 +0000
+++ b/sql/sql_help.cc 2011-10-27 08:43:56 +0000
@@ -189,11 +189,13 @@ int search_topics(THD *thd, TABLE *topic
SQL_SELECT *select, List<String> *names,
String *name, String *description, String *example)
{
- DBUG_ENTER("search_topics");
int count= 0;
-
READ_RECORD read_record_info;
- init_read_record(&read_record_info, thd, topics, select, 1, 0, FALSE);
+ DBUG_ENTER("search_topics");
+
+ if (init_read_record(&read_record_info, thd, topics, select, 1, 0, FALSE))
+ DBUG_RETURN(0);
+
while (!read_record_info.read_record(&read_record_info))
{
if (!select->cond->val_int()) // Doesn't match like
@@ -229,11 +231,13 @@ int search_topics(THD *thd, TABLE *topic
int search_keyword(THD *thd, TABLE *keywords, struct st_find_field *find_fields,
SQL_SELECT *select, int *key_id)
{
- DBUG_ENTER("search_keyword");
int count= 0;
-
READ_RECORD read_record_info;
- init_read_record(&read_record_info, thd, keywords, select, 1, 0, FALSE);
+ DBUG_ENTER("search_keyword");
+
+ if (init_read_record(&read_record_info, thd, keywords, select, 1, 0, FALSE))
+ DBUG_RETURN(0);
+
while (!read_record_info.read_record(&read_record_info) && count<2)
{
if (!select->cond->val_int()) // Dosn't match like
@@ -359,7 +363,10 @@ int search_categories(THD *thd, TABLE *c
DBUG_ENTER("search_categories");
- init_read_record(&read_record_info, thd, categories, select,1,0,FALSE);
+ if (init_read_record(&read_record_info, thd, categories, select,
+ 1, 0, FALSE))
+ DBUG_RETURN(0);
+
while (!read_record_info.read_record(&read_record_info))
{
if (select && !select->cond->val_int())
@@ -390,10 +397,12 @@ int search_categories(THD *thd, TABLE *c
void get_all_items_for_category(THD *thd, TABLE *items, Field *pfname,
SQL_SELECT *select, List<String> *res)
{
+ READ_RECORD read_record_info;
DBUG_ENTER("get_all_items_for_category");
- READ_RECORD read_record_info;
- init_read_record(&read_record_info, thd, items, select,1,0,FALSE);
+ if (init_read_record(&read_record_info, thd, items, select,
+ 1, 0, FALSE))
+ DBUG_VOID_RETURN;
while (!read_record_info.read_record(&read_record_info))
{
if (!select->cond->val_int())
=== modified file 'sql/sql_plugin.cc'
--- a/sql/sql_plugin.cc 2011-09-21 11:01:41 +0000
+++ b/sql/sql_plugin.cc 2011-10-27 08:43:56 +0000
@@ -1493,7 +1493,8 @@ static void plugin_load(MEM_ROOT *tmp_ro
goto end;
}
table= tables.table;
- init_read_record(&read_record_info, new_thd, table, NULL, 1, 0, FALSE);
+ if (init_read_record(&read_record_info, new_thd, table, NULL, 1, 1, FALSE))
+ goto end;
table->use_all_columns();
/*
there're no other threads running yet, so we don't need a mutex.
=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc 2011-10-27 08:40:40 +0000
+++ b/sql/sql_select.cc 2011-10-27 08:43:56 +0000
@@ -18839,8 +18839,9 @@ sub_select_sjm(JOIN *join, JOIN_TAB *joi
const READ_RECORD::Setup_func saved_rfr= last_tab->read_first_record;
// Initialize full scan
- init_read_record(&last_tab->read_record, join->thd,
- sjm->table, NULL, TRUE, TRUE, FALSE);
+ if (init_read_record(&last_tab->read_record, join->thd,
+ sjm->table, NULL, TRUE, TRUE, FALSE))
+ DBUG_RETURN(NESTED_LOOP_ERROR);
last_tab->read_first_record= join_read_record_no_init;
last_tab->read_record.copy_field= sjm->copy_field;
@@ -20082,8 +20083,9 @@ int join_init_read_record(JOIN_TAB *tab)
report_error(tab->table, error);
return 1;
}
- init_read_record(&tab->read_record, tab->join->thd, tab->table,
- tab->select,1,1, FALSE);
+ if (init_read_record(&tab->read_record, tab->join->thd, tab->table,
+ tab->select, 1, 1, FALSE))
+ return 1;
return (*tab->read_record.read_record)(&tab->read_record);
}
=== modified file 'sql/sql_servers.cc'
--- a/sql/sql_servers.cc 2011-07-28 10:54:44 +0000
+++ b/sql/sql_servers.cc 2011-10-27 08:43:56 +0000
@@ -208,8 +208,10 @@ static bool servers_load(THD *thd, TABLE
free_root(&mem, MYF(0));
init_sql_alloc(&mem, ACL_ALLOC_BLOCK_SIZE, 0);
- init_read_record(&read_record_info,thd,table=tables[0].table,NULL,1,0,
- FALSE);
+ if (init_read_record(&read_record_info, thd, table=tables[0].table,
+ NULL, 1, 1, FALSE))
+ DBUG_RETURN(TRUE);
+
while (!(read_record_info.read_record(&read_record_info)))
{
/* return_val is already TRUE, so no need to set */
=== modified file 'sql/sql_table.cc'
--- a/sql/sql_table.cc 2011-10-07 14:20:21 +0000
+++ b/sql/sql_table.cc 2011-10-27 08:43:56 +0000
@@ -7367,7 +7367,11 @@ copy_data_between_tables(TABLE *from,TAB
/* Tell handler that we have values for all columns in the to table */
to->use_all_columns();
- init_read_record(&info, thd, from, (SQL_SELECT *) 0, 1, 1, FALSE);
+ if (init_read_record(&info, thd, from, (SQL_SELECT *) 0, 1, 1, FALSE))
+ {
+ error= 1;
+ goto err;
+ }
if (ignore)
to->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
thd->get_stmt_da()->reset_current_row_for_warning();
=== modified file 'sql/sql_udf.cc'
--- a/sql/sql_udf.cc 2011-06-30 15:50:45 +0000
+++ b/sql/sql_udf.cc 2011-10-27 08:43:56 +0000
@@ -171,7 +171,8 @@ void udf_init()
}
table= tables.table;
- init_read_record(&read_record_info, new_thd, table, NULL,1,0,FALSE);
+ if (init_read_record(&read_record_info, new_thd, table, NULL, 1, 1, FALSE))
+ goto end;
table->use_all_columns();
while (!(error= read_record_info.read_record(&read_record_info)))
{
=== modified file 'sql/sql_update.cc'
--- a/sql/sql_update.cc 2011-09-14 15:03:55 +0000
+++ b/sql/sql_update.cc 2011-10-27 08:43:56 +0000
@@ -567,9 +567,12 @@ int mysql_update(THD *thd,
*/
if (used_index == MAX_KEY || (select && select->quick))
- init_read_record(&info, thd, table, select, 0, 1, FALSE);
+ error= init_read_record(&info, thd, table, select, 0, 1, FALSE);
else
- init_read_record_idx(&info, thd, table, 1, used_index, reverse);
+ error= init_read_record_idx(&info, thd, table, 1, used_index, reverse);
+
+ if (error)
+ goto exit_without_my_ok;
THD_STAGE_INFO(thd, stage_searching_rows_for_update);
ha_rows tmp_limit= limit;
@@ -640,7 +643,8 @@ int mysql_update(THD *thd,
if (select && select->quick && select->quick->reset())
goto exit_without_my_ok;
table->file->try_semi_consistent_read(1);
- init_read_record(&info, thd, table, select, 0, 1, FALSE);
+ if ((error= init_read_record(&info, thd, table, select, 0, 1, FALSE)))
+ goto exit_without_my_ok;
updated= found= 0;
/*
No bundle (reason: useless for push emails).
| Thread |
|---|
| • bzr push into mysql-trunk branch (sergey.glukhov:3534 to 3535) Bug#11746275 | Sergey Glukhov | 27 Oct |