diff options
-rw-r--r-- | mysql-test/r/insert_select.result | 12 | ||||
-rw-r--r-- | mysql-test/t/archive.test | 2 | ||||
-rw-r--r-- | mysql-test/t/insert_select.test | 15 | ||||
-rw-r--r-- | sql/examples/ha_archive.cc | 60 | ||||
-rw-r--r-- | sql/examples/ha_archive.h | 4 | ||||
-rw-r--r-- | sql/handler.cc | 14 | ||||
-rw-r--r-- | sql/set_var.cc | 4 | ||||
-rw-r--r-- | sql/sql_class.h | 2 | ||||
-rw-r--r-- | sql/sql_insert.cc | 47 | ||||
-rw-r--r-- | sql/sql_select.cc | 4 |
10 files changed, 139 insertions, 25 deletions
diff --git a/mysql-test/r/insert_select.result b/mysql-test/r/insert_select.result index 94d33f8090b..8882b95f2d8 100644 --- a/mysql-test/r/insert_select.result +++ b/mysql-test/r/insert_select.result @@ -638,3 +638,15 @@ No Field Count 0 1 100 0 2 100 drop table t1, t2; +CREATE TABLE t1 ( +ID int(11) NOT NULL auto_increment, +NO int(11) NOT NULL default '0', +SEQ int(11) NOT NULL default '0', +PRIMARY KEY (ID), +KEY t1$NO (SEQ,NO) +) ENGINE=MyISAM; +INSERT INTO t1 (SEQ, NO) SELECT "1" AS SEQ, IF(MAX(NO) IS NULL, 0, MAX(NO)) + 1 AS NO FROM t1 WHERE (SEQ = 1); +select SQL_BUFFER_RESULT * from t1 WHERE (SEQ = 1); +ID NO SEQ +1 1 1 +drop table t1; diff --git a/mysql-test/t/archive.test b/mysql-test/t/archive.test index 8cf54610914..f7ec603ca79 100644 --- a/mysql-test/t/archive.test +++ b/mysql-test/t/archive.test @@ -1,6 +1,6 @@ # # Simple test for archive example -# Taken fromm the select test +# Taken from the select test # -- source include/have_archive.inc diff --git a/mysql-test/t/insert_select.test b/mysql-test/t/insert_select.test index 15509b06679..a5b163b3533 100644 --- a/mysql-test/t/insert_select.test +++ b/mysql-test/t/insert_select.test @@ -180,3 +180,18 @@ insert into t2 Select null, Field, Count From t1 Where Month=20030901 and Type=2 select * from t2; drop table t1, t2; + +# +# BUG#6034 - Error code 124: Wrong medium type +# +CREATE TABLE t1 ( + ID int(11) NOT NULL auto_increment, + NO int(11) NOT NULL default '0', + SEQ int(11) NOT NULL default '0', + PRIMARY KEY (ID), + KEY t1$NO (SEQ,NO) +) ENGINE=MyISAM; +INSERT INTO t1 (SEQ, NO) SELECT "1" AS SEQ, IF(MAX(NO) IS NULL, 0, MAX(NO)) + 1 AS NO FROM t1 WHERE (SEQ = 1); +select SQL_BUFFER_RESULT * from t1 WHERE (SEQ = 1); +drop table t1; + diff --git a/sql/examples/ha_archive.cc b/sql/examples/ha_archive.cc index dccff88bf1f..436c72702a0 100644 --- a/sql/examples/ha_archive.cc +++ b/sql/examples/ha_archive.cc @@ -117,7 +117,6 @@ /* Variables for archive share methods */ pthread_mutex_t archive_mutex; static HASH archive_open_tables; -static int archive_init= 0; /* The file extension */ #define ARZ ".ARZ" // The data file @@ -143,6 +142,46 @@ static byte* archive_get_key(ARCHIVE_SHARE *share,uint *length, return (byte*) share->table_name; } + +/* + Initialize the archive handler. + + SYNOPSIS + archive_db_init() + void + + RETURN + FALSE OK + TRUE Error +*/ + +bool archive_db_init() +{ + VOID(pthread_mutex_init(&archive_mutex, MY_MUTEX_INIT_FAST)); + return (hash_init(&archive_open_tables, system_charset_info, 32, 0, 0, + (hash_get_key) archive_get_key, 0, 0)); +} + + +/* + Release the archive handler. + + SYNOPSIS + archive_db_end() + void + + RETURN + FALSE OK +*/ + +bool archive_db_end() +{ + hash_free(&archive_open_tables); + VOID(pthread_mutex_destroy(&archive_mutex)); + return FALSE; +} + + /* This method reads the header of a datafile and returns whether or not it was successful. */ @@ -269,23 +308,6 @@ ARCHIVE_SHARE *ha_archive::get_share(const char *table_name, TABLE *table) uint length; char *tmp_name; - if (!archive_init) - { - /* Hijack a mutex for init'ing the storage engine */ - pthread_mutex_lock(&LOCK_mysql_create_db); - if (!archive_init) - { - VOID(pthread_mutex_init(&archive_mutex,MY_MUTEX_INIT_FAST)); - if (hash_init(&archive_open_tables,system_charset_info,32,0,0, - (hash_get_key) archive_get_key,0,0)) - { - pthread_mutex_unlock(&LOCK_mysql_create_db); - return NULL; - } - archive_init++; - } - pthread_mutex_unlock(&LOCK_mysql_create_db); - } pthread_mutex_lock(&archive_mutex); length=(uint) strlen(table_name); @@ -371,6 +393,7 @@ int ha_archive::free_share(ARCHIVE_SHARE *share) (void)write_meta_file(share->meta_file, share->rows_recorded, FALSE); if (gzclose(share->archive_write) == Z_ERRNO) rc= 1; + my_close(share->meta_file,MYF(0)); my_free((gptr) share, MYF(0)); } pthread_mutex_unlock(&archive_mutex); @@ -787,6 +810,7 @@ int ha_archive::repair(THD* thd, HA_CHECK_OPT* check_opt) goto error; } (void)write_meta_file(meta_file, rows_recorded, TRUE); + my_close(meta_file,MYF(0)); rc= 0; } diff --git a/sql/examples/ha_archive.h b/sql/examples/ha_archive.h index 07bc7baa400..a511b5c67d6 100644 --- a/sql/examples/ha_archive.h +++ b/sql/examples/ha_archive.h @@ -105,3 +105,7 @@ public: THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to, enum thr_lock_type lock_type); }; + +bool archive_db_init(void); +bool archive_db_end(void); + diff --git a/sql/handler.cc b/sql/handler.cc index b1b741dfee9..059d1feaed1 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -373,6 +373,16 @@ int ha_init() opt_using_transactions=1; } #endif +#ifdef HAVE_ARCHIVE_DB + if (have_archive_db == SHOW_OPTION_YES) + { + if (archive_db_init()) + { + have_archive_db= SHOW_OPTION_DISABLED; + error= 1; + } + } +#endif return error; } @@ -404,6 +414,10 @@ int ha_panic(enum ha_panic_function flag) if (have_ndbcluster == SHOW_OPTION_YES) error|=ndbcluster_end(); #endif +#ifdef HAVE_ARCHIVE_DB + if (have_archive_db == SHOW_OPTION_YES) + error|= archive_db_end(); +#endif if (ha_finish_errors()) error= 1; return error; diff --git a/sql/set_var.cc b/sql/set_var.cc index b71e16653b2..105b00fe7e6 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -28,7 +28,7 @@ - If the variable is thread specific, add it to 'system_variables' struct. If not, add it to mysqld.cc and an declaration in 'mysql_priv.h' - If the variable should be changed from the command line, add a definition - of it in the my_option structure list in mysqld.dcc + of it in the my_option structure list in mysqld.cc - Don't forget to initialize new fields in global_system_variables and max_system_variables! - If the variable should show up in 'show variables' add it to the @@ -584,6 +584,7 @@ sys_var *sys_variables[]= &sys_max_tmp_tables, &sys_max_user_connections, &sys_max_write_lock_count, + &sys_multi_range_count, &sys_myisam_data_pointer_size, &sys_myisam_max_extra_sort_file_size, &sys_myisam_max_sort_file_size, @@ -828,6 +829,7 @@ struct show_var_st init_vars[]= { {sys_max_tmp_tables.name, (char*) &sys_max_tmp_tables, SHOW_SYS}, {sys_max_user_connections.name,(char*) &sys_max_user_connections, SHOW_SYS}, {sys_max_write_lock_count.name, (char*) &sys_max_write_lock_count,SHOW_SYS}, + {sys_multi_range_count.name, (char*) &sys_multi_range_count, SHOW_SYS}, {sys_myisam_data_pointer_size.name, (char*) &sys_myisam_data_pointer_size, SHOW_SYS}, {sys_myisam_max_extra_sort_file_size.name, (char*) &sys_myisam_max_extra_sort_file_size, diff --git a/sql/sql_class.h b/sql/sql_class.h index ca65f011b9d..8e6204ab3a3 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1280,6 +1280,7 @@ public: unit= u; return 0; } + virtual int prepare2(void) { return 0; } /* Because of peculiarities of prepared statements protocol we need to know number of columns in the result set (if @@ -1379,6 +1380,7 @@ class select_insert :public select_result_interceptor { enum_duplicates duplic, bool ignore); ~select_insert(); int prepare(List<Item> &list, SELECT_LEX_UNIT *u); + int prepare2(void); bool send_data(List<Item> &items); virtual void store_values(List<Item> &values); void send_error(uint errcode,const char *err); diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index ceb31f76953..4cb62d5e9d7 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1802,13 +1802,22 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u) thd->lex->current_select->options|= OPTION_BUFFER_RESULT; thd->lex->current_select->join->select_options|= OPTION_BUFFER_RESULT; } - + else + { + /* + We must not yet prepare the result table if it is the same as one of the + source tables (INSERT SELECT). The preparation may disable + indexes on the result table, which may be used during the select, if it + is the same table (Bug #6034). Do the preparation after the select phase + in select_insert::prepare2(). + */ + if (info.ignore || info.handle_duplicates != DUP_ERROR) + table->file->extra(HA_EXTRA_IGNORE_DUP_KEY); + table->file->start_bulk_insert((ha_rows) 0); + } restore_record(table,s->default_values); // Get empty record table->next_number_field=table->found_next_number_field; thd->cuted_fields=0; - if (info.ignore || info.handle_duplicates != DUP_ERROR) - table->file->extra(HA_EXTRA_IGNORE_DUP_KEY); - table->file->start_bulk_insert((ha_rows) 0); thd->no_trans_update= 0; thd->abort_on_warning= (!info.ignore && (thd->variables.sql_mode & @@ -1819,6 +1828,36 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u) } +/* + Finish the preparation of the result table. + + SYNOPSIS + select_insert::prepare2() + void + + DESCRIPTION + If the result table is the same as one of the source tables (INSERT SELECT), + the result table is not finally prepared at the join prepair phase. + Do the final preparation now. + + RETURN + 0 OK +*/ + +int select_insert::prepare2(void) +{ + DBUG_ENTER("select_insert::prepare2"); + + if (thd->lex->current_select->options & OPTION_BUFFER_RESULT) + { + if (info.ignore || info.handle_duplicates != DUP_ERROR) + table->file->extra(HA_EXTRA_IGNORE_DUP_KEY); + table->file->start_bulk_insert((ha_rows) 0); + } + return 0; +} + + void select_insert::cleanup() { /* select_insert/select_create are never re-used in prepared statement */ diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 8e6929fdddf..69b5c667f6b 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1164,6 +1164,7 @@ JOIN::exec() DBUG_VOID_RETURN; } } + (void) result->prepare2(); // Currently, this cannot fail. if (!tables_list) { // Only test of functions @@ -13149,7 +13150,8 @@ bool JOIN::change_result(select_result *res) { DBUG_ENTER("JOIN::change_result"); result= res; - if (!procedure && result->prepare(fields_list, select_lex->master_unit())) + if (!procedure && (result->prepare(fields_list, select_lex->master_unit()) || + result->prepare2())) { DBUG_RETURN(TRUE); } |