summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xBuild-tools/Do-compile26
-rw-r--r--innobase/btr/btr0cur.c11
-rw-r--r--innobase/include/lock0lock.h5
-rw-r--r--innobase/include/row0mysql.h7
-rw-r--r--innobase/include/srv0srv.h1
-rw-r--r--innobase/include/sync0arr.h2
-rw-r--r--innobase/include/trx0trx.h5
-rw-r--r--innobase/lock/lock0lock.c40
-rw-r--r--innobase/row/row0ins.c81
-rw-r--r--innobase/row/row0mysql.c21
-rw-r--r--innobase/srv/srv0srv.c3
-rw-r--r--innobase/srv/srv0start.c2
-rw-r--r--innobase/sync/sync0arr.c12
-rw-r--r--innobase/trx/trx0trx.c4
-rw-r--r--mysql-test/r/create_select_tmp.result19
-rw-r--r--mysql-test/r/rpl_drop.result10
-rw-r--r--mysql-test/t/create_select_tmp.test27
-rw-r--r--mysql-test/t/innodb.test17
-rw-r--r--mysql-test/t/rpl_drop.test10
-rw-r--r--sql/ha_innodb.cc4
-rw-r--r--sql/sql_insert.cc8
-rw-r--r--sql/sql_load.cc5
22 files changed, 248 insertions, 72 deletions
diff --git a/Build-tools/Do-compile b/Build-tools/Do-compile
index f47ae794b00..e6e71582c74 100755
--- a/Build-tools/Do-compile
+++ b/Build-tools/Do-compile
@@ -171,6 +171,17 @@ info("PATH is $ENV{PATH}");
log_timestamp();
+$md5_result= safe_system("perl $ENV{HOME}/my_md5sum -c ${opt_distribution}.md5");
+
+if ($md5_result != 0)
+{
+ abort("MD5 check failed for $opt_distribution!");
+}
+else
+{
+ info("SUCCESS: MD5 checks for $opt_distribution");
+}
+
if (-x "$host/bin/mysqladmin")
{
log_system("$host/bin/mysqladmin $mysqladmin_args -S $mysql_unix_port -s shutdown");
@@ -204,17 +215,6 @@ if ($opt_stage == 0)
safe_cd($host);
if ($opt_stage == 0 && ! $opt_use_old_distribution)
{
- $md5_result= safe_system("./my_md5sum -c ${opt_distribution}.md5");
-
- if ($md5_result != 0)
- {
- abort("MD5 failed for $opt_distribution!");
- }
- else
- {
- info("SUCCESS: MD5 checks for $opt_distribution");
- }
-
safe_system("gunzip < $opt_distribution | $tar xf -");
# Fix file times; This is needed because the time for files may be
@@ -343,7 +343,9 @@ $tar_file=<$pwd/$host/mysql*.t*gz>;
abort ("Could not find tarball!") unless ($tar_file);
# Generate the MD5 for the binary distribution
-safe_system("./my_md5sum $tar_file > ${tar_file}.md5}");
+$tar_file=~ /(mysql[^\/]*)\.(tar\.gz|tgz)/;
+$tar_file_lite= "$1.$2";
+system("cd $pwd/$host; perl $ENV{HOME}/my_md5sum $tar_file_lite > ${tar_file_lite}.md5");
#
# Unpack the binary distribution
diff --git a/innobase/btr/btr0cur.c b/innobase/btr/btr0cur.c
index 2e9194ff30f..be201da4510 100644
--- a/innobase/btr/btr0cur.c
+++ b/innobase/btr/btr0cur.c
@@ -2717,8 +2717,11 @@ btr_estimate_number_of_different_key_vals(
rec = page_rec_get_next(rec);
}
+
if (n_cols == dict_index_get_n_unique_in_tree(index)) {
- /* We add one because we know that the first record
+
+ /* If there is more than one leaf page in the tree,
+ we add one because we know that the first record
on the page certainly had a different prefix than the
last record on the previous index page in the
alphabetical order. Before this fix, if there was
@@ -2726,7 +2729,11 @@ btr_estimate_number_of_different_key_vals(
algorithm grossly underestimated the number of rows
in the table. */
- n_diff[n_cols]++;
+ if (btr_page_get_prev(page, &mtr) != FIL_NULL
+ || btr_page_get_next(page, &mtr) != FIL_NULL) {
+
+ n_diff[n_cols]++;
+ }
}
total_external_size +=
diff --git a/innobase/include/lock0lock.h b/innobase/include/lock0lock.h
index 9c5f35c6674..9f525042dcc 100644
--- a/innobase/include/lock0lock.h
+++ b/innobase/include/lock0lock.h
@@ -418,7 +418,8 @@ lock_release_off_kernel(
/*====================*/
trx_t* trx); /* in: transaction */
/*************************************************************************
-Releases table locks, and releases possible other transactions waiting
+Releases table locks explicitly requested with LOCK TABLES (indicated by
+lock type LOCK_TABLE_EXP), and releases possible other transactions waiting
because of these locks. */
void
@@ -548,7 +549,7 @@ extern lock_sys_t* lock_sys;
/* Lock types */
#define LOCK_TABLE 16 /* these type values should be so high that */
#define LOCK_REC 32 /* they can be ORed to the lock mode */
-#define LOCK_TABLE_EXP 80 /* explicit table lock */
+#define LOCK_TABLE_EXP 80 /* explicit table lock (80 = 16 + 64) */
#define LOCK_TYPE_MASK 0xF0UL /* mask used to extract lock type from the
type_mode field in a lock */
/* Waiting lock flag */
diff --git a/innobase/include/row0mysql.h b/innobase/include/row0mysql.h
index 390e8c4da57..8f6264944ce 100644
--- a/innobase/include/row0mysql.h
+++ b/innobase/include/row0mysql.h
@@ -161,11 +161,12 @@ row_lock_table_autoinc_for_mysql(
row_prebuilt_t* prebuilt); /* in: prebuilt struct in the MySQL
table handle */
/*************************************************************************
-Unlocks a table lock possibly reserved by trx. */
+Unlocks all table locks explicitly requested by trx (with LOCK TABLES,
+lock type LOCK_TABLE_EXP). */
void
-row_unlock_table_for_mysql(
-/*=======================*/
+row_unlock_tables_for_mysql(
+/*========================*/
trx_t* trx); /* in: transaction */
/*************************************************************************
Sets a table lock on the table mentioned in prebuilt. */
diff --git a/innobase/include/srv0srv.h b/innobase/include/srv0srv.h
index c527d40bc79..c7ba39aaaf1 100644
--- a/innobase/include/srv0srv.h
+++ b/innobase/include/srv0srv.h
@@ -157,6 +157,7 @@ extern ulint srv_test_n_mutexes;
extern ulint srv_test_array_size;
extern ulint srv_activity_count;
+extern ulint srv_fatal_semaphore_wait_threshold;
extern mutex_t* kernel_mutex_temp;/* mutex protecting the server, trx structs,
query threads, and lock table: we allocate
diff --git a/innobase/include/sync0arr.h b/innobase/include/sync0arr.h
index e7d511f8137..92691d5fdd9 100644
--- a/innobase/include/sync0arr.h
+++ b/innobase/include/sync0arr.h
@@ -95,7 +95,7 @@ void
sync_arr_wake_threads_if_sema_free(void);
/*====================================*/
/**************************************************************************
-Prints warnings of long semaphore waits to stderr. Currently > 120 sec. */
+Prints warnings of long semaphore waits to stderr. */
void
sync_array_print_long_waits(void);
diff --git a/innobase/include/trx0trx.h b/innobase/include/trx0trx.h
index a8c1df534da..7eb91048684 100644
--- a/innobase/include/trx0trx.h
+++ b/innobase/include/trx0trx.h
@@ -423,8 +423,9 @@ struct trx_struct{
lock_t* auto_inc_lock; /* possible auto-inc lock reserved by
the transaction; note that it is also
in the lock list trx_locks */
- ulint n_tables_locked;/* number of table locks reserved by
- the transaction, stored in trx_locks */
+ ulint n_lock_table_exp;/* number of explicit table locks
+ (LOCK TABLES) reserved by the
+ transaction, stored in trx_locks */
UT_LIST_NODE_T(trx_t)
trx_list; /* list of transactions */
UT_LIST_NODE_T(trx_t)
diff --git a/innobase/lock/lock0lock.c b/innobase/lock/lock0lock.c
index be0806590a9..92e8f224dea 100644
--- a/innobase/lock/lock0lock.c
+++ b/innobase/lock/lock0lock.c
@@ -2023,9 +2023,8 @@ lock_grant(
lock->trx->auto_inc_lock = lock;
} else if (lock_get_type(lock) == LOCK_TABLE_EXP) {
- ut_ad(lock_get_mode(lock) == LOCK_S
+ ut_a(lock_get_mode(lock) == LOCK_S
|| lock_get_mode(lock) == LOCK_X);
- lock->trx->n_tables_locked++;
}
if (lock_print_waits) {
@@ -3203,6 +3202,10 @@ lock_table_create(
lock->type_mode = type_mode | LOCK_TABLE;
lock->trx = trx;
+ if (lock_get_type(lock) == LOCK_TABLE_EXP) {
+ lock->trx->n_lock_table_exp++;
+ }
+
lock->un_member.tab_lock.table = table;
UT_LIST_ADD_LAST(un_member.tab_lock.locks, table->locks, lock);
@@ -3238,7 +3241,11 @@ lock_table_remove_low(
if (lock == trx->auto_inc_lock) {
trx->auto_inc_lock = NULL;
}
-
+
+ if (lock_get_type(lock) == LOCK_TABLE_EXP) {
+ lock->trx->n_lock_table_exp--;
+ }
+
UT_LIST_REMOVE(trx_locks, trx->trx_locks, lock);
UT_LIST_REMOVE(un_member.tab_lock.locks, table->locks, lock);
}
@@ -3386,7 +3393,7 @@ lock_table(
return(DB_SUCCESS);
}
- ut_ad(flags == 0 || flags == LOCK_TABLE_EXP);
+ ut_a(flags == 0 || flags == LOCK_TABLE_EXP);
trx = thr_get_trx(thr);
@@ -3418,10 +3425,7 @@ lock_table(
lock_table_create(table, mode | flags, trx);
- if (flags) {
- ut_ad(mode == LOCK_S || mode == LOCK_X);
- trx->n_tables_locked++;
- }
+ ut_a(!flags || mode == LOCK_S || mode == LOCK_X);
lock_mutex_exit_kernel();
@@ -3502,13 +3506,13 @@ lock_table_dequeue(
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
#endif /* UNIV_SYNC_DEBUG */
- ut_ad(lock_get_type(in_lock) == LOCK_TABLE ||
+ ut_a(lock_get_type(in_lock) == LOCK_TABLE ||
lock_get_type(in_lock) == LOCK_TABLE_EXP);
lock = UT_LIST_GET_NEXT(un_member.tab_lock.locks, in_lock);
lock_table_remove_low(in_lock);
-
+
/* Check if waiting locks in the queue can now be granted: grant
locks if there are no conflicting locks ahead. */
@@ -3608,9 +3612,8 @@ lock_release_off_kernel(
lock_table_dequeue(lock);
if (lock_get_type(lock) == LOCK_TABLE_EXP) {
- ut_ad(lock_get_mode(lock) == LOCK_S
+ ut_a(lock_get_mode(lock) == LOCK_S
|| lock_get_mode(lock) == LOCK_X);
- trx->n_tables_locked--;
}
}
@@ -3631,11 +3634,12 @@ lock_release_off_kernel(
mem_heap_empty(trx->lock_heap);
ut_a(trx->auto_inc_lock == NULL);
- ut_a(trx->n_tables_locked == 0);
+ ut_a(trx->n_lock_table_exp == 0);
}
/*************************************************************************
-Releases table locks, and releases possible other transactions waiting
+Releases table locks explicitly requested with LOCK TABLES (indicated by
+lock type LOCK_TABLE_EXP), and releases possible other transactions waiting
because of these locks. */
void
@@ -3660,7 +3664,7 @@ lock_release_tables_off_kernel(
count++;
if (lock_get_type(lock) == LOCK_TABLE_EXP) {
- ut_ad(lock_get_mode(lock) == LOCK_S
+ ut_a(lock_get_mode(lock) == LOCK_S
|| lock_get_mode(lock) == LOCK_X);
if (trx->insert_undo || trx->update_undo) {
@@ -3676,7 +3680,7 @@ lock_release_tables_off_kernel(
}
lock_table_dequeue(lock);
- trx->n_tables_locked--;
+
lock = UT_LIST_GET_LAST(trx->trx_locks);
continue;
}
@@ -3695,9 +3699,7 @@ lock_release_tables_off_kernel(
lock = UT_LIST_GET_PREV(trx_locks, lock);
}
- mem_heap_empty(trx->lock_heap);
-
- ut_a(trx->n_tables_locked == 0);
+ ut_a(trx->n_lock_table_exp == 0);
}
/*************************************************************************
diff --git a/innobase/row/row0ins.c b/innobase/row/row0ins.c
index 7f1852c70f2..0da749212d2 100644
--- a/innobase/row/row0ins.c
+++ b/innobase/row/row0ins.c
@@ -370,6 +370,32 @@ row_ins_cascade_ancestor_updates_table(
return(FALSE);
}
+/*************************************************************************
+Returns the number of ancestor UPDATE or DELETE nodes of a
+cascaded update/delete node. */
+static
+ulint
+row_ins_cascade_n_ancestors(
+/*========================*/
+ /* out: number of ancestors */
+ que_node_t* node) /* in: node in a query graph */
+{
+ que_node_t* parent;
+ ulint n_ancestors = 0;
+
+ parent = que_node_get_parent(node);
+
+ while (que_node_get_type(parent) == QUE_NODE_UPDATE) {
+ n_ancestors++;
+
+ parent = que_node_get_parent(parent);
+
+ ut_a(parent);
+ }
+
+ return(n_ancestors);
+}
+
/**********************************************************************
Calculates the update vector node->cascade->update for a child table in
a cascaded update. */
@@ -616,6 +642,34 @@ row_ins_foreign_report_add_err(
}
/*************************************************************************
+Invalidate the query cache for the given table. */
+static
+void
+row_ins_invalidate_query_cache(
+/*===========================*/
+ que_thr_t* thr, /* in: query thread whose run_node
+ is an update node */
+ const char* name) /* in: table name prefixed with
+ database name and a '/' character */
+{
+ char* buf;
+ char* ptr;
+ ulint len = strlen(name) + 1;
+
+ buf = mem_strdupl(name, len);
+
+ ptr = strchr(buf, '/');
+ ut_a(ptr);
+ *ptr = '\0';
+
+ /* We call a function in ha_innodb.cc */
+#ifndef UNIV_HOTBACKUP
+ innobase_invalidate_query_cache(thr_get_trx(thr), buf, len);
+#endif
+ mem_free(buf);
+}
+
+/*************************************************************************
Perform referential actions or checks when a parent row is deleted or updated
and the constraint had an ON DELETE or ON UPDATE condition which was not
RESTRICT. */
@@ -650,26 +704,15 @@ row_ins_foreign_check_on_constraint(
ulint n_to_update;
ulint err;
ulint i;
- char* ptr;
- char* table_name_buf;
+
+
ut_a(thr && foreign && pcur && mtr);
/* Since we are going to delete or update a row, we have to invalidate
the MySQL query cache for table */
- table_name_buf = mem_strdup(table->name);
-
- ptr = strchr(table_name_buf, '/');
- ut_a(ptr);
- *ptr = '\0';
-
-#ifndef UNIV_HOTBACKUP
- /* We call a function in ha_innodb.cc */
- innobase_invalidate_query_cache(thr_get_trx(thr), table_name_buf,
- strlen(table->name) + 1);
-#endif
- mem_free(table_name_buf);
+ row_ins_invalidate_query_cache(thr, table->name);
node = thr->run_node;
@@ -757,6 +800,16 @@ row_ins_foreign_check_on_constraint(
goto nonstandard_exit_func;
}
+ if (row_ins_cascade_n_ancestors(cascade) >= 15) {
+ err = DB_ROW_IS_REFERENCED;
+
+ row_ins_foreign_report_err(
+(char*)"Trying a too deep cascaded delete or update\n",
+ thr, foreign, btr_pcur_get_rec(pcur), entry);
+
+ goto nonstandard_exit_func;
+ }
+
index = btr_pcur_get_btr_cur(pcur)->index;
ut_a(index == foreign->foreign_index);
diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c
index c4408de2a85..556c80c948d 100644
--- a/innobase/row/row0mysql.c
+++ b/innobase/row/row0mysql.c
@@ -741,14 +741,15 @@ run_again:
}
/*************************************************************************
-Unlocks a table lock possibly reserved by trx. */
+Unlocks all table locks explicitly requested by trx (with LOCK TABLES,
+lock type LOCK_TABLE_EXP). */
void
-row_unlock_table_for_mysql(
-/*=======================*/
+row_unlock_tables_for_mysql(
+/*========================*/
trx_t* trx) /* in: transaction */
{
- if (!trx->n_tables_locked) {
+ if (!trx->n_lock_table_exp) {
return;
}
@@ -3175,7 +3176,12 @@ row_check_table_for_mysql(
REPEATABLE READ here */
prebuilt->trx->isolation_level = TRX_ISO_REPEATABLE_READ;
-
+
+ /* Enlarge the fatal lock wait timeout during CHECK TABLE. */
+ mutex_enter(&kernel_mutex);
+ srv_fatal_semaphore_wait_threshold += 7200; /* 2 hours */
+ mutex_exit(&kernel_mutex);
+
index = dict_table_get_first_index(table);
while (index != NULL) {
@@ -3223,6 +3229,11 @@ row_check_table_for_mysql(
ret = DB_ERROR;
}
+ /* Restore the fatal lock wait timeout after CHECK TABLE. */
+ mutex_enter(&kernel_mutex);
+ srv_fatal_semaphore_wait_threshold -= 7200; /* 2 hours */
+ mutex_exit(&kernel_mutex);
+
prebuilt->trx->op_info = "";
return(ret);
diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c
index fc46c95a8a6..4bc5b0dc795 100644
--- a/innobase/srv/srv0srv.c
+++ b/innobase/srv/srv0srv.c
@@ -55,6 +55,9 @@ ibool srv_lower_case_table_names = FALSE;
in the server */
ulint srv_activity_count = 0;
+/* The following is the maximum allowed duration of a lock wait. */
+ulint srv_fatal_semaphore_wait_threshold = 600;
+
ibool srv_lock_timeout_and_monitor_active = FALSE;
ibool srv_error_monitor_active = FALSE;
diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c
index dd38eddb20b..74dd23e4252 100644
--- a/innobase/srv/srv0start.c
+++ b/innobase/srv/srv0start.c
@@ -1115,7 +1115,7 @@ NetWare. */
srv_monitor_file_name = mem_alloc(
strlen(fil_path_to_mysql_datadir) +
20 + sizeof "/innodb_status.");
- sprintf(srv_monitor_file_name, "%s/innodb.status.%lu",
+ sprintf(srv_monitor_file_name, "%s/innodb_status.%lu",
fil_path_to_mysql_datadir, os_proc_get_number());
srv_monitor_file = fopen(srv_monitor_file_name, "w+");
if (!srv_monitor_file) {
diff --git a/innobase/sync/sync0arr.c b/innobase/sync/sync0arr.c
index d1644412fbb..7cd221df6a5 100644
--- a/innobase/sync/sync0arr.c
+++ b/innobase/sync/sync0arr.c
@@ -895,7 +895,7 @@ sync_arr_wake_threads_if_sema_free(void)
}
/**************************************************************************
-Prints warnings of long semaphore waits to stderr. Currently > 120 sec. */
+Prints warnings of long semaphore waits to stderr. */
void
sync_array_print_long_waits(void)
@@ -905,6 +905,7 @@ sync_array_print_long_waits(void)
ibool old_val;
ibool noticed = FALSE;
ulint i;
+ ulint fatal_timeout = srv_fatal_semaphore_wait_threshold;
for (i = 0; i < sync_primary_wait_array->n_cells; i++) {
@@ -919,12 +920,13 @@ sync_array_print_long_waits(void)
}
if (cell->wait_object != NULL
- && difftime(time(NULL), cell->reservation_time) > 600) {
+ && difftime(time(NULL), cell->reservation_time)
+ > fatal_timeout) {
- fputs(
-"InnoDB: Error: semaphore wait has lasted > 600 seconds\n"
+ fprintf(stderr,
+"InnoDB: Error: semaphore wait has lasted > %lu seconds\n"
"InnoDB: We intentionally crash the server, because it appears to be hung.\n",
- stderr);
+ fatal_timeout);
ut_error;
}
diff --git a/innobase/trx/trx0trx.c b/innobase/trx/trx0trx.c
index a9aae48dae6..f7497ac4090 100644
--- a/innobase/trx/trx0trx.c
+++ b/innobase/trx/trx0trx.c
@@ -151,7 +151,7 @@ trx_create(
trx->n_tickets_to_enter_innodb = 0;
trx->auto_inc_lock = NULL;
- trx->n_tables_locked = 0;
+ trx->n_lock_table_exp = 0;
trx->read_view_heap = mem_heap_create(256);
trx->read_view = NULL;
@@ -279,7 +279,7 @@ trx_free(
ut_a(!trx->has_search_latch);
ut_a(!trx->auto_inc_lock);
- ut_a(!trx->n_tables_locked);
+ ut_a(!trx->n_lock_table_exp);
ut_a(trx->dict_operation_lock_mode == 0);
diff --git a/mysql-test/r/create_select_tmp.result b/mysql-test/r/create_select_tmp.result
new file mode 100644
index 00000000000..610ee70b3e3
--- /dev/null
+++ b/mysql-test/r/create_select_tmp.result
@@ -0,0 +1,19 @@
+drop table if exists t1, t2;
+CREATE TABLE t1 ( a int );
+INSERT INTO t1 VALUES (1),(2),(1);
+CREATE TABLE t2 ( PRIMARY KEY (a) ) TYPE=INNODB SELECT a FROM t1;
+Duplicate entry '1' for key 1
+select * from t2;
+Table 'test.t2' doesn't exist
+CREATE TEMPORARY TABLE t2 ( PRIMARY KEY (a) ) TYPE=INNODB SELECT a FROM t1;
+Duplicate entry '1' for key 1
+select * from t2;
+Table 'test.t2' doesn't exist
+CREATE TABLE t2 ( PRIMARY KEY (a) ) TYPE=MYISAM SELECT a FROM t1;
+Duplicate entry '1' for key 1
+select * from t2;
+Table 'test.t2' doesn't exist
+CREATE TEMPORARY TABLE t2 ( PRIMARY KEY (a) ) TYPE=MYISAM SELECT a FROM t1;
+Duplicate entry '1' for key 1
+select * from t2;
+Table 'test.t2' doesn't exist
diff --git a/mysql-test/r/rpl_drop.result b/mysql-test/r/rpl_drop.result
new file mode 100644
index 00000000000..ce1f5b6ee81
--- /dev/null
+++ b/mysql-test/r/rpl_drop.result
@@ -0,0 +1,10 @@
+slave stop;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+slave start;
+drop table if exists t1, t2;
+create table t1 (a int);
+drop table t1, t2;
+Unknown table 't2'
diff --git a/mysql-test/t/create_select_tmp.test b/mysql-test/t/create_select_tmp.test
new file mode 100644
index 00000000000..36292abd899
--- /dev/null
+++ b/mysql-test/t/create_select_tmp.test
@@ -0,0 +1,27 @@
+# Testcase for BUG#4551
+# The bug was that when the table was TEMPORARY, it was not deleted if
+# the CREATE SELECT failed (the code intended too, but it actually
+# didn't). And as the CREATE TEMPORARY TABLE was not written to the
+# binlog if it was a transactional table, it resulted in an
+# inconsistency between binlog and the internal list of temp tables.
+
+-- source include/have_innodb.inc
+drop table if exists t1, t2;
+CREATE TABLE t1 ( a int );
+INSERT INTO t1 VALUES (1),(2),(1);
+--error 1062;
+CREATE TABLE t2 ( PRIMARY KEY (a) ) TYPE=INNODB SELECT a FROM t1;
+--error 1146;
+select * from t2;
+--error 1062;
+CREATE TEMPORARY TABLE t2 ( PRIMARY KEY (a) ) TYPE=INNODB SELECT a FROM t1;
+--error 1146;
+select * from t2;
+--error 1062;
+CREATE TABLE t2 ( PRIMARY KEY (a) ) TYPE=MYISAM SELECT a FROM t1;
+--error 1146;
+select * from t2;
+--error 1062;
+CREATE TEMPORARY TABLE t2 ( PRIMARY KEY (a) ) TYPE=MYISAM SELECT a FROM t1;
+--error 1146;
+select * from t2;
diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test
index e0cc96ccb32..50ab3bdb8bd 100644
--- a/mysql-test/t/innodb.test
+++ b/mysql-test/t/innodb.test
@@ -960,6 +960,23 @@ update t3 set t3.id=7 where t1.id =1 and t2.id = t1.id and t3.id = t2.id;
drop table t3,t2,t1;
#
+# test for recursion depth limit
+#
+create table t1(
+ id int primary key,
+ pid int,
+ index(pid),
+ foreign key(pid) references t1(id) on delete cascade) engine=innodb;
+insert into t1 values(0,0),(1,0),(2,1),(3,2),(4,3),(5,4),(6,5),(7,6),
+ (8,7),(9,8),(10,9),(11,10),(12,11),(13,12),(14,13),(15,14);
+-- error 1217
+delete from t1 where id=0;
+delete from t1 where id=15;
+delete from t1 where id=0;
+
+drop table t1;
+
+#
# Test timestamps
#
diff --git a/mysql-test/t/rpl_drop.test b/mysql-test/t/rpl_drop.test
new file mode 100644
index 00000000000..6fc2500fc97
--- /dev/null
+++ b/mysql-test/t/rpl_drop.test
@@ -0,0 +1,10 @@
+# Testcase for BUG#4552 (DROP on two tables, one of which does not
+# exist, must be binlogged with a non-zero error code)
+source include/master-slave.inc;
+drop table if exists t1, t2;
+create table t1 (a int);
+--error 1051;
+drop table t1, t2;
+save_master_pos;
+connection slave;
+sync_with_master;
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index 6eae315e443..21a2e338812 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -4783,8 +4783,8 @@ ha_innobase::external_lock(
trx->n_mysql_tables_in_use--;
prebuilt->mysql_has_locked = FALSE;
auto_inc_counter_for_this_stat = 0;
- if (trx->n_tables_locked) {
- row_unlock_table_for_mysql(trx);
+ if (trx->n_lock_table_exp) {
+ row_unlock_tables_for_mysql(trx);
}
/* If the MySQL lock count drops to zero we know that the current SQL
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index b769178565b..406bff6d273 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -1696,9 +1696,13 @@ void select_create::abort()
table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
enum db_type table_type=table->db_type;
if (!table->tmp_table)
+ {
hash_delete(&open_cache,(byte*) table);
- if (!create_info->table_existed)
- quick_rm_table(table_type,db,name);
+ if (!create_info->table_existed)
+ quick_rm_table(table_type, db, name);
+ }
+ else if (!create_info->table_existed)
+ close_temporary_table(thd, db, name);
table=0;
}
VOID(pthread_mutex_unlock(&LOCK_open));
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index 167fb2daf8b..8442d03c1d9 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -310,6 +310,11 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
{
if (transactional_table)
ha_autocommit_or_rollback(thd,error);
+
+ if (read_file_from_client)
+ while (!read_info.next_line())
+ ;
+
#ifndef EMBEDDED_LIBRARY
if (mysql_bin_log.is_open())
{