List:Commits« Previous MessageNext Message »
From:Alex Ivanov Notebook Date:January 31 2006 6:41pm
Subject:bk commit into 5.0 tree (aivanov:1.2020) BUG#16582
View as plain text  
Below is the list of changes that have just been committed into a local
5.0 repository of alexi. When alexi does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet
  1.2020 06/01/31 21:41:48 aivanov@stripped +11 -0
  Fixed: BUG#15653, BUG#16157, BUG#16229, BUG#16298, BUG#16387, BUG#16582.
    Applied innodb-5.0-ss149/162 snapshots.

  sql/ha_innodb.h
    1.110 06/01/31 21:41:43 aivanov@stripped +1 -12
    Applied innodb-5.0-149/162 snapshots.
      Remove some declarations of unused global variables and member
      variables of class ha_innobase.

  sql/ha_innodb.cc
    1.286 06/01/31 21:41:42 aivanov@stripped +36 -23
    Applied innodb-5.0-149/162 snapshots.
      Remove some declarations of unused global variables and member
        variables of class ha_innobase.
      Added diagnostic code trx_print() to
        innobase_query_caching_of_table_permitted() to find reason
        why we are holding adaptive search latch.
      Fixed bug #16229 MySQL/InnoDB uses full explicit table locks
        in trigger processing. Take a InnoDB table lock only if user
        has explicitly requested a table lock. Added some additional
        comments to store_lock() and external_lock(). Fixed some
        code style errors.
      Remember to use noninlined versions of the functions on
        ha_innodb.cc !

  mysql-test/t/innodb.test
    1.125 06/01/31 21:41:42 aivanov@stripped +102 -0
    Applied innodb-5.0-149/162 snapshots.
      Added test cases.

  mysql-test/r/innodb.result
    1.155 06/01/31 21:41:42 aivanov@stripped +71 -0
    Applied innodb-5.0-149/162 snapshots.
      Fixed results for added test cases.

  innobase/srv/srv0start.c
    1.88 06/01/31 21:41:42 aivanov@stripped +14 -0
    Applied innodb-5.0-149/162 snapshots.
      Fix bug #16157, a crash when innodb_log_group_home_dir is set
      to an empty string. This patch is from Heikki.

  innobase/os/os0sync.c
    1.27 06/01/31 21:41:42 aivanov@stripped +15 -15
    Applied innodb-5.0-149/162 snapshots.
      Replace goto in os_event_wait with a normal loop.

  innobase/include/univ.i
    1.45 06/01/31 21:41:42 aivanov@stripped +0 -6
    Applied innodb-5.0-149/162 snapshots.
      Avoid breaking --with-debug builds on QNS and other systems
      whose compiler pretends to be GCC 2.
      Outside __WIN__ define UNIV_INLINE as static inline.

  innobase/fil/fil0fil.c
    1.63 06/01/31 21:41:42 aivanov@stripped +81 -2
    Applied innodb-5.0-149/162 snapshots.
      Keep track on unflushed modifications to file spaces. When there
      are tens of thousands of file spaces, flushing all files in
      fil_flush_file_spaces() would be very slow (Bug #15653).
      fil_flush_file_spaces(): Only flush unflushed file spaces.
      fil_space_t, fil_system_t: Add a list of unflushed spaces.

  innobase/dict/dict0load.c
    1.41 06/01/31 21:41:42 aivanov@stripped +15 -5
    Applied innodb-5.0-149/162 snapshots.
      dict_load_columns(): Set the charset-collation code
      DATA_MYSQL_BINARY_CHARSET_COLL for those binary string columns
      that lack a charset-collation code, i.e., the tables were created
      with an older version of MySQL/InnoDB than 4.1.2 (Bug #16298).

  innobase/dict/dict0dict.c
    1.72 06/01/31 21:41:42 aivanov@stripped +2 -1
    Applied innodb-5.0-149/162 snapshots.
      Do not mistake TABLENAME_ibfk_0 for auto generated id (Bug #16387).
      dict_table_get_highest_foreign_id(): Ignore foreign constraint
        identifiers starting with the pattern TABLENAME_ibfk_0.

  innobase/btr/btr0sea.c
    1.38 06/01/31 21:41:42 aivanov@stripped +39 -5
    Applied innodb-5.0-149/162 snapshots.
      Account for a race condition when dropping the adaptive hash
      index for a B-tree page (Bug #16582).
      btr_search_drop_page_hash_index(): Retry the operation if a
        hash index with different parameters was built meanwhile.
        Add diagnostics for the case that hash node pointers to
        the page remain. This fix is from Heikki.
      btr_search_info-update_hash(), btr_search_info_update_slow():
        Document the parameter "info" as in/out.

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	aivanov
# Host:	mysqld.creware.com
# Root:	/home/alexi/innodb/mysql-5.0-ss162

--- 1.37/innobase/btr/btr0sea.c	2006-01-30 22:52:11 +03:00
+++ 1.38/innobase/btr/btr0sea.c	2006-01-31 21:41:42 +03:00
@@ -191,7 +191,7 @@
 void
 btr_search_info_update_hash(
 /*========================*/
-	btr_search_t*	info,	/* in: search info */
+	btr_search_t*	info,	/* in/out: search info */
 	btr_cur_t*	cursor)	/* in: cursor which was just positioned */
 {
 	dict_index_t*	index;
@@ -452,7 +452,7 @@
 void
 btr_search_info_update_slow(
 /*========================*/
-	btr_search_t*	info,	/* in: search info */
+	btr_search_t*	info,	/* in/out: search info */
 	btr_cur_t*	cursor)	/* in: cursor which was just positioned */
 {
 	buf_block_t*	block;
@@ -912,12 +912,12 @@
 	ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
 	ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
 #endif /* UNIV_SYNC_DEBUG */
-
+retry:
 	rw_lock_s_lock(&btr_search_latch);
 
 	block = buf_block_align(page);
 
-	if (!block->is_hashed) {
+	if (UNIV_LIKELY(!block->is_hashed)) {
 
 		rw_lock_s_unlock(&btr_search_latch);
 
@@ -958,6 +958,8 @@
 
 	tree_id = btr_page_get_index_id(page);
 	
+	ut_a(0 == ut_dulint_cmp(tree_id, index->id));
+
 	prev_fold = 0;
 
 	heap = NULL;
@@ -992,6 +994,26 @@
 
 	rw_lock_x_lock(&btr_search_latch);
 
+	if (UNIV_UNLIKELY(!block->is_hashed)) {
+		/* Someone else has meanwhile dropped the hash index */
+
+		goto cleanup;
+	}
+
+	ut_a(block->index == index);
+
+	if (UNIV_UNLIKELY(block->curr_n_fields != n_fields)
+	    || UNIV_UNLIKELY(block->curr_n_bytes != n_bytes)) {
+
+		/* Someone else has meanwhile built a new hash index on the
+		page, with different parameters */
+
+		rw_lock_x_unlock(&btr_search_latch);
+
+		mem_free(folds);
+		goto retry;
+	}
+
 	for (i = 0; i < n_cached; i++) {
 
 		ha_remove_all_nodes_to_page(table, folds[i], page);
@@ -999,8 +1021,20 @@
 
 	block->is_hashed = FALSE;
 	block->index = NULL;
+cleanup:
+	if (UNIV_UNLIKELY(block->n_pointers)) {
+		/* Corruption */
+		ut_print_timestamp(stderr);
+		fprintf(stderr,
+"  InnoDB: Corruption of adaptive hash index. After dropping\n"
+"InnoDB: the hash index to a page of %s, still %lu hash nodes remain.\n",
+			index->name, (ulong) block->n_pointers);
+		rw_lock_x_unlock(&btr_search_latch);
 
-	rw_lock_x_unlock(&btr_search_latch);
+		btr_search_validate();
+	} else {
+		rw_lock_x_unlock(&btr_search_latch);
+	}
 
 	mem_free(folds);
 }

--- 1.71/innobase/dict/dict0dict.c	2006-01-30 15:50:49 +03:00
+++ 1.72/innobase/dict/dict0dict.c	2006-01-31 21:41:42 +03:00
@@ -2803,7 +2803,8 @@
 		if (ut_strlen(foreign->id) > ((sizeof dict_ibfk) - 1) + len
 		    && 0 == ut_memcmp(foreign->id, table->name, len)
 		    && 0 == ut_memcmp(foreign->id + len,
-				dict_ibfk, (sizeof dict_ibfk) - 1)) {
+				dict_ibfk, (sizeof dict_ibfk) - 1)
+		    && foreign->id[len + ((sizeof dict_ibfk) - 1)] != '0') {
 			/* It is of the >= 4.0.18 format */
 
 			id = strtoul(foreign->id + len + ((sizeof dict_ibfk) - 1),

--- 1.40/innobase/dict/dict0load.c	2005-12-13 16:29:23 +03:00
+++ 1.41/innobase/dict/dict0load.c	2006-01-31 21:41:42 +03:00
@@ -385,13 +385,23 @@
 		field = rec_get_nth_field_old(rec, 6, &len);
 		prtype = mach_read_from_4(field);
 
-		if (dtype_is_non_binary_string_type(mtype, prtype)
-		    && dtype_get_charset_coll(prtype) == 0) {
-			/* This is a non-binary string type, and the table
-			was created with < 4.1.2. Use the default charset. */
+		if (dtype_get_charset_coll(prtype) == 0
+				&& dtype_is_string_type(mtype)) {
+			/* The table was created with < 4.1.2. */
 
-			prtype = dtype_form_prtype(prtype,
+			if (dtype_is_binary_string_type(mtype, prtype)) {
+				/* Use the binary collation for
+				string columns of binary type. */
+
+				prtype = dtype_form_prtype(prtype,
+					DATA_MYSQL_BINARY_CHARSET_COLL);
+			} else {
+				/* Use the default charset for
+				other than binary columns. */
+
+				prtype = dtype_form_prtype(prtype,
 					data_mysql_default_charset_coll);
+			}
 		}
 
 		field = rec_get_nth_field_old(rec, 7, &len);

--- 1.62/innobase/fil/fil0fil.c	2006-01-30 22:52:11 +03:00
+++ 1.63/innobase/fil/fil0fil.c	2006-01-31 21:41:42 +03:00
@@ -181,6 +181,11 @@
 	hash_node_t	name_hash;/* hash chain the name_hash table */
 	rw_lock_t	latch;	/* latch protecting the file space storage
 				allocation */
+	UT_LIST_NODE_T(fil_space_t) unflushed_spaces;
+				/* list of spaces with at least one unflushed
+				file we have written to */
+	ibool		is_in_unflushed_spaces; /* TRUE if this space is
+				currently in the list above */
 	UT_LIST_NODE_T(fil_space_t) space_list;
 				/* list of all spaces */
 	ibuf_data_t*	ibuf_data;
@@ -213,6 +218,12 @@
 					not put to this list: they are opened
 					after the startup, and kept open until
 					shutdown */
+	UT_LIST_BASE_NODE_T(fil_space_t) unflushed_spaces;
+					/* base node for the list of those
+					tablespaces whose files contain
+					unflushed writes; those spaces have
+					at least one file node where
+					modification_counter > flush_counter */
 	ulint		n_open;		/* number of files currently open */
 	ulint		max_n_open;	/* n_open is not allowed to exceed
 					this */
@@ -389,6 +400,36 @@
 	return(space->ibuf_data);
 }
 
+/**************************************************************************
+Checks if all the file nodes in a space are flushed. The caller must hold
+the fil_system mutex. */
+static
+ibool
+fil_space_is_flushed(
+/*=================*/
+				/* out: TRUE if all are flushed */
+	fil_space_t*	space)	/* in: space */
+{
+	fil_node_t*	node;
+
+#ifdef UNIV_SYNC_DEBUG
+	ut_ad(mutex_own(&(fil_system->mutex)));
+#endif /* UNIV_SYNC_DEBUG */
+
+	node = UT_LIST_GET_FIRST(space->chain);
+
+	while (node) {
+		if (node->modification_counter > node->flush_counter) {
+
+			return(FALSE);
+		}
+
+		node = UT_LIST_GET_NEXT(chain, node);
+	}
+
+	return(TRUE);
+}
+
 /***********************************************************************
 Appends a new file to the chain of files of a space. File must be closed. */
 
@@ -841,6 +882,16 @@
 
 		node->modification_counter = node->flush_counter;
 
+		if (space->is_in_unflushed_spaces
+		    && fil_space_is_flushed(space)) {
+
+			space->is_in_unflushed_spaces = FALSE;
+
+			UT_LIST_REMOVE(unflushed_spaces,
+					system->unflushed_spaces,
+					space);
+		}
+
 		fil_node_close_file(node, system);
 	}
 
@@ -1004,6 +1055,8 @@
 
 	HASH_INSERT(fil_space_t, name_hash, system->name_hash,
 						ut_fold_string(name), space);
+	space->is_in_unflushed_spaces = FALSE;
+
 	UT_LIST_ADD_LAST(space_list, system->space_list, space);
 				
 	mutex_exit(&(system->mutex));
@@ -1099,6 +1152,13 @@
 	HASH_DELETE(fil_space_t, name_hash, system->name_hash,
 					   ut_fold_string(space->name), space);
 
+	if (space->is_in_unflushed_spaces) {
+		space->is_in_unflushed_spaces = FALSE;
+
+		UT_LIST_REMOVE(unflushed_spaces, system->unflushed_spaces,
+								space);
+	}
+
 	UT_LIST_REMOVE(space_list, system->space_list, space);
 
 	ut_a(space->magic_n == FIL_SPACE_MAGIC_N);
@@ -1250,6 +1310,7 @@
 
 	system->tablespace_version = 0;
 
+	UT_LIST_INIT(system->unflushed_spaces);
 	UT_LIST_INIT(system->space_list);
 
 	return(system);
@@ -3742,6 +3803,14 @@
 	if (type == OS_FILE_WRITE) {
 		system->modification_counter++;
 		node->modification_counter = system->modification_counter;
+
+		if (!node->space->is_in_unflushed_spaces) {
+
+			node->space->is_in_unflushed_spaces = TRUE;
+			UT_LIST_ADD_FIRST(unflushed_spaces,
+					system->unflushed_spaces,
+					node->space);
+		}
 	}
 	
 	if (node->n_pending == 0 && node->space->purpose == FIL_TABLESPACE
@@ -4162,6 +4231,16 @@
 skip_flush:
 			if (node->flush_counter < old_mod_counter) {
 				node->flush_counter = old_mod_counter;
+
+				if (space->is_in_unflushed_spaces
+				    && fil_space_is_flushed(space)) {
+
+					space->is_in_unflushed_spaces = FALSE;
+
+					UT_LIST_REMOVE(unflushed_spaces,
+						system->unflushed_spaces,
+						space);
+				}
 			}
 
 			if (space->purpose == FIL_TABLESPACE) {
@@ -4193,7 +4272,7 @@
 
 	mutex_enter(&(system->mutex));
 
-	space = UT_LIST_GET_FIRST(system->space_list);
+	space = UT_LIST_GET_FIRST(system->unflushed_spaces);
 
 	while (space) {
 		if (space->purpose == purpose && !space->is_being_deleted) {
@@ -4209,7 +4288,7 @@
 
 			space->n_pending_flushes--;
 		}
-		space = UT_LIST_GET_NEXT(space_list, space);
+		space = UT_LIST_GET_NEXT(unflushed_spaces, space);
 	}
 	
 	mutex_exit(&(system->mutex));

--- 1.44/innobase/include/univ.i	2005-09-03 20:15:13 +04:00
+++ 1.45/innobase/include/univ.i	2006-01-31 21:41:42 +03:00
@@ -126,13 +126,7 @@
 #ifdef __WIN__
 #define UNIV_INLINE	__inline
 #else
-/* config.h contains the right def for 'inline' for the current compiler */
-#if (__GNUC__ == 2)
-#define UNIV_INLINE  extern inline
-#else
-/* extern inline doesn't work with gcc 3.0.2 */
 #define UNIV_INLINE static inline
-#endif
 #endif
 
 #else

--- 1.26/innobase/os/os0sync.c	2005-10-06 16:36:53 +04:00
+++ 1.27/innobase/os/os0sync.c	2006-01-31 21:41:42 +03:00
@@ -317,28 +317,28 @@
 	os_fast_mutex_lock(&(event->os_mutex));
 
 	old_signal_count = event->signal_count;
-loop:
-	if (event->is_set == TRUE
-            || event->signal_count != old_signal_count) {
 
-		os_fast_mutex_unlock(&(event->os_mutex));
+	for (;;) {
+		if (event->is_set == TRUE
+			|| event->signal_count != old_signal_count) {
 
-		if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
+			os_fast_mutex_unlock(&(event->os_mutex));
 
-		        os_thread_exit(NULL);
-		}
-		/* Ok, we may return */
+			if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
 
-		return;
-	}
+				os_thread_exit(NULL);
+			}
+			/* Ok, we may return */
 
-	pthread_cond_wait(&(event->cond_var), &(event->os_mutex));
+			return;
+		}
 
-	/* Solaris manual said that spurious wakeups may occur: we have to
-	check if the event really has been signaled after we came here to
-	wait */
+		pthread_cond_wait(&(event->cond_var), &(event->os_mutex));
 
-	goto loop;
+		/* Solaris manual said that spurious wakeups may occur: we
+		have to check if the event really has been signaled after
+		we came here to wait */
+	}
 #endif
 }
 

--- 1.87/innobase/srv/srv0start.c	2005-12-13 21:35:14 +03:00
+++ 1.88/innobase/srv/srv0start.c	2006-01-31 21:41:42 +03:00
@@ -233,6 +233,13 @@
 		}
 	}
 
+	if (i == 0) {
+		/* If innodb_data_file_path was defined it must contain
+		at least one data file definition */
+
+		return(FALSE);
+	}
+	
 	*data_file_names = (char**)ut_malloc(i * sizeof(void*));
 	*data_file_sizes = (ulint*)ut_malloc(i * sizeof(ulint));
 	*data_file_is_raw_partition = (ulint*)ut_malloc(i * sizeof(ulint));
@@ -379,6 +386,13 @@
 		}
 	}
 
+	if (i != 1) {
+		/* If innodb_log_group_home_dir was defined it must
+		contain exactly one path definition under current MySQL */
+		
+		return(FALSE);
+	}
+	
 	*log_group_home_dirs = (char**) ut_malloc(i * sizeof(void*));
 
 	/* Then store the actual values to our array */

--- 1.154/mysql-test/r/innodb.result	2006-01-30 15:50:49 +03:00
+++ 1.155/mysql-test/r/innodb.result	2006-01-31 21:41:42 +03:00
@@ -3180,3 +3180,74 @@
 7	D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B2
 update t1 set b = 'three' where a = 6;
 drop table t1;
+CREATE TABLE t1(a INT, PRIMARY KEY(a)) ENGINE=InnoDB;
+CREATE TABLE t2(a INT) ENGINE=InnoDB;
+ALTER TABLE t2 ADD FOREIGN KEY (a) REFERENCES t1(a);
+ALTER TABLE t2 DROP FOREIGN KEY t2_ibfk_1;
+ALTER TABLE t2 ADD CONSTRAINT t2_ibfk_0 FOREIGN KEY (a) REFERENCES t1(a);
+ALTER TABLE t2 DROP FOREIGN KEY t2_ibfk_0;
+SHOW CREATE TABLE t2;
+Table	Create Table
+t2	CREATE TABLE `t2` (
+  `a` int(11) default NULL,
+  KEY `t2_ibfk_0` (`a`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+DROP TABLE t2,t1;
+create table t1(a int not null, b int, c int, d int, primary key(a)) engine=innodb;
+insert into t1(a) values (1),(2),(3);
+commit;
+set autocommit = 0;
+update t1 set b = 5 where a = 2;
+create trigger t1t before insert on t1 for each row begin set NEW.b = NEW.a * 10 + 5, NEW.c = NEW.a / 10; end |
+set autocommit = 0;
+insert into t1(a) values (10),(20),(30),(40),(50),(60),(70),(80),(90),(100),
+(11),(21),(31),(41),(51),(61),(71),(81),(91),(101),
+(12),(22),(32),(42),(52),(62),(72),(82),(92),(102),
+(13),(23),(33),(43),(53),(63),(73),(83),(93),(103),
+(14),(24),(34),(44),(54),(64),(74),(84),(94),(104);
+commit;
+commit;
+drop trigger t1t;
+drop table t1;
+create table t1(a int not null, b int, c int, d int, primary key(a)) engine=innodb;
+create table t2(a int not null, b int, c int, d int, primary key(a)) engine=innodb;
+create table t3(a int not null, b int, c int, d int, primary key(a)) engine=innodb;
+create table t4(a int not null, b int, c int, d int, primary key(a)) engine=innodb;
+create table t5(a int not null, b int, c int, d int, primary key(a)) engine=innodb;
+insert into t1(a) values (1),(2),(3);
+insert into t2(a) values (1),(2),(3);
+insert into t3(a) values (1),(2),(3);
+insert into t4(a) values (1),(2),(3);
+insert into t3(a) values (5),(7),(8);
+insert into t4(a) values (5),(7),(8);
+insert into t5(a) values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12);
+create trigger t1t before insert on t1 for each row begin 
+INSERT INTO t2 SET a = NEW.a;
+end |
+create trigger t2t before insert on t2 for each row begin
+DELETE FROM t3 WHERE a = NEW.a;
+end |
+create trigger t3t before delete on t3 for each row begin  
+UPDATE t4 SET b = b + 1 WHERE a = OLD.a;
+end |
+create trigger t4t before update on t4 for each row begin
+UPDATE t5 SET b = b + 1 where a = NEW.a;
+end |
+commit;
+set autocommit = 0;
+update t1 set b = b + 5 where a = 1;
+update t2 set b = b + 5 where a = 1;
+update t3 set b = b + 5 where a = 1;
+update t4 set b = b + 5 where a = 1;
+insert into t5(a) values(20);
+set autocommit = 0;
+insert into t1(a) values(7);
+insert into t2(a) values(8);
+delete from t2 where a = 3;
+update t4 set b = b + 1 where a = 3;
+commit;
+drop trigger t1t;
+drop trigger t2t;
+drop trigger t3t;
+drop trigger t4t;
+drop table t1, t2, t3, t4, t5;

--- 1.124/mysql-test/t/innodb.test	2006-01-30 15:50:49 +03:00
+++ 1.125/mysql-test/t/innodb.test	2006-01-31 21:41:42 +03:00
@@ -2047,3 +2047,105 @@
 select a,hex(b) from t1 order by b;
 update t1 set b = 'three' where a = 6;
 drop table t1;
+
+# Ensure that <tablename>_ibfk_0 is not mistreated as a
+# generated foreign key identifier.  (Bug #16387)
+
+CREATE TABLE t1(a INT, PRIMARY KEY(a)) ENGINE=InnoDB;
+CREATE TABLE t2(a INT) ENGINE=InnoDB;
+ALTER TABLE t2 ADD FOREIGN KEY (a) REFERENCES t1(a);
+ALTER TABLE t2 DROP FOREIGN KEY t2_ibfk_1;
+ALTER TABLE t2 ADD CONSTRAINT t2_ibfk_0 FOREIGN KEY (a) REFERENCES t1(a);
+ALTER TABLE t2 DROP FOREIGN KEY t2_ibfk_0;
+SHOW CREATE TABLE t2;
+DROP TABLE t2,t1;
+
+#
+# Test case for bug #16229: MySQL/InnoDB uses full explicit table locks in trigger processing
+#
+
+connect (a,localhost,root,,);
+connect (b,localhost,root,,);
+connection a;
+create table t1(a int not null, b int, c int, d int, primary key(a)) engine=innodb;
+insert into t1(a) values (1),(2),(3);
+commit;
+connection b;
+set autocommit = 0;
+update t1 set b = 5 where a = 2;
+connection a;
+delimiter |;
+create trigger t1t before insert on t1 for each row begin set NEW.b = NEW.a * 10 + 5, NEW.c = NEW.a / 10; end |
+delimiter ;|
+set autocommit = 0;
+connection a;
+insert into t1(a) values (10),(20),(30),(40),(50),(60),(70),(80),(90),(100),
+(11),(21),(31),(41),(51),(61),(71),(81),(91),(101),
+(12),(22),(32),(42),(52),(62),(72),(82),(92),(102),
+(13),(23),(33),(43),(53),(63),(73),(83),(93),(103),
+(14),(24),(34),(44),(54),(64),(74),(84),(94),(104);
+connection b;
+commit;
+connection a;
+commit;
+drop trigger t1t;
+drop table t1;
+disconnect a;
+disconnect b;
+#
+# Another trigger test
+#
+connect (a,localhost,root,,);
+connect (b,localhost,root,,);
+connection a;
+create table t1(a int not null, b int, c int, d int, primary key(a)) engine=innodb;
+create table t2(a int not null, b int, c int, d int, primary key(a)) engine=innodb;
+create table t3(a int not null, b int, c int, d int, primary key(a)) engine=innodb;
+create table t4(a int not null, b int, c int, d int, primary key(a)) engine=innodb;
+create table t5(a int not null, b int, c int, d int, primary key(a)) engine=innodb;
+insert into t1(a) values (1),(2),(3);
+insert into t2(a) values (1),(2),(3);
+insert into t3(a) values (1),(2),(3);
+insert into t4(a) values (1),(2),(3);
+insert into t3(a) values (5),(7),(8);
+insert into t4(a) values (5),(7),(8);
+insert into t5(a) values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12);
+
+delimiter |;
+create trigger t1t before insert on t1 for each row begin 
+    INSERT INTO t2 SET a = NEW.a;
+end |
+
+create trigger t2t before insert on t2 for each row begin
+    DELETE FROM t3 WHERE a = NEW.a;
+end |
+
+create trigger t3t before delete on t3 for each row begin  
+    UPDATE t4 SET b = b + 1 WHERE a = OLD.a;
+end |
+
+create trigger t4t before update on t4 for each row begin
+    UPDATE t5 SET b = b + 1 where a = NEW.a;
+end |
+delimiter ;|
+commit;
+set autocommit = 0;
+update t1 set b = b + 5 where a = 1;
+update t2 set b = b + 5 where a = 1;
+update t3 set b = b + 5 where a = 1;
+update t4 set b = b + 5 where a = 1;
+insert into t5(a) values(20);
+connection b;
+set autocommit = 0;
+insert into t1(a) values(7);
+insert into t2(a) values(8);
+delete from t2 where a = 3;
+update t4 set b = b + 1 where a = 3;
+commit;
+drop trigger t1t;
+drop trigger t2t;
+drop trigger t3t;
+drop trigger t4t;
+drop table t1, t2, t3, t4, t5;
+disconnect a;
+disconnect b;

--- 1.285/sql/ha_innodb.cc	2006-01-18 15:20:47 +03:00
+++ 1.286/sql/ha_innodb.cc	2006-01-31 21:41:42 +03:00
@@ -138,8 +138,6 @@
 #define HA_INNOBASE_ROWS_IN_TABLE 10000 /* to get optimization right */
 #define HA_INNOBASE_RANGE_COUNT	  100
 
-uint 	innobase_init_flags 	= 0;
-ulong 	innobase_cache_size 	= 0;
 ulong 	innobase_large_page_size = 0;
 
 /* The default values for the following, type long or longlong, start-up
@@ -187,8 +185,6 @@
 #define INNOBASE_WAKE_INTERVAL	32
 ulong	innobase_active_counter	= 0;
 
-char*	innobase_home 	= NULL;
-
 static HASH 	innobase_open_tables;
 
 #ifdef __NETWARE__  	/* some special cleanup for NetWare */
@@ -814,7 +810,6 @@
                   HA_PRIMARY_KEY_IN_READ_INDEX |
                   HA_CAN_GEOMETRY |
                   HA_TABLE_SCAN_ON_INDEX),
-  last_dup_key((uint) -1),
   start_of_scan(0),
   num_write_row(0)
 {}
@@ -983,6 +978,11 @@
 		sql_print_error("The calling thread is holding the adaptive "
 				"search, latch though calling "
 				"innobase_query_caching_of_table_permitted.");
+
+		mutex_enter_noninline(&kernel_mutex);
+		trx_print(stderr, trx, 1024);
+		mutex_exit_noninline(&kernel_mutex);
+		ut_error;
 	}
 
 	innobase_release_stat_resources(trx);
@@ -6329,14 +6329,17 @@
 		TABLES if AUTOCOMMIT=1. It does not make much sense to acquire
 		an InnoDB table lock if it is released immediately at the end
 		of LOCK TABLES, and InnoDB's table locks in that case cause
-		VERY easily deadlocks. We do not set InnoDB table locks when
-		MySQL sets them at the start of a stored procedure call
-		(MySQL does have thd->in_lock_tables TRUE there). */
+		VERY easily deadlocks. 
+
+		We do not set InnoDB table locks if user has not explicitly
+		requested a table lock. Note that thd->in_lock_tables
+		can  be TRUE on some cases e.g. at the start of a stored
+		procedure call (SQLCOM_CALL). */
 
 		if (prebuilt->select_lock_type != LOCK_NONE) {
 
 			if (thd->in_lock_tables &&
-			    thd->lex->sql_command != SQLCOM_CALL &&
+			    thd->lex->sql_command == SQLCOM_LOCK_TABLES &&
 			    thd->variables.innodb_table_locks &&
 			    (thd->options & OPTION_NOT_AUTOCOMMIT)) {
 
@@ -6838,7 +6841,7 @@
 
 	} else if (lock_type != TL_IGNORE) {
 
-	        /* We set possible LOCK_X value in external_lock, not yet
+		/* We set possible LOCK_X value in external_lock, not yet
 		here even if this would be SELECT ... FOR UPDATE */
 
 		prebuilt->select_lock_type = LOCK_NONE;
@@ -6847,7 +6850,7 @@
 
 	if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK) {
 
-                /* Starting from 5.0.7, we weaken also the table locks
+		/* Starting from 5.0.7, we weaken also the table locks
 		set at the start of a MySQL stored procedure call, just like
 		we weaken the locks set at the start of an SQL statement.
 		MySQL does set thd->in_lock_tables TRUE there, but in reality
@@ -6870,26 +6873,36 @@
 			lock_type = TL_READ_NO_INSERT;
 		}
 
-    		/* If we are not doing a LOCK TABLE or DISCARD/IMPORT
-		TABLESPACE or TRUNCATE TABLE, then allow multiple writers */
+		/* If we are not doing a LOCK TABLE, DISCARD/IMPORT
+		TABLESPACE or TRUNCATE TABLE then allow multiple 
+		writers. Note that ALTER TABLE uses a TL_WRITE_ALLOW_READ
+		< TL_WRITE_CONCURRENT_INSERT.
 
-    		if ((lock_type >= TL_WRITE_CONCURRENT_INSERT &&
-	 	    lock_type <= TL_WRITE)
+		We especially allow multiple writers if MySQL is at the 
+		start of a stored procedure call (SQLCOM_CALL) 
+		(MySQL does have thd->in_lock_tables TRUE there). */
+
+    		if ((lock_type >= TL_WRITE_CONCURRENT_INSERT 
+		    && lock_type <= TL_WRITE)
 		    && (!thd->in_lock_tables
-		        || thd->lex->sql_command == SQLCOM_CALL)
+			|| thd->lex->sql_command == SQLCOM_CALL)
 		    && !thd->tablespace_op
 		    && thd->lex->sql_command != SQLCOM_TRUNCATE
-                    && thd->lex->sql_command != SQLCOM_OPTIMIZE
-                    && thd->lex->sql_command != SQLCOM_CREATE_TABLE) {
+		    && thd->lex->sql_command != SQLCOM_OPTIMIZE
+		    && thd->lex->sql_command != SQLCOM_CREATE_TABLE) {
 
-      			lock_type = TL_WRITE_ALLOW_WRITE;
+			lock_type = TL_WRITE_ALLOW_WRITE;
       		}
 
 		/* In queries of type INSERT INTO t1 SELECT ... FROM t2 ...
 		MySQL would use the lock TL_READ_NO_INSERT on t2, and that
 		would conflict with TL_WRITE_ALLOW_WRITE, blocking all inserts
 		to t2. Convert the lock to a normal read lock to allow
-		concurrent inserts to t2. */
+		concurrent inserts to t2. 
+
+		We especially allow concurrent inserts if MySQL is at the 
+		start of a stored procedure call (SQLCOM_CALL) 
+		(MySQL does have thd->in_lock_tables TRUE there). */
       		
 		if (lock_type == TL_READ_NO_INSERT
 		    && (!thd->in_lock_tables
@@ -6898,10 +6911,10 @@
 			lock_type = TL_READ;
 		}
 		
- 		lock.type = lock_type;
-  	}
+		lock.type = lock_type;
+	}
 
-  	*to++= &lock;
+	*to++= &lock;
 
 	return(to);
 }

--- 1.109/sql/ha_innodb.h	2006-01-18 15:01:54 +03:00
+++ 1.110/sql/ha_innodb.h	2006-01-31 21:41:43 +03:00
@@ -52,7 +52,6 @@
   	THR_LOCK_DATA 	lock;
 	INNOBASE_SHARE  *share;
 
-  	gptr 		alloc_ptr;
   	byte*		upd_buff;	/* buffer used in updates */
   	byte*		key_val_buff;	/* buffer used in converting
   					search key values from MySQL format
@@ -62,7 +61,6 @@
 					two buffers */
   	ulong 		int_table_flags;
   	uint 		primary_key;
-	uint		last_dup_key;
 	ulong		start_of_scan;	/* this is set to 1 when we are
 					starting a table scan but have not
 					yet fetched any row, else 0 */
@@ -70,7 +68,6 @@
 					ROW_SEL_EXACT, ROW_SEL_EXACT_PREFIX,
 					or undefined */
 	uint		num_write_row;	/* number of write_row() calls */
-	ulong max_supported_row_length(const byte *buf);
 
 	uint store_key_val_for_row(uint keynr, char* buff, uint buff_len,
 					       const byte* record);
@@ -199,11 +196,8 @@
 };
 
 extern struct show_var_st innodb_status_variables[];
-extern uint innobase_init_flags, innobase_lock_type;
-extern ulong innobase_cache_size, innobase_fast_shutdown;
+extern ulong innobase_fast_shutdown;
 extern ulong innobase_large_page_size;
-extern char *innobase_home, *innobase_tmpdir, *innobase_logdir;
-extern long innobase_lock_scan_time;
 extern long innobase_mirrored_log_groups, innobase_log_files_in_group;
 extern longlong innobase_buffer_pool_size, innobase_log_file_size;
 extern long innobase_log_buffer_size;
@@ -240,8 +234,6 @@
 extern ulong srv_flush_log_at_trx_commit;
 }
 
-extern TYPELIB innobase_lock_typelib;
-
 bool innobase_init(void);
 bool innobase_end(void);
 bool innobase_flush_logs(void);
@@ -309,9 +301,6 @@
 int innobase_rollback_by_xid(
 			/* out: 0 or error number */
 	XID	*xid);	/* in : X/Open XA Transaction Identification */
-
-
-int innobase_xa_end(THD *thd);
 
 
 int innobase_repl_report_sent_binlog(THD *thd, char *log_file_name,
Thread
bk commit into 5.0 tree (aivanov:1.2020) BUG#16582Alex Ivanov Notebook31 Jan