summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/insert_select.result12
-rw-r--r--mysql-test/t/archive.test2
-rw-r--r--mysql-test/t/insert_select.test15
-rw-r--r--sql/examples/ha_archive.cc60
-rw-r--r--sql/examples/ha_archive.h4
-rw-r--r--sql/handler.cc14
-rw-r--r--sql/set_var.cc4
-rw-r--r--sql/sql_class.h2
-rw-r--r--sql/sql_insert.cc47
-rw-r--r--sql/sql_select.cc4
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);
}